[PATCH] for acpi S1 power cycle resume problems
From: William Morrow
Date: Fri Aug 19 2005 - 09:40:03 EST
Hi
I was told that if I had a patch to submit for a baseline change that
this was the place to do it.
If not, please let me know...
thanks,
morrow
Patched against 2.6.11 baseline
problems fixed:
1) OHCI_INTR_RD not being cleared in ohci interrupt handler
results in interrupt storm and system hang on RD status.
ohci spec indicates this should be done.
2) PORT_CSC not being cleared in ehci_hub_status_data
code attempts to clear bit, but bit is write to clear.
there are other errant clears, since the PORTSCn regs
have 3 RWC bits, and the rest are RW. All stmts of the form:
writel (v, &ehci->regs->port_status[i])
should clear RWC bits if they do not intend to clear status,
and should set the bits which should be cleared (this case).
3) loop control and subsequent port resume/reset not correct.
unsigned index made detecting port1 active impossible, and
OWNER/POWER status was being ignored on ports assigned
to companion controller.
Signed-off-by: Jordan Crouse <jordan.crouse@xxxxxxx>
diff -uprN linux-2.6.11.orig/drivers/usb/host/ehci.h linux-2.6.11/drivers/usb/host/ehci.h
--- linux-2.6.11.orig/drivers/usb/host/ehci.h 2005-03-02 00:38:25.000000000 -0700
+++ linux-2.6.11/drivers/usb/host/ehci.h 2005-08-17 08:15:36.000000000 -0600
@@ -262,6 +262,7 @@ struct ehci_regs {
#define PORT_PE (1<<2) /* port enable */
#define PORT_CSC (1<<1) /* connect status change */
#define PORT_CONNECT (1<<0) /* device connected */
+#define PORT_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC)
} __attribute__ ((packed));
/* Appendix C, Debug port ... intended for use with special "debug devices"
diff -uprN linux-2.6.11.orig/drivers/usb/host/ehci-hcd.c linux-2.6.11/drivers/usb/host/ehci-hcd.c
--- linux-2.6.11.orig/drivers/usb/host/ehci-hcd.c 2005-03-02 00:38:38.000000000 -0700
+++ linux-2.6.11/drivers/usb/host/ehci-hcd.c 2005-08-17 08:15:36.000000000 -0600
@@ -722,7 +722,7 @@ static int ehci_suspend (struct usb_hcd
static int ehci_resume (struct usb_hcd *hcd)
{
struct ehci_hcd *ehci = hcd_to_ehci (hcd);
- unsigned port;
+ int port;
struct usb_device *root = hcd->self.root_hub;
int retval = -EINVAL;
int powerup = 0;
@@ -733,11 +733,11 @@ static int ehci_resume (struct usb_hcd *
msleep (100);
/* If any port is suspended, we know we can/must resume the HC. */
- for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; ) {
+ for (port = HCS_N_PORTS (ehci->hcs_params); --port >= 0; ) {
u32 status;
- port--;
status = readl (&ehci->regs->port_status [port]);
- if (status & PORT_SUSPEND) {
+ if ( (status & PORT_SUSPEND) != 0 ||
+ ((status & PORT_OWNER) != 0 && (status & PORT_POWER) != 0) ) {
down (&hcd->self.root_hub->serialize);
retval = ehci_hub_resume (hcd);
up (&hcd->self.root_hub->serialize);
@@ -755,7 +755,7 @@ static int ehci_resume (struct usb_hcd *
/* Else reset, to cope with power loss or flush-to-storage
* style "resume" having activated BIOS during reboot.
*/
- if (port == 0) {
+ if (port < 0) {
(void) ehci_halt (ehci);
(void) ehci_reset (ehci);
(void) ehci_hc_reset (hcd);
diff -uprN linux-2.6.11.orig/drivers/usb/host/ehci-hub.c linux-2.6.11/drivers/usb/host/ehci-hub.c
--- linux-2.6.11.orig/drivers/usb/host/ehci-hub.c 2005-03-02 00:38:32.000000000 -0700
+++ linux-2.6.11/drivers/usb/host/ehci-hub.c 2005-08-17 08:15:36.000000000 -0600
@@ -232,7 +232,8 @@ ehci_hub_status_data (struct usb_hcd *hc
if (temp & PORT_OWNER) {
/* don't report this in GetPortStatus */
if (temp & PORT_CSC) {
- temp &= ~PORT_CSC;
+ temp &= ~PORT_RWC_BITS;
+ temp |= PORT_CSC;
writel (temp, &ehci->regs->port_status [i]);
}
continue;
diff -uprN linux-2.6.11.orig/drivers/usb/host/ohci-hcd.c linux-2.6.11/drivers/usb/host/ohci-hcd.c
--- linux-2.6.11.orig/drivers/usb/host/ohci-hcd.c 2005-03-02 00:37:48.000000000 -0700
+++ linux-2.6.11/drivers/usb/host/ohci-hcd.c 2005-08-17 08:15:36.000000000 -0600
@@ -720,6 +720,7 @@ static irqreturn_t ohci_irq (struct usb_
if (ints & OHCI_INTR_RD) {
ohci_vdbg (ohci, "resume detect\n");
+ ohci_writel (ohci, OHCI_INTR_RD, ®s->intrstatus);
schedule_work(&ohci->rh_resume);
}