diff options
author | Juuso Oikarinen <juuso.oikarinen@nokia.com> | 2010-06-09 06:43:26 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-06-14 15:42:31 -0400 |
commit | 685429623f88d84f98bd5daffc3c427c408740d4 (patch) | |
tree | d50f119094dd3fb7668f837dbe50857d11bb4fa3 /net/mac80211/iface.c | |
parent | 5ea096c0c85e80335889539899af9a4717976e0b (diff) |
mac80211: Fix circular locking dependency in ARP filter handling
There is a circular locking dependency when configuring the
hardware ARP filters on association, occurring when flushing the mac80211
workqueue. This is what happens:
[ 92.026800] =======================================================
[ 92.030507] [ INFO: possible circular locking dependency detected ]
[ 92.030507] 2.6.34-04781-g2b2c009 #85
[ 92.030507] -------------------------------------------------------
[ 92.030507] modprobe/5225 is trying to acquire lock:
[ 92.030507] ((wiphy_name(local->hw.wiphy))){+.+.+.}, at: [<ffffffff8105b5c0>] flush_workq
ueue+0x0/0xb0
[ 92.030507]
[ 92.030507] but task is already holding lock:
[ 92.030507] (rtnl_mutex){+.+.+.}, at: [<ffffffff812b9ce2>] rtnl_lock+0x12/0x20
[ 92.030507]
[ 92.030507] which lock already depends on the new lock.
[ 92.030507]
[ 92.030507]
[ 92.030507] the existing dependency chain (in reverse order) is:
[ 92.030507]
[ 92.030507] -> #2 (rtnl_mutex){+.+.+.}:
[ 92.030507] [<ffffffff810761fb>] lock_acquire+0xdb/0x110
[ 92.030507] [<ffffffff81341754>] mutex_lock_nested+0x44/0x300
[ 92.030507] [<ffffffff812b9ce2>] rtnl_lock+0x12/0x20
[ 92.030507] [<ffffffffa022d47c>] ieee80211_assoc_done+0x6c/0xe0 [mac80211]
[ 92.030507] [<ffffffffa022f2ad>] ieee80211_work_work+0x31d/0x1280 [mac80211]
[ 92.030507] -> #1 ((&local->work_work)){+.+.+.}:
[ 92.030507] [<ffffffff810761fb>] lock_acquire+0xdb/0x110
[ 92.030507] [<ffffffff8105a51a>] worker_thread+0x22a/0x370
[ 92.030507] [<ffffffff8105ecc6>] kthread+0x96/0xb0
[ 92.030507] [<ffffffff81003a94>] kernel_thread_helper+0x4/0x10
[ 92.030507]
[ 92.030507] -> #0 ((wiphy_name(local->hw.wiphy))){+.+.+.}:
[ 92.030507] [<ffffffff81075fdc>] __lock_acquire+0x1c0c/0x1d50
[ 92.030507] [<ffffffff810761fb>] lock_acquire+0xdb/0x110
[ 92.030507] [<ffffffff8105b60e>] flush_workqueue+0x4e/0xb0
[ 92.030507] [<ffffffffa023ff7b>] ieee80211_stop_device+0x2b/0xb0 [mac80211]
[ 92.030507] [<ffffffffa0231635>] ieee80211_stop+0x3e5/0x680 [mac80211]
The locking in this case is quite complex. Fix the problem by rewriting the
way the hardware ARP filter list is handled - i.e. make a copy of the address
list to the bss_conf struct, and provide that list to the hardware driver
when needed.
The current patch will enable filtering also in promiscuous mode. This may need
to be changed in the future.
Reported-by: Reinette Chatre <reinette.chatre@intel.com>
Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/iface.c')
-rw-r--r-- | net/mac80211/iface.c | 3 |
1 files changed, 3 insertions, 0 deletions
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 490be2f3af27..910729fc18cd 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -1076,6 +1076,9 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1076 | sdata->wdev.wiphy = local->hw.wiphy; | 1076 | sdata->wdev.wiphy = local->hw.wiphy; |
1077 | sdata->local = local; | 1077 | sdata->local = local; |
1078 | sdata->dev = ndev; | 1078 | sdata->dev = ndev; |
1079 | #ifdef CONFIG_INET | ||
1080 | sdata->arp_filter_state = true; | ||
1081 | #endif | ||
1079 | 1082 | ||
1080 | for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) | 1083 | for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) |
1081 | skb_queue_head_init(&sdata->fragments[i].skb_list); | 1084 | skb_queue_head_init(&sdata->fragments[i].skb_list); |