diff options
Diffstat (limited to 'drivers/usb/host/xhci-ring.c')
-rw-r--r-- | drivers/usb/host/xhci-ring.c | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 54139a2f06ce..952e2ded61af 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c | |||
@@ -1934,8 +1934,10 @@ static int handle_tx_event(struct xhci_hcd *xhci, | |||
1934 | int status = -EINPROGRESS; | 1934 | int status = -EINPROGRESS; |
1935 | struct urb_priv *urb_priv; | 1935 | struct urb_priv *urb_priv; |
1936 | struct xhci_ep_ctx *ep_ctx; | 1936 | struct xhci_ep_ctx *ep_ctx; |
1937 | struct list_head *tmp; | ||
1937 | u32 trb_comp_code; | 1938 | u32 trb_comp_code; |
1938 | int ret = 0; | 1939 | int ret = 0; |
1940 | int td_num = 0; | ||
1939 | 1941 | ||
1940 | slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags)); | 1942 | slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags)); |
1941 | xdev = xhci->devs[slot_id]; | 1943 | xdev = xhci->devs[slot_id]; |
@@ -1957,6 +1959,12 @@ static int handle_tx_event(struct xhci_hcd *xhci, | |||
1957 | return -ENODEV; | 1959 | return -ENODEV; |
1958 | } | 1960 | } |
1959 | 1961 | ||
1962 | /* Count current td numbers if ep->skip is set */ | ||
1963 | if (ep->skip) { | ||
1964 | list_for_each(tmp, &ep_ring->td_list) | ||
1965 | td_num++; | ||
1966 | } | ||
1967 | |||
1960 | event_dma = le64_to_cpu(event->buffer); | 1968 | event_dma = le64_to_cpu(event->buffer); |
1961 | trb_comp_code = GET_COMP_CODE(le32_to_cpu(event->transfer_len)); | 1969 | trb_comp_code = GET_COMP_CODE(le32_to_cpu(event->transfer_len)); |
1962 | /* Look for common error cases */ | 1970 | /* Look for common error cases */ |
@@ -2068,7 +2076,18 @@ static int handle_tx_event(struct xhci_hcd *xhci, | |||
2068 | goto cleanup; | 2076 | goto cleanup; |
2069 | } | 2077 | } |
2070 | 2078 | ||
2079 | /* We've skipped all the TDs on the ep ring when ep->skip set */ | ||
2080 | if (ep->skip && td_num == 0) { | ||
2081 | ep->skip = false; | ||
2082 | xhci_dbg(xhci, "All tds on the ep_ring skipped. " | ||
2083 | "Clear skip flag.\n"); | ||
2084 | ret = 0; | ||
2085 | goto cleanup; | ||
2086 | } | ||
2087 | |||
2071 | td = list_entry(ep_ring->td_list.next, struct xhci_td, td_list); | 2088 | td = list_entry(ep_ring->td_list.next, struct xhci_td, td_list); |
2089 | if (ep->skip) | ||
2090 | td_num--; | ||
2072 | 2091 | ||
2073 | /* Is this a TRB in the currently executing TD? */ | 2092 | /* Is this a TRB in the currently executing TD? */ |
2074 | event_seg = trb_in_td(ep_ring->deq_seg, ep_ring->dequeue, | 2093 | event_seg = trb_in_td(ep_ring->deq_seg, ep_ring->dequeue, |