Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 232648
b: refs/heads/master
c: 0029227
h: refs/heads/master
v: v3
  • Loading branch information
Andiry Xu authored and Sarah Sharp committed Jan 14, 2011
1 parent d2e244f commit 70f8ff1
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 33 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 7111ebc97ed53a32314011c85a6f235f0dab8ae8
refs/heads/master: 0029227f1bc30b6c809ae751f9e7af6cef900997
7 changes: 6 additions & 1 deletion trunk/drivers/usb/core/hcd-pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,12 @@ static int suspend_common(struct device *dev, bool do_wakeup)
return retval;
}

synchronize_irq(pci_dev->irq);
/* If MSI-X is enabled, the driver will have synchronized all vectors
* in pci_suspend(). If MSI or legacy PCI is enabled, that will be
* synchronized here.
*/
if (!hcd->msix_enabled)
synchronize_irq(pci_dev->irq);

/* Downstream ports from this root hub should already be quiesced, so
* there will be no DMA activity. Now we can shut down the upstream
Expand Down
46 changes: 15 additions & 31 deletions trunk/drivers/usb/host/xhci.c
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,8 @@ static int xhci_setup_msi(struct xhci_hcd *xhci)
static int xhci_setup_msix(struct xhci_hcd *xhci)
{
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.
Expand Down Expand Up @@ -265,6 +266,7 @@ static int xhci_setup_msix(struct xhci_hcd *xhci)
goto disable_msix;
}

hcd->msix_enabled = 1;
return ret;

disable_msix:
Expand All @@ -280,7 +282,8 @@ static int xhci_setup_msix(struct xhci_hcd *xhci)
/* Free any IRQs and disable MSI-X */
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);

Expand All @@ -292,6 +295,7 @@ static void xhci_cleanup_msix(struct xhci_hcd *xhci)
pci_disable_msi(pdev);
}

hcd->msix_enabled = 0;
return;
}

Expand Down Expand Up @@ -647,6 +651,7 @@ int xhci_suspend(struct xhci_hcd *xhci)
int rc = 0;
struct usb_hcd *hcd = xhci_to_hcd(xhci);
u32 command;
int i;

spin_lock_irq(&xhci->lock);
clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
Expand Down Expand Up @@ -677,10 +682,15 @@ int xhci_suspend(struct xhci_hcd *xhci)
spin_unlock_irq(&xhci->lock);
return -ETIMEDOUT;
}
/* step 5: remove core well power */
xhci_cleanup_msix(xhci);
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;
}

Expand All @@ -694,7 +704,6 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
{
u32 command, temp = 0;
struct usb_hcd *hcd = xhci_to_hcd(xhci);
struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
int old_state, retval;

old_state = hcd->state;
Expand Down Expand Up @@ -729,9 +738,8 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
xhci_dbg(xhci, "Stop HCD\n");
xhci_halt(xhci);
xhci_reset(xhci);
if (hibernated)
xhci_cleanup_msix(xhci);
spin_unlock_irq(&xhci->lock);
xhci_cleanup_msix(xhci);

#ifdef CONFIG_USB_XHCI_HCD_DEBUGGING
/* Tell the event ring poll function not to reschedule */
Expand Down Expand Up @@ -765,30 +773,6 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
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 */
command = xhci_readl(xhci, &xhci->op_regs->command);
command |= CMD_RUN;
Expand Down
1 change: 1 addition & 0 deletions trunk/include/linux/usb/hcd.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ struct usb_hcd {
/* Flags that get set only during HCD registration or removal. */
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? */

/* The next flag is a stopgap, to be removed when all the HCDs
* support the new root-hub polling mechanism. */
Expand Down

0 comments on commit 70f8ff1

Please sign in to comment.