xref: /freebsd/sys/dev/ufshci/ufshci_req_queue.c (revision d59c7ea2701fe7b73b32eef49a7c712ef38de5a0)
1 /*-
2  * Copyright (c) 2025, Samsung Electronics Co., Ltd.
3  * Written by Jaeyoon Choi
4  *
5  * SPDX-License-Identifier: BSD-2-Clause
6  */
7 
8 #include <sys/param.h>
9 #include <sys/bus.h>
10 #include <sys/conf.h>
11 #include <sys/domainset.h>
12 #include <sys/module.h>
13 
14 #include <cam/scsi/scsi_all.h>
15 
16 #include "sys/kassert.h"
17 #include "ufshci_private.h"
18 
19 static void ufshci_req_queue_submit_tracker(struct ufshci_req_queue *req_queue,
20     struct ufshci_tracker *tr, enum ufshci_data_direction data_direction);
21 
22 static const struct ufshci_qops sdb_utmr_qops = {
23 	.construct = ufshci_req_sdb_construct,
24 	.destroy = ufshci_req_sdb_destroy,
25 	.get_hw_queue = ufshci_req_sdb_get_hw_queue,
26 	.enable = ufshci_req_sdb_enable,
27 	.disable = ufshci_req_sdb_disable,
28 	.reserve_slot = ufshci_req_sdb_reserve_slot,
29 	.reserve_admin_slot = ufshci_req_sdb_reserve_slot,
30 	.ring_doorbell = ufshci_req_sdb_utmr_ring_doorbell,
31 	.is_doorbell_cleared = ufshci_req_sdb_utmr_is_doorbell_cleared,
32 	.clear_cpl_ntf = ufshci_req_sdb_utmr_clear_cpl_ntf,
33 	.process_cpl = ufshci_req_sdb_process_cpl,
34 	.get_inflight_io = ufshci_req_sdb_get_inflight_io,
35 };
36 
37 static const struct ufshci_qops sdb_utr_qops = {
38 	.construct = ufshci_req_sdb_construct,
39 	.destroy = ufshci_req_sdb_destroy,
40 	.get_hw_queue = ufshci_req_sdb_get_hw_queue,
41 	.enable = ufshci_req_sdb_enable,
42 	.disable = ufshci_req_sdb_disable,
43 	.reserve_slot = ufshci_req_sdb_reserve_slot,
44 	.reserve_admin_slot = ufshci_req_sdb_reserve_slot,
45 	.ring_doorbell = ufshci_req_sdb_utr_ring_doorbell,
46 	.is_doorbell_cleared = ufshci_req_sdb_utr_is_doorbell_cleared,
47 	.clear_cpl_ntf = ufshci_req_sdb_utr_clear_cpl_ntf,
48 	.process_cpl = ufshci_req_sdb_process_cpl,
49 	.get_inflight_io = ufshci_req_sdb_get_inflight_io,
50 };
51 
52 int
53 ufshci_utmr_req_queue_construct(struct ufshci_controller *ctrlr)
54 {
55 	struct ufshci_req_queue *req_queue;
56 	int error;
57 
58 	/*
59 	 * UTP Task Management Request only supports Legacy Single Doorbell
60 	 * Queue.
61 	 */
62 	req_queue = &ctrlr->task_mgmt_req_queue;
63 	req_queue->queue_mode = UFSHCI_Q_MODE_SDB;
64 	req_queue->qops = sdb_utmr_qops;
65 
66 	error = req_queue->qops.construct(ctrlr, req_queue, UFSHCI_UTRM_ENTRIES,
67 	    /*is_task_mgmt*/ true);
68 
69 	return (error);
70 }
71 
72 void
73 ufshci_utmr_req_queue_destroy(struct ufshci_controller *ctrlr)
74 {
75 	/* Attach may fail before the queue ops are set up. */
76 	if (ctrlr->task_mgmt_req_queue.qops.destroy == NULL)
77 		return;
78 
79 	ctrlr->task_mgmt_req_queue.qops.destroy(ctrlr,
80 	    &ctrlr->task_mgmt_req_queue);
81 }
82 
83 void
84 ufshci_utmr_req_queue_disable(struct ufshci_controller *ctrlr)
85 {
86 	ctrlr->task_mgmt_req_queue.qops.disable(ctrlr,
87 	    &ctrlr->task_mgmt_req_queue);
88 }
89 
90 int
91 ufshci_utmr_req_queue_enable(struct ufshci_controller *ctrlr)
92 {
93 	return (ctrlr->task_mgmt_req_queue.qops.enable(ctrlr,
94 	    &ctrlr->task_mgmt_req_queue));
95 }
96 
97 int
98 ufshci_utr_req_queue_construct(struct ufshci_controller *ctrlr)
99 {
100 	struct ufshci_req_queue *req_queue;
101 	int error;
102 
103 	/*
104 	 * Currently, it does not support MCQ mode, so it should be set to SDB
105 	 * mode by default.
106 	 * TODO: Determine queue mode by checking Capability Registers
107 	 */
108 	req_queue = &ctrlr->transfer_req_queue;
109 	req_queue->queue_mode = UFSHCI_Q_MODE_SDB;
110 	req_queue->qops = sdb_utr_qops;
111 
112 	error = req_queue->qops.construct(ctrlr, req_queue, UFSHCI_UTR_ENTRIES,
113 	    /*is_task_mgmt*/ false);
114 
115 	return (error);
116 }
117 
118 void
119 ufshci_utr_req_queue_destroy(struct ufshci_controller *ctrlr)
120 {
121 	/* Attach may fail before the queue ops are set up. */
122 	if (ctrlr->transfer_req_queue.qops.destroy == NULL)
123 		return;
124 
125 	ctrlr->transfer_req_queue.qops.destroy(ctrlr,
126 	    &ctrlr->transfer_req_queue);
127 }
128 
129 void
130 ufshci_utr_req_queue_disable(struct ufshci_controller *ctrlr)
131 {
132 	ctrlr->transfer_req_queue.qops.disable(ctrlr,
133 	    &ctrlr->transfer_req_queue);
134 }
135 
136 int
137 ufshci_utr_req_queue_enable(struct ufshci_controller *ctrlr)
138 {
139 	return (ctrlr->transfer_req_queue.qops.enable(ctrlr,
140 	    &ctrlr->transfer_req_queue));
141 }
142 
143 static bool
144 ufshci_req_queue_response_is_error(struct ufshci_req_queue *req_queue,
145     uint8_t ocs, union ufshci_reponse_upiu *response)
146 {
147 	bool is_error = false;
148 
149 	/* Check request descriptor */
150 	if (ocs != UFSHCI_DESC_SUCCESS) {
151 		ufshci_printf(req_queue->ctrlr, "Invalid OCS = 0x%x\n", ocs);
152 		is_error = true;
153 	}
154 
155 	/* Check response UPIU header */
156 	if (response->header.response != UFSHCI_RESPONSE_CODE_TARGET_SUCCESS) {
157 		ufshci_printf(req_queue->ctrlr,
158 		    "Function(0x%x) Invalid response code = 0x%x\n",
159 		    response->header.ext_iid_or_function,
160 		    response->header.response);
161 		is_error = true;
162 	}
163 
164 	return (is_error);
165 }
166 
167 static void
168 ufshci_req_queue_manual_complete_tracker(struct ufshci_tracker *tr, uint8_t ocs,
169     uint8_t rc)
170 {
171 	struct ufshci_utp_xfer_req_desc *desc;
172 	struct ufshci_upiu_header *resp_header;
173 
174 	mtx_assert(&tr->hwq->qlock, MA_NOTOWNED);
175 
176 	resp_header = (struct ufshci_upiu_header *)tr->ucd->response_upiu;
177 	resp_header->response = rc;
178 
179 	desc = &tr->hwq->utrd[tr->slot_num];
180 	desc->overall_command_status = ocs;
181 
182 	ufshci_req_queue_complete_tracker(tr);
183 }
184 
185 static void
186 ufshci_req_queue_manual_complete_request(struct ufshci_req_queue *req_queue,
187     struct ufshci_request *req, uint8_t ocs, uint8_t rc)
188 {
189 	struct ufshci_completion cpl;
190 	bool error;
191 
192 	memset(&cpl, 0, sizeof(cpl));
193 	cpl.response_upiu.header.response = rc;
194 	error = ufshci_req_queue_response_is_error(req_queue, ocs,
195 	    &cpl.response_upiu);
196 
197 	if (error) {
198 		ufshci_printf(req_queue->ctrlr,
199 		    "Manual complete request error:0x%x", error);
200 	}
201 
202 	if (req->cb_fn)
203 		req->cb_fn(req->cb_arg, &cpl, error);
204 
205 	ufshci_free_request(req);
206 }
207 
208 void
209 ufshci_req_queue_fail(struct ufshci_controller *ctrlr,
210     struct ufshci_req_queue *req_queue)
211 {
212 	struct ufshci_hw_queue *hwq = req_queue->qops.get_hw_queue(req_queue);
213 	struct ufshci_tracker *tr;
214 	int i;
215 
216 	if (!mtx_initialized(&hwq->qlock))
217 		return;
218 
219 	mtx_lock(&hwq->qlock);
220 
221 	for (i = 0; i < req_queue->num_trackers; i++) {
222 		tr = hwq->act_tr[i];
223 
224 		if (tr->slot_state == UFSHCI_SLOT_STATE_RESERVED) {
225 			mtx_unlock(&hwq->qlock);
226 			ufshci_req_queue_manual_complete_request(req_queue,
227 			    tr->req, UFSHCI_DESC_ABORTED,
228 			    UFSHCI_RESPONSE_CODE_GENERAL_FAILURE);
229 			mtx_lock(&hwq->qlock);
230 		} else if (tr->slot_state == UFSHCI_SLOT_STATE_SCHEDULED) {
231 			/*
232 			 * Do not remove the tracker. The abort_tracker path
233 			 * will do that for us.
234 			 */
235 			mtx_unlock(&hwq->qlock);
236 			ufshci_req_queue_manual_complete_tracker(tr,
237 			    UFSHCI_DESC_ABORTED,
238 			    UFSHCI_RESPONSE_CODE_GENERAL_FAILURE);
239 			mtx_lock(&hwq->qlock);
240 		}
241 	}
242 
243 	mtx_unlock(&hwq->qlock);
244 }
245 
246 void
247 ufshci_req_queue_complete_tracker(struct ufshci_tracker *tr)
248 {
249 	struct ufshci_req_queue *req_queue = tr->req_queue;
250 	struct ufshci_hw_queue *hwq = tr->hwq;
251 	struct ufshci_request *req = tr->req;
252 	struct ufshci_completion cpl;
253 	uint8_t ocs;
254 	bool retry, error, retriable;
255 
256 	mtx_assert(&hwq->qlock, MA_NOTOWNED);
257 
258 	/* Copy the response from the Request Descriptor or UTP Command
259 	 * Descriptor. */
260 	cpl.size = tr->response_size;
261 	if (req_queue->is_task_mgmt) {
262 		memcpy(&cpl.response_upiu,
263 		    (void *)hwq->utmrd[tr->slot_num].response_upiu, cpl.size);
264 
265 		ocs = hwq->utmrd[tr->slot_num].overall_command_status;
266 	} else {
267 		bus_dmamap_sync(req_queue->dma_tag_ucd, req_queue->ucdmem_map,
268 		    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
269 
270 		memcpy(&cpl.response_upiu, (void *)tr->ucd->response_upiu,
271 		    cpl.size);
272 
273 		ocs = hwq->utrd[tr->slot_num].overall_command_status;
274 	}
275 
276 	error = ufshci_req_queue_response_is_error(req_queue, ocs,
277 	    &cpl.response_upiu);
278 
279 	/* Retry for admin commands */
280 	retriable = req->is_admin;
281 	retry = error && retriable &&
282 	    req->retries < req_queue->ctrlr->retry_count;
283 	if (retry)
284 		hwq->num_retries++;
285 	if (error && req->retries >= req_queue->ctrlr->retry_count && retriable)
286 		hwq->num_failures++;
287 
288 	KASSERT(tr->req, ("there is no request assigned to the tracker\n"));
289 	KASSERT(cpl.response_upiu.header.task_tag ==
290 		req->request_upiu.header.task_tag,
291 	    ("response task_tag does not match request task_tag\n"));
292 
293 	if (!retry) {
294 		if (req->payload_valid) {
295 			bus_dmamap_sync(req_queue->dma_tag_payload,
296 			    tr->payload_dma_map,
297 			    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
298 		}
299 		/* Copy response from the command descriptor */
300 		if (req->cb_fn)
301 			req->cb_fn(req->cb_arg, &cpl, error);
302 	}
303 
304 	mtx_lock(&hwq->qlock);
305 
306 	/* Clear the UTRL Completion Notification register */
307 	req_queue->qops.clear_cpl_ntf(req_queue->ctrlr, tr);
308 
309 	if (retry) {
310 		req->retries++;
311 		ufshci_req_queue_submit_tracker(req_queue, tr,
312 		    req->data_direction);
313 	} else {
314 		if (req->payload_valid) {
315 			bus_dmamap_unload(req_queue->dma_tag_payload,
316 			    tr->payload_dma_map);
317 		}
318 
319 		/* Clear tracker */
320 		ufshci_free_request(req);
321 		tr->req = NULL;
322 		tr->slot_state = UFSHCI_SLOT_STATE_FREE;
323 
324 		TAILQ_REMOVE(&hwq->outstanding_tr, tr, tailq);
325 		TAILQ_INSERT_HEAD(&hwq->free_tr, tr, tailq);
326 	}
327 
328 	mtx_unlock(&tr->hwq->qlock);
329 }
330 
331 bool
332 ufshci_req_queue_process_completions(struct ufshci_req_queue *req_queue)
333 {
334 	struct ufshci_hw_queue *hwq;
335 	bool done;
336 
337 	hwq = req_queue->qops.get_hw_queue(req_queue);
338 
339 	mtx_lock(&hwq->recovery_lock);
340 	done = req_queue->qops.process_cpl(req_queue);
341 	mtx_unlock(&hwq->recovery_lock);
342 
343 	return (done);
344 }
345 
346 static void
347 ufshci_payload_map(void *arg, bus_dma_segment_t *seg, int nseg, int error)
348 {
349 	struct ufshci_tracker *tr = arg;
350 	struct ufshci_prdt_entry *prdt_entry;
351 	int i;
352 
353 	/*
354 	 * If the mapping operation failed, return immediately. The caller
355 	 * is responsible for detecting the error status and failing the
356 	 * tracker manually.
357 	 */
358 	if (error != 0) {
359 		ufshci_printf(tr->req_queue->ctrlr,
360 		    "Failed to map payload %d\n", error);
361 		return;
362 	}
363 
364 	prdt_entry = (struct ufshci_prdt_entry *)tr->ucd->prd_table;
365 
366 	tr->prdt_entry_cnt = nseg;
367 
368 	for (i = 0; i < nseg; i++) {
369 		prdt_entry->data_base_address = htole64(seg[i].ds_addr) &
370 		    0xffffffff;
371 		prdt_entry->data_base_address_upper = htole64(seg[i].ds_addr) >>
372 		    32;
373 		prdt_entry->data_byte_count = htole32(seg[i].ds_len - 1);
374 
375 		++prdt_entry;
376 	}
377 
378 	bus_dmamap_sync(tr->req_queue->dma_tag_payload, tr->payload_dma_map,
379 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
380 }
381 
382 static int
383 ufshci_req_queue_prepare_prdt(struct ufshci_tracker *tr)
384 {
385 	struct ufshci_request *req = tr->req;
386 	struct ufshci_utp_cmd_desc *cmd_desc = tr->ucd;
387 	int error;
388 
389 	tr->prdt_off = UFSHCI_UTP_XFER_REQ_SIZE + UFSHCI_UTP_XFER_RESP_SIZE;
390 
391 	memset(cmd_desc->prd_table, 0, sizeof(cmd_desc->prd_table));
392 
393 	/* Filling PRDT enrties with payload */
394 	error = bus_dmamap_load_mem(tr->req_queue->dma_tag_payload,
395 	    tr->payload_dma_map, &req->payload, ufshci_payload_map, tr,
396 	    BUS_DMA_NOWAIT);
397 	if (error != 0) {
398 		/*
399 		 * The dmamap operation failed, so we manually fail the
400 		 *  tracker here with UFSHCI_DESC_INVALID_PRDT_ATTRIBUTES.
401 		 *
402 		 * ufshci_req_queue_manual_complete_tracker must not be called
403 		 *  with the req_queue lock held.
404 		 */
405 		ufshci_printf(tr->req_queue->ctrlr,
406 		    "bus_dmamap_load_mem returned with error:0x%x!\n", error);
407 
408 		mtx_unlock(&tr->hwq->qlock);
409 		ufshci_req_queue_manual_complete_tracker(tr,
410 		    UFSHCI_DESC_INVALID_PRDT_ATTRIBUTES,
411 		    UFSHCI_RESPONSE_CODE_GENERAL_FAILURE);
412 		mtx_lock(&tr->hwq->qlock);
413 	}
414 
415 	return (error);
416 }
417 
418 static void
419 ufshci_req_queue_fill_utmr_descriptor(
420     struct ufshci_utp_task_mgmt_req_desc *desc, struct ufshci_request *req)
421 {
422 	memset(desc, 0, sizeof(struct ufshci_utp_task_mgmt_req_desc));
423 	desc->interrupt = true;
424 	/* Set the initial value to Invalid. */
425 	desc->overall_command_status = UFSHCI_UTMR_OCS_INVALID;
426 
427 	memcpy(desc->request_upiu, &req->request_upiu, req->request_size);
428 }
429 
430 static void
431 ufshci_req_queue_fill_utr_descriptor(struct ufshci_utp_xfer_req_desc *desc,
432     uint8_t data_direction, const uint64_t paddr, const uint16_t response_off,
433     const uint16_t response_len, const uint16_t prdt_off,
434     const uint16_t prdt_entry_cnt)
435 {
436 	uint8_t command_type;
437 	/* Value to convert bytes to dwords */
438 	const uint16_t dword_size = 4;
439 
440 	/*
441 	 * Set command type to UFS storage.
442 	 * The UFS 4.1 spec only defines 'UFS Storage' as a command type.
443 	 */
444 	command_type = UFSHCI_COMMAND_TYPE_UFS_STORAGE;
445 
446 	memset(desc, 0, sizeof(struct ufshci_utp_xfer_req_desc));
447 	desc->command_type = command_type;
448 	desc->data_direction = data_direction;
449 	desc->interrupt = true;
450 	/* Set the initial value to Invalid. */
451 	desc->overall_command_status = UFSHCI_UTR_OCS_INVALID;
452 	desc->utp_command_descriptor_base_address = (uint32_t)(paddr &
453 	    0xffffffff);
454 	desc->utp_command_descriptor_base_address_upper = (uint32_t)(paddr >>
455 	    32);
456 
457 	desc->response_upiu_offset = response_off / dword_size;
458 	desc->response_upiu_length = response_len / dword_size;
459 	desc->prdt_offset = prdt_off / dword_size;
460 	desc->prdt_length = prdt_entry_cnt;
461 }
462 
463 static void
464 ufshci_req_queue_timeout_recovery(struct ufshci_controller *ctrlr,
465     struct ufshci_hw_queue *hwq)
466 {
467 	/* TODO: Step 2. Logical unit reset */
468 	/* TODO: Step 3. Target device reset */
469 	/* TODO: Step 4. Bus reset */
470 
471 	/*
472 	 * Step 5. All previous commands were timeout.
473 	 * Recovery failed, reset the host controller.
474 	 */
475 	ufshci_printf(ctrlr,
476 	    "Recovery step 5: Resetting controller due to a timeout.\n");
477 	hwq->recovery_state = RECOVERY_WAITING;
478 
479 	ufshci_ctrlr_reset(ctrlr);
480 }
481 
482 static void
483 ufshci_abort_complete(void *arg, const struct ufshci_completion *status,
484     bool error)
485 {
486 	struct ufshci_tracker *tr = arg;
487 	uint32_t output_param1;
488 
489 	/*
490 	 * We still need to check the active tracker array, to cover race where
491 	 * I/O timed out at same time controller was completing the I/O. An
492 	 * abort request always is on the Task Management Request queue, but
493 	 * affects either an Task Management Request or an I/O (UTRL) queue, so
494 	 * take the appropriate queue lock for the original command's queue,
495 	 * since we'll need it to avoid races with the completion code and to
496 	 * complete the command manually.
497 	 */
498 	mtx_lock(&tr->hwq->qlock);
499 	if (tr->slot_state != UFSHCI_SLOT_STATE_FREE) {
500 		mtx_unlock(&tr->hwq->qlock);
501 		/*
502 		 * An I/O has timed out, and the controller was unable to abort
503 		 * it for some reason.  And we've not processed a completion for
504 		 * it yet. Construct a fake completion status, and then complete
505 		 * the I/O's tracker manually.
506 		 */
507 		ufshci_printf(tr->hwq->ctrlr,
508 		    "abort task request failed, aborting task manually\n");
509 		ufshci_req_queue_manual_complete_tracker(tr,
510 		    UFSHCI_DESC_ABORTED, UFSHCI_RESPONSE_CODE_GENERAL_FAILURE);
511 
512 		output_param1 = be32toh(
513 		    status->response_upiu.task_mgmt_response_upiu.output_param1);
514 		if (output_param1 ==
515 			UFSHCI_TASK_MGMT_SERVICE_RESPONSE_FUNCTION_COMPLETE ||
516 		    output_param1 ==
517 			UFSHCI_TASK_MGMT_SERVICE_RESPONSE_FUNCTION_SUCCEEDED) {
518 			ufshci_printf(tr->hwq->ctrlr,
519 			    "Warning: the abort task request completed \
520 			    successfully, but the original task is still incomplete.");
521 			return;
522 		}
523 
524 		/* Abort Task failed. Perform recovery steps 2-5 */
525 		ufshci_req_queue_timeout_recovery(tr->hwq->ctrlr, tr->hwq);
526 	} else {
527 		mtx_unlock(&tr->hwq->qlock);
528 	}
529 }
530 
531 static void
532 ufshci_req_queue_timeout(void *arg)
533 {
534 	struct ufshci_hw_queue *hwq = arg;
535 	struct ufshci_controller *ctrlr = hwq->ctrlr;
536 	struct ufshci_tracker *tr;
537 	sbintime_t now;
538 	bool idle = true;
539 	bool fast;
540 
541 	mtx_assert(&hwq->recovery_lock, MA_OWNED);
542 
543 	/*
544 	 * If the controller is failed, then stop polling. This ensures that any
545 	 * failure processing that races with the hwq timeout will fail safely.
546 	 */
547 	if (ctrlr->is_failed) {
548 		ufshci_printf(ctrlr,
549 		    "Failed controller, stopping watchdog timeout.\n");
550 		hwq->timer_armed = false;
551 		return;
552 	}
553 
554 	/*
555 	 * Shutdown condition: We set hwq->timer_armed to false in
556 	 * ufshci_req_sdb_destroy before calling callout_drain. When we call
557 	 * that, this routine might get called one last time. Exit w/o setting a
558 	 * timeout. None of the watchdog stuff needs to be done since we're
559 	 * destroying the hwq.
560 	 */
561 	if (!hwq->timer_armed) {
562 		ufshci_printf(ctrlr,
563 		    "Timeout fired during ufshci_utr_req_queue_destroy\n");
564 		return;
565 	}
566 
567 	switch (hwq->recovery_state) {
568 	case RECOVERY_NONE:
569 		/*
570 		 * See if there's any recovery needed. First, do a fast check to
571 		 * see if anything could have timed out. If not, then skip
572 		 * everything else.
573 		 */
574 		fast = false;
575 		mtx_lock(&hwq->qlock);
576 		now = getsbinuptime();
577 		TAILQ_FOREACH(tr, &hwq->outstanding_tr, tailq) {
578 			/*
579 			 * If the first real transaction is not in timeout, then
580 			 * we're done. Otherwise, we try recovery.
581 			 */
582 			idle = false;
583 			if (now <= tr->deadline)
584 				fast = true;
585 			break;
586 		}
587 		mtx_unlock(&hwq->qlock);
588 		if (idle || fast)
589 			break;
590 
591 		/*
592 		 * There's a stale transaction at the start of the queue whose
593 		 * deadline has passed. Poll the competions as a last-ditch
594 		 * effort in case an interrupt has been missed.
595 		 */
596 		hwq->req_queue->qops.process_cpl(hwq->req_queue);
597 
598 		/*
599 		 * Now that we've run the ISR, re-rheck to see if there's any
600 		 * timed out commands and abort them or reset the card if so.
601 		 */
602 		mtx_lock(&hwq->qlock);
603 		idle = true;
604 		TAILQ_FOREACH(tr, &hwq->outstanding_tr, tailq) {
605 			/*
606 			 * If we know this tracker hasn't timed out, we also
607 			 * know all subsequent ones haven't timed out. The tr
608 			 * queue is in submission order and all normal commands
609 			 * in a queue have the same timeout (or the timeout was
610 			 * changed by the user, but we eventually timeout then).
611 			 */
612 			idle = false;
613 			if (now <= tr->deadline)
614 				break;
615 
616 			/*
617 			 * Timeout recovery is performed in five steps. If
618 			 * recovery fails at any step, the process continues to
619 			 * the next one:
620 			 * next steps:
621 			 * Step 1. Abort task
622 			 * Step 2. Logical unit reset 	(TODO)
623 			 * Step 3. Target device reset 	(TODO)
624 			 * Step 4. Bus reset 		(TODO)
625 			 * Step 5. Host controller reset
626 			 *
627 			 * If the timeout occurred in the Task Management
628 			 * Request queue, ignore Step 1.
629 			 */
630 			if (ctrlr->enable_aborts &&
631 			    !hwq->req_queue->is_task_mgmt &&
632 			    tr->req->cb_fn != ufshci_abort_complete) {
633 				/*
634 				 * Step 1. Timeout expired, abort the task.
635 				 *
636 				 * This isn't an abort command, ask for a
637 				 * hardware abort. This goes to the Task
638 				 * Management Request queue which will reset the
639 				 * task if it times out.
640 				 */
641 				ufshci_printf(ctrlr,
642 				    "Recovery step 1: Timeout occurred. aborting the task(%d).\n",
643 				    tr->req->request_upiu.header.task_tag);
644 				if (ufshci_ctrlr_cmd_send_task_mgmt_request(ctrlr,
645 					ufshci_abort_complete, tr,
646 					UFSHCI_TASK_MGMT_FUNCTION_ABORT_TASK,
647 					tr->req->request_upiu.header.lun,
648 					tr->req->request_upiu.header.task_tag,
649 					0) != 0) {
650 					ufshci_req_queue_timeout_recovery(ctrlr,
651 					    hwq);
652 					idle = false;
653 					break;
654 				}
655 			} else {
656 				/* Recovery Step 2-5 */
657 				ufshci_req_queue_timeout_recovery(ctrlr, hwq);
658 				idle = false;
659 				break;
660 			}
661 		}
662 		mtx_unlock(&hwq->qlock);
663 		break;
664 
665 	case RECOVERY_WAITING:
666 		/*
667 		 * These messages aren't interesting while we're suspended. We
668 		 * put the queues into waiting state while suspending.
669 		 * Suspending takes a while, so we'll see these during that time
670 		 * and they aren't diagnostic. At other times, they indicate a
671 		 * problem that's worth complaining about.
672 		 */
673 		if (!device_is_suspended(ctrlr->dev))
674 			ufshci_printf(ctrlr, "Waiting for reset to complete\n");
675 		idle = false; /* We want to keep polling */
676 		break;
677 	}
678 
679 	/*
680 	 * Rearm the timeout.
681 	 */
682 	if (!idle) {
683 		callout_schedule_sbt(&hwq->timer, SBT_1S / 2, SBT_1S / 2, 0);
684 	} else {
685 		hwq->timer_armed = false;
686 	}
687 }
688 
689 /*
690  * Submit the tracker to the hardware.
691  */
692 static void
693 ufshci_req_queue_submit_tracker(struct ufshci_req_queue *req_queue,
694     struct ufshci_tracker *tr, enum ufshci_data_direction data_direction)
695 {
696 	struct ufshci_controller *ctrlr = req_queue->ctrlr;
697 	struct ufshci_request *req = tr->req;
698 	struct ufshci_hw_queue *hwq;
699 	uint64_t ucd_paddr;
700 	uint16_t request_len, response_off, response_len;
701 	uint8_t slot_num = tr->slot_num;
702 	int timeout;
703 
704 	hwq = req_queue->qops.get_hw_queue(req_queue);
705 
706 	mtx_assert(&hwq->qlock, MA_OWNED);
707 
708 	if (req->cb_fn == ufshci_completion_poll_cb)
709 		timeout = 1;
710 	else
711 		timeout = ctrlr->timeout_period;
712 	tr->deadline = getsbinuptime() + timeout * SBT_1S;
713 	if (!hwq->timer_armed) {
714 		hwq->timer_armed = true;
715 		/*
716 		 * It wakes up once every 0.5 seconds to check if the deadline
717 		 * has passed.
718 		 */
719 		callout_reset_sbt_on(&hwq->timer, SBT_1S / 2, SBT_1S / 2,
720 		    ufshci_req_queue_timeout, hwq, hwq->cpu, 0);
721 	}
722 
723 	if (req_queue->is_task_mgmt) {
724 		/* Prepare UTP Task Management Request Descriptor. */
725 		ufshci_req_queue_fill_utmr_descriptor(&tr->hwq->utmrd[slot_num],
726 		    req);
727 	} else {
728 		request_len = req->request_size;
729 		response_off = UFSHCI_UTP_XFER_REQ_SIZE;
730 		response_len = req->response_size;
731 
732 		/* Prepare UTP Command Descriptor */
733 		memcpy(tr->ucd, &req->request_upiu, request_len);
734 		memset((uint8_t *)tr->ucd + response_off, 0, response_len);
735 
736 		/*
737 		 * Prepare PRDT. If the payload could not be mapped, the
738 		 * tracker has already been completed and released by the
739 		 * manual completion path, so the descriptor must not be
740 		 * built and the doorbell must not be rung.
741 		 */
742 		if (req->payload_valid &&
743 		    ufshci_req_queue_prepare_prdt(tr) != 0)
744 			return;
745 
746 		/* Prepare UTP Transfer Request Descriptor. */
747 		ucd_paddr = tr->ucd_bus_addr;
748 		ufshci_req_queue_fill_utr_descriptor(&tr->hwq->utrd[slot_num],
749 		    data_direction, ucd_paddr, response_off, response_len,
750 		    tr->prdt_off, tr->prdt_entry_cnt);
751 
752 		bus_dmamap_sync(req_queue->dma_tag_ucd, req_queue->ucdmem_map,
753 		    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
754 	}
755 
756 	bus_dmamap_sync(tr->hwq->dma_tag_queue, tr->hwq->queuemem_map,
757 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
758 
759 	tr->slot_state = UFSHCI_SLOT_STATE_SCHEDULED;
760 
761 	/* Ring the doorbell */
762 	req_queue->qops.ring_doorbell(ctrlr, tr);
763 }
764 
765 static int
766 _ufshci_req_queue_submit_request(struct ufshci_req_queue *req_queue,
767     struct ufshci_request *req)
768 {
769 	struct ufshci_tracker *tr = NULL;
770 	int error;
771 
772 	mtx_assert(&req_queue->qops.get_hw_queue(req_queue)->qlock, MA_OWNED);
773 
774 	error = req_queue->qops.reserve_slot(req_queue, &tr);
775 	if (error != 0) {
776 		ufshci_printf(req_queue->ctrlr, "Failed to get tracker");
777 		return (error);
778 	}
779 	KASSERT(tr, ("There is no tracker allocated."));
780 
781 	if (tr->slot_state == UFSHCI_SLOT_STATE_RESERVED ||
782 	    tr->slot_state == UFSHCI_SLOT_STATE_SCHEDULED)
783 		return (EBUSY);
784 
785 	/* Set the task_tag value to slot_num for traceability. */
786 	req->request_upiu.header.task_tag = tr->slot_num;
787 
788 	tr->slot_state = UFSHCI_SLOT_STATE_RESERVED;
789 	tr->response_size = req->response_size;
790 	tr->deadline = SBT_MAX;
791 	tr->req = req;
792 
793 	TAILQ_REMOVE(&tr->hwq->free_tr, tr, tailq);
794 	TAILQ_INSERT_TAIL(&tr->hwq->outstanding_tr, tr, tailq);
795 
796 	ufshci_req_queue_submit_tracker(req_queue, tr, req->data_direction);
797 
798 	return (0);
799 }
800 
801 int
802 ufshci_req_queue_submit_request(struct ufshci_req_queue *req_queue,
803     struct ufshci_request *req)
804 {
805 	struct ufshci_hw_queue *hwq;
806 	uint32_t error;
807 
808 	/* TODO: MCQs should use a separate Admin queue. */
809 
810 	hwq = req_queue->qops.get_hw_queue(req_queue);
811 	KASSERT(hwq, ("There is no HW queue allocated."));
812 
813 	mtx_lock(&hwq->qlock);
814 	error = _ufshci_req_queue_submit_request(req_queue, req);
815 	mtx_unlock(&hwq->qlock);
816 
817 	return (error);
818 }
819