diff options
author | Ivo van Doorn <ivdoorn@gmail.com> | 2008-06-25 15:27:00 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-06-27 14:49:52 -0400 |
commit | 980dfcb93232907034a2c92d62d3a7d6ac7bef44 (patch) | |
tree | fbb8ed96c1ed2164ad507f57cb551bf2584da3a7 /drivers/net/wireless/rt2x00/rt2x00mac.c | |
parent | 7ac3b02536c9ccfcc8aabc4c135a371ac4641805 (diff) |
rt2x00: Fix lock dependency errror
This fixes a circular locking dependency in the workqueue handling.
The interface work task uses the mac80211 function
ieee80211_iterate_active_interfaces() which grabs the RTNL lock.
However when the interface is brough down, this happens under the RTNL
lock as well, this causes problems because mac80211 will flush the workqueue
during the ifdown event. This causes mac80211 to wait until the driver has
completed all work which can't finish because it is waiting on the RTNL lock.
This is fixed by moving rt2x00 workqueue tasks on a different workqueue,
this workqueue can be flushed when the ieee80211_hw structure is removed
by the driver (when the driver is unloaded) which does not happen under the
RTNL lock.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00mac.c')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00mac.c | 4 |
1 files changed, 2 insertions, 2 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 87e280a21971..9cb023edd2e9 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c | |||
@@ -428,7 +428,7 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw, | |||
428 | if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags)) | 428 | if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags)) |
429 | rt2x00dev->ops->lib->config_filter(rt2x00dev, *total_flags); | 429 | rt2x00dev->ops->lib->config_filter(rt2x00dev, *total_flags); |
430 | else | 430 | else |
431 | queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->filter_work); | 431 | queue_work(rt2x00dev->workqueue, &rt2x00dev->filter_work); |
432 | } | 432 | } |
433 | EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter); | 433 | EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter); |
434 | 434 | ||
@@ -509,7 +509,7 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, | |||
509 | memcpy(&intf->conf, bss_conf, sizeof(*bss_conf)); | 509 | memcpy(&intf->conf, bss_conf, sizeof(*bss_conf)); |
510 | if (delayed) { | 510 | if (delayed) { |
511 | intf->delayed_flags |= delayed; | 511 | intf->delayed_flags |= delayed; |
512 | queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work); | 512 | queue_work(rt2x00dev->workqueue, &rt2x00dev->intf_work); |
513 | } | 513 | } |
514 | spin_unlock(&intf->lock); | 514 | spin_unlock(&intf->lock); |
515 | } | 515 | } |