aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJuuso Oikarinen <juuso.oikarinen@nokia.com>2011-03-28 07:32:32 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-03-28 15:42:02 -0400
commit2b78ac9bfc7483ba4bda9ad3d10dd4afcf88337c (patch)
treeda48e2e10050b2e535b908119bf60fe86b17b1e4
parentbef9bacc4ec7ea6a02876164cd6ccaa4759edce4 (diff)
cfg80211: fix BSS double-unlinking (continued)
This patch adds to the fix "fix BSS double-unlinking" (commit 3207390a8b58bfc1335750f91cf6783c48ca19ca) by Johannes Berg. It turns out, that the double-unlinking scenario can also occur if expired BSS elements are removed whilst an interface is performing association. To work around that, replace list_del with list_del_init also in the "cfg80211_bss_expire" function, so that the check for whether the BSS still is in the list works correctly in cfg80211_unlink_bss. Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com> Reviewed-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--net/wireless/scan.c18
1 files changed, 11 insertions, 7 deletions
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 300c11d99997..fbf6f33ae4d0 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -124,6 +124,15 @@ void cfg80211_bss_age(struct cfg80211_registered_device *dev,
124} 124}
125 125
126/* must hold dev->bss_lock! */ 126/* must hold dev->bss_lock! */
127static void __cfg80211_unlink_bss(struct cfg80211_registered_device *dev,
128 struct cfg80211_internal_bss *bss)
129{
130 list_del_init(&bss->list);
131 rb_erase(&bss->rbn, &dev->bss_tree);
132 kref_put(&bss->ref, bss_release);
133}
134
135/* must hold dev->bss_lock! */
127void cfg80211_bss_expire(struct cfg80211_registered_device *dev) 136void cfg80211_bss_expire(struct cfg80211_registered_device *dev)
128{ 137{
129 struct cfg80211_internal_bss *bss, *tmp; 138 struct cfg80211_internal_bss *bss, *tmp;
@@ -134,9 +143,7 @@ void cfg80211_bss_expire(struct cfg80211_registered_device *dev)
134 continue; 143 continue;
135 if (!time_after(jiffies, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE)) 144 if (!time_after(jiffies, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE))
136 continue; 145 continue;
137 list_del(&bss->list); 146 __cfg80211_unlink_bss(dev, bss);
138 rb_erase(&bss->rbn, &dev->bss_tree);
139 kref_put(&bss->ref, bss_release);
140 expired = true; 147 expired = true;
141 } 148 }
142 149
@@ -669,11 +676,8 @@ void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *pub)
669 676
670 spin_lock_bh(&dev->bss_lock); 677 spin_lock_bh(&dev->bss_lock);
671 if (!list_empty(&bss->list)) { 678 if (!list_empty(&bss->list)) {
672 list_del_init(&bss->list); 679 __cfg80211_unlink_bss(dev, bss);
673 dev->bss_generation++; 680 dev->bss_generation++;
674 rb_erase(&bss->rbn, &dev->bss_tree);
675
676 kref_put(&bss->ref, bss_release);
677 } 681 }
678 spin_unlock_bh(&dev->bss_lock); 682 spin_unlock_bh(&dev->bss_lock);
679} 683}