usb: host: xhci-ring: don't need to clear interrupt pending for MSI enabled hcd
authorPeter Chen <peter.chen@nxp.com>
Wed, 17 May 2017 15:32:02 +0000 (18:32 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 18 May 2017 13:19:41 +0000 (15:19 +0200)
According to xHCI spec Figure 30: Interrupt Throttle Flow Diagram

If PCI Message Signaled Interrupts (MSI or MSI-X) are enabled,
        then the assertion of the Interrupt Pending (IP) flag in Figure 30
        generates a PCI Dword write. The IP flag is automatically cleared
        by the completion of the PCI write.

the MSI enabled HCs don't need to clear interrupt pending bit, but
hcd->irq = 0 doesn't equal to MSI enabled HCD. At some Dual-role
controller software designs, it sets hcd->irq as 0 to avoid HCD
requesting interrupt, and they want to decide when to call usb_hcd_irq
by software.

Signed-off-by: Peter Chen <peter.chen@nxp.com>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c
include/linux/usb/hcd.h

index 507ba77..0830b25 100644 (file)
@@ -2707,12 +2707,9 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
         */
        status |= STS_EINT;
        writel(status, &xhci->op_regs->status);
-       /* FIXME when MSI-X is supported and there are multiple vectors */
-       /* Clear the MSI-X event interrupt status */
 
-       if (hcd->irq) {
+       if (!hcd->msi_enabled) {
                u32 irq_pending;
-               /* Acknowledge the PCI interrupt */
                irq_pending = readl(&xhci->ir_set->irq_pending);
                irq_pending |= IMAN_IP;
                writel(irq_pending, &xhci->ir_set->irq_pending);
index 2d13102..71eb299 100644 (file)
@@ -359,9 +359,10 @@ static int xhci_try_enable_msi(struct usb_hcd *hcd)
                /* fall back to msi*/
                ret = xhci_setup_msi(xhci);
 
-       if (!ret)
-               /* hcd->irq is 0, we have MSI */
+       if (!ret) {
+               hcd->msi_enabled = 1;
                return 0;
+       }
 
        if (!pdev->irq) {
                xhci_err(xhci, "No msi-x/msi found and no IRQ in BIOS\n");
index a469999..50398b6 100644 (file)
@@ -148,6 +148,7 @@ struct usb_hcd {
        unsigned                rh_registered:1;/* is root hub registered? */
        unsigned                rh_pollable:1;  /* may we poll the root hub? */
        unsigned                msix_enabled:1; /* driver has MSI-X enabled? */
+       unsigned                msi_enabled:1;  /* driver has MSI enabled? */
        unsigned                remove_phy:1;   /* auto-remove USB phy */
 
        /* The next flag is a stopgap, to be removed when all the HCDs