Merge tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
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
This commit is contained in:
@ -3575,6 +3575,17 @@ static int mpi3mr_prepare_sg_scmd(struct mpi3mr_ioc *mrioc,
|
|||||||
scmd->sc_data_direction);
|
scmd->sc_data_direction);
|
||||||
priv->meta_sg_valid = 1; /* To unmap meta sg DMA */
|
priv->meta_sg_valid = 1; /* To unmap meta sg DMA */
|
||||||
} else {
|
} 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);
|
sg_scmd = scsi_sglist(scmd);
|
||||||
sges_left = scsi_dma_map(scmd);
|
sges_left = scsi_dma_map(scmd);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
_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
|
* _base_build_sg_scmd - main sg creation routine
|
||||||
* pcie_device is unused here!
|
* 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;
|
sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
|
||||||
|
|
||||||
sg_scmd = scsi_sglist(scmd);
|
sg_scmd = scsi_sglist(scmd);
|
||||||
sges_left = scsi_dma_map(scmd);
|
sges_left = _base_scsi_dma_map(scmd);
|
||||||
if (sges_left < 0)
|
if (sges_left < 0)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@ -2861,7 +2877,7 @@ _base_build_sg_scmd_ieee(struct MPT3SAS_ADAPTER *ioc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
sg_scmd = scsi_sglist(scmd);
|
sg_scmd = scsi_sglist(scmd);
|
||||||
sges_left = scsi_dma_map(scmd);
|
sges_left = _base_scsi_dma_map(scmd);
|
||||||
if (sges_left < 0)
|
if (sges_left < 0)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@ -4205,6 +4205,8 @@ static int sd_resume(struct device *dev)
|
|||||||
{
|
{
|
||||||
struct scsi_disk *sdkp = dev_get_drvdata(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)) {
|
if (opal_unlock_from_suspend(sdkp->opal_dev)) {
|
||||||
sd_printk(KERN_NOTICE, sdkp, "OPAL unlock failed\n");
|
sd_printk(KERN_NOTICE, sdkp, "OPAL unlock failed\n");
|
||||||
return -EIO;
|
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() */
|
if (!sdkp) /* E.g.: runtime resume at the start of sd_probe() */
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
sd_printk(KERN_NOTICE, sdkp, "Starting disk\n");
|
|
||||||
|
|
||||||
if (!sd_do_start_stop(sdkp->device, runtime)) {
|
if (!sd_do_start_stop(sdkp->device, runtime)) {
|
||||||
sdkp->suspended = false;
|
sdkp->suspended = false;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sd_printk(KERN_NOTICE, sdkp, "Starting disk\n");
|
||||||
ret = sd_start_stop_device(sdkp, 1);
|
ret = sd_start_stop_device(sdkp, 1);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
sd_resume(dev);
|
sd_resume(dev);
|
||||||
|
@ -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);
|
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)
|
static inline int ufshcd_rpm_put_sync(struct ufs_hba *hba)
|
||||||
{
|
{
|
||||||
return pm_runtime_put_sync(&hba->ufs_device_wlun->sdev_gendev);
|
return pm_runtime_put_sync(&hba->ufs_device_wlun->sdev_gendev);
|
||||||
|
@ -2416,7 +2416,17 @@ static inline int ufshcd_hba_capabilities(struct ufs_hba *hba)
|
|||||||
return err;
|
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);
|
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)
|
if (!hba->mcq_sup)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -6553,7 +6563,8 @@ again:
|
|||||||
if (ufshcd_err_handling_should_stop(hba))
|
if (ufshcd_err_handling_should_stop(hba))
|
||||||
goto skip_err_handling;
|
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;
|
bool ret;
|
||||||
|
|
||||||
spin_unlock_irqrestore(hba->host->host_lock, flags);
|
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;
|
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,
|
err = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_WRITE_ATTR, QUERY_ATTR_IDN_SECONDS_PASSED,
|
||||||
0, 0, &val);
|
0, 0, &val);
|
||||||
ufshcd_rpm_put_sync(hba);
|
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);
|
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;
|
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 (!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);
|
err = scsi_add_host(host, hba->dev);
|
||||||
if (err) {
|
if (err) {
|
||||||
dev_err(hba->dev, "scsi_add_host failed\n");
|
dev_err(hba->dev, "scsi_add_host failed\n");
|
||||||
|
@ -1293,6 +1293,9 @@ static void exynos_ufs_fmp_resume(struct ufs_hba *hba)
|
|||||||
{
|
{
|
||||||
struct arm_smccc_res res;
|
struct arm_smccc_res res;
|
||||||
|
|
||||||
|
if (!(hba->caps & UFSHCD_CAP_CRYPTO))
|
||||||
|
return;
|
||||||
|
|
||||||
arm_smccc_smc(SMC_CMD_FMP_SECURITY, 0, SMU_EMBEDDED, CFG_DESCTYPE_3,
|
arm_smccc_smc(SMC_CMD_FMP_SECURITY, 0, SMU_EMBEDDED, CFG_DESCTYPE_3,
|
||||||
0, 0, 0, 0, &res);
|
0, 0, 0, 0, &res);
|
||||||
if (res.a0)
|
if (res.a0)
|
||||||
|
@ -1109,6 +1109,7 @@ struct ufs_hba {
|
|||||||
bool ext_iid_sup;
|
bool ext_iid_sup;
|
||||||
bool scsi_host_added;
|
bool scsi_host_added;
|
||||||
bool mcq_sup;
|
bool mcq_sup;
|
||||||
|
bool lsdb_sup;
|
||||||
bool mcq_enabled;
|
bool mcq_enabled;
|
||||||
struct ufshcd_res_info res[RES_MAX];
|
struct ufshcd_res_info res[RES_MAX];
|
||||||
void __iomem *mcq_base;
|
void __iomem *mcq_base;
|
||||||
|
@ -77,6 +77,7 @@ enum {
|
|||||||
MASK_OUT_OF_ORDER_DATA_DELIVERY_SUPPORT = 0x02000000,
|
MASK_OUT_OF_ORDER_DATA_DELIVERY_SUPPORT = 0x02000000,
|
||||||
MASK_UIC_DME_TEST_MODE_SUPPORT = 0x04000000,
|
MASK_UIC_DME_TEST_MODE_SUPPORT = 0x04000000,
|
||||||
MASK_CRYPTO_SUPPORT = 0x10000000,
|
MASK_CRYPTO_SUPPORT = 0x10000000,
|
||||||
|
MASK_LSDB_SUPPORT = 0x20000000,
|
||||||
MASK_MCQ_SUPPORT = 0x40000000,
|
MASK_MCQ_SUPPORT = 0x40000000,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user