mirror of
https://github.com/torvalds/linux.git
synced 2024-11-14 08:02:07 +00:00
SCSI fixes on 20211119
Six fixes, five in drivers (ufs, qla2xxx, iscsi) and one core change to fix a regression in user space device state setting, which is used by the iscsi daemons to effect device recovery. Signed-off-by: James E.J. Bottomley <jejb@linux.ibm.com> -----BEGIN PGP SIGNATURE----- iJwEABMIAEQWIQTnYEDbdso9F2cI+arnQslM7pishQUCYZelhSYcamFtZXMuYm90 dG9tbGV5QGhhbnNlbnBhcnRuZXJzaGlwLmNvbQAKCRDnQslM7pishcsGAP9rh7ja 1B/OA4L//dD/8iMUXzwm+c74HKSW0BjHeAyKPAEAsszc8aqKtTauAiRg+hKnn33J WufnWaF5aH4WatToQi8= =biOQ -----END PGP SIGNATURE----- Merge tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi Pull SCSI fixes from James Bottomley: "Six fixes, five in drivers (ufs, qla2xxx, iscsi) and one core change to fix a regression in user space device state setting, which is used by the iscsi daemons to effect device recovery" * tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: scsi: qla2xxx: Fix mailbox direction flags in qla2xxx_get_adapter_id() scsi: ufs: core: Fix another task management completion race scsi: ufs: core: Fix task management completion timeout race scsi: core: sysfs: Fix hang when device state is set via sysfs scsi: iscsi: Unblock session then wake up error handler scsi: ufs: core: Improve SCSI abort handling
This commit is contained in:
commit
ecd510d2ff
@ -1695,10 +1695,8 @@ qla2x00_get_adapter_id(scsi_qla_host_t *vha, uint16_t *id, uint8_t *al_pa,
|
||||
mcp->in_mb |= MBX_13|MBX_12|MBX_11|MBX_10;
|
||||
if (IS_FWI2_CAPABLE(vha->hw))
|
||||
mcp->in_mb |= MBX_19|MBX_18|MBX_17|MBX_16;
|
||||
if (IS_QLA27XX(vha->hw) || IS_QLA28XX(vha->hw)) {
|
||||
mcp->in_mb |= MBX_15;
|
||||
mcp->out_mb |= MBX_7|MBX_21|MBX_22|MBX_23;
|
||||
}
|
||||
if (IS_QLA27XX(vha->hw) || IS_QLA28XX(vha->hw))
|
||||
mcp->in_mb |= MBX_15|MBX_21|MBX_22|MBX_23;
|
||||
|
||||
mcp->tov = MBX_TOV_SECONDS;
|
||||
mcp->flags = 0;
|
||||
|
@ -792,6 +792,7 @@ store_state_field(struct device *dev, struct device_attribute *attr,
|
||||
int i, ret;
|
||||
struct scsi_device *sdev = to_scsi_device(dev);
|
||||
enum scsi_device_state state = 0;
|
||||
bool rescan_dev = false;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sdev_states); i++) {
|
||||
const int len = strlen(sdev_states[i].name);
|
||||
@ -810,20 +811,27 @@ store_state_field(struct device *dev, struct device_attribute *attr,
|
||||
}
|
||||
|
||||
mutex_lock(&sdev->state_mutex);
|
||||
ret = scsi_device_set_state(sdev, state);
|
||||
/*
|
||||
* If the device state changes to SDEV_RUNNING, we need to
|
||||
* run the queue to avoid I/O hang, and rescan the device
|
||||
* to revalidate it. Running the queue first is necessary
|
||||
* because another thread may be waiting inside
|
||||
* blk_mq_freeze_queue_wait() and because that call may be
|
||||
* waiting for pending I/O to finish.
|
||||
*/
|
||||
if (ret == 0 && state == SDEV_RUNNING) {
|
||||
if (sdev->sdev_state == SDEV_RUNNING && state == SDEV_RUNNING) {
|
||||
ret = count;
|
||||
} else {
|
||||
ret = scsi_device_set_state(sdev, state);
|
||||
if (ret == 0 && state == SDEV_RUNNING)
|
||||
rescan_dev = true;
|
||||
}
|
||||
mutex_unlock(&sdev->state_mutex);
|
||||
|
||||
if (rescan_dev) {
|
||||
/*
|
||||
* If the device state changes to SDEV_RUNNING, we need to
|
||||
* run the queue to avoid I/O hang, and rescan the device
|
||||
* to revalidate it. Running the queue first is necessary
|
||||
* because another thread may be waiting inside
|
||||
* blk_mq_freeze_queue_wait() and because that call may be
|
||||
* waiting for pending I/O to finish.
|
||||
*/
|
||||
blk_mq_run_hw_queues(sdev->request_queue, true);
|
||||
scsi_rescan_device(dev);
|
||||
}
|
||||
mutex_unlock(&sdev->state_mutex);
|
||||
|
||||
return ret == 0 ? count : -EINVAL;
|
||||
}
|
||||
|
@ -1899,12 +1899,12 @@ static void session_recovery_timedout(struct work_struct *work)
|
||||
}
|
||||
spin_unlock_irqrestore(&session->lock, flags);
|
||||
|
||||
if (session->transport->session_recovery_timedout)
|
||||
session->transport->session_recovery_timedout(session);
|
||||
|
||||
ISCSI_DBG_TRANS_SESSION(session, "Unblocking SCSI target\n");
|
||||
scsi_target_unblock(&session->dev, SDEV_TRANSPORT_OFFLINE);
|
||||
ISCSI_DBG_TRANS_SESSION(session, "Completed unblocking SCSI target\n");
|
||||
|
||||
if (session->transport->session_recovery_timedout)
|
||||
session->transport->session_recovery_timedout(session);
|
||||
}
|
||||
|
||||
static void __iscsi_unblock_session(struct work_struct *work)
|
||||
|
@ -6453,9 +6453,8 @@ static irqreturn_t ufshcd_tmc_handler(struct ufs_hba *hba)
|
||||
irqreturn_t ret = IRQ_NONE;
|
||||
int tag;
|
||||
|
||||
pending = ufshcd_readl(hba, REG_UTP_TASK_REQ_DOOR_BELL);
|
||||
|
||||
spin_lock_irqsave(hba->host->host_lock, flags);
|
||||
pending = ufshcd_readl(hba, REG_UTP_TASK_REQ_DOOR_BELL);
|
||||
issued = hba->outstanding_tasks & ~pending;
|
||||
for_each_set_bit(tag, &issued, hba->nutmrs) {
|
||||
struct request *req = hba->tmf_rqs[tag];
|
||||
@ -6616,11 +6615,6 @@ static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba,
|
||||
err = wait_for_completion_io_timeout(&wait,
|
||||
msecs_to_jiffies(TM_CMD_TIMEOUT));
|
||||
if (!err) {
|
||||
/*
|
||||
* Make sure that ufshcd_compl_tm() does not trigger a
|
||||
* use-after-free.
|
||||
*/
|
||||
req->end_io_data = NULL;
|
||||
ufshcd_add_tm_upiu_trace(hba, task_tag, UFS_TM_ERR);
|
||||
dev_err(hba->dev, "%s: task management cmd 0x%.2x timed-out\n",
|
||||
__func__, tm_function);
|
||||
@ -7116,6 +7110,7 @@ static int ufshcd_abort(struct scsi_cmnd *cmd)
|
||||
goto release;
|
||||
}
|
||||
|
||||
lrbp->cmd = NULL;
|
||||
err = SUCCESS;
|
||||
|
||||
release:
|
||||
|
Loading…
Reference in New Issue
Block a user