/*-------------------------------------------------------------------------*/
+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 */
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);
}
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);
/*-------------------------------------------------------------------------*/
/* 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
bus->bandwidth_isoc_reqs = 0;
INIT_LIST_HEAD (&bus->bus_list);
-
- atomic_set (&bus->refcnt, 1);
}
EXPORT_SYMBOL (usb_bus_init);
*
* 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)
{
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);
-
/*-------------------------------------------------------------------------*/
/**
* 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);
} 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);
clear_bit (bus->busnum, busmap.busmap);
- usb_bus_put (bus);
+ class_device_unregister(&bus->class_dev);
}
EXPORT_SYMBOL (usb_deregister_bus);
/*-------------------------------------------------------------------------*/
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,
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,