aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/message/fusion/mptsas.c112
-rw-r--r--drivers/message/fusion/mptscsih.c21
-rw-r--r--drivers/message/fusion/mptscsih.h1
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
144struct mptsas_portinfo { 147struct 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
1387static struct mptsas_phyinfo * 1415static struct mptsas_phyinfo *
@@ -1461,6 +1489,20 @@ mptscsih_sas_persist_clear_table(void * arg)
1461} 1489}
1462 1490
1463static void 1491static void
1492mptsas_reprobe_lun(struct scsi_device *sdev, void *data)
1493{
1494 sdev->no_uld_attach = data ? 1 : 0;
1495 scsi_device_reprobe(sdev);
1496}
1497
1498static void
1499mptsas_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
1505static void
1464mptsas_hotplug_work(void *arg) 1506mptsas_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
1951out_mptsas_probe: 2011out_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 */
2110int
2111mptscsih_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}
2123EXPORT_SYMBOL(mptscsih_is_phys_disk);
2124
2106int 2125int
2107mptscsih_raid_id_to_num(MPT_SCSI_HOST *hd, uint physdiskid) 2126mptscsih_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);
100extern void mptscsih_timer_expired(unsigned long data); 100extern void mptscsih_timer_expired(unsigned long data);
101extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout); 101extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
102extern int mptscsih_raid_id_to_num(MPT_SCSI_HOST *hd, uint physdiskid); 102extern int mptscsih_raid_id_to_num(MPT_SCSI_HOST *hd, uint physdiskid);
103extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id);