diff mbox

[v2,3/5] usb: Initialize USB3 devices on a hub and keep track of hub topology

Message ID 1470129584-27225-4-git-send-email-thuth@redhat.com
State Accepted
Headers show

Commit Message

Thomas Huth Aug. 2, 2016, 9:19 a.m. UTC
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>
---
 lib/libusb/usb-core.h |  1 +
 lib/libusb/usb-hub.c  | 36 +++++++++++++++++++++++++++++-------
 lib/libusb/usb-xhci.c | 10 ++++++----
 lib/libusb/usb-xhci.h |  3 +++
 4 files changed, 39 insertions(+), 11 deletions(-)

Comments

Nikunj A Dadhania Aug. 2, 2016, 9:52 a.m. UTC | #1
Thomas Huth <thuth@redhat.com> writes:

> 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>

Regards
Nikunj
diff mbox

Patch

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 eda5929..2d34133 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 */