From nobody Tue Nov 03 04:33:43 2026 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4jJbLJ030nz6xsJZ for ; Tue, 03 Nov 2026 04:33:44 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id 4jJbLH3pM3z4fXX for ; Tue, 03 Nov 2026 04:33:43 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1793680423; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=Kzi/guC4/fnZnkkfDo+ANqqSOAQPw9xCgr7jr4Au5GU=; b=X1a+0fTV28q4M2tRg+6TkBucaoc1bJF4liZRfD/3JQI3T70UKqdmEmfs6Q95+mCzzOmPS5 13MoNIY+6/uC26UmXP75jTkq8HC5JEDnbF9vDhZiU8vsn2KllI/ohnYs97U8yV/y6DCWe0 +/4YASiuce6Dho2D369rBNimV8Jp0TfRcGiG3YbfCUPNsVNcwqlH/DCUDL7cilyku+FfAF mxhVNi6yOFnpnNiYuMME6wm7+iKuNGhtM4aUMWBrk/Do+NWoRgYK0x6vZp7KxkgOTf4z6Q afwCbsGOSNHOr2kYkSlGwExLaE4gNPLcS6oFL/ENBNovgYr0SBMFXRfapGhiDw== ARC-Seal: i=1; a=rsa-sha256; d=freebsd.org; s=dkim; cv=none; t=1793680423; b=JBKg5O4c0H9d6fFNDcG9np8RJ9eN+05i5YEaYRPJu1o3sOmO0sBFDaWymrRbTQ8OigI39P lxIe2KWt5ZgfR3rydtFz+UbDGEUx/ZIOkucTWNZQH3ilRvWoH+Qs9VVjwelr1d+SHT5pgr h+YlLneaO+aiG9q7zuk1mSU0Jk4cb5c2novZC/41ruyPNbYOWHOtn8OIrtXC8kdEmFYa4Q C5bfLL6qw+qVHWwoikpjKy5JYi3rlDOYbC2QMiUZigs71fGLnZrgkTuiJsPiYjPTPdn6e9 KwqfFObiPEpyWm1vtEB4fnTbpsSowIcxUfJueALuxqjd9wLAZLMOGH9k1OpzDQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1793680423; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=Kzi/guC4/fnZnkkfDo+ANqqSOAQPw9xCgr7jr4Au5GU=; b=urWPfDo6Fufc4rWw1lXeUMyDe0EiPdAkk+MecbQSLSI86qVJZUKtfFmp0c/zSD9Gm0xMrT +PKAgFKXtHLf3S6oTh3VZmJjRhcu6EEDXuYJzH6eumfR/Fgzwk+c+qFNudIj3ofrLMDfFh oRqF7g7zfTknVgF0gZBl9IBWxOZ+zOfsRyXNUy0vmaNsKFb+mspJe4rTtAXKoxhKjOug6r bB7oNxHy6yEkXzEq7Qi4gpzjWCysTOG0FZCjlsJKkIj87tQ59cUNw6XR51WTj399CYjIS3 fnhg+IZB/rYB1iuYv25UsNhhYU44PVSwUsIk0EqKIILrShLTwWwdF0Tre6wWOQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4jJbLH2v15z1GXY for ; Tue, 03 Nov 2026 04:33:43 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 1f3c7 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Tue, 03 Nov 2026 04:33:43 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Jaeyoon Choi Subject: git: 088c6fc1f9bf - main - ufshci: claim a slot before completing it List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org List-Id: Commit messages for all branches of the src repository List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: jaeyoon X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 088c6fc1f9bf938fcad465fe7899d64cf4453b69 Auto-Submitted: auto-generated Date: Tue, 03 Nov 2026 04:33:43 +0000 Message-Id: <6ae96427.1f3c7.5fcbb415@gitrepo.freebsd.org> The branch main has been updated by jaeyoon: URL: https://cgit.FreeBSD.org/src/commit/?id=088c6fc1f9bf938fcad465fe7899d64cf4453b69 commit 088c6fc1f9bf938fcad465fe7899d64cf4453b69 Author: Jaeyoon Choi AuthorDate: 2026-11-03 04:16:36 +0000 Commit: Jaeyoon Choi CommitDate: 2026-11-03 04:29:42 +0000 ufshci: claim a slot before completing it A request is completed with the queue lock dropped, because the completion callback may submit the next request and take that lock again. The completion scan checked a slot under the lock, dropped the lock, and only then completed the request, with the slot still marked scheduled. The failure path and the abort completion look for such slots under the same lock, so one of them could pick the same slot in that window. The request was then completed twice, freed twice, and its CCB went back to CAM twice. After a reset every in-flight slot reads as done at once, so the window was easy to hit. No existing state could mark that window. FREE would hand the slot to a new request while the old completion still reads it, RESERVED means a submit in progress, and NEED_ERROR_HANDLING is about to mean a request that a reset has claimed but nobody has completed yet. Add a completing state. Every path that completes a slot sets it under the lock before dropping the lock, and every path skips a slot in that state. The abort completion now takes only a slot that is still scheduled, where it used to take anything that was not free. Reviewed by: imp Sponsored by: Samsung Electronics Differential Revision: https://reviews.freebsd.org/D61113 --- sys/dev/ufshci/ufshci_private.h | 1 + sys/dev/ufshci/ufshci_req_queue.c | 17 +++++++++++------ sys/dev/ufshci/ufshci_req_sdb.c | 8 +++++++- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/sys/dev/ufshci/ufshci_private.h b/sys/dev/ufshci/ufshci_private.h index 872518ee30b3..32818ca0392e 100644 --- a/sys/dev/ufshci/ufshci_private.h +++ b/sys/dev/ufshci/ufshci_private.h @@ -82,6 +82,7 @@ enum ufshci_slot_state { UFSHCI_SLOT_STATE_SCHEDULED = 0x2, UFSHCI_SLOT_STATE_TIMEOUT = 0x3, UFSHCI_SLOT_STATE_NEED_ERROR_HANDLING = 0x4, + UFSHCI_SLOT_STATE_COMPLETING = 0x5, }; struct ufshci_tracker { diff --git a/sys/dev/ufshci/ufshci_req_queue.c b/sys/dev/ufshci/ufshci_req_queue.c index ee73a0ca5462..96de50abd153 100644 --- a/sys/dev/ufshci/ufshci_req_queue.c +++ b/sys/dev/ufshci/ufshci_req_queue.c @@ -209,7 +209,7 @@ ufshci_req_queue_fail(struct ufshci_controller *ctrlr, mtx_lock(&hwq->qlock); - for (i = 0; i < req_queue->num_trackers; i++) { + for (i = 0; i < hwq->num_trackers; i++) { tr = hwq->act_tr[i]; /* @@ -222,11 +222,11 @@ ufshci_req_queue_fail(struct ufshci_controller *ctrlr, 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. + * Claim the tracker under the lock. Every other walker + * skips a slot in this state, so the tracker cannot + * complete twice while the lock is dropped. */ - tr->slot_state = UFSHCI_SLOT_STATE_NEED_ERROR_HANDLING; + tr->slot_state = UFSHCI_SLOT_STATE_COMPLETING; mtx_unlock(&hwq->qlock); ufshci_req_queue_manual_complete_tracker(tr, UFSHCI_DESC_ABORTED, @@ -491,7 +491,12 @@ ufshci_abort_complete(void *arg, const struct ufshci_completion *status, * complete the command manually. */ mtx_lock(&tr->hwq->qlock); - if (tr->slot_state != UFSHCI_SLOT_STATE_FREE) { + /* + * Only a scheduled slot still waits on the controller. Claim it + * before the unlock, so no other path completes it as well. + */ + if (tr->slot_state == UFSHCI_SLOT_STATE_SCHEDULED) { + tr->slot_state = UFSHCI_SLOT_STATE_COMPLETING; mtx_unlock(&tr->hwq->qlock); /* * An I/O has timed out, and the controller was unable to abort diff --git a/sys/dev/ufshci/ufshci_req_sdb.c b/sys/dev/ufshci/ufshci_req_sdb.c index 2404354bfade..6e756c523830 100644 --- a/sys/dev/ufshci/ufshci_req_sdb.c +++ b/sys/dev/ufshci/ufshci_req_sdb.c @@ -595,7 +595,7 @@ ufshci_req_sdb_process_cpl(struct ufshci_req_queue *req_queue) bus_dmamap_sync(hwq->dma_tag_queue, hwq->queuemem_map, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); - for (slot = 0; slot < req_queue->num_entries; slot++) { + for (slot = 0; slot < hwq->num_trackers; slot++) { bool completed; tr = hwq->act_tr[slot]; @@ -609,6 +609,12 @@ ufshci_req_sdb_process_cpl(struct ufshci_req_queue *req_queue) mtx_lock(&hwq->qlock); completed = tr->slot_state == UFSHCI_SLOT_STATE_SCHEDULED && req_queue->qops.is_completed(req_queue->ctrlr, slot); + /* + * Claim the slot while the lock is held, so no other path + * completes this request as well. + */ + if (completed) + tr->slot_state = UFSHCI_SLOT_STATE_COMPLETING; mtx_unlock(&hwq->qlock); if (completed) { ufshci_req_queue_complete_tracker(tr);