EHCI: don't hide ports owned by the companion

This patch (as709) changes the way ehci-hcd presents port status
values for ports owned by the companion controller.  It no longer
hides the information; in particular, it allows the core to see the
disconnect event that occurs when a full- or low-speed device is
switched over to the companion.  This is required for the next patch
in this series.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Cc: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 12f881f..076474d 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -270,16 +270,14 @@
 	spin_lock_irqsave (&ehci->lock, flags);
 	for (i = 0; i < ports; i++) {
 		temp = ehci_readl(ehci, &ehci->regs->port_status [i]);
-		if (temp & PORT_OWNER) {
-			/* don't report this in GetPortStatus */
-			if (temp & PORT_CSC) {
-				temp &= ~PORT_RWC_BITS;
-				temp |= PORT_CSC;
-				ehci_writel(ehci, temp,
-					    &ehci->regs->port_status [i]);
-			}
-			continue;
-		}
+
+		/*
+		 * Return status information even for ports with OWNER set.
+		 * Otherwise khubd wouldn't see the disconnect event when a
+		 * high-speed device is switched over to the companion
+		 * controller by the user.
+		 */
+
 		if (!(temp & PORT_CONNECT))
 			ehci->reset_done [i] = 0;
 		if ((temp & mask) != 0
@@ -377,8 +375,13 @@
 			goto error;
 		wIndex--;
 		temp = ehci_readl(ehci, status_reg);
-		if (temp & PORT_OWNER)
-			break;
+
+		/*
+		 * Even if OWNER is set, so the port is owned by the
+		 * companion controller, khubd needs to be able to clear
+		 * the port-change status bits (especially
+		 * USB_PORT_FEAT_C_CONNECTION).
+		 */
 
 		switch (wValue) {
 		case USB_PORT_FEAT_ENABLE:
@@ -501,24 +504,27 @@
 					ehci_readl(ehci, status_reg));
 		}
 
-		// don't show wPortStatus if it's owned by a companion hc
-		if (!(temp & PORT_OWNER)) {
-			if (temp & PORT_CONNECT) {
-				status |= 1 << USB_PORT_FEAT_CONNECTION;
-				// status may be from integrated TT
-				status |= ehci_port_speed(ehci, temp);
-			}
-			if (temp & PORT_PE)
-				status |= 1 << USB_PORT_FEAT_ENABLE;
-			if (temp & (PORT_SUSPEND|PORT_RESUME))
-				status |= 1 << USB_PORT_FEAT_SUSPEND;
-			if (temp & PORT_OC)
-				status |= 1 << USB_PORT_FEAT_OVER_CURRENT;
-			if (temp & PORT_RESET)
-				status |= 1 << USB_PORT_FEAT_RESET;
-			if (temp & PORT_POWER)
-				status |= 1 << USB_PORT_FEAT_POWER;
+		/*
+		 * Even if OWNER is set, there's no harm letting khubd
+		 * see the wPortStatus values (they should all be 0 except
+		 * for PORT_POWER anyway).
+		 */
+
+		if (temp & PORT_CONNECT) {
+			status |= 1 << USB_PORT_FEAT_CONNECTION;
+			// status may be from integrated TT
+			status |= ehci_port_speed(ehci, temp);
 		}
+		if (temp & PORT_PE)
+			status |= 1 << USB_PORT_FEAT_ENABLE;
+		if (temp & (PORT_SUSPEND|PORT_RESUME))
+			status |= 1 << USB_PORT_FEAT_SUSPEND;
+		if (temp & PORT_OC)
+			status |= 1 << USB_PORT_FEAT_OVER_CURRENT;
+		if (temp & PORT_RESET)
+			status |= 1 << USB_PORT_FEAT_RESET;
+		if (temp & PORT_POWER)
+			status |= 1 << USB_PORT_FEAT_POWER;
 
 #ifndef	EHCI_VERBOSE_DEBUG
 	if (status & ~0xffff)	/* only if wPortChange is interesting */