Commit 593f48d6 authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman

[PATCH] USB UHCI: restore more state following PM resume

Some systems don't save the internal state of the UHCI registers across a
PM suspend/resume cycle very well.  This patch saves & restores the
Frame Number and the Framelist Base Address registers (in addition to the
Interrupt Enable register, which was added separately in a recent patch.)
parent 2d5185c7
...@@ -2444,9 +2444,11 @@ static int uhci_suspend(struct usb_hcd *hcd, u32 state) ...@@ -2444,9 +2444,11 @@ static int uhci_suspend(struct usb_hcd *hcd, u32 state)
struct uhci_hcd *uhci = hcd_to_uhci(hcd); struct uhci_hcd *uhci = hcd_to_uhci(hcd);
/* Don't try to suspend broken motherboards, reset instead */ /* Don't try to suspend broken motherboards, reset instead */
if (suspend_allowed(uhci)) if (suspend_allowed(uhci)) {
suspend_hc(uhci); suspend_hc(uhci);
else uhci->saved_framenumber =
inw(uhci->io_addr + USBFRNUM) & 0x3ff;
} else
reset_hc(uhci); reset_hc(uhci);
return 0; return 0;
} }
...@@ -2460,9 +2462,13 @@ static int uhci_resume(struct usb_hcd *hcd) ...@@ -2460,9 +2462,13 @@ static int uhci_resume(struct usb_hcd *hcd)
if (uhci->state == UHCI_SUSPENDED) { if (uhci->state == UHCI_SUSPENDED) {
/* /*
* Some systems clear the Interrupt Enable register during * Some systems don't maintain the UHCI register values
* PM suspend/resume, so reinitialize it. * during a PM suspend/resume cycle, so reinitialize
* the Frame Number, the Framelist Base Address, and the
* Interrupt Enable registers.
*/ */
outw(uhci->saved_framenumber, uhci->io_addr + USBFRNUM);
outl(uhci->fl->dma_handle, uhci->io_addr + USBFLBASEADD);
outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC |
USBINTR_SP, uhci->io_addr + USBINTR); USBINTR_SP, uhci->io_addr + USBINTR);
uhci->resume_detect = 1; uhci->resume_detect = 1;
......
...@@ -350,6 +350,7 @@ struct uhci_hcd { ...@@ -350,6 +350,7 @@ struct uhci_hcd {
enum uhci_state state; /* FIXME: needs a spinlock */ enum uhci_state state; /* FIXME: needs a spinlock */
unsigned long state_end; /* Time of next transition */ unsigned long state_end; /* Time of next transition */
int resume_detect; /* Need a Global Resume */ int resume_detect; /* Need a Global Resume */
unsigned int saved_framenumber; /* Save during PM suspend */
/* Main list of URB's currently controlled by this HC */ /* Main list of URB's currently controlled by this HC */
spinlock_t urb_list_lock; spinlock_t urb_list_lock;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment