[SLOF] [PATCH 2/5] Stack optimization in libusb: split up setup_new_device()

Thomas Huth thuth at redhat.com
Thu Nov 26 06:58:16 AEDT 2015


When scanning hubs, the code in libusb can be called recursively, for
example usb_hub_init() calls setup_new_device(), which then calls
slof_usb_handle() to execute Forth code for the next device.
If that next device is a hub, we end up recursively in usb_hub_init()
again.
Since stack space is limited in SLOF, we can optimize here a little
bit by splitting up the setup_new_device() function into the part
that retrieves the descriptors (which takes most of the stack space
in this code path since the descriptors are placed on the stack),
and the part that populates the the device tree node of the new
device (which is responsible for the recursion).

Signed-off-by: Thomas Huth <thuth at redhat.com>
---
 lib/libusb/usb-core.c | 35 ++---------------------------------
 lib/libusb/usb-core.h |  7 +++++--
 lib/libusb/usb-ehci.c |  4 +++-
 lib/libusb/usb-hub.c  |  4 +++-
 lib/libusb/usb-ohci.c |  4 +++-
 lib/libusb/usb-slof.c | 34 +++++++++++++++++++++++++++++++++-
 lib/libusb/usb-xhci.c |  4 +++-
 7 files changed, 52 insertions(+), 40 deletions(-)

diff --git a/lib/libusb/usb-core.c b/lib/libusb/usb-core.c
index 6719c57..a55f016 100644
--- a/lib/libusb/usb-core.c
+++ b/lib/libusb/usb-core.c
@@ -383,8 +383,6 @@ int usb_hid_exit(void *vdev)
 	return true;
 }
 
-#define usb_get_intf_class(x) ((x & 0x00FF0000) >> 16)
-
 int usb_msc_init(void *vdev)
 {
 	struct usb_dev *dev;
@@ -420,7 +418,7 @@ int usb_msc_exit(void *vdev)
 	return true;
 }
 
-static int usb_msc_reset(struct usb_dev *dev)
+int usb_msc_reset(struct usb_dev *dev)
 {
 	struct usb_dev_req req;
 
@@ -485,7 +483,7 @@ static int usb_handle_device(struct usb_dev *dev, struct usb_dev_config_descr *c
 	return true;
 }
 
-int setup_new_device(struct usb_dev *dev, unsigned int port)
+int usb_setup_new_device(struct usb_dev *dev, unsigned int port)
 {
 	struct usb_dev_descr descr;
 	struct usb_dev_config_descr cfg;
@@ -552,35 +550,6 @@ int setup_new_device(struct usb_dev *dev, unsigned int port)
 	if (!usb_handle_device(dev, &cfg, data, len))
 		goto fail_mem_free;
 
-	switch (usb_get_intf_class(dev->class)) {
-	case 3:
-		dprintf("HID found %06X\n", dev->class);
-		slof_usb_handle(dev);
-		break;
-	case 8:
-		dprintf("MASS STORAGE found %d %06X\n", dev->intf_num,
-			dev->class);
-		if ((dev->class & 0x50) != 0x50) { /* Bulk-only supported */
-			printf("Device not supported %06X\n", dev->class);
-			goto fail_mem_free;
-		}
-
-		if (!usb_msc_reset(dev)) {
-			printf("%s: bulk reset failed\n", __func__);
-			goto fail_mem_free;
-		}
-		SLOF_msleep(100);
-		slof_usb_handle(dev);
-		break;
-	case 9:
-		dprintf("HUB found\n");
-		slof_usb_handle(dev);
-		break;
-	default:
-		printf("USB Interface class -%x- Not supported\n", dev->class);
-		break;
-	}
-
 	SLOF_dma_free(data, len);
 	return true;
 fail_mem_free:
diff --git a/lib/libusb/usb-core.h b/lib/libusb/usb-core.h
index 7441979..a35df34 100644
--- a/lib/libusb/usb-core.h
+++ b/lib/libusb/usb-core.h
@@ -261,6 +261,8 @@ struct usb_hcd_ops {
 	unsigned int usb_type;
 };
 
+#define usb_get_intf_class(x) ((x & 0x00FF0000) >> 16)
+
 extern void usb_hcd_register(struct usb_hcd_ops *ops);
 extern struct usb_pipe *usb_get_pipe(struct usb_dev *dev, struct usb_ep_descr *ep,
 				char *buf, size_t len);
@@ -269,11 +271,12 @@ extern int usb_poll_intr(struct usb_pipe *pipe, uint8_t *buf);
 extern int usb_send_ctrl(struct usb_pipe *pipe, struct usb_dev_req *req, void *data);
 extern struct usb_dev *usb_devpool_get(void);
 extern void usb_devpool_put(struct usb_dev *);
-extern int setup_new_device(struct usb_dev *dev, unsigned int port);
-extern int slof_usb_handle(struct usb_dev *dev);
+extern int usb_setup_new_device(struct usb_dev *dev, unsigned int port);
+extern void usb_slof_populate_new_device(struct usb_dev *dev);
 extern int usb_dev_populate_pipe(struct usb_dev *dev, struct usb_ep_descr *ep,
 				void *buf, size_t len);
 extern int usb_hid_kbd_init(struct usb_dev *dev);
 extern int usb_hid_kbd_exit(struct usb_dev *dev);
+extern int usb_msc_reset(struct usb_dev *dev);
 extern void usb_msc_resetrecovery(struct usb_dev *dev);
 #endif
diff --git a/lib/libusb/usb-ehci.c b/lib/libusb/usb-ehci.c
index 4cca0da..60af9e1 100644
--- a/lib/libusb/usb-ehci.c
+++ b/lib/libusb/usb-ehci.c
@@ -79,7 +79,9 @@ static int ehci_hub_check_ports(struct ehci_hcd *ehcd)
 			dprintf("usb-ehci: allocated device %p\n", dev);
 			dev->hcidev = ehcd->hcidev;
 			dev->speed = USB_HIGH_SPEED; /* TODO: Check for Low/Full speed device */
-			if (!setup_new_device(dev, i))
+			if (usb_setup_new_device(dev, i))
+				usb_slof_populate_new_device(dev);
+			else
 				printf("usb-ehci: unable to setup device on port %d\n", i);
 		}
 	}
diff --git a/lib/libusb/usb-hub.c b/lib/libusb/usb-hub.c
index 7059cd0..bb8a309 100644
--- a/lib/libusb/usb-hub.c
+++ b/lib/libusb/usb-hub.c
@@ -175,7 +175,9 @@ unsigned int usb_hub_init(void *hubdev)
 			newdev = usb_devpool_get();
 			dprintf("usb-hub: allocated device %p\n", newdev);
 			newdev->hcidev = dev->hcidev;
-			if (!setup_new_device(newdev, i))
+			if (usb_setup_new_device(newdev, i))
+				usb_slof_populate_new_device(newdev);
+			else
 				printf("usb-hub: unable to setup device on port %d\n", i);
 		}
 	}
diff --git a/lib/libusb/usb-ohci.c b/lib/libusb/usb-ohci.c
index 0e84004..2547e02 100644
--- a/lib/libusb/usb-ohci.c
+++ b/lib/libusb/usb-ohci.c
@@ -192,7 +192,9 @@ static void ohci_hub_check_ports(struct ohci_hcd *ohcd)
 			dev = usb_devpool_get();
 			dprintf("usb-ohci: Device reset, setting up %p\n", dev);
 			dev->hcidev = ohcd->hcidev;
-			if (!setup_new_device(dev, i))
+			if (usb_setup_new_device(dev, i))
+				usb_slof_populate_new_device(dev);
+			else
 				printf("usb-ohci: unable to setup device on port %d\n", i);
 		}
 		if (port_status & RH_PS_PESC) {
diff --git a/lib/libusb/usb-slof.c b/lib/libusb/usb-slof.c
index de841f0..ff07055 100644
--- a/lib/libusb/usb-slof.c
+++ b/lib/libusb/usb-slof.c
@@ -26,7 +26,7 @@
 #define dprintf(_x ...)
 #endif
 
-int slof_usb_handle(struct usb_dev *dev)
+static int slof_usb_handle(struct usb_dev *dev)
 {
 	struct slof_usb_dev sdev;
 	sdev.port = dev->port;
@@ -59,3 +59,35 @@ int slof_usb_handle(struct usb_dev *dev)
 	}
 	return true;
 }
+
+void usb_slof_populate_new_device(struct usb_dev *dev)
+{
+	switch (usb_get_intf_class(dev->class)) {
+	case 3:
+		dprintf("HID found %06X\n", dev->class);
+		slof_usb_handle(dev);
+		break;
+	case 8:
+		dprintf("MASS STORAGE found %d %06X\n", dev->intf_num,
+			dev->class);
+		if ((dev->class & 0x50) != 0x50) { /* Bulk-only supported */
+			printf("Device not supported %06X\n", dev->class);
+			break;
+		}
+
+		if (!usb_msc_reset(dev)) {
+			printf("%s: bulk reset failed\n", __func__);
+			break;
+		}
+		SLOF_msleep(100);
+		slof_usb_handle(dev);
+		break;
+	case 9:
+		dprintf("HUB found\n");
+		slof_usb_handle(dev);
+		break;
+	default:
+		printf("USB Interface class -%x- Not supported\n", dev->class);
+		break;
+	}
+}
diff --git a/lib/libusb/usb-xhci.c b/lib/libusb/usb-xhci.c
index 7683c51..858cd12 100644
--- a/lib/libusb/usb-xhci.c
+++ b/lib/libusb/usb-xhci.c
@@ -608,8 +608,10 @@ static bool xhci_alloc_dev(struct xhci_hcd *xhcd, uint32_t slot_id, uint32_t por
 	dev->port = newport;
 	dev->priv = xdev;
 	xdev->dev = dev;
-	if (setup_new_device(dev, newport))
+	if (usb_setup_new_device(dev, newport)) {
+		usb_slof_populate_new_device(dev);
 		return true;
+	}
 
 	xhci_free_ctx(&xdev->out_ctx, XHCI_CTX_BUF_SIZE);
 fail_control_seg:
-- 
1.8.3.1



More information about the SLOF mailing list