diff options
Diffstat (limited to 'drivers/usb/host/xhci-mem.c')
-rw-r--r-- | drivers/usb/host/xhci-mem.c | 74 |
1 files changed, 73 insertions, 1 deletions
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index d299ffad806b..5711048708d7 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c | |||
@@ -353,8 +353,19 @@ struct xhci_stream_ctx *xhci_alloc_stream_ctx(struct xhci_hcd *xhci, | |||
353 | mem_flags, dma); | 353 | mem_flags, dma); |
354 | } | 354 | } |
355 | 355 | ||
356 | struct xhci_ring *xhci_dma_to_transfer_ring( | ||
357 | struct xhci_virt_ep *ep, | ||
358 | u64 address) | ||
359 | { | ||
360 | if (ep->ep_state & EP_HAS_STREAMS) | ||
361 | return radix_tree_lookup(&ep->stream_info->trb_address_map, | ||
362 | address >> SEGMENT_SHIFT); | ||
363 | return ep->ring; | ||
364 | } | ||
365 | |||
366 | /* Only use this when you know stream_info is valid */ | ||
356 | #ifdef CONFIG_USB_XHCI_HCD_DEBUGGING | 367 | #ifdef CONFIG_USB_XHCI_HCD_DEBUGGING |
357 | struct xhci_ring *dma_to_stream_ring( | 368 | static struct xhci_ring *dma_to_stream_ring( |
358 | struct xhci_stream_info *stream_info, | 369 | struct xhci_stream_info *stream_info, |
359 | u64 address) | 370 | u64 address) |
360 | { | 371 | { |
@@ -363,6 +374,66 @@ struct xhci_ring *dma_to_stream_ring( | |||
363 | } | 374 | } |
364 | #endif /* CONFIG_USB_XHCI_HCD_DEBUGGING */ | 375 | #endif /* CONFIG_USB_XHCI_HCD_DEBUGGING */ |
365 | 376 | ||
377 | struct xhci_ring *xhci_stream_id_to_ring( | ||
378 | struct xhci_virt_device *dev, | ||
379 | unsigned int ep_index, | ||
380 | unsigned int stream_id) | ||
381 | { | ||
382 | struct xhci_virt_ep *ep = &dev->eps[ep_index]; | ||
383 | |||
384 | if (stream_id == 0) | ||
385 | return ep->ring; | ||
386 | if (!ep->stream_info) | ||
387 | return NULL; | ||
388 | |||
389 | if (stream_id > ep->stream_info->num_streams) | ||
390 | return NULL; | ||
391 | return ep->stream_info->stream_rings[stream_id]; | ||
392 | } | ||
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 | |||
366 | #ifdef CONFIG_USB_XHCI_HCD_DEBUGGING | 437 | #ifdef CONFIG_USB_XHCI_HCD_DEBUGGING |
367 | static int xhci_test_radix_tree(struct xhci_hcd *xhci, | 438 | static int xhci_test_radix_tree(struct xhci_hcd *xhci, |
368 | unsigned int num_streams, | 439 | unsigned int num_streams, |
@@ -515,6 +586,7 @@ struct xhci_stream_info *xhci_alloc_stream_info(struct xhci_hcd *xhci, | |||
515 | cur_ring = stream_info->stream_rings[cur_stream]; | 586 | cur_ring = stream_info->stream_rings[cur_stream]; |
516 | if (!cur_ring) | 587 | if (!cur_ring) |
517 | goto cleanup_rings; | 588 | goto cleanup_rings; |
589 | cur_ring->stream_id = cur_stream; | ||
518 | /* Set deq ptr, cycle bit, and stream context type */ | 590 | /* Set deq ptr, cycle bit, and stream context type */ |
519 | addr = cur_ring->first_seg->dma | | 591 | addr = cur_ring->first_seg->dma | |
520 | SCT_FOR_CTX(SCT_PRI_TR) | | 592 | SCT_FOR_CTX(SCT_PRI_TR) | |