diff options
Diffstat (limited to 'drivers/char/misc.c')
-rw-r--r-- | drivers/char/misc.c | 26 |
1 files changed, 11 insertions, 15 deletions
diff --git a/drivers/char/misc.c b/drivers/char/misc.c index 96f1cd086dd2..94a136e96c06 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c | |||
@@ -60,9 +60,7 @@ static DEFINE_MUTEX(misc_mtx); | |||
60 | * Assigned numbers, used for dynamic minors | 60 | * Assigned numbers, used for dynamic minors |
61 | */ | 61 | */ |
62 | #define DYNAMIC_MINORS 64 /* like dynamic majors */ | 62 | #define DYNAMIC_MINORS 64 /* like dynamic majors */ |
63 | static unsigned char misc_minors[DYNAMIC_MINORS / 8]; | 63 | static DECLARE_BITMAP(misc_minors, DYNAMIC_MINORS); |
64 | |||
65 | extern int pmu_device_init(void); | ||
66 | 64 | ||
67 | #ifdef CONFIG_PROC_FS | 65 | #ifdef CONFIG_PROC_FS |
68 | static void *misc_seq_start(struct seq_file *seq, loff_t *pos) | 66 | static void *misc_seq_start(struct seq_file *seq, loff_t *pos) |
@@ -198,24 +196,23 @@ int misc_register(struct miscdevice * misc) | |||
198 | } | 196 | } |
199 | 197 | ||
200 | if (misc->minor == MISC_DYNAMIC_MINOR) { | 198 | if (misc->minor == MISC_DYNAMIC_MINOR) { |
201 | int i = DYNAMIC_MINORS; | 199 | int i = find_first_zero_bit(misc_minors, DYNAMIC_MINORS); |
202 | while (--i >= 0) | 200 | if (i >= DYNAMIC_MINORS) { |
203 | if ( (misc_minors[i>>3] & (1 << (i&7))) == 0) | ||
204 | break; | ||
205 | if (i<0) { | ||
206 | mutex_unlock(&misc_mtx); | 201 | mutex_unlock(&misc_mtx); |
207 | return -EBUSY; | 202 | return -EBUSY; |
208 | } | 203 | } |
209 | misc->minor = i; | 204 | misc->minor = DYNAMIC_MINORS - i - 1; |
205 | set_bit(i, misc_minors); | ||
210 | } | 206 | } |
211 | 207 | ||
212 | if (misc->minor < DYNAMIC_MINORS) | ||
213 | misc_minors[misc->minor >> 3] |= 1 << (misc->minor & 7); | ||
214 | dev = MKDEV(MISC_MAJOR, misc->minor); | 208 | dev = MKDEV(MISC_MAJOR, misc->minor); |
215 | 209 | ||
216 | misc->this_device = device_create(misc_class, misc->parent, dev, | 210 | misc->this_device = device_create(misc_class, misc->parent, dev, |
217 | misc, "%s", misc->name); | 211 | misc, "%s", misc->name); |
218 | if (IS_ERR(misc->this_device)) { | 212 | if (IS_ERR(misc->this_device)) { |
213 | int i = DYNAMIC_MINORS - misc->minor - 1; | ||
214 | if (i < DYNAMIC_MINORS && i >= 0) | ||
215 | clear_bit(i, misc_minors); | ||
219 | err = PTR_ERR(misc->this_device); | 216 | err = PTR_ERR(misc->this_device); |
220 | goto out; | 217 | goto out; |
221 | } | 218 | } |
@@ -242,7 +239,7 @@ int misc_register(struct miscdevice * misc) | |||
242 | 239 | ||
243 | int misc_deregister(struct miscdevice *misc) | 240 | int misc_deregister(struct miscdevice *misc) |
244 | { | 241 | { |
245 | int i = misc->minor; | 242 | int i = DYNAMIC_MINORS - misc->minor - 1; |
246 | 243 | ||
247 | if (list_empty(&misc->list)) | 244 | if (list_empty(&misc->list)) |
248 | return -EINVAL; | 245 | return -EINVAL; |
@@ -250,9 +247,8 @@ int misc_deregister(struct miscdevice *misc) | |||
250 | mutex_lock(&misc_mtx); | 247 | mutex_lock(&misc_mtx); |
251 | list_del(&misc->list); | 248 | list_del(&misc->list); |
252 | device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor)); | 249 | device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor)); |
253 | if (i < DYNAMIC_MINORS && i>0) { | 250 | if (i < DYNAMIC_MINORS && i >= 0) |
254 | misc_minors[i>>3] &= ~(1 << (misc->minor & 7)); | 251 | clear_bit(i, misc_minors); |
255 | } | ||
256 | mutex_unlock(&misc_mtx); | 252 | mutex_unlock(&misc_mtx); |
257 | return 0; | 253 | return 0; |
258 | } | 254 | } |