blob: a41bb1d80958e81f3d91cf6962d6f08c64aa3517 [file] [log] [blame]
From 3c19b50440734aca43db7be3feea45aa431b9da4 Mon Sep 17 00:00:00 2001
From: Peter Chen <peter.chen@nxp.com>
Date: Wed, 17 May 2017 18:32:02 +0300
Subject: [PATCH 220/286] usb: host: xhci-ring: don't need to clear interrupt
pending for MSI enabled hcd
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>
(cherry picked from commit 6a29beef9d1b16c762e469d77e28c3de3f5c3dbb)
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
---
drivers/usb/host/xhci-ring.c | 5 +----
drivers/usb/host/xhci.c | 5 +++--
include/linux/usb/hcd.h | 1 +
3 files changed, 5 insertions(+), 6 deletions(-)
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -2710,12 +2710,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);
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -401,9 +401,10 @@ static int xhci_try_enable_msi(struct us
/* 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");
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -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