[U-Boot] [PATCH v2 13/80] dm: usb: Adjust usb_alloc_new_device() to return an error

Simon Glass sjg at chromium.org
Wed Mar 25 19:22:01 CET 2015


This function returns NULL on error at present. Adjust it so that we can
return a real error, as is needed with driver model. Also improve the
error handling in its caller, usb_hub_port_connect_change(), and adjust
the code order to prepare for driver model.

Signed-off-by: Simon Glass <sjg at chromium.org>
---

Changes in v2: None

 common/usb.c     | 17 ++++++++---------
 common/usb_hub.c | 41 ++++++++++++++++++++++++++---------------
 include/usb.h    | 20 ++++++++++++++++++--
 3 files changed, 52 insertions(+), 26 deletions(-)

diff --git a/common/usb.c b/common/usb.c
index 32e15cd..f87c6a5 100644
--- a/common/usb.c
+++ b/common/usb.c
@@ -94,12 +94,12 @@ int usb_init(void)
 		controllers_initialized++;
 		start_index = dev_index;
 		printf("scanning bus %d for devices... ", i);
-		dev = usb_alloc_new_device(ctrl);
+		ret = usb_alloc_new_device(ctrl, &dev);
 		/*
 		 * device 0 is always present
 		 * (root hub, so let it analyze)
 		 */
-		if (dev)
+		if (!ret)
 			usb_new_device(dev);
 
 		if (start_index == dev_index)
@@ -827,16 +827,13 @@ struct usb_device *usb_get_dev_index(int index)
 		return &usb_dev[index];
 }
 
-/* returns a pointer of a new device structure or NULL, if
- * no device struct is available
- */
-struct usb_device *usb_alloc_new_device(void *controller)
+int usb_alloc_new_device(struct udevice *controller, struct usb_device **devp)
 {
 	int i;
 	debug("New Device %d\n", dev_index);
 	if (dev_index == USB_MAX_DEVICE) {
 		printf("ERROR, too many USB Devices, max=%d\n", USB_MAX_DEVICE);
-		return NULL;
+		return -ENOSPC;
 	}
 	/* default Address is 0, real addresses start with 1 */
 	usb_dev[dev_index].devnum = dev_index + 1;
@@ -846,7 +843,9 @@ struct usb_device *usb_alloc_new_device(void *controller)
 	usb_dev[dev_index].parent = NULL;
 	usb_dev[dev_index].controller = controller;
 	dev_index++;
-	return &usb_dev[dev_index - 1];
+	*devp = &usb_dev[dev_index - 1];
+
+	return 0;
 }
 
 /*
@@ -854,7 +853,7 @@ struct usb_device *usb_alloc_new_device(void *controller)
  * Called in error cases where configuring a newly attached
  * device fails for some reason.
  */
-void usb_free_device(void)
+void usb_free_device(struct udevice *controller)
 {
 	dev_index--;
 	debug("Freeing device node: %d\n", dev_index);
diff --git a/common/usb_hub.c b/common/usb_hub.c
index 66b4a72..7199e25 100644
--- a/common/usb_hub.c
+++ b/common/usb_hub.c
@@ -24,6 +24,7 @@
 
 #include <common.h>
 #include <command.h>
+#include <errno.h>
 #include <asm/processor.h>
 #include <asm/unaligned.h>
 #include <linux/ctype.h>
@@ -206,16 +207,18 @@ int hub_port_reset(struct usb_device *dev, int port,
 }
 
 
-void usb_hub_port_connect_change(struct usb_device *dev, int port)
+int usb_hub_port_connect_change(struct usb_device *dev, int port)
 {
 	struct usb_device *usb;
 	ALLOC_CACHE_ALIGN_BUFFER(struct usb_port_status, portsts, 1);
 	unsigned short portstatus;
+	int ret, speed;
 
 	/* Check status */
-	if (usb_get_port_status(dev, port + 1, portsts) < 0) {
+	ret = usb_get_port_status(dev, port + 1, portsts);
+	if (ret < 0) {
 		debug("get_port_status failed\n");
-		return;
+		return ret;
 	}
 
 	portstatus = le16_to_cpu(portsts->wPortStatus);
@@ -233,47 +236,55 @@ void usb_hub_port_connect_change(struct usb_device *dev, int port)
 		debug("usb_disconnect(&hub->children[port]);\n");
 		/* Return now if nothing is connected */
 		if (!(portstatus & USB_PORT_STAT_CONNECTION))
-			return;
+			return -ENOTCONN;
 	}
 	mdelay(200);
 
 	/* Reset the port */
-	if (hub_port_reset(dev, port, &portstatus) < 0) {
+	ret = hub_port_reset(dev, port, &portstatus);
+	if (ret < 0) {
 		printf("cannot reset port %i!?\n", port + 1);
-		return;
+		return ret;
 	}
 
 	mdelay(200);
 
-	/* Allocate a new device struct for it */
-	usb = usb_alloc_new_device(dev->controller);
-
 	switch (portstatus & USB_PORT_STAT_SPEED_MASK) {
 	case USB_PORT_STAT_SUPER_SPEED:
-		usb->speed = USB_SPEED_SUPER;
+		speed = USB_SPEED_SUPER;
 		break;
 	case USB_PORT_STAT_HIGH_SPEED:
-		usb->speed = USB_SPEED_HIGH;
+		speed = USB_SPEED_HIGH;
 		break;
 	case USB_PORT_STAT_LOW_SPEED:
-		usb->speed = USB_SPEED_LOW;
+		speed = USB_SPEED_LOW;
 		break;
 	default:
-		usb->speed = USB_SPEED_FULL;
+		speed = USB_SPEED_FULL;
 		break;
 	}
 
+	ret = usb_alloc_new_device(dev->controller, &usb);
+	if (ret) {
+		printf("cannot create new device: ret=%d", ret);
+		return ret;
+	}
+
 	dev->children[port] = usb;
+	usb->speed = speed;
 	usb->parent = dev;
 	usb->portnr = port + 1;
 	/* Run it through the hoops (find a driver, etc) */
-	if (usb_new_device(usb)) {
+	ret = usb_new_device(usb);
+	if (ret < 0) {
 		/* Woops, disable the port */
-		usb_free_device();
+		usb_free_device(dev->controller);
 		dev->children[port] = NULL;
 		debug("hub: disabling port %d\n", port + 1);
 		usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_ENABLE);
 	}
+
+	return ret;
 }
 
 
diff --git a/include/usb.h b/include/usb.h
index 0e1c16a..11ff5ab 100644
--- a/include/usb.h
+++ b/include/usb.h
@@ -703,10 +703,26 @@ void usb_hub_reset(void);
 int hub_port_reset(struct usb_device *dev, int port,
 			  unsigned short *portstat);
 
-struct usb_device *usb_alloc_new_device(void *controller);
+/**
+ * usb_alloc_new_device() - Allocate a new device
+ *
+ * @devp: returns a pointer of a new device structure. With driver model this
+ *		is a device pointer, but with legacy USB this pointer is
+ *		driver-specific.
+ * @return 0 if OK, -ENOSPC if we have found out of room for new devices
+ */
+int usb_alloc_new_device(struct udevice *controller, struct usb_device **devp);
+
+/**
+ * usb_free_device() - Free a partially-inited device
+ *
+ * This is an internal function. It is used to reverse the action of
+ * usb_alloc_new_device() when we hit a problem during init.
+ */
+void usb_free_device(struct udevice *controller);
 
 int usb_new_device(struct usb_device *dev);
-void usb_free_device(void);
+
 int usb_alloc_device(struct usb_device *dev);
 
 #endif /*_USB_H_ */
-- 
2.2.0.rc0.207.ga3a616c



More information about the U-Boot mailing list