All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] scsi: ufs: core: Fix a deadlock between clock scaling and device commands
@ 2026-10-16 12:46 Joonhoe Kim
  2026-10-19 10:46 ` Peter Wang
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages 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] 4+ messages in thread

* Re: [PATCH] scsi: ufs: core: Fix a deadlock between clock scaling and device commands
  2026-10-16 12:46 [PATCH] scsi: ufs: core: Fix a deadlock between clock scaling and device commands Joonhoe Kim
@ 2026-10-19 10:46 ` Peter Wang
  2026-10-24  2:42 ` Martin K. Petersen
  2026-10-29  2:02 ` Martin K. Petersen (Oracle)
  2 siblings, 0 replies; 4+ messages in thread
From: Peter Wang @ 2026-10-19 10:46 UTC (permalink / raw)
  To: Joonhoe Kim, James.Bottomley, mkp
  Cc: alim.akhtar, bvanassche, beanhuo, stanleyjhu, can.guo, mani,
	linux-scsi, linux-arm-msm, linux-kernel, stable

On Fri, 2026-10-16 at 21:46 +0900, Joonhoe Kim wrote
> 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>
> ---

Reviewed-by: Peter Wang <peter.wang@mediatek.com>


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] scsi: ufs: core: Fix a deadlock between clock scaling and device commands
  2026-10-16 12:46 [PATCH] scsi: ufs: core: Fix a deadlock between clock scaling and device commands Joonhoe Kim
  2026-10-19 10:46 ` Peter Wang
@ 2026-10-24  2:42 ` Martin K. Petersen
  2026-10-29  2:02 ` Martin K. Petersen (Oracle)
  2 siblings, 0 replies; 4+ messages in thread
From: Martin K. Petersen @ 2026-10-24  2:42 UTC (permalink / raw)
  To: Joonhoe Kim
  Cc: James.Bottomley, mkp, alim.akhtar, bvanassche, beanhuo,
	stanleyjhu, peter.wang, can.guo, mani, linux-scsi, linux-arm-msm,
	linux-kernel, stable


Joonhoe,

> 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.

Applied to 7.4/scsi-staging, thanks!

-- 
Martin K. Petersen

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] scsi: ufs: core: Fix a deadlock between clock scaling and device commands
  2026-10-16 12:46 [PATCH] scsi: ufs: core: Fix a deadlock between clock scaling and device commands Joonhoe Kim
  2026-10-19 10:46 ` Peter Wang
  2026-10-24  2:42 ` Martin K. Petersen
@ 2026-10-29  2:02 ` Martin K. Petersen (Oracle)
  2 siblings, 0 replies; 4+ messages in thread
From: Martin K. Petersen (Oracle) @ 2026-10-29  2:02 UTC (permalink / raw)
  To: James.Bottomley, Joonhoe Kim
  Cc: Martin K . Petersen, alim.akhtar, bvanassche, beanhuo, stanleyjhu,
	peter.wang, can.guo, mani, linux-scsi, linux-arm-msm,
	linux-kernel, stable

On Fri, 16 Oct 2026 21:46:08 +0900, Joonhoe Kim wrote:

> 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.
> 
> [...]

Applied to 7.4/scsi-queue, thanks!

[1/1] scsi: ufs: core: Fix a deadlock between clock scaling and device commands
      https://git.kernel.org/mkp/scsi/c/2327df6d2a29

-- 
Martin K. Petersen

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-10-29  2:03 UTC | newest]

Thread overview: 4+ messages (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
2026-10-19 10:46 ` Peter Wang
2026-10-24  2:42 ` Martin K. Petersen
2026-10-29  2:02 ` Martin K. Petersen (Oracle)

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.