USB: Only treat lasting over-current conditions as errors
authorPaul Bolle <pebolle@tiscali.nl>
Fri, 11 Mar 2011 17:03:52 +0000 (18:03 +0100)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 11 Mar 2011 22:18:52 +0000 (14:18 -0800)
On a laptop I see these errors on (most) resumes:
    hub 3-0:1.0: over-current change on port 1
    hub 3-0:1.0: over-current change on port 2

Since over-current conditions can disappear quite quickly it's better to
downgrade that message to debug level, recheck for an over-current
condition a little later and only print and over-current condition error
if that condition (still) exists when it's rechecked.

Add similar logic to hub over-current changes. (That code is untested,
as those changes do not occur on this laptop.)

Signed-off-by: Paul Bolle <pebolle@tiscali.nl>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/core/hub.c

index 395754edd0631de70a1e07d20051ce0ccc37de5e..b574f9131b43f54f20a84a014945b4fdad93ae00 100644 (file)
@@ -3408,12 +3408,19 @@ static void hub_events(void)
                        }
                        
                        if (portchange & USB_PORT_STAT_C_OVERCURRENT) {
-                               dev_err (hub_dev,
-                                       "over-current change on port %d\n",
-                                       i);
+                               u16 status = 0;
+                               u16 unused;
+
+                               dev_dbg(hub_dev, "over-current change on port "
+                                       "%d\n", i);
                                clear_port_feature(hdev, i,
                                        USB_PORT_FEAT_C_OVER_CURRENT);
+                               msleep(100);    /* Cool down */
                                hub_power_on(hub, true);
+                               hub_port_status(hub, i, &status, &unused);
+                               if (status & USB_PORT_STAT_OVERCURRENT)
+                                       dev_err(hub_dev, "over-current "
+                                               "condition on port %d\n", i);
                        }
 
                        if (portchange & USB_PORT_STAT_C_RESET) {
@@ -3445,10 +3452,17 @@ static void hub_events(void)
                                        hub->limited_power = 0;
                        }
                        if (hubchange & HUB_CHANGE_OVERCURRENT) {
-                               dev_dbg (hub_dev, "overcurrent change\n");
-                               msleep(500);    /* Cool down */
+                               u16 status = 0;
+                               u16 unused;
+
+                               dev_dbg(hub_dev, "over-current change\n");
                                clear_hub_feature(hdev, C_HUB_OVER_CURRENT);
+                               msleep(500);    /* Cool down */
                                hub_power_on(hub, true);
+                               hub_hub_status(hub, &status, &unused);
+                               if (status & HUB_STATUS_OVERCURRENT)
+                                       dev_err(hub_dev, "over-current "
+                                               "condition\n");
                        }
                }