public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
From: Stefan Roese <sr@denx.de>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH v3 4/4] usb: Change power-on / scanning timeout handling
Date: Tue, 15 Mar 2016 10:46:52 +0100	[thread overview]
Message-ID: <56E7DA0C.2000202@denx.de> (raw)
In-Reply-To: <56E6F555.5020807@wwwdotorg.org>

Hi Stephan,

On 14.03.2016 18:31, Stephen Warren wrote:
> On 03/14/2016 04:18 AM, Stefan Roese wrote:
>> This patch changes the USB port scanning procedure and timeout
>> handling in the following ways:
> 
> A few nits/typos in the description, and some review comments below.

Thanks, will update the commit text in v4.

<snip>
 
>> diff --git a/common/usb_hub.c b/common/usb_hub.c
> 
>> @@ -120,7 +121,21 @@ static void usb_hub_power_on(struct 
>> usb_hub_device *hub)
>>           pgood_delay = max(pgood_delay,
>>                         (unsigned)simple_strtol(env, NULL, 0));
>>       debug("pgood_delay=%dms\n", pgood_delay);
>> -    mdelay(pgood_delay + 1000);
>> +
>> +    /*
>> +     * Do a minimum delay of the larger value of 100ms or pgood_delay
>> +     * so that the power can stablize before the devices are queried
>> +     */
>> +    dev->query_delay = get_timer(0) + max(100, (int)pgood_delay);
>> +
>> +    /*
>> +     * Record the power-on timeout here. The max. delay (timeout)
>> +     * will be done based on this value in the USB port loop in
>> +     * usb_hub_configure() later.
>> +     */
>> +    dev->connect_timeout = get_timer(0) + pgood_delay + 1000;
> 
> I'd be tempted to make that:
> 
> dev->connect_timeout = dev->query_delay + 1000;
> 
> That way, if the max() used in the calculation of dev->query_delay was 
> dominated by the 100 not the pgood_delay, then we still get a 1000ms 
> time for the device to connect after the power is stable. Currently, if 
> pgood_delay<=100 (is that legal?) then the delta might be as little as 
> 900ms (for pgood_delay==0).

Fixed.
 
>> static LIST_HEAD(usb_scan_list);
> 
> You could put that onto the stack in usb_hub_configure() and pass it as 
> a parameter to usb_device_list_scan(). That would avoid some globals, 
> which might make it easier to apply this technique across multiple 
> controllers/hubs/... in the future?

Multiple controllers/hubs should be supported currently (at least
in my tests). Its the parallel scanning of those controllers which
might be problematic. usb_hub.c needs some general rework, as it
has some more globals:

/* TODO(sjg at chromium.org): Remove this when CONFIG_DM_USB is defined */
static struct usb_hub_device hub_dev[USB_MAX_HUB];
static int usb_hub_index;

I've moved "usb_scan_list" to these declarations for now, so that
all of them can be cleaned up once somebody works on task.
 
>> +static int usb_scan_port(struct usb_device_scan *usb_scan)
> 
>> +    ret = usb_get_port_status(dev, i + 1, portsts);
>> +    if (ret < 0) {
>> +        debug("get_port_status failed\n");
>> +        return 0;
> 
> Shouldn't this cause a timeout eventually if it repeats forever?

Okay. I've added a timeout check here to remove such a non-functional
device.
 
>> +    /* Test if the connection came up, and if so, exit. */
>> +    if (portstatus & USB_PORT_STAT_CONNECTION) {
> 
> If you invert that test, you can return early and remove and indentation 
> level from the rest of the function.

Good catch. Changed in v4.
 
>> +        debug("devnum=%d port=%d: USB dev found\n", dev->devnum, i + 1);
>> +        /* Remove this device from scanning list */
>> +        list_del(&usb_scan->list);
>> +
>> +        /* A new USB device is ready at this point */
>> +
>> +        debug("Port %d Status %X Change %X\n",
>> +              i + 1, portstatus, portchange);
> 
> It might be nice to print this a little earlier (outside the 
> USB_PORT_STAT_CONNECTION if block) so that any 
> USB_PORT_STAT_C_CONNECTION triggers the print, not just if C_CONNECTION 
> && CONNECTION. That might help debug, and match the existing code.

Changed in v4.
 
>> +        if (portchange & USB_PORT_STAT_C_CONNECTION) {
>  > +            debug("port %d connection change\n", i + 1);
>  > +            usb_hub_port_connect_change(dev, i);
>  > +        }
> 
> That test is always true, or the function would have returned earlier.

Changed in v4.
 
>> +static int usb_device_list_scan(void)
> ...
>> +    static int running;
>> +    int ret = 0;
>> +
>> +    /* Only run this loop once for each controller */
>> +    if (running)
>> +        return 0;
>> +
>> +    running = 1;
> ...
>> +out:
>> +    /*
>> +     * This USB controller has has finished scanning all its connected
>> +     * USB devices. Set "running" back to 0, so that other USB 
>> controllers
>> +     * will scan their devices too.
>> +     */
>> +    running = 0;
> 
> Doesn't this function only get called a single time from 
> usb_hub_configure()? If so, I don't think the "running" variable is 
> required.

Its called recursively, if hubs are stacked. So its called e.g.
5 times in this setup:

=> usb tree
USB device tree:
  1  Hub (480 Mb/s, 0mA)
  |  u-boot EHCI Host Controller 
  |
  +-2  Hub (480 Mb/s, 0mA)
    |
    +-3  Hub (480 Mb/s, 100mA)
    | |
    | +-7  Hub (12 Mb/s, 100mA)
    |    
    +-4  Hub (480 Mb/s, 0mA)
    | |
    | +-8  Mass Storage (480 Mb/s, 200mA)
    | |    Kingston DataTraveler 2.0 50E549C688C4BE7189942766
    | |  
    | +-9  Mass Storage (480 Mb/s, 98mA)
    |      USBest Technology USB Mass Storage Device 09092207fbf0c4
    |    
    +-5  Mass Storage (480 Mb/s, 200mA)
    |    6989 Intenso Alu Line EE706F5E
    |  
    +-6  Mass Storage (480 Mb/s, 200mA)
         JetFlash Mass Storage Device 3281440601
 
>>   static int usb_hub_configure(struct usb_device *dev)
> 
>> +    for (i = 0; i < dev->maxchild; i++) {
>> +        struct usb_device_scan *usb_scan;
>>
>> +        usb_scan = calloc(1, sizeof(*usb_scan));
>> +        if (!usb_scan) {
>> +            printf("Can't allocate memory for USB device!\n");
>> +            return -ENOMEM;
> 
> I think there should be some resource cleanup for the previously 
> allocated list entries here. Perhaps that's what you meant in your other 
> email where you talked about some missing free()s?

Correct. I already noticed that the malloc is missing the free part.
Its added in v4.

Thanks for the review,
Stefan

  parent reply	other threads:[~2016-03-15  9:46 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-03-14 10:18 [U-Boot] [PATCH v3 0/4] usb: Reduce USB scanning time Stefan Roese
2016-03-14 10:18 ` [U-Boot] [PATCH v3 1/4] usb: legacy_hub_port_reset(): Speedup hub reset handling Stefan Roese
2016-03-14 10:18 ` [U-Boot] [PATCH v3 2/4] usb: Remove 200 ms delay in usb_hub_port_connect_change() Stefan Roese
2016-03-14 17:06   ` Stephen Warren
2016-03-14 10:18 ` [U-Boot] [PATCH v3 3/4] usb: Don't reset the USB hub a 2nd time Stefan Roese
2016-03-14 10:18 ` [U-Boot] [PATCH v3 4/4] usb: Change power-on / scanning timeout handling Stefan Roese
2016-03-14 12:45   ` Hans de Goede
2016-03-14 13:19     ` Stefan Roese
2016-03-14 17:31   ` Stephen Warren
2016-03-14 19:47     ` Hans de Goede
2016-03-15  9:46     ` Stefan Roese [this message]
2016-03-15 15:42       ` Stephen Warren
2016-03-14 17:51   ` Stephen Warren
2016-03-15 13:16     ` Stefan Roese
2016-03-15 15:52       ` Stephen Warren
2016-03-15 16:00         ` Stefan Roese
2016-03-15 16:07           ` Stephen Warren

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=56E7DA0C.2000202@denx.de \
    --to=sr@denx.de \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox