Patch "scsi: ufs: core: Quiesce request queues before checking pending cmds" has been added to the 6.9-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    scsi: ufs: core: Quiesce request queues before checking pending cmds

to the 6.9-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     scsi-ufs-core-quiesce-request-queues-before-checking.patch
and it can be found in the queue-6.9 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 0f6201e6126d3aaf7aad01ed0f98d8c766f6ec07
Author: Ziqi Chen <quic_ziqichen@xxxxxxxxxxx>
Date:   Fri Jun 7 18:06:23 2024 +0800

    scsi: ufs: core: Quiesce request queues before checking pending cmds
    
    [ Upstream commit 77691af484e28af7a692e511b9ed5ca63012ec6e ]
    
    In ufshcd_clock_scaling_prepare(), after SCSI layer is blocked,
    ufshcd_pending_cmds() is called to check whether there are pending
    transactions or not. And only if there are no pending transactions can we
    proceed to kickstart the clock scaling sequence.
    
    ufshcd_pending_cmds() traverses over all SCSI devices and calls
    sbitmap_weight() on their budget_map. sbitmap_weight() can be broken down
    to three steps:
    
     1. Calculate the nr outstanding bits set in the 'word' bitmap.
    
     2. Calculate the nr outstanding bits set in the 'cleared' bitmap.
    
     3. Subtract the result from step 1 by the result from step 2.
    
    This can lead to a race condition as outlined below:
    
    Assume there is one pending transaction in the request queue of one SCSI
    device, say sda, and the budget token of this request is 0, the 'word' is
    0x1 and the 'cleared' is 0x0.
    
     1. When step 1 executes, it gets the result as 1.
    
     2. Before step 2 executes, block layer tries to dispatch a new request to
        sda. Since the SCSI layer is blocked, the request cannot pass through
        SCSI but the block layer would do budget_get() and budget_put() to
        sda's budget map regardless, so the 'word' has become 0x3 and 'cleared'
        has become 0x2 (assume the new request got budget token 1).
    
     3. When step 2 executes, it gets the result as 1.
    
     4. When step 3 executes, it gets the result as 0, meaning there is no
        pending transactions, which is wrong.
    
        Thread A                        Thread B
        ufshcd_pending_cmds()           __blk_mq_sched_dispatch_requests()
        |                               |
        sbitmap_weight(word)            |
        |                               scsi_mq_get_budget()
        |                               |
        |                               scsi_mq_put_budget()
        |                               |
        sbitmap_weight(cleared)
        ...
    
    When this race condition happens, the clock scaling sequence is started
    with transactions still in flight, leading to subsequent hibernate enter
    failure, broken link, task abort and back to back error recovery.
    
    Fix this race condition by quiescing the request queues before calling
    ufshcd_pending_cmds() so that block layer won't touch the budget map when
    ufshcd_pending_cmds() is working on it. In addition, remove the SCSI layer
    blocking/unblocking to reduce redundancies and latencies.
    
    Fixes: 8d077ede48c1 ("scsi: ufs: Optimize the command queueing code")
    Co-developed-by: Can Guo <quic_cang@xxxxxxxxxxx>
    Signed-off-by: Can Guo <quic_cang@xxxxxxxxxxx>
    Signed-off-by: Ziqi Chen <quic_ziqichen@xxxxxxxxxxx>
    Link: https://lore.kernel.org/r/1717754818-39863-1-git-send-email-quic_ziqichen@xxxxxxxxxxx
    Reviewed-by: Bart Van Assche <bvanassche@xxxxxxx>
    Signed-off-by: Martin K. Petersen <martin.petersen@xxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
index 1322a9c318cff..ce1abd5d725ad 100644
--- a/drivers/ufs/core/ufshcd.c
+++ b/drivers/ufs/core/ufshcd.c
@@ -1392,7 +1392,7 @@ static int ufshcd_clock_scaling_prepare(struct ufs_hba *hba, u64 timeout_us)
 	 * make sure that there are no outstanding requests when
 	 * clock scaling is in progress
 	 */
-	ufshcd_scsi_block_requests(hba);
+	blk_mq_quiesce_tagset(&hba->host->tag_set);
 	mutex_lock(&hba->wb_mutex);
 	down_write(&hba->clk_scaling_lock);
 
@@ -1401,7 +1401,7 @@ static int ufshcd_clock_scaling_prepare(struct ufs_hba *hba, u64 timeout_us)
 		ret = -EBUSY;
 		up_write(&hba->clk_scaling_lock);
 		mutex_unlock(&hba->wb_mutex);
-		ufshcd_scsi_unblock_requests(hba);
+		blk_mq_unquiesce_tagset(&hba->host->tag_set);
 		goto out;
 	}
 
@@ -1422,7 +1422,7 @@ static void ufshcd_clock_scaling_unprepare(struct ufs_hba *hba, int err, bool sc
 
 	mutex_unlock(&hba->wb_mutex);
 
-	ufshcd_scsi_unblock_requests(hba);
+	blk_mq_unquiesce_tagset(&hba->host->tag_set);
 	ufshcd_release(hba);
 }
 




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux