X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fhwmon%2Fhwmon.c;h=3db28450a3b34504facc27cc8a9611a8e53569cd;hb=6e766458f78ca15198cf046bc098b36e40c8b471;hp=9b41c9bd805f561594fcc6fcf7d78923dad24490;hpb=c08319a9d50b5c9cb4fdb33728bd16497cf4ddd3;p=linux-2.6-omap-h63xx.git diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c index 9b41c9bd805..3db28450a3b 100644 --- a/drivers/hwmon/hwmon.c +++ b/drivers/hwmon/hwmon.c @@ -16,6 +16,8 @@ #include #include #include +#include +#include #define HWMON_ID_PREFIX "hwmon" #define HWMON_ID_FORMAT HWMON_ID_PREFIX "%d" @@ -23,51 +25,63 @@ static struct class *hwmon_class; static DEFINE_IDR(hwmon_idr); +static DEFINE_SPINLOCK(idr_lock); /** - * hwmon_device_register - register w/ hwmon sysfs class + * hwmon_device_register - register w/ hwmon * @dev: the device to register * - * hwmon_device_unregister() must be called when the class device is no + * hwmon_device_unregister() must be called when the device is no * longer needed. * - * Returns the pointer to the new struct class device. + * Returns the pointer to the new device. */ -struct class_device *hwmon_device_register(struct device *dev) +struct device *hwmon_device_register(struct device *dev) { - struct class_device *cdev; - int id; + struct device *hwdev; + int id, err; - if (idr_pre_get(&hwmon_idr, GFP_KERNEL) == 0) +again: + if (unlikely(idr_pre_get(&hwmon_idr, GFP_KERNEL) == 0)) return ERR_PTR(-ENOMEM); - if (idr_get_new(&hwmon_idr, NULL, &id) < 0) - return ERR_PTR(-ENOMEM); + spin_lock(&idr_lock); + err = idr_get_new(&hwmon_idr, NULL, &id); + spin_unlock(&idr_lock); + + if (unlikely(err == -EAGAIN)) + goto again; + else if (unlikely(err)) + return ERR_PTR(err); id = id & MAX_ID_MASK; - cdev = class_device_create(hwmon_class, MKDEV(0,0), dev, - HWMON_ID_FORMAT, id); + hwdev = device_create(hwmon_class, dev, MKDEV(0,0), HWMON_ID_FORMAT, id); - if (IS_ERR(cdev)) + if (IS_ERR(hwdev)) { + spin_lock(&idr_lock); idr_remove(&hwmon_idr, id); + spin_unlock(&idr_lock); + } - return cdev; + return hwdev; } /** * hwmon_device_unregister - removes the previously registered class device * - * @cdev: the class device to destroy + * @dev: the class device to destroy */ -void hwmon_device_unregister(struct class_device *cdev) +void hwmon_device_unregister(struct device *dev) { int id; - if (sscanf(cdev->class_id, HWMON_ID_FORMAT, &id) == 1) { - class_device_unregister(cdev); + if (likely(sscanf(dev->bus_id, HWMON_ID_FORMAT, &id) == 1)) { + device_unregister(dev); + spin_lock(&idr_lock); idr_remove(&hwmon_idr, id); + spin_unlock(&idr_lock); } else - dev_dbg(cdev->dev, + dev_dbg(dev->parent, "hwmon_device_unregister() failed: bad class ID!\n"); } @@ -86,7 +100,7 @@ static void __exit hwmon_exit(void) class_destroy(hwmon_class); } -module_init(hwmon_init); +subsys_initcall(hwmon_init); module_exit(hwmon_exit); EXPORT_SYMBOL_GPL(hwmon_device_register);