Commit e9df17eb authored by Sarah Sharp's avatar Sarah Sharp Committed by Greg Kroah-Hartman

USB: xhci: Correct assumptions about number of rings per endpoint.

Much of the xHCI driver code assumes that endpoints only have one ring.
Now an endpoint can have one ring per enabled stream ID, so correct that
assumption.  Use functions that translate the stream_id field in the URB
or the DMA address of a TRB into the correct stream ring.

Correct the polling loop to print out all enabled stream rings.  Make the
URB cancellation routine find the correct stream ring if the URB has
stream_id set.  Make sure the URB enqueueing routine does the same.  Also
correct the code that handles stalled/halted endpoints.

Check that commands and registers that can take stream IDs handle them
properly.  That includes ringing an endpoint doorbell, resetting a
stalled/halted endpoint, and setting a transfer ring dequeue pointer
(since that command can set the dequeue pointer in a stream context or an
endpoint context).

Correct the transfer event handler to translate a TRB DMA address into the
stream ring it was enqueued to.  Make the code to allocate and prepare TD
structures adds the TD to the right td_list for the stream ring.  Make
sure the code to give the first TRB in a TD to the hardware manipulates
the correct stream ring.

When an endpoint stalls, store the stream ID of the stream ring that
stalled in the xhci_virt_ep structure.  Use that instead of the stream ID
in the URB, since an URB may be re-used after it is given back after a
non-control endpoint stall.
Signed-off-by: default avatarSarah Sharp <sarah.a.sharp@linux.intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 8df75f42
...@@ -364,6 +364,30 @@ void xhci_debug_ring(struct xhci_hcd *xhci, struct xhci_ring *ring) ...@@ -364,6 +364,30 @@ void xhci_debug_ring(struct xhci_hcd *xhci, struct xhci_ring *ring)
xhci_debug_segment(xhci, seg); xhci_debug_segment(xhci, seg);
} }
void xhci_dbg_ep_rings(struct xhci_hcd *xhci,
unsigned int slot_id, unsigned int ep_index,
struct xhci_virt_ep *ep)
{
int i;
struct xhci_ring *ring;
if (ep->ep_state & EP_HAS_STREAMS) {
for (i = 1; i < ep->stream_info->num_streams; i++) {
ring = ep->stream_info->stream_rings[i];
xhci_dbg(xhci, "Dev %d endpoint %d stream ID %d:\n",
slot_id, ep_index, i);
xhci_debug_segment(xhci, ring->deq_seg);
}
} else {
ring = ep->ring;
if (!ring)
return;
xhci_dbg(xhci, "Dev %d endpoint ring %d:\n",
slot_id, ep_index);
xhci_debug_segment(xhci, ring->deq_seg);
}
}
void xhci_dbg_erst(struct xhci_hcd *xhci, struct xhci_erst *erst) void xhci_dbg_erst(struct xhci_hcd *xhci, struct xhci_erst *erst)
{ {
u32 addr = (u32) erst->erst_dma_addr; u32 addr = (u32) erst->erst_dma_addr;
......
...@@ -353,8 +353,19 @@ struct xhci_stream_ctx *xhci_alloc_stream_ctx(struct xhci_hcd *xhci, ...@@ -353,8 +353,19 @@ struct xhci_stream_ctx *xhci_alloc_stream_ctx(struct xhci_hcd *xhci,
mem_flags, dma); mem_flags, dma);
} }
struct xhci_ring *xhci_dma_to_transfer_ring(
struct xhci_virt_ep *ep,
u64 address)
{
if (ep->ep_state & EP_HAS_STREAMS)
return radix_tree_lookup(&ep->stream_info->trb_address_map,
address >> SEGMENT_SHIFT);
return ep->ring;
}
/* Only use this when you know stream_info is valid */
#ifdef CONFIG_USB_XHCI_HCD_DEBUGGING #ifdef CONFIG_USB_XHCI_HCD_DEBUGGING
struct xhci_ring *dma_to_stream_ring( static struct xhci_ring *dma_to_stream_ring(
struct xhci_stream_info *stream_info, struct xhci_stream_info *stream_info,
u64 address) u64 address)
{ {
...@@ -363,6 +374,66 @@ struct xhci_ring *dma_to_stream_ring( ...@@ -363,6 +374,66 @@ struct xhci_ring *dma_to_stream_ring(
} }
#endif /* CONFIG_USB_XHCI_HCD_DEBUGGING */ #endif /* CONFIG_USB_XHCI_HCD_DEBUGGING */
struct xhci_ring *xhci_stream_id_to_ring(
struct xhci_virt_device *dev,
unsigned int ep_index,
unsigned int stream_id)
{
struct xhci_virt_ep *ep = &dev->eps[ep_index];
if (stream_id == 0)
return ep->ring;
if (!ep->stream_info)
return NULL;
if (stream_id > ep->stream_info->num_streams)
return NULL;
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 #ifdef CONFIG_USB_XHCI_HCD_DEBUGGING
static int xhci_test_radix_tree(struct xhci_hcd *xhci, static int xhci_test_radix_tree(struct xhci_hcd *xhci,
unsigned int num_streams, unsigned int num_streams,
...@@ -515,6 +586,7 @@ struct xhci_stream_info *xhci_alloc_stream_info(struct xhci_hcd *xhci, ...@@ -515,6 +586,7 @@ struct xhci_stream_info *xhci_alloc_stream_info(struct xhci_hcd *xhci,
cur_ring = stream_info->stream_rings[cur_stream]; cur_ring = stream_info->stream_rings[cur_stream];
if (!cur_ring) if (!cur_ring)
goto cleanup_rings; goto cleanup_rings;
cur_ring->stream_id = cur_stream;
/* Set deq ptr, cycle bit, and stream context type */ /* Set deq ptr, cycle bit, and stream context type */
addr = cur_ring->first_seg->dma | addr = cur_ring->first_seg->dma |
SCT_FOR_CTX(SCT_PRI_TR) | SCT_FOR_CTX(SCT_PRI_TR) |
......
This diff is collapsed.
...@@ -353,11 +353,7 @@ void xhci_event_ring_work(unsigned long arg) ...@@ -353,11 +353,7 @@ void xhci_event_ring_work(unsigned long arg)
if (!xhci->devs[i]) if (!xhci->devs[i])
continue; continue;
for (j = 0; j < 31; ++j) { for (j = 0; j < 31; ++j) {
struct xhci_ring *ring = xhci->devs[i]->eps[j].ring; xhci_dbg_ep_rings(xhci, i, j, &xhci->devs[i]->eps[j]);
if (!ring)
continue;
xhci_dbg(xhci, "Dev %d endpoint ring %d:\n", i, j);
xhci_debug_segment(xhci, ring->deq_seg);
} }
} }
...@@ -839,7 +835,12 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) ...@@ -839,7 +835,12 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
xhci_debug_ring(xhci, xhci->event_ring); xhci_debug_ring(xhci, xhci->event_ring);
ep_index = xhci_get_endpoint_index(&urb->ep->desc); ep_index = xhci_get_endpoint_index(&urb->ep->desc);
ep = &xhci->devs[urb->dev->slot_id]->eps[ep_index]; ep = &xhci->devs[urb->dev->slot_id]->eps[ep_index];
ep_ring = ep->ring; ep_ring = xhci_urb_to_transfer_ring(xhci, urb);
if (!ep_ring) {
ret = -EINVAL;
goto done;
}
xhci_dbg(xhci, "Endpoint ring:\n"); xhci_dbg(xhci, "Endpoint ring:\n");
xhci_debug_ring(xhci, ep_ring); xhci_debug_ring(xhci, ep_ring);
td = (struct xhci_td *) urb->hcpriv; td = (struct xhci_td *) urb->hcpriv;
...@@ -1383,7 +1384,7 @@ void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci, ...@@ -1383,7 +1384,7 @@ void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci,
* or it will attempt to resend it on the next doorbell ring. * or it will attempt to resend it on the next doorbell ring.
*/ */
xhci_find_new_dequeue_state(xhci, udev->slot_id, xhci_find_new_dequeue_state(xhci, udev->slot_id,
ep_index, ep->stopped_td, ep_index, ep->stopped_stream, ep->stopped_td,
&deq_state); &deq_state);
/* HW with the reset endpoint quirk will use the saved dequeue state to /* HW with the reset endpoint quirk will use the saved dequeue state to
...@@ -1392,10 +1393,12 @@ void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci, ...@@ -1392,10 +1393,12 @@ void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci,
if (!(xhci->quirks & XHCI_RESET_EP_QUIRK)) { if (!(xhci->quirks & XHCI_RESET_EP_QUIRK)) {
xhci_dbg(xhci, "Queueing new dequeue state\n"); xhci_dbg(xhci, "Queueing new dequeue state\n");
xhci_queue_new_dequeue_state(xhci, udev->slot_id, xhci_queue_new_dequeue_state(xhci, udev->slot_id,
ep_index, &deq_state); ep_index, ep->stopped_stream, &deq_state);
} else { } else {
/* Better hope no one uses the input context between now and the /* Better hope no one uses the input context between now and the
* reset endpoint completion! * reset endpoint completion!
* XXX: No idea how this hardware will react when stream rings
* are enabled.
*/ */
xhci_dbg(xhci, "Setting up input context for " xhci_dbg(xhci, "Setting up input context for "
"configure endpoint command\n"); "configure endpoint command\n");
......
...@@ -444,6 +444,7 @@ struct xhci_doorbell_array { ...@@ -444,6 +444,7 @@ struct xhci_doorbell_array {
/* Endpoint Target - bits 0:7 */ /* Endpoint Target - bits 0:7 */
#define EPI_TO_DB(p) (((p) + 1) & 0xff) #define EPI_TO_DB(p) (((p) + 1) & 0xff)
#define STREAM_ID_TO_DB(p) (((p) & 0xffff) << 16)
/** /**
...@@ -714,6 +715,7 @@ struct xhci_virt_ep { ...@@ -714,6 +715,7 @@ struct xhci_virt_ep {
/* The TRB that was last reported in a stopped endpoint ring */ /* The TRB that was last reported in a stopped endpoint ring */
union xhci_trb *stopped_trb; union xhci_trb *stopped_trb;
struct xhci_td *stopped_td; struct xhci_td *stopped_td;
unsigned int stopped_stream;
/* Watchdog timer for stop endpoint command to cancel URBs */ /* Watchdog timer for stop endpoint command to cancel URBs */
struct timer_list stop_cmd_timer; struct timer_list stop_cmd_timer;
int stop_cmds_pending; int stop_cmds_pending;
...@@ -871,6 +873,10 @@ struct xhci_event_cmd { ...@@ -871,6 +873,10 @@ struct xhci_event_cmd {
#define TRB_TO_EP_INDEX(p) ((((p) & (0x1f << 16)) >> 16) - 1) #define TRB_TO_EP_INDEX(p) ((((p) & (0x1f << 16)) >> 16) - 1)
#define EP_ID_FOR_TRB(p) ((((p) + 1) & 0x1f) << 16) #define EP_ID_FOR_TRB(p) ((((p) + 1) & 0x1f) << 16)
/* Set TR Dequeue Pointer command TRB fields */
#define TRB_TO_STREAM_ID(p) ((((p) & (0xffff << 16)) >> 16))
#define STREAM_ID_FOR_TRB(p) ((((p)) & 0xffff) << 16)
/* Port Status Change Event TRB fields */ /* Port Status Change Event TRB fields */
/* Port ID - bits 31:24 */ /* Port ID - bits 31:24 */
...@@ -1040,6 +1046,7 @@ struct xhci_ring { ...@@ -1040,6 +1046,7 @@ struct xhci_ring {
* if we own the TRB (if we are the consumer). See section 4.9.1. * if we own the TRB (if we are the consumer). See section 4.9.1.
*/ */
u32 cycle_state; u32 cycle_state;
unsigned int stream_id;
}; };
struct xhci_erst_entry { struct xhci_erst_entry {
...@@ -1265,6 +1272,9 @@ void xhci_dbg_ring_ptrs(struct xhci_hcd *xhci, struct xhci_ring *ring); ...@@ -1265,6 +1272,9 @@ void xhci_dbg_ring_ptrs(struct xhci_hcd *xhci, struct xhci_ring *ring);
void xhci_dbg_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx, unsigned int last_ep); void xhci_dbg_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx, unsigned int last_ep);
char *xhci_get_slot_state(struct xhci_hcd *xhci, char *xhci_get_slot_state(struct xhci_hcd *xhci,
struct xhci_container_ctx *ctx); struct xhci_container_ctx *ctx);
void xhci_dbg_ep_rings(struct xhci_hcd *xhci,
unsigned int slot_id, unsigned int ep_index,
struct xhci_virt_ep *ep);
/* xHCI memory management */ /* xHCI memory management */
void xhci_mem_cleanup(struct xhci_hcd *xhci); void xhci_mem_cleanup(struct xhci_hcd *xhci);
...@@ -1302,6 +1312,18 @@ void xhci_setup_streams_ep_input_ctx(struct xhci_hcd *xhci, ...@@ -1302,6 +1312,18 @@ void xhci_setup_streams_ep_input_ctx(struct xhci_hcd *xhci,
void xhci_setup_no_streams_ep_input_ctx(struct xhci_hcd *xhci, void xhci_setup_no_streams_ep_input_ctx(struct xhci_hcd *xhci,
struct xhci_ep_ctx *ep_ctx, struct xhci_ep_ctx *ep_ctx,
struct xhci_virt_ep *ep); struct xhci_virt_ep *ep);
struct xhci_ring *xhci_dma_to_transfer_ring(
struct xhci_virt_ep *ep,
u64 address);
struct xhci_ring *xhci_urb_to_transfer_ring(struct xhci_hcd *xhci,
struct urb *urb);
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_ring *xhci_stream_id_to_ring(
struct xhci_virt_device *dev,
unsigned int ep_index,
unsigned int stream_id);
struct xhci_command *xhci_alloc_command(struct xhci_hcd *xhci, struct xhci_command *xhci_alloc_command(struct xhci_hcd *xhci,
bool allocate_in_ctx, bool allocate_completion, bool allocate_in_ctx, bool allocate_completion,
gfp_t mem_flags); gfp_t mem_flags);
...@@ -1374,9 +1396,11 @@ int xhci_queue_reset_ep(struct xhci_hcd *xhci, int slot_id, ...@@ -1374,9 +1396,11 @@ int xhci_queue_reset_ep(struct xhci_hcd *xhci, int slot_id,
int xhci_queue_reset_device(struct xhci_hcd *xhci, u32 slot_id); int xhci_queue_reset_device(struct xhci_hcd *xhci, u32 slot_id);
void xhci_find_new_dequeue_state(struct xhci_hcd *xhci, void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
unsigned int slot_id, unsigned int ep_index, unsigned int slot_id, unsigned int ep_index,
struct xhci_td *cur_td, struct xhci_dequeue_state *state); unsigned int stream_id, struct xhci_td *cur_td,
struct xhci_dequeue_state *state);
void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci, void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci,
unsigned int slot_id, unsigned int ep_index, unsigned int slot_id, unsigned int ep_index,
unsigned int stream_id,
struct xhci_dequeue_state *deq_state); struct xhci_dequeue_state *deq_state);
void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci, void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci,
struct usb_device *udev, unsigned int ep_index); struct usb_device *udev, unsigned int ep_index);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment