Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d4c4a9a1 authored by Alan Jenkins's avatar Alan Jenkins Committed by John W. Linville
Browse files

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: default avatarAlan Jenkins <alan-jenkins@tuffmail.co.uk>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent b7fcb5c4
Loading
Loading
Loading
Loading
+9 −10
Original line number Diff line number Diff line
@@ -909,6 +909,13 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
	if (result < 0)
		goto fail_sta_info;

	result = ieee80211_wep_init(local);
	if (result < 0) {
		printk(KERN_DEBUG "%s: Failed to initialize wep: %d\n",
		       wiphy_name(local->hw.wiphy), result);
		goto fail_wep;
	}

	rtnl_lock();
	result = dev_alloc_name(local->mdev, local->mdev->name);
	if (result < 0)
@@ -930,14 +937,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
		goto fail_rate;
	}

	result = ieee80211_wep_init(local);

	if (result < 0) {
		printk(KERN_DEBUG "%s: Failed to initialize wep: %d\n",
		       wiphy_name(local->hw.wiphy), result);
		goto fail_wep;
	}

	/* add one default STA interface if supported */
	if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
		result = ieee80211_if_add(local, "wlan%d", NULL,
@@ -967,13 +966,13 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)

	return 0;

fail_wep:
	rate_control_deinitialize(local);
fail_rate:
	unregister_netdevice(local->mdev);
	local->mdev = NULL;
fail_dev:
	rtnl_unlock();
	ieee80211_wep_free(local);
fail_wep:
	sta_info_stop(local);
fail_sta_info:
	debugfs_hw_del(local);