git: c4386988baa2 - main - ufshci: fix bug in ufshci_req_sdb_enable
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 25 Mar 2026 04:46:54 UTC
The branch main has been updated by jaeyoon:
URL: https://cgit.FreeBSD.org/src/commit/?id=c4386988baa2ecdcb482c8ccace183dc643d097c
commit c4386988baa2ecdcb482c8ccace183dc643d097c
Author: Jaeyoon Choi <jaeyoon@FreeBSD.org>
AuthorDate: 2026-03-24 05:12:14 +0000
Commit: Jaeyoon Choi <jaeyoon@FreeBSD.org>
CommitDate: 2026-03-24 16:45:27 +0000
ufshci: fix bug in ufshci_req_sdb_enable
When enabling the request queue, safely reset the list base address.
This was added due to a quirk in the Qualcomm UFS controller during
the process of activating it.
Sponsored by: Samsung Electronics
Reviewed by: imp (mentor)
Differential Revision: https://reviews.freebsd.org/D55984
---
sys/dev/ufshci/ufshci_req_sdb.c | 40 ++++++++++++++++++++++++++++++++++++----
1 file changed, 36 insertions(+), 4 deletions(-)
diff --git a/sys/dev/ufshci/ufshci_req_sdb.c b/sys/dev/ufshci/ufshci_req_sdb.c
index ca47aa159c5b..54542f48b32c 100644
--- a/sys/dev/ufshci/ufshci_req_sdb.c
+++ b/sys/dev/ufshci/ufshci_req_sdb.c
@@ -374,34 +374,63 @@ ufshci_req_sdb_enable(struct ufshci_controller *ctrlr,
struct ufshci_req_queue *req_queue)
{
struct ufshci_hw_queue *hwq = &req_queue->hwq[UFSHCI_SDB_Q];
+ int error = 0;
+
+ mtx_lock(&hwq->recovery_lock);
+ mtx_lock(&hwq->qlock);
if (req_queue->is_task_mgmt) {
uint32_t hcs, utmrldbr, utmrlrsr;
+ uint32_t utmrlba, utmrlbau;
+
+ /*
+ * Some controllers require re-enabling. When a controller is
+ * re-enabled, the utmrlba registers are initialized, and these
+ * must be reconfigured upon re-enabling.
+ */
+ utmrlba = hwq->req_queue_addr & 0xffffffff;
+ utmrlbau = hwq->req_queue_addr >> 32;
+ ufshci_mmio_write_4(ctrlr, utmrlba, utmrlba);
+ ufshci_mmio_write_4(ctrlr, utmrlbau, utmrlbau);
hcs = ufshci_mmio_read_4(ctrlr, hcs);
if (!(hcs & UFSHCIM(UFSHCI_HCS_REG_UTMRLRDY))) {
ufshci_printf(ctrlr,
"UTP task management request list is not ready\n");
- return (ENXIO);
+ error = ENXIO;
+ goto out;
}
utmrldbr = ufshci_mmio_read_4(ctrlr, utmrldbr);
if (utmrldbr != 0) {
ufshci_printf(ctrlr,
"UTP task management request list door bell is not ready\n");
- return (ENXIO);
+ error = ENXIO;
+ goto out;
}
utmrlrsr = UFSHCIM(UFSHCI_UTMRLRSR_REG_UTMRLRSR);
ufshci_mmio_write_4(ctrlr, utmrlrsr, utmrlrsr);
} else {
uint32_t hcs, utrldbr, utrlcnr, utrlrsr;
+ uint32_t utrlba, utrlbau;
+
+ /*
+ * Some controllers require re-enabling. When a controller is
+ * re-enabled, the utrlba registers are initialized, and these
+ * must be reconfigured upon re-enabling.
+ */
+ utrlba = hwq->req_queue_addr & 0xffffffff;
+ utrlbau = hwq->req_queue_addr >> 32;
+ ufshci_mmio_write_4(ctrlr, utrlba, utrlba);
+ ufshci_mmio_write_4(ctrlr, utrlbau, utrlbau);
hcs = ufshci_mmio_read_4(ctrlr, hcs);
if (!(hcs & UFSHCIM(UFSHCI_HCS_REG_UTRLRDY))) {
ufshci_printf(ctrlr,
"UTP transfer request list is not ready\n");
- return (ENXIO);
+ error = ENXIO;
+ goto out;
}
utrldbr = ufshci_mmio_read_4(ctrlr, utrldbr);
@@ -434,7 +463,10 @@ ufshci_req_sdb_enable(struct ufshci_controller *ctrlr,
hwq->recovery_state = RECOVERY_NONE;
- return (0);
+out:
+ mtx_unlock(&hwq->qlock);
+ mtx_unlock(&hwq->recovery_lock);
+ return (error);
}
int