Commit ecd510d2 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
Loading
Loading
Loading
Loading
+2 −4
Original line number Diff line number Diff line
@@ -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;
+19 −11
Original line number Diff line number Diff line
@@ -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,7 +811,16 @@ store_state_field(struct device *dev, struct device_attribute *attr,
	}

	mutex_lock(&sdev->state_mutex);
	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
@@ -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
		 * waiting for pending I/O to finish.
		 */
	if (ret == 0 && state == SDEV_RUNNING) {
		blk_mq_run_hw_queues(sdev->request_queue, true);
		scsi_rescan_device(dev);
	}
	mutex_unlock(&sdev->state_mutex);

	return ret == 0 ? count : -EINVAL;
}
+3 −3
Original line number Diff line number Diff line
@@ -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)
+2 −7
Original line number Diff line number Diff line
@@ -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: