Message ID | 20250508093854.3281475-1-quic_ziqichen@quicinc.com |
---|---|
State | Superseded |
Headers | show |
Series | [v3] scsi: ufs: core: skip UFS clkscale if host asynchronous scan in progress | expand |
On 5/8/25 2:38 AM, Ziqi Chen wrote: > diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c > index 1c53ccf5a616..04f40677e76a 100644 > --- a/drivers/ufs/core/ufshcd.c > +++ b/drivers/ufs/core/ufshcd.c > @@ -1207,6 +1207,9 @@ static bool ufshcd_is_devfreq_scaling_required(struct ufs_hba *hba, > if (list_empty(head)) > return false; > > + if (hba->host->async_scan) > + return false; Testing a boolean is never a proper way to synchronize code sections. As an example, the SCSI core could set hba->host->async_scan after this check completed and before the code below is executed. I think we need a better solution. Bart.
On 5/9/2025 12:06 AM, Bart Van Assche wrote: > On 5/8/25 2:38 AM, Ziqi Chen wrote: >> diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c >> index 1c53ccf5a616..04f40677e76a 100644 >> --- a/drivers/ufs/core/ufshcd.c >> +++ b/drivers/ufs/core/ufshcd.c >> @@ -1207,6 +1207,9 @@ static bool >> ufshcd_is_devfreq_scaling_required(struct ufs_hba *hba, >> if (list_empty(head)) >> return false; >> + if (hba->host->async_scan) >> + return false; > > Testing a boolean is never a proper way to synchronize code sections. > As an example, the SCSI core could set hba->host->async_scan after this > check completed and before the code below is executed. I think we need a > better solution. Hi Bart, I get your point, we have also taken this into consideration. That's why we move ufshcd_devfreq_init() out of ufshd_add_lus(). Old sequence: | ufshcd_async_scan() |ufshcd_add_lus() |ufshcd_devfreq_init() | | enable UFS clock scaling |scsi_scan_host() |scsi_prep_async_scan() | | set host->async_scan to '1' |async_schedule(do_scan_async, data) With this old sequence , The ufs devfreq monitor started before the scsi_prep_async_scan(), the SCSI core could set hba->host->async_scan after this check. New sequence: | ufshcd_async_scan() |ufshcd_add_lus() | |scsi_scan_host() | |scsi_prep_async_scan() | | | set host->async_scan to '1' | |async_schedule(do_scan_async, data) |ufshcd_devfreq_init() | |enable UFS clock scaling With the new sequence , it is guaranteed that host->async_scan is set before the UFS clock scaling enabling. I guess you might be worried about out-of-order execution will cause this flag not be set before clock scaling enabling with extremely low probability? If yes, do you have any suggestion on this ? BRs, Ziqi > > Bart.
diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index 1c53ccf5a616..04f40677e76a 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -1207,6 +1207,9 @@ static bool ufshcd_is_devfreq_scaling_required(struct ufs_hba *hba, if (list_empty(head)) return false; + if (hba->host->async_scan) + return false; + if (hba->use_pm_opp) return freq != hba->clk_scaling.target_freq; @@ -8740,21 +8743,6 @@ static int ufshcd_add_lus(struct ufs_hba *hba) if (ret) goto out; - /* Initialize devfreq after UFS device is detected */ - if (ufshcd_is_clkscaling_supported(hba)) { - memcpy(&hba->clk_scaling.saved_pwr_info, - &hba->pwr_info, - sizeof(struct ufs_pa_layer_attr)); - hba->clk_scaling.is_allowed = true; - - ret = ufshcd_devfreq_init(hba); - if (ret) - goto out; - - hba->clk_scaling.is_enabled = true; - ufshcd_init_clk_scaling_sysfs(hba); - } - /* * The RTC update code accesses the hba->ufs_device_wlun->sdev_gendev * pointer and hence must only be started after the WLUN pointer has @@ -9009,6 +8997,23 @@ static void ufshcd_async_scan(void *data, async_cookie_t cookie) /* Probe and add UFS logical units */ ret = ufshcd_add_lus(hba); + if (ret) + goto out; + + /* Initialize devfreq and start devfreq monitor */ + if (ufshcd_is_clkscaling_supported(hba)) { + memcpy(&hba->clk_scaling.saved_pwr_info, + &hba->pwr_info, + sizeof(struct ufs_pa_layer_attr)); + hba->clk_scaling.is_allowed = true; + + ret = ufshcd_devfreq_init(hba); + if (ret) + goto out; + + hba->clk_scaling.is_enabled = true; + ufshcd_init_clk_scaling_sysfs(hba); + } out: pm_runtime_put_sync(hba->dev);