Commit 8ec8d20b authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman

[PATCH] usbcore: register root hub in usb_add_hcd

This patch makes usbcore automatically allocate and register the root hub
device for a new host controller when the controller is registered.  This
way the HCDs don't all have to include the same boilerplate code.  As a
pleasant side benefit, the register_root_hub routine can now be made
static and not EXPORTed.
Signed-off-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent bc96c0ad
...@@ -832,30 +832,22 @@ static void usb_deregister_bus (struct usb_bus *bus) ...@@ -832,30 +832,22 @@ static void usb_deregister_bus (struct usb_bus *bus)
} }
/** /**
* usb_hcd_register_root_hub - called by HCD to register its root hub * register_root_hub - called by usb_add_hcd() to register a root hub
* @usb_dev: the usb root hub device to be registered. * @usb_dev: the usb root hub device to be registered.
* @hcd: host controller for this root hub * @hcd: host controller for this root hub
* *
* The USB host controller calls this function to register the root hub * This function registers the root hub with the USB subsystem. It sets up
* properly with the USB subsystem. It sets up the device properly in * the device properly in the device tree and stores the root_hub pointer
* the device tree and stores the root_hub pointer in the bus structure, * in the bus structure, then calls usb_new_device() to register the usb
* then calls usb_new_device() to register the usb device. It also * device. It also assigns the root hub's USB address (always 1).
* assigns the root hub's USB address (always 1).
*/ */
int usb_hcd_register_root_hub (struct usb_device *usb_dev, struct usb_hcd *hcd) static int register_root_hub (struct usb_device *usb_dev,
struct usb_hcd *hcd)
{ {
struct device *parent_dev = hcd->self.controller; struct device *parent_dev = hcd->self.controller;
const int devnum = 1; const int devnum = 1;
int retval; int retval;
/* hcd->driver->start() reported can_wakeup, probably with
* assistance from board's boot firmware.
* NOTE: normal devices won't enable wakeup by default.
*/
if (hcd->can_wakeup)
dev_dbg (parent_dev, "supports USB remote wakeup\n");
hcd->remote_wakeup = hcd->can_wakeup;
usb_dev->devnum = devnum; usb_dev->devnum = devnum;
usb_dev->bus->devnum_next = devnum + 1; usb_dev->bus->devnum_next = devnum + 1;
memset (&usb_dev->bus->devmap.devicemap, 0, memset (&usb_dev->bus->devmap.devicemap, 0,
...@@ -898,7 +890,6 @@ int usb_hcd_register_root_hub (struct usb_device *usb_dev, struct usb_hcd *hcd) ...@@ -898,7 +890,6 @@ int usb_hcd_register_root_hub (struct usb_device *usb_dev, struct usb_hcd *hcd)
return retval; return retval;
} }
EXPORT_SYMBOL_GPL(usb_hcd_register_root_hub);
void usb_enable_root_hub_irq (struct usb_bus *bus) void usb_enable_root_hub_irq (struct usb_bus *bus)
{ {
...@@ -1725,6 +1716,7 @@ int usb_add_hcd(struct usb_hcd *hcd, ...@@ -1725,6 +1716,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
unsigned int irqnum, unsigned long irqflags) unsigned int irqnum, unsigned long irqflags)
{ {
int retval; int retval;
struct usb_device *rhdev;
dev_info(hcd->self.controller, "%s\n", hcd->product_desc); dev_info(hcd->self.controller, "%s\n", hcd->product_desc);
...@@ -1740,7 +1732,7 @@ int usb_add_hcd(struct usb_hcd *hcd, ...@@ -1740,7 +1732,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
} }
if ((retval = usb_register_bus(&hcd->self)) < 0) if ((retval = usb_register_bus(&hcd->self)) < 0)
goto err1; goto err_register_bus;
if (hcd->driver->irq) { if (hcd->driver->irq) {
char buf[8], *bufp = buf; char buf[8], *bufp = buf;
...@@ -1757,7 +1749,7 @@ int usb_add_hcd(struct usb_hcd *hcd, ...@@ -1757,7 +1749,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
hcd->irq_descr, hcd)) != 0) { hcd->irq_descr, hcd)) != 0) {
dev_err(hcd->self.controller, dev_err(hcd->self.controller,
"request interrupt %s failed\n", bufp); "request interrupt %s failed\n", bufp);
goto err2; goto err_request_irq;
} }
hcd->irq = irqnum; hcd->irq = irqnum;
dev_info(hcd->self.controller, "irq %s, %s 0x%08llx\n", bufp, dev_info(hcd->self.controller, "irq %s, %s 0x%08llx\n", bufp,
...@@ -1773,21 +1765,55 @@ int usb_add_hcd(struct usb_hcd *hcd, ...@@ -1773,21 +1765,55 @@ int usb_add_hcd(struct usb_hcd *hcd,
(unsigned long long)hcd->rsrc_start); (unsigned long long)hcd->rsrc_start);
} }
/* Allocate the root hub before calling hcd->driver->start(),
* but don't register it until afterward so that the hardware
* is running.
*/
if ((rhdev = usb_alloc_dev(NULL, &hcd->self, 0)) == NULL) {
dev_err(hcd->self.controller, "unable to allocate root hub\n");
retval = -ENOMEM;
goto err_allocate_root_hub;
}
rhdev->speed = (hcd->driver->flags & HCD_USB2) ? USB_SPEED_HIGH :
USB_SPEED_FULL;
/* Although in principle hcd->driver->start() might need to use rhdev,
* none of the current drivers do.
*/
if ((retval = hcd->driver->start(hcd)) < 0) { if ((retval = hcd->driver->start(hcd)) < 0) {
dev_err(hcd->self.controller, "startup error %d\n", retval); dev_err(hcd->self.controller, "startup error %d\n", retval);
goto err3; goto err_hcd_driver_start;
} }
/* hcd->driver->start() reported can_wakeup, probably with
* assistance from board's boot firmware.
* NOTE: normal devices won't enable wakeup by default.
*/
if (hcd->can_wakeup)
dev_dbg(hcd->self.controller, "supports USB remote wakeup\n");
hcd->remote_wakeup = hcd->can_wakeup;
if ((retval = register_root_hub(rhdev, hcd)) != 0)
goto err_register_root_hub;
if (hcd->uses_new_polling && hcd->poll_rh) if (hcd->uses_new_polling && hcd->poll_rh)
usb_hcd_poll_rh_status(hcd); usb_hcd_poll_rh_status(hcd);
return retval; return retval;
err3: err_register_root_hub:
hcd->driver->stop(hcd);
err_hcd_driver_start:
usb_put_dev(rhdev);
err_allocate_root_hub:
if (hcd->irq >= 0) if (hcd->irq >= 0)
free_irq(irqnum, hcd); free_irq(irqnum, hcd);
err2:
err_request_irq:
usb_deregister_bus(&hcd->self); usb_deregister_bus(&hcd->self);
err1:
err_register_bus:
hcd_buffer_destroy(hcd); hcd_buffer_destroy(hcd);
return retval; return retval;
} }
......
...@@ -353,9 +353,6 @@ extern long usb_calc_bus_time (int speed, int is_input, ...@@ -353,9 +353,6 @@ extern long usb_calc_bus_time (int speed, int is_input,
extern struct usb_bus *usb_alloc_bus (struct usb_operations *); extern struct usb_bus *usb_alloc_bus (struct usb_operations *);
extern int usb_hcd_register_root_hub (struct usb_device *usb_dev,
struct usb_hcd *hcd);
extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd); extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd);
extern void usb_set_device_state(struct usb_device *udev, extern void usb_set_device_state(struct usb_device *udev,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment