Certain boards seem to like to issue false overcurrent notifications, for
example on ports that don't have anything connected to them.  This looks
like a hardware error, at the level of noise to those ports' overcurrent
input signals (or non-debounced VBUS comparators).  This surfaces to users
as truly massive amounts of syslog spam from khubd (which is appropriate
for real hardware problems, except for the volume from multiple ports).

Using this new "ignore_oc" flag helps such systems work more sanely, by
preventing such indications from getting to khubd (and spam syslog).  The
downside is of course that true overcurrent errors will be masked; they'll
appear as spontaneous disconnects, without the diagnostics that will let
users troubleshoot issues like short circuited cables.

Note that the bulk of these reports seem to be with VIA southbridges, but
I think some were with Intel ones.

Signed-off-by: David Brownell <[EMAIL PROTECTED]>

Index: g26/drivers/usb/host/ehci-hcd.c
===================================================================
--- g26.orig/drivers/usb/host/ehci-hcd.c        2006-11-12 12:22:30.000000000 
-0800
+++ g26/drivers/usb/host/ehci-hcd.c     2006-11-14 08:06:12.000000000 -0800
@@ -126,6 +126,11 @@ static unsigned park = 0;
 module_param (park, uint, S_IRUGO);
 MODULE_PARM_DESC (park, "park setting; 1-3 back-to-back async packets");
 
+/* for flakey hardware, ignore overcurrent indicators */
+static int ignore_oc = 0;
+module_param (ignore_oc, bool, S_IRUGO);
+MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications");
+
 #define        INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT)
 
 /*-------------------------------------------------------------------------*/
@@ -541,9 +546,10 @@ static int ehci_run (struct usb_hcd *hcd
 
        temp = HC_VERSION(readl (&ehci->caps->hc_capbase));
        ehci_info (ehci,
-               "USB %x.%x started, EHCI %x.%02x, driver %s\n",
+               "USB %x.%x started, EHCI %x.%02x, driver %s%s\n",
                ((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f),
-               temp >> 8, temp & 0xff, DRIVER_VERSION);
+               temp >> 8, temp & 0xff, DRIVER_VERSION,
+               ignore_oc ? ", overcurrent ignored" : "");
 
        writel (INTR_MASK, &ehci->regs->intr_enable); /* Turn On Interrupts */
 
Index: g26/drivers/usb/host/ehci-hub.c
===================================================================
--- g26.orig/drivers/usb/host/ehci-hub.c        2006-11-12 12:29:52.000000000 
-0800
+++ g26/drivers/usb/host/ehci-hub.c     2006-11-12 13:00:21.000000000 -0800
@@ -218,6 +218,7 @@ ehci_hub_status_data (struct usb_hcd *hc
 {
        struct ehci_hcd *ehci = hcd_to_ehci (hcd);
        u32             temp, status = 0;
+       u32             mask;
        int             ports, i, retval = 1;
        unsigned long   flags;
 
@@ -233,6 +234,18 @@ ehci_hub_status_data (struct usb_hcd *hc
                retval++;
        }
 
+       /* Some boards (mostly VIA?) report bogus overcurrent indications,
+        * causing massive log spam unless we completely ignore them.  It
+        * may be relevant that VIA VT8235 controlers, where PORT_POWER is
+        * always set, seem to clear PORT_OCC and PORT_CSC when writing to
+        * PORT_POWER; that's surprising, but maybe within-spec.
+        */
+       if (!ignore_oc)
+               mask = PORT_CSC | PORT_PEC | PORT_OCC;
+       else
+               mask = PORT_CSC | PORT_PEC;
+       // PORT_RESUME from hardware ~= PORT_STAT_C_SUSPEND
+
        /* no hub change reports (bit 0) for now (power, ...) */
 
        /* port N changes (bit N)? */
@@ -250,8 +263,7 @@ ehci_hub_status_data (struct usb_hcd *hc
                }
                if (!(temp & PORT_CONNECT))
                        ehci->reset_done [i] = 0;
-               if ((temp & (PORT_CSC | PORT_PEC | PORT_OCC)) != 0
-                               // PORT_STAT_C_SUSPEND?
+               if ((temp & mask) != 0
                                || ((temp & PORT_RESUME) != 0
                                        && time_after (jiffies,
                                                ehci->reset_done [i]))) {
@@ -418,7 +430,7 @@ static int ehci_hub_control (
                        status |= 1 << USB_PORT_FEAT_C_CONNECTION;
                if (temp & PORT_PEC)
                        status |= 1 << USB_PORT_FEAT_C_ENABLE;
-               if (temp & PORT_OCC)
+               if ((temp & PORT_OCC) && !ignore_oc)
                        status |= 1 << USB_PORT_FEAT_C_OVER_CURRENT;
 
                /* whoever resumes must GetPortStatus to complete it!! */

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to