UHCI: fix port resume problem

This patch (as863) fixes a problem encountered sometimes when resuming
a port on a UHCI controller. The hardware may turn off the
Resume-Detect bit before turning off the Suspend bit, leading usbcore
to think that the port is still suspended and the resume has failed.
The patch makes uhci_finish_suspend() wait until both bits are safely
off.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by Alan Stern and committed by Greg Kroah-Hartman 88018158 97b9eb91

+7 -4
+7 -4
drivers/usb/host/uhci-hub.c
··· 33 33 /* status change bits: nonzero writes will clear */ 34 34 #define RWC_BITS (USBPORTSC_OCC | USBPORTSC_PEC | USBPORTSC_CSC) 35 35 36 + /* suspend/resume bits: port suspended or port resuming */ 37 + #define SUSPEND_BITS (USBPORTSC_SUSP | USBPORTSC_RD) 38 + 36 39 /* A port that either is connected or has a changed-bit set will prevent 37 40 * us from AUTO_STOPPING. 38 41 */ ··· 99 96 int status; 100 97 int i; 101 98 102 - if (inw(port_addr) & (USBPORTSC_SUSP | USBPORTSC_RD)) { 103 - CLR_RH_PORTSTAT(USBPORTSC_SUSP | USBPORTSC_RD); 99 + if (inw(port_addr) & SUSPEND_BITS) { 100 + CLR_RH_PORTSTAT(SUSPEND_BITS); 104 101 if (test_bit(port, &uhci->resuming_ports)) 105 102 set_bit(port, &uhci->port_c_suspend); 106 103 ··· 110 107 * Experiments show that some controllers take longer, so 111 108 * we'll poll for completion. */ 112 109 for (i = 0; i < 10; ++i) { 113 - if (!(inw(port_addr) & USBPORTSC_RD)) 110 + if (!(inw(port_addr) & SUSPEND_BITS)) 114 111 break; 115 112 udelay(1); 116 113 } ··· 292 289 wPortStatus |= USB_PORT_STAT_CONNECTION; 293 290 if (status & USBPORTSC_PE) { 294 291 wPortStatus |= USB_PORT_STAT_ENABLE; 295 - if (status & (USBPORTSC_SUSP | USBPORTSC_RD)) 292 + if (status & SUSPEND_BITS) 296 293 wPortStatus |= USB_PORT_STAT_SUSPEND; 297 294 } 298 295 if (status & USBPORTSC_OC)