summaryrefslogtreecommitdiffstats
path: root/common/cmd_usb.c
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2014-09-20 16:54:35 +0200
committerMarek Vasut <marex@denx.de>2014-10-06 14:50:43 +0200
commit6e78c74f62ebfa378d1a2f9b83423b23545c28bf (patch)
treea1822c0772256b3b6b14ac55a08839b4c5bc40be /common/cmd_usb.c
parent0ea09dfe873657df47d83d5d4e0090bbf05c6abb (diff)
downloadtalos-obmc-uboot-6e78c74f62ebfa378d1a2f9b83423b23545c28bf.tar.gz
talos-obmc-uboot-6e78c74f62ebfa378d1a2f9b83423b23545c28bf.zip
usb: kbd: On a "usb reset" call usb_kbd_deregister() before calling usb_stop()
We need to call usb_kbd_deregister() before calling usb_stop(). usbkbd's stdio_dev->priv points to the usb_device, and usb_kbd_testc dereferences usb_device->privptr. usb_stop zeros usb_device, leaving usb_device->privptr NULL, causing bad things (tm) to happen once control returns to the main loop and usb_kbd_testc gets called. Calling usb_kbd_deregister() avoids this. Note that we do not allow the "usb reset" to continue when the deregister fails. This will be fixed in a later patch. For the same reasons always fail "usb stop" if the usb_kbd_deregister() fails, even in the force path. This can happen when CONFIG_SYS_STDIO_DEREGISTER is not set. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Diffstat (limited to 'common/cmd_usb.c')
-rw-r--r--common/cmd_usb.c27
1 files changed, 15 insertions, 12 deletions
diff --git a/common/cmd_usb.c b/common/cmd_usb.c
index 2519497dad..b2aa44c2a7 100644
--- a/common/cmd_usb.c
+++ b/common/cmd_usb.c
@@ -430,6 +430,16 @@ static int do_usbboot(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
}
#endif /* CONFIG_USB_STORAGE */
+static int do_usb_stop_keyboard(void)
+{
+#ifdef CONFIG_USB_KEYBOARD
+ if (usb_kbd_deregister() != 0) {
+ printf("USB not stopped: usbkbd still using USB\n");
+ return 1;
+ }
+#endif
+ return 0;
+}
/******************************************************************************
* usb command intepreter
@@ -450,6 +460,8 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
if ((strncmp(argv[1], "reset", 5) == 0) ||
(strncmp(argv[1], "start", 5) == 0)) {
bootstage_mark_name(BOOTSTAGE_ID_USB_START, "usb_start");
+ if (do_usb_stop_keyboard() != 0)
+ return 1;
usb_stop();
printf("(Re)start USB...\n");
if (usb_init() >= 0) {
@@ -468,19 +480,10 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
return 0;
}
if (strncmp(argv[1], "stop", 4) == 0) {
-#ifdef CONFIG_USB_KEYBOARD
- if (argc == 2) {
- if (usb_kbd_deregister() != 0) {
- printf("USB not stopped: usbkbd still"
- " using USB\n");
- return 1;
- }
- } else {
- /* forced stop, switch console in to serial */
+ if (argc != 2)
console_assign(stdin, "serial");
- usb_kbd_deregister();
- }
-#endif
+ if (do_usb_stop_keyboard() != 0)
+ return 1;
printf("stopping USB..\n");
usb_stop();
return 0;
OpenPOWER on IntegriCloud