Changeset 19f0048 in mainline for uspace/drv/bus/usb/xhci/hc.c
- Timestamp:
- 2018-02-01T02:13:34Z (6 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 17d34a8
- Parents:
- 53fdf8c
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/xhci/hc.c
r53fdf8c r19f0048 259 259 int hc_init_memory(xhci_hc_t *hc, ddf_dev_t *device) 260 260 { 261 int err ;261 int err = ENOMEM; 262 262 263 263 if (dma_buffer_alloc(&hc->dcbaa_dma, (1 + hc->max_slots) * sizeof(uint64_t))) … … 265 265 hc->dcbaa = hc->dcbaa_dma.virt; 266 266 267 hc->event_worker = joinable_fibril_create(&event_worker, hc); 268 if (!hc->event_worker) 269 goto err_dcbaa; 270 267 271 if ((err = xhci_event_ring_init(&hc->event_ring, 1))) 268 goto err_ dcbaa;272 goto err_worker; 269 273 270 274 if ((err = xhci_scratchpad_alloc(hc))) … … 277 281 goto err_cmd; 278 282 279 hc->event_worker = joinable_fibril_create(&event_worker, hc);280 if (!hc->event_worker)281 goto err_bus;282 283 283 xhci_sw_ring_init(&hc->sw_ring, PAGE_SIZE / sizeof(xhci_trb_t)); 284 284 285 joinable_fibril_start(hc->event_worker);286 287 285 return EOK; 288 286 289 err_bus:290 xhci_bus_fini(&hc->bus);291 287 err_cmd: 292 288 xhci_fini_commands(hc); … … 295 291 err_event_ring: 296 292 xhci_event_ring_fini(&hc->event_ring); 293 err_worker: 294 joinable_fibril_destroy(hc->event_worker); 297 295 err_dcbaa: 298 296 hc->dcbaa = NULL; … … 468 466 * Initialize the HC: section 4.2 469 467 */ 470 int hc_start(xhci_hc_t *hc , bool irq)468 int hc_start(xhci_hc_t *hc) 471 469 { 472 470 int err; … … 489 487 490 488 XHCI_REG_SET(hc->op_regs, XHCI_OP_EWE, 1); 489 490 xhci_event_ring_reset(&hc->event_ring); 491 491 492 492 xhci_interrupter_regs_t *intr0 = &hc->rt_regs->ir[0]; … … 499 499 XHCI_REG_WR(intr0, XHCI_INTR_ERSTBA_HI, UPPER32(erstptr)); 500 500 501 if ( irq) {501 if (hc->base.irq_cap > 0) { 502 502 XHCI_REG_SET(intr0, XHCI_INTR_IE, 1); 503 503 XHCI_REG_SET(hc->op_regs, XHCI_OP_INTE, 1); … … 506 506 XHCI_REG_SET(hc->op_regs, XHCI_OP_HSEE, 1); 507 507 508 xhci_sw_ring_restart(&hc->sw_ring); 509 joinable_fibril_start(hc->event_worker); 510 511 xhci_start_command_ring(hc); 512 508 513 XHCI_REG_SET(hc->op_regs, XHCI_OP_RS, 1); 509 514 510 xhci_rh_startup(&hc->rh); 515 /* RH needs to access port states on startup */ 516 xhci_rh_start(&hc->rh); 511 517 512 518 return EOK; 519 } 520 521 static void hc_stop(xhci_hc_t *hc) 522 { 523 /* Stop the HC in hardware. */ 524 XHCI_REG_CLR(hc->op_regs, XHCI_OP_RS, 1); 525 526 /* 527 * Wait until the HC is halted - it shall take at most 16 ms. 528 * Note that we ignore the return value here. 529 */ 530 xhci_reg_wait(&hc->op_regs->usbsts, XHCI_REG_MASK(XHCI_OP_HCH), 531 XHCI_REG_MASK(XHCI_OP_HCH)); 532 533 /* Make sure commands will not block other fibrils. */ 534 xhci_nuke_command_ring(hc); 535 536 /* Stop the event worker fibril to restart it */ 537 xhci_sw_ring_stop(&hc->sw_ring); 538 joinable_fibril_join(hc->event_worker); 539 540 /* Then, disconnect all roothub devices, which shall trigger 541 * disconnection of everything */ 542 xhci_rh_stop(&hc->rh); 543 } 544 545 static void hc_reinitialize(xhci_hc_t *hc) 546 { 547 /* Stop everything. */ 548 hc_stop(hc); 549 550 usb_log_info("HC stopped. Starting again..."); 551 552 /* The worker fibrils need to be started again */ 553 joinable_fibril_recreate(hc->event_worker); 554 joinable_fibril_recreate(hc->rh.event_worker); 555 556 /* Now, the HC shall be stopped and software shall be clean. */ 557 hc_start(hc); 558 } 559 560 static bool hc_is_broken(xhci_hc_t *hc) 561 { 562 const uint32_t usbcmd = XHCI_REG_RD_FIELD(&hc->op_regs->usbcmd, 32); 563 const uint32_t usbsts = XHCI_REG_RD_FIELD(&hc->op_regs->usbsts, 32); 564 565 return !(usbcmd & XHCI_REG_MASK(XHCI_OP_RS)) 566 || (usbsts & XHCI_REG_MASK(XHCI_OP_HCE)) 567 || (usbsts & XHCI_REG_MASK(XHCI_OP_HSE)); 513 568 } 514 569 … … 622 677 hc->event_handler = 0; 623 678 624 /* Update the ERDP to make room in the ring. */625 679 uint64_t erdp = hc->event_ring.dequeue_ptr; 626 680 erdp |= XHCI_REG_MASK(XHCI_INTR_ERDP_EHB); … … 646 700 647 701 if (status & XHCI_REG_MASK(XHCI_OP_HSE)) { 648 usb_log_error("Host controller error occured. Bad things gonna happen..."); 649 status &= ~XHCI_REG_MASK(XHCI_OP_HSE); 702 usb_log_error("Host system error occured. Aren't we supposed to be dead already?"); 703 return; 704 } 705 706 if (status & XHCI_REG_MASK(XHCI_OP_HCE)) { 707 usb_log_error("Host controller error occured. Reinitializing..."); 708 hc_reinitialize(hc); 709 return; 650 710 } 651 711 … … 676 736 void hc_fini(xhci_hc_t *hc) 677 737 { 678 xhci_sw_ring_stop(&hc->sw_ring);679 joinable_fibril_join(hc->event_worker); 738 hc_stop(hc); 739 680 740 xhci_sw_ring_fini(&hc->sw_ring); 681 741 joinable_fibril_destroy(hc->event_worker); 682 742 xhci_bus_fini(&hc->bus); 683 743 xhci_event_ring_fini(&hc->event_ring); … … 882 942 xhci_hc_t * const hc = bus_to_hc(dev->base.bus); 883 943 944 if (hc_is_broken(hc)) 945 return EOK; 946 884 947 /* Issue configure endpoint command (sec 4.3.5) with the DC flag. */ 885 948 return xhci_cmd_sync_inline(hc, CONFIGURE_ENDPOINT, … … 930 993 { 931 994 xhci_device_t * const dev = xhci_ep_to_dev(ep); 995 xhci_hc_t * const hc = bus_to_hc(dev->base.bus); 932 996 const unsigned dci = endpoint_dci(ep); 997 998 if (hc_is_broken(hc)) 999 return EOK; 933 1000 934 1001 /* Issue configure endpoint command (sec 4.3.5). */ … … 938 1005 return err; 939 1006 940 xhci_hc_t * const hc = bus_to_hc(dev->base.bus);941 1007 xhci_input_ctx_t *ictx = ictx_dma_buf.virt; 942 1008 XHCI_INPUT_CTRL_CTX_DROP_SET(*XHCI_GET_CTRL_CTX(ictx, hc), dci); … … 992 1058 const unsigned dci = endpoint_dci(ep); 993 1059 xhci_hc_t * const hc = bus_to_hc(dev->base.bus); 1060 1061 if (hc_is_broken(hc)) 1062 return EOK; 1063 994 1064 return xhci_cmd_sync_inline(hc, STOP_ENDPOINT, 995 1065 .slot_id = dev->slot_id,
Note:
See TracChangeset
for help on using the changeset viewer.