diff options
author | Andrei Otcheretianski <andrei.otcheretianski@intel.com> | 2014-05-09 07:11:47 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2014-05-15 09:00:58 -0400 |
commit | 0d06d9ba93ad4272dc3cd2865deb18c9e9885fd5 (patch) | |
tree | 20bfaeeb61e088d3004d4667bfb4285000a30c9a /net/mac80211 | |
parent | 9a774c78e2114c7e8605e3a168ccd552cbe3d922 (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.c | 24 | ||||
-rw-r--r-- | net/mac80211/ibss.c | 2 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 6 | ||||
-rw-r--r-- | net/mac80211/main.c | 2 | ||||
-rw-r--r-- | net/mac80211/mesh.c | 2 | ||||
-rw-r--r-- | net/mac80211/tx.c | 58 |
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, ¶ms->beacon_csa); | 3213 | err = ieee80211_assign_beacon(sdata, ¶ms->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 | |||
73 | struct ieee80211_fragment_entry { | 75 | struct 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 | ||
2469 | bool ieee80211_csa_is_complete(struct ieee80211_vif *vif) | 2483 | bool 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)) |