git: 94e28f979a84 - stable/15 - ufshci: run the controller fail path only once
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 06 Oct 2026 07:51:27 UTC
The branch stable/15 has been updated by jaeyoon:
URL: https://cgit.FreeBSD.org/src/commit/?id=94e28f979a84251f7108c10db7efc8ccdf424b2e
commit 94e28f979a84251f7108c10db7efc8ccdf424b2e
Author: Jaeyoon Choi <jaeyoon@FreeBSD.org>
AuthorDate: 2026-08-27 04:58:21 +0000
Commit: Jaeyoon Choi <jaeyoon@FreeBSD.org>
CommitDate: 2026-10-06 06:28:04 +0000
ufshci: run the controller fail path only once
Two threads could run ufshci_ctrlr_fail() at the same time.
Each one walked the queues and completed the same trackers
again, which caused a double free and a panic.
Turn is_failed into an atomic gate, so only the first caller
walks the queues. The reset task now returns early on a failed
controller instead of re-enabling it.
Reviewed by: imp (mentor)
Sponsored by: Samsung Electronics
Differential Revision: https://reviews.freebsd.org/D58944
(cherry picked from commit 1258ae2bcb559854c966e425f4c5c48668d3cf7b)
---
sys/dev/ufshci/ufshci_ctrlr.c | 12 +++++++++++-
sys/dev/ufshci/ufshci_private.h | 2 +-
2 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/sys/dev/ufshci/ufshci_ctrlr.c b/sys/dev/ufshci/ufshci_ctrlr.c
index bb07ad5f76da..2f930d55a295 100644
--- a/sys/dev/ufshci/ufshci_ctrlr.c
+++ b/sys/dev/ufshci/ufshci_ctrlr.c
@@ -15,7 +15,13 @@
static void
ufshci_ctrlr_fail(struct ufshci_controller *ctrlr)
{
- ctrlr->is_failed = true;
+ /*
+ * The attach thread and the reset task can both fail the
+ * controller. A second queue walk would complete the same
+ * trackers again.
+ */
+ if (atomic_swap_32(&ctrlr->is_failed, 1) != 0)
+ return;
ufshci_req_queue_fail(ctrlr, &ctrlr->task_mgmt_req_queue);
ufshci_req_queue_fail(ctrlr, &ctrlr->transfer_req_queue);
@@ -312,6 +318,10 @@ ufshci_ctrlr_reset_task(void *arg, int pending)
struct ufshci_controller *ctrlr = arg;
int error;
+ /* A failed controller must not be re-enabled. */
+ if (ctrlr->is_failed)
+ return;
+
/* Release resources */
ufshci_utmr_req_queue_disable(ctrlr);
ufshci_utr_req_queue_disable(ctrlr);
diff --git a/sys/dev/ufshci/ufshci_private.h b/sys/dev/ufshci/ufshci_private.h
index c738e246e96c..7b74faf95c53 100644
--- a/sys/dev/ufshci/ufshci_private.h
+++ b/sys/dev/ufshci/ufshci_private.h
@@ -423,7 +423,7 @@ struct ufshci_controller {
uint32_t max_tx_lanes;
uint32_t max_rx_lanes;
- bool is_failed;
+ uint32_t is_failed;
};
#define ufshci_mmio_offsetof(reg) offsetof(struct ufshci_registers, reg)