From: Alan Stern Date: Tue, 16 Jan 2007 16:58:47 +0000 (-0500) Subject: EHCI: don't hide ports owned by the companion X-Git-Tag: v2.6.21-rc1~92^2~29^2~27 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=625b5c9a0069ef1b61feb3ce599b39f1b04b5666;p=linux-2.6 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 Cc: David Brownell Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 12f881ff4b..076474d95d 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -270,16 +270,14 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf) 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 @@ static int ehci_hub_control ( 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 @@ static int ehci_hub_control ( 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 */