Page MenuHomeFreeBSD

D61116.1793944221.diff
No OneTemporary

Authored By
Unknown
Size
3 KB
Referenced Files
None
Subscribers
None

D61116.1793944221.diff

diff --git a/sys/dev/ufshci/ufshci_private.h b/sys/dev/ufshci/ufshci_private.h
--- a/sys/dev/ufshci/ufshci_private.h
+++ b/sys/dev/ufshci/ufshci_private.h
@@ -513,6 +513,7 @@
void ufshci_utr_req_queue_disable(struct ufshci_controller *ctrlr);
int ufshci_utr_req_queue_enable(struct ufshci_controller *ctrlr);
void ufshci_req_queue_stop_watchdog(struct ufshci_req_queue *req_queue);
+void ufshci_req_queue_complete_aborted_hwq(struct ufshci_hw_queue *hwq);
void ufshci_req_queue_fail(struct ufshci_controller *ctrlr,
struct ufshci_req_queue *req_queue);
int ufshci_req_queue_submit_request(struct ufshci_req_queue *req_queue,
diff --git a/sys/dev/ufshci/ufshci_req_queue.c b/sys/dev/ufshci/ufshci_req_queue.c
--- a/sys/dev/ufshci/ufshci_req_queue.c
+++ b/sys/dev/ufshci/ufshci_req_queue.c
@@ -220,6 +220,35 @@
ufshci_req_queue_complete_tracker(tr);
}
+/*
+ * Complete every tracker the reset claimed. The claim keeps the
+ * completion scan away, so no tracker completes twice.
+ */
+void
+ufshci_req_queue_complete_aborted_hwq(struct ufshci_hw_queue *hwq)
+{
+ struct ufshci_tracker *tr;
+ uint32_t i;
+
+ mtx_lock(&hwq->qlock);
+
+ for (i = 0; i < hwq->num_trackers; i++) {
+ tr = hwq->act_tr[i];
+
+ if (tr->slot_state != UFSHCI_SLOT_STATE_NEED_ERROR_HANDLING)
+ continue;
+
+ tr->slot_state = UFSHCI_SLOT_STATE_COMPLETING;
+ 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);
+}
+
void
ufshci_req_queue_fail(struct ufshci_controller *ctrlr,
struct ufshci_req_queue *req_queue)
@@ -240,9 +269,12 @@
* 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.
+ * alone. A reset that failed before it enabled the queue
+ * again leaves its claimed slots behind, and nothing
+ * else completes those.
*/
- if (tr->slot_state != UFSHCI_SLOT_STATE_SCHEDULED)
+ if (tr->slot_state != UFSHCI_SLOT_STATE_SCHEDULED &&
+ tr->slot_state != UFSHCI_SLOT_STATE_NEED_ERROR_HANDLING)
continue;
/*
diff --git a/sys/dev/ufshci/ufshci_req_sdb.c b/sys/dev/ufshci/ufshci_req_sdb.c
--- a/sys/dev/ufshci/ufshci_req_sdb.c
+++ b/sys/dev/ufshci/ufshci_req_sdb.c
@@ -382,6 +382,20 @@
hwq->recovery_state = RECOVERY_WAITING;
TAILQ_FOREACH_SAFE(tr, &hwq->outstanding_tr, tailq, tr_temp) {
tr->deadline = SBT_MAX;
+
+ /*
+ * A failed controller never enables the queue again, so
+ * the failure path owns the requests.
+ */
+ if (ctrlr->is_failed)
+ continue;
+
+ /*
+ * The reset wipes the request list, so nothing completes
+ * an unclaimed slot.
+ */
+ if (tr->slot_state == UFSHCI_SLOT_STATE_SCHEDULED)
+ tr->slot_state = UFSHCI_SLOT_STATE_NEED_ERROR_HANDLING;
}
mtx_unlock(&hwq->qlock);
@@ -485,6 +499,11 @@
out:
mtx_unlock(&hwq->qlock);
mtx_unlock(&hwq->recovery_lock);
+
+ /* The queue is back, so an aborted request can retry right away. */
+ if (error == 0)
+ ufshci_req_queue_complete_aborted_hwq(hwq);
+
return (error);
}

File Metadata

Mime Type
text/plain
Expires
Fri, Nov 6, 5:50 AM (2 h, 13 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
41360525
Default Alt Text
D61116.1793944221.diff (3 KB)

Event Timeline