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