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

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
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -932,7 +932,6 @@ static int autosuspend_check(struct usb_device *udev, int reschedule)
	 * is disabled.  Also fail if any interfaces require remote wakeup
	 * but it isn't available.
	 */
	udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
	if (udev->pm_usage_cnt > 0)
		return -EBUSY;
	if (udev->autosuspend_delay < 0 || udev->autosuspend_disabled)
+7 −10
Original line number Diff line number Diff line
@@ -30,6 +30,8 @@

#ifdef	CONFIG_PM

#define	PORT_WAKE_BITS	(PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E)

static int ehci_hub_control(
	struct usb_hcd	*hcd,
	u16		typeReq,
@@ -149,10 +151,10 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
		}

		/* enable remote wakeup on all ports */
		if (device_may_wakeup(&hcd->self.root_hub->dev))
			t2 |= PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E;
		if (hcd->self.root_hub->do_remote_wakeup)
			t2 |= PORT_WAKE_BITS;
		else
			t2 &= ~(PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E);
			t2 &= ~PORT_WAKE_BITS;

		if (t1 != t2) {
			ehci_vdbg (ehci, "port %d, %08x -> %08x\n",
@@ -174,7 +176,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)

	/* allow remote wakeup */
	mask = INTR_MASK;
	if (!device_may_wakeup(&hcd->self.root_hub->dev))
	if (!hcd->self.root_hub->do_remote_wakeup)
		mask &= ~STS_PCD;
	ehci_writel(ehci, mask, &ehci->regs->intr_enable);
	ehci_readl(ehci, &ehci->regs->intr_enable);
@@ -232,8 +234,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
	i = HCS_N_PORTS (ehci->hcs_params);
	while (i--) {
		temp = ehci_readl(ehci, &ehci->regs->port_status [i]);
		temp &= ~(PORT_RWC_BITS
			| PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E);
		temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
		if (test_bit(i, &ehci->bus_suspended) &&
				(temp & PORT_SUSPEND)) {
			ehci->reset_done [i] = jiffies + msecs_to_jiffies (20);
@@ -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 (
	struct usb_hcd	*hcd,
	u16		typeReq,
@@ -801,8 +800,6 @@ static int ehci_hub_control (
			if ((temp & PORT_PE) == 0
					|| (temp & PORT_RESET) != 0)
				goto error;
			if (device_may_wakeup(&hcd->self.root_hub->dev))
				temp |= PORT_WAKE_BITS;
			ehci_writel(ehci, temp | PORT_SUSPEND, status_reg);
			break;
		case USB_PORT_FEAT_POWER:
+1 −1
Original line number Diff line number Diff line
@@ -300,7 +300,7 @@ static int ehci_pci_resume(struct usb_hcd *hcd)
	if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) {
		int	mask = INTR_MASK;

		if (!device_may_wakeup(&hcd->self.root_hub->dev))
		if (!hcd->self.root_hub->do_remote_wakeup)
			mask &= ~STS_PCD;
		ehci_writel(ehci, mask, &ehci->regs->intr_enable);
		ehci_readl(ehci, &ehci->regs->intr_enable);
+1 −1
Original line number Diff line number Diff line
@@ -1400,7 +1400,7 @@ static int isp116x_bus_suspend(struct usb_hcd *hcd)
		spin_unlock_irqrestore(&isp116x->lock, flags);
		val &= (~HCCONTROL_HCFS & ~HCCONTROL_RWE);
		val |= HCCONTROL_USB_SUSPEND;
		if (device_may_wakeup(&hcd->self.root_hub->dev))
		if (hcd->self.root_hub->do_remote_wakeup)
			val |= HCCONTROL_RWE;
		/* Wait for usb transfers to finish */
		msleep(2);
+2 −3
Original line number Diff line number Diff line
@@ -103,10 +103,9 @@ __acquires(ohci->lock)
	finish_unlinks (ohci, ohci_frame_no(ohci));

	/* maybe resume can wake root hub */
	if (device_may_wakeup(&ohci_to_hcd(ohci)->self.root_hub->dev) ||
			autostop)
	if (ohci_to_hcd(ohci)->self.root_hub->do_remote_wakeup || autostop) {
		ohci->hc_control |= OHCI_CTRL_RWE;
	else {
	} else {
		ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrdisable);
		ohci->hc_control &= ~OHCI_CTRL_RWE;
	}
Loading