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

[PATCH] USB UHCI: Add root-hub suspend/resume support

This patch implements (finally!) separate suspend and resume routines
for the root hub and the controller in the UHCI driver.  It also
changes the sequence used to reset the controller during initial
probing, so as to preserve the existing state during a Resume-From-Disk.
(This new sequence is what should be used in the PCI Quirks code for
early USB handoffs, incidentally.)  Lastly it adds a notion of the
controller being "inaccessible" while in a PCI low-power state, when
normal I/O operations shouldn't be allowed.
Signed-off-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent c8f4fe43
This diff is collapsed.
......@@ -41,6 +41,7 @@
#define USBFRNUM 6
#define USBFLBASEADD 8
#define USBSOF 12
#define USBSOF_DEFAULT 64 /* Frame length is exactly 1 ms */
/* USB port status and control registers */
#define USBPORTSC1 16
......@@ -66,6 +67,8 @@
/* Legacy support register */
#define USBLEGSUP 0xc0
#define USBLEGSUP_DEFAULT 0x2000 /* only PIRQ enable set */
#define USBLEGSUP_RWC 0x8f00 /* the R/WC bits */
#define USBLEGSUP_RO 0x5040 /* R/O and reserved bits */
#define UHCI_NULL_DATA_SIZE 0x7FF /* for UHCI controller TD */
......@@ -325,8 +328,9 @@ static inline int __interval_to_skel(int interval)
*/
enum uhci_rh_state {
/* In the next 4 states the HC must be halted */
UHCI_RH_RESET,
UHCI_RH_RESET, /* These two must come first */
UHCI_RH_SUSPENDED,
UHCI_RH_AUTO_STOPPED,
UHCI_RH_RESUMING,
......@@ -334,7 +338,8 @@ enum uhci_rh_state {
* can legally appear either way */
UHCI_RH_SUSPENDING,
/* In the next two states it's an error if the HC is halted */
/* In the next two states it's an error if the HC is halted.
* These two must come last */
UHCI_RH_RUNNING, /* The normal state */
UHCI_RH_RUNNING_NODEVS, /* Running with no devices attached */
};
......@@ -376,6 +381,7 @@ struct uhci_hcd {
unsigned int scan_in_progress:1; /* Schedule scan is running */
unsigned int need_rescan:1; /* Redo the schedule scan */
unsigned int resume_detect:1; /* Need a Global Resume */
unsigned int hc_inaccessible:1; /* HC is suspended or dead */
/* Support for port suspend/resume/reset */
unsigned long port_c_suspend; /* Bit-arrays of ports */
......
......@@ -54,6 +54,9 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)
struct uhci_hcd *uhci = hcd_to_uhci(hcd);
int port;
if (uhci->hc_inaccessible)
return 0;
*buf = 0;
for (port = 0; port < uhci->rh_numports; ++port) {
if ((inw(uhci->io_addr + USBPORTSC1 + port * 2) & RWC_BITS) ||
......@@ -150,6 +153,9 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
u16 wPortChange, wPortStatus;
unsigned long flags;
if (uhci->hc_inaccessible)
return -ETIMEDOUT;
spin_lock_irqsave(&uhci->lock, flags);
switch (typeReq) {
......
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