diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-10 15:05:02 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-10 15:05:02 -0700 |
commit | 9895850b23886e030cd1e7241d5529a57e969c3d (patch) | |
tree | 1061626db450aeb72dcfcd247c24b33e5238c8c4 /drivers/usb/host/xhci-mem.c | |
parent | fc385c313275b114bc6ad36e60c5177d63250548 (diff) | |
parent | b58af4066d240b18b43f202e07b9ec7461d90b17 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6: (148 commits)
USB: serial: fix stalled writes
USB: remove fake "address-of" expressions
USB: fix thread-unsafe anchor utiliy routines
USB: usbtest: support test device with only one iso-in or iso-out endpoint
USB: usbtest: avoid to free coherent buffer in atomic context
USB: xhci: Set DMA mask for host.
USB: xhci: Don't flush doorbell writes.
USB: xhci: Reduce reads and writes of interrupter registers.
USB: xhci: Make xhci_set_hc_event_deq() static.
USB: xhci: Minimize HW event ring dequeue pointer writes.
USB: xhci: Make xhci_handle_event() static.
USB: xhci: Remove unnecessary reads of IRQ_PENDING register.
USB: xhci: Performance - move xhci_work() into xhci_irq()
USB: xhci: Performance - move interrupt handlers into xhci-ring.c
USB: xhci: Performance - move functions that find ep ring.
USB:: fix linux/usb.h kernel-doc warnings
USB: add USB serial ssu100 driver
USB: usb-storage: implement autosuspend
USB: ehci: fix remove of ehci debugfs dir
USB: Add USB 2.0 to ssb ohci driver
...
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( return ep->stream_info->stream_rings[stream_id]; } -struct xhci_ring *xhci_triad_to_transfer_ring(struct xhci_hcd *xhci, - unsigned int slot_id, unsigned int ep_index, - unsigned int stream_id) -{ - struct xhci_virt_ep *ep; - - ep = &xhci->devs[slot_id]->eps[ep_index]; - /* Common case: no streams */ - if (!(ep->ep_state & EP_HAS_STREAMS)) - return ep->ring; - - if (stream_id == 0) { - xhci_warn(xhci, - "WARN: Slot ID %u, ep index %u has streams, " - "but URB has no stream ID.\n", - slot_id, ep_index); - return NULL; - } - - if (stream_id < ep->stream_info->num_streams) - return ep->stream_info->stream_rings[stream_id]; - - xhci_warn(xhci, - "WARN: Slot ID %u, ep index %u has " - "stream IDs 1 to %u allocated, " - "but stream ID %u is requested.\n", - slot_id, ep_index, - ep->stream_info->num_streams - 1, - stream_id); - return NULL; -} - -/* Get the right ring for the given URB. - * If the endpoint supports streams, boundary check the URB's stream ID. - * If the endpoint doesn't support streams, return the singular endpoint ring. - */ -struct xhci_ring *xhci_urb_to_transfer_ring(struct xhci_hcd *xhci, - struct urb *urb) -{ - return xhci_triad_to_transfer_ring(xhci, urb->dev->slot_id, - xhci_get_endpoint_index(&urb->ep->desc), urb->stream_id); -} - #ifdef CONFIG_USB_XHCI_HCD_DEBUGGING static int xhci_test_radix_tree(struct xhci_hcd *xhci, unsigned int num_streams, @@ -1112,8 +1069,18 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index); /* Set up the endpoint ring */ - virt_dev->eps[ep_index].new_ring = - xhci_ring_alloc(xhci, 1, true, mem_flags); + /* + * Isochronous endpoint ring needs bigger size because one isoc URB + * carries multiple packets and it will insert multiple tds to the + * ring. + * This should be replaced with dynamic ring resizing in the future. + */ + if (usb_endpoint_xfer_isoc(&ep->desc)) + virt_dev->eps[ep_index].new_ring = + xhci_ring_alloc(xhci, 8, true, mem_flags); + else + virt_dev->eps[ep_index].new_ring = + xhci_ring_alloc(xhci, 1, true, mem_flags); if (!virt_dev->eps[ep_index].new_ring) { /* Attempt to use the ring cache */ if (virt_dev->num_rings_cached == 0) @@ -1124,6 +1091,7 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, virt_dev->num_rings_cached--; xhci_reinit_cached_ring(xhci, virt_dev->eps[ep_index].new_ring); } + virt_dev->eps[ep_index].skip = false; ep_ring = virt_dev->eps[ep_index].new_ring; ep_ctx->deq = ep_ring->first_seg->dma | ep_ring->cycle_state; @@ -1389,6 +1357,22 @@ struct xhci_command *xhci_alloc_command(struct xhci_hcd *xhci, return command; } +void xhci_urb_free_priv(struct xhci_hcd *xhci, struct urb_priv *urb_priv) +{ + int last; + + if (!urb_priv) + return; + + last = urb_priv->length - 1; + if (last >= 0) { + int i; + for (i = 0; i <= last; i++) + kfree(urb_priv->td[i]); + } + kfree(urb_priv); +} + void xhci_free_command(struct xhci_hcd *xhci, struct xhci_command *command) { @@ -1588,7 +1572,7 @@ static int xhci_check_trb_in_td_math(struct xhci_hcd *xhci, gfp_t mem_flags) unsigned int num_tests; int i, ret; - num_tests = sizeof(simple_test_vector) / sizeof(simple_test_vector[0]); + num_tests = ARRAY_SIZE(simple_test_vector); for (i = 0; i < num_tests; i++) { ret = xhci_test_trb_in_td(xhci, 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) return ret; } - num_tests = sizeof(complex_test_vector) / sizeof(complex_test_vector[0]); + num_tests = ARRAY_SIZE(complex_test_vector); for (i = 0; i < num_tests; i++) { ret = xhci_test_trb_in_td(xhci, 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) return 0; } +static void xhci_set_hc_event_deq(struct xhci_hcd *xhci) +{ + u64 temp; + dma_addr_t deq; + + deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg, + xhci->event_ring->dequeue); + if (deq == 0 && !in_interrupt()) + xhci_warn(xhci, "WARN something wrong with SW event ring " + "dequeue ptr.\n"); + /* Update HC event ring dequeue pointer */ + temp = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); + temp &= ERST_PTR_MASK; + /* Don't clear the EHB bit (which is RW1C) because + * there might be more events to service. + */ + temp &= ~ERST_EHB; + xhci_dbg(xhci, "// Write event ring dequeue pointer, " + "preserving EHB bit\n"); + xhci_write_64(xhci, ((u64) deq & (u64) ~ERST_PTR_MASK) | temp, + &xhci->ir_set->erst_dequeue); +} + int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) { |