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 <sjg@chromium.org> Reviewed-by: Marek Vasut <marex@denx.de>
This commit is contained in:
parent
cad4291cd0
commit
79b5888729
19
common/usb.c
19
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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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_ */
|
||||
|
Loading…
Reference in New Issue
Block a user