If someone plays with the UFS clk scaling devfreq governor through sysfs,
ufshcd_devfreq_scale may be called even when hba is not runtime ACTIVE,
which can lead to unexpected error. We cannot just protect it by calling
pm_runtime_get_sync, because that may cause racing problem since hba
runtime suspend ops needs to suspend clk scaling. In order to fix it, call
pm_runtime_get_noresume and check hba's runtime status, then only proceed
if hba is runtime ACTIVE, otherwise just bail.

governor_store
 devfreq_performance_handler
  update_devfreq
   devfreq_set_target
    ufshcd_devfreq_target
     ufshcd_devfreq_scale

Signed-off-by: Can Guo <[email protected]>

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index e4cb994..847f355 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -1294,8 +1294,15 @@ static int ufshcd_devfreq_target(struct device *dev,
        }
        spin_unlock_irqrestore(hba->host->host_lock, irq_flags);
 
+       pm_runtime_get_noresume(hba->dev);
+       if (!pm_runtime_active(hba->dev)) {
+               pm_runtime_put_noidle(hba->dev);
+               ret = -EAGAIN;
+               goto out;
+       }
        start = ktime_get();
        ret = ufshcd_devfreq_scale(hba, scale_up);
+       pm_runtime_put(hba->dev);
 
        trace_ufshcd_profile_clk_scaling(dev_name(hba->dev),
                (scale_up ? "up" : "down"),
-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux 
Foundation Collaborative Project.

Reply via email to