Greg:
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.
Alan Stern
Signed-off-by: Alan Stern <[EMAIL PROTECTED]>
===== drivers/usb/core/hub.c 1.160 vs edited =====
--- 1.160/drivers/usb/core/hub.c Tue Jun 1 12:54:17 2004
+++ edited/drivers/usb/core/hub.c Fri Jun 4 14:10:33 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 new InstallShield X.
>From Windows to Linux, servers to mobile, InstallShield X is the one
installation-authoring solution that does it all. Learn more and
evaluate today! http://www.installshield.com/Dev2Dev/0504
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel