X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fhwmon%2Fhwmon.c;h=7321a88a51128adef8ba40016e03f0648b7e4a97;hb=4b1fefaca9f5fdd43b24aa248777a75a81dfa8d6;hp=dddd3eb9b3870ef060e84db9d8db4e099303c71d;hpb=2ecc26b87a2b3e8650d3c7fe3fc85a8c73d5560d;p=linux-2.6-omap-h63xx.git diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c index dddd3eb9b38..7321a88a511 100644 --- a/drivers/hwmon/hwmon.c +++ b/drivers/hwmon/hwmon.c @@ -17,6 +17,7 @@ #include #include #include +#include #define HWMON_ID_PREFIX "hwmon" #define HWMON_ID_FORMAT HWMON_ID_PREFIX "%d" @@ -24,51 +25,64 @@ 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, NULL, MKDEV(0,0), dev, - HWMON_ID_FORMAT, id); + hwdev = device_create_drvdata(hwmon_class, dev, MKDEV(0, 0), NULL, + 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"); } @@ -87,7 +101,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);