diff options
author | Alan Jenkins <alan-jenkins@tuffmail.co.uk> | 2009-04-29 06:41:24 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-04-29 16:48:33 -0400 |
commit | d4c4a9a1bce1912ed5681251f0037fd4f2364a3e (patch) | |
tree | 85c5631e48bf75bfdb3e52634a983e4f7c46f06d | |
parent | b7fcb5c4a4c27da2f6d86cb03d18687e537442cf (diff) |
mac80211: fix modprobe deadlock by not calling wep_init under rtnl_lock
- ieee80211_wep_init(), which is called with rtnl_lock held, blocks in
request_module() [waiting for modprobe to load a crypto module].
- modprobe blocks in a call to flush_workqueue(), when it closes a TTY
[presumably when it exits].
- The workqueue item linkwatch_event() blocks on rtnl_lock.
There's no reason for wep_init() to be called with rtnl_lock held, so
just move it outside the critical section.
Signed-off-by: Alan Jenkins <alan-jenkins@tuffmail.co.uk>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | net/mac80211/main.c | 19 |
1 files changed, 9 insertions, 10 deletions
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index fbcbed6cad01..00968c2d22bb 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -909,6 +909,13 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
909 | if (result < 0) | 909 | if (result < 0) |
910 | goto fail_sta_info; | 910 | goto fail_sta_info; |
911 | 911 | ||
912 | result = ieee80211_wep_init(local); | ||
913 | if (result < 0) { | ||
914 | printk(KERN_DEBUG "%s: Failed to initialize wep: %d\n", | ||
915 | wiphy_name(local->hw.wiphy), result); | ||
916 | goto fail_wep; | ||
917 | } | ||
918 | |||
912 | rtnl_lock(); | 919 | rtnl_lock(); |
913 | result = dev_alloc_name(local->mdev, local->mdev->name); | 920 | result = dev_alloc_name(local->mdev, local->mdev->name); |
914 | if (result < 0) | 921 | if (result < 0) |
@@ -930,14 +937,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
930 | goto fail_rate; | 937 | goto fail_rate; |
931 | } | 938 | } |
932 | 939 | ||
933 | result = ieee80211_wep_init(local); | ||
934 | |||
935 | if (result < 0) { | ||
936 | printk(KERN_DEBUG "%s: Failed to initialize wep: %d\n", | ||
937 | wiphy_name(local->hw.wiphy), result); | ||
938 | goto fail_wep; | ||
939 | } | ||
940 | |||
941 | /* add one default STA interface if supported */ | 940 | /* add one default STA interface if supported */ |
942 | if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) { | 941 | if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) { |
943 | result = ieee80211_if_add(local, "wlan%d", NULL, | 942 | result = ieee80211_if_add(local, "wlan%d", NULL, |
@@ -967,13 +966,13 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
967 | 966 | ||
968 | return 0; | 967 | return 0; |
969 | 968 | ||
970 | fail_wep: | ||
971 | rate_control_deinitialize(local); | ||
972 | fail_rate: | 969 | fail_rate: |
973 | unregister_netdevice(local->mdev); | 970 | unregister_netdevice(local->mdev); |
974 | local->mdev = NULL; | 971 | local->mdev = NULL; |
975 | fail_dev: | 972 | fail_dev: |
976 | rtnl_unlock(); | 973 | rtnl_unlock(); |
974 | ieee80211_wep_free(local); | ||
975 | fail_wep: | ||
977 | sta_info_stop(local); | 976 | sta_info_stop(local); |
978 | fail_sta_info: | 977 | fail_sta_info: |
979 | debugfs_hw_del(local); | 978 | debugfs_hw_del(local); |