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