ufs: core: fix lockdep warning of clk_scaling_lock
Subsystems (3)
PATCH v2 1/1 ufs: core: fix lockdep warning of clk_scaling_lock
From: Peter Wang <[email protected]>
There have a lockdep warning like below in current flow. kworker/u16:0: Possible unsafe locking scenario:
kworker/u16:0: CPU0 CPU1 kworker/u16:0: ---- ----
kworker/u16:0: lock(&hba->clk_scaling_lock);
kworker/u16:0: lock(&hba->dev_cmd.lock);
kworker/u16:0: lock(&hba->clk_scaling_lock);
kworker/u16:0: lock(&hba->dev_cmd.lock);
kworker/u16:0:
Before this patch clk_scaling_lock was held in reader mode during the ufshcd_wb_toggle() call. With this patch applied clk_scaling_lock is not held while ufshcd_wb_toggle() is called.
This is safe because ufshcd_wb_toggle will held clk_scaling_lock in reader mode "again" in flow ufshcd_wb_toggle -> __ufshcd_wb_toggle -> ufshcd_query_flag_retry -> ufshcd_query_flag -> ufshcd_exec_dev_cmd -> down_read(&hba->clk_scaling_lock);
The protect should enough and make sure clock is not change while send command.
--- drivers/ufs/core/ufshcd.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-)
drivers/ufs/core/ufshcd.c +11 -11
@@ -1249,12 +1249,10 @@ static int ufshcd_clock_scaling_prepare(struct ufs_hba *hba)return ret; } -static void ufshcd_clock_scaling_unprepare (struct ufs_hba *hba,bool writelock) +static void ufshcd_clock_scaling_unprepare (struct ufs_hba *hba) { -if (writelock) -up_write (&hba->clk_scaling_lock); -else -up_read (&hba->clk_scaling_lock); +up_write (&hba->clk_scaling_lock); +ufshcd_scsi_unblock_requests (hba);ufshcd_release (hba); }
@@ -1271,7 +1269,7 @@ static void ufshcd_clock_scaling_unprepare(struct ufs_hba *hba, bool writelock)static int ufshcd_devfreq_scale (struct ufs_hba *hba,bool scale_up) {int ret =0 ; -bool is_writelock = true; +bool wb_toggle = false; ret =ufshcd_clock_scaling_prepare (hba);if (ret)
@@ -1300,13 +1298,15 @@ static int ufshcd_devfreq_scale(struct ufs_hba *hba, bool scale_up) } } -/* Enable Write Booster if we have scaled up else disable it */ -downgrade_write (&hba->clk_scaling_lock); - is_writelock = false; -ufshcd_wb_toggle (hba, scale_up); + wb_toggle = true; out_unprepare: -ufshcd_clock_scaling_unprepare (hba, is_writelock); +ufshcd_clock_scaling_unprepare (hba); + +/* Enable Write Booster if we have scaled up else disable it */ +if (wb_toggle) +ufshcd_wb_toggle (hba, scale_up); +return ret; }
Signature · 1 line
2.18.0
Bart Van Assche
reviewerQuoted 13 lines · On 7/24/22 21:30, [email protected] wrote:
From: Peter Wang <[email protected]>
There have a lockdep warning like below in current flow. kworker/u16:0: Possible unsafe locking scenario:
kworker/u16:0: CPU0 CPU1 kworker/u16:0: ---- ----kworker/u16:0:
lock(&hba->clk_scaling_lock);
kworker/u16:0:lock(&hba->dev_cmd.lock);
kworker/u16:0:lock(&hba->clk_scaling_lock);
kworker/u16:0:lock(&hba->dev_cmd.lock);
kworker/u16:0:
Quoted 7 lines
Before this patch
clk_scaling_lockwas held in reader mode during theufshcd_wb_toggle()call. With this patch appliedclk_scaling_lockis not held whileufshcd_wb_toggle()is called.This is safe because
ufshcd_wb_togglewill heldclk_scaling_lockin reader mode "again" in flowufshcd_wb_toggle->__ufshcd_wb_toggle->ufshcd_query_flag_retry->ufshcd_query_flag->ufshcd_exec_dev_cmd->down_read(&hba->clk_scaling_lock);
The protect should enough and make sure clock is not change while send command.
Since this is a bug fix, please add a Fixes: tag.
drivers/ufs/core/ufshcd.c static int ufshcd_devfreq_scale(struct ufs_hba *hba, bool scale_up) · line 1311
Quoted 10 lines
out_unprepare:drivers/ufs/core/ufshcd.c +6
-1-ufshcd_clock_scaling_unprepare (hba, is_writelock); +ufshcd_clock_scaling_unprepare (hba); + +/* Enable Write Booster if we have scaled up else disable it */ +if (wb_toggle) +ufshcd_wb_toggle (hba, scale_up); +return ret; }
Can the above patch can have the following unwanted effect?
* ufshcd_devfreq_scale() calls ufshcd_clock_scaling_unprepare().
* Clock scaling to a lower frequency happens.
* ufshcd_wb_toggle() enables the write booster.
Shouldn't the above ufshcd_wb_toggle() call be surrounded by down_read() and up_read() calls in addition to a check whether the WriteBooster really should be enabled instead of using 'scale_up'?
Thanks,
Bart.
Hi Bart,
Quoted 17 lines · Bart Van Assche
Quoted 16 lines · On 7/24/22 21:30, [email protected] wrote:
From: Peter Wang <[email protected]>
There have a lockdep warning like below in current flow. kworker/u16:0: Possible unsafe locking scenario:
kworker/u16:0: CPU0 CPU1 kworker/u16:0: ---- ---- kworker/u16:0:
lock(&hba->clk_scaling_lock); kworker/u16:0:lock(&hba->dev_cmd.lock); kworker/u16:0:lock(&hba->clk_scaling_lock); kworker/u16:0:lock(&hba->dev_cmd.lock); kworker/u16:0:Before this patch
clk_scaling_lockwas held in reader mode during theufshcd_wb_toggle()call. With this patch appliedclk_scaling_lockis not held whileufshcd_wb_toggle()is called.
Quoted 6 lines
Quoted 4 lines
This is safe because
ufshcd_wb_togglewill heldclk_scaling_lockin reader mode "again" in flowufshcd_wb_toggle->__ufshcd_wb_toggle->ufshcd_query_flag_retry->ufshcd_query_flag->ufshcd_exec_dev_cmd->down_read(&hba->clk_scaling_lock);
The protect should enough and make sure clock is not change while send command.Since this is a bug fix, please add a Fixes: tag.
Will add Fixes: tag in next version.
Quoted 17 lines
Quoted 11 lines
out_unprepare:
-ufshcd_clock_scaling_unprepare(hba, is_writelock); +ufshcd_clock_scaling_unprepare(hba);drivers/ufs/core/ufshcd.c +5
-0+ + /* Enable Write Booster if we have scaled up else disable it */ + if (wb_toggle) + ufshcd_wb_toggle(hba, scale_up); +return ret;
}Can the above patch can have the following unwanted effect?
*ufshcd_devfreq_scale()callsufshcd_clock_scaling_unprepare().
* Clock scaling to a lower frequency happens.
*ufshcd_wb_toggle()enables the write booster.
Quoted 7 lines
Shouldn't the above
ufshcd_wb_toggle()call be surrounded bydown_read()andup_read()calls in addition to a check whether the WriteBooster really should be enabled instead of using 'scale_up'?Thanks,
Bart.
You means ufshcd_devfreq_scale may have racing in two thread, right?
Then yes, it may have this unwanted effect in this condition.
But ufshcd_wb_toggle should not hold clk_scaling_lock, or the deadlock may happen.
I will change this patch to protect ufshcd_devfreq_scale racing and ufshcd_wb_toggle in next version.
Thanks.
Peter