aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2008-04-14 12:17:10 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2008-04-25 00:16:53 -0400
commit58a97ffeb2297f154659f339d77eb3f32c4d8b3e (patch)
tree2ca171b7f720769007f9c9624b74ca4ad3442f02
parentb950bdbc67041412cb042e404938667204c7902c (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.c1
-rw-r--r--drivers/usb/host/ehci-hub.c17
-rw-r--r--drivers/usb/host/ehci-pci.c2
-rw-r--r--drivers/usb/host/isp116x-hcd.c2
-rw-r--r--drivers/usb/host/ohci-hub.c5
-rw-r--r--drivers/usb/host/uhci-hcd.c21
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
33static int ehci_hub_control( 35static 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
539static int ehci_hub_control ( 538static 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