/* Update event ring dequeue pointer before dropping the lock */
        inc_deq(xhci, xhci->event_ring, true);
-       xhci_set_hc_event_deq(xhci);
 
        spin_unlock(&xhci->lock);
        /* Pass this up to the core */
                 */
                if (trb_comp_code == COMP_MISSED_INT || !ep->skip) {
                        inc_deq(xhci, xhci->event_ring, true);
-                       xhci_set_hc_event_deq(xhci);
                }
 
                if (ret) {
                return;
        }
 
-       if (update_ptrs) {
-               /* Update SW and HC event ring dequeue pointer */
+       if (update_ptrs)
+               /* Update SW event ring dequeue pointer */
                inc_deq(xhci, xhci->event_ring, true);
-               xhci_set_hc_event_deq(xhci);
-       }
+
        /* Are there more items on the event ring? */
        xhci_handle_event(xhci);
 }
        u32 status, irq_pending;
        union xhci_trb *trb;
        u64 temp_64;
+       union xhci_trb *event_ring_deq;
+       dma_addr_t deq;
 
        spin_lock(&xhci->lock);
        trb = xhci->event_ring->dequeue;
        irq_pending |= 0x3;
        xhci_writel(xhci, irq_pending, &xhci->ir_set->irq_pending);
 
-       if (xhci->xhc_state & XHCI_STATE_DYING)
+       if (xhci->xhc_state & XHCI_STATE_DYING) {
                xhci_dbg(xhci, "xHCI dying, ignoring interrupt. "
                                "Shouldn't IRQs be disabled?\n");
-       else
-               /* FIXME this should be a delayed service routine
-                * that clears the EHB.
+               /* Clear the event handler busy flag (RW1C);
+                * the event ring should be empty.
                 */
-               xhci_handle_event(xhci);
+               temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
+               xhci_write_64(xhci, temp_64 | ERST_EHB,
+                               &xhci->ir_set->erst_dequeue);
+               spin_unlock(&xhci->lock);
+
+               return IRQ_HANDLED;
+       }
+
+       event_ring_deq = xhci->event_ring->dequeue;
+       /* FIXME this should be a delayed service routine
+        * that clears the EHB.
+        */
+       xhci_handle_event(xhci);
 
-       /* Clear the event handler busy flag (RW1C); event ring is 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);
+       /* 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);
+       }
+
+       /* 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);
+
        spin_unlock(&xhci->lock);
 
        return IRQ_HANDLED;