Commit 3df7169e73fc1d71a39cffeacc969f6840cdf52b

Authored by Alan Stern
Committed by Greg Kroah-Hartman
1 parent 637ed74ff9

OHCI: work around for nVidia shutdown problem

This patch (as1417) fixes a problem affecting some (or all) nVidia
chipsets.  When the computer is shut down, the OHCI controllers
continue to power the USB buses and evidently they drive a Reset
signal out all their ports.  This prevents attached devices from going
to low power.  Mouse LEDs stay on, for example, which is disconcerting
for users and a drain on laptop batteries.

The fix involves leaving each OHCI controller in the OPERATIONAL state
during system shutdown rather than putting it in the RESET state.
Although this nominally means the controller is running, in fact it's
not doing very much since all the schedules are all disabled.  However
there is ongoing DMA to the Host Controller Communications Area, so
the patch also disables the bus-master capability of all PCI USB
controllers after the shutdown routine runs.

The fix is applied only to nVidia-based PCI OHCI controllers, so it
shouldn't cause problems on systems using other hardware.  As an added
safety measure, in case the kernel encounters one of these running
controllers during boot, the patch changes quirk_usb_handoff_ohci()
(which runs early on during PCI discovery) to reset the controller
before anything bad can happen.

Reported-by: Pali Rohár <pali.rohar@gmail.com>
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
CC: David Brownell <david-b@pacbell.net>
Tested-by: Pali Rohár <pali.rohar@gmail.com>
CC: stable <stable@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

Showing 5 changed files with 41 additions and 9 deletions Side-by-side Diff

drivers/usb/core/hcd-pci.c
... ... @@ -329,8 +329,10 @@
329 329 return;
330 330  
331 331 if (test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) &&
332   - hcd->driver->shutdown)
  332 + hcd->driver->shutdown) {
333 333 hcd->driver->shutdown(hcd);
  334 + pci_disable_device(dev);
  335 + }
334 336 }
335 337 EXPORT_SYMBOL_GPL(usb_hcd_pci_shutdown);
336 338  
drivers/usb/host/ohci-hcd.c
... ... @@ -398,7 +398,14 @@
398 398  
399 399 ohci = hcd_to_ohci (hcd);
400 400 ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
401   - ohci_usb_reset (ohci);
  401 + ohci->hc_control = ohci_readl(ohci, &ohci->regs->control);
  402 +
  403 + /* If the SHUTDOWN quirk is set, don't put the controller in RESET */
  404 + ohci->hc_control &= (ohci->flags & OHCI_QUIRK_SHUTDOWN ?
  405 + OHCI_CTRL_RWC | OHCI_CTRL_HCFS :
  406 + OHCI_CTRL_RWC);
  407 + ohci_writel(ohci, ohci->hc_control, &ohci->regs->control);
  408 +
402 409 /* flush the writes */
403 410 (void) ohci_readl (ohci, &ohci->regs->control);
404 411 }
drivers/usb/host/ohci-pci.c
... ... @@ -201,6 +201,20 @@
201 201 return 0;
202 202 }
203 203  
  204 +/* nVidia controllers continue to drive Reset signalling on the bus
  205 + * even after system shutdown, wasting power. This flag tells the
  206 + * shutdown routine to leave the controller OPERATIONAL instead of RESET.
  207 + */
  208 +static int ohci_quirk_nvidia_shutdown(struct usb_hcd *hcd)
  209 +{
  210 + struct ohci_hcd *ohci = hcd_to_ohci(hcd);
  211 +
  212 + ohci->flags |= OHCI_QUIRK_SHUTDOWN;
  213 + ohci_dbg(ohci, "enabled nVidia shutdown quirk\n");
  214 +
  215 + return 0;
  216 +}
  217 +
204 218 /*
205 219 * The hardware normally enables the A-link power management feature, which
206 220 * lets the system lower the power consumption in idle states.
... ... @@ -331,6 +345,10 @@
331 345 {
332 346 PCI_DEVICE(PCI_VENDOR_ID_ATI, 0x4399),
333 347 .driver_data = (unsigned long)ohci_quirk_amd700,
  348 + },
  349 + {
  350 + PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID),
  351 + .driver_data = (unsigned long) ohci_quirk_nvidia_shutdown,
334 352 },
335 353  
336 354 /* FIXME for some of the early AMD 760 southbridges, OHCI
drivers/usb/host/ohci.h
... ... @@ -403,6 +403,7 @@
403 403 #define OHCI_QUIRK_HUB_POWER 0x100 /* distrust firmware power/oc setup */
404 404 #define OHCI_QUIRK_AMD_ISO 0x200 /* ISO transfers*/
405 405 #define OHCI_QUIRK_AMD_PREFETCH 0x400 /* pre-fetch for ISO transfer */
  406 +#define OHCI_QUIRK_SHUTDOWN 0x800 /* nVidia power bug */
406 407 // there are also chip quirks/bugs in init logic
407 408  
408 409 struct work_struct nec_work; /* Worker for NEC quirk */
drivers/usb/host/pci-quirks.c
... ... @@ -169,6 +169,7 @@
169 169 static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
170 170 {
171 171 void __iomem *base;
  172 + u32 control;
172 173  
173 174 if (!mmio_resource_enabled(pdev, 0))
174 175 return;
175 176  
... ... @@ -177,10 +178,14 @@
177 178 if (base == NULL)
178 179 return;
179 180  
  181 + control = readl(base + OHCI_CONTROL);
  182 +
180 183 /* On PA-RISC, PDC can leave IR set incorrectly; ignore it there. */
181   -#ifndef __hppa__
182   -{
183   - u32 control = readl(base + OHCI_CONTROL);
  184 +#ifdef __hppa__
  185 +#define OHCI_CTRL_MASK (OHCI_CTRL_RWC | OHCI_CTRL_IR)
  186 +#else
  187 +#define OHCI_CTRL_MASK OHCI_CTRL_RWC
  188 +
184 189 if (control & OHCI_CTRL_IR) {
185 190 int wait_time = 500; /* arbitrary; 5 seconds */
186 191 writel(OHCI_INTR_OC, base + OHCI_INTRENABLE);
187 192  
188 193  
... ... @@ -194,12 +199,11 @@
194 199 dev_warn(&pdev->dev, "OHCI: BIOS handoff failed"
195 200 " (BIOS bug?) %08x\n",
196 201 readl(base + OHCI_CONTROL));
197   -
198   - /* reset controller, preserving RWC */
199   - writel(control & OHCI_CTRL_RWC, base + OHCI_CONTROL);
200 202 }
201   -}
202 203 #endif
  204 +
  205 + /* reset controller, preserving RWC (and possibly IR) */
  206 + writel(control & OHCI_CTRL_MASK, base + OHCI_CONTROL);
203 207  
204 208 /*
205 209 * disable interrupts