Commit ecd510d2 authored by Linus Torvalds's avatar Linus Torvalds

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
parents a8b5f8f2 39200687
......@@ -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:
......
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