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

Skip to content

Commit 08b168f

Browse files
committed
xhci: Clear EHB bit only at end of interrupt handler
The Event Handler Busy bit shall be cleared by software when the Event Ring is empty. The xHC is thereby informed that it may raise another interrupt once it has enqueued new events (sec 4.17.2). However since commit dc0ffbe ("usb: host: xhci: update event ring dequeue pointer on purpose"), the EHB bit is already cleared after half a segment has been processed. As a result, spurious interrupts may occur: - xhci_irq() processes half a segment, clears EHB, continues processing remaining events. - xHC enqueues new events. Because EHB has been cleared, xHC sets Interrupt Pending bit. Interrupt moderation countdown begins. - Meanwhile xhci_irq() continues processing events. Interrupt moderation countdown reaches zero, so an MSI interrupt is signaled. - xhci_irq() empties the Event Ring, clears EHB again and is done. - Because an MSI interrupt has been signaled, xhci_irq() is run again. It discovers there's nothing to do and returns IRQ_NONE. Avoid by clearing the EHB bit only at the end of xhci_irq(). Fixes: dc0ffbe ("usb: host: xhci: update event ring dequeue pointer on purpose") Signed-off-by: Lukas Wunner <[email protected]> Cc: [email protected] # v5.5+ Cc: Peter Chen <[email protected]>
1 parent 73ff953 commit 08b168f

File tree

1 file changed

+6
-4
lines changed

1 file changed

+6
-4
lines changed

drivers/usb/host/xhci-ring.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3021,7 +3021,8 @@ static int xhci_handle_event(struct xhci_hcd *xhci)
30213021
* - To avoid "Event Ring Full Error" condition
30223022
*/
30233023
static void xhci_update_erst_dequeue(struct xhci_hcd *xhci,
3024-
union xhci_trb *event_ring_deq)
3024+
union xhci_trb *event_ring_deq,
3025+
bool clear_ehb)
30253026
{
30263027
u64 temp_64;
30273028
dma_addr_t deq;
@@ -3047,7 +3048,8 @@ static void xhci_update_erst_dequeue(struct xhci_hcd *xhci,
30473048
}
30483049

30493050
/* Clear the event handler busy flag (RW1C) */
3050-
temp_64 |= ERST_EHB;
3051+
if (clear_ehb)
3052+
temp_64 |= ERST_EHB;
30513053
xhci_write_64(xhci, temp_64, &xhci->ir_set->erst_dequeue);
30523054
}
30533055

@@ -3120,7 +3122,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
31203122
while (xhci_handle_event(xhci) > 0) {
31213123
if (event_loop++ < xhci->event_ring->trbs_per_seg / 2)
31223124
continue;
3123-
xhci_update_erst_dequeue(xhci, event_ring_deq);
3125+
xhci_update_erst_dequeue(xhci, event_ring_deq, false);
31243126
event_ring_deq = xhci->event_ring->dequeue;
31253127

31263128
/* ring is half-full, force isoc trbs to interrupt more often */
@@ -3130,7 +3132,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
31303132
event_loop = 0;
31313133
}
31323134

3133-
xhci_update_erst_dequeue(xhci, event_ring_deq);
3135+
xhci_update_erst_dequeue(xhci, event_ring_deq, true);
31343136
ret = IRQ_HANDLED;
31353137

31363138
out:

0 commit comments

Comments
 (0)