diff options
author | Fernando Luis Vázquez Cao <fernando_b1@lab.ntt.co.jp> | 2014-02-26 16:51:24 +0900 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2014-02-26 11:01:28 +0100 |
commit | 47587fc098451c2100dc1fb618855fc2e2d937af (patch) | |
tree | 229cc6c8a11f97b1b369c8faa554f91a5c054818 /drivers/hid/hidraw.c | |
parent | 5f5750d2e471866576225c3af28eedfadebb0765 (diff) | |
download | blackbird-op-linux-47587fc098451c2100dc1fb618855fc2e2d937af.tar.gz blackbird-op-linux-47587fc098451c2100dc1fb618855fc2e2d937af.zip |
HID: hidraw: fix warning destroying hidraw device files after parent
I noticed that after hot unplugging a Logitech unifying receiver
(drivers/hid/hid-logitech-dj.c) the kernel would occasionally spew a
stack trace similar to this:
usb 1-1.1.2: USB disconnect, device number 7
WARNING: CPU: 0 PID: 2865 at fs/sysfs/group.c:216 device_del+0x40/0x1b0()
sysfs group ffffffff8187fa20 not found for kobject 'hidraw0'
[...]
CPU: 0 PID: 2865 Comm: upowerd Tainted: G W 3.14.0-rc4 #7
Hardware name: LENOVO 7783PN4/ , BIOS 9HKT43AUS 07/11/2011
0000000000000009 ffffffff814cd684 ffff880427ccfdf8 ffffffff810616e7
ffff88041ec61800 ffff880427ccfe48 ffff88041e444d80 ffff880426fab8e8
ffff880429359960 ffffffff8106174c ffffffff81714b98 0000000000000028
Call Trace:
[<ffffffff814cd684>] ? dump_stack+0x41/0x51
[<ffffffff810616e7>] ? warn_slowpath_common+0x77/0x90
[<ffffffff8106174c>] ? warn_slowpath_fmt+0x4c/0x50
[<ffffffff81374fd0>] ? device_del+0x40/0x1b0
[<ffffffff8137516f>] ? device_unregister+0x2f/0x50
[<ffffffff813751fa>] ? device_destroy+0x3a/0x40
[<ffffffffa03ca245>] ? drop_ref+0x55/0x120 [hid]
[<ffffffffa03ca3e6>] ? hidraw_release+0x96/0xb0 [hid]
[<ffffffff811929da>] ? __fput+0xca/0x210
[<ffffffff8107fe17>] ? task_work_run+0x97/0xd0
[<ffffffff810139a9>] ? do_notify_resume+0x69/0xa0
[<ffffffff814dbd22>] ? int_signal+0x12/0x17
---[ end trace 63f4a46f6566d737 ]---
During device removal hid_disconnect() is called via hid_hw_stop() to
stop the device and free all its resources, including the sysfs
files. The problem is that if a user space process, such as upowerd,
holds a reference to a hidraw file the corresponding sysfs files will
be kept around (drop_ref() does not call device_destroy() if the open
counter is not 0) and it will be usb_disconnect() who, by calling
device_del() for the USB device, will indirectly remove the sysfs
files of the hidraw device (sysfs_remove_dir() is recursive these
days). Because of this, by the time user space releases the last
reference to the hidraw file and drop_ref() tries to destroy the
device the sysfs files are already gone and the kernel will print
the warning above.
Fix this by calling device_destroy() at USB disconnect time.
Signed-off-by: Fernando Luis Vazquez Cao <fernando@oss.ntt.co.jp>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
Cc: stable@vger.kernel.org # 3.13
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid/hidraw.c')
-rw-r--r-- | drivers/hid/hidraw.c | 4 |
1 files changed, 2 insertions, 2 deletions
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index cb0137b3718d..ab24ce2eb28f 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c @@ -320,13 +320,13 @@ static void drop_ref(struct hidraw *hidraw, int exists_bit) hid_hw_close(hidraw->hid); wake_up_interruptible(&hidraw->wait); } + device_destroy(hidraw_class, + MKDEV(hidraw_major, hidraw->minor)); } else { --hidraw->open; } if (!hidraw->open) { if (!hidraw->exist) { - device_destroy(hidraw_class, - MKDEV(hidraw_major, hidraw->minor)); hidraw_table[hidraw->minor] = NULL; kfree(hidraw); } else { |