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.c198
1 files changed, 173 insertions, 25 deletions
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index 5a06d8d8694e..8e77837c07ec 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -89,6 +89,8 @@ static int mptsasMgmtCtx = -1;
89enum mptsas_hotplug_action { 89enum mptsas_hotplug_action {
90 MPTSAS_ADD_DEVICE, 90 MPTSAS_ADD_DEVICE,
91 MPTSAS_DEL_DEVICE, 91 MPTSAS_DEL_DEVICE,
92 MPTSAS_ADD_RAID,
93 MPTSAS_DEL_RAID,
92}; 94};
93 95
94struct mptsas_hotplug_event { 96struct mptsas_hotplug_event {
@@ -114,6 +116,7 @@ struct mptsas_hotplug_event {
114 116
115struct mptsas_devinfo { 117struct mptsas_devinfo {
116 u16 handle; /* unique id to address this device */ 118 u16 handle; /* unique id to address this device */
119 u16 handle_parent; /* unique id to address parent device */
117 u8 phy_id; /* phy number of parent device */ 120 u8 phy_id; /* phy number of parent device */
118 u8 port_id; /* sas physical port this device 121 u8 port_id; /* sas physical port this device
119 is assoc'd with */ 122 is assoc'd with */
@@ -714,6 +717,7 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
714 mptsas_print_device_pg0(buffer); 717 mptsas_print_device_pg0(buffer);
715 718
716 device_info->handle = le16_to_cpu(buffer->DevHandle); 719 device_info->handle = le16_to_cpu(buffer->DevHandle);
720 device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
717 device_info->phy_id = buffer->PhyNum; 721 device_info->phy_id = buffer->PhyNum;
718 device_info->port_id = buffer->PhysicalPort; 722 device_info->port_id = buffer->PhysicalPort;
719 device_info->id = buffer->TargetID; 723 device_info->id = buffer->TargetID;
@@ -863,6 +867,26 @@ mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
863 return error; 867 return error;
864} 868}
865 869
870/*
871 * Returns true if there is a scsi end device
872 */
873static inline int
874mptsas_is_end_device(struct mptsas_devinfo * attached)
875{
876 if ((attached->handle) &&
877 (attached->device_info &
878 MPI_SAS_DEVICE_INFO_END_DEVICE) &&
879 ((attached->device_info &
880 MPI_SAS_DEVICE_INFO_SSP_TARGET) |
881 (attached->device_info &
882 MPI_SAS_DEVICE_INFO_STP_TARGET) |
883 (attached->device_info &
884 MPI_SAS_DEVICE_INFO_SATA_DEVICE)))
885 return 1;
886 else
887 return 0;
888}
889
866static void 890static void
867mptsas_parse_device_info(struct sas_identify *identify, 891mptsas_parse_device_info(struct sas_identify *identify,
868 struct mptsas_devinfo *device_info) 892 struct mptsas_devinfo *device_info)
@@ -1227,7 +1251,7 @@ mptsas_find_phyinfo_by_parent(MPT_ADAPTER *ioc, u16 parent_handle, u8 phy_id)
1227} 1251}
1228 1252
1229static struct mptsas_phyinfo * 1253static struct mptsas_phyinfo *
1230mptsas_find_phyinfo_by_handle(MPT_ADAPTER *ioc, u16 handle) 1254mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id)
1231{ 1255{
1232 struct mptsas_portinfo *port_info; 1256 struct mptsas_portinfo *port_info;
1233 struct mptsas_phyinfo *phy_info = NULL; 1257 struct mptsas_phyinfo *phy_info = NULL;
@@ -1239,12 +1263,12 @@ mptsas_find_phyinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)
1239 */ 1263 */
1240 mutex_lock(&ioc->sas_topology_mutex); 1264 mutex_lock(&ioc->sas_topology_mutex);
1241 list_for_each_entry(port_info, &ioc->sas_topology, list) { 1265 list_for_each_entry(port_info, &ioc->sas_topology, list) {
1242 for (i = 0; i < port_info->num_phys; i++) { 1266 for (i = 0; i < port_info->num_phys; i++)
1243 if (port_info->phy_info[i].attached.handle == handle) { 1267 if (mptsas_is_end_device(&port_info->phy_info[i].attached))
1244 phy_info = &port_info->phy_info[i]; 1268 if (port_info->phy_info[i].attached.id == id) {
1245 break; 1269 phy_info = &port_info->phy_info[i];
1246 } 1270 break;
1247 } 1271 }
1248 } 1272 }
1249 mutex_unlock(&ioc->sas_topology_mutex); 1273 mutex_unlock(&ioc->sas_topology_mutex);
1250 1274
@@ -1258,36 +1282,58 @@ mptsas_hotplug_work(void *arg)
1258 MPT_ADAPTER *ioc = ev->ioc; 1282 MPT_ADAPTER *ioc = ev->ioc;
1259 struct mptsas_phyinfo *phy_info; 1283 struct mptsas_phyinfo *phy_info;
1260 struct sas_rphy *rphy; 1284 struct sas_rphy *rphy;
1285 struct scsi_device *sdev;
1261 char *ds = NULL; 1286 char *ds = NULL;
1262 1287 struct mptsas_devinfo sas_device;
1263 if (ev->device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1264 ds = "ssp";
1265 if (ev->device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
1266 ds = "stp";
1267 if (ev->device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1268 ds = "sata";
1269 1288
1270 switch (ev->event_type) { 1289 switch (ev->event_type) {
1271 case MPTSAS_DEL_DEVICE: 1290 case MPTSAS_DEL_DEVICE:
1272 printk(MYIOC_s_INFO_FMT
1273 "removing %s device, channel %d, id %d, phy %d\n",
1274 ioc->name, ds, ev->channel, ev->id, ev->phy_id);
1275 1291
1276 phy_info = mptsas_find_phyinfo_by_handle(ioc, ev->handle); 1292 phy_info = mptsas_find_phyinfo_by_target(ioc, ev->id);
1277 if (!phy_info) { 1293 if (!phy_info) {
1278 printk("mptsas: remove event for non-existant PHY.\n"); 1294 printk("mptsas: remove event for non-existant PHY.\n");
1279 break; 1295 break;
1280 } 1296 }
1281 1297
1298 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1299 ds = "ssp";
1300 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
1301 ds = "stp";
1302 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1303 ds = "sata";
1304
1305 printk(MYIOC_s_INFO_FMT
1306 "removing %s device, channel %d, id %d, phy %d\n",
1307 ioc->name, ds, ev->channel, ev->id, phy_info->phy_id);
1308
1282 if (phy_info->rphy) { 1309 if (phy_info->rphy) {
1283 sas_rphy_delete(phy_info->rphy); 1310 sas_rphy_delete(phy_info->rphy);
1284 phy_info->rphy = NULL; 1311 phy_info->rphy = NULL;
1285 } 1312 }
1286 break; 1313 break;
1287 case MPTSAS_ADD_DEVICE: 1314 case MPTSAS_ADD_DEVICE:
1288 printk(MYIOC_s_INFO_FMT 1315
1289 "attaching %s device, channel %d, id %d, phy %d\n", 1316 /*
1290 ioc->name, ds, ev->channel, ev->id, ev->phy_id); 1317 * When there is no sas address,
1318 * RAID volumes are being deleted,
1319 * and hidden phy disk are being added.
1320 * We don't know the SAS data yet,
1321 * so lookup sas device page to get
1322 * pertaining info
1323 */
1324 if (!ev->sas_address) {
1325 if (mptsas_sas_device_pg0(ioc,
1326 &sas_device, ev->id,
1327 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
1328 MPI_SAS_DEVICE_PGAD_FORM_SHIFT)))
1329 break;
1330 ev->handle = sas_device.handle;
1331 ev->parent_handle = sas_device.handle_parent;
1332 ev->channel = sas_device.channel;
1333 ev->phy_id = sas_device.phy_id;
1334 ev->sas_address = sas_device.sas_address;
1335 ev->device_info = sas_device.device_info;
1336 }
1291 1337
1292 phy_info = mptsas_find_phyinfo_by_parent(ioc, 1338 phy_info = mptsas_find_phyinfo_by_parent(ioc,
1293 ev->parent_handle, ev->phy_id); 1339 ev->parent_handle, ev->phy_id);
@@ -1310,10 +1356,23 @@ mptsas_hotplug_work(void *arg)
1310 phy_info->attached.sas_address = ev->sas_address; 1356 phy_info->attached.sas_address = ev->sas_address;
1311 phy_info->attached.device_info = ev->device_info; 1357 phy_info->attached.device_info = ev->device_info;
1312 1358
1359 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1360 ds = "ssp";
1361 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
1362 ds = "stp";
1363 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1364 ds = "sata";
1365
1366 printk(MYIOC_s_INFO_FMT
1367 "attaching %s device, channel %d, id %d, phy %d\n",
1368 ioc->name, ds, ev->channel, ev->id, ev->phy_id);
1369
1370
1313 rphy = sas_rphy_alloc(phy_info->phy); 1371 rphy = sas_rphy_alloc(phy_info->phy);
1314 if (!rphy) 1372 if (!rphy)
1315 break; /* non-fatal: an rphy can be added later */ 1373 break; /* non-fatal: an rphy can be added later */
1316 1374
1375 rphy->scsi_target_id = phy_info->attached.id;
1317 mptsas_parse_device_info(&rphy->identify, &phy_info->attached); 1376 mptsas_parse_device_info(&rphy->identify, &phy_info->attached);
1318 if (sas_rphy_add(rphy)) { 1377 if (sas_rphy_add(rphy)) {
1319 sas_rphy_free(rphy); 1378 sas_rphy_free(rphy);
@@ -1322,6 +1381,40 @@ mptsas_hotplug_work(void *arg)
1322 1381
1323 phy_info->rphy = rphy; 1382 phy_info->rphy = rphy;
1324 break; 1383 break;
1384 case MPTSAS_ADD_RAID:
1385 sdev = scsi_device_lookup(
1386 ioc->sh,
1387 ioc->num_ports,
1388 ev->id,
1389 0);
1390 if (sdev) {
1391 scsi_device_put(sdev);
1392 break;
1393 }
1394 printk(MYIOC_s_INFO_FMT
1395 "attaching device, channel %d, id %d\n",
1396 ioc->name, ioc->num_ports, ev->id);
1397 scsi_add_device(ioc->sh,
1398 ioc->num_ports,
1399 ev->id,
1400 0);
1401 mpt_findImVolumes(ioc);
1402 break;
1403 case MPTSAS_DEL_RAID:
1404 sdev = scsi_device_lookup(
1405 ioc->sh,
1406 ioc->num_ports,
1407 ev->id,
1408 0);
1409 if (!sdev)
1410 break;
1411 printk(MYIOC_s_INFO_FMT
1412 "removing device, channel %d, id %d\n",
1413 ioc->name, ioc->num_ports, ev->id);
1414 scsi_remove_device(sdev);
1415 scsi_device_put(sdev);
1416 mpt_findImVolumes(ioc);
1417 break;
1325 } 1418 }
1326 1419
1327 kfree(ev); 1420 kfree(ev);
@@ -1372,23 +1465,78 @@ mptscsih_send_sas_event(MPT_ADAPTER *ioc,
1372 schedule_work(&ev->work); 1465 schedule_work(&ev->work);
1373} 1466}
1374 1467
1468static void
1469mptscsih_send_raid_event(MPT_ADAPTER *ioc,
1470 EVENT_DATA_RAID *raid_event_data)
1471{
1472 struct mptsas_hotplug_event *ev;
1473 RAID_VOL0_STATUS * volumeStatus;
1474
1475 if (ioc->bus_type != SAS)
1476 return;
1477
1478 ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
1479 if (!ev) {
1480 printk(KERN_WARNING "mptsas: lost hotplug event\n");
1481 return;
1482 }
1483
1484 memset(ev,0,sizeof(struct mptsas_hotplug_event));
1485 INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
1486 ev->ioc = ioc;
1487 ev->id = raid_event_data->VolumeID;
1488
1489 switch (raid_event_data->ReasonCode) {
1490 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
1491 ev->event_type = MPTSAS_ADD_DEVICE;
1492 break;
1493 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
1494 ev->event_type = MPTSAS_DEL_DEVICE;
1495 break;
1496 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
1497 ev->event_type = MPTSAS_DEL_RAID;
1498 break;
1499 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
1500 ev->event_type = MPTSAS_ADD_RAID;
1501 break;
1502 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
1503 volumeStatus = (RAID_VOL0_STATUS *) &
1504 raid_event_data->SettingsStatus;
1505 ev->event_type = (volumeStatus->State ==
1506 MPI_RAIDVOL0_STATUS_STATE_FAILED) ?
1507 MPTSAS_DEL_RAID : MPTSAS_ADD_RAID;
1508 break;
1509 default:
1510 break;
1511 }
1512 schedule_work(&ev->work);
1513}
1514
1375static int 1515static int
1376mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) 1516mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
1377{ 1517{
1518 int rc=1;
1378 u8 event = le32_to_cpu(reply->Event) & 0xFF; 1519 u8 event = le32_to_cpu(reply->Event) & 0xFF;
1379 1520
1380 if (!ioc->sh) 1521 if (!ioc->sh)
1381 return 1; 1522 goto out;
1382 1523
1383 switch (event) { 1524 switch (event) {
1384 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE: 1525 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
1385 mptscsih_send_sas_event(ioc, 1526 mptscsih_send_sas_event(ioc,
1386 (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data); 1527 (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data);
1387 return 1; /* currently means nothing really */ 1528 break;
1388 1529 case MPI_EVENT_INTEGRATED_RAID:
1530 mptscsih_send_raid_event(ioc,
1531 (EVENT_DATA_RAID *)reply->Data);
1532 break;
1389 default: 1533 default:
1390 return mptscsih_event_process(ioc, reply); 1534 rc = mptscsih_event_process(ioc, reply);
1535 break;
1391 } 1536 }
1537 out:
1538
1539 return rc;
1392} 1540}
1393 1541
1394static int 1542static int