aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/tx.c
diff options
context:
space:
mode:
authorLuciano Coelho <luciano.coelho@intel.com>2014-01-13 12:43:00 -0500
committerJohannes Berg <johannes.berg@intel.com>2014-02-04 15:48:06 -0500
commit66e01cf99e0a9d0cbff21b0288c049654d5acf3e (patch)
tree260f0faa7f500757b98049ace42b7d34ab002a77 /net/mac80211/tx.c
parentb58e81e96a81c80886011ad87cdbe73585dec4f7 (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.c19
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
2405void 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}
2412EXPORT_SYMBOL(ieee80211_csa_finish);
2413
2414static void ieee80211_update_csa(struct ieee80211_sub_if_data *sdata, 2405static 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();