diff options
Diffstat (limited to 'drivers/usb/host/xhci-mem.c')
| -rw-r--r-- | drivers/usb/host/xhci-mem.c | 101 |
1 files changed, 54 insertions, 47 deletions
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 2eb658d26394..4e51343ddffc 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c | |||
| @@ -391,49 +391,6 @@ struct xhci_ring *xhci_stream_id_to_ring( | |||
| 391 | return ep->stream_info->stream_rings[stream_id]; | 391 | return ep->stream_info->stream_rings[stream_id]; |
| 392 | } | 392 | } |
| 393 | 393 | ||
| 394 | struct xhci_ring *xhci_triad_to_transfer_ring(struct xhci_hcd *xhci, | ||
| 395 | unsigned int slot_id, unsigned int ep_index, | ||
| 396 | unsigned int stream_id) | ||
| 397 | { | ||
| 398 | struct xhci_virt_ep *ep; | ||
| 399 | |||
| 400 | ep = &xhci->devs[slot_id]->eps[ep_index]; | ||
| 401 | /* Common case: no streams */ | ||
| 402 | if (!(ep->ep_state & EP_HAS_STREAMS)) | ||
| 403 | return ep->ring; | ||
| 404 | |||
| 405 | if (stream_id == 0) { | ||
| 406 | xhci_warn(xhci, | ||
| 407 | "WARN: Slot ID %u, ep index %u has streams, " | ||
| 408 | "but URB has no stream ID.\n", | ||
| 409 | slot_id, ep_index); | ||
| 410 | return NULL; | ||
| 411 | } | ||
| 412 | |||
| 413 | if (stream_id < ep->stream_info->num_streams) | ||
| 414 | return ep->stream_info->stream_rings[stream_id]; | ||
| 415 | |||
| 416 | xhci_warn(xhci, | ||
| 417 | "WARN: Slot ID %u, ep index %u has " | ||
| 418 | "stream IDs 1 to %u allocated, " | ||
| 419 | "but stream ID %u is requested.\n", | ||
| 420 | slot_id, ep_index, | ||
| 421 | ep->stream_info->num_streams - 1, | ||
| 422 | stream_id); | ||
| 423 | return NULL; | ||
| 424 | } | ||
| 425 | |||
| 426 | /* Get the right ring for the given URB. | ||
| 427 | * If the endpoint supports streams, boundary check the URB's stream ID. | ||
| 428 | * If the endpoint doesn't support streams, return the singular endpoint ring. | ||
| 429 | */ | ||
| 430 | struct xhci_ring *xhci_urb_to_transfer_ring(struct xhci_hcd *xhci, | ||
| 431 | struct urb *urb) | ||
| 432 | { | ||
| 433 | return xhci_triad_to_transfer_ring(xhci, urb->dev->slot_id, | ||
| 434 | xhci_get_endpoint_index(&urb->ep->desc), urb->stream_id); | ||
| 435 | } | ||
| 436 | |||
| 437 | #ifdef CONFIG_USB_XHCI_HCD_DEBUGGING | 394 | #ifdef CONFIG_USB_XHCI_HCD_DEBUGGING |
| 438 | static int xhci_test_radix_tree(struct xhci_hcd *xhci, | 395 | static int xhci_test_radix_tree(struct xhci_hcd *xhci, |
| 439 | unsigned int num_streams, | 396 | unsigned int num_streams, |
| @@ -1112,8 +1069,18 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, | |||
| 1112 | ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index); | 1069 | ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index); |
| 1113 | 1070 | ||
| 1114 | /* Set up the endpoint ring */ | 1071 | /* Set up the endpoint ring */ |
| 1115 | virt_dev->eps[ep_index].new_ring = | 1072 | /* |
| 1116 | xhci_ring_alloc(xhci, 1, true, mem_flags); | 1073 | * Isochronous endpoint ring needs bigger size because one isoc URB |
| 1074 | * carries multiple packets and it will insert multiple tds to the | ||
| 1075 | * ring. | ||
| 1076 | * This should be replaced with dynamic ring resizing in the future. | ||
| 1077 | */ | ||
| 1078 | if (usb_endpoint_xfer_isoc(&ep->desc)) | ||
| 1079 | virt_dev->eps[ep_index].new_ring = | ||
| 1080 | xhci_ring_alloc(xhci, 8, true, mem_flags); | ||
| 1081 | else | ||
| 1082 | virt_dev->eps[ep_index].new_ring = | ||
| 1083 | xhci_ring_alloc(xhci, 1, true, mem_flags); | ||
| 1117 | if (!virt_dev->eps[ep_index].new_ring) { | 1084 | if (!virt_dev->eps[ep_index].new_ring) { |
| 1118 | /* Attempt to use the ring cache */ | 1085 | /* Attempt to use the ring cache */ |
| 1119 | if (virt_dev->num_rings_cached == 0) | 1086 | if (virt_dev->num_rings_cached == 0) |
| @@ -1124,6 +1091,7 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, | |||
| 1124 | virt_dev->num_rings_cached--; | 1091 | virt_dev->num_rings_cached--; |
| 1125 | xhci_reinit_cached_ring(xhci, virt_dev->eps[ep_index].new_ring); | 1092 | xhci_reinit_cached_ring(xhci, virt_dev->eps[ep_index].new_ring); |
| 1126 | } | 1093 | } |
| 1094 | virt_dev->eps[ep_index].skip = false; | ||
| 1127 | ep_ring = virt_dev->eps[ep_index].new_ring; | 1095 | ep_ring = virt_dev->eps[ep_index].new_ring; |
| 1128 | ep_ctx->deq = ep_ring->first_seg->dma | ep_ring->cycle_state; | 1096 | ep_ctx->deq = ep_ring->first_seg->dma | ep_ring->cycle_state; |
| 1129 | 1097 | ||
| @@ -1389,6 +1357,22 @@ struct xhci_command *xhci_alloc_command(struct xhci_hcd *xhci, | |||
| 1389 | return command; | 1357 | return command; |
| 1390 | } | 1358 | } |
| 1391 | 1359 | ||
| 1360 | void xhci_urb_free_priv(struct xhci_hcd *xhci, struct urb_priv *urb_priv) | ||
| 1361 | { | ||
| 1362 | int last; | ||
| 1363 | |||
| 1364 | if (!urb_priv) | ||
| 1365 | return; | ||
| 1366 | |||
| 1367 | last = urb_priv->length - 1; | ||
| 1368 | if (last >= 0) { | ||
| 1369 | int i; | ||
| 1370 | for (i = 0; i <= last; i++) | ||
| 1371 | kfree(urb_priv->td[i]); | ||
| 1372 | } | ||
| 1373 | kfree(urb_priv); | ||
| 1374 | } | ||
| 1375 | |||
| 1392 | void xhci_free_command(struct xhci_hcd *xhci, | 1376 | void xhci_free_command(struct xhci_hcd *xhci, |
| 1393 | struct xhci_command *command) | 1377 | struct xhci_command *command) |
| 1394 | { | 1378 | { |
| @@ -1588,7 +1572,7 @@ static int xhci_check_trb_in_td_math(struct xhci_hcd *xhci, gfp_t mem_flags) | |||
| 1588 | unsigned int num_tests; | 1572 | unsigned int num_tests; |
| 1589 | int i, ret; | 1573 | int i, ret; |
| 1590 | 1574 | ||
| 1591 | num_tests = sizeof(simple_test_vector) / sizeof(simple_test_vector[0]); | 1575 | num_tests = ARRAY_SIZE(simple_test_vector); |
| 1592 | for (i = 0; i < num_tests; i++) { | 1576 | for (i = 0; i < num_tests; i++) { |
| 1593 | ret = xhci_test_trb_in_td(xhci, | 1577 | ret = xhci_test_trb_in_td(xhci, |
| 1594 | xhci->event_ring->first_seg, | 1578 | xhci->event_ring->first_seg, |
| @@ -1601,7 +1585,7 @@ static int xhci_check_trb_in_td_math(struct xhci_hcd *xhci, gfp_t mem_flags) | |||
| 1601 | return ret; | 1585 | return ret; |
| 1602 | } | 1586 | } |
| 1603 | 1587 | ||
| 1604 | num_tests = sizeof(complex_test_vector) / sizeof(complex_test_vector[0]); | 1588 | num_tests = ARRAY_SIZE(complex_test_vector); |
| 1605 | for (i = 0; i < num_tests; i++) { | 1589 | for (i = 0; i < num_tests; i++) { |
| 1606 | ret = xhci_test_trb_in_td(xhci, | 1590 | ret = xhci_test_trb_in_td(xhci, |
| 1607 | complex_test_vector[i].input_seg, | 1591 | complex_test_vector[i].input_seg, |
| @@ -1617,6 +1601,29 @@ static int xhci_check_trb_in_td_math(struct xhci_hcd *xhci, gfp_t mem_flags) | |||
| 1617 | return 0; | 1601 | return 0; |
| 1618 | } | 1602 | } |
| 1619 | 1603 | ||
| 1604 | static void xhci_set_hc_event_deq(struct xhci_hcd *xhci) | ||
| 1605 | { | ||
| 1606 | u64 temp; | ||
| 1607 | dma_addr_t deq; | ||
| 1608 | |||
| 1609 | deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg, | ||
| 1610 | xhci->event_ring->dequeue); | ||
| 1611 | if (deq == 0 && !in_interrupt()) | ||
| 1612 | xhci_warn(xhci, "WARN something wrong with SW event ring " | ||
| 1613 | "dequeue ptr.\n"); | ||
| 1614 | /* Update HC event ring dequeue pointer */ | ||
| 1615 | temp = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); | ||
| 1616 | temp &= ERST_PTR_MASK; | ||
| 1617 | /* Don't clear the EHB bit (which is RW1C) because | ||
| 1618 | * there might be more events to service. | ||
| 1619 | */ | ||
| 1620 | temp &= ~ERST_EHB; | ||
| 1621 | xhci_dbg(xhci, "// Write event ring dequeue pointer, " | ||
| 1622 | "preserving EHB bit\n"); | ||
| 1623 | xhci_write_64(xhci, ((u64) deq & (u64) ~ERST_PTR_MASK) | temp, | ||
| 1624 | &xhci->ir_set->erst_dequeue); | ||
| 1625 | } | ||
| 1626 | |||
| 1620 | 1627 | ||
| 1621 | int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) | 1628 | int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) |
| 1622 | { | 1629 | { |
