diff mbox

[U-Boot,fix,for,v2014.10,2/5] usb: kbd: On a "usb reset" call usb_kbd_deregister() before calling usb_stop()

Message ID 1411224878-13692-3-git-send-email-hdegoede@redhat.com
State Accepted
Delegated to: Marek Vasut
Headers show

Commit Message

Hans de Goede Sept. 20, 2014, 2:54 p.m. UTC
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>
---
 common/cmd_usb.c | 27 +++++++++++++++------------
 1 file changed, 15 insertions(+), 12 deletions(-)

Comments

Marek Vasut Sept. 22, 2014, 12:01 p.m. UTC | #1
On Saturday, September 20, 2014 at 04:54:35 PM, Hans de Goede wrote:
> 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>
> ---
>  common/cmd_usb.c | 27 +++++++++++++++------------
>  1 file changed, 15 insertions(+), 12 deletions(-)
> 
> diff --git a/common/cmd_usb.c b/common/cmd_usb.c
> index 2519497..b2aa44c 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");

I tried this set of patches with the DWC2 driver on RPI just now and i get this 
message and 'usb start' fails and doesn't scan bus. I suspect we have a problem 
here, can you check and post a fix ?

Best regards,
Marek Vasut
Hans de Goede Sept. 23, 2014, 9:10 a.m. UTC | #2
Hi,

On 09/22/2014 02:01 PM, Marek Vasut wrote:
> On Saturday, September 20, 2014 at 04:54:35 PM, Hans de Goede wrote:
>> 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>
>> ---
>>  common/cmd_usb.c | 27 +++++++++++++++------------
>>  1 file changed, 15 insertions(+), 12 deletions(-)
>>
>> diff --git a/common/cmd_usb.c b/common/cmd_usb.c
>> index 2519497..b2aa44c 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");
> 
> I tried this set of patches with the DWC2 driver on RPI just now and i get this 
> message and 'usb start' fails and doesn't scan bus. I suspect we have a problem 
> here, can you check and post a fix ?

Do you have the entire set applied ? This is a known regression as mentioned
in the commit msg. Once the force parameter is in place this should go
away for a start/reset.

Also is usb start being called twice ? The first deregister should never fail,
since then no device is registered.

Regards,

Hans
Marek Vasut Sept. 23, 2014, 12:15 p.m. UTC | #3
On Tuesday, September 23, 2014 at 11:10:34 AM, Hans de Goede wrote:
> Hi,
> 
> On 09/22/2014 02:01 PM, Marek Vasut wrote:
> > On Saturday, September 20, 2014 at 04:54:35 PM, Hans de Goede wrote:
> >> 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>
> >> ---
> >> 
> >>  common/cmd_usb.c | 27 +++++++++++++++------------
> >>  1 file changed, 15 insertions(+), 12 deletions(-)
> >> 
> >> diff --git a/common/cmd_usb.c b/common/cmd_usb.c
> >> index 2519497..b2aa44c 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");
> > 
> > I tried this set of patches with the DWC2 driver on RPI just now and i
> > get this message and 'usb start' fails and doesn't scan bus. I suspect
> > we have a problem here, can you check and post a fix ?
> 
> Do you have the entire set applied ?

Yes, the current u-boot-usb/master

> This is a known regression as
> mentioned in the commit msg. Once the force parameter is in place this
> should go away for a start/reset.

You mean the 'force' param ?

> Also is usb start being called twice ? The first deregister should never
> fail, since then no device is registered.

Ugh, I must be dumb or somesuch, for whatever reason the issue went away and I 
can no longer replicate it. I will keep on a lookout.

Best regards,
Marek Vasut
Hans de Goede Sept. 23, 2014, 12:51 p.m. UTC | #4
Hi,

On 09/23/2014 02:15 PM, Marek Vasut wrote:
> On Tuesday, September 23, 2014 at 11:10:34 AM, Hans de Goede wrote:
>> Hi,
>>
>> On 09/22/2014 02:01 PM, Marek Vasut wrote:
>>> On Saturday, September 20, 2014 at 04:54:35 PM, Hans de Goede wrote:
>>>> 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>
>>>> ---
>>>>
>>>>  common/cmd_usb.c | 27 +++++++++++++++------------
>>>>  1 file changed, 15 insertions(+), 12 deletions(-)
>>>>
>>>> diff --git a/common/cmd_usb.c b/common/cmd_usb.c
>>>> index 2519497..b2aa44c 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");
>>>
>>> I tried this set of patches with the DWC2 driver on RPI just now and i
>>> get this message and 'usb start' fails and doesn't scan bus. I suspect
>>> we have a problem here, can you check and post a fix ?
>>
>> Do you have the entire set applied ?
> 
> Yes, the current u-boot-usb/master
> 
>> This is a known regression as
>> mentioned in the commit msg. Once the force parameter is in place this
>> should go away for a start/reset.
> 
> You mean the 'force' param ?

Yes, when that is 1, which it is on a start / reset, the deregister should never fail.

>> Also is usb start being called twice ? The first deregister should never
>> fail, since then no device is registered.
> 
> Ugh, I must be dumb or somesuch, for whatever reason the issue went away and I 
> can no longer replicate it. I will keep on a lookout.

Ok.

Regards,

Hans
diff mbox

Patch

diff --git a/common/cmd_usb.c b/common/cmd_usb.c
index 2519497..b2aa44c 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;