diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-03-23 18:51:32 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-03-23 18:51:32 -0500 |
commit | b6585dedac232ca79fe978d97a95fdaa6da24f66 (patch) | |
tree | 4d2d78300bb9bcfb40cb35450f78dd3af82c78d3 /drivers/hwmon/hwmon.c | |
parent | a3ea9b584ed2acdeae817f0dc91a5880e0828a05 (diff) | |
parent | ded2b66615613093eeb83b81499bc270de8fc499 (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/i2c-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/gregkh/i2c-2.6: (36 commits)
[PATCH] hwmon: add required idr locking
[PATCH] I2C: hwmon: Rename register parameters
[PATCH] I2C: Drop unneeded i2c-dev.h includes
[PATCH] I2C: i2c-ixp4xx: Add hwmon class
[PATCH] I2C: i2c-piix4: Add Broadcom HT-1000 support
[PATCH] I2C: i2c-amd756-s4882: Improve static mutex initialization
[PATCH] I2C: i2c-ali1535: Drop redundant mutex
[PATCH] i2c: Cleanup isp1301_omap
[PATCH] i2c: Fix i2c-ite name initialization
[PATCH] i2c: Drop the i2c-frodo bus driver
[PATCH] i2c: Optimize core_lists mutex usage
[PATCH] w83781d: Don't reset the chip by default
[PATCH] w83781d: Document the alarm and beep bits
[PATCH] w83627ehf: Refactor the sysfs interface
[PATCH] hwmon: Support the Pentium M VID code
[PATCH] hwmon: Add support for the Winbond W83687THF
[PATCH] hwmon: f71805f semaphore to mutex conversions
[PATCH] hwmon: Semaphore to mutex conversions
[PATCH] i2c: Semaphore to mutex conversions, part 3
[PATCH] i2c: Semaphore to mutex conversions, part 2
...
Diffstat (limited to 'drivers/hwmon/hwmon.c')
-rw-r--r-- | drivers/hwmon/hwmon.c | 26 |
1 files changed, 20 insertions, 6 deletions
diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c index dddd3eb9b387..106fa01cdb60 100644 --- a/drivers/hwmon/hwmon.c +++ b/drivers/hwmon/hwmon.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/idr.h> | 17 | #include <linux/idr.h> |
18 | #include <linux/hwmon.h> | 18 | #include <linux/hwmon.h> |
19 | #include <linux/gfp.h> | 19 | #include <linux/gfp.h> |
20 | #include <linux/spinlock.h> | ||
20 | 21 | ||
21 | #define HWMON_ID_PREFIX "hwmon" | 22 | #define HWMON_ID_PREFIX "hwmon" |
22 | #define HWMON_ID_FORMAT HWMON_ID_PREFIX "%d" | 23 | #define HWMON_ID_FORMAT HWMON_ID_PREFIX "%d" |
@@ -24,6 +25,7 @@ | |||
24 | static struct class *hwmon_class; | 25 | static struct class *hwmon_class; |
25 | 26 | ||
26 | static DEFINE_IDR(hwmon_idr); | 27 | static DEFINE_IDR(hwmon_idr); |
28 | static DEFINE_SPINLOCK(idr_lock); | ||
27 | 29 | ||
28 | /** | 30 | /** |
29 | * hwmon_device_register - register w/ hwmon sysfs class | 31 | * hwmon_device_register - register w/ hwmon sysfs class |
@@ -37,20 +39,30 @@ static DEFINE_IDR(hwmon_idr); | |||
37 | struct class_device *hwmon_device_register(struct device *dev) | 39 | struct class_device *hwmon_device_register(struct device *dev) |
38 | { | 40 | { |
39 | struct class_device *cdev; | 41 | struct class_device *cdev; |
40 | int id; | 42 | int id, err; |
41 | 43 | ||
42 | if (idr_pre_get(&hwmon_idr, GFP_KERNEL) == 0) | 44 | again: |
45 | if (unlikely(idr_pre_get(&hwmon_idr, GFP_KERNEL) == 0)) | ||
43 | return ERR_PTR(-ENOMEM); | 46 | return ERR_PTR(-ENOMEM); |
44 | 47 | ||
45 | if (idr_get_new(&hwmon_idr, NULL, &id) < 0) | 48 | spin_lock(&idr_lock); |
46 | return ERR_PTR(-ENOMEM); | 49 | err = idr_get_new(&hwmon_idr, NULL, &id); |
50 | spin_unlock(&idr_lock); | ||
51 | |||
52 | if (unlikely(err == -EAGAIN)) | ||
53 | goto again; | ||
54 | else if (unlikely(err)) | ||
55 | return ERR_PTR(err); | ||
47 | 56 | ||
48 | id = id & MAX_ID_MASK; | 57 | id = id & MAX_ID_MASK; |
49 | cdev = class_device_create(hwmon_class, NULL, MKDEV(0,0), dev, | 58 | cdev = class_device_create(hwmon_class, NULL, MKDEV(0,0), dev, |
50 | HWMON_ID_FORMAT, id); | 59 | HWMON_ID_FORMAT, id); |
51 | 60 | ||
52 | if (IS_ERR(cdev)) | 61 | if (IS_ERR(cdev)) { |
62 | spin_lock(&idr_lock); | ||
53 | idr_remove(&hwmon_idr, id); | 63 | idr_remove(&hwmon_idr, id); |
64 | spin_unlock(&idr_lock); | ||
65 | } | ||
54 | 66 | ||
55 | return cdev; | 67 | return cdev; |
56 | } | 68 | } |
@@ -64,9 +76,11 @@ void hwmon_device_unregister(struct class_device *cdev) | |||
64 | { | 76 | { |
65 | int id; | 77 | int id; |
66 | 78 | ||
67 | if (sscanf(cdev->class_id, HWMON_ID_FORMAT, &id) == 1) { | 79 | if (likely(sscanf(cdev->class_id, HWMON_ID_FORMAT, &id) == 1)) { |
68 | class_device_unregister(cdev); | 80 | class_device_unregister(cdev); |
81 | spin_lock(&idr_lock); | ||
69 | idr_remove(&hwmon_idr, id); | 82 | idr_remove(&hwmon_idr, id); |
83 | spin_unlock(&idr_lock); | ||
70 | } else | 84 | } else |
71 | dev_dbg(cdev->dev, | 85 | dev_dbg(cdev->dev, |
72 | "hwmon_device_unregister() failed: bad class ID!\n"); | 86 | "hwmon_device_unregister() failed: bad class ID!\n"); |