Commit c696f7b8 authored by Suganath Prabu Subramani's avatar Suganath Prabu Subramani Committed by Martin K. Petersen

scsi: mpt3sas: Implement device_remove_in_progress check in IOCTL path

When device missing event arrives, device_remove_in_progress bit will be
set and hence driver has to stop sending IOCTL commands.Now the check has
been added in IOCTL path to test device_remove_in_progress bit is set, if
so then IOCTL will be failed printing failure message.
Signed-off-by: default avatarChaitra P B <chaitra.basappa@broadcom.com>
Signed-off-by: default avatarSathya Prakash <sathya.prakash@broadcom.com>
Signed-off-by: default avatarSuganath Prabu S <suganath-prabu.subramani@broadcom.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent bb350661
...@@ -5334,6 +5334,21 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc) ...@@ -5334,6 +5334,21 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc)
goto out_free_resources; goto out_free_resources;
} }
/* allocate memory for pending OS device add list */
ioc->pend_os_device_add_sz = (ioc->facts.MaxDevHandle / 8);
if (ioc->facts.MaxDevHandle % 8)
ioc->pend_os_device_add_sz++;
ioc->pend_os_device_add = kzalloc(ioc->pend_os_device_add_sz,
GFP_KERNEL);
if (!ioc->pend_os_device_add)
goto out_free_resources;
ioc->device_remove_in_progress_sz = ioc->pend_os_device_add_sz;
ioc->device_remove_in_progress =
kzalloc(ioc->device_remove_in_progress_sz, GFP_KERNEL);
if (!ioc->device_remove_in_progress)
goto out_free_resources;
ioc->fwfault_debug = mpt3sas_fwfault_debug; ioc->fwfault_debug = mpt3sas_fwfault_debug;
/* base internal command bits */ /* base internal command bits */
...@@ -5416,6 +5431,8 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc) ...@@ -5416,6 +5431,8 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc)
kfree(ioc->reply_post_host_index); kfree(ioc->reply_post_host_index);
kfree(ioc->pd_handles); kfree(ioc->pd_handles);
kfree(ioc->blocking_handles); kfree(ioc->blocking_handles);
kfree(ioc->device_remove_in_progress);
kfree(ioc->pend_os_device_add);
kfree(ioc->tm_cmds.reply); kfree(ioc->tm_cmds.reply);
kfree(ioc->transport_cmds.reply); kfree(ioc->transport_cmds.reply);
kfree(ioc->scsih_cmds.reply); kfree(ioc->scsih_cmds.reply);
...@@ -5457,6 +5474,8 @@ mpt3sas_base_detach(struct MPT3SAS_ADAPTER *ioc) ...@@ -5457,6 +5474,8 @@ mpt3sas_base_detach(struct MPT3SAS_ADAPTER *ioc)
kfree(ioc->reply_post_host_index); kfree(ioc->reply_post_host_index);
kfree(ioc->pd_handles); kfree(ioc->pd_handles);
kfree(ioc->blocking_handles); kfree(ioc->blocking_handles);
kfree(ioc->device_remove_in_progress);
kfree(ioc->pend_os_device_add);
kfree(ioc->pfacts); kfree(ioc->pfacts);
kfree(ioc->ctl_cmds.reply); kfree(ioc->ctl_cmds.reply);
kfree(ioc->ctl_cmds.sense); kfree(ioc->ctl_cmds.sense);
......
...@@ -1079,6 +1079,9 @@ struct MPT3SAS_ADAPTER { ...@@ -1079,6 +1079,9 @@ struct MPT3SAS_ADAPTER {
void *pd_handles; void *pd_handles;
u16 pd_handles_sz; u16 pd_handles_sz;
void *pend_os_device_add;
u16 pend_os_device_add_sz;
/* config page */ /* config page */
u16 config_page_sz; u16 config_page_sz;
void *config_page; void *config_page;
...@@ -1187,6 +1190,8 @@ struct MPT3SAS_ADAPTER { ...@@ -1187,6 +1190,8 @@ struct MPT3SAS_ADAPTER {
struct SL_WH_EVENT_TRIGGERS_T diag_trigger_event; struct SL_WH_EVENT_TRIGGERS_T diag_trigger_event;
struct SL_WH_SCSI_TRIGGERS_T diag_trigger_scsi; struct SL_WH_SCSI_TRIGGERS_T diag_trigger_scsi;
struct SL_WH_MPI_TRIGGERS_T diag_trigger_mpi; struct SL_WH_MPI_TRIGGERS_T diag_trigger_mpi;
void *device_remove_in_progress;
u16 device_remove_in_progress_sz;
}; };
typedef u8 (*MPT_CALLBACK)(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, typedef u8 (*MPT_CALLBACK)(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
......
...@@ -654,6 +654,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, ...@@ -654,6 +654,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
size_t data_in_sz = 0; size_t data_in_sz = 0;
long ret; long ret;
u16 wait_state_count; u16 wait_state_count;
u16 device_handle = MPT3SAS_INVALID_DEVICE_HANDLE;
issue_reset = 0; issue_reset = 0;
...@@ -738,10 +739,13 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, ...@@ -738,10 +739,13 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
data_in_sz = karg.data_in_size; data_in_sz = karg.data_in_size;
if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST || if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST ||
mpi_request->Function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) { mpi_request->Function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH ||
if (!le16_to_cpu(mpi_request->FunctionDependent1) || mpi_request->Function == MPI2_FUNCTION_SCSI_TASK_MGMT ||
le16_to_cpu(mpi_request->FunctionDependent1) > mpi_request->Function == MPI2_FUNCTION_SATA_PASSTHROUGH) {
ioc->facts.MaxDevHandle) {
device_handle = le16_to_cpu(mpi_request->FunctionDependent1);
if (!device_handle || (device_handle >
ioc->facts.MaxDevHandle)) {
ret = -EINVAL; ret = -EINVAL;
mpt3sas_base_free_smid(ioc, smid); mpt3sas_base_free_smid(ioc, smid);
goto out; goto out;
...@@ -797,12 +801,18 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, ...@@ -797,12 +801,18 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
scsiio_request->SenseBufferLowAddress = scsiio_request->SenseBufferLowAddress =
mpt3sas_base_get_sense_buffer_dma(ioc, smid); mpt3sas_base_get_sense_buffer_dma(ioc, smid);
memset(ioc->ctl_cmds.sense, 0, SCSI_SENSE_BUFFERSIZE); memset(ioc->ctl_cmds.sense, 0, SCSI_SENSE_BUFFERSIZE);
if (test_bit(device_handle, ioc->device_remove_in_progress)) {
dtmprintk(ioc, pr_info(MPT3SAS_FMT
"handle(0x%04x) :ioctl failed due to device removal in progress\n",
ioc->name, device_handle));
mpt3sas_base_free_smid(ioc, smid);
ret = -EINVAL;
goto out;
}
ioc->build_sg(ioc, psge, data_out_dma, data_out_sz, ioc->build_sg(ioc, psge, data_out_dma, data_out_sz,
data_in_dma, data_in_sz); data_in_dma, data_in_sz);
if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST) if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST)
mpt3sas_base_put_smid_scsi_io(ioc, smid, mpt3sas_base_put_smid_scsi_io(ioc, smid, device_handle);
le16_to_cpu(mpi_request->FunctionDependent1));
else else
mpt3sas_base_put_smid_default(ioc, smid); mpt3sas_base_put_smid_default(ioc, smid);
break; break;
...@@ -827,6 +837,14 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, ...@@ -827,6 +837,14 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
} }
} }
if (test_bit(device_handle, ioc->device_remove_in_progress)) {
dtmprintk(ioc, pr_info(MPT3SAS_FMT
"handle(0x%04x) :ioctl failed due to device removal in progress\n",
ioc->name, device_handle));
mpt3sas_base_free_smid(ioc, smid);
ret = -EINVAL;
goto out;
}
mpt3sas_scsih_set_tm_flag(ioc, le16_to_cpu( mpt3sas_scsih_set_tm_flag(ioc, le16_to_cpu(
tm_request->DevHandle)); tm_request->DevHandle));
ioc->build_sg_mpi(ioc, psge, data_out_dma, data_out_sz, ioc->build_sg_mpi(ioc, psge, data_out_dma, data_out_sz,
...@@ -866,6 +884,20 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, ...@@ -866,6 +884,20 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
break; break;
} }
case MPI2_FUNCTION_SATA_PASSTHROUGH: case MPI2_FUNCTION_SATA_PASSTHROUGH:
{
if (test_bit(device_handle, ioc->device_remove_in_progress)) {
dtmprintk(ioc, pr_info(MPT3SAS_FMT
"handle(0x%04x) :ioctl failed due to device removal in progress\n",
ioc->name, device_handle));
mpt3sas_base_free_smid(ioc, smid);
ret = -EINVAL;
goto out;
}
ioc->build_sg(ioc, psge, data_out_dma, data_out_sz, data_in_dma,
data_in_sz);
mpt3sas_base_put_smid_default(ioc, smid);
break;
}
case MPI2_FUNCTION_FW_DOWNLOAD: case MPI2_FUNCTION_FW_DOWNLOAD:
case MPI2_FUNCTION_FW_UPLOAD: case MPI2_FUNCTION_FW_UPLOAD:
{ {
......
...@@ -788,6 +788,11 @@ _scsih_sas_device_add(struct MPT3SAS_ADAPTER *ioc, ...@@ -788,6 +788,11 @@ _scsih_sas_device_add(struct MPT3SAS_ADAPTER *ioc,
list_add_tail(&sas_device->list, &ioc->sas_device_list); list_add_tail(&sas_device->list, &ioc->sas_device_list);
spin_unlock_irqrestore(&ioc->sas_device_lock, flags); spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
if (ioc->hide_drives) {
clear_bit(sas_device->handle, ioc->pend_os_device_add);
return;
}
if (!mpt3sas_transport_port_add(ioc, sas_device->handle, if (!mpt3sas_transport_port_add(ioc, sas_device->handle,
sas_device->sas_address_parent)) { sas_device->sas_address_parent)) {
_scsih_sas_device_remove(ioc, sas_device); _scsih_sas_device_remove(ioc, sas_device);
...@@ -803,7 +808,8 @@ _scsih_sas_device_add(struct MPT3SAS_ADAPTER *ioc, ...@@ -803,7 +808,8 @@ _scsih_sas_device_add(struct MPT3SAS_ADAPTER *ioc,
sas_device->sas_address_parent); sas_device->sas_address_parent);
_scsih_sas_device_remove(ioc, sas_device); _scsih_sas_device_remove(ioc, sas_device);
} }
} } else
clear_bit(sas_device->handle, ioc->pend_os_device_add);
} }
/** /**
...@@ -3138,6 +3144,8 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle) ...@@ -3138,6 +3144,8 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle)
if (test_bit(handle, ioc->pd_handles)) if (test_bit(handle, ioc->pd_handles))
return; return;
clear_bit(handle, ioc->pend_os_device_add);
spin_lock_irqsave(&ioc->sas_device_lock, flags); spin_lock_irqsave(&ioc->sas_device_lock, flags);
sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle); sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle);
if (sas_device && sas_device->starget && if (sas_device && sas_device->starget &&
...@@ -3192,6 +3200,7 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle) ...@@ -3192,6 +3200,7 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle)
mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
mpi_request->DevHandle = cpu_to_le16(handle); mpi_request->DevHandle = cpu_to_le16(handle);
mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET; mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
set_bit(handle, ioc->device_remove_in_progress);
mpt3sas_base_put_smid_hi_priority(ioc, smid, 0); mpt3sas_base_put_smid_hi_priority(ioc, smid, 0);
mpt3sas_trigger_master(ioc, MASTER_TRIGGER_DEVICE_REMOVAL); mpt3sas_trigger_master(ioc, MASTER_TRIGGER_DEVICE_REMOVAL);
...@@ -3326,6 +3335,11 @@ _scsih_sas_control_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid, ...@@ -3326,6 +3335,11 @@ _scsih_sas_control_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid,
ioc->name, le16_to_cpu(mpi_reply->DevHandle), smid, ioc->name, le16_to_cpu(mpi_reply->DevHandle), smid,
le16_to_cpu(mpi_reply->IOCStatus), le16_to_cpu(mpi_reply->IOCStatus),
le32_to_cpu(mpi_reply->IOCLogInfo))); le32_to_cpu(mpi_reply->IOCLogInfo)));
if (le16_to_cpu(mpi_reply->IOCStatus) ==
MPI2_IOCSTATUS_SUCCESS) {
clear_bit(le16_to_cpu(mpi_reply->DevHandle),
ioc->device_remove_in_progress);
}
} else { } else {
pr_err(MPT3SAS_FMT "mpi_reply not valid at %s:%d/%s()!\n", pr_err(MPT3SAS_FMT "mpi_reply not valid at %s:%d/%s()!\n",
ioc->name, __FILE__, __LINE__, __func__); ioc->name, __FILE__, __LINE__, __func__);
...@@ -5449,6 +5463,7 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num, ...@@ -5449,6 +5463,7 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num,
device_info = le32_to_cpu(sas_device_pg0.DeviceInfo); device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
if (!(_scsih_is_end_device(device_info))) if (!(_scsih_is_end_device(device_info)))
return -1; return -1;
set_bit(handle, ioc->pend_os_device_add);
sas_address = le64_to_cpu(sas_device_pg0.SASAddress); sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
/* check if device is present */ /* check if device is present */
...@@ -5467,6 +5482,7 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num, ...@@ -5467,6 +5482,7 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num,
sas_device = mpt3sas_get_sdev_by_addr(ioc, sas_device = mpt3sas_get_sdev_by_addr(ioc,
sas_address); sas_address);
if (sas_device) { if (sas_device) {
clear_bit(handle, ioc->pend_os_device_add);
sas_device_put(sas_device); sas_device_put(sas_device);
return -1; return -1;
} }
...@@ -5790,6 +5806,9 @@ _scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc, ...@@ -5790,6 +5806,9 @@ _scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc,
_scsih_check_device(ioc, sas_address, handle, _scsih_check_device(ioc, sas_address, handle,
phy_number, link_rate); phy_number, link_rate);
if (!test_bit(handle, ioc->pend_os_device_add))
break;
case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED: case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
...@@ -7707,6 +7726,9 @@ mpt3sas_scsih_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase) ...@@ -7707,6 +7726,9 @@ mpt3sas_scsih_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase)
complete(&ioc->tm_cmds.done); complete(&ioc->tm_cmds.done);
} }
memset(ioc->pend_os_device_add, 0, ioc->pend_os_device_add_sz);
memset(ioc->device_remove_in_progress, 0,
ioc->device_remove_in_progress_sz);
_scsih_fw_event_cleanup_queue(ioc); _scsih_fw_event_cleanup_queue(ioc);
_scsih_flush_running_cmds(ioc); _scsih_flush_running_cmds(ioc);
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment