diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2008-04-14 12:17:10 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2008-04-25 00:16:53 -0400 |
commit | 58a97ffeb2297f154659f339d77eb3f32c4d8b3e (patch) | |
tree | 2ca171b7f720769007f9c9624b74ca4ad3442f02 | |
parent | b950bdbc67041412cb042e404938667204c7902c (diff) |
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: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/usb/core/driver.c | 1 | ||||
-rw-r--r-- | drivers/usb/host/ehci-hub.c | 17 | ||||
-rw-r--r-- | drivers/usb/host/ehci-pci.c | 2 | ||||
-rw-r--r-- | drivers/usb/host/isp116x-hcd.c | 2 | ||||
-rw-r--r-- | drivers/usb/host/ohci-hub.c | 5 | ||||
-rw-r--r-- | drivers/usb/host/uhci-hcd.c | 21 |
6 files changed, 18 insertions, 30 deletions
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 2ea333a43d65..edc31e13e95e 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c | |||
@@ -932,7 +932,6 @@ static int autosuspend_check(struct usb_device *udev, int reschedule) | |||
932 | * is disabled. Also fail if any interfaces require remote wakeup | 932 | * is disabled. Also fail if any interfaces require remote wakeup |
933 | * but it isn't available. | 933 | * but it isn't available. |
934 | */ | 934 | */ |
935 | udev->do_remote_wakeup = device_may_wakeup(&udev->dev); | ||
936 | if (udev->pm_usage_cnt > 0) | 935 | if (udev->pm_usage_cnt > 0) |
937 | return -EBUSY; | 936 | return -EBUSY; |
938 | if (udev->autosuspend_delay < 0 || udev->autosuspend_disabled) | 937 | if (udev->autosuspend_delay < 0 || udev->autosuspend_disabled) |
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 21ac3781f21a..536b433d24f7 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c | |||
@@ -30,6 +30,8 @@ | |||
30 | 30 | ||
31 | #ifdef CONFIG_PM | 31 | #ifdef CONFIG_PM |
32 | 32 | ||
33 | #define PORT_WAKE_BITS (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E) | ||
34 | |||
33 | static int ehci_hub_control( | 35 | static int ehci_hub_control( |
34 | struct usb_hcd *hcd, | 36 | struct usb_hcd *hcd, |
35 | u16 typeReq, | 37 | u16 typeReq, |
@@ -149,10 +151,10 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) | |||
149 | } | 151 | } |
150 | 152 | ||
151 | /* enable remote wakeup on all ports */ | 153 | /* enable remote wakeup on all ports */ |
152 | if (device_may_wakeup(&hcd->self.root_hub->dev)) | 154 | if (hcd->self.root_hub->do_remote_wakeup) |
153 | t2 |= PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E; | 155 | t2 |= PORT_WAKE_BITS; |
154 | else | 156 | else |
155 | t2 &= ~(PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E); | 157 | t2 &= ~PORT_WAKE_BITS; |
156 | 158 | ||
157 | if (t1 != t2) { | 159 | if (t1 != t2) { |
158 | ehci_vdbg (ehci, "port %d, %08x -> %08x\n", | 160 | ehci_vdbg (ehci, "port %d, %08x -> %08x\n", |
@@ -174,7 +176,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) | |||
174 | 176 | ||
175 | /* allow remote wakeup */ | 177 | /* allow remote wakeup */ |
176 | mask = INTR_MASK; | 178 | mask = INTR_MASK; |
177 | if (!device_may_wakeup(&hcd->self.root_hub->dev)) | 179 | if (!hcd->self.root_hub->do_remote_wakeup) |
178 | mask &= ~STS_PCD; | 180 | mask &= ~STS_PCD; |
179 | ehci_writel(ehci, mask, &ehci->regs->intr_enable); | 181 | ehci_writel(ehci, mask, &ehci->regs->intr_enable); |
180 | ehci_readl(ehci, &ehci->regs->intr_enable); | 182 | ehci_readl(ehci, &ehci->regs->intr_enable); |
@@ -232,8 +234,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd) | |||
232 | i = HCS_N_PORTS (ehci->hcs_params); | 234 | i = HCS_N_PORTS (ehci->hcs_params); |
233 | while (i--) { | 235 | while (i--) { |
234 | temp = ehci_readl(ehci, &ehci->regs->port_status [i]); | 236 | temp = ehci_readl(ehci, &ehci->regs->port_status [i]); |
235 | temp &= ~(PORT_RWC_BITS | 237 | temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); |
236 | | PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E); | ||
237 | if (test_bit(i, &ehci->bus_suspended) && | 238 | if (test_bit(i, &ehci->bus_suspended) && |
238 | (temp & PORT_SUSPEND)) { | 239 | (temp & PORT_SUSPEND)) { |
239 | ehci->reset_done [i] = jiffies + msecs_to_jiffies (20); | 240 | ehci->reset_done [i] = jiffies + msecs_to_jiffies (20); |
@@ -534,8 +535,6 @@ ehci_hub_descriptor ( | |||
534 | 535 | ||
535 | /*-------------------------------------------------------------------------*/ | 536 | /*-------------------------------------------------------------------------*/ |
536 | 537 | ||
537 | #define PORT_WAKE_BITS (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E) | ||
538 | |||
539 | static int ehci_hub_control ( | 538 | static int ehci_hub_control ( |
540 | struct usb_hcd *hcd, | 539 | struct usb_hcd *hcd, |
541 | u16 typeReq, | 540 | u16 typeReq, |
@@ -801,8 +800,6 @@ static int ehci_hub_control ( | |||
801 | if ((temp & PORT_PE) == 0 | 800 | if ((temp & PORT_PE) == 0 |
802 | || (temp & PORT_RESET) != 0) | 801 | || (temp & PORT_RESET) != 0) |
803 | goto error; | 802 | goto error; |
804 | if (device_may_wakeup(&hcd->self.root_hub->dev)) | ||
805 | temp |= PORT_WAKE_BITS; | ||
806 | ehci_writel(ehci, temp | PORT_SUSPEND, status_reg); | 803 | ehci_writel(ehci, temp | PORT_SUSPEND, status_reg); |
807 | break; | 804 | break; |
808 | case USB_PORT_FEAT_POWER: | 805 | case USB_PORT_FEAT_POWER: |
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index a0afc78b273e..88dad4b53131 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c | |||
@@ -300,7 +300,7 @@ static int ehci_pci_resume(struct usb_hcd *hcd) | |||
300 | if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) { | 300 | if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) { |
301 | int mask = INTR_MASK; | 301 | int mask = INTR_MASK; |
302 | 302 | ||
303 | if (!device_may_wakeup(&hcd->self.root_hub->dev)) | 303 | if (!hcd->self.root_hub->do_remote_wakeup) |
304 | mask &= ~STS_PCD; | 304 | mask &= ~STS_PCD; |
305 | ehci_writel(ehci, mask, &ehci->regs->intr_enable); | 305 | ehci_writel(ehci, mask, &ehci->regs->intr_enable); |
306 | ehci_readl(ehci, &ehci->regs->intr_enable); | 306 | ehci_readl(ehci, &ehci->regs->intr_enable); |
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index 66d773c726f6..20b9a0d07420 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c | |||
@@ -1400,7 +1400,7 @@ static int isp116x_bus_suspend(struct usb_hcd *hcd) | |||
1400 | spin_unlock_irqrestore(&isp116x->lock, flags); | 1400 | spin_unlock_irqrestore(&isp116x->lock, flags); |
1401 | val &= (~HCCONTROL_HCFS & ~HCCONTROL_RWE); | 1401 | val &= (~HCCONTROL_HCFS & ~HCCONTROL_RWE); |
1402 | val |= HCCONTROL_USB_SUSPEND; | 1402 | val |= HCCONTROL_USB_SUSPEND; |
1403 | if (device_may_wakeup(&hcd->self.root_hub->dev)) | 1403 | if (hcd->self.root_hub->do_remote_wakeup) |
1404 | val |= HCCONTROL_RWE; | 1404 | val |= HCCONTROL_RWE; |
1405 | /* Wait for usb transfers to finish */ | 1405 | /* Wait for usb transfers to finish */ |
1406 | msleep(2); | 1406 | msleep(2); |
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index 28d6d775eb5f..cf3e1d255639 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c | |||
@@ -103,10 +103,9 @@ __acquires(ohci->lock) | |||
103 | finish_unlinks (ohci, ohci_frame_no(ohci)); | 103 | finish_unlinks (ohci, ohci_frame_no(ohci)); |
104 | 104 | ||
105 | /* maybe resume can wake root hub */ | 105 | /* maybe resume can wake root hub */ |
106 | if (device_may_wakeup(&ohci_to_hcd(ohci)->self.root_hub->dev) || | 106 | if (ohci_to_hcd(ohci)->self.root_hub->do_remote_wakeup || autostop) { |
107 | autostop) | ||
108 | ohci->hc_control |= OHCI_CTRL_RWE; | 107 | ohci->hc_control |= OHCI_CTRL_RWE; |
109 | else { | 108 | } else { |
110 | ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrdisable); | 109 | ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrdisable); |
111 | ohci->hc_control &= ~OHCI_CTRL_RWE; | 110 | ohci->hc_control &= ~OHCI_CTRL_RWE; |
112 | } | 111 | } |
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index fec9872dd9dc..f65d5a858733 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c | |||
@@ -262,20 +262,12 @@ __acquires(uhci->lock) | |||
262 | { | 262 | { |
263 | int auto_stop; | 263 | int auto_stop; |
264 | int int_enable, egsm_enable; | 264 | int int_enable, egsm_enable; |
265 | struct usb_device *rhdev = uhci_to_hcd(uhci)->self.root_hub; | ||
265 | 266 | ||
266 | auto_stop = (new_state == UHCI_RH_AUTO_STOPPED); | 267 | auto_stop = (new_state == UHCI_RH_AUTO_STOPPED); |
267 | dev_dbg(&uhci_to_hcd(uhci)->self.root_hub->dev, | 268 | dev_dbg(&rhdev->dev, "%s%s\n", __func__, |
268 | "%s%s\n", __FUNCTION__, | ||
269 | (auto_stop ? " (auto-stop)" : "")); | 269 | (auto_stop ? " (auto-stop)" : "")); |
270 | 270 | ||
271 | /* If we get a suspend request when we're already auto-stopped | ||
272 | * then there's nothing to do. | ||
273 | */ | ||
274 | if (uhci->rh_state == UHCI_RH_AUTO_STOPPED) { | ||
275 | uhci->rh_state = new_state; | ||
276 | return; | ||
277 | } | ||
278 | |||
279 | /* Enable resume-detect interrupts if they work. | 271 | /* Enable resume-detect interrupts if they work. |
280 | * Then enter Global Suspend mode if _it_ works, still configured. | 272 | * Then enter Global Suspend mode if _it_ works, still configured. |
281 | */ | 273 | */ |
@@ -285,8 +277,10 @@ __acquires(uhci->lock) | |||
285 | if (remote_wakeup_is_broken(uhci)) | 277 | if (remote_wakeup_is_broken(uhci)) |
286 | egsm_enable = 0; | 278 | egsm_enable = 0; |
287 | if (resume_detect_interrupts_are_broken(uhci) || !egsm_enable || | 279 | if (resume_detect_interrupts_are_broken(uhci) || !egsm_enable || |
288 | !device_may_wakeup( | 280 | #ifdef CONFIG_PM |
289 | &uhci_to_hcd(uhci)->self.root_hub->dev)) | 281 | (!auto_stop && !rhdev->do_remote_wakeup) || |
282 | #endif | ||
283 | (auto_stop && !device_may_wakeup(&rhdev->dev))) | ||
290 | uhci->working_RD = int_enable = 0; | 284 | uhci->working_RD = int_enable = 0; |
291 | 285 | ||
292 | outw(int_enable, uhci->io_addr + USBINTR); | 286 | outw(int_enable, uhci->io_addr + USBINTR); |
@@ -308,8 +302,7 @@ __acquires(uhci->lock) | |||
308 | return; | 302 | return; |
309 | } | 303 | } |
310 | if (!(inw(uhci->io_addr + USBSTS) & USBSTS_HCH)) | 304 | if (!(inw(uhci->io_addr + USBSTS) & USBSTS_HCH)) |
311 | dev_warn(&uhci_to_hcd(uhci)->self.root_hub->dev, | 305 | dev_warn(uhci_dev(uhci), "Controller not stopped yet!\n"); |
312 | "Controller not stopped yet!\n"); | ||
313 | 306 | ||
314 | uhci_get_current_frame_number(uhci); | 307 | uhci_get_current_frame_number(uhci); |
315 | 308 | ||