Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit dc0ffbe

Browse files
Peter Chengregkh
authored andcommitted
usb: host: xhci: update event ring dequeue pointer on purpose
On some situations, the software handles TRB events slower than adding TRBs, then xhci_handle_event can't return zero long time, the xHC will consider the event ring is full, and trigger "Event Ring Full" error, but in fact, the software has already finished lots of events, just no chance to update ERDP (event ring dequeue pointer). In this commit, we force update ERDP if half of TRBS_PER_SEGMENT events have handled to avoid "Event Ring Full" error. Signed-off-by: Peter Chen <[email protected]> Signed-off-by: Mathias Nyman <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 6e0f306 commit dc0ffbe

File tree

1 file changed

+43
-17
lines changed

1 file changed

+43
-17
lines changed

drivers/usb/host/xhci-ring.c

Lines changed: 43 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2740,6 +2740,42 @@ static int xhci_handle_event(struct xhci_hcd *xhci)
27402740
return 1;
27412741
}
27422742

2743+
/*
2744+
* Update Event Ring Dequeue Pointer:
2745+
* - When all events have finished
2746+
* - To avoid "Event Ring Full Error" condition
2747+
*/
2748+
static void xhci_update_erst_dequeue(struct xhci_hcd *xhci,
2749+
union xhci_trb *event_ring_deq)
2750+
{
2751+
u64 temp_64;
2752+
dma_addr_t deq;
2753+
2754+
temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
2755+
/* If necessary, update the HW's version of the event ring deq ptr. */
2756+
if (event_ring_deq != xhci->event_ring->dequeue) {
2757+
deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg,
2758+
xhci->event_ring->dequeue);
2759+
if (deq == 0)
2760+
xhci_warn(xhci, "WARN something wrong with SW event ring dequeue ptr\n");
2761+
/*
2762+
* Per 4.9.4, Software writes to the ERDP register shall
2763+
* always advance the Event Ring Dequeue Pointer value.
2764+
*/
2765+
if ((temp_64 & (u64) ~ERST_PTR_MASK) ==
2766+
((u64) deq & (u64) ~ERST_PTR_MASK))
2767+
return;
2768+
2769+
/* Update HC event ring dequeue pointer */
2770+
temp_64 &= ERST_PTR_MASK;
2771+
temp_64 |= ((u64) deq & (u64) ~ERST_PTR_MASK);
2772+
}
2773+
2774+
/* Clear the event handler busy flag (RW1C) */
2775+
temp_64 |= ERST_EHB;
2776+
xhci_write_64(xhci, temp_64, &xhci->ir_set->erst_dequeue);
2777+
}
2778+
27432779
/*
27442780
* xHCI spec says we can get an interrupt, and if the HC has an error condition,
27452781
* we might get bad data out of the event ring. Section 4.10.2.7 has a list of
@@ -2751,9 +2787,9 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
27512787
union xhci_trb *event_ring_deq;
27522788
irqreturn_t ret = IRQ_NONE;
27532789
unsigned long flags;
2754-
dma_addr_t deq;
27552790
u64 temp_64;
27562791
u32 status;
2792+
int event_loop = 0;
27572793

27582794
spin_lock_irqsave(&xhci->lock, flags);
27592795
/* Check if the xHC generated the interrupt, or the irq is shared */
@@ -2807,24 +2843,14 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
28072843
/* FIXME this should be a delayed service routine
28082844
* that clears the EHB.
28092845
*/
2810-
while (xhci_handle_event(xhci) > 0) {}
2811-
2812-
temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
2813-
/* If necessary, update the HW's version of the event ring deq ptr. */
2814-
if (event_ring_deq != xhci->event_ring->dequeue) {
2815-
deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg,
2816-
xhci->event_ring->dequeue);
2817-
if (deq == 0)
2818-
xhci_warn(xhci, "WARN something wrong with SW event "
2819-
"ring dequeue ptr.\n");
2820-
/* Update HC event ring dequeue pointer */
2821-
temp_64 &= ERST_PTR_MASK;
2822-
temp_64 |= ((u64) deq & (u64) ~ERST_PTR_MASK);
2846+
while (xhci_handle_event(xhci) > 0) {
2847+
if (event_loop++ < TRBS_PER_SEGMENT / 2)
2848+
continue;
2849+
xhci_update_erst_dequeue(xhci, event_ring_deq);
2850+
event_loop = 0;
28232851
}
28242852

2825-
/* Clear the event handler busy flag (RW1C); event ring is empty. */
2826-
temp_64 |= ERST_EHB;
2827-
xhci_write_64(xhci, temp_64, &xhci->ir_set->erst_dequeue);
2853+
xhci_update_erst_dequeue(xhci, event_ring_deq);
28282854
ret = IRQ_HANDLED;
28292855

28302856
out:

0 commit comments

Comments
 (0)