|
@@ -176,6 +176,8 @@ static void check_and_reset_hc(struct uhci_hcd *uhci)
|
|
|
*/
|
|
|
static void configure_hc(struct uhci_hcd *uhci)
|
|
|
{
|
|
|
+ struct pci_dev *pdev = to_pci_dev(uhci_dev(uhci));
|
|
|
+
|
|
|
/* Set the frame length to the default: 1 ms exactly */
|
|
|
outb(USBSOF_DEFAULT, uhci->io_addr + USBSOF);
|
|
|
|
|
@@ -191,8 +193,11 @@ static void configure_hc(struct uhci_hcd *uhci)
|
|
|
mb();
|
|
|
|
|
|
/* Enable PIRQ */
|
|
|
- pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,
|
|
|
- USBLEGSUP_DEFAULT);
|
|
|
+ pci_write_config_word(pdev, USBLEGSUP, USBLEGSUP_DEFAULT);
|
|
|
+
|
|
|
+ /* Disable platform-specific non-PME# wakeup */
|
|
|
+ if (pdev->vendor == PCI_VENDOR_ID_INTEL)
|
|
|
+ pci_write_config_byte(pdev, USBRES_INTEL, 0);
|
|
|
}
|
|
|
|
|
|
|
|
@@ -791,6 +796,7 @@ static int uhci_rh_resume(struct usb_hcd *hcd)
|
|
|
static int uhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
|
|
|
{
|
|
|
struct uhci_hcd *uhci = hcd_to_uhci(hcd);
|
|
|
+ struct pci_dev *pdev = to_pci_dev(uhci_dev(uhci));
|
|
|
int rc = 0;
|
|
|
|
|
|
dev_dbg(uhci_dev(uhci), "%s\n", __func__);
|
|
@@ -808,11 +814,15 @@ static int uhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
|
|
|
/* All PCI host controllers are required to disable IRQ generation
|
|
|
* at the source, so we must turn off PIRQ.
|
|
|
*/
|
|
|
- pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0);
|
|
|
- mb();
|
|
|
+ pci_write_config_word(pdev, USBLEGSUP, 0);
|
|
|
clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
|
|
|
|
|
|
- /* FIXME: Enable non-PME# remote wakeup? */
|
|
|
+ /* Enable platform-specific non-PME# wakeup */
|
|
|
+ if (do_wakeup) {
|
|
|
+ if (pdev->vendor == PCI_VENDOR_ID_INTEL)
|
|
|
+ pci_write_config_byte(pdev, USBRES_INTEL,
|
|
|
+ USBPORT1EN | USBPORT2EN);
|
|
|
+ }
|
|
|
|
|
|
done_okay:
|
|
|
clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
|
|
@@ -831,7 +841,6 @@ static int uhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
|
|
|
* even if the controller was dead.
|
|
|
*/
|
|
|
set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
|
|
|
- mb();
|
|
|
|
|
|
spin_lock_irq(&uhci->lock);
|
|
|
|
|
@@ -839,8 +848,6 @@ static int uhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
|
|
|
if (hibernated)
|
|
|
uhci_hc_died(uhci);
|
|
|
|
|
|
- /* FIXME: Disable non-PME# remote wakeup? */
|
|
|
-
|
|
|
/* The firmware or a boot kernel may have changed the controller
|
|
|
* settings during a system wakeup. Check it and reconfigure
|
|
|
* to avoid problems.
|
|
@@ -850,12 +857,9 @@ static int uhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
|
|
|
/* If the controller was dead before, it's back alive now */
|
|
|
configure_hc(uhci);
|
|
|
|
|
|
- if (uhci->rh_state == UHCI_RH_RESET) {
|
|
|
-
|
|
|
- /* The controller had to be reset */
|
|
|
+ /* Tell the core if the controller had to be reset */
|
|
|
+ if (uhci->rh_state == UHCI_RH_RESET)
|
|
|
usb_root_hub_lost_power(hcd->self.root_hub);
|
|
|
- suspend_rh(uhci, UHCI_RH_SUSPENDED);
|
|
|
- }
|
|
|
|
|
|
spin_unlock_irq(&uhci->lock);
|
|
|
|