aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/message/fusion/mptsas.c
diff options
context:
space:
mode:
authorMoore, Eric <Eric.Moore@lsil.com>2006-01-26 18:20:06 -0500
committerJames Bottomley <jejb@mulgrave.(none)>2006-01-31 15:39:37 -0500
commitc73787eecdbe4691d4e3f989052db8b552e1ac34 (patch)
treef5c53229a700edbc0f27a4fc203811032dcb1c02 /drivers/message/fusion/mptsas.c
parentd99ca4180fe44ae7f409fc73f1a09f270b8d458a (diff)
[SCSI] fusion: add support for raid hot add/del support
RAID event support. This will hot add and remove raid volumes when managment application creates and deletes the volumes. The driver is basically responding to firmware asyn events, and reporting the changes to the above layers. Signed-off-by: Eric Moore <Eric.Moore@lsil.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
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