Commit 7f1a07538f71b2b0f37744bdc899be294e0518b5

Authored by Hans de Goede
Committed by Simon Glass
1 parent f78a5c0774

dm: usb: Copy over usb_device values from usb_scan_device() to final usb_device

Currently we copy over a number of usb_device values stored in the on stack
struct usb_device probed in usb_scan_device() to the final driver-model managed
struct usb_device in usb_child_pre_probe() through usb_device_platdata, and
then call usb_select_config() to fill in the rest.

There are 3 problems with this approach:

1) It does not fill in enough fields before calling usb_select_config(),
specifically it does not fill in ep0's maxpacketsize causing a div by zero
exception in the ehci driver.

2) It unnecessarily redoes a number of usb requests making usb probing slower

3) Calling usb_select_config() a second time fails on some usb-1 devices
plugged into usb-2 hubs, causing u-boot to not recognize these devices.

This commit fixes these issues by removing (*) the usb_select_config() call
from usb_child_pre_probe(), and instead of copying over things field by field
through usb_device_platdata, store a pointer to the in stack usb_device
(which is still valid when usb_child_pre_probe() gets called) and copy
over the entire struct.

*) Except for devices which are explictly instantiated through device-tree
rather then discovered through usb_scan_device() such as emulated usb devices
in the sandbox.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Acked-by: Simon Glass <sjg@chromium.org>

Showing 2 changed files with 38 additions and 22 deletions Side-by-side Diff

drivers/usb/host/usb-uclass.c
... ... @@ -533,11 +533,7 @@
533 533 plat = dev_get_parent_platdata(dev);
534 534 debug("%s: Probing '%s', plat=%p\n", __func__, dev->name, plat);
535 535 plat->devnum = udev->devnum;
536   - plat->speed = udev->speed;
537   - plat->slot_id = udev->slot_id;
538   - plat->portnr = port;
539   - debug("** device '%s': stashing slot_id=%d\n", dev->name,
540   - plat->slot_id);
  536 + plat->udev = udev;
541 537 priv->next_addr++;
542 538 ret = device_probe(dev);
543 539 if (ret) {
544 540  
... ... @@ -597,17 +593,34 @@
597 593 struct usb_dev_platdata *plat = dev_get_parent_platdata(dev);
598 594 int ret;
599 595  
600   - udev->controller_dev = usb_get_bus(dev);
601   - udev->dev = dev;
602   - udev->devnum = plat->devnum;
603   - udev->slot_id = plat->slot_id;
604   - udev->portnr = plat->portnr;
605   - udev->speed = plat->speed;
606   - debug("** device '%s': getting slot_id=%d\n", dev->name, plat->slot_id);
  596 + if (plat->udev) {
  597 + /*
  598 + * Copy over all the values set in the on stack struct
  599 + * usb_device in usb_scan_device() to our final struct
  600 + * usb_device for this dev.
  601 + */
  602 + *udev = *(plat->udev);
  603 + /* And clear plat->udev as it will not be valid for long */
  604 + plat->udev = NULL;
  605 + udev->dev = dev;
  606 + } else {
  607 + /*
  608 + * This happens with devices which are explicitly bound
  609 + * instead of being discovered through usb_scan_device()
  610 + * such as sandbox emul devices.
  611 + */
  612 + udev->dev = dev;
  613 + udev->controller_dev = usb_get_bus(dev);
  614 + udev->devnum = plat->devnum;
607 615  
608   - ret = usb_select_config(udev);
609   - if (ret)
610   - return ret;
  616 + /*
  617 + * udev did not go through usb_scan_device(), so we need to
  618 + * select the config and read the config descriptors.
  619 + */
  620 + ret = usb_select_config(udev);
  621 + if (ret)
  622 + return ret;
  623 + }
611 624  
612 625 return 0;
613 626 }
... ... @@ -571,20 +571,23 @@
571 571 * This is used by sandbox to provide emulation data also.
572 572 *
573 573 * @id: ID used to match this device
574   - * @speed: Stores the speed associated with a USB device
575 574 * @devnum: Device address on the USB bus
576   - * @slot_id: USB3 slot ID, which is separate from the device address
577   - * @portnr: Port number of this device on its parent hub, numbered from 1
578   - * (0 mean this device is the root hub)
  575 + * @udev: usb-uclass internal use only do NOT use
579 576 * @strings: List of descriptor strings (for sandbox emulation purposes)
580 577 * @desc_list: List of descriptors (for sandbox emulation purposes)
581 578 */
582 579 struct usb_dev_platdata {
583 580 struct usb_device_id id;
584   - enum usb_device_speed speed;
585 581 int devnum;
586   - int slot_id;
587   - int portnr; /* Hub port number, 1..n */
  582 + /*
  583 + * This pointer is used to pass the usb_device used in usb_scan_device,
  584 + * to get the usb descriptors before the driver is known, to the
  585 + * actual udevice once the driver is known and the udevice is created.
  586 + * This will be NULL except during probe, do NOT use.
  587 + *
  588 + * This should eventually go away.
  589 + */
  590 + struct usb_device *udev;
588 591 #ifdef CONFIG_SANDBOX
589 592 struct usb_string *strings;
590 593 /* NULL-terminated list of descriptor pointers */