diff options
Diffstat (limited to 'drivers/usb/host/uhci-hcd.c')
-rw-r--r-- | drivers/usb/host/uhci-hcd.c | 66 |
1 files changed, 34 insertions, 32 deletions
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index fba99b120588..c8ae199cfbb8 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c | |||
@@ -294,50 +294,50 @@ __acquires(uhci->lock) | |||
294 | * and that remote wakeups should be enabled. | 294 | * and that remote wakeups should be enabled. |
295 | */ | 295 | */ |
296 | egsm_enable = USBCMD_EGSM; | 296 | egsm_enable = USBCMD_EGSM; |
297 | uhci->RD_enable = 1; | ||
298 | int_enable = USBINTR_RESUME; | 297 | int_enable = USBINTR_RESUME; |
299 | wakeup_enable = 1; | 298 | wakeup_enable = 1; |
300 | 299 | ||
301 | /* In auto-stop mode wakeups must always be detected, but | 300 | /* |
302 | * Resume-Detect interrupts may be prohibited. (In the absence | 301 | * In auto-stop mode, we must be able to detect new connections. |
303 | * of CONFIG_PM, they are always disallowed.) | 302 | * The user can force us to poll by disabling remote wakeup; |
303 | * otherwise we will use the EGSM/RD mechanism. | ||
304 | */ | 304 | */ |
305 | if (auto_stop) { | 305 | if (auto_stop) { |
306 | if (!device_may_wakeup(&rhdev->dev)) | 306 | if (!device_may_wakeup(&rhdev->dev)) |
307 | int_enable = 0; | 307 | egsm_enable = int_enable = 0; |
308 | } | ||
308 | 309 | ||
309 | /* In bus-suspend mode wakeups may be disabled, but if they are | ||
310 | * allowed then so are Resume-Detect interrupts. | ||
311 | */ | ||
312 | } else { | ||
313 | #ifdef CONFIG_PM | 310 | #ifdef CONFIG_PM |
311 | /* | ||
312 | * In bus-suspend mode, we use the wakeup setting specified | ||
313 | * for the root hub. | ||
314 | */ | ||
315 | else { | ||
314 | if (!rhdev->do_remote_wakeup) | 316 | if (!rhdev->do_remote_wakeup) |
315 | wakeup_enable = 0; | 317 | wakeup_enable = 0; |
316 | #endif | ||
317 | } | 318 | } |
319 | #endif | ||
318 | 320 | ||
319 | /* EGSM causes the root hub to echo a 'K' signal (resume) out any | 321 | /* |
320 | * port which requests a remote wakeup. According to the USB spec, | 322 | * UHCI doesn't distinguish between wakeup requests from downstream |
321 | * every hub is supposed to do this. But if we are ignoring | 323 | * devices and local connect/disconnect events. There's no way to |
322 | * remote-wakeup requests anyway then there's no point to it. | 324 | * enable one without the other; both are controlled by EGSM. Thus |
323 | * We also shouldn't enable EGSM if it's broken. | 325 | * if wakeups are disallowed then EGSM must be turned off -- in which |
324 | */ | 326 | * case remote wakeup requests from downstream during system sleep |
325 | if (!wakeup_enable || global_suspend_mode_is_broken(uhci)) | 327 | * will be lost. |
326 | egsm_enable = 0; | 328 | * |
327 | 329 | * In addition, if EGSM is broken then we can't use it. Likewise, | |
328 | /* If we're ignoring wakeup events then there's no reason to | 330 | * if Resume-Detect interrupts are broken then we can't use them. |
329 | * enable Resume-Detect interrupts. We also shouldn't enable | ||
330 | * them if they are broken or disallowed. | ||
331 | * | 331 | * |
332 | * This logic may lead us to enabling RD but not EGSM. The UHCI | 332 | * Finally, neither EGSM nor RD is useful by itself. Without EGSM, |
333 | * spec foolishly says that RD works only when EGSM is on, but | 333 | * the RD status bit will never get set. Without RD, the controller |
334 | * there's no harm in enabling it anyway -- perhaps some chips | 334 | * won't generate interrupts to tell the system about wakeup events. |
335 | * will implement it! | ||
336 | */ | 335 | */ |
337 | if (!wakeup_enable || resume_detect_interrupts_are_broken(uhci) || | 336 | if (!wakeup_enable || global_suspend_mode_is_broken(uhci) || |
338 | !int_enable) | 337 | resume_detect_interrupts_are_broken(uhci)) |
339 | uhci->RD_enable = int_enable = 0; | 338 | egsm_enable = int_enable = 0; |
340 | 339 | ||
340 | uhci->RD_enable = !!int_enable; | ||
341 | uhci_writew(uhci, int_enable, USBINTR); | 341 | uhci_writew(uhci, int_enable, USBINTR); |
342 | uhci_writew(uhci, egsm_enable | USBCMD_CF, USBCMD); | 342 | uhci_writew(uhci, egsm_enable | USBCMD_CF, USBCMD); |
343 | mb(); | 343 | mb(); |
@@ -364,10 +364,12 @@ __acquires(uhci->lock) | |||
364 | uhci->rh_state = new_state; | 364 | uhci->rh_state = new_state; |
365 | uhci->is_stopped = UHCI_IS_STOPPED; | 365 | uhci->is_stopped = UHCI_IS_STOPPED; |
366 | 366 | ||
367 | /* If interrupts don't work and remote wakeup is enabled then | 367 | /* |
368 | * the suspended root hub needs to be polled. | 368 | * If remote wakeup is enabled but either EGSM or RD interrupts |
369 | * doesn't work, then we won't get an interrupt when a wakeup event | ||
370 | * occurs. Thus the suspended root hub needs to be polled. | ||
369 | */ | 371 | */ |
370 | if (!int_enable && wakeup_enable) | 372 | if (wakeup_enable && (!int_enable || !egsm_enable)) |
371 | set_bit(HCD_FLAG_POLL_RH, &uhci_to_hcd(uhci)->flags); | 373 | set_bit(HCD_FLAG_POLL_RH, &uhci_to_hcd(uhci)->flags); |
372 | else | 374 | else |
373 | clear_bit(HCD_FLAG_POLL_RH, &uhci_to_hcd(uhci)->flags); | 375 | clear_bit(HCD_FLAG_POLL_RH, &uhci_to_hcd(uhci)->flags); |