aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorAndrei Otcheretianski <andrei.otcheretianski@intel.com>2014-05-09 07:11:47 -0400
committerJohannes Berg <johannes.berg@intel.com>2014-05-15 09:00:58 -0400
commit0d06d9ba93ad4272dc3cd2865deb18c9e9885fd5 (patch)
tree20bfaeeb61e088d3004d4667bfb4285000a30c9a /net/mac80211
parent9a774c78e2114c7e8605e3a168ccd552cbe3d922 (diff)
mac80211: Support multiple CSA counters
Support up to IEEE80211_MAX_CSA_COUNTERS_NUM csa counters. This is defined to be 2 now, to support both CSA and eCSA counters. Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com> Signed-off-by: Luciano Coelho <luciano.coelho@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/cfg.c24
-rw-r--r--net/mac80211/ibss.c2
-rw-r--r--net/mac80211/ieee80211_i.h6
-rw-r--r--net/mac80211/main.c2
-rw-r--r--net/mac80211/mesh.c2
-rw-r--r--net/mac80211/tx.c58
6 files changed, 61 insertions, 33 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 7a6f8aba5c46..d44dca56b8ff 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -3191,14 +3191,24 @@ static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata,
3191 if (params->count <= 1) 3191 if (params->count <= 1)
3192 break; 3192 break;
3193 3193
3194 sdata->csa_counter_offset_beacon = 3194 if ((params->n_counter_offsets_beacon >
3195 params->counter_offsets_beacon[0]; 3195 IEEE80211_MAX_CSA_COUNTERS_NUM) ||
3196 (params->n_counter_offsets_presp >
3197 IEEE80211_MAX_CSA_COUNTERS_NUM))
3198 return -EINVAL;
3196 3199
3197 if (params->n_counter_offsets_presp) 3200 /* make sure we don't have garbage in other counters */
3198 sdata->csa_counter_offset_presp = 3201 memset(sdata->csa_counter_offset_beacon, 0,
3199 params->counter_offsets_presp[0]; 3202 sizeof(sdata->csa_counter_offset_beacon));
3200 else 3203 memset(sdata->csa_counter_offset_presp, 0,
3201 sdata->csa_counter_offset_presp = 0; 3204 sizeof(sdata->csa_counter_offset_presp));
3205
3206 memcpy(sdata->csa_counter_offset_beacon,
3207 params->counter_offsets_beacon,
3208 params->n_counter_offsets_beacon * sizeof(u16));
3209 memcpy(sdata->csa_counter_offset_presp,
3210 params->counter_offsets_presp,
3211 params->n_counter_offsets_presp * sizeof(u16));
3202 3212
3203 err = ieee80211_assign_beacon(sdata, &params->beacon_csa); 3213 err = ieee80211_assign_beacon(sdata, &params->beacon_csa);
3204 if (err < 0) { 3214 if (err < 0) {
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index ff4d4155a84d..1bbac94da58d 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -143,7 +143,7 @@ ieee80211_ibss_build_presp(struct ieee80211_sub_if_data *sdata,
143 *pos++ = csa_settings->block_tx ? 1 : 0; 143 *pos++ = csa_settings->block_tx ? 1 : 0;
144 *pos++ = ieee80211_frequency_to_channel( 144 *pos++ = ieee80211_frequency_to_channel(
145 csa_settings->chandef.chan->center_freq); 145 csa_settings->chandef.chan->center_freq);
146 sdata->csa_counter_offset_beacon = (pos - presp->head); 146 sdata->csa_counter_offset_beacon[0] = (pos - presp->head);
147 *pos++ = csa_settings->count; 147 *pos++ = csa_settings->count;
148 } 148 }
149 149
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index fb2d9e755158..05ed592d8bbe 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -70,6 +70,8 @@ struct ieee80211_local;
70 70
71#define IEEE80211_DEAUTH_FRAME_LEN (24 /* hdr */ + 2 /* reason */) 71#define IEEE80211_DEAUTH_FRAME_LEN (24 /* hdr */ + 2 /* reason */)
72 72
73#define IEEE80211_MAX_CSA_COUNTERS_NUM 2
74
73struct ieee80211_fragment_entry { 75struct ieee80211_fragment_entry {
74 unsigned long first_frag_time; 76 unsigned long first_frag_time;
75 unsigned int seq; 77 unsigned int seq;
@@ -753,8 +755,8 @@ struct ieee80211_sub_if_data {
753 struct mac80211_qos_map __rcu *qos_map; 755 struct mac80211_qos_map __rcu *qos_map;
754 756
755 struct work_struct csa_finalize_work; 757 struct work_struct csa_finalize_work;
756 int csa_counter_offset_beacon; 758 u16 csa_counter_offset_beacon[IEEE80211_MAX_CSA_COUNTERS_NUM];
757 int csa_counter_offset_presp; 759 u16 csa_counter_offset_presp[IEEE80211_MAX_CSA_COUNTERS_NUM];
758 bool csa_radar_required; 760 bool csa_radar_required;
759 bool csa_block_tx; /* write-protected by sdata_lock and local->mtx */ 761 bool csa_block_tx; /* write-protected by sdata_lock and local->mtx */
760 struct cfg80211_chan_def csa_chandef; 762 struct cfg80211_chan_def csa_chandef;
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 69175f1539b7..767335f0ca2f 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -954,6 +954,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
954 if (local->hw.wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) 954 if (local->hw.wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)
955 local->hw.wiphy->flags |= WIPHY_FLAG_TDLS_EXTERNAL_SETUP; 955 local->hw.wiphy->flags |= WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
956 956
957 local->hw.wiphy->max_num_csa_counters = IEEE80211_MAX_CSA_COUNTERS_NUM;
958
957 result = wiphy_register(local->hw.wiphy); 959 result = wiphy_register(local->hw.wiphy);
958 if (result < 0) 960 if (result < 0)
959 goto fail_wiphy_register; 961 goto fail_wiphy_register;
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index b06ddc9519ce..6495a3f0428d 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -679,7 +679,7 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
679 *pos++ = 0x0; 679 *pos++ = 0x0;
680 *pos++ = ieee80211_frequency_to_channel( 680 *pos++ = ieee80211_frequency_to_channel(
681 csa->settings.chandef.chan->center_freq); 681 csa->settings.chandef.chan->center_freq);
682 sdata->csa_counter_offset_beacon = hdr_len + 6; 682 sdata->csa_counter_offset_beacon[0] = hdr_len + 6;
683 *pos++ = csa->settings.count; 683 *pos++ = csa->settings.count;
684 *pos++ = WLAN_EID_CHAN_SWITCH_PARAM; 684 *pos++ = WLAN_EID_CHAN_SWITCH_PARAM;
685 *pos++ = 6; 685 *pos++ = 6;
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 263dea5a5cbb..0d1a42d4b6de 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -2417,10 +2417,9 @@ static void ieee80211_update_csa(struct ieee80211_sub_if_data *sdata,
2417 struct beacon_data *beacon) 2417 struct beacon_data *beacon)
2418{ 2418{
2419 struct probe_resp *resp; 2419 struct probe_resp *resp;
2420 int counter_offset_beacon = sdata->csa_counter_offset_beacon;
2421 int counter_offset_presp = sdata->csa_counter_offset_presp;
2422 u8 *beacon_data; 2420 u8 *beacon_data;
2423 size_t beacon_data_len; 2421 size_t beacon_data_len;
2422 int i;
2424 2423
2425 switch (sdata->vif.type) { 2424 switch (sdata->vif.type) {
2426 case NL80211_IFTYPE_AP: 2425 case NL80211_IFTYPE_AP:
@@ -2438,32 +2437,47 @@ static void ieee80211_update_csa(struct ieee80211_sub_if_data *sdata,
2438 default: 2437 default:
2439 return; 2438 return;
2440 } 2439 }
2441 if (WARN_ON(counter_offset_beacon >= beacon_data_len))
2442 return;
2443 2440
2444 /* Warn if the driver did not check for/react to csa 2441 for (i = 0; i < IEEE80211_MAX_CSA_COUNTERS_NUM; ++i) {
2445 * completeness. A beacon with CSA counter set to 0 should 2442 u16 counter_offset_beacon =
2446 * never occur, because a counter of 1 means switch just 2443 sdata->csa_counter_offset_beacon[i];
2447 * before the next beacon. 2444 u16 counter_offset_presp = sdata->csa_counter_offset_presp[i];
2448 */
2449 if (WARN_ON(beacon_data[counter_offset_beacon] == 1))
2450 return;
2451 2445
2452 sdata->csa_current_counter--; 2446 if (counter_offset_beacon) {
2453 beacon_data[counter_offset_beacon] = sdata->csa_current_counter; 2447 if (WARN_ON(counter_offset_beacon >= beacon_data_len))
2448 return;
2454 2449
2455 if (sdata->vif.type == NL80211_IFTYPE_AP && counter_offset_presp) { 2450 /* Warn if the driver did not check for/react to csa
2456 rcu_read_lock(); 2451 * completeness. A beacon with CSA counter set to 0
2457 resp = rcu_dereference(sdata->u.ap.probe_resp); 2452 * should never occur, because a counter of 1 means
2453 * switch just before the next beacon.
2454 */
2455 if (WARN_ON(beacon_data[counter_offset_beacon] == 1))
2456 return;
2458 2457
2459 /* if nl80211 accepted the offset, this should not happen. */ 2458 beacon_data[counter_offset_beacon] =
2460 if (WARN_ON(!resp)) { 2459 sdata->csa_current_counter - 1;
2460 }
2461
2462 if (sdata->vif.type == NL80211_IFTYPE_AP &&
2463 counter_offset_presp) {
2464 rcu_read_lock();
2465 resp = rcu_dereference(sdata->u.ap.probe_resp);
2466
2467 /* If nl80211 accepted the offset, this should
2468 * not happen.
2469 */
2470 if (WARN_ON(!resp)) {
2471 rcu_read_unlock();
2472 return;
2473 }
2474 resp->data[counter_offset_presp] =
2475 sdata->csa_current_counter - 1;
2461 rcu_read_unlock(); 2476 rcu_read_unlock();
2462 return;
2463 } 2477 }
2464 resp->data[counter_offset_presp] = sdata->csa_current_counter;
2465 rcu_read_unlock();
2466 } 2478 }
2479
2480 sdata->csa_current_counter--;
2467} 2481}
2468 2482
2469bool ieee80211_csa_is_complete(struct ieee80211_vif *vif) 2483bool ieee80211_csa_is_complete(struct ieee80211_vif *vif)
@@ -2472,7 +2486,7 @@ bool ieee80211_csa_is_complete(struct ieee80211_vif *vif)
2472 struct beacon_data *beacon = NULL; 2486 struct beacon_data *beacon = NULL;
2473 u8 *beacon_data; 2487 u8 *beacon_data;
2474 size_t beacon_data_len; 2488 size_t beacon_data_len;
2475 int counter_beacon = sdata->csa_counter_offset_beacon; 2489 int counter_beacon = sdata->csa_counter_offset_beacon[0];
2476 int ret = false; 2490 int ret = false;
2477 2491
2478 if (!ieee80211_sdata_running(sdata)) 2492 if (!ieee80211_sdata_running(sdata))