aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/message/fusion/mptsas.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/message/fusion/mptsas.c')
-rw-r--r--drivers/message/fusion/mptsas.c112
1 files changed, 86 insertions, 26 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: