aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2013-08-09 15:08:10 -0400
committerJohn W. Linville <linville@tuxdriver.com>2013-08-09 15:08:10 -0400
commitfa5978447cb0144411df3a588e3d01459c12d855 (patch)
tree998e58c515def864c8cd87511625d1e7184a7a21 /net/mac80211
parent2437f3c5d6bc07252c6d7d24448755e0c35ed91c (diff)
parent73da7d5bab79ad7e16ff44d67c3fe8b9c0b33e5b (diff)
Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/cfg.c187
-rw-r--r--net/mac80211/chan.c58
-rw-r--r--net/mac80211/debugfs_sta.c9
-rw-r--r--net/mac80211/driver-ops.h13
-rw-r--r--net/mac80211/ibss.c30
-rw-r--r--net/mac80211/ieee80211_i.h18
-rw-r--r--net/mac80211/iface.c9
-rw-r--r--net/mac80211/led.c19
-rw-r--r--net/mac80211/led.h4
-rw-r--r--net/mac80211/status.c78
-rw-r--r--net/mac80211/trace.h26
-rw-r--r--net/mac80211/tx.c79
12 files changed, 497 insertions, 33 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 973594b229f4..31fc2247bc37 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -862,8 +862,8 @@ static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata,
862 return 0; 862 return 0;
863} 863}
864 864
865static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata, 865int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
866 struct cfg80211_beacon_data *params) 866 struct cfg80211_beacon_data *params)
867{ 867{
868 struct beacon_data *new, *old; 868 struct beacon_data *new, *old;
869 int new_head_len, new_tail_len; 869 int new_head_len, new_tail_len;
@@ -1026,6 +1026,12 @@ static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev,
1026 1026
1027 sdata = IEEE80211_DEV_TO_SUB_IF(dev); 1027 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1028 1028
1029 /* don't allow changing the beacon while CSA is in place - offset
1030 * of channel switch counter may change
1031 */
1032 if (sdata->vif.csa_active)
1033 return -EBUSY;
1034
1029 old = rtnl_dereference(sdata->u.ap.beacon); 1035 old = rtnl_dereference(sdata->u.ap.beacon);
1030 if (!old) 1036 if (!old)
1031 return -ENOENT; 1037 return -ENOENT;
@@ -1050,6 +1056,10 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
1050 return -ENOENT; 1056 return -ENOENT;
1051 old_probe_resp = rtnl_dereference(sdata->u.ap.probe_resp); 1057 old_probe_resp = rtnl_dereference(sdata->u.ap.probe_resp);
1052 1058
1059 /* abort any running channel switch */
1060 sdata->vif.csa_active = false;
1061 cancel_work_sync(&sdata->csa_finalize_work);
1062
1053 /* turn off carrier for this interface and dependent VLANs */ 1063 /* turn off carrier for this interface and dependent VLANs */
1054 list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) 1064 list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
1055 netif_carrier_off(vlan->dev); 1065 netif_carrier_off(vlan->dev);
@@ -2777,6 +2787,178 @@ static int ieee80211_start_radar_detection(struct wiphy *wiphy,
2777 return 0; 2787 return 0;
2778} 2788}
2779 2789
2790static struct cfg80211_beacon_data *
2791cfg80211_beacon_dup(struct cfg80211_beacon_data *beacon)
2792{
2793 struct cfg80211_beacon_data *new_beacon;
2794 u8 *pos;
2795 int len;
2796
2797 len = beacon->head_len + beacon->tail_len + beacon->beacon_ies_len +
2798 beacon->proberesp_ies_len + beacon->assocresp_ies_len +
2799 beacon->probe_resp_len;
2800
2801 new_beacon = kzalloc(sizeof(*new_beacon) + len, GFP_KERNEL);
2802 if (!new_beacon)
2803 return NULL;
2804
2805 pos = (u8 *)(new_beacon + 1);
2806 if (beacon->head_len) {
2807 new_beacon->head_len = beacon->head_len;
2808 new_beacon->head = pos;
2809 memcpy(pos, beacon->head, beacon->head_len);
2810 pos += beacon->head_len;
2811 }
2812 if (beacon->tail_len) {
2813 new_beacon->tail_len = beacon->tail_len;
2814 new_beacon->tail = pos;
2815 memcpy(pos, beacon->tail, beacon->tail_len);
2816 pos += beacon->tail_len;
2817 }
2818 if (beacon->beacon_ies_len) {
2819 new_beacon->beacon_ies_len = beacon->beacon_ies_len;
2820 new_beacon->beacon_ies = pos;
2821 memcpy(pos, beacon->beacon_ies, beacon->beacon_ies_len);
2822 pos += beacon->beacon_ies_len;
2823 }
2824 if (beacon->proberesp_ies_len) {
2825 new_beacon->proberesp_ies_len = beacon->proberesp_ies_len;
2826 new_beacon->proberesp_ies = pos;
2827 memcpy(pos, beacon->proberesp_ies, beacon->proberesp_ies_len);
2828 pos += beacon->proberesp_ies_len;
2829 }
2830 if (beacon->assocresp_ies_len) {
2831 new_beacon->assocresp_ies_len = beacon->assocresp_ies_len;
2832 new_beacon->assocresp_ies = pos;
2833 memcpy(pos, beacon->assocresp_ies, beacon->assocresp_ies_len);
2834 pos += beacon->assocresp_ies_len;
2835 }
2836 if (beacon->probe_resp_len) {
2837 new_beacon->probe_resp_len = beacon->probe_resp_len;
2838 beacon->probe_resp = pos;
2839 memcpy(pos, beacon->probe_resp, beacon->probe_resp_len);
2840 pos += beacon->probe_resp_len;
2841 }
2842
2843 return new_beacon;
2844}
2845
2846void ieee80211_csa_finalize_work(struct work_struct *work)
2847{
2848 struct ieee80211_sub_if_data *sdata =
2849 container_of(work, struct ieee80211_sub_if_data,
2850 csa_finalize_work);
2851 struct ieee80211_local *local = sdata->local;
2852 int err, changed;
2853
2854 if (!ieee80211_sdata_running(sdata))
2855 return;
2856
2857 if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP))
2858 return;
2859
2860 sdata->radar_required = sdata->csa_radar_required;
2861 err = ieee80211_vif_change_channel(sdata, &local->csa_chandef,
2862 &changed);
2863 if (WARN_ON(err < 0))
2864 return;
2865
2866 err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon);
2867 if (err < 0)
2868 return;
2869
2870 changed |= err;
2871 kfree(sdata->u.ap.next_beacon);
2872 sdata->u.ap.next_beacon = NULL;
2873 sdata->vif.csa_active = false;
2874
2875 ieee80211_wake_queues_by_reason(&sdata->local->hw,
2876 IEEE80211_MAX_QUEUE_MAP,
2877 IEEE80211_QUEUE_STOP_REASON_CSA);
2878
2879 ieee80211_bss_info_change_notify(sdata, changed);
2880
2881 cfg80211_ch_switch_notify(sdata->dev, &local->csa_chandef);
2882}
2883
2884static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
2885 struct cfg80211_csa_settings *params)
2886{
2887 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
2888 struct ieee80211_local *local = sdata->local;
2889 struct ieee80211_chanctx_conf *chanctx_conf;
2890 struct ieee80211_chanctx *chanctx;
2891 int err, num_chanctx;
2892
2893 if (!list_empty(&local->roc_list) || local->scanning)
2894 return -EBUSY;
2895
2896 if (sdata->wdev.cac_started)
2897 return -EBUSY;
2898
2899 if (cfg80211_chandef_identical(&params->chandef,
2900 &sdata->vif.bss_conf.chandef))
2901 return -EINVAL;
2902
2903 rcu_read_lock();
2904 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
2905 if (!chanctx_conf) {
2906 rcu_read_unlock();
2907 return -EBUSY;
2908 }
2909
2910 /* don't handle for multi-VIF cases */
2911 chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf);
2912 if (chanctx->refcount > 1) {
2913 rcu_read_unlock();
2914 return -EBUSY;
2915 }
2916 num_chanctx = 0;
2917 list_for_each_entry_rcu(chanctx, &local->chanctx_list, list)
2918 num_chanctx++;
2919 rcu_read_unlock();
2920
2921 if (num_chanctx > 1)
2922 return -EBUSY;
2923
2924 /* don't allow another channel switch if one is already active. */
2925 if (sdata->vif.csa_active)
2926 return -EBUSY;
2927
2928 /* only handle AP for now. */
2929 switch (sdata->vif.type) {
2930 case NL80211_IFTYPE_AP:
2931 break;
2932 default:
2933 return -EOPNOTSUPP;
2934 }
2935
2936 sdata->u.ap.next_beacon = cfg80211_beacon_dup(&params->beacon_after);
2937 if (!sdata->u.ap.next_beacon)
2938 return -ENOMEM;
2939
2940 sdata->csa_counter_offset_beacon = params->counter_offset_beacon;
2941 sdata->csa_counter_offset_presp = params->counter_offset_presp;
2942 sdata->csa_radar_required = params->radar_required;
2943
2944 if (params->block_tx)
2945 ieee80211_stop_queues_by_reason(&local->hw,
2946 IEEE80211_MAX_QUEUE_MAP,
2947 IEEE80211_QUEUE_STOP_REASON_CSA);
2948
2949 err = ieee80211_assign_beacon(sdata, &params->beacon_csa);
2950 if (err < 0)
2951 return err;
2952
2953 local->csa_chandef = params->chandef;
2954 sdata->vif.csa_active = true;
2955
2956 ieee80211_bss_info_change_notify(sdata, err);
2957 drv_channel_switch_beacon(sdata, &params->chandef);
2958
2959 return 0;
2960}
2961
2780static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, 2962static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
2781 struct ieee80211_channel *chan, bool offchan, 2963 struct ieee80211_channel *chan, bool offchan,
2782 unsigned int wait, const u8 *buf, size_t len, 2964 unsigned int wait, const u8 *buf, size_t len,
@@ -3494,4 +3676,5 @@ struct cfg80211_ops mac80211_config_ops = {
3494 .get_et_strings = ieee80211_get_et_strings, 3676 .get_et_strings = ieee80211_get_et_strings,
3495 .get_channel = ieee80211_cfg_get_channel, 3677 .get_channel = ieee80211_cfg_get_channel,
3496 .start_radar_detection = ieee80211_start_radar_detection, 3678 .start_radar_detection = ieee80211_start_radar_detection,
3679 .channel_switch = ieee80211_channel_switch,
3497}; 3680};
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index 03e8d2e3270e..3a4764b2869e 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -410,6 +410,64 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
410 return ret; 410 return ret;
411} 411}
412 412
413int ieee80211_vif_change_channel(struct ieee80211_sub_if_data *sdata,
414 const struct cfg80211_chan_def *chandef,
415 u32 *changed)
416{
417 struct ieee80211_local *local = sdata->local;
418 struct ieee80211_chanctx_conf *conf;
419 struct ieee80211_chanctx *ctx;
420 int ret;
421 u32 chanctx_changed = 0;
422
423 /* should never be called if not performing a channel switch. */
424 if (WARN_ON(!sdata->vif.csa_active))
425 return -EINVAL;
426
427 if (!cfg80211_chandef_usable(sdata->local->hw.wiphy, chandef,
428 IEEE80211_CHAN_DISABLED))
429 return -EINVAL;
430
431 mutex_lock(&local->chanctx_mtx);
432 conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
433 lockdep_is_held(&local->chanctx_mtx));
434 if (!conf) {
435 ret = -EINVAL;
436 goto out;
437 }
438
439 ctx = container_of(conf, struct ieee80211_chanctx, conf);
440 if (ctx->refcount != 1) {
441 ret = -EINVAL;
442 goto out;
443 }
444
445 if (sdata->vif.bss_conf.chandef.width != chandef->width) {
446 chanctx_changed = IEEE80211_CHANCTX_CHANGE_WIDTH;
447 *changed |= BSS_CHANGED_BANDWIDTH;
448 }
449
450 sdata->vif.bss_conf.chandef = *chandef;
451 ctx->conf.def = *chandef;
452
453 chanctx_changed |= IEEE80211_CHANCTX_CHANGE_CHANNEL;
454 drv_change_chanctx(local, ctx, chanctx_changed);
455
456 if (!local->use_chanctx) {
457 local->_oper_chandef = *chandef;
458 ieee80211_hw_config(local, 0);
459 }
460
461 ieee80211_recalc_chanctx_chantype(local, ctx);
462 ieee80211_recalc_smps_chanctx(local, ctx);
463 ieee80211_recalc_radar_chanctx(local, ctx);
464
465 ret = 0;
466 out:
467 mutex_unlock(&local->chanctx_mtx);
468 return ret;
469}
470
413int ieee80211_vif_change_bandwidth(struct ieee80211_sub_if_data *sdata, 471int ieee80211_vif_change_bandwidth(struct ieee80211_sub_if_data *sdata,
414 const struct cfg80211_chan_def *chandef, 472 const struct cfg80211_chan_def *chandef,
415 u32 *changed) 473 u32 *changed)
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c
index 44e201d60a13..19c54a44ed47 100644
--- a/net/mac80211/debugfs_sta.c
+++ b/net/mac80211/debugfs_sta.c
@@ -455,6 +455,15 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta)
455 DEBUGFS_ADD_COUNTER(tx_retry_count, tx_retry_count); 455 DEBUGFS_ADD_COUNTER(tx_retry_count, tx_retry_count);
456 DEBUGFS_ADD_COUNTER(wep_weak_iv_count, wep_weak_iv_count); 456 DEBUGFS_ADD_COUNTER(wep_weak_iv_count, wep_weak_iv_count);
457 457
458 if (sizeof(sta->driver_buffered_tids) == sizeof(u32))
459 debugfs_create_x32("driver_buffered_tids", 0400,
460 sta->debugfs.dir,
461 (u32 *)&sta->driver_buffered_tids);
462 else
463 debugfs_create_x64("driver_buffered_tids", 0400,
464 sta->debugfs.dir,
465 (u64 *)&sta->driver_buffered_tids);
466
458 drv_sta_add_debugfs(local, sdata, &sta->sta, sta->debugfs.dir); 467 drv_sta_add_debugfs(local, sdata, &sta->sta, sta->debugfs.dir);
459} 468}
460 469
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index b931c96a596f..b3ea11f3d526 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -1072,4 +1072,17 @@ static inline void drv_ipv6_addr_change(struct ieee80211_local *local,
1072} 1072}
1073#endif 1073#endif
1074 1074
1075static inline void
1076drv_channel_switch_beacon(struct ieee80211_sub_if_data *sdata,
1077 struct cfg80211_chan_def *chandef)
1078{
1079 struct ieee80211_local *local = sdata->local;
1080
1081 if (local->ops->channel_switch_beacon) {
1082 trace_drv_channel_switch_beacon(local, sdata, chandef);
1083 local->ops->channel_switch_beacon(&local->hw, &sdata->vif,
1084 chandef);
1085 }
1086}
1087
1075#endif /* __MAC80211_DRIVER_OPS */ 1088#endif /* __MAC80211_DRIVER_OPS */
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 5e6836c3aa4c..e08387cdc8fd 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -30,6 +30,7 @@
30 30
31#define IEEE80211_IBSS_MERGE_INTERVAL (30 * HZ) 31#define IEEE80211_IBSS_MERGE_INTERVAL (30 * HZ)
32#define IEEE80211_IBSS_INACTIVITY_LIMIT (60 * HZ) 32#define IEEE80211_IBSS_INACTIVITY_LIMIT (60 * HZ)
33#define IEEE80211_IBSS_RSN_INACTIVITY_LIMIT (10 * HZ)
33 34
34#define IEEE80211_IBSS_MAX_STA_ENTRIES 128 35#define IEEE80211_IBSS_MAX_STA_ENTRIES 128
35 36
@@ -740,6 +741,33 @@ static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata)
740 return active; 741 return active;
741} 742}
742 743
744static void ieee80211_ibss_sta_expire(struct ieee80211_sub_if_data *sdata)
745{
746 struct ieee80211_local *local = sdata->local;
747 struct sta_info *sta, *tmp;
748 unsigned long exp_time = IEEE80211_IBSS_INACTIVITY_LIMIT;
749 unsigned long exp_rsn_time = IEEE80211_IBSS_RSN_INACTIVITY_LIMIT;
750
751 mutex_lock(&local->sta_mtx);
752
753 list_for_each_entry_safe(sta, tmp, &local->sta_list, list) {
754 if (sdata != sta->sdata)
755 continue;
756
757 if (time_after(jiffies, sta->last_rx + exp_time) ||
758 (time_after(jiffies, sta->last_rx + exp_rsn_time) &&
759 sta->sta_state != IEEE80211_STA_AUTHORIZED)) {
760 sta_dbg(sta->sdata, "expiring inactive %sSTA %pM\n",
761 sta->sta_state != IEEE80211_STA_AUTHORIZED ?
762 "not authorized " : "", sta->sta.addr);
763
764 WARN_ON(__sta_info_destroy(sta));
765 }
766 }
767
768 mutex_unlock(&local->sta_mtx);
769}
770
743/* 771/*
744 * This function is called with state == IEEE80211_IBSS_MLME_JOINED 772 * This function is called with state == IEEE80211_IBSS_MLME_JOINED
745 */ 773 */
@@ -754,7 +782,7 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata)
754 mod_timer(&ifibss->timer, 782 mod_timer(&ifibss->timer,
755 round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL)); 783 round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL));
756 784
757 ieee80211_sta_expire(sdata, IEEE80211_IBSS_INACTIVITY_LIMIT); 785 ieee80211_ibss_sta_expire(sdata);
758 786
759 if (time_before(jiffies, ifibss->last_scan_completed + 787 if (time_before(jiffies, ifibss->last_scan_completed +
760 IEEE80211_IBSS_MERGE_INTERVAL)) 788 IEEE80211_IBSS_MERGE_INTERVAL))
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 3d32df1fbc6d..e94c84050e9c 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -259,6 +259,8 @@ struct ieee80211_if_ap {
259 struct beacon_data __rcu *beacon; 259 struct beacon_data __rcu *beacon;
260 struct probe_resp __rcu *probe_resp; 260 struct probe_resp __rcu *probe_resp;
261 261
262 /* to be used after channel switch. */
263 struct cfg80211_beacon_data *next_beacon;
262 struct list_head vlans; 264 struct list_head vlans;
263 265
264 struct ps_data ps; 266 struct ps_data ps;
@@ -716,6 +718,11 @@ struct ieee80211_sub_if_data {
716 718
717 struct ieee80211_tx_queue_params tx_conf[IEEE80211_NUM_ACS]; 719 struct ieee80211_tx_queue_params tx_conf[IEEE80211_NUM_ACS];
718 720
721 struct work_struct csa_finalize_work;
722 int csa_counter_offset_beacon;
723 int csa_counter_offset_presp;
724 bool csa_radar_required;
725
719 /* used to reconfigure hardware SM PS */ 726 /* used to reconfigure hardware SM PS */
720 struct work_struct recalc_smps; 727 struct work_struct recalc_smps;
721 728
@@ -1094,7 +1101,6 @@ struct ieee80211_local {
1094 u32 dot11TransmittedFrameCount; 1101 u32 dot11TransmittedFrameCount;
1095 1102
1096#ifdef CONFIG_MAC80211_LEDS 1103#ifdef CONFIG_MAC80211_LEDS
1097 int tx_led_counter, rx_led_counter;
1098 struct led_trigger *tx_led, *rx_led, *assoc_led, *radio_led; 1104 struct led_trigger *tx_led, *rx_led, *assoc_led, *radio_led;
1099 struct tpt_led_trigger *tpt_led_trigger; 1105 struct tpt_led_trigger *tpt_led_trigger;
1100 char tx_led_name[32], rx_led_name[32], 1106 char tx_led_name[32], rx_led_name[32],
@@ -1373,6 +1379,9 @@ void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc, bool free);
1373void ieee80211_sw_roc_work(struct work_struct *work); 1379void ieee80211_sw_roc_work(struct work_struct *work);
1374void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc); 1380void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc);
1375 1381
1382/* channel switch handling */
1383void ieee80211_csa_finalize_work(struct work_struct *work);
1384
1376/* interface handling */ 1385/* interface handling */
1377int ieee80211_iface_init(void); 1386int ieee80211_iface_init(void);
1378void ieee80211_iface_exit(void); 1387void ieee80211_iface_exit(void);
@@ -1394,6 +1403,8 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local);
1394 1403
1395bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata); 1404bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata);
1396void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata); 1405void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata);
1406int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
1407 struct cfg80211_beacon_data *params);
1397 1408
1398static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata) 1409static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata)
1399{ 1410{
@@ -1655,6 +1666,11 @@ int __must_check
1655ieee80211_vif_change_bandwidth(struct ieee80211_sub_if_data *sdata, 1666ieee80211_vif_change_bandwidth(struct ieee80211_sub_if_data *sdata,
1656 const struct cfg80211_chan_def *chandef, 1667 const struct cfg80211_chan_def *chandef,
1657 u32 *changed); 1668 u32 *changed);
1669/* NOTE: only use ieee80211_vif_change_channel() for channel switch */
1670int __must_check
1671ieee80211_vif_change_channel(struct ieee80211_sub_if_data *sdata,
1672 const struct cfg80211_chan_def *chandef,
1673 u32 *changed);
1658void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata); 1674void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata);
1659void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata); 1675void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata);
1660void ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata, 1676void ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 4c41c11958c8..7ca534bf4cea 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -274,6 +274,12 @@ static int ieee80211_check_concurrent_iface(struct ieee80211_sub_if_data *sdata,
274 if (iftype == NL80211_IFTYPE_ADHOC && 274 if (iftype == NL80211_IFTYPE_ADHOC &&
275 nsdata->vif.type == NL80211_IFTYPE_ADHOC) 275 nsdata->vif.type == NL80211_IFTYPE_ADHOC)
276 return -EBUSY; 276 return -EBUSY;
277 /*
278 * will not add another interface while any channel
279 * switch is active.
280 */
281 if (nsdata->vif.csa_active)
282 return -EBUSY;
277 283
278 /* 284 /*
279 * The remaining checks are only performed for interfaces 285 * The remaining checks are only performed for interfaces
@@ -804,6 +810,8 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
804 cancel_work_sync(&local->dynamic_ps_enable_work); 810 cancel_work_sync(&local->dynamic_ps_enable_work);
805 811
806 cancel_work_sync(&sdata->recalc_smps); 812 cancel_work_sync(&sdata->recalc_smps);
813 sdata->vif.csa_active = false;
814 cancel_work_sync(&sdata->csa_finalize_work);
807 815
808 cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); 816 cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);
809 817
@@ -1267,6 +1275,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
1267 skb_queue_head_init(&sdata->skb_queue); 1275 skb_queue_head_init(&sdata->skb_queue);
1268 INIT_WORK(&sdata->work, ieee80211_iface_work); 1276 INIT_WORK(&sdata->work, ieee80211_iface_work);
1269 INIT_WORK(&sdata->recalc_smps, ieee80211_recalc_smps_work); 1277 INIT_WORK(&sdata->recalc_smps, ieee80211_recalc_smps_work);
1278 INIT_WORK(&sdata->csa_finalize_work, ieee80211_csa_finalize_work);
1270 1279
1271 switch (type) { 1280 switch (type) {
1272 case NL80211_IFTYPE_P2P_GO: 1281 case NL80211_IFTYPE_P2P_GO:
diff --git a/net/mac80211/led.c b/net/mac80211/led.c
index bcffa6903129..e2b836446af3 100644
--- a/net/mac80211/led.c
+++ b/net/mac80211/led.c
@@ -12,27 +12,22 @@
12#include <linux/export.h> 12#include <linux/export.h>
13#include "led.h" 13#include "led.h"
14 14
15#define MAC80211_BLINK_DELAY 50 /* ms */
16
15void ieee80211_led_rx(struct ieee80211_local *local) 17void ieee80211_led_rx(struct ieee80211_local *local)
16{ 18{
19 unsigned long led_delay = MAC80211_BLINK_DELAY;
17 if (unlikely(!local->rx_led)) 20 if (unlikely(!local->rx_led))
18 return; 21 return;
19 if (local->rx_led_counter++ % 2 == 0) 22 led_trigger_blink_oneshot(local->rx_led, &led_delay, &led_delay, 0);
20 led_trigger_event(local->rx_led, LED_OFF);
21 else
22 led_trigger_event(local->rx_led, LED_FULL);
23} 23}
24 24
25/* q is 1 if a packet was enqueued, 0 if it has been transmitted */ 25void ieee80211_led_tx(struct ieee80211_local *local)
26void ieee80211_led_tx(struct ieee80211_local *local, int q)
27{ 26{
27 unsigned long led_delay = MAC80211_BLINK_DELAY;
28 if (unlikely(!local->tx_led)) 28 if (unlikely(!local->tx_led))
29 return; 29 return;
30 /* not sure how this is supposed to work ... */ 30 led_trigger_blink_oneshot(local->tx_led, &led_delay, &led_delay, 0);
31 local->tx_led_counter += 2*q-1;
32 if (local->tx_led_counter % 2 == 0)
33 led_trigger_event(local->tx_led, LED_OFF);
34 else
35 led_trigger_event(local->tx_led, LED_FULL);
36} 31}
37 32
38void ieee80211_led_assoc(struct ieee80211_local *local, bool associated) 33void ieee80211_led_assoc(struct ieee80211_local *local, bool associated)
diff --git a/net/mac80211/led.h b/net/mac80211/led.h
index e0275d9befa8..89f4344f13b9 100644
--- a/net/mac80211/led.h
+++ b/net/mac80211/led.h
@@ -13,7 +13,7 @@
13 13
14#ifdef CONFIG_MAC80211_LEDS 14#ifdef CONFIG_MAC80211_LEDS
15void ieee80211_led_rx(struct ieee80211_local *local); 15void ieee80211_led_rx(struct ieee80211_local *local);
16void ieee80211_led_tx(struct ieee80211_local *local, int q); 16void ieee80211_led_tx(struct ieee80211_local *local);
17void ieee80211_led_assoc(struct ieee80211_local *local, 17void ieee80211_led_assoc(struct ieee80211_local *local,
18 bool associated); 18 bool associated);
19void ieee80211_led_radio(struct ieee80211_local *local, 19void ieee80211_led_radio(struct ieee80211_local *local,
@@ -27,7 +27,7 @@ void ieee80211_mod_tpt_led_trig(struct ieee80211_local *local,
27static inline void ieee80211_led_rx(struct ieee80211_local *local) 27static inline void ieee80211_led_rx(struct ieee80211_local *local)
28{ 28{
29} 29}
30static inline void ieee80211_led_tx(struct ieee80211_local *local, int q) 30static inline void ieee80211_led_tx(struct ieee80211_local *local)
31{ 31{
32} 32}
33static inline void ieee80211_led_assoc(struct ieee80211_local *local, 33static inline void ieee80211_led_assoc(struct ieee80211_local *local,
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 6ad4c14385ef..368837fe3b80 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -235,7 +235,8 @@ static int ieee80211_tx_radiotap_len(struct ieee80211_tx_info *info)
235 235
236 /* IEEE80211_RADIOTAP_RATE rate */ 236 /* IEEE80211_RADIOTAP_RATE rate */
237 if (info->status.rates[0].idx >= 0 && 237 if (info->status.rates[0].idx >= 0 &&
238 !(info->status.rates[0].flags & IEEE80211_TX_RC_MCS)) 238 !(info->status.rates[0].flags & (IEEE80211_TX_RC_MCS |
239 IEEE80211_TX_RC_VHT_MCS)))
239 len += 2; 240 len += 2;
240 241
241 /* IEEE80211_RADIOTAP_TX_FLAGS */ 242 /* IEEE80211_RADIOTAP_TX_FLAGS */
@@ -244,16 +245,21 @@ static int ieee80211_tx_radiotap_len(struct ieee80211_tx_info *info)
244 /* IEEE80211_RADIOTAP_DATA_RETRIES */ 245 /* IEEE80211_RADIOTAP_DATA_RETRIES */
245 len += 1; 246 len += 1;
246 247
247 /* IEEE80211_TX_RC_MCS */ 248 /* IEEE80211_RADIOTAP_MCS
248 if (info->status.rates[0].idx >= 0 && 249 * IEEE80211_RADIOTAP_VHT */
249 info->status.rates[0].flags & IEEE80211_TX_RC_MCS) 250 if (info->status.rates[0].idx >= 0) {
250 len += 3; 251 if (info->status.rates[0].flags & IEEE80211_TX_RC_MCS)
252 len += 3;
253 else if (info->status.rates[0].flags & IEEE80211_TX_RC_VHT_MCS)
254 len = ALIGN(len, 2) + 12;
255 }
251 256
252 return len; 257 return len;
253} 258}
254 259
255static void 260static void
256ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band *sband, 261ieee80211_add_tx_radiotap_header(struct ieee80211_local *local,
262 struct ieee80211_supported_band *sband,
257 struct sk_buff *skb, int retry_count, 263 struct sk_buff *skb, int retry_count,
258 int rtap_len, int shift) 264 int rtap_len, int shift)
259{ 265{
@@ -280,7 +286,8 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band *sband,
280 286
281 /* IEEE80211_RADIOTAP_RATE */ 287 /* IEEE80211_RADIOTAP_RATE */
282 if (info->status.rates[0].idx >= 0 && 288 if (info->status.rates[0].idx >= 0 &&
283 !(info->status.rates[0].flags & IEEE80211_TX_RC_MCS)) { 289 !(info->status.rates[0].flags & (IEEE80211_TX_RC_MCS |
290 IEEE80211_TX_RC_VHT_MCS))) {
284 u16 rate; 291 u16 rate;
285 292
286 rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE); 293 rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE);
@@ -310,9 +317,12 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band *sband,
310 *pos = retry_count; 317 *pos = retry_count;
311 pos++; 318 pos++;
312 319
313 /* IEEE80211_TX_RC_MCS */ 320 if (info->status.rates[0].idx < 0)
314 if (info->status.rates[0].idx >= 0 && 321 return;
315 info->status.rates[0].flags & IEEE80211_TX_RC_MCS) { 322
323 /* IEEE80211_RADIOTAP_MCS
324 * IEEE80211_RADIOTAP_VHT */
325 if (info->status.rates[0].flags & IEEE80211_TX_RC_MCS) {
316 rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_MCS); 326 rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_MCS);
317 pos[0] = IEEE80211_RADIOTAP_MCS_HAVE_MCS | 327 pos[0] = IEEE80211_RADIOTAP_MCS_HAVE_MCS |
318 IEEE80211_RADIOTAP_MCS_HAVE_GI | 328 IEEE80211_RADIOTAP_MCS_HAVE_GI |
@@ -325,8 +335,48 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band *sband,
325 pos[1] |= IEEE80211_RADIOTAP_MCS_FMT_GF; 335 pos[1] |= IEEE80211_RADIOTAP_MCS_FMT_GF;
326 pos[2] = info->status.rates[0].idx; 336 pos[2] = info->status.rates[0].idx;
327 pos += 3; 337 pos += 3;
328 } 338 } else if (info->status.rates[0].flags & IEEE80211_TX_RC_VHT_MCS) {
339 u16 known = local->hw.radiotap_vht_details &
340 (IEEE80211_RADIOTAP_VHT_KNOWN_GI |
341 IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH);
342
343 rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_VHT);
344
345 /* required alignment from rthdr */
346 pos = (u8 *)rthdr + ALIGN(pos - (u8 *)rthdr, 2);
329 347
348 /* u16 known - IEEE80211_RADIOTAP_VHT_KNOWN_* */
349 put_unaligned_le16(known, pos);
350 pos += 2;
351
352 /* u8 flags - IEEE80211_RADIOTAP_VHT_FLAG_* */
353 if (info->status.rates[0].flags & IEEE80211_TX_RC_SHORT_GI)
354 *pos |= IEEE80211_RADIOTAP_VHT_FLAG_SGI;
355 pos++;
356
357 /* u8 bandwidth */
358 if (info->status.rates[0].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
359 *pos = 1;
360 else if (info->status.rates[0].flags & IEEE80211_TX_RC_80_MHZ_WIDTH)
361 *pos = 4;
362 else if (info->status.rates[0].flags & IEEE80211_TX_RC_160_MHZ_WIDTH)
363 *pos = 11;
364 else /* IEEE80211_TX_RC_{20_MHZ_WIDTH,FIXME:DUP_DATA} */
365 *pos = 0;
366 pos++;
367
368 /* u8 mcs_nss[4] */
369 *pos = (ieee80211_rate_get_vht_mcs(&info->status.rates[0]) << 4) |
370 ieee80211_rate_get_vht_nss(&info->status.rates[0]);
371 pos += 4;
372
373 /* u8 coding */
374 pos++;
375 /* u8 group_id */
376 pos++;
377 /* u16 partial_aid */
378 pos += 2;
379 }
330} 380}
331 381
332static void ieee80211_report_used_skb(struct ieee80211_local *local, 382static void ieee80211_report_used_skb(struct ieee80211_local *local,
@@ -564,7 +614,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
564 614
565 rcu_read_unlock(); 615 rcu_read_unlock();
566 616
567 ieee80211_led_tx(local, 0); 617 ieee80211_led_tx(local);
568 618
569 /* SNMP counters 619 /* SNMP counters
570 * Fragments are passed to low-level drivers as separate skbs, so these 620 * Fragments are passed to low-level drivers as separate skbs, so these
@@ -631,8 +681,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
631 dev_kfree_skb(skb); 681 dev_kfree_skb(skb);
632 return; 682 return;
633 } 683 }
634 ieee80211_add_tx_radiotap_header(sband, skb, retry_count, rtap_len, 684 ieee80211_add_tx_radiotap_header(local, sband, skb, retry_count,
635 shift); 685 rtap_len, shift);
636 686
637 /* XXX: is this sufficient for BPF? */ 687 /* XXX: is this sufficient for BPF? */
638 skb_set_mac_header(skb, 0); 688 skb_set_mac_header(skb, 0);
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index c215fafd7a2f..1aba645882bd 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -1906,6 +1906,32 @@ TRACE_EVENT(api_radar_detected,
1906 ) 1906 )
1907); 1907);
1908 1908
1909TRACE_EVENT(drv_channel_switch_beacon,
1910 TP_PROTO(struct ieee80211_local *local,
1911 struct ieee80211_sub_if_data *sdata,
1912 struct cfg80211_chan_def *chandef),
1913
1914 TP_ARGS(local, sdata, chandef),
1915
1916 TP_STRUCT__entry(
1917 LOCAL_ENTRY
1918 VIF_ENTRY
1919 CHANDEF_ENTRY
1920 ),
1921
1922 TP_fast_assign(
1923 LOCAL_ASSIGN;
1924 VIF_ASSIGN;
1925 CHANDEF_ASSIGN(chandef);
1926 ),
1927
1928 TP_printk(
1929 LOCAL_PR_FMT VIF_PR_FMT " channel switch to " CHANDEF_PR_FMT,
1930 LOCAL_PR_ARG, VIF_PR_ARG, CHANDEF_PR_ARG
1931 )
1932);
1933
1934
1909#ifdef CONFIG_MAC80211_MESSAGE_TRACING 1935#ifdef CONFIG_MAC80211_MESSAGE_TRACING
1910#undef TRACE_SYSTEM 1936#undef TRACE_SYSTEM
1911#define TRACE_SYSTEM mac80211_msg 1937#define TRACE_SYSTEM mac80211_msg
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index be4d3caf4879..0e42322aa6b1 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1300,7 +1300,6 @@ static bool __ieee80211_tx(struct ieee80211_local *local,
1300 txpending); 1300 txpending);
1301 1301
1302 ieee80211_tpt_led_trig_tx(local, fc, led_len); 1302 ieee80211_tpt_led_trig_tx(local, fc, led_len);
1303 ieee80211_led_tx(local, 1);
1304 1303
1305 WARN_ON_ONCE(!skb_queue_empty(skbs)); 1304 WARN_ON_ONCE(!skb_queue_empty(skbs));
1306 1305
@@ -2339,6 +2338,81 @@ static int ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
2339 return 0; 2338 return 0;
2340} 2339}
2341 2340
2341void ieee80211_csa_finish(struct ieee80211_vif *vif)
2342{
2343 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
2344
2345 ieee80211_queue_work(&sdata->local->hw,
2346 &sdata->csa_finalize_work);
2347}
2348EXPORT_SYMBOL(ieee80211_csa_finish);
2349
2350static void ieee80211_update_csa(struct ieee80211_sub_if_data *sdata,
2351 struct beacon_data *beacon)
2352{
2353 struct probe_resp *resp;
2354 int counter_offset_beacon = sdata->csa_counter_offset_beacon;
2355 int counter_offset_presp = sdata->csa_counter_offset_presp;
2356
2357 /* warn if the driver did not check for/react to csa completeness */
2358 if (WARN_ON(((u8 *)beacon->tail)[counter_offset_beacon] == 0))
2359 return;
2360
2361 ((u8 *)beacon->tail)[counter_offset_beacon]--;
2362
2363 if (sdata->vif.type == NL80211_IFTYPE_AP &&
2364 counter_offset_presp) {
2365 rcu_read_lock();
2366 resp = rcu_dereference(sdata->u.ap.probe_resp);
2367
2368 /* if nl80211 accepted the offset, this should not happen. */
2369 if (WARN_ON(!resp)) {
2370 rcu_read_unlock();
2371 return;
2372 }
2373 resp->data[counter_offset_presp]--;
2374 rcu_read_unlock();
2375 }
2376}
2377
2378bool ieee80211_csa_is_complete(struct ieee80211_vif *vif)
2379{
2380 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
2381 struct beacon_data *beacon = NULL;
2382 u8 *beacon_data;
2383 size_t beacon_data_len;
2384 int counter_beacon = sdata->csa_counter_offset_beacon;
2385 int ret = false;
2386
2387 if (!ieee80211_sdata_running(sdata))
2388 return false;
2389
2390 rcu_read_lock();
2391 if (vif->type == NL80211_IFTYPE_AP) {
2392 struct ieee80211_if_ap *ap = &sdata->u.ap;
2393
2394 beacon = rcu_dereference(ap->beacon);
2395 if (WARN_ON(!beacon || !beacon->tail))
2396 goto out;
2397 beacon_data = beacon->tail;
2398 beacon_data_len = beacon->tail_len;
2399 } else {
2400 WARN_ON(1);
2401 goto out;
2402 }
2403
2404 if (WARN_ON(counter_beacon > beacon_data_len))
2405 goto out;
2406
2407 if (beacon_data[counter_beacon] == 0)
2408 ret = true;
2409 out:
2410 rcu_read_unlock();
2411
2412 return ret;
2413}
2414EXPORT_SYMBOL(ieee80211_csa_is_complete);
2415
2342struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, 2416struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
2343 struct ieee80211_vif *vif, 2417 struct ieee80211_vif *vif,
2344 u16 *tim_offset, u16 *tim_length) 2418 u16 *tim_offset, u16 *tim_length)
@@ -2369,6 +2443,9 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
2369 struct beacon_data *beacon = rcu_dereference(ap->beacon); 2443 struct beacon_data *beacon = rcu_dereference(ap->beacon);
2370 2444
2371 if (beacon) { 2445 if (beacon) {
2446 if (sdata->vif.csa_active)
2447 ieee80211_update_csa(sdata, beacon);
2448
2372 /* 2449 /*
2373 * headroom, head length, 2450 * headroom, head length,
2374 * tail length and maximum TIM length 2451 * tail length and maximum TIM length