aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid/hidraw.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hid/hidraw.c')
-rw-r--r--drivers/hid/hidraw.c33
1 files changed, 18 insertions, 15 deletions
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index af3edb98df43..7685ae6808c4 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -38,7 +38,7 @@ static int hidraw_major;
38static struct cdev hidraw_cdev; 38static struct cdev hidraw_cdev;
39static struct class *hidraw_class; 39static struct class *hidraw_class;
40static struct hidraw *hidraw_table[HIDRAW_MAX_DEVICES]; 40static struct hidraw *hidraw_table[HIDRAW_MAX_DEVICES];
41static DEFINE_SPINLOCK(minors_lock); 41static DEFINE_MUTEX(minors_lock);
42 42
43static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) 43static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
44{ 44{
@@ -159,13 +159,13 @@ static int hidraw_open(struct inode *inode, struct file *file)
159 struct hidraw_list *list; 159 struct hidraw_list *list;
160 int err = 0; 160 int err = 0;
161 161
162 lock_kernel();
163 if (!(list = kzalloc(sizeof(struct hidraw_list), GFP_KERNEL))) { 162 if (!(list = kzalloc(sizeof(struct hidraw_list), GFP_KERNEL))) {
164 err = -ENOMEM; 163 err = -ENOMEM;
165 goto out; 164 goto out;
166 } 165 }
167 166
168 spin_lock(&minors_lock); 167 lock_kernel();
168 mutex_lock(&minors_lock);
169 if (!hidraw_table[minor]) { 169 if (!hidraw_table[minor]) {
170 printk(KERN_EMERG "hidraw device with minor %d doesn't exist\n", 170 printk(KERN_EMERG "hidraw device with minor %d doesn't exist\n",
171 minor); 171 minor);
@@ -180,13 +180,16 @@ static int hidraw_open(struct inode *inode, struct file *file)
180 file->private_data = list; 180 file->private_data = list;
181 181
182 dev = hidraw_table[minor]; 182 dev = hidraw_table[minor];
183 if (!dev->open++) 183 if (!dev->open++) {
184 dev->hid->ll_driver->open(dev->hid); 184 err = dev->hid->ll_driver->open(dev->hid);
185 if (err < 0)
186 dev->open--;
187 }
185 188
186out_unlock: 189out_unlock:
187 spin_unlock(&minors_lock); 190 mutex_unlock(&minors_lock);
188out:
189 unlock_kernel(); 191 unlock_kernel();
192out:
190 return err; 193 return err;
191 194
192} 195}
@@ -264,6 +267,7 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd,
264 default: 267 default:
265 ret = -ENOTTY; 268 ret = -ENOTTY;
266 } 269 }
270 unlock_kernel();
267 return ret; 271 return ret;
268} 272}
269 273
@@ -309,7 +313,7 @@ int hidraw_connect(struct hid_device *hid)
309 313
310 result = -EINVAL; 314 result = -EINVAL;
311 315
312 spin_lock(&minors_lock); 316 mutex_lock(&minors_lock);
313 317
314 for (minor = 0; minor < HIDRAW_MAX_DEVICES; minor++) { 318 for (minor = 0; minor < HIDRAW_MAX_DEVICES; minor++) {
315 if (hidraw_table[minor]) 319 if (hidraw_table[minor])
@@ -319,9 +323,8 @@ int hidraw_connect(struct hid_device *hid)
319 break; 323 break;
320 } 324 }
321 325
322 spin_unlock(&minors_lock);
323
324 if (result) { 326 if (result) {
327 mutex_unlock(&minors_lock);
325 kfree(dev); 328 kfree(dev);
326 goto out; 329 goto out;
327 } 330 }
@@ -330,14 +333,14 @@ int hidraw_connect(struct hid_device *hid)
330 NULL, "%s%d", "hidraw", minor); 333 NULL, "%s%d", "hidraw", minor);
331 334
332 if (IS_ERR(dev->dev)) { 335 if (IS_ERR(dev->dev)) {
333 spin_lock(&minors_lock);
334 hidraw_table[minor] = NULL; 336 hidraw_table[minor] = NULL;
335 spin_unlock(&minors_lock); 337 mutex_unlock(&minors_lock);
336 result = PTR_ERR(dev->dev); 338 result = PTR_ERR(dev->dev);
337 kfree(dev); 339 kfree(dev);
338 goto out; 340 goto out;
339 } 341 }
340 342
343 mutex_unlock(&minors_lock);
341 init_waitqueue_head(&dev->wait); 344 init_waitqueue_head(&dev->wait);
342 INIT_LIST_HEAD(&dev->list); 345 INIT_LIST_HEAD(&dev->list);
343 346
@@ -359,9 +362,9 @@ void hidraw_disconnect(struct hid_device *hid)
359 362
360 hidraw->exist = 0; 363 hidraw->exist = 0;
361 364
362 spin_lock(&minors_lock); 365 mutex_lock(&minors_lock);
363 hidraw_table[hidraw->minor] = NULL; 366 hidraw_table[hidraw->minor] = NULL;
364 spin_unlock(&minors_lock); 367 mutex_unlock(&minors_lock);
365 368
366 device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor)); 369 device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
367 370
@@ -403,7 +406,7 @@ out:
403 return result; 406 return result;
404} 407}
405 408
406void __exit hidraw_exit(void) 409void hidraw_exit(void)
407{ 410{
408 dev_t dev_id = MKDEV(hidraw_major, 0); 411 dev_t dev_id = MKDEV(hidraw_major, 0);
409 412