* [PATCH] scsi: ufs: core: Fix a deadlock between clock scaling and device commands
@ 2026-10-16 12:46 Joonhoe Kim
0 siblings, 0 replies; only message in thread
From: Joonhoe Kim @ 2026-10-16 12:46 UTC (permalink / raw)
To: James.Bottomley, mkp
Cc: alim.akhtar, bvanassche, beanhuo, stanleyjhu, peter.wang, can.guo,
mani, linux-scsi, linux-arm-msm, linux-kernel, stable
Since commit 08b12cda6c44 ("scsi: ufs: core: Switch to
scsi_get_internal_cmd()"), device management commands go through
blk_execute_rq() on the pseudo SCSI device, which shares the tagset
with the logical units, while ufshcd_dev_man_lock() holds
clk_scaling_lock for reading.
ufshcd_clock_scaling_prepare() and ufshcd_pause_command_processing()
quiesce the tagset before taking clk_scaling_lock for writing. A device
management command holding the lock for reading at that point is never
dispatched and never times out, so the writer waits forever with all
logical units quiesced. On a Lenovo Legion Tab Y700 Gen 5 this ended in
a hung task panic.
Take clk_scaling_lock before quiescing the tagset, and in
ufshcd_clock_scaling_prepare() also wb_mutex, which is always taken
before clk_scaling_lock. Release them in the reverse order. Commit
b52d695d0620 ("scsi: ufs: core: Keep internal commands dispatchable
during error handling") fixed the same problem in the error handler.
Fixes: 08b12cda6c44 ("scsi: ufs: core: Switch to scsi_get_internal_cmd()")
Fixes: dc5dcac53278 ("scsi: ufs: core: Add helpers to pause and resume command processing")
Cc: stable@vger.kernel.org
Signed-off-by: Joonhoe Kim <26rote@gmail.com>
---
Reproduced on v7.3-rc4 with out-of-tree board support, using short fio
write bursts and readers of the exception_event_status attribute while
devfreq scales: a deadlock within 10 s without this patch, two clean
600 s runs with it. The pause path was only checked by reading the
code, and the reversed release order only by building it. Sashiko
flagged this lock order in [1] and [2].
[1] https://lore.kernel.org/all/20260723130641.92FD31F000E9@smtp.kernel.org/
[2] https://lore.kernel.org/all/20260813222950.8C1581F00A3E@smtp.kernel.org/
drivers/ufs/core/ufshcd.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
index cc75384c6502..87f78ffc8cbd 100644
--- a/drivers/ufs/core/ufshcd.c
+++ b/drivers/ufs/core/ufshcd.c
@@ -1360,13 +1360,13 @@ int ufshcd_pause_command_processing(struct ufs_hba *hba, u64 timeout_us)
int ret = 0;
mutex_lock(&hba->host->scan_mutex);
- blk_mq_quiesce_tagset(&hba->host->tag_set);
down_write(&hba->clk_scaling_lock);
+ blk_mq_quiesce_tagset(&hba->host->tag_set);
if (ufshcd_wait_for_pending_cmds(hba, timeout_us)) {
ret = -EBUSY;
- up_write(&hba->clk_scaling_lock);
blk_mq_unquiesce_tagset(&hba->host->tag_set);
+ up_write(&hba->clk_scaling_lock);
mutex_unlock(&hba->host->scan_mutex);
}
@@ -1383,8 +1383,8 @@ void ufshcd_resume_command_processing(struct ufs_hba *hba)
__releases(&hba->clk_scaling_lock)
__releases(&hba->host->scan_mutex)
{
- up_write(&hba->clk_scaling_lock);
blk_mq_unquiesce_tagset(&hba->host->tag_set);
+ up_write(&hba->clk_scaling_lock);
mutex_unlock(&hba->host->scan_mutex);
}
@@ -1461,16 +1461,16 @@ static int ufshcd_clock_scaling_prepare(struct ufs_hba *hba, u64 timeout_us)
* clock scaling is in progress
*/
mutex_lock(&hba->host->scan_mutex);
- blk_mq_quiesce_tagset(&hba->host->tag_set);
mutex_lock(&hba->wb_mutex);
down_write(&hba->clk_scaling_lock);
+ blk_mq_quiesce_tagset(&hba->host->tag_set);
if (!hba->clk_scaling.is_allowed ||
ufshcd_wait_for_pending_cmds(hba, timeout_us)) {
ret = -EBUSY;
+ blk_mq_unquiesce_tagset(&hba->host->tag_set);
up_write(&hba->clk_scaling_lock);
mutex_unlock(&hba->wb_mutex);
- blk_mq_unquiesce_tagset(&hba->host->tag_set);
mutex_unlock(&hba->host->scan_mutex);
goto out;
}
@@ -1487,9 +1487,9 @@ static void ufshcd_clock_scaling_unprepare(struct ufs_hba *hba, int err)
__releases(&hba->wb_mutex)
__releases(&hba->host->scan_mutex)
{
+ blk_mq_unquiesce_tagset(&hba->host->tag_set);
up_write(&hba->clk_scaling_lock);
mutex_unlock(&hba->wb_mutex);
- blk_mq_unquiesce_tagset(&hba->host->tag_set);
mutex_unlock(&hba->host->scan_mutex);
/* Enable Write Booster if current gear requires it else disable it */
--
2.43.0
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-10-16 12:46 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-16 12:46 [PATCH] scsi: ufs: core: Fix a deadlock between clock scaling and device commands Joonhoe Kim
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.