HID: fix locking in hidraw_open()

As open needs to sleep hidraw was wrong to call it with a spinlock held.
Furthermore, open can of course fail which needs to be handled.

Signed-off-by: Oliver Neukum <oneukum@suse.de>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>

authored by Oliver Neukum and committed by Jiri Kosina 7d672cd7 4ffaf869

+16 -14
+16 -14
drivers/hid/hidraw.c
··· 38 static struct cdev hidraw_cdev; 39 static struct class *hidraw_class; 40 static struct hidraw *hidraw_table[HIDRAW_MAX_DEVICES]; 41 - static DEFINE_SPINLOCK(minors_lock); 42 43 static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) 44 { ··· 159 struct hidraw_list *list; 160 int err = 0; 161 162 - lock_kernel(); 163 if (!(list = kzalloc(sizeof(struct hidraw_list), GFP_KERNEL))) { 164 err = -ENOMEM; 165 goto out; 166 } 167 168 - spin_lock(&minors_lock); 169 if (!hidraw_table[minor]) { 170 printk(KERN_EMERG "hidraw device with minor %d doesn't exist\n", 171 minor); ··· 180 file->private_data = list; 181 182 dev = hidraw_table[minor]; 183 - if (!dev->open++) 184 - dev->hid->ll_driver->open(dev->hid); 185 186 out_unlock: 187 - spin_unlock(&minors_lock); 188 - out: 189 unlock_kernel(); 190 return err; 191 192 } ··· 313 314 result = -EINVAL; 315 316 - spin_lock(&minors_lock); 317 318 for (minor = 0; minor < HIDRAW_MAX_DEVICES; minor++) { 319 if (hidraw_table[minor]) ··· 323 break; 324 } 325 326 - spin_unlock(&minors_lock); 327 - 328 if (result) { 329 kfree(dev); 330 goto out; 331 } ··· 333 NULL, "%s%d", "hidraw", minor); 334 335 if (IS_ERR(dev->dev)) { 336 - spin_lock(&minors_lock); 337 hidraw_table[minor] = NULL; 338 - spin_unlock(&minors_lock); 339 result = PTR_ERR(dev->dev); 340 kfree(dev); 341 goto out; 342 } 343 344 init_waitqueue_head(&dev->wait); 345 INIT_LIST_HEAD(&dev->list); 346 ··· 362 363 hidraw->exist = 0; 364 365 - spin_lock(&minors_lock); 366 hidraw_table[hidraw->minor] = NULL; 367 - spin_unlock(&minors_lock); 368 369 device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor)); 370
··· 38 static struct cdev hidraw_cdev; 39 static struct class *hidraw_class; 40 static struct hidraw *hidraw_table[HIDRAW_MAX_DEVICES]; 41 + static DEFINE_MUTEX(minors_lock); 42 43 static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) 44 { ··· 159 struct hidraw_list *list; 160 int err = 0; 161 162 if (!(list = kzalloc(sizeof(struct hidraw_list), GFP_KERNEL))) { 163 err = -ENOMEM; 164 goto out; 165 } 166 167 + lock_kernel(); 168 + mutex_lock(&minors_lock); 169 if (!hidraw_table[minor]) { 170 printk(KERN_EMERG "hidraw device with minor %d doesn't exist\n", 171 minor); ··· 180 file->private_data = list; 181 182 dev = hidraw_table[minor]; 183 + if (!dev->open++) { 184 + err = dev->hid->ll_driver->open(dev->hid); 185 + if (err < 0) 186 + dev->open--; 187 + } 188 189 out_unlock: 190 + mutex_unlock(&minors_lock); 191 unlock_kernel(); 192 + out: 193 return err; 194 195 } ··· 310 311 result = -EINVAL; 312 313 + mutex_lock(&minors_lock); 314 315 for (minor = 0; minor < HIDRAW_MAX_DEVICES; minor++) { 316 if (hidraw_table[minor]) ··· 320 break; 321 } 322 323 if (result) { 324 + mutex_unlock(&minors_lock); 325 kfree(dev); 326 goto out; 327 } ··· 331 NULL, "%s%d", "hidraw", minor); 332 333 if (IS_ERR(dev->dev)) { 334 hidraw_table[minor] = NULL; 335 + mutex_unlock(&minors_lock); 336 result = PTR_ERR(dev->dev); 337 kfree(dev); 338 goto out; 339 } 340 341 + mutex_unlock(&minors_lock); 342 init_waitqueue_head(&dev->wait); 343 INIT_LIST_HEAD(&dev->list); 344 ··· 360 361 hidraw->exist = 0; 362 363 + mutex_lock(&minors_lock); 364 hidraw_table[hidraw->minor] = NULL; 365 + mutex_unlock(&minors_lock); 366 367 device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor)); 368