mirror of
https://github.com/torvalds/linux.git
synced 2024-11-11 22:51:42 +00:00
[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>
This commit is contained in:
parent
6faace2a0e
commit
35116db95c
@ -1356,6 +1356,9 @@ mpt2sas_config_get_volume_handle(struct MPT2SAS_ADAPTER *ioc, u16 pd_handle,
|
||||
Mpi2ConfigReply_t mpi_reply;
|
||||
int r, i, config_page_sz;
|
||||
u16 ioc_status;
|
||||
int config_num;
|
||||
u16 element_type;
|
||||
u16 phys_disk_dev_handle;
|
||||
|
||||
*volume_handle = 0;
|
||||
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
|
||||
@ -1371,35 +1374,53 @@ mpt2sas_config_get_volume_handle(struct MPT2SAS_ADAPTER *ioc, u16 pd_handle,
|
||||
if (r)
|
||||
goto out;
|
||||
|
||||
mpi_request.PageAddress =
|
||||
cpu_to_le32(MPI2_RAID_PGAD_FORM_ACTIVE_CONFIG);
|
||||
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
|
||||
config_page_sz = (le16_to_cpu(mpi_reply.ExtPageLength) * 4);
|
||||
config_page = kmalloc(config_page_sz, GFP_KERNEL);
|
||||
if (!config_page)
|
||||
if (!config_page) {
|
||||
r = -1;
|
||||
goto out;
|
||||
r = _config_request(ioc, &mpi_request, &mpi_reply,
|
||||
MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
|
||||
config_page_sz);
|
||||
if (r)
|
||||
goto out;
|
||||
|
||||
r = -1;
|
||||
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
|
||||
if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
|
||||
goto out;
|
||||
for (i = 0; i < config_page->NumElements; i++) {
|
||||
if ((le16_to_cpu(config_page->ConfigElement[i].ElementFlags) &
|
||||
MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE) !=
|
||||
MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT)
|
||||
continue;
|
||||
if (le16_to_cpu(config_page->ConfigElement[i].
|
||||
PhysDiskDevHandle) == pd_handle) {
|
||||
*volume_handle = le16_to_cpu(config_page->
|
||||
ConfigElement[i].VolDevHandle);
|
||||
r = 0;
|
||||
}
|
||||
config_num = 0xff;
|
||||
while (1) {
|
||||
mpi_request.PageAddress = cpu_to_le32(config_num +
|
||||
MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM);
|
||||
r = _config_request(ioc, &mpi_request, &mpi_reply,
|
||||
MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
|
||||
config_page_sz);
|
||||
if (r)
|
||||
goto out;
|
||||
r = -1;
|
||||
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
|
||||
MPI2_IOCSTATUS_MASK;
|
||||
if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
|
||||
goto out;
|
||||
for (i = 0; i < config_page->NumElements; i++) {
|
||||
element_type = le16_to_cpu(config_page->
|
||||
ConfigElement[i].ElementFlags) &
|
||||
MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE;
|
||||
if (element_type ==
|
||||
MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT ||
|
||||
element_type ==
|
||||
MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT) {
|
||||
phys_disk_dev_handle =
|
||||
le16_to_cpu(config_page->ConfigElement[i].
|
||||
PhysDiskDevHandle);
|
||||
if (phys_disk_dev_handle == pd_handle) {
|
||||
*volume_handle =
|
||||
le16_to_cpu(config_page->
|
||||
ConfigElement[i].VolDevHandle);
|
||||
r = 0;
|
||||
goto out;
|
||||
}
|
||||
} else if (element_type ==
|
||||
MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT) {
|
||||
*volume_handle = 0;
|
||||
r = 0;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
config_num = config_page->ConfigNum;
|
||||
}
|
||||
out:
|
||||
kfree(config_page);
|
||||
|
@ -610,8 +610,15 @@ _scsih_sas_device_add(struct MPT2SAS_ADAPTER *ioc,
|
||||
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
|
||||
|
||||
if (!mpt2sas_transport_port_add(ioc, sas_device->handle,
|
||||
sas_device->sas_address_parent))
|
||||
sas_device->sas_address_parent)) {
|
||||
_scsih_sas_device_remove(ioc, sas_device);
|
||||
} else if (!sas_device->starget) {
|
||||
if (!ioc->is_driver_loading)
|
||||
mpt2sas_transport_port_remove(ioc,
|
||||
sas_device->sas_address,
|
||||
sas_device->sas_address_parent);
|
||||
_scsih_sas_device_remove(ioc, sas_device);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1423,6 +1430,10 @@ _scsih_slave_destroy(struct scsi_device *sdev)
|
||||
{
|
||||
struct MPT2SAS_TARGET *sas_target_priv_data;
|
||||
struct scsi_target *starget;
|
||||
struct Scsi_Host *shost;
|
||||
struct MPT2SAS_ADAPTER *ioc;
|
||||
struct _sas_device *sas_device;
|
||||
unsigned long flags;
|
||||
|
||||
if (!sdev->hostdata)
|
||||
return;
|
||||
@ -1430,6 +1441,19 @@ _scsih_slave_destroy(struct scsi_device *sdev)
|
||||
starget = scsi_target(sdev);
|
||||
sas_target_priv_data = starget->hostdata;
|
||||
sas_target_priv_data->num_luns--;
|
||||
|
||||
shost = dev_to_shost(&starget->dev);
|
||||
ioc = shost_priv(shost);
|
||||
|
||||
if (!(sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) {
|
||||
spin_lock_irqsave(&ioc->sas_device_lock, flags);
|
||||
sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
|
||||
sas_target_priv_data->sas_address);
|
||||
if (sas_device)
|
||||
sas_device->starget = NULL;
|
||||
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
|
||||
}
|
||||
|
||||
kfree(sdev->hostdata);
|
||||
sdev->hostdata = NULL;
|
||||
}
|
||||
@ -2045,7 +2069,8 @@ _scsih_slave_configure(struct scsi_device *sdev)
|
||||
__FILE__, __LINE__, __func__));
|
||||
return 1;
|
||||
}
|
||||
if (mpt2sas_config_get_volume_wwid(ioc,
|
||||
if (sas_device->volume_handle &&
|
||||
mpt2sas_config_get_volume_wwid(ioc,
|
||||
sas_device->volume_handle,
|
||||
&sas_device->volume_wwid)) {
|
||||
dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
|
||||
@ -5893,8 +5918,11 @@ _scsih_reprobe_lun(struct scsi_device *sdev, void *no_uld_attach)
|
||||
static void
|
||||
_scsih_reprobe_target(struct scsi_target *starget, int no_uld_attach)
|
||||
{
|
||||
struct MPT2SAS_TARGET *sas_target_priv_data = starget->hostdata;
|
||||
struct MPT2SAS_TARGET *sas_target_priv_data;
|
||||
|
||||
if (starget == NULL)
|
||||
return;
|
||||
sas_target_priv_data = starget->hostdata;
|
||||
if (no_uld_attach)
|
||||
sas_target_priv_data->flags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
|
||||
else
|
||||
@ -7676,8 +7704,9 @@ _scsih_probe_boot_devices(struct MPT2SAS_ADAPTER *ioc)
|
||||
sas_device->sas_address_parent)) {
|
||||
_scsih_sas_device_remove(ioc, sas_device);
|
||||
} else if (!sas_device->starget) {
|
||||
mpt2sas_transport_port_remove(ioc, sas_address,
|
||||
sas_address_parent);
|
||||
if (!ioc->is_driver_loading)
|
||||
mpt2sas_transport_port_remove(ioc, sas_address,
|
||||
sas_address_parent);
|
||||
_scsih_sas_device_remove(ioc, sas_device);
|
||||
}
|
||||
}
|
||||
@ -7731,9 +7760,10 @@ _scsih_probe_sas(struct MPT2SAS_ADAPTER *ioc)
|
||||
kfree(sas_device);
|
||||
continue;
|
||||
} else if (!sas_device->starget) {
|
||||
mpt2sas_transport_port_remove(ioc,
|
||||
sas_device->sas_address,
|
||||
sas_device->sas_address_parent);
|
||||
if (!ioc->is_driver_loading)
|
||||
mpt2sas_transport_port_remove(ioc,
|
||||
sas_device->sas_address,
|
||||
sas_device->sas_address_parent);
|
||||
list_del(&sas_device->list);
|
||||
kfree(sas_device);
|
||||
continue;
|
||||
|
Loading…
Reference in New Issue
Block a user