|
@@ -226,7 +226,8 @@ static int xhci_setup_msi(struct xhci_hcd *xhci)
|
|
static int xhci_setup_msix(struct xhci_hcd *xhci)
|
|
static int xhci_setup_msix(struct xhci_hcd *xhci)
|
|
{
|
|
{
|
|
int i, ret = 0;
|
|
int i, ret = 0;
|
|
- struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller);
|
|
|
|
|
|
+ struct usb_hcd *hcd = xhci_to_hcd(xhci);
|
|
|
|
+ struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
|
|
|
|
|
|
/*
|
|
/*
|
|
* calculate number of msi-x vectors supported.
|
|
* calculate number of msi-x vectors supported.
|
|
@@ -265,6 +266,7 @@ static int xhci_setup_msix(struct xhci_hcd *xhci)
|
|
goto disable_msix;
|
|
goto disable_msix;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ hcd->msix_enabled = 1;
|
|
return ret;
|
|
return ret;
|
|
|
|
|
|
disable_msix:
|
|
disable_msix:
|
|
@@ -280,7 +282,8 @@ free_entries:
|
|
/* Free any IRQs and disable MSI-X */
|
|
/* Free any IRQs and disable MSI-X */
|
|
static void xhci_cleanup_msix(struct xhci_hcd *xhci)
|
|
static void xhci_cleanup_msix(struct xhci_hcd *xhci)
|
|
{
|
|
{
|
|
- struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller);
|
|
|
|
|
|
+ struct usb_hcd *hcd = xhci_to_hcd(xhci);
|
|
|
|
+ struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
|
|
|
|
|
|
xhci_free_irq(xhci);
|
|
xhci_free_irq(xhci);
|
|
|
|
|
|
@@ -292,6 +295,7 @@ static void xhci_cleanup_msix(struct xhci_hcd *xhci)
|
|
pci_disable_msi(pdev);
|
|
pci_disable_msi(pdev);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ hcd->msix_enabled = 0;
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -647,6 +651,7 @@ int xhci_suspend(struct xhci_hcd *xhci)
|
|
int rc = 0;
|
|
int rc = 0;
|
|
struct usb_hcd *hcd = xhci_to_hcd(xhci);
|
|
struct usb_hcd *hcd = xhci_to_hcd(xhci);
|
|
u32 command;
|
|
u32 command;
|
|
|
|
+ int i;
|
|
|
|
|
|
spin_lock_irq(&xhci->lock);
|
|
spin_lock_irq(&xhci->lock);
|
|
clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
|
|
clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
|
|
@@ -677,10 +682,15 @@ int xhci_suspend(struct xhci_hcd *xhci)
|
|
spin_unlock_irq(&xhci->lock);
|
|
spin_unlock_irq(&xhci->lock);
|
|
return -ETIMEDOUT;
|
|
return -ETIMEDOUT;
|
|
}
|
|
}
|
|
- /* step 5: remove core well power */
|
|
|
|
- xhci_cleanup_msix(xhci);
|
|
|
|
spin_unlock_irq(&xhci->lock);
|
|
spin_unlock_irq(&xhci->lock);
|
|
|
|
|
|
|
|
+ /* step 5: remove core well power */
|
|
|
|
+ /* synchronize irq when using MSI-X */
|
|
|
|
+ if (xhci->msix_entries) {
|
|
|
|
+ for (i = 0; i < xhci->msix_count; i++)
|
|
|
|
+ synchronize_irq(xhci->msix_entries[i].vector);
|
|
|
|
+ }
|
|
|
|
+
|
|
return rc;
|
|
return rc;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -694,7 +704,6 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
|
|
{
|
|
{
|
|
u32 command, temp = 0;
|
|
u32 command, temp = 0;
|
|
struct usb_hcd *hcd = xhci_to_hcd(xhci);
|
|
struct usb_hcd *hcd = xhci_to_hcd(xhci);
|
|
- struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
|
|
|
|
int old_state, retval;
|
|
int old_state, retval;
|
|
|
|
|
|
old_state = hcd->state;
|
|
old_state = hcd->state;
|
|
@@ -729,9 +738,8 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
|
|
xhci_dbg(xhci, "Stop HCD\n");
|
|
xhci_dbg(xhci, "Stop HCD\n");
|
|
xhci_halt(xhci);
|
|
xhci_halt(xhci);
|
|
xhci_reset(xhci);
|
|
xhci_reset(xhci);
|
|
- if (hibernated)
|
|
|
|
- xhci_cleanup_msix(xhci);
|
|
|
|
spin_unlock_irq(&xhci->lock);
|
|
spin_unlock_irq(&xhci->lock);
|
|
|
|
+ xhci_cleanup_msix(xhci);
|
|
|
|
|
|
#ifdef CONFIG_USB_XHCI_HCD_DEBUGGING
|
|
#ifdef CONFIG_USB_XHCI_HCD_DEBUGGING
|
|
/* Tell the event ring poll function not to reschedule */
|
|
/* Tell the event ring poll function not to reschedule */
|
|
@@ -765,30 +773,6 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
|
|
return retval;
|
|
return retval;
|
|
}
|
|
}
|
|
|
|
|
|
- spin_unlock_irq(&xhci->lock);
|
|
|
|
- /* Re-setup MSI-X */
|
|
|
|
- if (hcd->irq)
|
|
|
|
- free_irq(hcd->irq, hcd);
|
|
|
|
- hcd->irq = -1;
|
|
|
|
-
|
|
|
|
- retval = xhci_setup_msix(xhci);
|
|
|
|
- if (retval)
|
|
|
|
- /* fall back to msi*/
|
|
|
|
- retval = xhci_setup_msi(xhci);
|
|
|
|
-
|
|
|
|
- if (retval) {
|
|
|
|
- /* fall back to legacy interrupt*/
|
|
|
|
- retval = request_irq(pdev->irq, &usb_hcd_irq, IRQF_SHARED,
|
|
|
|
- hcd->irq_descr, hcd);
|
|
|
|
- if (retval) {
|
|
|
|
- xhci_err(xhci, "request interrupt %d failed\n",
|
|
|
|
- pdev->irq);
|
|
|
|
- return retval;
|
|
|
|
- }
|
|
|
|
- hcd->irq = pdev->irq;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- spin_lock_irq(&xhci->lock);
|
|
|
|
/* step 4: set Run/Stop bit */
|
|
/* step 4: set Run/Stop bit */
|
|
command = xhci_readl(xhci, &xhci->op_regs->command);
|
|
command = xhci_readl(xhci, &xhci->op_regs->command);
|
|
command |= CMD_RUN;
|
|
command |= CMD_RUN;
|