aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2009-07-27 15:03:40 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-07-28 17:31:12 -0400
commit2d83109be62edd9647c45d7ed2b916b03974a7ec (patch)
tree77320544c5000b29b61140bde6fa6d1688171cc1 /drivers/usb/host
parent62889610f5591005bed9517360e17531684f72d0 (diff)
USB: xhci: Correct Event Handler Busy flag usage.
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 <sarah.a.sharp@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host')
-rw-r--r--drivers/usb/host/xhci-hcd.c4
-rw-r--r--drivers/usb/host/xhci-ring.c6
2 files changed, 7 insertions, 3 deletions
diff --git a/drivers/usb/host/xhci-hcd.c b/drivers/usb/host/xhci-hcd.c
index e15773598e4e..2e8e5bf6b6ca 100644
--- a/drivers/usb/host/xhci-hcd.c
+++ b/drivers/usb/host/xhci-hcd.c
@@ -249,9 +249,9 @@ static void xhci_work(struct xhci_hcd *xhci)
249 /* FIXME this should be a delayed service routine that clears the EHB */ 249 /* FIXME this should be a delayed service routine that clears the EHB */
250 xhci_handle_event(xhci); 250 xhci_handle_event(xhci);
251 251
252 /* Clear the event handler busy flag; the event ring should be empty. */ 252 /* Clear the event handler busy flag (RW1C); the event ring should be empty. */
253 temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); 253 temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
254 xhci_write_64(xhci, temp_64 & ~ERST_EHB, &xhci->ir_set->erst_dequeue); 254 xhci_write_64(xhci, temp_64 | ERST_EHB, &xhci->ir_set->erst_dequeue);
255 /* Flush posted writes -- FIXME is this necessary? */ 255 /* Flush posted writes -- FIXME is this necessary? */
256 xhci_readl(xhci, &xhci->ir_set->irq_pending); 256 xhci_readl(xhci, &xhci->ir_set->irq_pending);
257} 257}
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 5dd3b1fd71c0..fe9541a89a3d 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -248,8 +248,12 @@ void xhci_set_hc_event_deq(struct xhci_hcd *xhci)
248 /* Update HC event ring dequeue pointer */ 248 /* Update HC event ring dequeue pointer */
249 temp = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); 249 temp = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
250 temp &= ERST_PTR_MASK; 250 temp &= ERST_PTR_MASK;
251 /* Don't clear the EHB bit (which is RW1C) because
252 * there might be more events to service.
253 */
254 temp &= ~ERST_EHB;
251 if (!in_interrupt()) 255 if (!in_interrupt())
252 xhci_dbg(xhci, "// Write event ring dequeue pointer\n"); 256 xhci_dbg(xhci, "// Write event ring dequeue pointer, preserving EHB bit\n");
253 xhci_write_64(xhci, ((u64) deq & (u64) ~ERST_PTR_MASK) | temp, 257 xhci_write_64(xhci, ((u64) deq & (u64) ~ERST_PTR_MASK) | temp,
254 &xhci->ir_set->erst_dequeue); 258 &xhci->ir_set->erst_dequeue);
255} 259}