Commit 5f8364b7d63acdc2216ca0f7d0a8557c318479ea

Authored by Alan Stern
Committed by Greg Kroah-Hartman
1 parent fe1ec341df

UHCI: module parameter to ignore overcurrent changes

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 spamming
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.  In addition, controllers with no devices
attached will be forced to poll for new devices rather than relying on
interrupts, since each overcurrent event would generate a new
interrupt.

This patch (as826) is essentially a copy of David Brownell's ignore_oc
patch for ehci-hcd, ported to uhci-hcd.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

Showing 3 changed files with 32 additions and 3 deletions Side-by-side Diff

Documentation/kernel-parameters.txt
... ... @@ -1714,6 +1714,14 @@
1714 1714 uart6850= [HW,OSS]
1715 1715 Format: <io>,<irq>
1716 1716  
  1717 + uhci-hcd.ignore_oc=
  1718 + [USB] Ignore overcurrent events (default N).
  1719 + Some badly-designed motherboards generate lots of
  1720 + bogus events, for ports that aren't wired to
  1721 + anything. Set this parameter to avoid log spamming.
  1722 + Note that genuine overcurrent events won't be
  1723 + reported either.
  1724 +
1717 1725 usbhid.mousepoll=
1718 1726 [USBHID] The interval which mice are to be polled at.
1719 1727  
drivers/usb/host/uhci-hcd.c
... ... @@ -60,6 +60,11 @@
60 60 Alan Stern"
61 61 #define DRIVER_DESC "USB Universal Host Controller Interface driver"
62 62  
  63 +/* for flakey hardware, ignore overcurrent indicators */
  64 +static int ignore_oc;
  65 +module_param(ignore_oc, bool, S_IRUGO);
  66 +MODULE_PARM_DESC(ignore_oc, "ignore hardware overcurrent indications");
  67 +
63 68 /*
64 69 * debug = 0, no debugging messages
65 70 * debug = 1, dump failed URBs except for stalls
... ... @@ -169,6 +174,11 @@
169 174 {
170 175 int port;
171 176  
  177 + /* If we have to ignore overcurrent events then almost by definition
  178 + * we can't depend on resume-detect interrupts. */
  179 + if (ignore_oc)
  180 + return 1;
  181 +
172 182 switch (to_pci_dev(uhci_dev(uhci))->vendor) {
173 183 default:
174 184 break;
... ... @@ -921,7 +931,8 @@
921 931 {
922 932 int retval = -ENOMEM;
923 933  
924   - printk(KERN_INFO DRIVER_DESC " " DRIVER_VERSION "\n");
  934 + printk(KERN_INFO DRIVER_DESC " " DRIVER_VERSION "%s\n",
  935 + ignore_oc ? ", overcurrent ignored" : "");
925 936  
926 937 if (usb_disabled())
927 938 return -ENODEV;
drivers/usb/host/uhci-hub.c
... ... @@ -52,10 +52,20 @@
52 52 static inline int get_hub_status_data(struct uhci_hcd *uhci, char *buf)
53 53 {
54 54 int port;
  55 + int mask = RWC_BITS;
55 56  
  57 + /* Some boards (both VIA and Intel apparently) report bogus
  58 + * overcurrent indications, causing massive log spam unless
  59 + * we completely ignore them. This doesn't seem to be a problem
  60 + * with the chipset so much as with the way it is connected on
  61 + * the motherboard; if the overcurrent input is left to float
  62 + * then it may constantly register false positives. */
  63 + if (ignore_oc)
  64 + mask &= ~USBPORTSC_OCC;
  65 +
56 66 *buf = 0;
57 67 for (port = 0; port < uhci->rh_numports; ++port) {
58   - if ((inw(uhci->io_addr + USBPORTSC1 + port * 2) & RWC_BITS) ||
  68 + if ((inw(uhci->io_addr + USBPORTSC1 + port * 2) & mask) ||
59 69 test_bit(port, &uhci->port_c_suspend))
60 70 *buf |= (1 << (port + 1));
61 71 }
... ... @@ -263,7 +273,7 @@
263 273 wPortChange |= USB_PORT_STAT_C_CONNECTION;
264 274 if (status & USBPORTSC_PEC)
265 275 wPortChange |= USB_PORT_STAT_C_ENABLE;
266   - if (status & USBPORTSC_OCC)
  276 + if ((status & USBPORTSC_OCC) && !ignore_oc)
267 277 wPortChange |= USB_PORT_STAT_C_OVERCURRENT;
268 278  
269 279 if (test_bit(port, &uhci->port_c_suspend)) {