diff options
author | Moore, Eric <Eric.Moore@lsil.com> | 2006-03-14 11:14:21 -0500 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2006-03-14 15:35:01 -0500 |
commit | f44e5461d919a344d44f7ca4f06cf8d169da8454 (patch) | |
tree | 9d2d140b44954b41e3b439f098f40643216d529f /drivers/message/fusion | |
parent | db9c9174e42bdc8d52bc18df7c55823cf4546eda (diff) |
[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 <Eric.Moore@lsil.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/message/fusion')
-rw-r--r-- | drivers/message/fusion/mptsas.c | 112 | ||||
-rw-r--r-- | drivers/message/fusion/mptscsih.c | 21 | ||||
-rw-r--r-- | drivers/message/fusion/mptscsih.h | 1 |
3 files changed, 107 insertions, 27 deletions
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index b6a6f27082b6..289fcdbe89ba 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c | |||
@@ -104,6 +104,8 @@ struct mptsas_hotplug_event { | |||
104 | u16 handle; | 104 | u16 handle; |
105 | u16 parent_handle; | 105 | u16 parent_handle; |
106 | u8 phy_id; | 106 | u8 phy_id; |
107 | u8 phys_disk_num; | ||
108 | u8 phys_disk_num_valid; | ||
107 | }; | 109 | }; |
108 | 110 | ||
109 | /* | 111 | /* |
@@ -139,6 +141,7 @@ struct mptsas_phyinfo { | |||
139 | struct mptsas_devinfo attached; /* point to attached device info */ | 141 | struct mptsas_devinfo attached; /* point to attached device info */ |
140 | struct sas_phy *phy; | 142 | struct sas_phy *phy; |
141 | struct sas_rphy *rphy; | 143 | struct sas_rphy *rphy; |
144 | struct scsi_target *starget; | ||
142 | }; | 145 | }; |
143 | 146 | ||
144 | struct mptsas_portinfo { | 147 | struct mptsas_portinfo { |
@@ -388,6 +391,17 @@ mptsas_slave_alloc(struct scsi_device *sdev) | |||
388 | target_id = p->phy_info[i].attached.id; | 391 | target_id = p->phy_info[i].attached.id; |
389 | vtarget->bus_id = p->phy_info[i].attached.channel; | 392 | vtarget->bus_id = p->phy_info[i].attached.channel; |
390 | vdev->lun = sdev->lun; | 393 | vdev->lun = sdev->lun; |
394 | p->phy_info[i].starget = sdev->sdev_target; | ||
395 | /* | ||
396 | * Exposing hidden disk (RAID) | ||
397 | */ | ||
398 | if (mptscsih_is_phys_disk(hd->ioc, target_id)) { | ||
399 | target_id = mptscsih_raid_id_to_num(hd, | ||
400 | target_id); | ||
401 | vdev->vtarget->tflags |= | ||
402 | MPT_TARGET_FLAGS_RAID_COMPONENT; | ||
403 | sdev->no_uld_attach = 1; | ||
404 | } | ||
391 | mutex_unlock(&hd->ioc->sas_topology_mutex); | 405 | mutex_unlock(&hd->ioc->sas_topology_mutex); |
392 | goto out; | 406 | goto out; |
393 | } | 407 | } |
@@ -1378,10 +1392,24 @@ mptsas_scan_sas_topology(MPT_ADAPTER *ioc) | |||
1378 | { | 1392 | { |
1379 | u32 handle = 0xFFFF; | 1393 | u32 handle = 0xFFFF; |
1380 | int index = 0; | 1394 | int index = 0; |
1395 | int i; | ||
1381 | 1396 | ||
1382 | mptsas_probe_hba_phys(ioc, &index); | 1397 | mptsas_probe_hba_phys(ioc, &index); |
1383 | while (!mptsas_probe_expander_phys(ioc, &handle, &index)) | 1398 | while (!mptsas_probe_expander_phys(ioc, &handle, &index)) |
1384 | ; | 1399 | ; |
1400 | /* | ||
1401 | Reporting RAID volumes. | ||
1402 | */ | ||
1403 | if (!ioc->raid_data.pIocPg2) | ||
1404 | goto out; | ||
1405 | if (!ioc->raid_data.pIocPg2->NumActiveVolumes) | ||
1406 | goto out; | ||
1407 | for (i=0; i<ioc->raid_data.pIocPg2->NumActiveVolumes; i++) { | ||
1408 | scsi_add_device(ioc->sh, ioc->num_ports, | ||
1409 | ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0); | ||
1410 | } | ||
1411 | out: | ||
1412 | return; | ||
1385 | } | 1413 | } |
1386 | 1414 | ||
1387 | static struct mptsas_phyinfo * | 1415 | static struct mptsas_phyinfo * |
@@ -1461,6 +1489,20 @@ mptscsih_sas_persist_clear_table(void * arg) | |||
1461 | } | 1489 | } |
1462 | 1490 | ||
1463 | static void | 1491 | static void |
1492 | mptsas_reprobe_lun(struct scsi_device *sdev, void *data) | ||
1493 | { | ||
1494 | sdev->no_uld_attach = data ? 1 : 0; | ||
1495 | scsi_device_reprobe(sdev); | ||
1496 | } | ||
1497 | |||
1498 | static void | ||
1499 | mptsas_reprobe_target(struct scsi_target *starget, int uld_attach) | ||
1500 | { | ||
1501 | starget_for_each_device(starget, uld_attach ? (void *)1 : NULL, | ||
1502 | mptsas_reprobe_lun); | ||
1503 | } | ||
1504 | |||
1505 | static void | ||
1464 | mptsas_hotplug_work(void *arg) | 1506 | mptsas_hotplug_work(void *arg) |
1465 | { | 1507 | { |
1466 | struct mptsas_hotplug_event *ev = arg; | 1508 | struct mptsas_hotplug_event *ev = arg; |
@@ -1470,14 +1512,33 @@ mptsas_hotplug_work(void *arg) | |||
1470 | struct scsi_device *sdev; | 1512 | struct scsi_device *sdev; |
1471 | char *ds = NULL; | 1513 | char *ds = NULL; |
1472 | struct mptsas_devinfo sas_device; | 1514 | struct mptsas_devinfo sas_device; |
1515 | VirtTarget *vtarget; | ||
1473 | 1516 | ||
1474 | switch (ev->event_type) { | 1517 | switch (ev->event_type) { |
1475 | case MPTSAS_DEL_DEVICE: | 1518 | case MPTSAS_DEL_DEVICE: |
1476 | 1519 | ||
1477 | phy_info = mptsas_find_phyinfo_by_target(ioc, ev->id); | 1520 | phy_info = mptsas_find_phyinfo_by_target(ioc, ev->id); |
1478 | if (!phy_info) { | 1521 | /* |
1479 | printk("mptsas: remove event for non-existant PHY.\n"); | 1522 | * Sanity checks, for non-existing phys and remote rphys. |
1523 | */ | ||
1524 | if (!phy_info) | ||
1480 | break; | 1525 | break; |
1526 | if (!phy_info->rphy) | ||
1527 | break; | ||
1528 | if (phy_info->starget) { | ||
1529 | vtarget = phy_info->starget->hostdata; | ||
1530 | |||
1531 | if (!vtarget) | ||
1532 | break; | ||
1533 | /* | ||
1534 | * Handling RAID components | ||
1535 | */ | ||
1536 | if (ev->phys_disk_num_valid) { | ||
1537 | vtarget->target_id = ev->phys_disk_num; | ||
1538 | vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT; | ||
1539 | mptsas_reprobe_target(vtarget->starget, 1); | ||
1540 | break; | ||
1541 | } | ||
1481 | } | 1542 | } |
1482 | 1543 | ||
1483 | if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET) | 1544 | if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET) |
@@ -1491,11 +1552,10 @@ mptsas_hotplug_work(void *arg) | |||
1491 | "removing %s device, channel %d, id %d, phy %d\n", | 1552 | "removing %s device, channel %d, id %d, phy %d\n", |
1492 | ioc->name, ds, ev->channel, ev->id, phy_info->phy_id); | 1553 | ioc->name, ds, ev->channel, ev->id, phy_info->phy_id); |
1493 | 1554 | ||
1494 | if (phy_info->rphy) { | 1555 | sas_rphy_delete(phy_info->rphy); |
1495 | sas_rphy_delete(phy_info->rphy); | 1556 | memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo)); |
1496 | memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo)); | 1557 | phy_info->rphy = NULL; |
1497 | phy_info->rphy = NULL; | 1558 | phy_info->starget = NULL; |
1498 | } | ||
1499 | break; | 1559 | break; |
1500 | case MPTSAS_ADD_DEVICE: | 1560 | case MPTSAS_ADD_DEVICE: |
1501 | 1561 | ||
@@ -1509,16 +1569,27 @@ mptsas_hotplug_work(void *arg) | |||
1509 | 1569 | ||
1510 | phy_info = mptsas_find_phyinfo_by_parent(ioc, | 1570 | phy_info = mptsas_find_phyinfo_by_parent(ioc, |
1511 | sas_device.handle_parent, sas_device.phy_id); | 1571 | sas_device.handle_parent, sas_device.phy_id); |
1512 | if (!phy_info) { | 1572 | if (!phy_info) |
1513 | printk("mptsas: add event for non-existant PHY.\n"); | ||
1514 | break; | 1573 | break; |
1515 | } | 1574 | if (phy_info->starget) { |
1575 | vtarget = phy_info->starget->hostdata; | ||
1516 | 1576 | ||
1517 | if (phy_info->rphy) { | 1577 | if (!vtarget) |
1518 | printk("mptsas: trying to add existing device.\n"); | 1578 | break; |
1579 | /* | ||
1580 | * Handling RAID components | ||
1581 | */ | ||
1582 | if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) { | ||
1583 | vtarget->tflags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT; | ||
1584 | vtarget->target_id = ev->id; | ||
1585 | mptsas_reprobe_target(phy_info->starget, 0); | ||
1586 | } | ||
1519 | break; | 1587 | break; |
1520 | } | 1588 | } |
1521 | 1589 | ||
1590 | if (phy_info->rphy) | ||
1591 | break; | ||
1592 | |||
1522 | memcpy(&phy_info->attached, &sas_device, | 1593 | memcpy(&phy_info->attached, &sas_device, |
1523 | sizeof(struct mptsas_devinfo)); | 1594 | sizeof(struct mptsas_devinfo)); |
1524 | 1595 | ||
@@ -1672,6 +1743,9 @@ mptscsih_send_raid_event(MPT_ADAPTER *ioc, | |||
1672 | ev->event_type = MPTSAS_ADD_DEVICE; | 1743 | ev->event_type = MPTSAS_ADD_DEVICE; |
1673 | break; | 1744 | break; |
1674 | case MPI_EVENT_RAID_RC_PHYSDISK_CREATED: | 1745 | case MPI_EVENT_RAID_RC_PHYSDISK_CREATED: |
1746 | ioc->raid_data.isRaid = 1; | ||
1747 | ev->phys_disk_num_valid = 1; | ||
1748 | ev->phys_disk_num = raid_event_data->PhysDiskNum; | ||
1675 | ev->event_type = MPTSAS_DEL_DEVICE; | 1749 | ev->event_type = MPTSAS_DEL_DEVICE; |
1676 | break; | 1750 | break; |
1677 | case MPI_EVENT_RAID_RC_VOLUME_DELETED: | 1751 | case MPI_EVENT_RAID_RC_VOLUME_DELETED: |
@@ -1932,20 +2006,6 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1932 | 2006 | ||
1933 | mptsas_scan_sas_topology(ioc); | 2007 | mptsas_scan_sas_topology(ioc); |
1934 | 2008 | ||
1935 | /* | ||
1936 | Reporting RAID volumes. | ||
1937 | */ | ||
1938 | if (!ioc->raid_data.pIocPg2) | ||
1939 | return 0; | ||
1940 | if (!ioc->raid_data.pIocPg2->NumActiveVolumes) | ||
1941 | return 0; | ||
1942 | for (ii=0;ii<ioc->raid_data.pIocPg2->NumActiveVolumes;ii++) { | ||
1943 | scsi_add_device(sh, | ||
1944 | ioc->num_ports, | ||
1945 | ioc->raid_data.pIocPg2->RaidVolume[ii].VolumeID, | ||
1946 | 0); | ||
1947 | } | ||
1948 | |||
1949 | return 0; | 2009 | return 0; |
1950 | 2010 | ||
1951 | out_mptsas_probe: | 2011 | out_mptsas_probe: |
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index c99a918feb58..3729062db317 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 *)) | |||
1235 | return SCSI_MLQUEUE_HOST_BUSY; | 1235 | return SCSI_MLQUEUE_HOST_BUSY; |
1236 | } | 1236 | } |
1237 | 1237 | ||
1238 | if (vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT && | 1238 | if ((hd->ioc->bus_type == SPI) && |
1239 | vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT && | ||
1239 | mptscsih_raid_id_to_num(hd, SCpnt->device->id) < 0) { | 1240 | mptscsih_raid_id_to_num(hd, SCpnt->device->id) < 0) { |
1240 | SCpnt->result = DID_NO_CONNECT << 16; | 1241 | SCpnt->result = DID_NO_CONNECT << 16; |
1241 | done(SCpnt); | 1242 | done(SCpnt); |
@@ -2103,6 +2104,24 @@ mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev, | |||
2103 | return 0; | 2104 | return 0; |
2104 | } | 2105 | } |
2105 | 2106 | ||
2107 | /* Search IOC page 3 to determine if this is hidden physical disk | ||
2108 | * | ||
2109 | */ | ||
2110 | int | ||
2111 | mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id) | ||
2112 | { | ||
2113 | int i; | ||
2114 | |||
2115 | if (!ioc->raid_data.isRaid || !ioc->raid_data.pIocPg3) | ||
2116 | return 0; | ||
2117 | for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) { | ||
2118 | if (id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) | ||
2119 | return 1; | ||
2120 | } | ||
2121 | return 0; | ||
2122 | } | ||
2123 | EXPORT_SYMBOL(mptscsih_is_phys_disk); | ||
2124 | |||
2106 | int | 2125 | int |
2107 | mptscsih_raid_id_to_num(MPT_SCSI_HOST *hd, uint physdiskid) | 2126 | mptscsih_raid_id_to_num(MPT_SCSI_HOST *hd, uint physdiskid) |
2108 | { | 2127 | { |
diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h index 2447a203513f..14a5b6c2e2bd 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); | |||
100 | extern void mptscsih_timer_expired(unsigned long data); | 100 | extern void mptscsih_timer_expired(unsigned long data); |
101 | extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout); | 101 | extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout); |
102 | extern int mptscsih_raid_id_to_num(MPT_SCSI_HOST *hd, uint physdiskid); | 102 | extern int mptscsih_raid_id_to_num(MPT_SCSI_HOST *hd, uint physdiskid); |
103 | extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id); | ||