|
|
a8a466 |
From a372b29ab979095c323d33ab922062015d459ddd Mon Sep 17 00:00:00 2001
|
|
|
a8a466 |
From: Suganath Prabu Subramani <suganath-prabu.subramani@broadcom.com>
|
|
|
a8a466 |
Date: Wed, 26 Oct 2016 13:34:34 +0530
|
|
|
a8a466 |
Subject: [PATCH 03/11] scsi: mpt3sas: Implement device_remove_in_progress
|
|
|
a8a466 |
check in IOCTL path
|
|
|
a8a466 |
|
|
|
a8a466 |
When device missing event arrives, device_remove_in_progress bit will be
|
|
|
a8a466 |
set and hence driver has to stop sending IOCTL commands.Now the check has
|
|
|
a8a466 |
been added in IOCTL path to test device_remove_in_progress bit is set, if
|
|
|
a8a466 |
so then IOCTL will be failed printing failure message.
|
|
|
a8a466 |
|
|
|
a8a466 |
Signed-off-by: Chaitra P B <chaitra.basappa@broadcom.com>
|
|
|
a8a466 |
Signed-off-by: Sathya Prakash <sathya.prakash@broadcom.com>
|
|
|
a8a466 |
Signed-off-by: Suganath Prabu S <suganath-prabu.subramani@broadcom.com>
|
|
|
a8a466 |
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
|
|
|
a8a466 |
---
|
|
|
a8a466 |
drivers/scsi/mpt3sas/mpt3sas_base.c | 19 +++++++++++++++
|
|
|
a8a466 |
drivers/scsi/mpt3sas/mpt3sas_base.h | 5 ++++
|
|
|
a8a466 |
drivers/scsi/mpt3sas/mpt3sas_ctl.c | 46 ++++++++++++++++++++++++++++++------
|
|
|
a8a466 |
drivers/scsi/mpt3sas/mpt3sas_scsih.c | 24 ++++++++++++++++++-
|
|
|
a8a466 |
4 files changed, 86 insertions(+), 8 deletions(-)
|
|
|
a8a466 |
|
|
|
a8a466 |
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c
|
|
|
a8a466 |
index 2319db8..ac87e12 100644
|
|
|
a8a466 |
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
|
|
|
a8a466 |
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
|
|
|
a8a466 |
@@ -5368,6 +5368,21 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc)
|
|
|
a8a466 |
goto out_free_resources;
|
|
|
a8a466 |
}
|
|
|
a8a466 |
|
|
|
a8a466 |
+ /* allocate memory for pending OS device add list */
|
|
|
a8a466 |
+ ioc->pend_os_device_add_sz = (ioc->facts.MaxDevHandle / 8);
|
|
|
a8a466 |
+ if (ioc->facts.MaxDevHandle % 8)
|
|
|
a8a466 |
+ ioc->pend_os_device_add_sz++;
|
|
|
a8a466 |
+ ioc->pend_os_device_add = kzalloc(ioc->pend_os_device_add_sz,
|
|
|
a8a466 |
+ GFP_KERNEL);
|
|
|
a8a466 |
+ if (!ioc->pend_os_device_add)
|
|
|
a8a466 |
+ goto out_free_resources;
|
|
|
a8a466 |
+
|
|
|
a8a466 |
+ ioc->device_remove_in_progress_sz = ioc->pend_os_device_add_sz;
|
|
|
a8a466 |
+ ioc->device_remove_in_progress =
|
|
|
a8a466 |
+ kzalloc(ioc->device_remove_in_progress_sz, GFP_KERNEL);
|
|
|
a8a466 |
+ if (!ioc->device_remove_in_progress)
|
|
|
a8a466 |
+ goto out_free_resources;
|
|
|
a8a466 |
+
|
|
|
a8a466 |
ioc->fwfault_debug = mpt3sas_fwfault_debug;
|
|
|
a8a466 |
|
|
|
a8a466 |
/* base internal command bits */
|
|
|
a8a466 |
@@ -5450,6 +5465,8 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc)
|
|
|
a8a466 |
kfree(ioc->reply_post_host_index);
|
|
|
a8a466 |
kfree(ioc->pd_handles);
|
|
|
a8a466 |
kfree(ioc->blocking_handles);
|
|
|
a8a466 |
+ kfree(ioc->device_remove_in_progress);
|
|
|
a8a466 |
+ kfree(ioc->pend_os_device_add);
|
|
|
a8a466 |
kfree(ioc->tm_cmds.reply);
|
|
|
a8a466 |
kfree(ioc->transport_cmds.reply);
|
|
|
a8a466 |
kfree(ioc->scsih_cmds.reply);
|
|
|
a8a466 |
@@ -5491,6 +5508,8 @@ mpt3sas_base_detach(struct MPT3SAS_ADAPTER *ioc)
|
|
|
a8a466 |
kfree(ioc->reply_post_host_index);
|
|
|
a8a466 |
kfree(ioc->pd_handles);
|
|
|
a8a466 |
kfree(ioc->blocking_handles);
|
|
|
a8a466 |
+ kfree(ioc->device_remove_in_progress);
|
|
|
a8a466 |
+ kfree(ioc->pend_os_device_add);
|
|
|
a8a466 |
kfree(ioc->pfacts);
|
|
|
a8a466 |
kfree(ioc->ctl_cmds.reply);
|
|
|
a8a466 |
kfree(ioc->ctl_cmds.sense);
|
|
|
a8a466 |
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h
|
|
|
a8a466 |
index 1a614d7..241a660 100644
|
|
|
a8a466 |
--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
|
|
|
a8a466 |
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
|
|
|
a8a466 |
@@ -1093,6 +1093,9 @@ struct MPT3SAS_ADAPTER {
|
|
|
a8a466 |
void *pd_handles;
|
|
|
a8a466 |
u16 pd_handles_sz;
|
|
|
a8a466 |
|
|
|
a8a466 |
+ void *pend_os_device_add;
|
|
|
a8a466 |
+ u16 pend_os_device_add_sz;
|
|
|
a8a466 |
+
|
|
|
a8a466 |
/* config page */
|
|
|
a8a466 |
u16 config_page_sz;
|
|
|
a8a466 |
void *config_page;
|
|
|
a8a466 |
@@ -1201,6 +1204,8 @@ struct MPT3SAS_ADAPTER {
|
|
|
a8a466 |
struct SL_WH_EVENT_TRIGGERS_T diag_trigger_event;
|
|
|
a8a466 |
struct SL_WH_SCSI_TRIGGERS_T diag_trigger_scsi;
|
|
|
a8a466 |
struct SL_WH_MPI_TRIGGERS_T diag_trigger_mpi;
|
|
|
a8a466 |
+ void *device_remove_in_progress;
|
|
|
a8a466 |
+ u16 device_remove_in_progress_sz;
|
|
|
a8a466 |
};
|
|
|
a8a466 |
|
|
|
a8a466 |
typedef u8 (*MPT_CALLBACK)(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
|
|
|
a8a466 |
diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
|
|
|
a8a466 |
index 7d00f09..a75f8a3 100644
|
|
|
a8a466 |
--- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c
|
|
|
a8a466 |
+++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
|
|
|
a8a466 |
@@ -655,6 +655,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
|
|
|
a8a466 |
size_t data_in_sz = 0;
|
|
|
a8a466 |
long ret;
|
|
|
a8a466 |
u16 wait_state_count;
|
|
|
a8a466 |
+ u16 device_handle = MPT3SAS_INVALID_DEVICE_HANDLE;
|
|
|
a8a466 |
|
|
|
a8a466 |
issue_reset = 0;
|
|
|
a8a466 |
|
|
|
a8a466 |
@@ -739,10 +740,13 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
|
|
|
a8a466 |
data_in_sz = karg.data_in_size;
|
|
|
a8a466 |
|
|
|
a8a466 |
if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST ||
|
|
|
a8a466 |
- mpi_request->Function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) {
|
|
|
a8a466 |
- if (!le16_to_cpu(mpi_request->FunctionDependent1) ||
|
|
|
a8a466 |
- le16_to_cpu(mpi_request->FunctionDependent1) >
|
|
|
a8a466 |
- ioc->facts.MaxDevHandle) {
|
|
|
a8a466 |
+ mpi_request->Function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH ||
|
|
|
a8a466 |
+ mpi_request->Function == MPI2_FUNCTION_SCSI_TASK_MGMT ||
|
|
|
a8a466 |
+ mpi_request->Function == MPI2_FUNCTION_SATA_PASSTHROUGH) {
|
|
|
a8a466 |
+
|
|
|
a8a466 |
+ device_handle = le16_to_cpu(mpi_request->FunctionDependent1);
|
|
|
a8a466 |
+ if (!device_handle || (device_handle >
|
|
|
a8a466 |
+ ioc->facts.MaxDevHandle)) {
|
|
|
a8a466 |
ret = -EINVAL;
|
|
|
a8a466 |
mpt3sas_base_free_smid(ioc, smid);
|
|
|
a8a466 |
goto out;
|
|
|
a8a466 |
@@ -798,12 +802,18 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
|
|
|
a8a466 |
scsiio_request->SenseBufferLowAddress =
|
|
|
a8a466 |
mpt3sas_base_get_sense_buffer_dma(ioc, smid);
|
|
|
a8a466 |
memset(ioc->ctl_cmds.sense, 0, SCSI_SENSE_BUFFERSIZE);
|
|
|
a8a466 |
+ if (test_bit(device_handle, ioc->device_remove_in_progress)) {
|
|
|
a8a466 |
+ dtmprintk(ioc, pr_info(MPT3SAS_FMT
|
|
|
a8a466 |
+ "handle(0x%04x) :ioctl failed due to device removal in progress\n",
|
|
|
a8a466 |
+ ioc->name, device_handle));
|
|
|
a8a466 |
+ mpt3sas_base_free_smid(ioc, smid);
|
|
|
a8a466 |
+ ret = -EINVAL;
|
|
|
a8a466 |
+ goto out;
|
|
|
a8a466 |
+ }
|
|
|
a8a466 |
ioc->build_sg(ioc, psge, data_out_dma, data_out_sz,
|
|
|
a8a466 |
data_in_dma, data_in_sz);
|
|
|
a8a466 |
-
|
|
|
a8a466 |
if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST)
|
|
|
a8a466 |
- mpt3sas_base_put_smid_scsi_io(ioc, smid,
|
|
|
a8a466 |
- le16_to_cpu(mpi_request->FunctionDependent1));
|
|
|
a8a466 |
+ mpt3sas_base_put_smid_scsi_io(ioc, smid, device_handle);
|
|
|
a8a466 |
else
|
|
|
a8a466 |
mpt3sas_base_put_smid_default(ioc, smid);
|
|
|
a8a466 |
break;
|
|
|
a8a466 |
@@ -828,6 +838,14 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
|
|
|
a8a466 |
}
|
|
|
a8a466 |
}
|
|
|
a8a466 |
|
|
|
a8a466 |
+ if (test_bit(device_handle, ioc->device_remove_in_progress)) {
|
|
|
a8a466 |
+ dtmprintk(ioc, pr_info(MPT3SAS_FMT
|
|
|
a8a466 |
+ "handle(0x%04x) :ioctl failed due to device removal in progress\n",
|
|
|
a8a466 |
+ ioc->name, device_handle));
|
|
|
a8a466 |
+ mpt3sas_base_free_smid(ioc, smid);
|
|
|
a8a466 |
+ ret = -EINVAL;
|
|
|
a8a466 |
+ goto out;
|
|
|
a8a466 |
+ }
|
|
|
a8a466 |
mpt3sas_scsih_set_tm_flag(ioc, le16_to_cpu(
|
|
|
a8a466 |
tm_request->DevHandle));
|
|
|
a8a466 |
ioc->build_sg_mpi(ioc, psge, data_out_dma, data_out_sz,
|
|
|
a8a466 |
@@ -867,6 +885,20 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
|
|
|
a8a466 |
break;
|
|
|
a8a466 |
}
|
|
|
a8a466 |
case MPI2_FUNCTION_SATA_PASSTHROUGH:
|
|
|
a8a466 |
+ {
|
|
|
a8a466 |
+ if (test_bit(device_handle, ioc->device_remove_in_progress)) {
|
|
|
a8a466 |
+ dtmprintk(ioc, pr_info(MPT3SAS_FMT
|
|
|
a8a466 |
+ "handle(0x%04x) :ioctl failed due to device removal in progress\n",
|
|
|
a8a466 |
+ ioc->name, device_handle));
|
|
|
a8a466 |
+ mpt3sas_base_free_smid(ioc, smid);
|
|
|
a8a466 |
+ ret = -EINVAL;
|
|
|
a8a466 |
+ goto out;
|
|
|
a8a466 |
+ }
|
|
|
a8a466 |
+ ioc->build_sg(ioc, psge, data_out_dma, data_out_sz, data_in_dma,
|
|
|
a8a466 |
+ data_in_sz);
|
|
|
a8a466 |
+ mpt3sas_base_put_smid_default(ioc, smid);
|
|
|
a8a466 |
+ break;
|
|
|
a8a466 |
+ }
|
|
|
a8a466 |
case MPI2_FUNCTION_FW_DOWNLOAD:
|
|
|
a8a466 |
case MPI2_FUNCTION_FW_UPLOAD:
|
|
|
a8a466 |
{
|
|
|
a8a466 |
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
|
|
|
a8a466 |
index 9c61476..c6aa172 100644
|
|
|
a8a466 |
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
|
|
|
a8a466 |
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
|
|
|
a8a466 |
@@ -785,6 +785,11 @@ _scsih_sas_device_add(struct MPT3SAS_ADAPTER *ioc,
|
|
|
a8a466 |
list_add_tail(&sas_device->list, &ioc->sas_device_list);
|
|
|
a8a466 |
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
|
|
|
a8a466 |
|
|
|
a8a466 |
+ if (ioc->hide_drives) {
|
|
|
a8a466 |
+ clear_bit(sas_device->handle, ioc->pend_os_device_add);
|
|
|
a8a466 |
+ return;
|
|
|
a8a466 |
+ }
|
|
|
a8a466 |
+
|
|
|
a8a466 |
if (!mpt3sas_transport_port_add(ioc, sas_device->handle,
|
|
|
a8a466 |
sas_device->sas_address_parent)) {
|
|
|
a8a466 |
_scsih_sas_device_remove(ioc, sas_device);
|
|
|
a8a466 |
@@ -800,7 +805,8 @@ _scsih_sas_device_add(struct MPT3SAS_ADAPTER *ioc,
|
|
|
a8a466 |
sas_device->sas_address_parent);
|
|
|
a8a466 |
_scsih_sas_device_remove(ioc, sas_device);
|
|
|
a8a466 |
}
|
|
|
a8a466 |
- }
|
|
|
a8a466 |
+ } else
|
|
|
a8a466 |
+ clear_bit(sas_device->handle, ioc->pend_os_device_add);
|
|
|
a8a466 |
}
|
|
|
a8a466 |
|
|
|
a8a466 |
/**
|
|
|
a8a466 |
@@ -3189,6 +3195,8 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle)
|
|
|
a8a466 |
if (test_bit(handle, ioc->pd_handles))
|
|
|
a8a466 |
return;
|
|
|
a8a466 |
|
|
|
a8a466 |
+ clear_bit(handle, ioc->pend_os_device_add);
|
|
|
a8a466 |
+
|
|
|
a8a466 |
spin_lock_irqsave(&ioc->sas_device_lock, flags);
|
|
|
a8a466 |
sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle);
|
|
|
a8a466 |
if (sas_device && sas_device->starget &&
|
|
|
a8a466 |
@@ -3243,6 +3251,7 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle)
|
|
|
a8a466 |
mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
|
|
|
a8a466 |
mpi_request->DevHandle = cpu_to_le16(handle);
|
|
|
a8a466 |
mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
|
|
|
a8a466 |
+ set_bit(handle, ioc->device_remove_in_progress);
|
|
|
a8a466 |
mpt3sas_base_put_smid_hi_priority(ioc, smid, 0);
|
|
|
a8a466 |
mpt3sas_trigger_master(ioc, MASTER_TRIGGER_DEVICE_REMOVAL);
|
|
|
a8a466 |
|
|
|
a8a466 |
@@ -3377,6 +3386,11 @@ _scsih_sas_control_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid,
|
|
|
a8a466 |
ioc->name, le16_to_cpu(mpi_reply->DevHandle), smid,
|
|
|
a8a466 |
le16_to_cpu(mpi_reply->IOCStatus),
|
|
|
a8a466 |
le32_to_cpu(mpi_reply->IOCLogInfo)));
|
|
|
a8a466 |
+ if (le16_to_cpu(mpi_reply->IOCStatus) ==
|
|
|
a8a466 |
+ MPI2_IOCSTATUS_SUCCESS) {
|
|
|
a8a466 |
+ clear_bit(le16_to_cpu(mpi_reply->DevHandle),
|
|
|
a8a466 |
+ ioc->device_remove_in_progress);
|
|
|
a8a466 |
+ }
|
|
|
a8a466 |
} else {
|
|
|
a8a466 |
pr_err(MPT3SAS_FMT "mpi_reply not valid at %s:%d/%s()!\n",
|
|
|
a8a466 |
ioc->name, __FILE__, __LINE__, __func__);
|
|
|
a8a466 |
@@ -5506,6 +5520,7 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num,
|
|
|
a8a466 |
device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
|
|
|
a8a466 |
if (!(_scsih_is_end_device(device_info)))
|
|
|
a8a466 |
return -1;
|
|
|
a8a466 |
+ set_bit(handle, ioc->pend_os_device_add);
|
|
|
a8a466 |
sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
|
|
|
a8a466 |
|
|
|
a8a466 |
/* check if device is present */
|
|
|
a8a466 |
@@ -5524,6 +5539,7 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num,
|
|
|
a8a466 |
sas_device = mpt3sas_get_sdev_by_addr(ioc,
|
|
|
a8a466 |
sas_address);
|
|
|
a8a466 |
if (sas_device) {
|
|
|
a8a466 |
+ clear_bit(handle, ioc->pend_os_device_add);
|
|
|
a8a466 |
sas_device_put(sas_device);
|
|
|
a8a466 |
return -1;
|
|
|
a8a466 |
}
|
|
|
a8a466 |
@@ -5846,6 +5862,9 @@ _scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc,
|
|
|
a8a466 |
_scsih_check_device(ioc, sas_address, handle,
|
|
|
a8a466 |
phy_number, link_rate);
|
|
|
a8a466 |
|
|
|
a8a466 |
+ if (!test_bit(handle, ioc->pend_os_device_add))
|
|
|
a8a466 |
+ break;
|
|
|
a8a466 |
+
|
|
|
a8a466 |
|
|
|
a8a466 |
case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
|
|
|
a8a466 |
|
|
|
a8a466 |
@@ -7766,6 +7785,9 @@ mpt3sas_scsih_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase)
|
|
|
a8a466 |
complete(&ioc->tm_cmds.done);
|
|
|
a8a466 |
}
|
|
|
a8a466 |
|
|
|
a8a466 |
+ memset(ioc->pend_os_device_add, 0, ioc->pend_os_device_add_sz);
|
|
|
a8a466 |
+ memset(ioc->device_remove_in_progress, 0,
|
|
|
a8a466 |
+ ioc->device_remove_in_progress_sz);
|
|
|
a8a466 |
_scsih_fw_event_cleanup_queue(ioc);
|
|
|
a8a466 |
_scsih_flush_running_cmds(ioc);
|
|
|
a8a466 |
break;
|
|
|
a8a466 |
--
|
|
|
a8a466 |
1.8.3.1
|
|
|
a8a466 |
|