Skip to contentSkip to conversation

scsi: ufs: Make sure clk scaling happens only when hba is runtime ACTIVE

PATCH Applied Can Guo 3 participants 4 messages Sep 22, 2020 – Nov 19, 2020 SCSI

lore
Share & tools
lore

Can Guo

author
#0 lore raw

PATCH 1/1 scsi: ufs: Make sure clk scaling happens only when hba is runtime ACTIVE

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

drivers/scsi/ufs/ufshcd.c +7 -0
index e4cb994..847f355 100644
@@ -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"),
Signature · 1 line
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.
author
#1 lore raw

Hi Stanley,

Quoted 37 lines · Can Guo

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

drivers/scsi/ufs/ufshcd.c +7 -0
index e4cb994..847f355 100644
@@ -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),
Quoted 1 line

(scale_up ? "up" : "down"),

Could you please review this one since we may be the only two users of clk scaling?

Thanks,

Can Guo.

Reviewed-by
#2 lore raw

Hi Can,

Quoted 43 lines · Can Guo

Hi Stanley,

Quoted 40 lines · Can Guo

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

drivers/scsi/ufs/ufshcd.c +7 -0
index e4cb994..847f355 100644
@@ -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);
 
Quoted 6 lines
Quoted 2 lines
drivers/scsi/ufs/ufshcd.c +0 -0
 	trace_ufshcd_profile_clk_scaling(dev_name(hba->dev),

(scale_up ? "up" : "down"),

Could you please review this one since we may be the only two users of clk scaling?

Looks good to me.

#3 lore raw
In reply to Can Guo
Quoted 9 lines · Can Guo

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.

[...]

Applied to 5.10/scsi-fixes, thanks!

[1/1] scsi: ufs: Make sure clk scaling happens only when HBA is runtime ACTIVE

      https://git.kernel.org/mkp/scsi/c/73cc291c2702
Signature · 1 line
Martin K. Petersen	Oracle Linux Engineering