aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/misc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/misc.c')
-rw-r--r--drivers/char/misc.c31
1 files changed, 12 insertions, 19 deletions
diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index 07fa612a58d5..94a136e96c06 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -49,7 +49,6 @@
49#include <linux/device.h> 49#include <linux/device.h>
50#include <linux/tty.h> 50#include <linux/tty.h>
51#include <linux/kmod.h> 51#include <linux/kmod.h>
52#include <linux/smp_lock.h>
53 52
54/* 53/*
55 * Head entry for the doubly linked miscdevice list 54 * Head entry for the doubly linked miscdevice list
@@ -61,9 +60,7 @@ static DEFINE_MUTEX(misc_mtx);
61 * Assigned numbers, used for dynamic minors 60 * Assigned numbers, used for dynamic minors
62 */ 61 */
63#define DYNAMIC_MINORS 64 /* like dynamic majors */ 62#define DYNAMIC_MINORS 64 /* like dynamic majors */
64static unsigned char misc_minors[DYNAMIC_MINORS / 8]; 63static DECLARE_BITMAP(misc_minors, DYNAMIC_MINORS);
65
66extern int pmu_device_init(void);
67 64
68#ifdef CONFIG_PROC_FS 65#ifdef CONFIG_PROC_FS
69static void *misc_seq_start(struct seq_file *seq, loff_t *pos) 66static void *misc_seq_start(struct seq_file *seq, loff_t *pos)
@@ -118,8 +115,7 @@ static int misc_open(struct inode * inode, struct file * file)
118 struct miscdevice *c; 115 struct miscdevice *c;
119 int err = -ENODEV; 116 int err = -ENODEV;
120 const struct file_operations *old_fops, *new_fops = NULL; 117 const struct file_operations *old_fops, *new_fops = NULL;
121 118
122 lock_kernel();
123 mutex_lock(&misc_mtx); 119 mutex_lock(&misc_mtx);
124 120
125 list_for_each_entry(c, &misc_list, list) { 121 list_for_each_entry(c, &misc_list, list) {
@@ -157,7 +153,6 @@ static int misc_open(struct inode * inode, struct file * file)
157 fops_put(old_fops); 153 fops_put(old_fops);
158fail: 154fail:
159 mutex_unlock(&misc_mtx); 155 mutex_unlock(&misc_mtx);
160 unlock_kernel();
161 return err; 156 return err;
162} 157}
163 158
@@ -201,24 +196,23 @@ int misc_register(struct miscdevice * misc)
201 } 196 }
202 197
203 if (misc->minor == MISC_DYNAMIC_MINOR) { 198 if (misc->minor == MISC_DYNAMIC_MINOR) {
204 int i = DYNAMIC_MINORS; 199 int i = find_first_zero_bit(misc_minors, DYNAMIC_MINORS);
205 while (--i >= 0) 200 if (i >= DYNAMIC_MINORS) {
206 if ( (misc_minors[i>>3] & (1 << (i&7))) == 0)
207 break;
208 if (i<0) {
209 mutex_unlock(&misc_mtx); 201 mutex_unlock(&misc_mtx);
210 return -EBUSY; 202 return -EBUSY;
211 } 203 }
212 misc->minor = i; 204 misc->minor = DYNAMIC_MINORS - i - 1;
205 set_bit(i, misc_minors);
213 } 206 }
214 207
215 if (misc->minor < DYNAMIC_MINORS)
216 misc_minors[misc->minor >> 3] |= 1 << (misc->minor & 7);
217 dev = MKDEV(MISC_MAJOR, misc->minor); 208 dev = MKDEV(MISC_MAJOR, misc->minor);
218 209
219 misc->this_device = device_create(misc_class, misc->parent, dev, 210 misc->this_device = device_create(misc_class, misc->parent, dev,
220 misc, "%s", misc->name); 211 misc, "%s", misc->name);
221 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);
222 err = PTR_ERR(misc->this_device); 216 err = PTR_ERR(misc->this_device);
223 goto out; 217 goto out;
224 } 218 }
@@ -245,7 +239,7 @@ int misc_register(struct miscdevice * misc)
245 239
246int misc_deregister(struct miscdevice *misc) 240int misc_deregister(struct miscdevice *misc)
247{ 241{
248 int i = misc->minor; 242 int i = DYNAMIC_MINORS - misc->minor - 1;
249 243
250 if (list_empty(&misc->list)) 244 if (list_empty(&misc->list))
251 return -EINVAL; 245 return -EINVAL;
@@ -253,9 +247,8 @@ int misc_deregister(struct miscdevice *misc)
253 mutex_lock(&misc_mtx); 247 mutex_lock(&misc_mtx);
254 list_del(&misc->list); 248 list_del(&misc->list);
255 device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor)); 249 device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor));
256 if (i < DYNAMIC_MINORS && i>0) { 250 if (i < DYNAMIC_MINORS && i >= 0)
257 misc_minors[i>>3] &= ~(1 << (misc->minor & 7)); 251 clear_bit(i, misc_minors);
258 }
259 mutex_unlock(&misc_mtx); 252 mutex_unlock(&misc_mtx);
260 return 0; 253 return 0;
261} 254}