diff options
author | Roger Quadros <rogerq@ti.com> | 2012-07-30 13:05:09 +0800 |
---|---|---|
committer | Andy Green <andy.green@linaro.org> | 2012-07-30 13:05:09 +0800 |
commit | 237ab3b2d4d50db8c11aa2e4ebc903353863f622 (patch) | |
tree | e0b6ff76400a03f63b6d20ac6a7ee5597eb6796f | |
parent | e9a283315f425e89f8fbed2e97f8d506d9e9171b (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>
-rw-r--r-- | drivers/usb/musb/musb_core.c | 16 | ||||
-rw-r--r-- | drivers/usb/musb/musb_core.h | 2 |
2 files changed, 16 insertions, 2 deletions
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index c78108eb398..f94d91e80af 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; } diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index f4a40f001c8..8c349e0952f 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -456,6 +456,8 @@ struct musb { #ifdef MUSB_CONFIG_PROC_FS struct proc_dir_entry *proc_entry; #endif + + unsigned suspended:1; /* module disabled */ }; static inline struct musb *gadget_to_musb(struct usb_gadget *g) |