From: Moore, Eric Date: Tue, 14 Mar 2006 16:14:21 +0000 (-0700) Subject: [SCSI] fusion - exposing raid components in mptsas X-Git-Tag: v2.6.17-rc1~1129^2~4^2~11 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f44e5461d919a344d44f7ca4f06cf8d169da8454;p=linux-2.6 [SCSI] fusion - exposing raid components in mptsas 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 Signed-off-by: James Bottomley --- diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index b6a6f27082..289fcdbe89 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -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; iraid_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;iiraid_data.pIocPg2->NumActiveVolumes;ii++) { - scsi_add_device(sh, - ioc->num_ports, - ioc->raid_data.pIocPg2->RaidVolume[ii].VolumeID, - 0); - } - return 0; out_mptsas_probe: diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index c99a918feb..3729062db3 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -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) { diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h index 2447a20351..14a5b6c2e2 100644 --- a/drivers/message/fusion/mptscsih.h +++ b/drivers/message/fusion/mptscsih.h @@ -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);