Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid

Pull HID fix from Jiri Kosina:
"This reverts a patch that causes regression in binding between HID
devices and drivers during device unplug/replug cycle."

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid:
HID: hidraw: put old deallocation mechanism in place

+43 -26
+43 -26
drivers/hid/hidraw.c
··· 42 42 static struct class *hidraw_class; 43 43 static struct hidraw *hidraw_table[HIDRAW_MAX_DEVICES]; 44 44 static DEFINE_MUTEX(minors_lock); 45 - static void drop_ref(struct hidraw *hid, int exists_bit); 46 45 47 46 static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) 48 47 { ··· 113 114 __u8 *buf; 114 115 int ret = 0; 115 116 116 - if (!hidraw_table[minor] || !hidraw_table[minor]->exist) { 117 + if (!hidraw_table[minor]) { 117 118 ret = -ENODEV; 118 119 goto out; 119 120 } ··· 261 262 } 262 263 263 264 mutex_lock(&minors_lock); 264 - if (!hidraw_table[minor] || !hidraw_table[minor]->exist) { 265 + if (!hidraw_table[minor]) { 265 266 err = -ENODEV; 266 267 goto out_unlock; 267 268 } ··· 298 299 static int hidraw_release(struct inode * inode, struct file * file) 299 300 { 300 301 unsigned int minor = iminor(inode); 302 + struct hidraw *dev; 301 303 struct hidraw_list *list = file->private_data; 304 + int ret; 305 + int i; 302 306 303 - drop_ref(hidraw_table[minor], 0); 307 + mutex_lock(&minors_lock); 308 + if (!hidraw_table[minor]) { 309 + ret = -ENODEV; 310 + goto unlock; 311 + } 312 + 304 313 list_del(&list->node); 314 + dev = hidraw_table[minor]; 315 + if (!--dev->open) { 316 + if (list->hidraw->exist) { 317 + hid_hw_power(dev->hid, PM_HINT_NORMAL); 318 + hid_hw_close(dev->hid); 319 + } else { 320 + kfree(list->hidraw); 321 + } 322 + } 323 + 324 + for (i = 0; i < HIDRAW_BUFFER_SIZE; ++i) 325 + kfree(list->buffer[i].value); 305 326 kfree(list); 306 - return 0; 327 + ret = 0; 328 + unlock: 329 + mutex_unlock(&minors_lock); 330 + 331 + return ret; 307 332 } 308 333 309 334 static long hidraw_ioctl(struct file *file, unsigned int cmd, ··· 529 506 void hidraw_disconnect(struct hid_device *hid) 530 507 { 531 508 struct hidraw *hidraw = hid->hidraw; 532 - drop_ref(hidraw, 1); 509 + 510 + mutex_lock(&minors_lock); 511 + hidraw->exist = 0; 512 + 513 + device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor)); 514 + 515 + hidraw_table[hidraw->minor] = NULL; 516 + 517 + if (hidraw->open) { 518 + hid_hw_close(hid); 519 + wake_up_interruptible(&hidraw->wait); 520 + } else { 521 + kfree(hidraw); 522 + } 523 + mutex_unlock(&minors_lock); 533 524 } 534 525 EXPORT_SYMBOL_GPL(hidraw_disconnect); 535 526 ··· 591 554 class_destroy(hidraw_class); 592 555 unregister_chrdev_region(dev_id, HIDRAW_MAX_DEVICES); 593 556 594 - } 595 - 596 - static void drop_ref(struct hidraw *hidraw, int exists_bit) 597 - { 598 - mutex_lock(&minors_lock); 599 - if (exists_bit) { 600 - hid_hw_close(hidraw->hid); 601 - hidraw->exist = 0; 602 - if (hidraw->open) 603 - wake_up_interruptible(&hidraw->wait); 604 - } else { 605 - --hidraw->open; 606 - } 607 - 608 - if (!hidraw->open && !hidraw->exist) { 609 - device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor)); 610 - hidraw_table[hidraw->minor] = NULL; 611 - kfree(hidraw); 612 - } 613 - mutex_unlock(&minors_lock); 614 557 }