diff --git a/drivers/scsi/ufs/ufs-qcom-debugfs.c b/drivers/scsi/ufs/ufs-qcom-debugfs.c index 8532439c392d..4547a6dbdb23 100644 --- a/drivers/scsi/ufs/ufs-qcom-debugfs.c +++ b/drivers/scsi/ufs/ufs-qcom-debugfs.c @@ -67,6 +67,7 @@ static int ufs_qcom_dbg_testbus_en_read(void *data, u64 *attr_val) static int ufs_qcom_dbg_testbus_en_set(void *data, u64 attr_id) { struct ufs_qcom_host *host = data; + int ret = 0; if (!host) return -EINVAL; @@ -76,7 +77,13 @@ static int ufs_qcom_dbg_testbus_en_set(void *data, u64 attr_id) else host->dbg_print_en &= ~UFS_QCOM_DBG_PRINT_TEST_BUS_EN; - return ufs_qcom_testbus_config(host); + pm_runtime_get_sync(host->hba->dev); + ufshcd_hold(host->hba, false); + ret = ufs_qcom_testbus_config(host); + ufshcd_release(host->hba, false); + pm_runtime_put_sync(host->hba->dev); + + return ret; } DEFINE_SIMPLE_ATTRIBUTE(ufs_qcom_dbg_testbus_en_ops, @@ -142,7 +149,11 @@ static ssize_t ufs_qcom_dbg_testbus_cfg_write(struct file *file, * Sanity check of the {major, minor} tuple is done in the * config function */ + pm_runtime_get_sync(host->hba->dev); + ufshcd_hold(host->hba, false); ret = ufs_qcom_testbus_config(host); + ufshcd_release(host->hba, false); + pm_runtime_put_sync(host->hba->dev); if (!ret) dev_dbg(host->hba->dev, "%s: New configuration: major=%d, minor=%d\n", diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index 03b222d8be93..7369478a8c5d 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -2452,6 +2452,11 @@ static bool ufs_qcom_testbus_cfg_is_ok(struct ufs_qcom_host *host) return true; } +/* + * The caller of this function must make sure that the controller + * is out of runtime suspend and appropriate clocks are enabled + * before accessing. + */ int ufs_qcom_testbus_config(struct ufs_qcom_host *host) { int reg; @@ -2522,8 +2527,6 @@ int ufs_qcom_testbus_config(struct ufs_qcom_host *host) } mask <<= offset; - pm_runtime_get_sync(host->hba->dev); - ufshcd_hold(host->hba, false); ufshcd_rmwl(host->hba, TEST_BUS_SEL, (u32)host->testbus.select_major << 19, REG_UFS_CFG1); @@ -2536,8 +2539,6 @@ int ufs_qcom_testbus_config(struct ufs_qcom_host *host) * committed before returning. */ mb(); - ufshcd_release(host->hba, false); - pm_runtime_put_sync(host->hba->dev); return 0; } diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index d4acc3c911f5..73d298da7885 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -4141,17 +4141,17 @@ int ufshcd_wait_for_doorbell_clr(struct ufs_hba *hba, u64 wait_timeout_us) ufshcd_hold_all(hba); spin_lock_irqsave(hba->host->host_lock, flags); - if (hba->ufshcd_state != UFSHCD_STATE_OPERATIONAL) { - ret = -EBUSY; - goto out; - } - /* * Wait for all the outstanding tasks/transfer requests. * Verify by checking the doorbell registers are clear. */ start = ktime_get(); do { + if (hba->ufshcd_state != UFSHCD_STATE_OPERATIONAL) { + ret = -EBUSY; + goto out; + } + tm_doorbell = ufshcd_readl(hba, REG_UTP_TASK_REQ_DOOR_BELL); tr_doorbell = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL); if (!tm_doorbell && !tr_doorbell) {