dm: usb: Adjust usb_alloc_new_device() to return an error
authorSimon Glass <sjg@chromium.org>
Wed, 25 Mar 2015 18:22:01 +0000 (12:22 -0600)
committerSimon Glass <sjg@chromium.org>
Sat, 18 Apr 2015 17:11:20 +0000 (11:11 -0600)
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@chromium.org>
Reviewed-by: Marek Vasut <marex@denx.de>
common/usb.c
common/usb_hub.c
include/usb.h

index d94640a99e866d168174be1f11e91428296ba196..4f3713d92f3532adda085edebcfb016fa7ebe8e8 100644 (file)
@@ -94,8 +94,8 @@ int usb_init(void)
                controllers_initialized++;
                start_index = dev_index;
                printf("scanning bus %d for devices... ", i);
-               dev = usb_alloc_new_device(ctrl);
-               if (!dev)
+               ret = usb_alloc_new_device(ctrl, &dev);
+               if (ret)
                        break;
 
                /*
@@ -104,7 +104,7 @@ int usb_init(void)
                 */
                ret = usb_new_device(dev);
                if (ret)
-                       usb_free_device();
+                       usb_free_device(dev->controller);
 
                if (start_index == dev_index) {
                        puts("No USB Device found\n");
@@ -833,16 +833,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;
@@ -852,7 +849,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;
 }
 
 /*
@@ -860,7 +859,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);
index f54a404a4958bb1bce61ab0a7b084abb95a9e413..020cdc6605ea8f5cc19bf4bf4e38d97692061a26 100644 (file)
@@ -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>
@@ -214,16 +215,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);
@@ -241,47 +244,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;
 }
 
 
index 67615eaa2269c60f6bba4f3d019f5b2f2303c720..8cedaa23f8ca2cf46f32155b4ebf3dbcd6a7388e 100644 (file)
@@ -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_ */