Commit defaf1a2 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull SCSI fixes from James Bottomley:
 "One core change that reverts the double message print patch in sd.c
  (it was causing regressions on embedded systems).

  The rest are driver fixes in ufs, mpt3sas and mpi3mr"

* tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi:
  scsi: ufs: exynos: Don't resume FMP when crypto support is disabled
  scsi: mpt3sas: Avoid IOMMU page faults on REPORT ZONES
  scsi: mpi3mr: Avoid IOMMU page faults on REPORT ZONES
  scsi: ufs: core: Do not set link to OFF state while waking up from hibernation
  scsi: Revert "scsi: sd: Do not repeat the starting disk message"
  scsi: ufs: core: Fix deadlock during RTC update
  scsi: ufs: core: Bypass quick recovery if force reset is needed
  scsi: ufs: core: Check LSDBS cap when !mcq
parents d3426a6e 7c632fc3
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -3575,6 +3575,17 @@ static int mpi3mr_prepare_sg_scmd(struct mpi3mr_ioc *mrioc,
		    scmd->sc_data_direction);
		priv->meta_sg_valid = 1; /* To unmap meta sg DMA */
	} else {
		/*
		 * Some firmware versions byte-swap the REPORT ZONES command
		 * reply from ATA-ZAC devices by directly accessing in the host
		 * buffer. This does not respect the default command DMA
		 * direction and causes IOMMU page faults on some architectures
		 * with an IOMMU enforcing write mappings (e.g. AMD hosts).
		 * Avoid such issue by making the REPORT ZONES buffer mapping
		 * bi-directional.
		 */
		if (scmd->cmnd[0] == ZBC_IN && scmd->cmnd[1] == ZI_REPORT_ZONES)
			scmd->sc_data_direction = DMA_BIDIRECTIONAL;
		sg_scmd = scsi_sglist(scmd);
		sges_left = scsi_dma_map(scmd);
	}
+18 −2
Original line number Diff line number Diff line
@@ -2671,6 +2671,22 @@ _base_build_zero_len_sge_ieee(struct MPT3SAS_ADAPTER *ioc, void *paddr)
	_base_add_sg_single_ieee(paddr, sgl_flags, 0, 0, -1);
}

static inline int _base_scsi_dma_map(struct scsi_cmnd *cmd)
{
	/*
	 * Some firmware versions byte-swap the REPORT ZONES command reply from
	 * ATA-ZAC devices by directly accessing in the host buffer. This does
	 * not respect the default command DMA direction and causes IOMMU page
	 * faults on some architectures with an IOMMU enforcing write mappings
	 * (e.g. AMD hosts). Avoid such issue by making the report zones buffer
	 * mapping bi-directional.
	 */
	if (cmd->cmnd[0] == ZBC_IN && cmd->cmnd[1] == ZI_REPORT_ZONES)
		cmd->sc_data_direction = DMA_BIDIRECTIONAL;

	return scsi_dma_map(cmd);
}

/**
 * _base_build_sg_scmd - main sg creation routine
 *		pcie_device is unused here!
@@ -2717,7 +2733,7 @@ _base_build_sg_scmd(struct MPT3SAS_ADAPTER *ioc,
	sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;

	sg_scmd = scsi_sglist(scmd);
	sges_left = scsi_dma_map(scmd);
	sges_left = _base_scsi_dma_map(scmd);
	if (sges_left < 0)
		return -ENOMEM;

@@ -2861,7 +2877,7 @@ _base_build_sg_scmd_ieee(struct MPT3SAS_ADAPTER *ioc,
	}

	sg_scmd = scsi_sglist(scmd);
	sges_left = scsi_dma_map(scmd);
	sges_left = _base_scsi_dma_map(scmd);
	if (sges_left < 0)
		return -ENOMEM;

+3 −2
Original line number Diff line number Diff line
@@ -4205,6 +4205,8 @@ static int sd_resume(struct device *dev)
{
	struct scsi_disk *sdkp = dev_get_drvdata(dev);

	sd_printk(KERN_NOTICE, sdkp, "Starting disk\n");

	if (opal_unlock_from_suspend(sdkp->opal_dev)) {
		sd_printk(KERN_NOTICE, sdkp, "OPAL unlock failed\n");
		return -EIO;
@@ -4221,13 +4223,12 @@ static int sd_resume_common(struct device *dev, bool runtime)
	if (!sdkp)	/* E.g.: runtime resume at the start of sd_probe() */
		return 0;

	sd_printk(KERN_NOTICE, sdkp, "Starting disk\n");

	if (!sd_do_start_stop(sdkp->device, runtime)) {
		sdkp->suspended = false;
		return 0;
	}

	sd_printk(KERN_NOTICE, sdkp, "Starting disk\n");
	ret = sd_start_stop_device(sdkp, 1);
	if (!ret) {
		sd_resume(dev);
+5 −0
Original line number Diff line number Diff line
@@ -316,6 +316,11 @@ static inline int ufshcd_rpm_get_sync(struct ufs_hba *hba)
	return pm_runtime_get_sync(&hba->ufs_device_wlun->sdev_gendev);
}

static inline int ufshcd_rpm_get_if_active(struct ufs_hba *hba)
{
	return pm_runtime_get_if_active(&hba->ufs_device_wlun->sdev_gendev);
}

static inline int ufshcd_rpm_put_sync(struct ufs_hba *hba)
{
	return pm_runtime_put_sync(&hba->ufs_device_wlun->sdev_gendev);
+22 −5
Original line number Diff line number Diff line
@@ -2416,7 +2416,17 @@ static inline int ufshcd_hba_capabilities(struct ufs_hba *hba)
		return err;
	}

	/*
	 * The UFSHCI 3.0 specification does not define MCQ_SUPPORT and
	 * LSDB_SUPPORT, but [31:29] as reserved bits with reset value 0s, which
	 * means we can simply read values regardless of version.
	 */
	hba->mcq_sup = FIELD_GET(MASK_MCQ_SUPPORT, hba->capabilities);
	/*
	 * 0h: legacy single doorbell support is available
	 * 1h: indicate that legacy single doorbell support has been removed
	 */
	hba->lsdb_sup = !FIELD_GET(MASK_LSDB_SUPPORT, hba->capabilities);
	if (!hba->mcq_sup)
		return 0;

@@ -6553,7 +6563,8 @@ static void ufshcd_err_handler(struct work_struct *work)
	if (ufshcd_err_handling_should_stop(hba))
		goto skip_err_handling;

	if (hba->dev_quirks & UFS_DEVICE_QUIRK_RECOVERY_FROM_DL_NAC_ERRORS) {
	if ((hba->dev_quirks & UFS_DEVICE_QUIRK_RECOVERY_FROM_DL_NAC_ERRORS) &&
	    !hba->force_reset) {
		bool ret;

		spin_unlock_irqrestore(hba->host->host_lock, flags);
@@ -8211,7 +8222,10 @@ static void ufshcd_update_rtc(struct ufs_hba *hba)
	 */
	val = ts64.tv_sec - hba->dev_info.rtc_time_baseline;

	ufshcd_rpm_get_sync(hba);
	/* Skip update RTC if RPM state is not RPM_ACTIVE */
	if (ufshcd_rpm_get_if_active(hba) <= 0)
		return;

	err = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_WRITE_ATTR, QUERY_ATTR_IDN_SECONDS_PASSED,
				0, 0, &val);
	ufshcd_rpm_put_sync(hba);
@@ -10265,9 +10279,6 @@ int ufshcd_system_restore(struct device *dev)
	 */
	ufshcd_readl(hba, REG_UTP_TASK_REQ_LIST_BASE_H);

	/* Resuming from hibernate, assume that link was OFF */
	ufshcd_set_link_off(hba);

	return 0;

}
@@ -10496,6 +10507,12 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
	}

	if (!is_mcq_supported(hba)) {
		if (!hba->lsdb_sup) {
			dev_err(hba->dev, "%s: failed to initialize (legacy doorbell mode not supported)\n",
				__func__);
			err = -EINVAL;
			goto out_disable;
		}
		err = scsi_add_host(host, hba->dev);
		if (err) {
			dev_err(hba->dev, "scsi_add_host failed\n");
Loading