We can skip many of the steps involved in handling a line-based interrupt when using MSIs. For example, we don't need to read the status register, or clear the interrupt flag in the status register. This removes six MMIO reads from the interrupt path. Signed-off-by: Matthew Wilcox <matthew.r.wilcox@xxxxxxxxx> --- drivers/usb/host/xhci-ring.c | 24 ++++++++++++++++++------ drivers/usb/host/xhci.c | 14 ++++++-------- drivers/usb/host/xhci.h | 2 +- 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index c3c2aec..b772b0e 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -2336,18 +2336,30 @@ hw_died: return IRQ_HANDLED; } -irqreturn_t xhci_msi_irq(int irq, struct usb_hcd *hcd) +irqreturn_t xhci_msi_irq(int irq, void *dev_id) { - irqreturn_t ret; - struct xhci_hcd *xhci; + struct xhci_erst *erst = dev_id; + struct xhci_hcd *xhci = erst->hcd; + irqreturn_t ret = IRQ_NONE; + u64 erdp; - xhci = hcd_to_xhci(hcd); - set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); + set_bit(HCD_FLAG_SAW_IRQ, &xhci->main_hcd->flags); if (xhci->shared_hcd) set_bit(HCD_FLAG_SAW_IRQ, &xhci->shared_hcd->flags); - ret = xhci_irq(hcd); + spin_lock(&xhci->lock); + while (xhci_handle_event(erst) > 0) { + ret = IRQ_HANDLED; + } + spin_unlock(&xhci->lock); + + if (ret == IRQ_NONE) + return ret; + erdp = xhci_trb_virt_to_dma(erst->ring->deq_seg, + erst->ring->dequeue); + erdp |= ERST_EHB; + xhci_write_64(xhci, erdp, &erst->ir_set->erst_dequeue); return ret; } diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 94c2000..0d9e7d6 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -191,10 +191,9 @@ static void xhci_free_irq(struct xhci_hcd *xhci) if (xhci->msix_entries) { for (i = 0; i < xhci->msix_count; i++) if (xhci->msix_entries[i].vector) - free_irq(xhci->msix_entries[i].vector, - xhci_to_hcd(xhci)); + free_irq(xhci->msix_entries[i].vector, &xhci->erst); } else if (pdev->irq >= 0) - free_irq(pdev->irq, xhci_to_hcd(xhci)); + free_irq(pdev->irq, &xhci->erst); return; } @@ -213,8 +212,8 @@ static int xhci_setup_msi(struct xhci_hcd *xhci) return ret; } - ret = request_irq(pdev->irq, (irq_handler_t)xhci_msi_irq, - 0, "xhci_hcd", xhci_to_hcd(xhci)); + ret = request_irq(pdev->irq, xhci_msi_irq, 0, "xhci_hcd", + &xhci->erst); if (ret) { xhci_err(xhci, "disable MSI interrupt\n"); pci_disable_msi(pdev); @@ -262,9 +261,8 @@ static int xhci_setup_msix(struct xhci_hcd *xhci) } for (i = 0; i < xhci->msix_count; i++) { - ret = request_irq(xhci->msix_entries[i].vector, - (irq_handler_t)xhci_msi_irq, - 0, "xhci_hcd", xhci_to_hcd(xhci)); + ret = request_irq(xhci->msix_entries[i].vector, xhci_msi_irq, + 0, "xhci_hcd", &xhci->erst); if (ret) goto disable_msix; } diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 45fa667..a3be33d 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1488,7 +1488,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated); int xhci_get_frame(struct usb_hcd *hcd); irqreturn_t xhci_irq(struct usb_hcd *hcd); -irqreturn_t xhci_msi_irq(int irq, struct usb_hcd *hcd); +irqreturn_t xhci_msi_irq(int irq, void *erst); int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev); void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev); int xhci_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev, -- 1.7.4.4 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html