Skip to content

Commit 15f3ef0

Browse files
l1kgregkh
authored andcommitted
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 <lukas@wunner.de> Cc: stable@vger.kernel.org # v5.5+ Cc: Peter Chen <peter.chen@kernel.org> Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> Link: https://lore.kernel.org/r/20230915143108.1532163-4-mathias.nyman@linux.intel.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent d7cdfc3 commit 15f3ef0

File tree

1 file changed

+7
-5
lines changed

1 file changed

+7
-5
lines changed

drivers/usb/host/xhci-ring.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2996,7 +2996,8 @@ static int xhci_handle_event(struct xhci_hcd *xhci, struct xhci_interrupter *ir)
29962996
*/
29972997
static void xhci_update_erst_dequeue(struct xhci_hcd *xhci,
29982998
struct xhci_interrupter *ir,
2999-
union xhci_trb *event_ring_deq)
2999+
union xhci_trb *event_ring_deq,
3000+
bool clear_ehb)
30003001
{
30013002
u64 temp_64;
30023003
dma_addr_t deq;
@@ -3017,12 +3018,13 @@ static void xhci_update_erst_dequeue(struct xhci_hcd *xhci,
30173018
return;
30183019

30193020
/* Update HC event ring dequeue pointer */
3020-
temp_64 &= ERST_PTR_MASK;
3021+
temp_64 &= ERST_DESI_MASK;
30213022
temp_64 |= ((u64) deq & (u64) ~ERST_PTR_MASK);
30223023
}
30233024

30243025
/* Clear the event handler busy flag (RW1C) */
3025-
temp_64 |= ERST_EHB;
3026+
if (clear_ehb)
3027+
temp_64 |= ERST_EHB;
30263028
xhci_write_64(xhci, temp_64, &ir->ir_set->erst_dequeue);
30273029
}
30283030

@@ -3103,7 +3105,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
31033105
while (xhci_handle_event(xhci, ir) > 0) {
31043106
if (event_loop++ < TRBS_PER_SEGMENT / 2)
31053107
continue;
3106-
xhci_update_erst_dequeue(xhci, ir, event_ring_deq);
3108+
xhci_update_erst_dequeue(xhci, ir, event_ring_deq, false);
31073109
event_ring_deq = ir->event_ring->dequeue;
31083110

31093111
/* ring is half-full, force isoc trbs to interrupt more often */
@@ -3113,7 +3115,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
31133115
event_loop = 0;
31143116
}
31153117

3116-
xhci_update_erst_dequeue(xhci, ir, event_ring_deq);
3118+
xhci_update_erst_dequeue(xhci, ir, event_ring_deq, true);
31173119
ret = IRQ_HANDLED;
31183120

31193121
out:

0 commit comments

Comments
 (0)