diff options
author | Jiri Slaby <jirislaby@gmail.com> | 2008-09-09 01:23:03 +0200 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2008-10-14 23:50:59 +0200 |
commit | d92870ddd248e8c2562a8c4047885d3ad221ece7 (patch) | |
tree | 27dc3359f8ed8beff068eda6feae205f0d136a79 /drivers/hid | |
parent | d1d3a5f6eaee337d793ab9ac28e696f0262c3c8a (diff) |
HID: fix tty<->hid deadlock
hid_compat_load() runs on the default workqueue, it request_module(), it
execs modprobe, it exits, tty flushes default workqueue, it hangs, because
we are still in it.
Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
Tested-by: <Valdis.Kletnieks@vt.edu>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid')
-rw-r--r-- | drivers/hid/hid-core.c | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 18b277a833f..63c8ce5540f 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1657,6 +1657,7 @@ static void hid_compat_load(struct work_struct *ws) request_module("hid-dummy"); } static DECLARE_WORK(hid_compat_work, hid_compat_load); +static struct workqueue_struct *hid_compat_wq; #endif static int __init hid_init(void) @@ -1674,7 +1675,12 @@ static int __init hid_init(void) goto err_bus; #ifdef CONFIG_HID_COMPAT - schedule_work(&hid_compat_work); + hid_compat_wq = create_workqueue("hid_compat"); + if (!hid_compat_wq) { + hidraw_exit(); + goto err; + } + queue_work(hid_compat_wq, &hid_compat_work); #endif return 0; @@ -1686,6 +1692,9 @@ err: static void __exit hid_exit(void) { +#ifdef CONFIG_HID_COMPAT + destroy_workqueue(hid_compat_wq); +#endif hidraw_exit(); bus_unregister(&hid_bus_type); } |