Commit 58a97ffe authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman

USB: HCDs use the do_remote_wakeup flag

When a USB device is suspended, whether or not it is enabled for
remote wakeup depends on the device_may_wakeup() setting.  The setting
is then saved in the do_remote_wakeup flag.

Later on, however, the device_may_wakeup() value can change because of
user activity.  So when testing whether a suspended device is or
should be enabled for remote wakeup, we should always test
do_remote_wakeup instead of device_may_wakeup().  This patch (as1076)
makes that change for root hubs in several places.

The patch also adjusts uhci-hcd so that when an autostopped controller
is suspended, the remote wakeup setting agrees with the value recorded
in the root hub's do_remote_wakeup flag.

And the patch adjusts ehci-hcd so that wakeup events on selectively
suspended ports (i.e., the bus itself isn't suspended) don't turn on
the PME# wakeup signal.
Signed-off-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent b950bdbc
...@@ -932,7 +932,6 @@ static int autosuspend_check(struct usb_device *udev, int reschedule) ...@@ -932,7 +932,6 @@ static int autosuspend_check(struct usb_device *udev, int reschedule)
* is disabled. Also fail if any interfaces require remote wakeup * is disabled. Also fail if any interfaces require remote wakeup
* but it isn't available. * but it isn't available.
*/ */
udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
if (udev->pm_usage_cnt > 0) if (udev->pm_usage_cnt > 0)
return -EBUSY; return -EBUSY;
if (udev->autosuspend_delay < 0 || udev->autosuspend_disabled) if (udev->autosuspend_delay < 0 || udev->autosuspend_disabled)
......
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
#ifdef CONFIG_PM #ifdef CONFIG_PM
#define PORT_WAKE_BITS (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E)
static int ehci_hub_control( static int ehci_hub_control(
struct usb_hcd *hcd, struct usb_hcd *hcd,
u16 typeReq, u16 typeReq,
...@@ -149,10 +151,10 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) ...@@ -149,10 +151,10 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
} }
/* enable remote wakeup on all ports */ /* enable remote wakeup on all ports */
if (device_may_wakeup(&hcd->self.root_hub->dev)) if (hcd->self.root_hub->do_remote_wakeup)
t2 |= PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E; t2 |= PORT_WAKE_BITS;
else else
t2 &= ~(PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E); t2 &= ~PORT_WAKE_BITS;
if (t1 != t2) { if (t1 != t2) {
ehci_vdbg (ehci, "port %d, %08x -> %08x\n", ehci_vdbg (ehci, "port %d, %08x -> %08x\n",
...@@ -174,7 +176,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) ...@@ -174,7 +176,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
/* allow remote wakeup */ /* allow remote wakeup */
mask = INTR_MASK; mask = INTR_MASK;
if (!device_may_wakeup(&hcd->self.root_hub->dev)) if (!hcd->self.root_hub->do_remote_wakeup)
mask &= ~STS_PCD; mask &= ~STS_PCD;
ehci_writel(ehci, mask, &ehci->regs->intr_enable); ehci_writel(ehci, mask, &ehci->regs->intr_enable);
ehci_readl(ehci, &ehci->regs->intr_enable); ehci_readl(ehci, &ehci->regs->intr_enable);
...@@ -232,8 +234,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd) ...@@ -232,8 +234,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
i = HCS_N_PORTS (ehci->hcs_params); i = HCS_N_PORTS (ehci->hcs_params);
while (i--) { while (i--) {
temp = ehci_readl(ehci, &ehci->regs->port_status [i]); temp = ehci_readl(ehci, &ehci->regs->port_status [i]);
temp &= ~(PORT_RWC_BITS temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
| PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E);
if (test_bit(i, &ehci->bus_suspended) && if (test_bit(i, &ehci->bus_suspended) &&
(temp & PORT_SUSPEND)) { (temp & PORT_SUSPEND)) {
ehci->reset_done [i] = jiffies + msecs_to_jiffies (20); ehci->reset_done [i] = jiffies + msecs_to_jiffies (20);
...@@ -534,8 +535,6 @@ ehci_hub_descriptor ( ...@@ -534,8 +535,6 @@ ehci_hub_descriptor (
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
#define PORT_WAKE_BITS (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E)
static int ehci_hub_control ( static int ehci_hub_control (
struct usb_hcd *hcd, struct usb_hcd *hcd,
u16 typeReq, u16 typeReq,
...@@ -801,8 +800,6 @@ static int ehci_hub_control ( ...@@ -801,8 +800,6 @@ static int ehci_hub_control (
if ((temp & PORT_PE) == 0 if ((temp & PORT_PE) == 0
|| (temp & PORT_RESET) != 0) || (temp & PORT_RESET) != 0)
goto error; goto error;
if (device_may_wakeup(&hcd->self.root_hub->dev))
temp |= PORT_WAKE_BITS;
ehci_writel(ehci, temp | PORT_SUSPEND, status_reg); ehci_writel(ehci, temp | PORT_SUSPEND, status_reg);
break; break;
case USB_PORT_FEAT_POWER: case USB_PORT_FEAT_POWER:
......
...@@ -300,7 +300,7 @@ static int ehci_pci_resume(struct usb_hcd *hcd) ...@@ -300,7 +300,7 @@ static int ehci_pci_resume(struct usb_hcd *hcd)
if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) { if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) {
int mask = INTR_MASK; int mask = INTR_MASK;
if (!device_may_wakeup(&hcd->self.root_hub->dev)) if (!hcd->self.root_hub->do_remote_wakeup)
mask &= ~STS_PCD; mask &= ~STS_PCD;
ehci_writel(ehci, mask, &ehci->regs->intr_enable); ehci_writel(ehci, mask, &ehci->regs->intr_enable);
ehci_readl(ehci, &ehci->regs->intr_enable); ehci_readl(ehci, &ehci->regs->intr_enable);
......
...@@ -1400,7 +1400,7 @@ static int isp116x_bus_suspend(struct usb_hcd *hcd) ...@@ -1400,7 +1400,7 @@ static int isp116x_bus_suspend(struct usb_hcd *hcd)
spin_unlock_irqrestore(&isp116x->lock, flags); spin_unlock_irqrestore(&isp116x->lock, flags);
val &= (~HCCONTROL_HCFS & ~HCCONTROL_RWE); val &= (~HCCONTROL_HCFS & ~HCCONTROL_RWE);
val |= HCCONTROL_USB_SUSPEND; val |= HCCONTROL_USB_SUSPEND;
if (device_may_wakeup(&hcd->self.root_hub->dev)) if (hcd->self.root_hub->do_remote_wakeup)
val |= HCCONTROL_RWE; val |= HCCONTROL_RWE;
/* Wait for usb transfers to finish */ /* Wait for usb transfers to finish */
msleep(2); msleep(2);
......
...@@ -103,10 +103,9 @@ __acquires(ohci->lock) ...@@ -103,10 +103,9 @@ __acquires(ohci->lock)
finish_unlinks (ohci, ohci_frame_no(ohci)); finish_unlinks (ohci, ohci_frame_no(ohci));
/* maybe resume can wake root hub */ /* maybe resume can wake root hub */
if (device_may_wakeup(&ohci_to_hcd(ohci)->self.root_hub->dev) || if (ohci_to_hcd(ohci)->self.root_hub->do_remote_wakeup || autostop) {
autostop)
ohci->hc_control |= OHCI_CTRL_RWE; ohci->hc_control |= OHCI_CTRL_RWE;
else { } else {
ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrdisable); ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrdisable);
ohci->hc_control &= ~OHCI_CTRL_RWE; ohci->hc_control &= ~OHCI_CTRL_RWE;
} }
......
...@@ -262,20 +262,12 @@ __acquires(uhci->lock) ...@@ -262,20 +262,12 @@ __acquires(uhci->lock)
{ {
int auto_stop; int auto_stop;
int int_enable, egsm_enable; int int_enable, egsm_enable;
struct usb_device *rhdev = uhci_to_hcd(uhci)->self.root_hub;
auto_stop = (new_state == UHCI_RH_AUTO_STOPPED); auto_stop = (new_state == UHCI_RH_AUTO_STOPPED);
dev_dbg(&uhci_to_hcd(uhci)->self.root_hub->dev, dev_dbg(&rhdev->dev, "%s%s\n", __func__,
"%s%s\n", __FUNCTION__,
(auto_stop ? " (auto-stop)" : "")); (auto_stop ? " (auto-stop)" : ""));
/* If we get a suspend request when we're already auto-stopped
* then there's nothing to do.
*/
if (uhci->rh_state == UHCI_RH_AUTO_STOPPED) {
uhci->rh_state = new_state;
return;
}
/* Enable resume-detect interrupts if they work. /* Enable resume-detect interrupts if they work.
* Then enter Global Suspend mode if _it_ works, still configured. * Then enter Global Suspend mode if _it_ works, still configured.
*/ */
...@@ -285,8 +277,10 @@ __acquires(uhci->lock) ...@@ -285,8 +277,10 @@ __acquires(uhci->lock)
if (remote_wakeup_is_broken(uhci)) if (remote_wakeup_is_broken(uhci))
egsm_enable = 0; egsm_enable = 0;
if (resume_detect_interrupts_are_broken(uhci) || !egsm_enable || if (resume_detect_interrupts_are_broken(uhci) || !egsm_enable ||
!device_may_wakeup( #ifdef CONFIG_PM
&uhci_to_hcd(uhci)->self.root_hub->dev)) (!auto_stop && !rhdev->do_remote_wakeup) ||
#endif
(auto_stop && !device_may_wakeup(&rhdev->dev)))
uhci->working_RD = int_enable = 0; uhci->working_RD = int_enable = 0;
outw(int_enable, uhci->io_addr + USBINTR); outw(int_enable, uhci->io_addr + USBINTR);
...@@ -308,8 +302,7 @@ __acquires(uhci->lock) ...@@ -308,8 +302,7 @@ __acquires(uhci->lock)
return; return;
} }
if (!(inw(uhci->io_addr + USBSTS) & USBSTS_HCH)) if (!(inw(uhci->io_addr + USBSTS) & USBSTS_HCH))
dev_warn(&uhci_to_hcd(uhci)->self.root_hub->dev, dev_warn(uhci_dev(uhci), "Controller not stopped yet!\n");
"Controller not stopped yet!\n");
uhci_get_current_frame_number(uhci); uhci_get_current_frame_number(uhci);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment