Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Alan Stern and committed by
Greg Kroah-Hartman
58a97ffe b950bdbc

+18 -30
-1
drivers/usb/core/driver.c
··· 932 932 * is disabled. Also fail if any interfaces require remote wakeup 933 933 * but it isn't available. 934 934 */ 935 - udev->do_remote_wakeup = device_may_wakeup(&udev->dev); 936 935 if (udev->pm_usage_cnt > 0) 937 936 return -EBUSY; 938 937 if (udev->autosuspend_delay < 0 || udev->autosuspend_disabled)
+7 -10
drivers/usb/host/ehci-hub.c
··· 30 30 31 31 #ifdef CONFIG_PM 32 32 33 + #define PORT_WAKE_BITS (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E) 34 + 33 35 static int ehci_hub_control( 34 36 struct usb_hcd *hcd, 35 37 u16 typeReq, ··· 151 149 } 152 150 153 151 /* enable remote wakeup on all ports */ 154 - if (device_may_wakeup(&hcd->self.root_hub->dev)) 155 - t2 |= PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E; 152 + if (hcd->self.root_hub->do_remote_wakeup) 153 + t2 |= PORT_WAKE_BITS; 156 154 else 157 - t2 &= ~(PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E); 155 + t2 &= ~PORT_WAKE_BITS; 158 156 159 157 if (t1 != t2) { 160 158 ehci_vdbg (ehci, "port %d, %08x -> %08x\n", ··· 176 174 177 175 /* allow remote wakeup */ 178 176 mask = INTR_MASK; 179 - if (!device_may_wakeup(&hcd->self.root_hub->dev)) 177 + if (!hcd->self.root_hub->do_remote_wakeup) 180 178 mask &= ~STS_PCD; 181 179 ehci_writel(ehci, mask, &ehci->regs->intr_enable); 182 180 ehci_readl(ehci, &ehci->regs->intr_enable); ··· 234 232 i = HCS_N_PORTS (ehci->hcs_params); 235 233 while (i--) { 236 234 temp = ehci_readl(ehci, &ehci->regs->port_status [i]); 237 - temp &= ~(PORT_RWC_BITS 238 - | PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E); 235 + temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); 239 236 if (test_bit(i, &ehci->bus_suspended) && 240 237 (temp & PORT_SUSPEND)) { 241 238 ehci->reset_done [i] = jiffies + msecs_to_jiffies (20); ··· 535 534 536 535 /*-------------------------------------------------------------------------*/ 537 536 538 - #define PORT_WAKE_BITS (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E) 539 - 540 537 static int ehci_hub_control ( 541 538 struct usb_hcd *hcd, 542 539 u16 typeReq, ··· 800 801 if ((temp & PORT_PE) == 0 801 802 || (temp & PORT_RESET) != 0) 802 803 goto error; 803 - if (device_may_wakeup(&hcd->self.root_hub->dev)) 804 - temp |= PORT_WAKE_BITS; 805 804 ehci_writel(ehci, temp | PORT_SUSPEND, status_reg); 806 805 break; 807 806 case USB_PORT_FEAT_POWER:
+1 -1
drivers/usb/host/ehci-pci.c
··· 300 300 if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) { 301 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 304 mask &= ~STS_PCD; 305 305 ehci_writel(ehci, mask, &ehci->regs->intr_enable); 306 306 ehci_readl(ehci, &ehci->regs->intr_enable);
+1 -1
drivers/usb/host/isp116x-hcd.c
··· 1400 1400 spin_unlock_irqrestore(&isp116x->lock, flags); 1401 1401 val &= (~HCCONTROL_HCFS & ~HCCONTROL_RWE); 1402 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 1404 val |= HCCONTROL_RWE; 1405 1405 /* Wait for usb transfers to finish */ 1406 1406 msleep(2);
+2 -3
drivers/usb/host/ohci-hub.c
··· 103 103 finish_unlinks (ohci, ohci_frame_no(ohci)); 104 104 105 105 /* maybe resume can wake root hub */ 106 - if (device_may_wakeup(&ohci_to_hcd(ohci)->self.root_hub->dev) || 107 - autostop) 106 + if (ohci_to_hcd(ohci)->self.root_hub->do_remote_wakeup || autostop) { 108 107 ohci->hc_control |= OHCI_CTRL_RWE; 109 - else { 108 + } else { 110 109 ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrdisable); 111 110 ohci->hc_control &= ~OHCI_CTRL_RWE; 112 111 }
+7 -14
drivers/usb/host/uhci-hcd.c
··· 262 262 { 263 263 int auto_stop; 264 264 int int_enable, egsm_enable; 265 + struct usb_device *rhdev = uhci_to_hcd(uhci)->self.root_hub; 265 266 266 267 auto_stop = (new_state == UHCI_RH_AUTO_STOPPED); 267 - dev_dbg(&uhci_to_hcd(uhci)->self.root_hub->dev, 268 - "%s%s\n", __FUNCTION__, 268 + dev_dbg(&rhdev->dev, "%s%s\n", __func__, 269 269 (auto_stop ? " (auto-stop)" : "")); 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 270 279 271 /* Enable resume-detect interrupts if they work. 280 272 * Then enter Global Suspend mode if _it_ works, still configured. ··· 277 285 if (remote_wakeup_is_broken(uhci)) 278 286 egsm_enable = 0; 279 287 if (resume_detect_interrupts_are_broken(uhci) || !egsm_enable || 280 - !device_may_wakeup( 281 - &uhci_to_hcd(uhci)->self.root_hub->dev)) 288 + #ifdef CONFIG_PM 289 + (!auto_stop && !rhdev->do_remote_wakeup) || 290 + #endif 291 + (auto_stop && !device_may_wakeup(&rhdev->dev))) 282 292 uhci->working_RD = int_enable = 0; 283 293 284 294 outw(int_enable, uhci->io_addr + USBINTR); ··· 302 308 return; 303 309 } 304 310 if (!(inw(uhci->io_addr + USBSTS) & USBSTS_HCH)) 305 - dev_warn(&uhci_to_hcd(uhci)->self.root_hub->dev, 306 - "Controller not stopped yet!\n"); 311 + dev_warn(uhci_dev(uhci), "Controller not stopped yet!\n"); 307 312 308 313 uhci_get_current_frame_number(uhci); 309 314