The branch main has been updated by jaeyoon:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=c686e7d3b0d315c358be81b4a1151711213d998d

commit c686e7d3b0d315c358be81b4a1151711213d998d
Author:     Jaeyoon Choi <[email protected]>
AuthorDate: 2026-08-10 01:49:31 +0000
Commit:     Jaeyoon Choi <[email protected]>
CommitDate: 2026-08-10 02:28:53 +0000

    ufshci: check completions under the queue lock
    
    The completion scan held only the recovery lock. The submit path sets
    a slot to SCHEDULED and then rings the doorbell, both under the queue
    lock. A scan running between those two steps saw a SCHEDULED slot with
    a clear doorbell and completed a command the device had not started.
    The command failed with OCS 0xf, and a reused slot could return wrong
    read data.
    
    Check the slot state and the doorbell under the queue lock. The submit
    path holds it across both steps, so a half-submitted slot can no
    longer be seen. Found with fio randrw verify on QEMU.
    
    Sponsored by:           Samsung Electronics
    Reviewed by:            imp (mentor)
    Differential Revision:  https://reviews.freebsd.org/D58668
---
 sys/dev/ufshci/ufshci_req_sdb.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/sys/dev/ufshci/ufshci_req_sdb.c b/sys/dev/ufshci/ufshci_req_sdb.c
index 9f3a2a866ae0..80c4e53230e3 100644
--- a/sys/dev/ufshci/ufshci_req_sdb.c
+++ b/sys/dev/ufshci/ufshci_req_sdb.c
@@ -584,16 +584,23 @@ ufshci_req_sdb_process_cpl(struct ufshci_req_queue 
*req_queue)
            BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
 
        for (slot = 0; slot < req_queue->num_entries; slot++) {
+               bool completed;
+
                tr = hwq->act_tr[slot];
 
                KASSERT(tr, ("there is no tracker assigned to the slot"));
                /*
                 * When the response is delivered from the device, the doorbell
-                * is cleared.
+                * is cleared. Check it under qlock so that a slot whose
+                * doorbell write is still in flight in the submit path is not
+                * mistaken for a completed one.
                 */
-               if (tr->slot_state == UFSHCI_SLOT_STATE_SCHEDULED &&
+               mtx_lock(&hwq->qlock);
+               completed = tr->slot_state == UFSHCI_SLOT_STATE_SCHEDULED &&
                    req_queue->qops.is_doorbell_cleared(req_queue->ctrlr,
-                       slot)) {
+                       slot);
+               mtx_unlock(&hwq->qlock);
+               if (completed) {
                        ufshci_req_queue_complete_tracker(tr);
                        done = true;
                }

Reply via email to