Commit b14d209d authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

[PATCH] USB: use the driver model to handle reference counting of struct usb_device

parent d92e1bbd
...@@ -108,6 +108,7 @@ static int usb_parse_interface(struct usb_interface *interface, unsigned char *b ...@@ -108,6 +108,7 @@ static int usb_parse_interface(struct usb_interface *interface, unsigned char *b
interface->act_altsetting = 0; interface->act_altsetting = 0;
interface->num_altsetting = 0; interface->num_altsetting = 0;
interface->max_altsetting = USB_ALTSETTINGALLOC; interface->max_altsetting = USB_ALTSETTINGALLOC;
device_initialize(&interface->dev);
interface->altsetting = kmalloc(sizeof(*interface->altsetting) * interface->max_altsetting, interface->altsetting = kmalloc(sizeof(*interface->altsetting) * interface->max_altsetting,
GFP_KERNEL); GFP_KERNEL);
......
...@@ -23,6 +23,13 @@ ...@@ -23,6 +23,13 @@
*/ */
#include <linux/config.h> #include <linux/config.h>
#ifdef CONFIG_USB_DEBUG
#define DEBUG
#else
#undef DEBUG
#endif
#include <linux/module.h> #include <linux/module.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/bitops.h> #include <linux/bitops.h>
...@@ -33,12 +40,6 @@ ...@@ -33,12 +40,6 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#ifdef CONFIG_USB_DEBUG
#define DEBUG
#else
#undef DEBUG
#endif
#include <linux/usb.h> #include <linux/usb.h>
#include <asm/io.h> #include <asm/io.h>
...@@ -677,13 +678,14 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus) ...@@ -677,13 +678,14 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus)
memset(dev, 0, sizeof(*dev)); memset(dev, 0, sizeof(*dev));
device_initialize(&dev->dev);
usb_bus_get(bus); usb_bus_get(bus);
if (!parent) if (!parent)
dev->devpath [0] = '0'; dev->devpath [0] = '0';
dev->bus = bus; dev->bus = bus;
dev->parent = parent; dev->parent = parent;
atomic_set(&dev->refcnt, 1);
INIT_LIST_HEAD(&dev->filelist); INIT_LIST_HEAD(&dev->filelist);
init_MUTEX(&dev->serialize); init_MUTEX(&dev->serialize);
...@@ -695,7 +697,7 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus) ...@@ -695,7 +697,7 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus)
} }
/** /**
* usb_get_dev - increments the reference count of the device * usb_get_dev - increments the reference count of the usb device structure
* @dev: the device being referenced * @dev: the device being referenced
* *
* Each live reference to a device should be refcounted. * Each live reference to a device should be refcounted.
...@@ -708,36 +710,54 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus) ...@@ -708,36 +710,54 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus)
*/ */
struct usb_device *usb_get_dev (struct usb_device *dev) struct usb_device *usb_get_dev (struct usb_device *dev)
{ {
if (dev) { struct device *tmp;
atomic_inc (&dev->refcnt);
return dev; if (!dev)
} return NULL;
tmp = get_device(&dev->dev);
if (tmp)
return to_usb_device(tmp);
else
return NULL; return NULL;
} }
/** /**
* usb_put_dev - free a usb device structure when all users of it are finished. * usb_put_dev - release a use of the usb device structure
* @dev: device that's been disconnected * @dev: device that's been disconnected
* Context: !in_interrupt ()
* *
* Must be called when a user of a device is finished with it. When the last * Must be called when a user of a device is finished with it. When the last
* user of the device calls this function, the memory of the device is freed. * user of the device calls this function, the memory of the device is freed.
*
* Used by hub and virtual root hub drivers. The device is completely
* gone, everything is cleaned up, so it's time to get rid of these last
* records of this device.
*/ */
void usb_put_dev(struct usb_device *dev) void usb_put_dev(struct usb_device *dev)
{ {
if (atomic_dec_and_test(&dev->refcnt)) { if (dev)
if (dev->bus->op->deallocate) put_device(&dev->dev);
dev->bus->op->deallocate(dev);
usb_destroy_configuration (dev);
usb_bus_put (dev->bus);
kfree (dev);
}
} }
/**
* usb_release_dev - free a usb device structure when all users of it are finished.
* @dev: device that's been disconnected
*
* Will be called only by the device core when all users of this usb device are
* done.
*/
static void usb_release_dev(struct device *dev)
{
struct usb_device *udev;
udev = to_usb_device(dev);
if (!udev)
return;
if (udev->bus && udev->bus->op && udev->bus->op->deallocate)
udev->bus->op->deallocate(udev);
usb_destroy_configuration (udev);
usb_bus_put (udev->bus);
kfree (udev);
}
/** /**
* usb_get_current_frame_number - return current bus frame number * usb_get_current_frame_number - return current bus frame number
* @dev: the device whose bus is being queried * @dev: the device whose bus is being queried
...@@ -980,6 +1000,8 @@ int usb_new_device(struct usb_device *dev, struct device *parent) ...@@ -980,6 +1000,8 @@ int usb_new_device(struct usb_device *dev, struct device *parent)
dev->dev.parent = parent; dev->dev.parent = parent;
dev->dev.driver = &usb_generic_driver; dev->dev.driver = &usb_generic_driver;
dev->dev.bus = &usb_bus_type; dev->dev.bus = &usb_bus_type;
dev->dev.release = usb_release_dev;
usb_get_dev(dev);
if (dev->dev.bus_id[0] == 0) if (dev->dev.bus_id[0] == 0)
sprintf (&dev->dev.bus_id[0], "%d-%s", sprintf (&dev->dev.bus_id[0], "%d-%s",
dev->bus->busnum, dev->devpath); dev->bus->busnum, dev->devpath);
...@@ -1096,7 +1118,7 @@ int usb_new_device(struct usb_device *dev, struct device *parent) ...@@ -1096,7 +1118,7 @@ int usb_new_device(struct usb_device *dev, struct device *parent)
#endif #endif
/* put into sysfs, with device and config specific files */ /* put into sysfs, with device and config specific files */
err = device_register (&dev->dev); err = device_add (&dev->dev);
if (err) if (err)
return err; return err;
usb_create_driverfs_dev_files (dev); usb_create_driverfs_dev_files (dev);
...@@ -1130,7 +1152,7 @@ int usb_new_device(struct usb_device *dev, struct device *parent) ...@@ -1130,7 +1152,7 @@ int usb_new_device(struct usb_device *dev, struct device *parent)
desc->bInterfaceNumber); desc->bInterfaceNumber);
} }
dbg ("%s - registering %s", __FUNCTION__, interface->dev.bus_id); dbg ("%s - registering %s", __FUNCTION__, interface->dev.bus_id);
device_register (&interface->dev); device_add (&interface->dev);
usb_create_driverfs_intf_files (interface); usb_create_driverfs_intf_files (interface);
} }
......
...@@ -217,7 +217,6 @@ struct usb_device { ...@@ -217,7 +217,6 @@ struct usb_device {
struct usb_tt *tt; /* low/full speed dev, highspeed hub */ struct usb_tt *tt; /* low/full speed dev, highspeed hub */
int ttport; /* device port on that tt hub */ int ttport; /* device port on that tt hub */
atomic_t refcnt; /* Reference count */
struct semaphore serialize; struct semaphore serialize;
unsigned int toggle[2]; /* one bit for each endpoint ([0] = IN, [1] = OUT) */ unsigned int toggle[2]; /* one bit for each endpoint ([0] = IN, [1] = OUT) */
......
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