From 79b5888729b65e7040d6a964f0015fc2c21b2385 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Mar 2015 12:22:01 -0600 Subject: [PATCH] dm: usb: Adjust usb_alloc_new_device() to return an error 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 Reviewed-by: Marek Vasut --- common/usb.c | 19 +++++++++---------- common/usb_hub.c | 41 ++++++++++++++++++++++++++--------------- include/usb.h | 20 ++++++++++++++++++-- 3 files changed, 53 insertions(+), 27 deletions(-) diff --git a/common/usb.c b/common/usb.c index d94640a99e..4f3713d92f 100644 --- a/common/usb.c +++ b/common/usb.c @@ -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); diff --git a/common/usb_hub.c b/common/usb_hub.c index f54a404a49..020cdc6605 100644 --- a/common/usb_hub.c +++ b/common/usb_hub.c @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -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; } diff --git a/include/usb.h b/include/usb.h index 67615eaa22..8cedaa23f8 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.30.2