aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorMichal Kazior <michal.kazior@tieto.com>2014-06-05 08:21:36 -0400
committerJohannes Berg <johannes.berg@intel.com>2014-06-23 08:22:06 -0400
commitaf296bdb8da4d0a4284de10fc4a61497272ddf11 (patch)
tree5387b60fbc8d858402068f2ee69d57104f961e5f /net/mac80211
parentb49328361bab10d786e321aeae79b4429fdff38c (diff)
mac80211: move csa counters from sdata to beacon/presp
Having csa counters part of beacon and probe_resp structures makes it easier to get rid of possible races between setting a beacon and updating counters on SMP systems by guaranteeing counters are always consistent against given beacon struct. While at it relax WARN_ON into WARN_ON_ONCE to prevent spamming logs and racing. Signed-off-by: Michal Kazior <michal.kazior@tieto.com> [remove pointless array check] Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/cfg.c67
-rw-r--r--net/mac80211/ibss.c2
-rw-r--r--net/mac80211/ieee80211_i.h16
-rw-r--r--net/mac80211/mesh.c2
-rw-r--r--net/mac80211/tx.c103
5 files changed, 115 insertions, 75 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index b6d73c14e1ae..af3eac482acd 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -554,7 +554,8 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy,
554} 554}
555 555
556static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata, 556static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata,
557 const u8 *resp, size_t resp_len) 557 const u8 *resp, size_t resp_len,
558 const struct ieee80211_csa_settings *csa)
558{ 559{
559 struct probe_resp *new, *old; 560 struct probe_resp *new, *old;
560 561
@@ -570,6 +571,11 @@ static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata,
570 new->len = resp_len; 571 new->len = resp_len;
571 memcpy(new->data, resp, resp_len); 572 memcpy(new->data, resp, resp_len);
572 573
574 if (csa)
575 memcpy(new->csa_counter_offsets, csa->counter_offsets_presp,
576 csa->n_counter_offsets_presp *
577 sizeof(new->csa_counter_offsets[0]));
578
573 rcu_assign_pointer(sdata->u.ap.probe_resp, new); 579 rcu_assign_pointer(sdata->u.ap.probe_resp, new);
574 if (old) 580 if (old)
575 kfree_rcu(old, rcu_head); 581 kfree_rcu(old, rcu_head);
@@ -578,7 +584,8 @@ static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata,
578} 584}
579 585
580static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata, 586static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
581 struct cfg80211_beacon_data *params) 587 struct cfg80211_beacon_data *params,
588 const struct ieee80211_csa_settings *csa)
582{ 589{
583 struct beacon_data *new, *old; 590 struct beacon_data *new, *old;
584 int new_head_len, new_tail_len; 591 int new_head_len, new_tail_len;
@@ -622,6 +629,13 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
622 new->head_len = new_head_len; 629 new->head_len = new_head_len;
623 new->tail_len = new_tail_len; 630 new->tail_len = new_tail_len;
624 631
632 if (csa) {
633 new->csa_current_counter = csa->count;
634 memcpy(new->csa_counter_offsets, csa->counter_offsets_beacon,
635 csa->n_counter_offsets_beacon *
636 sizeof(new->csa_counter_offsets[0]));
637 }
638
625 /* copy in head */ 639 /* copy in head */
626 if (params->head) 640 if (params->head)
627 memcpy(new->head, params->head, new_head_len); 641 memcpy(new->head, params->head, new_head_len);
@@ -636,7 +650,7 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
636 memcpy(new->tail, old->tail, new_tail_len); 650 memcpy(new->tail, old->tail, new_tail_len);
637 651
638 err = ieee80211_set_probe_resp(sdata, params->probe_resp, 652 err = ieee80211_set_probe_resp(sdata, params->probe_resp,
639 params->probe_resp_len); 653 params->probe_resp_len, csa);
640 if (err < 0) 654 if (err < 0)
641 return err; 655 return err;
642 if (err == 0) 656 if (err == 0)
@@ -721,7 +735,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
721 sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow |= 735 sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow |=
722 IEEE80211_P2P_OPPPS_ENABLE_BIT; 736 IEEE80211_P2P_OPPPS_ENABLE_BIT;
723 737
724 err = ieee80211_assign_beacon(sdata, &params->beacon); 738 err = ieee80211_assign_beacon(sdata, &params->beacon, NULL);
725 if (err < 0) { 739 if (err < 0) {
726 ieee80211_vif_release_channel(sdata); 740 ieee80211_vif_release_channel(sdata);
727 return err; 741 return err;
@@ -769,7 +783,7 @@ static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev,
769 if (!old) 783 if (!old)
770 return -ENOENT; 784 return -ENOENT;
771 785
772 err = ieee80211_assign_beacon(sdata, params); 786 err = ieee80211_assign_beacon(sdata, params, NULL);
773 if (err < 0) 787 if (err < 0)
774 return err; 788 return err;
775 ieee80211_bss_info_change_notify(sdata, err); 789 ieee80211_bss_info_change_notify(sdata, err);
@@ -2752,7 +2766,8 @@ static int ieee80211_set_after_csa_beacon(struct ieee80211_sub_if_data *sdata,
2752 2766
2753 switch (sdata->vif.type) { 2767 switch (sdata->vif.type) {
2754 case NL80211_IFTYPE_AP: 2768 case NL80211_IFTYPE_AP:
2755 err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon); 2769 err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon,
2770 NULL);
2756 kfree(sdata->u.ap.next_beacon); 2771 kfree(sdata->u.ap.next_beacon);
2757 sdata->u.ap.next_beacon = NULL; 2772 sdata->u.ap.next_beacon = NULL;
2758 2773
@@ -2855,6 +2870,7 @@ static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata,
2855 struct cfg80211_csa_settings *params, 2870 struct cfg80211_csa_settings *params,
2856 u32 *changed) 2871 u32 *changed)
2857{ 2872{
2873 struct ieee80211_csa_settings csa = {};
2858 int err; 2874 int err;
2859 2875
2860 switch (sdata->vif.type) { 2876 switch (sdata->vif.type) {
@@ -2889,20 +2905,13 @@ static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata,
2889 IEEE80211_MAX_CSA_COUNTERS_NUM)) 2905 IEEE80211_MAX_CSA_COUNTERS_NUM))
2890 return -EINVAL; 2906 return -EINVAL;
2891 2907
2892 /* make sure we don't have garbage in other counters */ 2908 csa.counter_offsets_beacon = params->counter_offsets_beacon;
2893 memset(sdata->csa_counter_offset_beacon, 0, 2909 csa.counter_offsets_presp = params->counter_offsets_presp;
2894 sizeof(sdata->csa_counter_offset_beacon)); 2910 csa.n_counter_offsets_beacon = params->n_counter_offsets_beacon;
2895 memset(sdata->csa_counter_offset_presp, 0, 2911 csa.n_counter_offsets_presp = params->n_counter_offsets_presp;
2896 sizeof(sdata->csa_counter_offset_presp)); 2912 csa.count = params->count;
2897
2898 memcpy(sdata->csa_counter_offset_beacon,
2899 params->counter_offsets_beacon,
2900 params->n_counter_offsets_beacon * sizeof(u16));
2901 memcpy(sdata->csa_counter_offset_presp,
2902 params->counter_offsets_presp,
2903 params->n_counter_offsets_presp * sizeof(u16));
2904 2913
2905 err = ieee80211_assign_beacon(sdata, &params->beacon_csa); 2914 err = ieee80211_assign_beacon(sdata, &params->beacon_csa, &csa);
2906 if (err < 0) { 2915 if (err < 0) {
2907 kfree(sdata->u.ap.next_beacon); 2916 kfree(sdata->u.ap.next_beacon);
2908 return err; 2917 return err;
@@ -3046,7 +3055,6 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
3046 sdata->csa_radar_required = params->radar_required; 3055 sdata->csa_radar_required = params->radar_required;
3047 sdata->csa_chandef = params->chandef; 3056 sdata->csa_chandef = params->chandef;
3048 sdata->csa_block_tx = params->block_tx; 3057 sdata->csa_block_tx = params->block_tx;
3049 sdata->csa_current_counter = params->count;
3050 sdata->vif.csa_active = true; 3058 sdata->vif.csa_active = true;
3051 3059
3052 if (sdata->csa_block_tx) 3060 if (sdata->csa_block_tx)
@@ -3194,10 +3202,23 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
3194 sdata->vif.type == NL80211_IFTYPE_ADHOC) && 3202 sdata->vif.type == NL80211_IFTYPE_ADHOC) &&
3195 params->n_csa_offsets) { 3203 params->n_csa_offsets) {
3196 int i; 3204 int i;
3197 u8 c = sdata->csa_current_counter; 3205 struct beacon_data *beacon = NULL;
3198 3206
3199 for (i = 0; i < params->n_csa_offsets; i++) 3207 rcu_read_lock();
3200 data[params->csa_offsets[i]] = c; 3208
3209 if (sdata->vif.type == NL80211_IFTYPE_AP)
3210 beacon = rcu_dereference(sdata->u.ap.beacon);
3211 else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
3212 beacon = rcu_dereference(sdata->u.ibss.presp);
3213 else if (ieee80211_vif_is_mesh(&sdata->vif))
3214 beacon = rcu_dereference(sdata->u.mesh.beacon);
3215
3216 if (beacon)
3217 for (i = 0; i < params->n_csa_offsets; i++)
3218 data[params->csa_offsets[i]] =
3219 beacon->csa_current_counter;
3220
3221 rcu_read_unlock();
3201 } 3222 }
3202 3223
3203 IEEE80211_SKB_CB(skb)->flags = flags; 3224 IEEE80211_SKB_CB(skb)->flags = flags;
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 18ee0a256b1e..713485f9effc 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[0] = (pos - presp->head); 146 presp->csa_counter_offsets[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 4372d48b718f..d9af7ef3c11a 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -229,16 +229,29 @@ struct ieee80211_rx_data {
229 u16 tkip_iv16; 229 u16 tkip_iv16;
230}; 230};
231 231
232struct ieee80211_csa_settings {
233 const u16 *counter_offsets_beacon;
234 const u16 *counter_offsets_presp;
235
236 int n_counter_offsets_beacon;
237 int n_counter_offsets_presp;
238
239 u8 count;
240};
241
232struct beacon_data { 242struct beacon_data {
233 u8 *head, *tail; 243 u8 *head, *tail;
234 int head_len, tail_len; 244 int head_len, tail_len;
235 struct ieee80211_meshconf_ie *meshconf; 245 struct ieee80211_meshconf_ie *meshconf;
246 u16 csa_counter_offsets[IEEE80211_MAX_CSA_COUNTERS_NUM];
247 u8 csa_current_counter;
236 struct rcu_head rcu_head; 248 struct rcu_head rcu_head;
237}; 249};
238 250
239struct probe_resp { 251struct probe_resp {
240 struct rcu_head rcu_head; 252 struct rcu_head rcu_head;
241 int len; 253 int len;
254 u16 csa_counter_offsets[IEEE80211_MAX_CSA_COUNTERS_NUM];
242 u8 data[0]; 255 u8 data[0];
243}; 256};
244 257
@@ -754,8 +767,6 @@ struct ieee80211_sub_if_data {
754 struct mac80211_qos_map __rcu *qos_map; 767 struct mac80211_qos_map __rcu *qos_map;
755 768
756 struct work_struct csa_finalize_work; 769 struct work_struct csa_finalize_work;
757 u16 csa_counter_offset_beacon[IEEE80211_MAX_CSA_COUNTERS_NUM];
758 u16 csa_counter_offset_presp[IEEE80211_MAX_CSA_COUNTERS_NUM];
759 bool csa_radar_required; 770 bool csa_radar_required;
760 bool csa_block_tx; /* write-protected by sdata_lock and local->mtx */ 771 bool csa_block_tx; /* write-protected by sdata_lock and local->mtx */
761 struct cfg80211_chan_def csa_chandef; 772 struct cfg80211_chan_def csa_chandef;
@@ -767,7 +778,6 @@ struct ieee80211_sub_if_data {
767 struct ieee80211_chanctx *reserved_chanctx; 778 struct ieee80211_chanctx *reserved_chanctx;
768 struct cfg80211_chan_def reserved_chandef; 779 struct cfg80211_chan_def reserved_chandef;
769 bool reserved_radar_required; 780 bool reserved_radar_required;
770 u8 csa_current_counter;
771 781
772 /* used to reconfigure hardware SM PS */ 782 /* used to reconfigure hardware SM PS */
773 struct work_struct recalc_smps; 783 struct work_struct recalc_smps;
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index da164685b524..e9f99c1e3fad 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[0] = hdr_len + 6; 682 bcn->csa_counter_offsets[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 3c80bf29b050..ed56f0091663 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -2426,7 +2426,7 @@ static void ieee80211_set_csa(struct ieee80211_sub_if_data *sdata,
2426 u8 *beacon_data; 2426 u8 *beacon_data;
2427 size_t beacon_data_len; 2427 size_t beacon_data_len;
2428 int i; 2428 int i;
2429 u8 count = sdata->csa_current_counter; 2429 u8 count = beacon->csa_current_counter;
2430 2430
2431 switch (sdata->vif.type) { 2431 switch (sdata->vif.type) {
2432 case NL80211_IFTYPE_AP: 2432 case NL80211_IFTYPE_AP:
@@ -2445,46 +2445,53 @@ static void ieee80211_set_csa(struct ieee80211_sub_if_data *sdata,
2445 return; 2445 return;
2446 } 2446 }
2447 2447
2448 rcu_read_lock();
2448 for (i = 0; i < IEEE80211_MAX_CSA_COUNTERS_NUM; ++i) { 2449 for (i = 0; i < IEEE80211_MAX_CSA_COUNTERS_NUM; ++i) {
2449 u16 counter_offset_beacon = 2450 resp = rcu_dereference(sdata->u.ap.probe_resp);
2450 sdata->csa_counter_offset_beacon[i];
2451 u16 counter_offset_presp = sdata->csa_counter_offset_presp[i];
2452
2453 if (counter_offset_beacon) {
2454 if (WARN_ON(counter_offset_beacon >= beacon_data_len))
2455 return;
2456
2457 beacon_data[counter_offset_beacon] = count;
2458 }
2459
2460 if (sdata->vif.type == NL80211_IFTYPE_AP &&
2461 counter_offset_presp) {
2462 rcu_read_lock();
2463 resp = rcu_dereference(sdata->u.ap.probe_resp);
2464 2451
2465 /* If nl80211 accepted the offset, this should 2452 if (beacon->csa_counter_offsets[i]) {
2466 * not happen. 2453 if (WARN_ON_ONCE(beacon->csa_counter_offsets[i] >=
2467 */ 2454 beacon_data_len)) {
2468 if (WARN_ON(!resp)) {
2469 rcu_read_unlock(); 2455 rcu_read_unlock();
2470 return; 2456 return;
2471 } 2457 }
2472 resp->data[counter_offset_presp] = count; 2458
2473 rcu_read_unlock(); 2459 beacon_data[beacon->csa_counter_offsets[i]] = count;
2474 } 2460 }
2461
2462 if (sdata->vif.type == NL80211_IFTYPE_AP && resp)
2463 resp->data[resp->csa_counter_offsets[i]] = count;
2475 } 2464 }
2465 rcu_read_unlock();
2476} 2466}
2477 2467
2478u8 ieee80211_csa_update_counter(struct ieee80211_vif *vif) 2468u8 ieee80211_csa_update_counter(struct ieee80211_vif *vif)
2479{ 2469{
2480 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); 2470 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
2471 struct beacon_data *beacon = NULL;
2472 u8 count = 0;
2481 2473
2482 sdata->csa_current_counter--; 2474 rcu_read_lock();
2475
2476 if (sdata->vif.type == NL80211_IFTYPE_AP)
2477 beacon = rcu_dereference(sdata->u.ap.beacon);
2478 else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
2479 beacon = rcu_dereference(sdata->u.ibss.presp);
2480 else if (ieee80211_vif_is_mesh(&sdata->vif))
2481 beacon = rcu_dereference(sdata->u.mesh.beacon);
2482
2483 if (!beacon)
2484 goto unlock;
2485
2486 beacon->csa_current_counter--;
2483 2487
2484 /* the counter should never reach 0 */ 2488 /* the counter should never reach 0 */
2485 WARN_ON(!sdata->csa_current_counter); 2489 WARN_ON_ONCE(!beacon->csa_current_counter);
2490 count = beacon->csa_current_counter;
2486 2491
2487 return sdata->csa_current_counter; 2492unlock:
2493 rcu_read_unlock();
2494 return count;
2488} 2495}
2489EXPORT_SYMBOL(ieee80211_csa_update_counter); 2496EXPORT_SYMBOL(ieee80211_csa_update_counter);
2490 2497
@@ -2494,7 +2501,6 @@ bool ieee80211_csa_is_complete(struct ieee80211_vif *vif)
2494 struct beacon_data *beacon = NULL; 2501 struct beacon_data *beacon = NULL;
2495 u8 *beacon_data; 2502 u8 *beacon_data;
2496 size_t beacon_data_len; 2503 size_t beacon_data_len;
2497 int counter_beacon = sdata->csa_counter_offset_beacon[0];
2498 int ret = false; 2504 int ret = false;
2499 2505
2500 if (!ieee80211_sdata_running(sdata)) 2506 if (!ieee80211_sdata_running(sdata))
@@ -2532,10 +2538,10 @@ bool ieee80211_csa_is_complete(struct ieee80211_vif *vif)
2532 goto out; 2538 goto out;
2533 } 2539 }
2534 2540
2535 if (WARN_ON(counter_beacon > beacon_data_len)) 2541 if (WARN_ON_ONCE(beacon->csa_counter_offsets[0] > beacon_data_len))
2536 goto out; 2542 goto out;
2537 2543
2538 if (beacon_data[counter_beacon] == 1) 2544 if (beacon_data[beacon->csa_counter_offsets[0]] == 1)
2539 ret = true; 2545 ret = true;
2540 out: 2546 out:
2541 rcu_read_unlock(); 2547 rcu_read_unlock();
@@ -2551,6 +2557,7 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw,
2551 bool is_template) 2557 bool is_template)
2552{ 2558{
2553 struct ieee80211_local *local = hw_to_local(hw); 2559 struct ieee80211_local *local = hw_to_local(hw);
2560 struct beacon_data *beacon = NULL;
2554 struct sk_buff *skb = NULL; 2561 struct sk_buff *skb = NULL;
2555 struct ieee80211_tx_info *info; 2562 struct ieee80211_tx_info *info;
2556 struct ieee80211_sub_if_data *sdata = NULL; 2563 struct ieee80211_sub_if_data *sdata = NULL;
@@ -2572,8 +2579,8 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw,
2572 2579
2573 if (sdata->vif.type == NL80211_IFTYPE_AP) { 2580 if (sdata->vif.type == NL80211_IFTYPE_AP) {
2574 struct ieee80211_if_ap *ap = &sdata->u.ap; 2581 struct ieee80211_if_ap *ap = &sdata->u.ap;
2575 struct beacon_data *beacon = rcu_dereference(ap->beacon);
2576 2582
2583 beacon = rcu_dereference(ap->beacon);
2577 if (beacon) { 2584 if (beacon) {
2578 if (sdata->vif.csa_active) { 2585 if (sdata->vif.csa_active) {
2579 if (!is_template) 2586 if (!is_template)
@@ -2616,34 +2623,34 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw,
2616 } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { 2623 } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
2617 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; 2624 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
2618 struct ieee80211_hdr *hdr; 2625 struct ieee80211_hdr *hdr;
2619 struct beacon_data *presp = rcu_dereference(ifibss->presp);
2620 2626
2621 if (!presp) 2627 beacon = rcu_dereference(ifibss->presp);
2628 if (!beacon)
2622 goto out; 2629 goto out;
2623 2630
2624 if (sdata->vif.csa_active) { 2631 if (sdata->vif.csa_active) {
2625 if (!is_template) 2632 if (!is_template)
2626 ieee80211_csa_update_counter(vif); 2633 ieee80211_csa_update_counter(vif);
2627 2634
2628 ieee80211_set_csa(sdata, presp); 2635 ieee80211_set_csa(sdata, beacon);
2629 } 2636 }
2630 2637
2631 skb = dev_alloc_skb(local->tx_headroom + presp->head_len + 2638 skb = dev_alloc_skb(local->tx_headroom + beacon->head_len +
2632 local->hw.extra_beacon_tailroom); 2639 local->hw.extra_beacon_tailroom);
2633 if (!skb) 2640 if (!skb)
2634 goto out; 2641 goto out;
2635 skb_reserve(skb, local->tx_headroom); 2642 skb_reserve(skb, local->tx_headroom);
2636 memcpy(skb_put(skb, presp->head_len), presp->head, 2643 memcpy(skb_put(skb, beacon->head_len), beacon->head,
2637 presp->head_len); 2644 beacon->head_len);
2638 2645
2639 hdr = (struct ieee80211_hdr *) skb->data; 2646 hdr = (struct ieee80211_hdr *) skb->data;
2640 hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | 2647 hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
2641 IEEE80211_STYPE_BEACON); 2648 IEEE80211_STYPE_BEACON);
2642 } else if (ieee80211_vif_is_mesh(&sdata->vif)) { 2649 } else if (ieee80211_vif_is_mesh(&sdata->vif)) {
2643 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; 2650 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
2644 struct beacon_data *bcn = rcu_dereference(ifmsh->beacon);
2645 2651
2646 if (!bcn) 2652 beacon = rcu_dereference(ifmsh->beacon);
2653 if (!beacon)
2647 goto out; 2654 goto out;
2648 2655
2649 if (sdata->vif.csa_active) { 2656 if (sdata->vif.csa_active) {
@@ -2655,40 +2662,42 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw,
2655 */ 2662 */
2656 ieee80211_csa_update_counter(vif); 2663 ieee80211_csa_update_counter(vif);
2657 2664
2658 ieee80211_set_csa(sdata, bcn); 2665 ieee80211_set_csa(sdata, beacon);
2659 } 2666 }
2660 2667
2661 if (ifmsh->sync_ops) 2668 if (ifmsh->sync_ops)
2662 ifmsh->sync_ops->adjust_tbtt(sdata, bcn); 2669 ifmsh->sync_ops->adjust_tbtt(sdata, beacon);
2663 2670
2664 skb = dev_alloc_skb(local->tx_headroom + 2671 skb = dev_alloc_skb(local->tx_headroom +
2665 bcn->head_len + 2672 beacon->head_len +
2666 256 + /* TIM IE */ 2673 256 + /* TIM IE */
2667 bcn->tail_len + 2674 beacon->tail_len +
2668 local->hw.extra_beacon_tailroom); 2675 local->hw.extra_beacon_tailroom);
2669 if (!skb) 2676 if (!skb)
2670 goto out; 2677 goto out;
2671 skb_reserve(skb, local->tx_headroom); 2678 skb_reserve(skb, local->tx_headroom);
2672 memcpy(skb_put(skb, bcn->head_len), bcn->head, bcn->head_len); 2679 memcpy(skb_put(skb, beacon->head_len), beacon->head,
2680 beacon->head_len);
2673 ieee80211_beacon_add_tim(sdata, &ifmsh->ps, skb, is_template); 2681 ieee80211_beacon_add_tim(sdata, &ifmsh->ps, skb, is_template);
2674 2682
2675 if (offs) { 2683 if (offs) {
2676 offs->tim_offset = bcn->head_len; 2684 offs->tim_offset = beacon->head_len;
2677 offs->tim_length = skb->len - bcn->head_len; 2685 offs->tim_length = skb->len - beacon->head_len;
2678 } 2686 }
2679 2687
2680 memcpy(skb_put(skb, bcn->tail_len), bcn->tail, bcn->tail_len); 2688 memcpy(skb_put(skb, beacon->tail_len), beacon->tail,
2689 beacon->tail_len);
2681 } else { 2690 } else {
2682 WARN_ON(1); 2691 WARN_ON(1);
2683 goto out; 2692 goto out;
2684 } 2693 }
2685 2694
2686 /* CSA offsets */ 2695 /* CSA offsets */
2687 if (offs) { 2696 if (offs && beacon) {
2688 int i; 2697 int i;
2689 2698
2690 for (i = 0; i < IEEE80211_MAX_CSA_COUNTERS_NUM; i++) { 2699 for (i = 0; i < IEEE80211_MAX_CSA_COUNTERS_NUM; i++) {
2691 u16 csa_off = sdata->csa_counter_offset_beacon[i]; 2700 u16 csa_off = beacon->csa_counter_offsets[i];
2692 2701
2693 if (!csa_off) 2702 if (!csa_off)
2694 continue; 2703 continue;