ChangeSet 1.1722.83.20, 2004/06/04 15:14:11-07:00, [EMAIL PROTECTED]

[PATCH] USB: Debounce all connect change events

This patch makes the hub driver debounce all connection changes.  Right
now the driver only does so if the status happens to be CONNECTED at one
particular instant.  However, the whole point of debouncing is that the
connection is subject to transient interruptions until it has stabilized;
hence deciding whether to debounce based on a single initial test defeats
the entire purpose.

There are some additional smaller changes that go along with the major
one:

        Comments added to hub_port_connect_change() detailing the
        conditions under which it will be called.

        Don't clear the port's connect-changed feature if it wasn't
        set.

        Skip debouncing if there wasn't a physical connection change
        but only a logical port-enable change (or a firmware-download-
        induced device morph -- not yet implemented).

        Clear all the hub status change indicators in hub_events()
        before handling a connect change.  This will reduce syslog
        clutter from status change bits that remain set while khubd
        is busy taking care of a new device.

The patch includes no changes to the debounce routine itself.  Please
apply.


Signed-off-by: Alan Stern <[EMAIL PROTECTED]>
Signed-off-by: Greg Kroah-Hartman <[EMAIL PROTECTED]>


 drivers/usb/core/hub.c |   63 +++++++++++++++++++++++++++++++------------------
 1 files changed, 41 insertions(+), 22 deletions(-)


diff -Nru a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
--- a/drivers/usb/core/hub.c    Fri Jun 18 11:03:13 2004
+++ b/drivers/usb/core/hub.c    Fri Jun 18 11:03:13 2004
@@ -1486,7 +1486,14 @@
        }
        return remaining;
 }
- 
+
+/* Handle physical or logical connection change events.
+ * This routine is called when:
+ *     a port connection-change occurs;
+ *     a port enable-change occurs (often caused by EMI);
+ *     usb_reset_device() encounters changed descriptors (as from
+ *             a firmware download)
+ */
 static void hub_port_connect_change(struct usb_hub *hub, int port,
                                        u16 portstatus, u16 portchange)
 {
@@ -1497,9 +1504,6 @@
        dev_dbg (hub_dev,
                "port %d, status %04x, change %04x, %s\n",
                port + 1, portstatus, portchange, portspeed (portstatus));
- 
-       /* Clear the connection change status */
-       clear_port_feature(hdev, port + 1, USB_PORT_FEAT_C_CONNECTION);
 
        if (hub->has_indicators) {
                set_port_led(hdev, port + 1, HUB_LED_AUTO);
@@ -1510,6 +1514,18 @@
        if (hdev->children[port])
                usb_disconnect(&hdev->children[port]);
 
+       if (portchange & USB_PORT_STAT_C_CONNECTION) {
+               status = hub_port_debounce(hdev, port);
+               if (status == -ENOTCONN)
+                       portstatus = 0;
+               else if (status < 0) {
+                       dev_err (hub_dev,
+                               "connect-debounce failed, port %d disabled\n",
+                               port+1);
+                       goto done;
+               }
+       }
+
        /* Return now if nothing is connected */
        if (!(portstatus & USB_PORT_STAT_CONNECTION)) {
 
@@ -1523,13 +1539,6 @@
                        goto done;
                return;
        }
-  
-       if (hub_port_debounce(hdev, port)) {
-               dev_err (hub_dev,
-                       "connect-debounce failed, port %d disabled\n",
-                       port+1);
-               goto done;
-       }
 
        for (i = 0; i < SET_CONFIG_TRIES; i++) {
                struct usb_device *udev;
@@ -1631,6 +1640,7 @@
        u16 portstatus;
        u16 portchange;
        int i, ret;
+       int connect_change;
 
        /*
         *  We restart the list every time to avoid a deadlock with
@@ -1676,16 +1686,22 @@
 
                for (i = 0; i < hub->descriptor->bNbrPorts; i++) {
                        ret = hub_port_status(hdev, i, &portstatus, &portchange);
-                       if (ret < 0) {
+                       if (ret < 0)
                                continue;
-                       }
+                       connect_change = 0;
 
                        if (portchange & USB_PORT_STAT_C_CONNECTION) {
-                               hub_port_connect_change(hub, i, portstatus, 
portchange);
-                       } else if (portchange & USB_PORT_STAT_C_ENABLE) {
-                               dev_dbg (hub_dev,
-                                       "port %d enable change, status %08x\n",
-                                       i + 1, portstatus);
+                               clear_port_feature(hdev,
+                                       i + 1, USB_PORT_FEAT_C_CONNECTION);
+                               connect_change = 1;
+                       }
+
+                       if (portchange & USB_PORT_STAT_C_ENABLE) {
+                               if (!connect_change)
+                                       dev_dbg (hub_dev,
+                                               "port %d enable change, "
+                                               "status %08x\n",
+                                               i + 1, portstatus);
                                clear_port_feature(hdev,
                                        i + 1, USB_PORT_FEAT_C_ENABLE);
 
@@ -1696,15 +1712,14 @@
                                 * Works at least with mouse driver. 
                                 */
                                if (!(portstatus & USB_PORT_STAT_ENABLE)
-                                   && (portstatus & USB_PORT_STAT_CONNECTION)
-                                   && (hdev->children[i])) {
+                                   && !connect_change
+                                   && hdev->children[i]) {
                                        dev_err (hub_dev,
                                            "port %i "
                                            "disabled by hub (EMI?), "
                                            "re-enabling...",
                                                i + 1);
-                                       hub_port_connect_change(hub,
-                                               i, portstatus, portchange);
+                                       connect_change = 1;
                                }
                        }
 
@@ -1732,6 +1747,10 @@
                                clear_port_feature(hdev,
                                        i + 1, USB_PORT_FEAT_C_RESET);
                        }
+
+                       if (connect_change)
+                               hub_port_connect_change(hub, i,
+                                               portstatus, portchange);
                } /* end for i */
 
                /* deal with hub status changes */



-------------------------------------------------------
This SF.Net email is sponsored by The 2004 JavaOne(SM) Conference
Learn from the experts at JavaOne(SM), Sun's Worldwide Java Developer
Conference, June 28 - July 1 at the Moscone Center in San Francisco, CA
REGISTER AND SAVE! http://java.sun.com/javaone/sf Priority Code NWMGYKND
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to