ChangeSet 1.1525.6.3, 2003/07/01 13:30:15-07:00, greg@kroah.com [PATCH] USB: make struct usb_bus a struct class_device This creates sys/class/usb_host/ which lists all usb hosts in the system. drivers/usb/core/hcd-pci.c | 16 ++++---- drivers/usb/core/hcd.c | 83 +++++++++++++++++++++++++++----------------- drivers/usb/core/hcd.h | 5 +- drivers/usb/core/usb.c | 12 +++++- drivers/usb/host/hc_sl811.c | 2 - include/linux/usb.h | 4 +- 6 files changed, 77 insertions(+), 45 deletions(-) diff -Nru a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c --- a/drivers/usb/core/hcd-pci.c Tue Jul 1 14:22:59 2003 +++ b/drivers/usb/core/hcd-pci.c Tue Jul 1 14:22:59 2003 @@ -38,6 +38,14 @@ /*-------------------------------------------------------------------------*/ +static void hcd_pci_release(struct usb_bus *bus) +{ + struct usb_hcd *hcd = bus->hcpriv; + + if (hcd) + hcd->driver->hcd_free(hcd); +} + /* configure so an HC device and id are always provided */ /* always called with process context; sleeping is OK */ @@ -172,6 +180,7 @@ usb_bus_init (&hcd->self); hcd->self.op = &usb_hcd_operations; hcd->self.hcpriv = (void *) hcd; + hcd->self.release = &hcd_pci_release; INIT_LIST_HEAD (&hcd->dev_list); @@ -234,13 +243,6 @@ } usb_deregister_bus (&hcd->self); - if (atomic_read (&hcd->self.refcnt) != 1) { - dev_warn (hcd->controller, - "dangling refs (%d) to bus %d!\n", - atomic_read (&hcd->self.refcnt) - 1, - hcd->self.busnum); - } - hcd->driver->hcd_free (hcd); } EXPORT_SYMBOL (usb_hcd_pci_remove); diff -Nru a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c --- a/drivers/usb/core/hcd.c Tue Jul 1 14:22:59 2003 +++ b/drivers/usb/core/hcd.c Tue Jul 1 14:22:59 2003 @@ -557,20 +557,52 @@ /*-------------------------------------------------------------------------*/ /* exported only within usbcore */ -void usb_bus_get (struct usb_bus *bus) +struct usb_bus *usb_bus_get (struct usb_bus *bus) { - atomic_inc (&bus->refcnt); + struct class_device *tmp; + + if (!bus) + return NULL; + + tmp = class_device_get(&bus->class_dev); + if (tmp) + return to_usb_bus(tmp); + else + return NULL; } /* exported only within usbcore */ void usb_bus_put (struct usb_bus *bus) { - if (atomic_dec_and_test (&bus->refcnt)) - kfree (bus); + if (bus) + class_device_put(&bus->class_dev); } /*-------------------------------------------------------------------------*/ +static void usb_host_release(struct class_device *class_dev) +{ + struct usb_bus *bus = to_usb_bus(class_dev); + + if (bus->release) + bus->release(bus); +} + +static struct class usb_host_class = { + .name = "usb_host", + .release = &usb_host_release, +}; + +void usb_host_init(void) +{ + class_register(&usb_host_class); +} + +void usb_host_cleanup(void) +{ + class_unregister(&usb_host_class); +} + /** * usb_bus_init - shared initialization code * @bus: the bus structure being initialized @@ -592,8 +624,6 @@ bus->bandwidth_isoc_reqs = 0; INIT_LIST_HEAD (&bus->bus_list); - - atomic_set (&bus->refcnt, 1); } EXPORT_SYMBOL (usb_bus_init); @@ -607,7 +637,7 @@ * * If no memory is available, NULL is returned. * - * The caller should call usb_free_bus() when it is finished with the structure. + * The caller should call usb_put_bus() when it is finished with the structure. */ struct usb_bus *usb_alloc_bus (struct usb_operations *op) { @@ -616,32 +646,13 @@ bus = kmalloc (sizeof *bus, GFP_KERNEL); if (!bus) return NULL; + memset(bus, 0, sizeof(struct usb_bus)); usb_bus_init (bus); bus->op = op; return bus; } EXPORT_SYMBOL (usb_alloc_bus); -/** - * usb_free_bus - frees the memory used by a bus structure - * @bus: pointer to the bus to free - * - * To be invoked by a HCD, only as the last step of decoupling from - * hardware. It is an error to call this if the reference count is - * anything but one. That would indicate that some system component - * did not correctly shut down, and thought the hardware was still - * accessible. - */ -void usb_free_bus (struct usb_bus *bus) -{ - if (!bus) - return; - if (atomic_read (&bus->refcnt) != 1) - err ("usb_free_bus #%d, count != 1", bus->busnum); - usb_bus_put (bus); -} -EXPORT_SYMBOL (usb_free_bus); - /*-------------------------------------------------------------------------*/ /** @@ -652,9 +663,10 @@ * Assigns a bus number, and links the controller into usbcore data * structures so that it can be seen by scanning the bus list. */ -void usb_register_bus(struct usb_bus *bus) +int usb_register_bus(struct usb_bus *bus) { int busnum; + int retval; down (&usb_bus_list_lock); busnum = find_next_zero_bit (busmap.busmap, USB_MAXBUS, 1); @@ -664,15 +676,24 @@ } else warn ("too many buses"); - usb_bus_get (bus); + snprintf(bus->class_dev.class_id, BUS_ID_SIZE, "usb%d", busnum); + bus->class_dev.class = &usb_host_class; + bus->class_dev.dev = bus->controller; + retval = class_device_register(&bus->class_dev); + if (retval) { + clear_bit(busnum, busmap.busmap); + up(&usb_bus_list_lock); + return retval; + } - /* Add it to the list of buses */ + /* Add it to the local list of buses */ list_add (&bus->bus_list, &usb_bus_list); up (&usb_bus_list_lock); usbfs_add_bus (bus); dev_info (bus->controller, "new USB bus registered, assigned bus number %d\n", bus->busnum); + return 0; } EXPORT_SYMBOL (usb_register_bus); @@ -701,7 +722,7 @@ clear_bit (bus->busnum, busmap.busmap); - usb_bus_put (bus); + class_device_unregister(&bus->class_dev); } EXPORT_SYMBOL (usb_deregister_bus); diff -Nru a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h --- a/drivers/usb/core/hcd.h Tue Jul 1 14:22:59 2003 +++ b/drivers/usb/core/hcd.h Tue Jul 1 14:22:59 2003 @@ -347,9 +347,8 @@ /*-------------------------------------------------------------------------*/ extern struct usb_bus *usb_alloc_bus (struct usb_operations *); -extern void usb_free_bus (struct usb_bus *); -extern void usb_register_bus (struct usb_bus *); +extern int usb_register_bus (struct usb_bus *); extern void usb_deregister_bus (struct usb_bus *); extern int usb_register_root_hub (struct usb_device *usb_dev, @@ -369,7 +368,7 @@ extern struct list_head usb_bus_list; extern struct semaphore usb_bus_list_lock; -extern void usb_bus_get (struct usb_bus *bus); +extern struct usb_bus *usb_bus_get (struct usb_bus *bus); extern void usb_bus_put (struct usb_bus *bus); extern int usb_find_interface_driver (struct usb_device *dev, diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c --- a/drivers/usb/core/usb.c Tue Jul 1 14:22:59 2003 +++ b/drivers/usb/core/usb.c Tue Jul 1 14:22:59 2003 @@ -54,6 +54,8 @@ extern void usb_hub_cleanup(void); extern int usb_major_init(void); extern void usb_major_cleanup(void); +extern int usb_host_init(void); +extern void usb_host_cleanup(void); int nousb; /* Disable USB when built into kernel image */ @@ -652,11 +654,15 @@ memset(dev, 0, sizeof(*dev)); + bus = usb_bus_get(bus); + if (!bus) { + kfree(dev); + return NULL; + } + device_initialize(&dev->dev); dev->state = USB_STATE_ATTACHED; - usb_bus_get(bus); - if (!parent) dev->devpath [0] = '0'; dev->bus = bus; @@ -1531,6 +1537,7 @@ } bus_register(&usb_bus_type); + usb_host_init(); usb_major_init(); usbfs_init(); usb_hub_init(); @@ -1553,6 +1560,7 @@ usb_major_cleanup(); usbfs_cleanup(); usb_hub_cleanup(); + usb_host_cleanup(); bus_unregister(&usb_bus_type); } diff -Nru a/drivers/usb/host/hc_sl811.c b/drivers/usb/host/hc_sl811.c --- a/drivers/usb/host/hc_sl811.c Tue Jul 1 14:22:59 2003 +++ b/drivers/usb/host/hc_sl811.c Tue Jul 1 14:22:59 2003 @@ -1205,7 +1205,7 @@ } usb_deregister_bus (hci->bus); - usb_free_bus (hci->bus); + usb_put_bus (hci->bus); list_del_init (&hci->hci_hcd_list); diff -Nru a/include/linux/usb.h b/include/linux/usb.h --- a/include/linux/usb.h Tue Jul 1 14:22:59 2003 +++ b/include/linux/usb.h Tue Jul 1 14:22:59 2003 @@ -207,8 +207,10 @@ struct dentry *usbfs_dentry; /* usbfs dentry entry for the bus */ struct dentry *usbdevfs_dentry; /* usbdevfs dentry entry for the bus */ - atomic_t refcnt; + struct class_device class_dev; /* class device for this bus */ + void (*release)(struct usb_bus *bus); /* function to destroy this bus's memory */ }; +#define to_usb_bus(d) container_of(d, struct usb_bus, class_dev) /* -------------------------------------------------------------------------- */