aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/mpt2sas
diff options
context:
space:
mode:
authornagalakshmi.nandigama@lsi.com <nagalakshmi.nandigama@lsi.com>2011-10-21 00:38:07 -0400
committerJames Bottomley <JBottomley@Parallels.com>2011-10-30 04:56:55 -0400
commit35116db95c42937061bfca93998291f6562e9e92 (patch)
treeca1c8d23186c78d8796c8786d8d566c7fc845f64 /drivers/scsi/mpt2sas
parent6faace2a0e418b45728bcea6d3626922cf16b14b (diff)
[SCSI] mpt2sas: Fix for Panic when inactive volume is tried deleting
The driver was setting the action to MPI2_CONFIG_ACTION_PAGE_READ_CURRENT, which only returns active volumes. In order to get info on inactive volumes, the driver needs to change the action to MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM, and traverse each config till the iocstatus is MPI2_IOCSTATUS_CONFIG_INVALID_PAGE returned. Added a change in the driver to remove the instance of sas_device object when the driver returns "1" from the slave_configure callback. Also fixed code to report the hot spares to the operating system with a /dev/sg assigned. Signed-off-by: Nagalakshmi Nandigama <nagalakshmi.nandigama@lsi.com> Cc: stable@kernel.org Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/mpt2sas')
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_config.c67
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_scsih.c46
2 files changed, 82 insertions, 31 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_config.c b/drivers/scsi/mpt2sas/mpt2sas_config.c
index 2b1101076cfe..36ea0b2d8020 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_config.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_config.c
@@ -1356,6 +1356,9 @@ mpt2sas_config_get_volume_handle(struct MPT2SAS_ADAPTER *ioc, u16 pd_handle,
1356 Mpi2ConfigReply_t mpi_reply; 1356 Mpi2ConfigReply_t mpi_reply;
1357 int r, i, config_page_sz; 1357 int r, i, config_page_sz;
1358 u16 ioc_status; 1358 u16 ioc_status;
1359 int config_num;
1360 u16 element_type;
1361 u16 phys_disk_dev_handle;
1359 1362
1360 *volume_handle = 0; 1363 *volume_handle = 0;
1361 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1364 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
@@ -1371,35 +1374,53 @@ mpt2sas_config_get_volume_handle(struct MPT2SAS_ADAPTER *ioc, u16 pd_handle,
1371 if (r) 1374 if (r)
1372 goto out; 1375 goto out;
1373 1376
1374 mpi_request.PageAddress =
1375 cpu_to_le32(MPI2_RAID_PGAD_FORM_ACTIVE_CONFIG);
1376 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1377 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1377 config_page_sz = (le16_to_cpu(mpi_reply.ExtPageLength) * 4); 1378 config_page_sz = (le16_to_cpu(mpi_reply.ExtPageLength) * 4);
1378 config_page = kmalloc(config_page_sz, GFP_KERNEL); 1379 config_page = kmalloc(config_page_sz, GFP_KERNEL);
1379 if (!config_page) 1380 if (!config_page) {
1380 goto out; 1381 r = -1;
1381 r = _config_request(ioc, &mpi_request, &mpi_reply,
1382 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1383 config_page_sz);
1384 if (r)
1385 goto out; 1382 goto out;
1386 1383 }
1387 r = -1; 1384 config_num = 0xff;
1388 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; 1385 while (1) {
1389 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) 1386 mpi_request.PageAddress = cpu_to_le32(config_num +
1390 goto out; 1387 MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM);
1391 for (i = 0; i < config_page->NumElements; i++) { 1388 r = _config_request(ioc, &mpi_request, &mpi_reply,
1392 if ((le16_to_cpu(config_page->ConfigElement[i].ElementFlags) & 1389 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1393 MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE) != 1390 config_page_sz);
1394 MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT) 1391 if (r)
1395 continue; 1392 goto out;
1396 if (le16_to_cpu(config_page->ConfigElement[i]. 1393 r = -1;
1397 PhysDiskDevHandle) == pd_handle) { 1394 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1398 *volume_handle = le16_to_cpu(config_page-> 1395 MPI2_IOCSTATUS_MASK;
1399 ConfigElement[i].VolDevHandle); 1396 if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
1400 r = 0;
1401 goto out; 1397 goto out;
1398 for (i = 0; i < config_page->NumElements; i++) {
1399 element_type = le16_to_cpu(config_page->
1400 ConfigElement[i].ElementFlags) &
1401 MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE;
1402 if (element_type ==
1403 MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT ||
1404 element_type ==
1405 MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT) {
1406 phys_disk_dev_handle =
1407 le16_to_cpu(config_page->ConfigElement[i].
1408 PhysDiskDevHandle);
1409 if (phys_disk_dev_handle == pd_handle) {
1410 *volume_handle =
1411 le16_to_cpu(config_page->
1412 ConfigElement[i].VolDevHandle);
1413 r = 0;
1414 goto out;
1415 }
1416 } else if (element_type ==
1417 MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT) {
1418 *volume_handle = 0;
1419 r = 0;
1420 goto out;
1421 }
1402 } 1422 }
1423 config_num = config_page->ConfigNum;
1403 } 1424 }
1404 out: 1425 out:
1405 kfree(config_page); 1426 kfree(config_page);
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
index a8cb57723ff4..8889b1babcac 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -610,8 +610,15 @@ _scsih_sas_device_add(struct MPT2SAS_ADAPTER *ioc,
610 spin_unlock_irqrestore(&ioc->sas_device_lock, flags); 610 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
611 611
612 if (!mpt2sas_transport_port_add(ioc, sas_device->handle, 612 if (!mpt2sas_transport_port_add(ioc, sas_device->handle,
613 sas_device->sas_address_parent)) 613 sas_device->sas_address_parent)) {
614 _scsih_sas_device_remove(ioc, sas_device); 614 _scsih_sas_device_remove(ioc, sas_device);
615 } else if (!sas_device->starget) {
616 if (!ioc->is_driver_loading)
617 mpt2sas_transport_port_remove(ioc,
618 sas_device->sas_address,
619 sas_device->sas_address_parent);
620 _scsih_sas_device_remove(ioc, sas_device);
621 }
615} 622}
616 623
617/** 624/**
@@ -1423,6 +1430,10 @@ _scsih_slave_destroy(struct scsi_device *sdev)
1423{ 1430{
1424 struct MPT2SAS_TARGET *sas_target_priv_data; 1431 struct MPT2SAS_TARGET *sas_target_priv_data;
1425 struct scsi_target *starget; 1432 struct scsi_target *starget;
1433 struct Scsi_Host *shost;
1434 struct MPT2SAS_ADAPTER *ioc;
1435 struct _sas_device *sas_device;
1436 unsigned long flags;
1426 1437
1427 if (!sdev->hostdata) 1438 if (!sdev->hostdata)
1428 return; 1439 return;
@@ -1430,6 +1441,19 @@ _scsih_slave_destroy(struct scsi_device *sdev)
1430 starget = scsi_target(sdev); 1441 starget = scsi_target(sdev);
1431 sas_target_priv_data = starget->hostdata; 1442 sas_target_priv_data = starget->hostdata;
1432 sas_target_priv_data->num_luns--; 1443 sas_target_priv_data->num_luns--;
1444
1445 shost = dev_to_shost(&starget->dev);
1446 ioc = shost_priv(shost);
1447
1448 if (!(sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) {
1449 spin_lock_irqsave(&ioc->sas_device_lock, flags);
1450 sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
1451 sas_target_priv_data->sas_address);
1452 if (sas_device)
1453 sas_device->starget = NULL;
1454 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1455 }
1456
1433 kfree(sdev->hostdata); 1457 kfree(sdev->hostdata);
1434 sdev->hostdata = NULL; 1458 sdev->hostdata = NULL;
1435} 1459}
@@ -2045,7 +2069,8 @@ _scsih_slave_configure(struct scsi_device *sdev)
2045 __FILE__, __LINE__, __func__)); 2069 __FILE__, __LINE__, __func__));
2046 return 1; 2070 return 1;
2047 } 2071 }
2048 if (mpt2sas_config_get_volume_wwid(ioc, 2072 if (sas_device->volume_handle &&
2073 mpt2sas_config_get_volume_wwid(ioc,
2049 sas_device->volume_handle, 2074 sas_device->volume_handle,
2050 &sas_device->volume_wwid)) { 2075 &sas_device->volume_wwid)) {
2051 dfailprintk(ioc, printk(MPT2SAS_WARN_FMT 2076 dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
@@ -5893,8 +5918,11 @@ _scsih_reprobe_lun(struct scsi_device *sdev, void *no_uld_attach)
5893static void 5918static void
5894_scsih_reprobe_target(struct scsi_target *starget, int no_uld_attach) 5919_scsih_reprobe_target(struct scsi_target *starget, int no_uld_attach)
5895{ 5920{
5896 struct MPT2SAS_TARGET *sas_target_priv_data = starget->hostdata; 5921 struct MPT2SAS_TARGET *sas_target_priv_data;
5897 5922
5923 if (starget == NULL)
5924 return;
5925 sas_target_priv_data = starget->hostdata;
5898 if (no_uld_attach) 5926 if (no_uld_attach)
5899 sas_target_priv_data->flags |= MPT_TARGET_FLAGS_RAID_COMPONENT; 5927 sas_target_priv_data->flags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
5900 else 5928 else
@@ -7676,8 +7704,9 @@ _scsih_probe_boot_devices(struct MPT2SAS_ADAPTER *ioc)
7676 sas_device->sas_address_parent)) { 7704 sas_device->sas_address_parent)) {
7677 _scsih_sas_device_remove(ioc, sas_device); 7705 _scsih_sas_device_remove(ioc, sas_device);
7678 } else if (!sas_device->starget) { 7706 } else if (!sas_device->starget) {
7679 mpt2sas_transport_port_remove(ioc, sas_address, 7707 if (!ioc->is_driver_loading)
7680 sas_address_parent); 7708 mpt2sas_transport_port_remove(ioc, sas_address,
7709 sas_address_parent);
7681 _scsih_sas_device_remove(ioc, sas_device); 7710 _scsih_sas_device_remove(ioc, sas_device);
7682 } 7711 }
7683 } 7712 }
@@ -7731,9 +7760,10 @@ _scsih_probe_sas(struct MPT2SAS_ADAPTER *ioc)
7731 kfree(sas_device); 7760 kfree(sas_device);
7732 continue; 7761 continue;
7733 } else if (!sas_device->starget) { 7762 } else if (!sas_device->starget) {
7734 mpt2sas_transport_port_remove(ioc, 7763 if (!ioc->is_driver_loading)
7735 sas_device->sas_address, 7764 mpt2sas_transport_port_remove(ioc,
7736 sas_device->sas_address_parent); 7765 sas_device->sas_address,
7766 sas_device->sas_address_parent);
7737 list_del(&sas_device->list); 7767 list_del(&sas_device->list);
7738 kfree(sas_device); 7768 kfree(sas_device);
7739 continue; 7769 continue;