summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRemy Bohmer <linux@bohmer.net>2008-08-20 11:22:02 +0200
committerWolfgang Denk <wd@denx.de>2008-09-09 16:59:25 +0200
commiteba1f2fc75f128a9a6c1328d786996a93fd7a707 (patch)
treedcce0e39df081f833ff056c278900d61e6de906f
parent2c8ccf2728f5e67d991cecf76c4057db75a87b67 (diff)
downloadu-boot-eba1f2fc75f128a9a6c1328d786996a93fd7a707.tar.gz
u-boot-eba1f2fc75f128a9a6c1328d786996a93fd7a707.tar.xz
u-boot-eba1f2fc75f128a9a6c1328d786996a93fd7a707.zip
Make usb-stop() safe to call multiple times in a row.
A recent commit (936897d4d1365452bbbdf8430db5e7769ef08d38) enabled the usb_stop() command in common/cmd_bootm.c which was not enabled for some time, because no board did actually set the CFG_CMD_USB flag. So, now the usb_stop() is executed before loading the linux kernel. However, the usb_ohci driver hangs up (at least on AT91SAM) if the driver is stopped twice (e.g. the peripheral clock is stopped on AT91). If some other piece of code calls usb_stop() before the bootm command, this command will hangup the system during boot. (usb start and stop is typically used while booting from usb memory stick) But, stopping the usb stack twice is useless anyway, and a flag already existed that kept track on the usb_init()/usb_stop() calls. So, we now check if the usb stack is really started before we stop it. This problem is now fixed in both the upper as low-level layer. Signed-off-by: Remy Bohmer <linux@bohmer.net> Acked-by: Markus Klotzbuecher <mk@denx.de>
-rw-r--r--common/usb.c13
-rw-r--r--drivers/usb/usb_ohci.c4
2 files changed, 12 insertions, 5 deletions
diff --git a/common/usb.c b/common/usb.c
index 9502f39038..52e5964c77 100644
--- a/common/usb.c
+++ b/common/usb.c
@@ -126,10 +126,15 @@ int usb_init(void)
*/
int usb_stop(void)
{
- asynch_allowed=1;
- usb_started = 0;
- usb_hub_reset();
- return usb_lowlevel_stop();
+ int res = 0;
+
+ if (usb_started) {
+ asynch_allowed = 1;
+ usb_started = 0;
+ usb_hub_reset();
+ res = usb_lowlevel_stop();
+ }
+ return res;
}
/*
diff --git a/drivers/usb/usb_ohci.c b/drivers/usb/usb_ohci.c
index fd5567f713..da11ecbc0f 100644
--- a/drivers/usb/usb_ohci.c
+++ b/drivers/usb/usb_ohci.c
@@ -1943,7 +1943,9 @@ int usb_lowlevel_stop(void)
if(usb_cpu_stop())
return -1;
#endif
-
+ /* This driver is no longer initialised. It needs a new low-level
+ * init (board/cpu) before it can be used again. */
+ ohci_inited = 0;
return 0;
}
#endif /* CONFIG_USB_OHCI_NEW */