diff options
author | Thomas Huth <thuth@redhat.com> | 2016-08-02 11:19:42 +0200 |
---|---|---|
committer | Alexey Kardashevskiy <aik@ozlabs.ru> | 2016-08-03 13:48:18 +1000 |
commit | cf7963a12c7fb516a1addcba40d78977d61fbcc5 (patch) | |
tree | 6ba78d0fd596cdd5c4e1947d2961059266c373e2 /lib | |
parent | f1d7dc911c0203f91af5dfbc462106623c6b8a9b (diff) | |
download | SLOF-cf7963a12c7fb516a1addcba40d78977d61fbcc5.zip SLOF-cf7963a12c7fb516a1addcba40d78977d61fbcc5.tar.gz SLOF-cf7963a12c7fb516a1addcba40d78977d61fbcc5.tar.bz2 |
usb: Initialize USB3 devices on a hub and keep track of hub topology
USB3 devices need to be initialized with usb3_dev_init(), so that
they get assigned a proper slot ID. And for USB3 devices that are
attached to a (non-root) hub, we also need to keep track of the
hub topology, so a new field called "hub" is added to the struct
usb_dev which references the hub devices where the current USB
devices is attached to. The hub topology will be used later to
build the so-called "route string" for the USB3 devices.
Signed-off-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libusb/usb-core.h | 1 | ||||
-rw-r--r-- | lib/libusb/usb-hub.c | 36 | ||||
-rw-r--r-- | lib/libusb/usb-xhci.c | 10 | ||||
-rw-r--r-- | lib/libusb/usb-xhci.h | 3 |
4 files changed, 39 insertions, 11 deletions
diff --git a/lib/libusb/usb-core.h b/lib/libusb/usb-core.h index a35df34..070aab5 100644 --- a/lib/libusb/usb-core.h +++ b/lib/libusb/usb-core.h @@ -79,6 +79,7 @@ enum USB_SPEED_TYPE { struct usb_dev { struct usb_dev *next; + struct usb_dev *hub; struct usb_hcd_dev *hcidev; struct usb_pipe *intr; struct usb_pipe *control; diff --git a/lib/libusb/usb-hub.c b/lib/libusb/usb-hub.c index bb8a309..5f56630 100644 --- a/lib/libusb/usb-hub.c +++ b/lib/libusb/usb-hub.c @@ -13,6 +13,7 @@ #include <stdio.h> #include <string.h> #include "usb-core.h" +#include "usb-xhci.h" #undef HUB_DEBUG //#define HUB_DEBUG @@ -151,11 +152,37 @@ static int hub_check_port(struct usb_dev *dev, int port) return false; } +static bool usb_hub_init_dev(struct usb_dev *hub_dev, int port) +{ + struct usb_dev *newdev; + + if (hub_dev->hcidev->type == USB_XHCI) { + /* + * USB3 devices need special setup (e.g. with assigning + * a slot ID and route string), which will all be done + * by usb3_dev_init() - it also calls usb_devpool_get(), + * usb_setup_new_device() and usb_slof_populate_new_device() + * internally, so we can return immediately after this step. + */ + return usb3_dev_init(hub_dev->hcidev->priv, hub_dev, port); + } + + newdev = usb_devpool_get(); + dprintf("usb-hub: allocated device %p\n", newdev); + newdev->hub = hub_dev; + newdev->hcidev = hub_dev->hcidev; + if (usb_setup_new_device(newdev, port)) { + usb_slof_populate_new_device(newdev); + return true; + } + + return false; +} + unsigned int usb_hub_init(void *hubdev) { struct usb_dev *dev = hubdev; struct usb_dev_hub_descr hub; - struct usb_dev *newdev; int i; dprintf("%s: enter %p\n", __func__, dev); @@ -172,12 +199,7 @@ unsigned int usb_hub_init(void *hubdev) dprintf("***********************************************\n"); dprintf("\t\tusb-hub: device found %d\n", i); dprintf("***********************************************\n"); - newdev = usb_devpool_get(); - dprintf("usb-hub: allocated device %p\n", newdev); - newdev->hcidev = dev->hcidev; - if (usb_setup_new_device(newdev, i)) - usb_slof_populate_new_device(newdev); - else + if (!usb_hub_init_dev(dev, i)) printf("usb-hub: unable to setup device on port %d\n", i); } } diff --git a/lib/libusb/usb-xhci.c b/lib/libusb/usb-xhci.c index 931d779..f3de6fb 100644 --- a/lib/libusb/usb-xhci.c +++ b/lib/libusb/usb-xhci.c @@ -528,7 +528,8 @@ static uint32_t usb_control_max_packet(uint32_t speed) return max_packet; } -static bool xhci_alloc_dev(struct xhci_hcd *xhcd, uint32_t slot_id, uint32_t port) +static bool xhci_alloc_dev(struct xhci_hcd *xhcd, struct usb_dev *hub, + uint32_t slot_id, uint32_t port) { struct usb_dev *dev; struct xhci_dev *xdev; @@ -629,6 +630,7 @@ static bool xhci_alloc_dev(struct xhci_hcd *xhcd, uint32_t slot_id, uint32_t por dev->speed = USB_SUPER_SPEED; dev->addr = USB_DEV_ADDRESS(slot->field4); dev->port = newport; + dev->hub = hub; dev->priv = xdev; xdev->dev = dev; if (usb_setup_new_device(dev, newport)) { @@ -654,7 +656,7 @@ static void xhci_free_dev(struct xhci_dev *xdev) xhci_free_ctx(&xdev->out_ctx, XHCI_CTX_BUF_SIZE); } -static bool usb3_dev_init(struct xhci_hcd *xhcd, uint32_t port) +bool usb3_dev_init(struct xhci_hcd *xhcd, struct usb_dev *hub, uint32_t port) { /* Device enable slot */ xhci_send_enable_slot(xhcd, port); @@ -663,7 +665,7 @@ static bool usb3_dev_init(struct xhci_hcd *xhcd, uint32_t port) return false; } dprintf("SLOT ID: %d\n", xhcd->slot_id); - if (!xhci_alloc_dev(xhcd, xhcd->slot_id, port)) { + if (!xhci_alloc_dev(xhcd, hub, xhcd->slot_id, port)) { dprintf("Unable to allocate device\n"); return false; } @@ -741,7 +743,7 @@ static int xhci_port_scan(struct xhci_hcd *xhcd, dprintf("Port reset complete %d\n", i); } print_port_status(prs); - if (!usb3_dev_init(xhcd, (i - (port_off - 1)))) { + if (!usb3_dev_init(xhcd, NULL, (i - (port_off - 1)))) { dprintf("USB device initialization failed\n"); } } diff --git a/lib/libusb/usb-xhci.h b/lib/libusb/usb-xhci.h index 793f18c..0fd2d8e 100644 --- a/lib/libusb/usb-xhci.h +++ b/lib/libusb/usb-xhci.h @@ -372,4 +372,7 @@ struct xhci_pipe { uint32_t buflen; }; +extern bool usb3_dev_init(struct xhci_hcd *xhcd, struct usb_dev *hub, + uint32_t port); + #endif /* USB_XHCI_H */ |