USB: EHCI hooks for high speed electrical tests
authorDavid Brownell <david-b@pacbell.net>
Fri, 17 Nov 2006 07:56:15 +0000 (23:56 -0800)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 1 Dec 2006 22:23:36 +0000 (14:23 -0800)
EHCI hooks for high speed electrical tests of the root hub ports.

The expectation is that a usermode program actually triggers the test,
making the same control request it would make for an external hub.
Tests for peripheral upstream ports would issue a different request.
In all cases, the hardware needs re-initialization before it could
be used "normally" again (e.g. unplug/replug, rmmod/modprobe).

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/host/ehci-hub.c

index 1b20722..7c170a2 100644 (file)
@@ -319,6 +319,7 @@ static int ehci_hub_control (
        u32             temp, status;
        unsigned long   flags;
        int             retval = 0;
+       unsigned        selector;
 
        /*
         * FIXME:  support SetPortFeatures USB_PORT_FEAT_INDICATOR.
@@ -506,6 +507,8 @@ static int ehci_hub_control (
                }
                break;
        case SetPortFeature:
+               selector = wIndex >> 8;
+               wIndex &= 0xff;
                if (!wIndex || wIndex > ports)
                        goto error;
                wIndex--;
@@ -559,6 +562,22 @@ static int ehci_hub_control (
                        }
                        writel (temp, &ehci->regs->port_status [wIndex]);
                        break;
+
+               /* For downstream facing ports (these):  one hub port is put
+                * into test mode according to USB2 11.24.2.13, then the hub
+                * must be reset (which for root hub now means rmmod+modprobe,
+                * or else system reboot).  See EHCI 2.3.9 and 4.14 for info
+                * about the EHCI-specific stuff.
+                */
+               case USB_PORT_FEAT_TEST:
+                       if (!selector || selector > 5)
+                               goto error;
+                       ehci_quiesce(ehci);
+                       ehci_halt(ehci);
+                       temp |= selector << 16;
+                       writel (temp, &ehci->regs->port_status [wIndex]);
+                       break;
+
                default:
                        goto error;
                }