Loading drivers/usb/host/xhci-ring.c +43 −17 Original line number Diff line number Diff line Loading @@ -2758,6 +2758,42 @@ static int xhci_handle_event(struct xhci_hcd *xhci) return 1; } /* * Update Event Ring Dequeue Pointer: * - When all events have finished * - To avoid "Event Ring Full Error" condition */ static void xhci_update_erst_dequeue(struct xhci_hcd *xhci, union xhci_trb *event_ring_deq) { u64 temp_64; dma_addr_t deq; temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); /* If necessary, update the HW's version of the event ring deq ptr. */ if (event_ring_deq != xhci->event_ring->dequeue) { deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg, xhci->event_ring->dequeue); if (deq == 0) xhci_warn(xhci, "WARN something wrong with SW event ring dequeue ptr\n"); /* * Per 4.9.4, Software writes to the ERDP register shall * always advance the Event Ring Dequeue Pointer value. */ if ((temp_64 & (u64) ~ERST_PTR_MASK) == ((u64) deq & (u64) ~ERST_PTR_MASK)) return; /* Update HC event ring dequeue pointer */ temp_64 &= ERST_PTR_MASK; temp_64 |= ((u64) deq & (u64) ~ERST_PTR_MASK); } /* Clear the event handler busy flag (RW1C) */ temp_64 |= ERST_EHB; xhci_write_64(xhci, temp_64, &xhci->ir_set->erst_dequeue); } /* * xHCI spec says we can get an interrupt, and if the HC has an error condition, * we might get bad data out of the event ring. Section 4.10.2.7 has a list of Loading @@ -2769,9 +2805,9 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd) union xhci_trb *event_ring_deq; irqreturn_t ret = IRQ_NONE; unsigned long flags; dma_addr_t deq; u64 temp_64; u32 status; int event_loop = 0; spin_lock_irqsave(&xhci->lock, flags); /* Check if the xHC generated the interrupt, or the irq is shared */ Loading Loading @@ -2825,24 +2861,14 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd) /* FIXME this should be a delayed service routine * that clears the EHB. */ while (xhci_handle_event(xhci) > 0) {} temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); /* If necessary, update the HW's version of the event ring deq ptr. */ if (event_ring_deq != xhci->event_ring->dequeue) { deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg, xhci->event_ring->dequeue); if (deq == 0) xhci_warn(xhci, "WARN something wrong with SW event " "ring dequeue ptr.\n"); /* Update HC event ring dequeue pointer */ temp_64 &= ERST_PTR_MASK; temp_64 |= ((u64) deq & (u64) ~ERST_PTR_MASK); while (xhci_handle_event(xhci) > 0) { if (event_loop++ < TRBS_PER_SEGMENT / 2) continue; xhci_update_erst_dequeue(xhci, event_ring_deq); event_loop = 0; } /* Clear the event handler busy flag (RW1C); event ring is empty. */ temp_64 |= ERST_EHB; xhci_write_64(xhci, temp_64, &xhci->ir_set->erst_dequeue); xhci_update_erst_dequeue(xhci, event_ring_deq); ret = IRQ_HANDLED; out: Loading Loading
drivers/usb/host/xhci-ring.c +43 −17 Original line number Diff line number Diff line Loading @@ -2758,6 +2758,42 @@ static int xhci_handle_event(struct xhci_hcd *xhci) return 1; } /* * Update Event Ring Dequeue Pointer: * - When all events have finished * - To avoid "Event Ring Full Error" condition */ static void xhci_update_erst_dequeue(struct xhci_hcd *xhci, union xhci_trb *event_ring_deq) { u64 temp_64; dma_addr_t deq; temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); /* If necessary, update the HW's version of the event ring deq ptr. */ if (event_ring_deq != xhci->event_ring->dequeue) { deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg, xhci->event_ring->dequeue); if (deq == 0) xhci_warn(xhci, "WARN something wrong with SW event ring dequeue ptr\n"); /* * Per 4.9.4, Software writes to the ERDP register shall * always advance the Event Ring Dequeue Pointer value. */ if ((temp_64 & (u64) ~ERST_PTR_MASK) == ((u64) deq & (u64) ~ERST_PTR_MASK)) return; /* Update HC event ring dequeue pointer */ temp_64 &= ERST_PTR_MASK; temp_64 |= ((u64) deq & (u64) ~ERST_PTR_MASK); } /* Clear the event handler busy flag (RW1C) */ temp_64 |= ERST_EHB; xhci_write_64(xhci, temp_64, &xhci->ir_set->erst_dequeue); } /* * xHCI spec says we can get an interrupt, and if the HC has an error condition, * we might get bad data out of the event ring. Section 4.10.2.7 has a list of Loading @@ -2769,9 +2805,9 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd) union xhci_trb *event_ring_deq; irqreturn_t ret = IRQ_NONE; unsigned long flags; dma_addr_t deq; u64 temp_64; u32 status; int event_loop = 0; spin_lock_irqsave(&xhci->lock, flags); /* Check if the xHC generated the interrupt, or the irq is shared */ Loading Loading @@ -2825,24 +2861,14 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd) /* FIXME this should be a delayed service routine * that clears the EHB. */ while (xhci_handle_event(xhci) > 0) {} temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); /* If necessary, update the HW's version of the event ring deq ptr. */ if (event_ring_deq != xhci->event_ring->dequeue) { deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg, xhci->event_ring->dequeue); if (deq == 0) xhci_warn(xhci, "WARN something wrong with SW event " "ring dequeue ptr.\n"); /* Update HC event ring dequeue pointer */ temp_64 &= ERST_PTR_MASK; temp_64 |= ((u64) deq & (u64) ~ERST_PTR_MASK); while (xhci_handle_event(xhci) > 0) { if (event_loop++ < TRBS_PER_SEGMENT / 2) continue; xhci_update_erst_dequeue(xhci, event_ring_deq); event_loop = 0; } /* Clear the event handler busy flag (RW1C); event ring is empty. */ temp_64 |= ERST_EHB; xhci_write_64(xhci, temp_64, &xhci->ir_set->erst_dequeue); xhci_update_erst_dequeue(xhci, event_ring_deq); ret = IRQ_HANDLED; out: Loading