diff options
Diffstat (limited to 'net/mac80211/tx.c')
-rw-r--r-- | net/mac80211/tx.c | 58 |
1 files changed, 36 insertions, 22 deletions
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)) |