summaryrefslogtreecommitdiff
path: root/net/wireless/reg.c
diff options
context:
space:
mode:
authorLuis R. Rodriguez <mcgrof@do-not-panic.com>2012-12-19 10:53:02 -0800
committerJohannes Berg <johannes.berg@intel.com>2013-01-03 13:01:37 +0100
commit3ebfa6e76beab01e644e1facd5fdb84d4274043e (patch)
tree7324fb5171326d8ce0af3eb22c2d50a9f5531573 /net/wireless/reg.c
parentad2d223aa900179031feb40273881e212941573d (diff)
downloadlinux-stable-3ebfa6e76beab01e644e1facd5fdb84d4274043e.tar.gz
linux-stable-3ebfa6e76beab01e644e1facd5fdb84d4274043e.tar.bz2
linux-stable-3ebfa6e76beab01e644e1facd5fdb84d4274043e.zip
cfg80211: do not process beacon hints if one is already queued
Regulatory beacon hints are used to help with world roaming and as it is right now we learn from a beacon hint processed on one wiphy to all other wiphys. The processing of beacon hints however is scheduled and if we have a lot of interfaces we may hit the case that we'll queue a the same beacon hint many times until its processed. To avoid this do a lookup on the queued up beacon hints prior to adding a new beacon hint. If the beacon hint is removed from the pending reg beacon hint list then it would be processed and we'd ensure all wiphys would have learned from it, if its on the pending reg beacon list we'd now find it prior to it being processed. Tested-by: Ben Greear <greearb@candelatech.com> Reported-by: Ben Greear <greearb@candelatech.com> Reported-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: Luis R. Rodriguez <mcgrof@do-not-panic.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/wireless/reg.c')
-rw-r--r--net/wireless/reg.c19
1 files changed, 19 insertions, 0 deletions
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index fd53d975c0bc..2a3ae4d1001d 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -1925,11 +1925,23 @@ static bool freq_is_chan_12_13_14(u16 freq)
return false;
}
+static bool pending_reg_beacon(struct ieee80211_channel *beacon_chan)
+{
+ struct reg_beacon *pending_beacon;
+
+ list_for_each_entry(pending_beacon, &reg_pending_beacons, list)
+ if (beacon_chan->center_freq ==
+ pending_beacon->chan.center_freq)
+ return true;
+ return false;
+}
+
int regulatory_hint_found_beacon(struct wiphy *wiphy,
struct ieee80211_channel *beacon_chan,
gfp_t gfp)
{
struct reg_beacon *reg_beacon;
+ bool processing;
if (beacon_chan->beacon_found ||
beacon_chan->flags & IEEE80211_CHAN_RADAR ||
@@ -1937,6 +1949,13 @@ int regulatory_hint_found_beacon(struct wiphy *wiphy,
!freq_is_chan_12_13_14(beacon_chan->center_freq)))
return 0;
+ spin_lock_bh(&reg_pending_beacons_lock);
+ processing = pending_reg_beacon(beacon_chan);
+ spin_unlock_bh(&reg_pending_beacons_lock);
+
+ if (processing)
+ return 0;
+
reg_beacon = kzalloc(sizeof(struct reg_beacon), gfp);
if (!reg_beacon)
return -ENOMEM;