]> git.kernelconcepts.de Git - karo-tx-uboot.git/commitdiff
Make usb-stop() safe to call multiple times in a row.
authorRemy Bohmer <linux@bohmer.net>
Wed, 20 Aug 2008 09:22:02 +0000 (11:22 +0200)
committerWolfgang Denk <wd@denx.de>
Tue, 9 Sep 2008 14:59:25 +0000 (16:59 +0200)
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>
common/usb.c
drivers/usb/usb_ohci.c

index 9502f39038b1637149d2804c9e7ede2405a76e77..52e5964c77039ecc2bcd4088d466a91d094ddf2e 100644 (file)
@@ -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;
 }
 
 /*
index fd5567f713fe607e5ed70fcea8cba04de0afa295..da11ecbc0fef92f1c936fd9684628829ca51496e 100644 (file)
@@ -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 */