aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Brownell <david-b@pacbell.net>2006-11-17 02:34:58 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2006-12-01 17:23:37 -0500
commit93f1a47c4af34c4ee014b3d2aae70089b3b69f72 (patch)
tree10e9b58f9b93cbbc0ab375778396632d465ce28e
parentf0d7f27351058284f62ab4848909373c2d1f5ce8 (diff)
USB: add ehci_hcd.ignore_oc parameter
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 <dbrownell@users.sourceforge.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/usb/host/ehci-hcd.c10
-rw-r--r--drivers/usb/host/ehci-hub.c18
2 files changed, 23 insertions, 5 deletions
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 9030994aba98..f2ceb5fdbeb7 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -126,6 +126,11 @@ static unsigned park = 0;
126module_param (park, uint, S_IRUGO); 126module_param (park, uint, S_IRUGO);
127MODULE_PARM_DESC (park, "park setting; 1-3 back-to-back async packets"); 127MODULE_PARM_DESC (park, "park setting; 1-3 back-to-back async packets");
128 128
129/* for flakey hardware, ignore overcurrent indicators */
130static int ignore_oc = 0;
131module_param (ignore_oc, bool, S_IRUGO);
132MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications");
133
129#define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT) 134#define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT)
130 135
131/*-------------------------------------------------------------------------*/ 136/*-------------------------------------------------------------------------*/
@@ -541,9 +546,10 @@ static int ehci_run (struct usb_hcd *hcd)
541 546
542 temp = HC_VERSION(readl (&ehci->caps->hc_capbase)); 547 temp = HC_VERSION(readl (&ehci->caps->hc_capbase));
543 ehci_info (ehci, 548 ehci_info (ehci,
544 "USB %x.%x started, EHCI %x.%02x, driver %s\n", 549 "USB %x.%x started, EHCI %x.%02x, driver %s%s\n",
545 ((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f), 550 ((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f),
546 temp >> 8, temp & 0xff, DRIVER_VERSION); 551 temp >> 8, temp & 0xff, DRIVER_VERSION,
552 ignore_oc ? ", overcurrent ignored" : "");
547 553
548 writel (INTR_MASK, &ehci->regs->intr_enable); /* Turn On Interrupts */ 554 writel (INTR_MASK, &ehci->regs->intr_enable); /* Turn On Interrupts */
549 555
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 7c170a29f959..0a56dfa2745d 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -218,6 +218,7 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
218{ 218{
219 struct ehci_hcd *ehci = hcd_to_ehci (hcd); 219 struct ehci_hcd *ehci = hcd_to_ehci (hcd);
220 u32 temp, status = 0; 220 u32 temp, status = 0;
221 u32 mask;
221 int ports, i, retval = 1; 222 int ports, i, retval = 1;
222 unsigned long flags; 223 unsigned long flags;
223 224
@@ -233,6 +234,18 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
233 retval++; 234 retval++;
234 } 235 }
235 236
237 /* Some boards (mostly VIA?) report bogus overcurrent indications,
238 * causing massive log spam unless we completely ignore them. It
239 * may be relevant that VIA VT8235 controlers, where PORT_POWER is
240 * always set, seem to clear PORT_OCC and PORT_CSC when writing to
241 * PORT_POWER; that's surprising, but maybe within-spec.
242 */
243 if (!ignore_oc)
244 mask = PORT_CSC | PORT_PEC | PORT_OCC;
245 else
246 mask = PORT_CSC | PORT_PEC;
247 // PORT_RESUME from hardware ~= PORT_STAT_C_SUSPEND
248
236 /* no hub change reports (bit 0) for now (power, ...) */ 249 /* no hub change reports (bit 0) for now (power, ...) */
237 250
238 /* port N changes (bit N)? */ 251 /* port N changes (bit N)? */
@@ -250,8 +263,7 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
250 } 263 }
251 if (!(temp & PORT_CONNECT)) 264 if (!(temp & PORT_CONNECT))
252 ehci->reset_done [i] = 0; 265 ehci->reset_done [i] = 0;
253 if ((temp & (PORT_CSC | PORT_PEC | PORT_OCC)) != 0 266 if ((temp & mask) != 0
254 // PORT_STAT_C_SUSPEND?
255 || ((temp & PORT_RESUME) != 0 267 || ((temp & PORT_RESUME) != 0
256 && time_after (jiffies, 268 && time_after (jiffies,
257 ehci->reset_done [i]))) { 269 ehci->reset_done [i]))) {
@@ -418,7 +430,7 @@ static int ehci_hub_control (
418 status |= 1 << USB_PORT_FEAT_C_CONNECTION; 430 status |= 1 << USB_PORT_FEAT_C_CONNECTION;
419 if (temp & PORT_PEC) 431 if (temp & PORT_PEC)
420 status |= 1 << USB_PORT_FEAT_C_ENABLE; 432 status |= 1 << USB_PORT_FEAT_C_ENABLE;
421 if (temp & PORT_OCC) 433 if ((temp & PORT_OCC) && !ignore_oc)
422 status |= 1 << USB_PORT_FEAT_C_OVER_CURRENT; 434 status |= 1 << USB_PORT_FEAT_C_OVER_CURRENT;
423 435
424 /* whoever resumes must GetPortStatus to complete it!! */ 436 /* whoever resumes must GetPortStatus to complete it!! */