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, ...@@ -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; mcp->in_mb |= MBX_13|MBX_12|MBX_11|MBX_10;
if (IS_FWI2_CAPABLE(vha->hw)) if (IS_FWI2_CAPABLE(vha->hw))
mcp->in_mb |= MBX_19|MBX_18|MBX_17|MBX_16; mcp->in_mb |= MBX_19|MBX_18|MBX_17|MBX_16;
if (IS_QLA27XX(vha->hw) || IS_QLA28XX(vha->hw)) { if (IS_QLA27XX(vha->hw) || IS_QLA28XX(vha->hw))
mcp->in_mb |= MBX_15; mcp->in_mb |= MBX_15|MBX_21|MBX_22|MBX_23;
mcp->out_mb |= MBX_7|MBX_21|MBX_22|MBX_23;
}
mcp->tov = MBX_TOV_SECONDS; mcp->tov = MBX_TOV_SECONDS;
mcp->flags = 0; mcp->flags = 0;
......
...@@ -792,6 +792,7 @@ store_state_field(struct device *dev, struct device_attribute *attr, ...@@ -792,6 +792,7 @@ store_state_field(struct device *dev, struct device_attribute *attr,
int i, ret; int i, ret;
struct scsi_device *sdev = to_scsi_device(dev); struct scsi_device *sdev = to_scsi_device(dev);
enum scsi_device_state state = 0; enum scsi_device_state state = 0;
bool rescan_dev = false;
for (i = 0; i < ARRAY_SIZE(sdev_states); i++) { for (i = 0; i < ARRAY_SIZE(sdev_states); i++) {
const int len = strlen(sdev_states[i].name); const int len = strlen(sdev_states[i].name);
...@@ -810,7 +811,16 @@ store_state_field(struct device *dev, struct device_attribute *attr, ...@@ -810,7 +811,16 @@ store_state_field(struct device *dev, struct device_attribute *attr,
} }
mutex_lock(&sdev->state_mutex); mutex_lock(&sdev->state_mutex);
if (sdev->sdev_state == SDEV_RUNNING && state == SDEV_RUNNING) {
ret = count;
} else {
ret = scsi_device_set_state(sdev, state); 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 * If the device state changes to SDEV_RUNNING, we need to
* run the queue to avoid I/O hang, and rescan the device * run the queue to avoid I/O hang, and rescan the device
...@@ -819,11 +829,9 @@ store_state_field(struct device *dev, struct device_attribute *attr, ...@@ -819,11 +829,9 @@ store_state_field(struct device *dev, struct device_attribute *attr,
* blk_mq_freeze_queue_wait() and because that call may be * blk_mq_freeze_queue_wait() and because that call may be
* waiting for pending I/O to finish. * waiting for pending I/O to finish.
*/ */
if (ret == 0 && state == SDEV_RUNNING) {
blk_mq_run_hw_queues(sdev->request_queue, true); blk_mq_run_hw_queues(sdev->request_queue, true);
scsi_rescan_device(dev); scsi_rescan_device(dev);
} }
mutex_unlock(&sdev->state_mutex);
return ret == 0 ? count : -EINVAL; return ret == 0 ? count : -EINVAL;
} }
......
...@@ -1899,12 +1899,12 @@ static void session_recovery_timedout(struct work_struct *work) ...@@ -1899,12 +1899,12 @@ static void session_recovery_timedout(struct work_struct *work)
} }
spin_unlock_irqrestore(&session->lock, flags); 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"); ISCSI_DBG_TRANS_SESSION(session, "Unblocking SCSI target\n");
scsi_target_unblock(&session->dev, SDEV_TRANSPORT_OFFLINE); scsi_target_unblock(&session->dev, SDEV_TRANSPORT_OFFLINE);
ISCSI_DBG_TRANS_SESSION(session, "Completed unblocking SCSI target\n"); 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) static void __iscsi_unblock_session(struct work_struct *work)
......
...@@ -6453,9 +6453,8 @@ static irqreturn_t ufshcd_tmc_handler(struct ufs_hba *hba) ...@@ -6453,9 +6453,8 @@ static irqreturn_t ufshcd_tmc_handler(struct ufs_hba *hba)
irqreturn_t ret = IRQ_NONE; irqreturn_t ret = IRQ_NONE;
int tag; int tag;
pending = ufshcd_readl(hba, REG_UTP_TASK_REQ_DOOR_BELL);
spin_lock_irqsave(hba->host->host_lock, flags); spin_lock_irqsave(hba->host->host_lock, flags);
pending = ufshcd_readl(hba, REG_UTP_TASK_REQ_DOOR_BELL);
issued = hba->outstanding_tasks & ~pending; issued = hba->outstanding_tasks & ~pending;
for_each_set_bit(tag, &issued, hba->nutmrs) { for_each_set_bit(tag, &issued, hba->nutmrs) {
struct request *req = hba->tmf_rqs[tag]; struct request *req = hba->tmf_rqs[tag];
...@@ -6616,11 +6615,6 @@ static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba, ...@@ -6616,11 +6615,6 @@ static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba,
err = wait_for_completion_io_timeout(&wait, err = wait_for_completion_io_timeout(&wait,
msecs_to_jiffies(TM_CMD_TIMEOUT)); msecs_to_jiffies(TM_CMD_TIMEOUT));
if (!err) { 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); ufshcd_add_tm_upiu_trace(hba, task_tag, UFS_TM_ERR);
dev_err(hba->dev, "%s: task management cmd 0x%.2x timed-out\n", dev_err(hba->dev, "%s: task management cmd 0x%.2x timed-out\n",
__func__, tm_function); __func__, tm_function);
...@@ -7116,6 +7110,7 @@ static int ufshcd_abort(struct scsi_cmnd *cmd) ...@@ -7116,6 +7110,7 @@ static int ufshcd_abort(struct scsi_cmnd *cmd)
goto release; goto release;
} }
lrbp->cmd = NULL;
err = SUCCESS; err = SUCCESS;
release: 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