From 93f1a47c4af34c4ee014b3d2aae70089b3b69f72 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Thu, 16 Nov 2006 23:34:58 -0800 Subject: 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 Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hcd.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers/usb/host/ehci-hcd.c') diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 9030994aba9..f2ceb5fdbeb 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -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 */ -- cgit v1.2.3 From 8c03356a559ced6fa78931f498193f776d67e445 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 9 Nov 2006 14:42:16 -0500 Subject: EHCI: Fix root-hub and port suspend/resume problems This patch (as738b) fixes numerous problems in the controller/root-hub suspend/resume/remote-wakeup support in ehci-hcd: The bus_resume() routine should wake up only the ports that were suspended by bus_suspend(). Ports that were already suspended should remain that way. The interrupt mask is used to detect loss of power in the bus_resume() routine (if the mask is 0 then power was lost). However bus_suspend() always sets the mask to 0. Instead the mask should retain its normal value, with port-change-detect interrupts disabled if remote wakeup is turned off. The interrupt mask should be reset to its correct value at the end of bus_resume() regardless of whether power was lost. bus_resume() reinitializes the operational registers if power was lost. However those registers are not in the aux power well, hence they can lose their values whenever the controller is put into D3. They should always be reinitialized. When a port-change interrupt occurs and the root hub is suspended, the interrupt handler should request a root-hub resume instead of starting up the controller all by itself. There's no need for the interrupt handler to request a root-hub resume every time a suspended port sends a remote-wakeup request. The pci_resume() method doesn't need to check for connected ports when deciding whether or not to reset the controller. It can make that decision based on whether Vaux power was maintained. Even when the controller does not need to be reset, pci_resume() must undo the effect of pci_suspend() by re-enabling the interrupt mask. If power was lost, pci_resume() must not call ehci_run(). At this point the root hub is still supposed to be suspended, not running. It's enough to rewrite the command register and set the configured_flag. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hcd.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/usb/host/ehci-hcd.c') diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index f2ceb5fdbeb..025d3331368 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -619,9 +619,8 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) unsigned i = HCS_N_PORTS (ehci->hcs_params); /* resume root hub? */ - status = readl (&ehci->regs->command); - if (!(status & CMD_RUN)) - writel (status | CMD_RUN, &ehci->regs->command); + if (!(readl(&ehci->regs->command) & CMD_RUN)) + usb_hcd_resume_root_hub(hcd); while (i--) { int pstatus = readl (&ehci->regs->port_status [i]); @@ -638,7 +637,6 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) */ ehci->reset_done [i] = jiffies + msecs_to_jiffies (20); ehci_dbg (ehci, "port %d remote wakeup\n", i + 1); - usb_hcd_resume_root_hub(hcd); } } -- cgit v1.2.3