diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2007-01-16 11:58:47 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-02-07 18:44:37 -0500 |
commit | 625b5c9a0069ef1b61feb3ce599b39f1b04b5666 (patch) | |
tree | 74fac9295b6240c2fbc394cc0289bc178fb004a3 /drivers/usb | |
parent | e6316565e568b3b5733be10cfca3c27259bef499 (diff) |
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>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/host/ehci-hub.c | 64 |
1 files changed, 35 insertions, 29 deletions
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 12f881ff4b23..076474d95dbf 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) | |||
270 | spin_lock_irqsave (&ehci->lock, flags); | 270 | spin_lock_irqsave (&ehci->lock, flags); |
271 | for (i = 0; i < ports; i++) { | 271 | for (i = 0; i < ports; i++) { |
272 | temp = ehci_readl(ehci, &ehci->regs->port_status [i]); | 272 | temp = ehci_readl(ehci, &ehci->regs->port_status [i]); |
273 | if (temp & PORT_OWNER) { | 273 | |
274 | /* don't report this in GetPortStatus */ | 274 | /* |
275 | if (temp & PORT_CSC) { | 275 | * Return status information even for ports with OWNER set. |
276 | temp &= ~PORT_RWC_BITS; | 276 | * Otherwise khubd wouldn't see the disconnect event when a |
277 | temp |= PORT_CSC; | 277 | * high-speed device is switched over to the companion |
278 | ehci_writel(ehci, temp, | 278 | * controller by the user. |
279 | &ehci->regs->port_status [i]); | 279 | */ |
280 | } | 280 | |
281 | continue; | ||
282 | } | ||
283 | if (!(temp & PORT_CONNECT)) | 281 | if (!(temp & PORT_CONNECT)) |
284 | ehci->reset_done [i] = 0; | 282 | ehci->reset_done [i] = 0; |
285 | if ((temp & mask) != 0 | 283 | if ((temp & mask) != 0 |
@@ -377,8 +375,13 @@ static int ehci_hub_control ( | |||
377 | goto error; | 375 | goto error; |
378 | wIndex--; | 376 | wIndex--; |
379 | temp = ehci_readl(ehci, status_reg); | 377 | temp = ehci_readl(ehci, status_reg); |
380 | if (temp & PORT_OWNER) | 378 | |
381 | break; | 379 | /* |
380 | * Even if OWNER is set, so the port is owned by the | ||
381 | * companion controller, khubd needs to be able to clear | ||
382 | * the port-change status bits (especially | ||
383 | * USB_PORT_FEAT_C_CONNECTION). | ||
384 | */ | ||
382 | 385 | ||
383 | switch (wValue) { | 386 | switch (wValue) { |
384 | case USB_PORT_FEAT_ENABLE: | 387 | case USB_PORT_FEAT_ENABLE: |
@@ -501,24 +504,27 @@ static int ehci_hub_control ( | |||
501 | ehci_readl(ehci, status_reg)); | 504 | ehci_readl(ehci, status_reg)); |
502 | } | 505 | } |
503 | 506 | ||
504 | // don't show wPortStatus if it's owned by a companion hc | 507 | /* |
505 | if (!(temp & PORT_OWNER)) { | 508 | * Even if OWNER is set, there's no harm letting khubd |
506 | if (temp & PORT_CONNECT) { | 509 | * see the wPortStatus values (they should all be 0 except |
507 | status |= 1 << USB_PORT_FEAT_CONNECTION; | 510 | * for PORT_POWER anyway). |
508 | // status may be from integrated TT | 511 | */ |
509 | status |= ehci_port_speed(ehci, temp); | 512 | |
510 | } | 513 | if (temp & PORT_CONNECT) { |
511 | if (temp & PORT_PE) | 514 | status |= 1 << USB_PORT_FEAT_CONNECTION; |
512 | status |= 1 << USB_PORT_FEAT_ENABLE; | 515 | // status may be from integrated TT |
513 | if (temp & (PORT_SUSPEND|PORT_RESUME)) | 516 | status |= ehci_port_speed(ehci, temp); |
514 | status |= 1 << USB_PORT_FEAT_SUSPEND; | ||
515 | if (temp & PORT_OC) | ||
516 | status |= 1 << USB_PORT_FEAT_OVER_CURRENT; | ||
517 | if (temp & PORT_RESET) | ||
518 | status |= 1 << USB_PORT_FEAT_RESET; | ||
519 | if (temp & PORT_POWER) | ||
520 | status |= 1 << USB_PORT_FEAT_POWER; | ||
521 | } | 517 | } |
518 | if (temp & PORT_PE) | ||
519 | status |= 1 << USB_PORT_FEAT_ENABLE; | ||
520 | if (temp & (PORT_SUSPEND|PORT_RESUME)) | ||
521 | status |= 1 << USB_PORT_FEAT_SUSPEND; | ||
522 | if (temp & PORT_OC) | ||
523 | status |= 1 << USB_PORT_FEAT_OVER_CURRENT; | ||
524 | if (temp & PORT_RESET) | ||
525 | status |= 1 << USB_PORT_FEAT_RESET; | ||
526 | if (temp & PORT_POWER) | ||
527 | status |= 1 << USB_PORT_FEAT_POWER; | ||
522 | 528 | ||
523 | #ifndef EHCI_VERBOSE_DEBUG | 529 | #ifndef EHCI_VERBOSE_DEBUG |
524 | if (status & ~0xffff) /* only if wPortChange is interesting */ | 530 | if (status & ~0xffff) /* only if wPortChange is interesting */ |