Skip to content

Commit

Permalink
USB: xhci: Correct Event Handler Busy flag usage.
Browse files Browse the repository at this point in the history
The Event Handler Busy bit in the event ring dequeue pointer is write 1 to
clear.  Fix the interrupt service routine to clear that bit after the
event handler has run.

xhci_set_hc_event_deq() is designed to update the event ring dequeue pointer
without changing any of the four reserved bits in the lower nibble.  The event
handler busy (EHB) bit is write one to clear, so the new value must always
contain a zero in that bit in order to preserve the EHB value.

Signed-off-by: Sarah Sharp <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
  • Loading branch information
Sarah Sharp authored and gregkh committed Jul 28, 2009
1 parent 6288961 commit 2d83109
Show file tree
Hide file tree
Showing 2 changed files with 7 additions and 3 deletions.
4 changes: 2 additions & 2 deletions drivers/usb/host/xhci-hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -249,9 +249,9 @@ static void xhci_work(struct xhci_hcd *xhci)
/* FIXME this should be a delayed service routine that clears the EHB */
xhci_handle_event(xhci);

/* Clear the event handler busy flag; the event ring should be empty. */
/* Clear the event handler busy flag (RW1C); the event ring should be empty. */
temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
xhci_write_64(xhci, temp_64 & ~ERST_EHB, &xhci->ir_set->erst_dequeue);
xhci_write_64(xhci, temp_64 | ERST_EHB, &xhci->ir_set->erst_dequeue);
/* Flush posted writes -- FIXME is this necessary? */
xhci_readl(xhci, &xhci->ir_set->irq_pending);
}
Expand Down
6 changes: 5 additions & 1 deletion drivers/usb/host/xhci-ring.c
Original file line number Diff line number Diff line change
Expand Up @@ -248,8 +248,12 @@ void xhci_set_hc_event_deq(struct xhci_hcd *xhci)
/* Update HC event ring dequeue pointer */
temp = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
temp &= ERST_PTR_MASK;
/* Don't clear the EHB bit (which is RW1C) because
* there might be more events to service.
*/
temp &= ~ERST_EHB;
if (!in_interrupt())
xhci_dbg(xhci, "// Write event ring dequeue pointer\n");
xhci_dbg(xhci, "// Write event ring dequeue pointer, preserving EHB bit\n");
xhci_write_64(xhci, ((u64) deq & (u64) ~ERST_PTR_MASK) | temp,
&xhci->ir_set->erst_dequeue);
}
Expand Down

0 comments on commit 2d83109

Please sign in to comment.