Commit 1c8ac1c4 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull SCSI fixes from James Bottomley:
 "Four fixes, three in drivers.

  The two biggest fixes are ufs and the remaining driver and core fix
  are small and obvious (and the core fix is low risk)"

* tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi:
  scsi: ufs: core: Fix a race condition related to device management
  scsi: core: Fix warning in scsi_alloc_sgtables()
  scsi: ufs: host: Hold reference returned by of_parse_phandle()
  scsi: mpt3sas: Stop fw fault watchdog work item during system shutdown
parents bb83c99d f5c2976e
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -11386,6 +11386,7 @@ scsih_shutdown(struct pci_dev *pdev)
	_scsih_ir_shutdown(ioc);
	_scsih_ir_shutdown(ioc);
	_scsih_nvme_shutdown(ioc);
	_scsih_nvme_shutdown(ioc);
	mpt3sas_base_mask_interrupts(ioc);
	mpt3sas_base_mask_interrupts(ioc);
	mpt3sas_base_stop_watchdog(ioc);
	ioc->shost_recovery = 1;
	ioc->shost_recovery = 1;
	mpt3sas_base_make_ioc_ready(ioc, SOFT_RESET);
	mpt3sas_base_make_ioc_ready(ioc, SOFT_RESET);
	ioc->shost_recovery = 0;
	ioc->shost_recovery = 0;
+1 −1
Original line number Original line Diff line number Diff line
@@ -450,7 +450,7 @@ static int sg_io(struct scsi_device *sdev, struct sg_io_hdr *hdr, fmode_t mode)
		goto out_put_request;
		goto out_put_request;


	ret = 0;
	ret = 0;
	if (hdr->iovec_count) {
	if (hdr->iovec_count && hdr->dxfer_len) {
		struct iov_iter i;
		struct iov_iter i;
		struct iovec *iov = NULL;
		struct iovec *iov = NULL;


+40 −18
Original line number Original line Diff line number Diff line
@@ -2953,37 +2953,59 @@ ufshcd_dev_cmd_completion(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
static int ufshcd_wait_for_dev_cmd(struct ufs_hba *hba,
static int ufshcd_wait_for_dev_cmd(struct ufs_hba *hba,
		struct ufshcd_lrb *lrbp, int max_timeout)
		struct ufshcd_lrb *lrbp, int max_timeout)
{
{
	int err = 0;
	unsigned long time_left = msecs_to_jiffies(max_timeout);
	unsigned long time_left;
	unsigned long flags;
	unsigned long flags;
	bool pending;
	int err;


retry:
	time_left = wait_for_completion_timeout(hba->dev_cmd.complete,
	time_left = wait_for_completion_timeout(hba->dev_cmd.complete,
			msecs_to_jiffies(max_timeout));
						time_left);


	spin_lock_irqsave(hba->host->host_lock, flags);
	hba->dev_cmd.complete = NULL;
	if (likely(time_left)) {
	if (likely(time_left)) {
		/*
		 * The completion handler called complete() and the caller of
		 * this function still owns the @lrbp tag so the code below does
		 * not trigger any race conditions.
		 */
		hba->dev_cmd.complete = NULL;
		err = ufshcd_get_tr_ocs(lrbp);
		err = ufshcd_get_tr_ocs(lrbp);
		if (!err)
		if (!err)
			err = ufshcd_dev_cmd_completion(hba, lrbp);
			err = ufshcd_dev_cmd_completion(hba, lrbp);
	}
	} else {
	spin_unlock_irqrestore(hba->host->host_lock, flags);

	if (!time_left) {
		err = -ETIMEDOUT;
		err = -ETIMEDOUT;
		dev_dbg(hba->dev, "%s: dev_cmd request timedout, tag %d\n",
		dev_dbg(hba->dev, "%s: dev_cmd request timedout, tag %d\n",
			__func__, lrbp->task_tag);
			__func__, lrbp->task_tag);
		if (!ufshcd_clear_cmds(hba, 1U << lrbp->task_tag))
		if (ufshcd_clear_cmds(hba, 1U << lrbp->task_tag) == 0) {
			/* successfully cleared the command, retry if needed */
			/* successfully cleared the command, retry if needed */
			err = -EAGAIN;
			err = -EAGAIN;
			/*
			/*
		 * in case of an error, after clearing the doorbell,
			 * Since clearing the command succeeded we also need to
		 * we also need to clear the outstanding_request
			 * clear the task tag bit from the outstanding_reqs
		 * field in hba
			 * variable.
			 */
			 */
			spin_lock_irqsave(&hba->outstanding_lock, flags);
			spin_lock_irqsave(&hba->outstanding_lock, flags);
		__clear_bit(lrbp->task_tag, &hba->outstanding_reqs);
			pending = test_bit(lrbp->task_tag,
					   &hba->outstanding_reqs);
			if (pending) {
				hba->dev_cmd.complete = NULL;
				__clear_bit(lrbp->task_tag,
					    &hba->outstanding_reqs);
			}
			spin_unlock_irqrestore(&hba->outstanding_lock, flags);
			spin_unlock_irqrestore(&hba->outstanding_lock, flags);

			if (!pending) {
				/*
				 * The completion handler ran while we tried to
				 * clear the command.
				 */
				time_left = 1;
				goto retry;
			}
		} else {
			dev_err(hba->dev, "%s: failed to clear tag %d\n",
				__func__, lrbp->task_tag);
		}
	}
	}


	return err;
	return err;
+13 −2
Original line number Original line Diff line number Diff line
@@ -108,6 +108,17 @@ static int ufshcd_parse_clock_info(struct ufs_hba *hba)
	return ret;
	return ret;
}
}


static bool phandle_exists(const struct device_node *np,
			   const char *phandle_name, int index)
{
	struct device_node *parse_np = of_parse_phandle(np, phandle_name, index);

	if (parse_np)
		of_node_put(parse_np);

	return parse_np != NULL;
}

#define MAX_PROP_SIZE 32
#define MAX_PROP_SIZE 32
static int ufshcd_populate_vreg(struct device *dev, const char *name,
static int ufshcd_populate_vreg(struct device *dev, const char *name,
				struct ufs_vreg **out_vreg)
				struct ufs_vreg **out_vreg)
@@ -122,7 +133,7 @@ static int ufshcd_populate_vreg(struct device *dev, const char *name,
	}
	}


	snprintf(prop_name, MAX_PROP_SIZE, "%s-supply", name);
	snprintf(prop_name, MAX_PROP_SIZE, "%s-supply", name);
	if (!of_parse_phandle(np, prop_name, 0)) {
	if (!phandle_exists(np, prop_name, 0)) {
		dev_info(dev, "%s: Unable to find %s regulator, assuming enabled\n",
		dev_info(dev, "%s: Unable to find %s regulator, assuming enabled\n",
				__func__, prop_name);
				__func__, prop_name);
		goto out;
		goto out;