Commit 6ee56790 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

[PATCH] USB: make struct usb_bus a struct class_device

This creates sys/class/usb_host/ which lists all usb hosts in the system.
parent 37a46d38
...@@ -38,6 +38,14 @@ ...@@ -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 */ /* configure so an HC device and id are always provided */
/* always called with process context; sleeping is OK */ /* always called with process context; sleeping is OK */
...@@ -172,6 +180,7 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id) ...@@ -172,6 +180,7 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
usb_bus_init (&hcd->self); usb_bus_init (&hcd->self);
hcd->self.op = &usb_hcd_operations; hcd->self.op = &usb_hcd_operations;
hcd->self.hcpriv = (void *) hcd; hcd->self.hcpriv = (void *) hcd;
hcd->self.release = &hcd_pci_release;
INIT_LIST_HEAD (&hcd->dev_list); INIT_LIST_HEAD (&hcd->dev_list);
...@@ -234,13 +243,6 @@ void usb_hcd_pci_remove (struct pci_dev *dev) ...@@ -234,13 +243,6 @@ void usb_hcd_pci_remove (struct pci_dev *dev)
} }
usb_deregister_bus (&hcd->self); 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); EXPORT_SYMBOL (usb_hcd_pci_remove);
......
...@@ -557,20 +557,52 @@ void usb_rh_status_dequeue (struct usb_hcd *hcd, struct urb *urb) ...@@ -557,20 +557,52 @@ void usb_rh_status_dequeue (struct usb_hcd *hcd, struct urb *urb)
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
/* exported only within usbcore */ /* 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 */ /* exported only within usbcore */
void usb_bus_put (struct usb_bus *bus) void usb_bus_put (struct usb_bus *bus)
{ {
if (atomic_dec_and_test (&bus->refcnt)) if (bus)
kfree (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 * usb_bus_init - shared initialization code
* @bus: the bus structure being initialized * @bus: the bus structure being initialized
...@@ -592,8 +624,6 @@ void usb_bus_init (struct usb_bus *bus) ...@@ -592,8 +624,6 @@ void usb_bus_init (struct usb_bus *bus)
bus->bandwidth_isoc_reqs = 0; bus->bandwidth_isoc_reqs = 0;
INIT_LIST_HEAD (&bus->bus_list); INIT_LIST_HEAD (&bus->bus_list);
atomic_set (&bus->refcnt, 1);
} }
EXPORT_SYMBOL (usb_bus_init); EXPORT_SYMBOL (usb_bus_init);
...@@ -607,7 +637,7 @@ EXPORT_SYMBOL (usb_bus_init); ...@@ -607,7 +637,7 @@ EXPORT_SYMBOL (usb_bus_init);
* *
* If no memory is available, NULL is returned. * 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) struct usb_bus *usb_alloc_bus (struct usb_operations *op)
{ {
...@@ -616,32 +646,13 @@ struct usb_bus *usb_alloc_bus (struct usb_operations *op) ...@@ -616,32 +646,13 @@ struct usb_bus *usb_alloc_bus (struct usb_operations *op)
bus = kmalloc (sizeof *bus, GFP_KERNEL); bus = kmalloc (sizeof *bus, GFP_KERNEL);
if (!bus) if (!bus)
return NULL; return NULL;
memset(bus, 0, sizeof(struct usb_bus));
usb_bus_init (bus); usb_bus_init (bus);
bus->op = op; bus->op = op;
return bus; return bus;
} }
EXPORT_SYMBOL (usb_alloc_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 @@ EXPORT_SYMBOL (usb_free_bus); ...@@ -652,9 +663,10 @@ EXPORT_SYMBOL (usb_free_bus);
* Assigns a bus number, and links the controller into usbcore data * Assigns a bus number, and links the controller into usbcore data
* structures so that it can be seen by scanning the bus list. * 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 busnum;
int retval;
down (&usb_bus_list_lock); down (&usb_bus_list_lock);
busnum = find_next_zero_bit (busmap.busmap, USB_MAXBUS, 1); busnum = find_next_zero_bit (busmap.busmap, USB_MAXBUS, 1);
...@@ -664,15 +676,24 @@ void usb_register_bus(struct usb_bus *bus) ...@@ -664,15 +676,24 @@ void usb_register_bus(struct usb_bus *bus)
} else } else
warn ("too many buses"); 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); list_add (&bus->bus_list, &usb_bus_list);
up (&usb_bus_list_lock); up (&usb_bus_list_lock);
usbfs_add_bus (bus); usbfs_add_bus (bus);
dev_info (bus->controller, "new USB bus registered, assigned bus number %d\n", bus->busnum); dev_info (bus->controller, "new USB bus registered, assigned bus number %d\n", bus->busnum);
return 0;
} }
EXPORT_SYMBOL (usb_register_bus); EXPORT_SYMBOL (usb_register_bus);
...@@ -701,7 +722,7 @@ void usb_deregister_bus (struct usb_bus *bus) ...@@ -701,7 +722,7 @@ void usb_deregister_bus (struct usb_bus *bus)
clear_bit (bus->busnum, busmap.busmap); clear_bit (bus->busnum, busmap.busmap);
usb_bus_put (bus); class_device_unregister(&bus->class_dev);
} }
EXPORT_SYMBOL (usb_deregister_bus); EXPORT_SYMBOL (usb_deregister_bus);
......
...@@ -347,9 +347,8 @@ extern long usb_calc_bus_time (int speed, int is_input, ...@@ -347,9 +347,8 @@ 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 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 void usb_deregister_bus (struct usb_bus *);
extern int usb_register_root_hub (struct usb_device *usb_dev, extern int usb_register_root_hub (struct usb_device *usb_dev,
...@@ -369,7 +368,7 @@ static inline int hcd_register_root (struct usb_hcd *hcd) ...@@ -369,7 +368,7 @@ static inline int hcd_register_root (struct usb_hcd *hcd)
extern struct list_head usb_bus_list; extern struct list_head usb_bus_list;
extern struct semaphore usb_bus_list_lock; 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 void usb_bus_put (struct usb_bus *bus);
extern int usb_find_interface_driver (struct usb_device *dev, extern int usb_find_interface_driver (struct usb_device *dev,
......
...@@ -54,6 +54,8 @@ extern int usb_hub_init(void); ...@@ -54,6 +54,8 @@ extern int usb_hub_init(void);
extern void usb_hub_cleanup(void); extern void usb_hub_cleanup(void);
extern int usb_major_init(void); extern int usb_major_init(void);
extern void usb_major_cleanup(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 */ int nousb; /* Disable USB when built into kernel image */
...@@ -652,11 +654,15 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus) ...@@ -652,11 +654,15 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus)
memset(dev, 0, sizeof(*dev)); memset(dev, 0, sizeof(*dev));
bus = usb_bus_get(bus);
if (!bus) {
kfree(dev);
return NULL;
}
device_initialize(&dev->dev); device_initialize(&dev->dev);
dev->state = USB_STATE_ATTACHED; dev->state = USB_STATE_ATTACHED;
usb_bus_get(bus);
if (!parent) if (!parent)
dev->devpath [0] = '0'; dev->devpath [0] = '0';
dev->bus = bus; dev->bus = bus;
...@@ -1531,6 +1537,7 @@ static int __init usb_init(void) ...@@ -1531,6 +1537,7 @@ static int __init usb_init(void)
} }
bus_register(&usb_bus_type); bus_register(&usb_bus_type);
usb_host_init();
usb_major_init(); usb_major_init();
usbfs_init(); usbfs_init();
usb_hub_init(); usb_hub_init();
...@@ -1553,6 +1560,7 @@ static void __exit usb_exit(void) ...@@ -1553,6 +1560,7 @@ static void __exit usb_exit(void)
usb_major_cleanup(); usb_major_cleanup();
usbfs_cleanup(); usbfs_cleanup();
usb_hub_cleanup(); usb_hub_cleanup();
usb_host_cleanup();
bus_unregister(&usb_bus_type); bus_unregister(&usb_bus_type);
} }
......
...@@ -1205,7 +1205,7 @@ static void hc_release_hci (hci_t * hci) ...@@ -1205,7 +1205,7 @@ static void hc_release_hci (hci_t * hci)
} }
usb_deregister_bus (hci->bus); usb_deregister_bus (hci->bus);
usb_free_bus (hci->bus); usb_put_bus (hci->bus);
list_del_init (&hci->hci_hcd_list); list_del_init (&hci->hci_hcd_list);
......
...@@ -207,8 +207,10 @@ struct usb_bus { ...@@ -207,8 +207,10 @@ struct usb_bus {
struct dentry *usbfs_dentry; /* usbfs dentry entry for the bus */ struct dentry *usbfs_dentry; /* usbfs dentry entry for the bus */
struct dentry *usbdevfs_dentry; /* usbdevfs 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)
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
......
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