]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/2.6.20.2/uhci-fix-port-resume-problem.patch
4.9-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 2.6.20.2 / uhci-fix-port-resume-problem.patch
CommitLineData
a1cd50fd
GKH
1From stable-bounces@linux.kernel.org Mon Feb 26 14:17:37 2007
2From: Alan Stern <stern@rowland.harvard.edu>
3Date: Mon, 26 Feb 2007 17:16:06 -0500 (EST)
4Subject: UHCI: fix port resume problem
5To: Greg KH <greg@kroah.com>, <stable@kernel.org>
6Cc: Guilherme Salgado <gsalgado@gmail.com>, USB development list <linux-usb-devel@lists.sourceforge.net>
7Message-ID: <Pine.LNX.4.44L0.0702261713080.3374-100000@iolanthe.rowland.org>
8
9From: Alan Stern <stern@rowland.harvard.edu>
10
11This patch (as863) fixes a problem encountered sometimes when resuming
12a port on a UHCI controller. The hardware may turn off the
13Resume-Detect bit before turning off the Suspend bit, leading usbcore
14to think that the port is still suspended and the resume has failed.
15The patch makes uhci_finish_suspend() wait until both bits are safely
16off.
17
18Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
19Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
20
21---
22 drivers/usb/host/uhci-hub.c | 11 +++++++----
23 1 file changed, 7 insertions(+), 4 deletions(-)
24
25--- linux-2.6.20.1.orig/drivers/usb/host/uhci-hub.c
26+++ linux-2.6.20.1/drivers/usb/host/uhci-hub.c
27@@ -33,6 +33,9 @@ static __u8 root_hub_hub_des[] =
28 /* status change bits: nonzero writes will clear */
29 #define RWC_BITS (USBPORTSC_OCC | USBPORTSC_PEC | USBPORTSC_CSC)
30
31+/* suspend/resume bits: port suspended or port resuming */
32+#define SUSPEND_BITS (USBPORTSC_SUSP | USBPORTSC_RD)
33+
34 /* A port that either is connected or has a changed-bit set will prevent
35 * us from AUTO_STOPPING.
36 */
37@@ -96,8 +99,8 @@ static void uhci_finish_suspend(struct u
38 int status;
39 int i;
40
41- if (inw(port_addr) & (USBPORTSC_SUSP | USBPORTSC_RD)) {
42- CLR_RH_PORTSTAT(USBPORTSC_SUSP | USBPORTSC_RD);
43+ if (inw(port_addr) & SUSPEND_BITS) {
44+ CLR_RH_PORTSTAT(SUSPEND_BITS);
45 if (test_bit(port, &uhci->resuming_ports))
46 set_bit(port, &uhci->port_c_suspend);
47
48@@ -107,7 +110,7 @@ static void uhci_finish_suspend(struct u
49 * Experiments show that some controllers take longer, so
50 * we'll poll for completion. */
51 for (i = 0; i < 10; ++i) {
52- if (!(inw(port_addr) & USBPORTSC_RD))
53+ if (!(inw(port_addr) & SUSPEND_BITS))
54 break;
55 udelay(1);
56 }
57@@ -289,7 +292,7 @@ static int uhci_hub_control(struct usb_h
58 wPortStatus |= USB_PORT_STAT_CONNECTION;
59 if (status & USBPORTSC_PE) {
60 wPortStatus |= USB_PORT_STAT_ENABLE;
61- if (status & (USBPORTSC_SUSP | USBPORTSC_RD))
62+ if (status & SUSPEND_BITS)
63 wPortStatus |= USB_PORT_STAT_SUSPEND;
64 }
65 if (status & USBPORTSC_OC)