diff options
author | Roger Quadros <rogerq@ti.com> | 2012-07-26 18:08:09 +0300 |
---|---|---|
committer | Xavier Boudet <x-boudet@ti.com> | 2012-07-26 17:21:09 +0200 |
commit | 651c1e3dd877011714b0f6d50d7c653e731df6db (patch) | |
tree | 3868c055a43209b0fab7be6700dfd4a893087e0f /drivers/usb/musb/musb_core.c | |
parent | 692a9a995256d0813a7c494913f66c28f8d53e58 (diff) |
usb: musb: fix suspend/resume after gadget driver is loaded and unloaded
If the MUSB controller is already suspended via runtime suspend then it
will be disabled (and clocks gated) thus accessing the controller
while system suspend to save state will cause L3 bus errors.
This problem can be reproduced by loading a gadget driver, unloading
it and putting the system to suspend.
There is no need to save/restore controller state in this case
as the corresponding runtime suspend/resume functions are already doing that.
This patch makes sure we don't access the MUSB controller registers in the
suspend path if it is already disabled.
Signed-off-by: Roger Quadros <rogerq@ti.com>
Diffstat (limited to 'drivers/usb/musb/musb_core.c')
-rw-r--r-- | drivers/usb/musb/musb_core.c | 16 |
1 files changed, 14 insertions, 2 deletions
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index c78108eb398d..f94d91e80aff 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -2327,7 +2327,11 @@ static int musb_suspend(struct device *dev) } spin_unlock_irqrestore(&musb->lock, flags); - musb_save_context(musb); + + /* Need to save state only if it is not yet runtime suspended */ + if (!musb->suspended) { + musb_save_context(musb); + } return 0; } @@ -2340,7 +2344,13 @@ static int musb_resume_noirq(struct device *dev) * module got reset through the PSC (vs just being disabled). */ - musb_restore_context(musb); + /* + * Restore state only if device was not runtime suspended before + * the system suspend + */ + if (!musb->suspended) { + musb_restore_context(musb); + } return 0; } @@ -2349,6 +2359,7 @@ static int musb_runtime_suspend(struct device *dev) struct musb *musb = dev_to_musb(dev); musb_save_context(musb); + musb->suspended = true; return 0; } @@ -2370,6 +2381,7 @@ static int musb_runtime_resume(struct device *dev) if (!first) musb_restore_context(musb); first = 0; + musb->suspended = false; return 0; } |