diff options
author | Subash Abhinov Kasiviswanathan <subashab@codeaurora.org> | 2019-11-22 18:47:43 -0700 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2019-11-22 19:45:07 -0800 |
commit | 1df496e828e2c6b9f0f810132f0e1121002ffd1a (patch) | |
tree | 4af37e7bc46f8167c8c3395e9a3e2f66d565d90b /drivers | |
parent | 7bfe056aaa62258ff3985754df12a58c296c95ea (diff) | |
download | data-kernel-1df496e828e2c6b9f0f810132f0e1121002ffd1a.tar.gz |
drivers: shs: fix deadlock caused between generic netlink and rtnl locks
Fix for a deadlock seen when trying to register the shs generic netlink family
inside of the callback context of rtnl_netlink. Instead of running in the
notifier's context, the generic netlink registration is moved to initialization
of the kernel module. Fixes the following lock contention scenario:
[ 3302.102281] Call trace:
[ 3302.102332] __switch_to+0x108/0x118
[ 3302.102357] __schedule+0x8fc/0xcd8
[ 3302.102368] schedule_preempt_disabled+0x7c/0xa8
[ 3302.102384] __mutex_lock+0x444/0x660
[ 3302.102392] __mutex_lock_slowpath+0x10/0x18
[ 3302.102399] mutex_lock+0x30/0x38 mutex_lock(&rtnl_mutex);
[ 3302.102422] rtnl_lock+0x14/0x20 rtnl_lock
[ 3302.102448] nl80211_pre_doit+0x28/0x1a0
[ 3302.102465] genl_rcv_msg+0x3a4/0x408
[ 3302.102473] netlink_rcv_skb+0xa8/0x120
[ 3302.102481] genl_rcv+0x30/0x48 down_read(&cb_lock);
[ 3302.102487] netlink_unicast+0x1ec/0x290
[ 3302.102496] netlink_sendmsg+0x2ec/0x348
[ 3302.102609] Call trace:
[ 3302.102615] __switch_to+0x108/0x118
[ 3302.102624] __schedule+0x8fc/0xcd8
[ 3302.102630] schedule+0x70/0x90
[ 3302.102638] rwsem_down_write_failed+0x2bc/0x3c8
[ 3302.102644] down_write+0x4c/0x50
[ 3302.102652] genl_register_family+0xb4/0x650 down_write(&cb_lock);
[ 3302.102818] rmnet_shs_wq_genl_init+0x1c/0x38 [rmnet_shs]
[ 3302.102847] rmnet_shs_wq_init+0x218/0x328 [rmnet_shs]
[ 3302.102873] rmnet_shs_dev_notify_cb+0x378/0x3e0 [rmnet_shs]
[ 3302.102892] raw_notifier_call_chain+0x3c/0x68
[ 3302.102909] register_netdevice+0x374/0x560
[ 3302.102934] rmnet_vnd_newlink+0x6c/0xe8
[ 3302.102942] rmnet_newlink+0x9c/0x198
[ 3302.102950] rtnl_newlink+0x648/0x7b0
[ 3302.102960] rtnetlink_rcv_msg+0x270/0x388 mutex_lock(&rtnl_mutex);
Change-Id: Ib71de0cb4617477cab40a7f42154584765e30c2b
Signed-off-by: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/rmnet/shs/rmnet_shs_config.c | 9 | ||||
-rw-r--r-- | drivers/rmnet/shs/rmnet_shs_wq.c | 5 |
2 files changed, 9 insertions, 5 deletions
diff --git a/drivers/rmnet/shs/rmnet_shs_config.c b/drivers/rmnet/shs/rmnet_shs_config.c index a268c98..e6b4002 100644 --- a/drivers/rmnet/shs/rmnet_shs_config.c +++ b/drivers/rmnet/shs/rmnet_shs_config.c @@ -20,6 +20,7 @@ #include "rmnet_shs_config.h" #include "rmnet_shs.h" #include "rmnet_shs_wq.h" +#include "rmnet_shs_wq_genl.h" MODULE_LICENSE("GPL v2"); @@ -51,6 +52,11 @@ int __init rmnet_shs_module_init(void) pr_info("%s(): Starting rmnet SHS module\n", __func__); trace_rmnet_shs_high(RMNET_SHS_MODULE, RMNET_SHS_MODULE_INIT, 0xDEF, 0xDEF, 0xDEF, 0xDEF, NULL, NULL); + + if (rmnet_shs_wq_genl_init()) { + rm_err("%s", "SHS_GNL: Failed to init generic netlink"); + } + return register_netdevice_notifier(&rmnet_shs_dev_notifier); } @@ -60,6 +66,9 @@ void __exit rmnet_shs_module_exit(void) trace_rmnet_shs_high(RMNET_SHS_MODULE, RMNET_SHS_MODULE_EXIT, 0xDEF, 0xDEF, 0xDEF, 0xDEF, NULL, NULL); unregister_netdevice_notifier(&rmnet_shs_dev_notifier); + + rmnet_shs_wq_genl_deinit(); + pr_info("%s(): Exiting rmnet SHS module\n", __func__); } diff --git a/drivers/rmnet/shs/rmnet_shs_wq.c b/drivers/rmnet/shs/rmnet_shs_wq.c index 09aeed7..298058c 100644 --- a/drivers/rmnet/shs/rmnet_shs_wq.c +++ b/drivers/rmnet/shs/rmnet_shs_wq.c @@ -1989,7 +1989,6 @@ void rmnet_shs_wq_exit(void) if (!rmnet_shs_wq || !rmnet_shs_delayed_wq) return; - rmnet_shs_wq_genl_deinit(); rmnet_shs_wq_mem_deinit(); trace_rmnet_shs_wq_high(RMNET_SHS_WQ_EXIT, RMNET_SHS_WQ_EXIT_START, @@ -2078,10 +2077,6 @@ void rmnet_shs_wq_init(struct net_device *dev) INIT_DEFERRABLE_WORK(&rmnet_shs_delayed_wq->wq, rmnet_shs_wq_process_wq); - if (rmnet_shs_wq_genl_init()) { - rm_err("%s", "SHS_GNL: Failed to init generic netlink"); - } - trace_rmnet_shs_wq_high(RMNET_SHS_WQ_INIT, RMNET_SHS_WQ_INIT_END, 0xDEF, 0xDEF, 0xDEF, 0xDEF, NULL, NULL); } |