diff options
author | Luciano Coelho <luciano.coelho@intel.com> | 2014-01-13 12:43:00 -0500 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2014-02-04 15:48:06 -0500 |
commit | 66e01cf99e0a9d0cbff21b0288c049654d5acf3e (patch) | |
tree | 260f0faa7f500757b98049ace42b7d34ab002a77 /net/mac80211/tx.c | |
parent | b58e81e96a81c80886011ad87cdbe73585dec4f7 (diff) |
mac80211: only set CSA beacon when at least one beacon must be transmitted
A beacon should never have a Channel Switch Announcement information
element with a count of 0, because a count of 1 means switch just
before the next beacon. So, if a count of 0 was valid in a beacon, it
would have been transmitted in the next channel already, which is
useless. A CSA count equal to zero is only meaningful in action
frames or probe_responses.
Fix the ieee80211_csa_is_complete() and ieee80211_update_csa()
functions accordingly.
With a CSA count of 0, we won't transmit any CSA beacons, because the
switch will happen before the next TBTT. To avoid extra work and
potential confusion in the drivers, complete the CSA immediately,
instead of waiting for the driver to call ieee80211_csa_finish().
To keep things simpler, we also switch immediately when the CSA count
is 1, while in theory we should delay the switch until just before the
next TBTT.
Additionally, move the ieee80211_csa_finish() function to cfg.c,
where it makes more sense.
Tested-by: Simon Wunderlich <sw@simonwunderlich.de>
Acked-by: Simon Wunderlich <sw@simonwunderlich.de>
Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/tx.c')
-rw-r--r-- | net/mac80211/tx.c | 19 |
1 files changed, 7 insertions, 12 deletions
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 27c990bf2320..bb990ecfa655 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -2402,15 +2402,6 @@ static int ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata, | |||
2402 | return 0; | 2402 | return 0; |
2403 | } | 2403 | } |
2404 | 2404 | ||
2405 | void ieee80211_csa_finish(struct ieee80211_vif *vif) | ||
2406 | { | ||
2407 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
2408 | |||
2409 | ieee80211_queue_work(&sdata->local->hw, | ||
2410 | &sdata->csa_finalize_work); | ||
2411 | } | ||
2412 | EXPORT_SYMBOL(ieee80211_csa_finish); | ||
2413 | |||
2414 | static void ieee80211_update_csa(struct ieee80211_sub_if_data *sdata, | 2405 | static void ieee80211_update_csa(struct ieee80211_sub_if_data *sdata, |
2415 | struct beacon_data *beacon) | 2406 | struct beacon_data *beacon) |
2416 | { | 2407 | { |
@@ -2439,8 +2430,12 @@ static void ieee80211_update_csa(struct ieee80211_sub_if_data *sdata, | |||
2439 | if (WARN_ON(counter_offset_beacon >= beacon_data_len)) | 2430 | if (WARN_ON(counter_offset_beacon >= beacon_data_len)) |
2440 | return; | 2431 | return; |
2441 | 2432 | ||
2442 | /* warn if the driver did not check for/react to csa completeness */ | 2433 | /* Warn if the driver did not check for/react to csa |
2443 | if (WARN_ON(beacon_data[counter_offset_beacon] == 0)) | 2434 | * completeness. A beacon with CSA counter set to 0 should |
2435 | * never occur, because a counter of 1 means switch just | ||
2436 | * before the next beacon. | ||
2437 | */ | ||
2438 | if (WARN_ON(beacon_data[counter_offset_beacon] == 1)) | ||
2444 | return; | 2439 | return; |
2445 | 2440 | ||
2446 | beacon_data[counter_offset_beacon]--; | 2441 | beacon_data[counter_offset_beacon]--; |
@@ -2506,7 +2501,7 @@ bool ieee80211_csa_is_complete(struct ieee80211_vif *vif) | |||
2506 | if (WARN_ON(counter_beacon > beacon_data_len)) | 2501 | if (WARN_ON(counter_beacon > beacon_data_len)) |
2507 | goto out; | 2502 | goto out; |
2508 | 2503 | ||
2509 | if (beacon_data[counter_beacon] == 0) | 2504 | if (beacon_data[counter_beacon] == 1) |
2510 | ret = true; | 2505 | ret = true; |
2511 | out: | 2506 | out: |
2512 | rcu_read_unlock(); | 2507 | rcu_read_unlock(); |