The branch main has been updated by jaeyoon: URL: https://cgit.FreeBSD.org/src/commit/?id=7682b8f37669671844fedd94a382ec0c459b9b2c
commit 7682b8f37669671844fedd94a382ec0c459b9b2c Author: Jaeyoon Choi <[email protected]> AuthorDate: 2026-08-27 05:00:41 +0000 Commit: Jaeyoon Choi <[email protected]> CommitDate: 2026-08-27 05:08:37 +0000 ufshci: claim trackers before failing them ufshci_req_queue_fail() drops the queue lock to complete each tracker. In that window the completion path could complete the same tracker again. Claim the slot before dropping the lock, so the completion scan skips it. Reserved slots are left to their submit thread, which completes them itself. The manual request completion helper lost its only caller, so drop it. Reviewed by: imp (mentor) Sponsored by: Samsung Electronics Differential Revision: https://reviews.freebsd.org/D58945 --- sys/dev/ufshci/ufshci_req_queue.c | 60 +++++++++++++-------------------------- 1 file changed, 20 insertions(+), 40 deletions(-) diff --git a/sys/dev/ufshci/ufshci_req_queue.c b/sys/dev/ufshci/ufshci_req_queue.c index db96d13fad24..97eccd082176 100644 --- a/sys/dev/ufshci/ufshci_req_queue.c +++ b/sys/dev/ufshci/ufshci_req_queue.c @@ -182,29 +182,6 @@ ufshci_req_queue_manual_complete_tracker(struct ufshci_tracker *tr, uint8_t ocs, ufshci_req_queue_complete_tracker(tr); } -static void -ufshci_req_queue_manual_complete_request(struct ufshci_req_queue *req_queue, - struct ufshci_request *req, uint8_t ocs, uint8_t rc) -{ - struct ufshci_completion cpl; - bool error; - - memset(&cpl, 0, sizeof(cpl)); - cpl.response_upiu.header.response = rc; - error = ufshci_req_queue_response_is_error(req_queue, ocs, - &cpl.response_upiu); - - if (error) { - ufshci_printf(req_queue->ctrlr, - "Manual complete request error:0x%x", error); - } - - if (req->cb_fn) - req->cb_fn(req->cb_arg, &cpl, error); - - ufshci_free_request(req); -} - void ufshci_req_queue_fail(struct ufshci_controller *ctrlr, struct ufshci_req_queue *req_queue) @@ -221,23 +198,26 @@ ufshci_req_queue_fail(struct ufshci_controller *ctrlr, for (i = 0; i < req_queue->num_trackers; i++) { tr = hwq->act_tr[i]; - if (tr->slot_state == UFSHCI_SLOT_STATE_RESERVED) { - mtx_unlock(&hwq->qlock); - ufshci_req_queue_manual_complete_request(req_queue, - tr->req, UFSHCI_DESC_ABORTED, - UFSHCI_RESPONSE_CODE_GENERAL_FAILURE); - mtx_lock(&hwq->qlock); - } else if (tr->slot_state == UFSHCI_SLOT_STATE_SCHEDULED) { - /* - * Do not remove the tracker. The abort_tracker path - * will do that for us. - */ - mtx_unlock(&hwq->qlock); - ufshci_req_queue_manual_complete_tracker(tr, - UFSHCI_DESC_ABORTED, - UFSHCI_RESPONSE_CODE_GENERAL_FAILURE); - mtx_lock(&hwq->qlock); - } + /* + * A slot in UFSHCI_SLOT_STATE_RESERVED is visible here + * only while its submit thread is failing a PRDT setup. + * That thread completes the request, so leave the slot + * alone. + */ + if (tr->slot_state != UFSHCI_SLOT_STATE_SCHEDULED) + continue; + + /* + * Claim the tracker under the lock. The completion + * scan only completes SCHEDULED slots, so it will + * skip this one while the lock is dropped. + */ + tr->slot_state = UFSHCI_SLOT_STATE_NEED_ERROR_HANDLING; + mtx_unlock(&hwq->qlock); + ufshci_req_queue_manual_complete_tracker(tr, + UFSHCI_DESC_ABORTED, + UFSHCI_RESPONSE_CODE_GENERAL_FAILURE); + mtx_lock(&hwq->qlock); } mtx_unlock(&hwq->qlock);
