Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 35116db9 authored by nagalakshmi.nandigama@lsi.com's avatar nagalakshmi.nandigama@lsi.com Committed by James Bottomley
Browse files

[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: default avatarNagalakshmi Nandigama <nagalakshmi.nandigama@lsi.com>
Cc: stable@kernel.org
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 6faace2a
Loading
Loading
Loading
Loading
+44 −23
Original line number Diff line number Diff line
@@ -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;
	}
	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;
		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->
			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);
+38 −8
Original line number Diff line number Diff line
@@ -610,9 +610,16 @@ _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);
		}
}

/**
 * _scsih_sas_device_init_add - insert sas_device to the list.
@@ -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,6 +7704,7 @@ _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) {
			if (!ioc->is_driver_loading)
				mpt2sas_transport_port_remove(ioc, sas_address,
					sas_address_parent);
			_scsih_sas_device_remove(ioc, sas_device);
@@ -7731,6 +7760,7 @@ _scsih_probe_sas(struct MPT2SAS_ADAPTER *ioc)
			kfree(sas_device);
			continue;
		} else if (!sas_device->starget) {
			if (!ioc->is_driver_loading)
				mpt2sas_transport_port_remove(ioc,
					sas_device->sas_address,
					sas_device->sas_address_parent);