]> err.no Git - linux-2.6/commitdiff
[SCSI] fusion - exposing raid components in mptsas
authorMoore, Eric <Eric.Moore@lsil.com>
Tue, 14 Mar 2006 16:14:21 +0000 (09:14 -0700)
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>
Tue, 14 Mar 2006 20:35:01 +0000 (14:35 -0600)
Suppport for exposing hidden raid components
for sg interface. The sdev->no_uld_attach flag
will set set accordingly.

The sas module supports adding/removing raid
volumes using online storage management application
interface.

This patch rely's on patch's provided to me
by Christoph Hellwig, that exports device_reprobe.
I will post those patch's on behalf of Christoph.

Signed-off-by: Eric Moore <Eric.Moore@lsil.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
drivers/message/fusion/mptsas.c
drivers/message/fusion/mptscsih.c
drivers/message/fusion/mptscsih.h

index b6a6f27082b64f800b422a0858d0e2de93b450c6..289fcdbe89ba1277555fbb49877b83911e634d4e 100644 (file)
@@ -104,6 +104,8 @@ struct mptsas_hotplug_event {
        u16                     handle;
        u16                     parent_handle;
        u8                      phy_id;
+       u8                      phys_disk_num;
+       u8                      phys_disk_num_valid;
 };
 
 /*
@@ -139,6 +141,7 @@ struct mptsas_phyinfo {
        struct mptsas_devinfo attached; /* point to attached device info */
        struct sas_phy *phy;
        struct sas_rphy *rphy;
+       struct scsi_target *starget;
 };
 
 struct mptsas_portinfo {
@@ -388,6 +391,17 @@ mptsas_slave_alloc(struct scsi_device *sdev)
                                target_id = p->phy_info[i].attached.id;
                                vtarget->bus_id = p->phy_info[i].attached.channel;
                                vdev->lun = sdev->lun;
+                               p->phy_info[i].starget = sdev->sdev_target;
+                               /*
+                                * Exposing hidden disk (RAID)
+                                */
+                               if (mptscsih_is_phys_disk(hd->ioc, target_id)) {
+                                       target_id = mptscsih_raid_id_to_num(hd,
+                                                       target_id);
+                                       vdev->vtarget->tflags |=
+                                           MPT_TARGET_FLAGS_RAID_COMPONENT;
+                                       sdev->no_uld_attach = 1;
+                               }
                                mutex_unlock(&hd->ioc->sas_topology_mutex);
                                goto out;
                        }
@@ -1378,10 +1392,24 @@ mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
 {
        u32 handle = 0xFFFF;
        int index = 0;
+       int i;
 
        mptsas_probe_hba_phys(ioc, &index);
        while (!mptsas_probe_expander_phys(ioc, &handle, &index))
                ;
+       /*
+         Reporting RAID volumes.
+       */
+       if (!ioc->raid_data.pIocPg2)
+               goto out;
+       if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
+               goto out;
+       for (i=0; i<ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
+               scsi_add_device(ioc->sh, ioc->num_ports,
+                   ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
+       }
+ out:
+       return;
 }
 
 static struct mptsas_phyinfo *
@@ -1460,6 +1488,20 @@ mptscsih_sas_persist_clear_table(void * arg)
        mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT);
 }
 
+static void
+mptsas_reprobe_lun(struct scsi_device *sdev, void *data)
+{
+       sdev->no_uld_attach = data ? 1 : 0;
+       scsi_device_reprobe(sdev);
+}
+
+static void
+mptsas_reprobe_target(struct scsi_target *starget, int uld_attach)
+{
+       starget_for_each_device(starget, uld_attach ? (void *)1 : NULL,
+                       mptsas_reprobe_lun);
+}
+
 static void
 mptsas_hotplug_work(void *arg)
 {
@@ -1470,14 +1512,33 @@ mptsas_hotplug_work(void *arg)
        struct scsi_device *sdev;
        char *ds = NULL;
        struct mptsas_devinfo sas_device;
+       VirtTarget *vtarget;
 
        switch (ev->event_type) {
        case MPTSAS_DEL_DEVICE:
 
                phy_info = mptsas_find_phyinfo_by_target(ioc, ev->id);
-               if (!phy_info) {
-                       printk("mptsas: remove event for non-existant PHY.\n");
+               /*
+                * Sanity checks, for non-existing phys and remote rphys.
+                */
+               if (!phy_info)
                        break;
+               if (!phy_info->rphy)
+                       break;
+               if (phy_info->starget) {
+                       vtarget = phy_info->starget->hostdata;
+
+                       if (!vtarget)
+                               break;
+                       /*
+                        * Handling  RAID components
+                        */
+                       if (ev->phys_disk_num_valid) {
+                               vtarget->target_id = ev->phys_disk_num;
+                               vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
+                               mptsas_reprobe_target(vtarget->starget, 1);
+                               break;
+                       }
                }
 
                if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
@@ -1491,11 +1552,10 @@ mptsas_hotplug_work(void *arg)
                       "removing %s device, channel %d, id %d, phy %d\n",
                       ioc->name, ds, ev->channel, ev->id, phy_info->phy_id);
 
-               if (phy_info->rphy) {
-                       sas_rphy_delete(phy_info->rphy);
-                       memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
-                       phy_info->rphy = NULL;
-               }
+               sas_rphy_delete(phy_info->rphy);
+               memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
+               phy_info->rphy = NULL;
+               phy_info->starget = NULL;
                break;
        case MPTSAS_ADD_DEVICE:
 
@@ -1509,16 +1569,27 @@ mptsas_hotplug_work(void *arg)
 
                phy_info = mptsas_find_phyinfo_by_parent(ioc,
                                sas_device.handle_parent, sas_device.phy_id);
-               if (!phy_info) {
-                       printk("mptsas: add event for non-existant PHY.\n");
+               if (!phy_info)
                        break;
-               }
+               if (phy_info->starget) {
+                       vtarget = phy_info->starget->hostdata;
 
-               if (phy_info->rphy) {
-                       printk("mptsas: trying to add existing device.\n");
+                       if (!vtarget)
+                               break;
+                       /*
+                        * Handling  RAID components
+                        */
+                       if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
+                               vtarget->tflags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT;
+                               vtarget->target_id = ev->id;
+                               mptsas_reprobe_target(phy_info->starget, 0);
+                       }
                        break;
                }
 
+               if (phy_info->rphy)
+                       break;
+
                memcpy(&phy_info->attached, &sas_device,
                    sizeof(struct mptsas_devinfo));
 
@@ -1672,6 +1743,9 @@ mptscsih_send_raid_event(MPT_ADAPTER *ioc,
                ev->event_type = MPTSAS_ADD_DEVICE;
                break;
        case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
+               ioc->raid_data.isRaid = 1;
+               ev->phys_disk_num_valid = 1;
+               ev->phys_disk_num = raid_event_data->PhysDiskNum;
                ev->event_type = MPTSAS_DEL_DEVICE;
                break;
        case MPI_EVENT_RAID_RC_VOLUME_DELETED:
@@ -1932,20 +2006,6 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
        mptsas_scan_sas_topology(ioc);
 
-       /*
-         Reporting RAID volumes.
-       */
-       if (!ioc->raid_data.pIocPg2)
-               return 0;
-       if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
-               return 0;
-       for (ii=0;ii<ioc->raid_data.pIocPg2->NumActiveVolumes;ii++) {
-               scsi_add_device(sh,
-                       ioc->num_ports,
-                       ioc->raid_data.pIocPg2->RaidVolume[ii].VolumeID,
-                       0);
-       }
-
        return 0;
 
 out_mptsas_probe:
index c99a918feb5808ba4d4dcae0a25d2e23581bb93b..3729062db3177a2fd6c57c992a6d0c9b09bb1fa2 100644 (file)
@@ -1235,7 +1235,8 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
                return SCSI_MLQUEUE_HOST_BUSY;
        }
 
-       if (vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT &&
+       if ((hd->ioc->bus_type == SPI) &&
+           vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT &&
            mptscsih_raid_id_to_num(hd, SCpnt->device->id) < 0) {
                SCpnt->result = DID_NO_CONNECT << 16;
                done(SCpnt);
@@ -2103,6 +2104,24 @@ mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
        return 0;
 }
 
+/* Search IOC page 3 to determine if this is hidden physical disk
+ *
+ */
+int
+mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id)
+{
+       int i;
+
+       if (!ioc->raid_data.isRaid || !ioc->raid_data.pIocPg3)
+               return 0;
+       for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
+                if (id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID)
+                        return 1;
+        }
+        return 0;
+}
+EXPORT_SYMBOL(mptscsih_is_phys_disk);
+
 int
 mptscsih_raid_id_to_num(MPT_SCSI_HOST *hd, uint physdiskid)
 {
index 2447a203513f46304a03904b9095432193a5357c..14a5b6c2e2bdeb4ea60f8e992ec516641d167a29 100644 (file)
@@ -100,3 +100,4 @@ extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth);
 extern void mptscsih_timer_expired(unsigned long data);
 extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
 extern int mptscsih_raid_id_to_num(MPT_SCSI_HOST *hd, uint physdiskid);
+extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id);