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>

diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 2ea333a..edc31e1 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -932,7 +932,6 @@
 	 * 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)
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 21ac378..536b433 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -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 @@
 		}
 
 		/* 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 @@
 
 	/* 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 @@
 	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 @@
 
 /*-------------------------------------------------------------------------*/
 
-#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 @@
 			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:
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index a0afc78..88dad4b 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -300,7 +300,7 @@
 	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);
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index 66d773c..20b9a0d 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -1400,7 +1400,7 @@
 		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);
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index 28d6d77..cf3e1d2 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -103,10 +103,9 @@
 	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;
 	}
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index fec9872..f65d5a8 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -262,20 +262,12 @@
 {
 	int auto_stop;
 	int int_enable, egsm_enable;
+	struct usb_device *rhdev = uhci_to_hcd(uhci)->self.root_hub;
 
 	auto_stop = (new_state == UHCI_RH_AUTO_STOPPED);
-	dev_dbg(&uhci_to_hcd(uhci)->self.root_hub->dev,
-			"%s%s\n", __FUNCTION__,
+	dev_dbg(&rhdev->dev, "%s%s\n", __func__,
 			(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.
 	 * Then enter Global Suspend mode if _it_ works, still configured.
 	 */
@@ -285,8 +277,10 @@
 	if (remote_wakeup_is_broken(uhci))
 		egsm_enable = 0;
 	if (resume_detect_interrupts_are_broken(uhci) || !egsm_enable ||
-			!device_may_wakeup(
-				&uhci_to_hcd(uhci)->self.root_hub->dev))
+#ifdef CONFIG_PM
+			(!auto_stop && !rhdev->do_remote_wakeup) ||
+#endif
+			(auto_stop && !device_may_wakeup(&rhdev->dev)))
 		uhci->working_RD = int_enable = 0;
 
 	outw(int_enable, uhci->io_addr + USBINTR);
@@ -308,8 +302,7 @@
 			return;
 	}
 	if (!(inw(uhci->io_addr + USBSTS) & USBSTS_HCH))
-		dev_warn(&uhci_to_hcd(uhci)->self.root_hub->dev,
-			"Controller not stopped yet!\n");
+		dev_warn(uhci_dev(uhci), "Controller not stopped yet!\n");
 
 	uhci_get_current_frame_number(uhci);