diff options
author | John W. Linville <linville@tuxdriver.com> | 2014-02-20 15:02:02 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2014-02-20 15:02:02 -0500 |
commit | 88daf80dcca19ff995cc263592426f734a9702f3 (patch) | |
tree | 7a52e25df74e52d00c3821032e719244e8a5526f /net/mac80211 | |
parent | 010d3c3989706d800ae72253773fa6537cc9f74c (diff) | |
parent | 35582ad9d342025653aaf28ed321bf5352488d7f (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/agg-tx.c | 2 | ||||
-rw-r--r-- | net/mac80211/cfg.c | 198 | ||||
-rw-r--r-- | net/mac80211/cfg.h | 2 | ||||
-rw-r--r-- | net/mac80211/chan.c | 2 | ||||
-rw-r--r-- | net/mac80211/debugfs_sta.c | 2 | ||||
-rw-r--r-- | net/mac80211/ht.c | 2 | ||||
-rw-r--r-- | net/mac80211/ibss.c | 28 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 14 | ||||
-rw-r--r-- | net/mac80211/iface.c | 2 | ||||
-rw-r--r-- | net/mac80211/main.c | 9 | ||||
-rw-r--r-- | net/mac80211/mesh.c | 96 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 41 | ||||
-rw-r--r-- | net/mac80211/rate.c | 46 | ||||
-rw-r--r-- | net/mac80211/rate.h | 2 | ||||
-rw-r--r-- | net/mac80211/rc80211_minstrel.c | 2 | ||||
-rw-r--r-- | net/mac80211/rc80211_minstrel.h | 2 | ||||
-rw-r--r-- | net/mac80211/rc80211_minstrel_ht.c | 7 | ||||
-rw-r--r-- | net/mac80211/rc80211_pid_algo.c | 2 | ||||
-rw-r--r-- | net/mac80211/rx.c | 101 | ||||
-rw-r--r-- | net/mac80211/sta_info.h | 2 | ||||
-rw-r--r-- | net/mac80211/status.c | 3 | ||||
-rw-r--r-- | net/mac80211/tx.c | 33 | ||||
-rw-r--r-- | net/mac80211/util.c | 42 | ||||
-rw-r--r-- | net/mac80211/vht.c | 26 | ||||
-rw-r--r-- | net/mac80211/wpa.c | 9 |
25 files changed, 368 insertions, 307 deletions
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 13b7683de5a4..ce9633a3cfb0 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -107,7 +107,7 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, | |||
107 | mgmt->u.action.u.addba_req.start_seq_num = | 107 | mgmt->u.action.u.addba_req.start_seq_num = |
108 | cpu_to_le16(start_seq_num << 4); | 108 | cpu_to_le16(start_seq_num << 4); |
109 | 109 | ||
110 | ieee80211_tx_skb_tid(sdata, skb, tid); | 110 | ieee80211_tx_skb(sdata, skb); |
111 | } | 111 | } |
112 | 112 | ||
113 | void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn) | 113 | void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn) |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 453e974287d1..363d19b5d5c8 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -451,11 +451,11 @@ void sta_set_rate_info_rx(struct sta_info *sta, struct rate_info *rinfo) | |||
451 | rinfo->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; | 451 | rinfo->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; |
452 | if (sta->last_rx_rate_flag & RX_FLAG_SHORT_GI) | 452 | if (sta->last_rx_rate_flag & RX_FLAG_SHORT_GI) |
453 | rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI; | 453 | rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI; |
454 | if (sta->last_rx_rate_flag & RX_FLAG_80MHZ) | 454 | if (sta->last_rx_rate_vht_flag & RX_VHT_FLAG_80MHZ) |
455 | rinfo->flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; | 455 | rinfo->flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; |
456 | if (sta->last_rx_rate_flag & RX_FLAG_80P80MHZ) | 456 | if (sta->last_rx_rate_vht_flag & RX_VHT_FLAG_80P80MHZ) |
457 | rinfo->flags |= RATE_INFO_FLAGS_80P80_MHZ_WIDTH; | 457 | rinfo->flags |= RATE_INFO_FLAGS_80P80_MHZ_WIDTH; |
458 | if (sta->last_rx_rate_flag & RX_FLAG_160MHZ) | 458 | if (sta->last_rx_rate_vht_flag & RX_VHT_FLAG_160MHZ) |
459 | rinfo->flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH; | 459 | rinfo->flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH; |
460 | } | 460 | } |
461 | 461 | ||
@@ -970,9 +970,9 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
970 | /* TODO: make hostapd tell us what it wants */ | 970 | /* TODO: make hostapd tell us what it wants */ |
971 | sdata->smps_mode = IEEE80211_SMPS_OFF; | 971 | sdata->smps_mode = IEEE80211_SMPS_OFF; |
972 | sdata->needed_rx_chains = sdata->local->rx_chains; | 972 | sdata->needed_rx_chains = sdata->local->rx_chains; |
973 | sdata->radar_required = params->radar_required; | ||
974 | 973 | ||
975 | mutex_lock(&local->mtx); | 974 | mutex_lock(&local->mtx); |
975 | sdata->radar_required = params->radar_required; | ||
976 | err = ieee80211_vif_use_channel(sdata, ¶ms->chandef, | 976 | err = ieee80211_vif_use_channel(sdata, ¶ms->chandef, |
977 | IEEE80211_CHANCTX_SHARED); | 977 | IEEE80211_CHANCTX_SHARED); |
978 | mutex_unlock(&local->mtx); | 978 | mutex_unlock(&local->mtx); |
@@ -1056,6 +1056,7 @@ static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev, | |||
1056 | int err; | 1056 | int err; |
1057 | 1057 | ||
1058 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1058 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1059 | sdata_assert_lock(sdata); | ||
1059 | 1060 | ||
1060 | /* don't allow changing the beacon while CSA is in place - offset | 1061 | /* don't allow changing the beacon while CSA is in place - offset |
1061 | * of channel switch counter may change | 1062 | * of channel switch counter may change |
@@ -1083,6 +1084,8 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) | |||
1083 | struct probe_resp *old_probe_resp; | 1084 | struct probe_resp *old_probe_resp; |
1084 | struct cfg80211_chan_def chandef; | 1085 | struct cfg80211_chan_def chandef; |
1085 | 1086 | ||
1087 | sdata_assert_lock(sdata); | ||
1088 | |||
1086 | old_beacon = sdata_dereference(sdata->u.ap.beacon, sdata); | 1089 | old_beacon = sdata_dereference(sdata->u.ap.beacon, sdata); |
1087 | if (!old_beacon) | 1090 | if (!old_beacon) |
1088 | return -ENOENT; | 1091 | return -ENOENT; |
@@ -1343,6 +1346,18 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
1343 | ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, | 1346 | ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, |
1344 | params->vht_capa, sta); | 1347 | params->vht_capa, sta); |
1345 | 1348 | ||
1349 | if (params->opmode_notif_used) { | ||
1350 | enum ieee80211_band band = | ||
1351 | ieee80211_get_sdata_band(sdata); | ||
1352 | |||
1353 | /* returned value is only needed for rc update, but the | ||
1354 | * rc isn't initialized here yet, so ignore it | ||
1355 | */ | ||
1356 | __ieee80211_vht_handle_opmode(sdata, sta, | ||
1357 | params->opmode_notif, | ||
1358 | band, false); | ||
1359 | } | ||
1360 | |||
1346 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | 1361 | if (ieee80211_vif_is_mesh(&sdata->vif)) { |
1347 | #ifdef CONFIG_MAC80211_MESH | 1362 | #ifdef CONFIG_MAC80211_MESH |
1348 | u32 changed = 0; | 1363 | u32 changed = 0; |
@@ -2630,6 +2645,18 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
2630 | if (!roc) | 2645 | if (!roc) |
2631 | return -ENOMEM; | 2646 | return -ENOMEM; |
2632 | 2647 | ||
2648 | /* | ||
2649 | * If the duration is zero, then the driver | ||
2650 | * wouldn't actually do anything. Set it to | ||
2651 | * 10 for now. | ||
2652 | * | ||
2653 | * TODO: cancel the off-channel operation | ||
2654 | * when we get the SKB's TX status and | ||
2655 | * the wait time was zero before. | ||
2656 | */ | ||
2657 | if (!duration) | ||
2658 | duration = 10; | ||
2659 | |||
2633 | roc->chan = channel; | 2660 | roc->chan = channel; |
2634 | roc->duration = duration; | 2661 | roc->duration = duration; |
2635 | roc->req_duration = duration; | 2662 | roc->req_duration = duration; |
@@ -2671,18 +2698,6 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
2671 | 2698 | ||
2672 | /* otherwise actually kick it off here (for error handling) */ | 2699 | /* otherwise actually kick it off here (for error handling) */ |
2673 | 2700 | ||
2674 | /* | ||
2675 | * If the duration is zero, then the driver | ||
2676 | * wouldn't actually do anything. Set it to | ||
2677 | * 10 for now. | ||
2678 | * | ||
2679 | * TODO: cancel the off-channel operation | ||
2680 | * when we get the SKB's TX status and | ||
2681 | * the wait time was zero before. | ||
2682 | */ | ||
2683 | if (!duration) | ||
2684 | duration = 10; | ||
2685 | |||
2686 | ret = drv_remain_on_channel(local, sdata, channel, duration, type); | 2701 | ret = drv_remain_on_channel(local, sdata, channel, duration, type); |
2687 | if (ret) { | 2702 | if (ret) { |
2688 | kfree(roc); | 2703 | kfree(roc); |
@@ -2990,69 +3005,88 @@ cfg80211_beacon_dup(struct cfg80211_beacon_data *beacon) | |||
2990 | return new_beacon; | 3005 | return new_beacon; |
2991 | } | 3006 | } |
2992 | 3007 | ||
2993 | void ieee80211_csa_finalize_work(struct work_struct *work) | 3008 | void ieee80211_csa_finish(struct ieee80211_vif *vif) |
3009 | { | ||
3010 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
3011 | |||
3012 | ieee80211_queue_work(&sdata->local->hw, | ||
3013 | &sdata->csa_finalize_work); | ||
3014 | } | ||
3015 | EXPORT_SYMBOL(ieee80211_csa_finish); | ||
3016 | |||
3017 | static void ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata) | ||
2994 | { | 3018 | { |
2995 | struct ieee80211_sub_if_data *sdata = | ||
2996 | container_of(work, struct ieee80211_sub_if_data, | ||
2997 | csa_finalize_work); | ||
2998 | struct ieee80211_local *local = sdata->local; | 3019 | struct ieee80211_local *local = sdata->local; |
2999 | int err, changed = 0; | 3020 | int err, changed = 0; |
3000 | 3021 | ||
3001 | sdata_lock(sdata); | 3022 | sdata_assert_lock(sdata); |
3002 | /* AP might have been stopped while waiting for the lock. */ | ||
3003 | if (!sdata->vif.csa_active) | ||
3004 | goto unlock; | ||
3005 | |||
3006 | if (!ieee80211_sdata_running(sdata)) | ||
3007 | goto unlock; | ||
3008 | 3023 | ||
3009 | sdata->radar_required = sdata->csa_radar_required; | ||
3010 | mutex_lock(&local->mtx); | 3024 | mutex_lock(&local->mtx); |
3025 | sdata->radar_required = sdata->csa_radar_required; | ||
3011 | err = ieee80211_vif_change_channel(sdata, &changed); | 3026 | err = ieee80211_vif_change_channel(sdata, &changed); |
3012 | mutex_unlock(&local->mtx); | 3027 | mutex_unlock(&local->mtx); |
3013 | if (WARN_ON(err < 0)) | 3028 | if (WARN_ON(err < 0)) |
3014 | goto unlock; | 3029 | return; |
3015 | 3030 | ||
3016 | if (!local->use_chanctx) { | 3031 | if (!local->use_chanctx) { |
3017 | local->_oper_chandef = sdata->csa_chandef; | 3032 | local->_oper_chandef = sdata->csa_chandef; |
3018 | ieee80211_hw_config(local, 0); | 3033 | ieee80211_hw_config(local, 0); |
3019 | } | 3034 | } |
3020 | 3035 | ||
3021 | ieee80211_bss_info_change_notify(sdata, changed); | ||
3022 | |||
3023 | sdata->vif.csa_active = false; | 3036 | sdata->vif.csa_active = false; |
3024 | switch (sdata->vif.type) { | 3037 | switch (sdata->vif.type) { |
3025 | case NL80211_IFTYPE_AP: | 3038 | case NL80211_IFTYPE_AP: |
3026 | err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon); | 3039 | err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon); |
3027 | if (err < 0) | ||
3028 | goto unlock; | ||
3029 | |||
3030 | changed |= err; | ||
3031 | kfree(sdata->u.ap.next_beacon); | 3040 | kfree(sdata->u.ap.next_beacon); |
3032 | sdata->u.ap.next_beacon = NULL; | 3041 | sdata->u.ap.next_beacon = NULL; |
3033 | 3042 | ||
3034 | ieee80211_bss_info_change_notify(sdata, err); | 3043 | if (err < 0) |
3044 | return; | ||
3045 | changed |= err; | ||
3035 | break; | 3046 | break; |
3036 | case NL80211_IFTYPE_ADHOC: | 3047 | case NL80211_IFTYPE_ADHOC: |
3037 | ieee80211_ibss_finish_csa(sdata); | 3048 | err = ieee80211_ibss_finish_csa(sdata); |
3049 | if (err < 0) | ||
3050 | return; | ||
3051 | changed |= err; | ||
3038 | break; | 3052 | break; |
3039 | #ifdef CONFIG_MAC80211_MESH | 3053 | #ifdef CONFIG_MAC80211_MESH |
3040 | case NL80211_IFTYPE_MESH_POINT: | 3054 | case NL80211_IFTYPE_MESH_POINT: |
3041 | err = ieee80211_mesh_finish_csa(sdata); | 3055 | err = ieee80211_mesh_finish_csa(sdata); |
3042 | if (err < 0) | 3056 | if (err < 0) |
3043 | goto unlock; | 3057 | return; |
3058 | changed |= err; | ||
3044 | break; | 3059 | break; |
3045 | #endif | 3060 | #endif |
3046 | default: | 3061 | default: |
3047 | WARN_ON(1); | 3062 | WARN_ON(1); |
3048 | goto unlock; | 3063 | return; |
3049 | } | 3064 | } |
3050 | 3065 | ||
3066 | ieee80211_bss_info_change_notify(sdata, changed); | ||
3067 | |||
3051 | ieee80211_wake_queues_by_reason(&sdata->local->hw, | 3068 | ieee80211_wake_queues_by_reason(&sdata->local->hw, |
3052 | IEEE80211_MAX_QUEUE_MAP, | 3069 | IEEE80211_MAX_QUEUE_MAP, |
3053 | IEEE80211_QUEUE_STOP_REASON_CSA); | 3070 | IEEE80211_QUEUE_STOP_REASON_CSA); |
3054 | 3071 | ||
3055 | cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef); | 3072 | cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef); |
3073 | } | ||
3074 | |||
3075 | void ieee80211_csa_finalize_work(struct work_struct *work) | ||
3076 | { | ||
3077 | struct ieee80211_sub_if_data *sdata = | ||
3078 | container_of(work, struct ieee80211_sub_if_data, | ||
3079 | csa_finalize_work); | ||
3080 | |||
3081 | sdata_lock(sdata); | ||
3082 | /* AP might have been stopped while waiting for the lock. */ | ||
3083 | if (!sdata->vif.csa_active) | ||
3084 | goto unlock; | ||
3085 | |||
3086 | if (!ieee80211_sdata_running(sdata)) | ||
3087 | goto unlock; | ||
3088 | |||
3089 | ieee80211_csa_finalize(sdata); | ||
3056 | 3090 | ||
3057 | unlock: | 3091 | unlock: |
3058 | sdata_unlock(sdata); | 3092 | sdata_unlock(sdata); |
@@ -3066,9 +3100,9 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | |||
3066 | struct ieee80211_chanctx_conf *chanctx_conf; | 3100 | struct ieee80211_chanctx_conf *chanctx_conf; |
3067 | struct ieee80211_chanctx *chanctx; | 3101 | struct ieee80211_chanctx *chanctx; |
3068 | struct ieee80211_if_mesh __maybe_unused *ifmsh; | 3102 | struct ieee80211_if_mesh __maybe_unused *ifmsh; |
3069 | int err, num_chanctx; | 3103 | int err, num_chanctx, changed = 0; |
3070 | 3104 | ||
3071 | lockdep_assert_held(&sdata->wdev.mtx); | 3105 | sdata_assert_lock(sdata); |
3072 | 3106 | ||
3073 | if (!list_empty(&local->roc_list) || local->scanning) | 3107 | if (!list_empty(&local->roc_list) || local->scanning) |
3074 | return -EBUSY; | 3108 | return -EBUSY; |
@@ -3107,19 +3141,40 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | |||
3107 | 3141 | ||
3108 | switch (sdata->vif.type) { | 3142 | switch (sdata->vif.type) { |
3109 | case NL80211_IFTYPE_AP: | 3143 | case NL80211_IFTYPE_AP: |
3110 | sdata->csa_counter_offset_beacon = | ||
3111 | params->counter_offset_beacon; | ||
3112 | sdata->csa_counter_offset_presp = params->counter_offset_presp; | ||
3113 | sdata->u.ap.next_beacon = | 3144 | sdata->u.ap.next_beacon = |
3114 | cfg80211_beacon_dup(¶ms->beacon_after); | 3145 | cfg80211_beacon_dup(¶ms->beacon_after); |
3115 | if (!sdata->u.ap.next_beacon) | 3146 | if (!sdata->u.ap.next_beacon) |
3116 | return -ENOMEM; | 3147 | return -ENOMEM; |
3117 | 3148 | ||
3149 | /* | ||
3150 | * With a count of 0, we don't have to wait for any | ||
3151 | * TBTT before switching, so complete the CSA | ||
3152 | * immediately. In theory, with a count == 1 we | ||
3153 | * should delay the switch until just before the next | ||
3154 | * TBTT, but that would complicate things so we switch | ||
3155 | * immediately too. If we would delay the switch | ||
3156 | * until the next TBTT, we would have to set the probe | ||
3157 | * response here. | ||
3158 | * | ||
3159 | * TODO: A channel switch with count <= 1 without | ||
3160 | * sending a CSA action frame is kind of useless, | ||
3161 | * because the clients won't know we're changing | ||
3162 | * channels. The action frame must be implemented | ||
3163 | * either here or in the userspace. | ||
3164 | */ | ||
3165 | if (params->count <= 1) | ||
3166 | break; | ||
3167 | |||
3168 | sdata->csa_counter_offset_beacon = | ||
3169 | params->counter_offset_beacon; | ||
3170 | sdata->csa_counter_offset_presp = params->counter_offset_presp; | ||
3118 | err = ieee80211_assign_beacon(sdata, ¶ms->beacon_csa); | 3171 | err = ieee80211_assign_beacon(sdata, ¶ms->beacon_csa); |
3119 | if (err < 0) { | 3172 | if (err < 0) { |
3120 | kfree(sdata->u.ap.next_beacon); | 3173 | kfree(sdata->u.ap.next_beacon); |
3121 | return err; | 3174 | return err; |
3122 | } | 3175 | } |
3176 | changed |= err; | ||
3177 | |||
3123 | break; | 3178 | break; |
3124 | case NL80211_IFTYPE_ADHOC: | 3179 | case NL80211_IFTYPE_ADHOC: |
3125 | if (!sdata->vif.bss_conf.ibss_joined) | 3180 | if (!sdata->vif.bss_conf.ibss_joined) |
@@ -3147,17 +3202,21 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | |||
3147 | params->chandef.chan->band) | 3202 | params->chandef.chan->band) |
3148 | return -EINVAL; | 3203 | return -EINVAL; |
3149 | 3204 | ||
3150 | err = ieee80211_ibss_csa_beacon(sdata, params); | 3205 | /* see comments in the NL80211_IFTYPE_AP block */ |
3151 | if (err < 0) | 3206 | if (params->count > 1) { |
3152 | return err; | 3207 | err = ieee80211_ibss_csa_beacon(sdata, params); |
3208 | if (err < 0) | ||
3209 | return err; | ||
3210 | changed |= err; | ||
3211 | } | ||
3212 | |||
3213 | ieee80211_send_action_csa(sdata, params); | ||
3214 | |||
3153 | break; | 3215 | break; |
3154 | #ifdef CONFIG_MAC80211_MESH | 3216 | #ifdef CONFIG_MAC80211_MESH |
3155 | case NL80211_IFTYPE_MESH_POINT: | 3217 | case NL80211_IFTYPE_MESH_POINT: |
3156 | ifmsh = &sdata->u.mesh; | 3218 | ifmsh = &sdata->u.mesh; |
3157 | 3219 | ||
3158 | if (!ifmsh->mesh_id) | ||
3159 | return -EINVAL; | ||
3160 | |||
3161 | if (params->chandef.width != sdata->vif.bss_conf.chandef.width) | 3220 | if (params->chandef.width != sdata->vif.bss_conf.chandef.width) |
3162 | return -EINVAL; | 3221 | return -EINVAL; |
3163 | 3222 | ||
@@ -3166,17 +3225,27 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | |||
3166 | params->chandef.chan->band) | 3225 | params->chandef.chan->band) |
3167 | return -EINVAL; | 3226 | return -EINVAL; |
3168 | 3227 | ||
3169 | ifmsh->chsw_init = true; | 3228 | if (ifmsh->csa_role == IEEE80211_MESH_CSA_ROLE_NONE) { |
3170 | if (!ifmsh->pre_value) | 3229 | ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_INIT; |
3171 | ifmsh->pre_value = 1; | 3230 | if (!ifmsh->pre_value) |
3172 | else | 3231 | ifmsh->pre_value = 1; |
3173 | ifmsh->pre_value++; | 3232 | else |
3233 | ifmsh->pre_value++; | ||
3234 | } | ||
3174 | 3235 | ||
3175 | err = ieee80211_mesh_csa_beacon(sdata, params, true); | 3236 | /* see comments in the NL80211_IFTYPE_AP block */ |
3176 | if (err < 0) { | 3237 | if (params->count > 1) { |
3177 | ifmsh->chsw_init = false; | 3238 | err = ieee80211_mesh_csa_beacon(sdata, params); |
3178 | return err; | 3239 | if (err < 0) { |
3240 | ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE; | ||
3241 | return err; | ||
3242 | } | ||
3243 | changed |= err; | ||
3179 | } | 3244 | } |
3245 | |||
3246 | if (ifmsh->csa_role == IEEE80211_MESH_CSA_ROLE_INIT) | ||
3247 | ieee80211_send_action_csa(sdata, params); | ||
3248 | |||
3180 | break; | 3249 | break; |
3181 | #endif | 3250 | #endif |
3182 | default: | 3251 | default: |
@@ -3193,8 +3262,13 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | |||
3193 | sdata->csa_chandef = params->chandef; | 3262 | sdata->csa_chandef = params->chandef; |
3194 | sdata->vif.csa_active = true; | 3263 | sdata->vif.csa_active = true; |
3195 | 3264 | ||
3196 | ieee80211_bss_info_change_notify(sdata, err); | 3265 | if (changed) { |
3197 | drv_channel_switch_beacon(sdata, ¶ms->chandef); | 3266 | ieee80211_bss_info_change_notify(sdata, changed); |
3267 | drv_channel_switch_beacon(sdata, ¶ms->chandef); | ||
3268 | } else { | ||
3269 | /* if the beacon didn't change, we can finalize immediately */ | ||
3270 | ieee80211_csa_finalize(sdata); | ||
3271 | } | ||
3198 | 3272 | ||
3199 | return 0; | 3273 | return 0; |
3200 | } | 3274 | } |
@@ -3865,7 +3939,7 @@ static int ieee80211_set_qos_map(struct wiphy *wiphy, | |||
3865 | return 0; | 3939 | return 0; |
3866 | } | 3940 | } |
3867 | 3941 | ||
3868 | struct cfg80211_ops mac80211_config_ops = { | 3942 | const struct cfg80211_ops mac80211_config_ops = { |
3869 | .add_virtual_intf = ieee80211_add_iface, | 3943 | .add_virtual_intf = ieee80211_add_iface, |
3870 | .del_virtual_intf = ieee80211_del_iface, | 3944 | .del_virtual_intf = ieee80211_del_iface, |
3871 | .change_virtual_intf = ieee80211_change_iface, | 3945 | .change_virtual_intf = ieee80211_change_iface, |
diff --git a/net/mac80211/cfg.h b/net/mac80211/cfg.h index 7d7879f5b00b..2d51f62dc76c 100644 --- a/net/mac80211/cfg.h +++ b/net/mac80211/cfg.h | |||
@@ -4,6 +4,6 @@ | |||
4 | #ifndef __CFG_H | 4 | #ifndef __CFG_H |
5 | #define __CFG_H | 5 | #define __CFG_H |
6 | 6 | ||
7 | extern struct cfg80211_ops mac80211_config_ops; | 7 | extern const struct cfg80211_ops mac80211_config_ops; |
8 | 8 | ||
9 | #endif /* __CFG_H */ | 9 | #endif /* __CFG_H */ |
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index f43613a97dd6..42c659229a09 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c | |||
@@ -196,6 +196,8 @@ static bool ieee80211_is_radar_required(struct ieee80211_local *local) | |||
196 | { | 196 | { |
197 | struct ieee80211_sub_if_data *sdata; | 197 | struct ieee80211_sub_if_data *sdata; |
198 | 198 | ||
199 | lockdep_assert_held(&local->mtx); | ||
200 | |||
199 | rcu_read_lock(); | 201 | rcu_read_lock(); |
200 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 202 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
201 | if (sdata->radar_required) { | 203 | if (sdata->radar_required) { |
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 80194b557a0c..2ecb4deddb5d 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c | |||
@@ -195,7 +195,7 @@ static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, | |||
195 | static ssize_t sta_agg_status_write(struct file *file, const char __user *userbuf, | 195 | static ssize_t sta_agg_status_write(struct file *file, const char __user *userbuf, |
196 | size_t count, loff_t *ppos) | 196 | size_t count, loff_t *ppos) |
197 | { | 197 | { |
198 | char _buf[12], *buf = _buf; | 198 | char _buf[12] = {}, *buf = _buf; |
199 | struct sta_info *sta = file->private_data; | 199 | struct sta_info *sta = file->private_data; |
200 | bool start, tx; | 200 | bool start, tx; |
201 | unsigned long tid; | 201 | unsigned long tid; |
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 70dd013de836..afbe2b203c3e 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c | |||
@@ -375,7 +375,7 @@ void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, | |||
375 | mgmt->u.action.u.delba.params = cpu_to_le16(params); | 375 | mgmt->u.action.u.delba.params = cpu_to_le16(params); |
376 | mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code); | 376 | mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code); |
377 | 377 | ||
378 | ieee80211_tx_skb_tid(sdata, skb, tid); | 378 | ieee80211_tx_skb(sdata, skb); |
379 | } | 379 | } |
380 | 380 | ||
381 | void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, | 381 | void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 2796a198728f..4453e2725e40 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -220,7 +220,6 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
220 | { | 220 | { |
221 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 221 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
222 | struct ieee80211_local *local = sdata->local; | 222 | struct ieee80211_local *local = sdata->local; |
223 | struct ieee80211_supported_band *sband; | ||
224 | struct ieee80211_mgmt *mgmt; | 223 | struct ieee80211_mgmt *mgmt; |
225 | struct cfg80211_bss *bss; | 224 | struct cfg80211_bss *bss; |
226 | u32 bss_change; | 225 | u32 bss_change; |
@@ -294,7 +293,6 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
294 | } | 293 | } |
295 | 294 | ||
296 | mutex_lock(&local->mtx); | 295 | mutex_lock(&local->mtx); |
297 | ieee80211_vif_release_channel(sdata); | ||
298 | if (ieee80211_vif_use_channel(sdata, &chandef, | 296 | if (ieee80211_vif_use_channel(sdata, &chandef, |
299 | ifibss->fixed_channel ? | 297 | ifibss->fixed_channel ? |
300 | IEEE80211_CHANCTX_SHARED : | 298 | IEEE80211_CHANCTX_SHARED : |
@@ -303,12 +301,11 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
303 | mutex_unlock(&local->mtx); | 301 | mutex_unlock(&local->mtx); |
304 | return; | 302 | return; |
305 | } | 303 | } |
304 | sdata->radar_required = radar_required; | ||
306 | mutex_unlock(&local->mtx); | 305 | mutex_unlock(&local->mtx); |
307 | 306 | ||
308 | memcpy(ifibss->bssid, bssid, ETH_ALEN); | 307 | memcpy(ifibss->bssid, bssid, ETH_ALEN); |
309 | 308 | ||
310 | sband = local->hw.wiphy->bands[chan->band]; | ||
311 | |||
312 | presp = ieee80211_ibss_build_presp(sdata, beacon_int, basic_rates, | 309 | presp = ieee80211_ibss_build_presp(sdata, beacon_int, basic_rates, |
313 | capability, tsf, &chandef, | 310 | capability, tsf, &chandef, |
314 | &have_higher_than_11mbit, NULL); | 311 | &have_higher_than_11mbit, NULL); |
@@ -318,7 +315,6 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
318 | rcu_assign_pointer(ifibss->presp, presp); | 315 | rcu_assign_pointer(ifibss->presp, presp); |
319 | mgmt = (void *)presp->head; | 316 | mgmt = (void *)presp->head; |
320 | 317 | ||
321 | sdata->radar_required = radar_required; | ||
322 | sdata->vif.bss_conf.enable_beacon = true; | 318 | sdata->vif.bss_conf.enable_beacon = true; |
323 | sdata->vif.bss_conf.beacon_int = beacon_int; | 319 | sdata->vif.bss_conf.beacon_int = beacon_int; |
324 | sdata->vif.bss_conf.basic_rates = basic_rates; | 320 | sdata->vif.bss_conf.basic_rates = basic_rates; |
@@ -386,7 +382,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
386 | presp->head_len, 0, GFP_KERNEL); | 382 | presp->head_len, 0, GFP_KERNEL); |
387 | cfg80211_put_bss(local->hw.wiphy, bss); | 383 | cfg80211_put_bss(local->hw.wiphy, bss); |
388 | netif_carrier_on(sdata->dev); | 384 | netif_carrier_on(sdata->dev); |
389 | cfg80211_ibss_joined(sdata->dev, ifibss->bssid, GFP_KERNEL); | 385 | cfg80211_ibss_joined(sdata->dev, ifibss->bssid, chan, GFP_KERNEL); |
390 | } | 386 | } |
391 | 387 | ||
392 | static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | 388 | static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, |
@@ -521,12 +517,6 @@ int ieee80211_ibss_csa_beacon(struct ieee80211_sub_if_data *sdata, | |||
521 | if (old_presp) | 517 | if (old_presp) |
522 | kfree_rcu(old_presp, rcu_head); | 518 | kfree_rcu(old_presp, rcu_head); |
523 | 519 | ||
524 | /* it might not send the beacon for a while. send an action frame | ||
525 | * immediately to announce the channel switch. | ||
526 | */ | ||
527 | if (csa_settings) | ||
528 | ieee80211_send_action_csa(sdata, csa_settings); | ||
529 | |||
530 | return BSS_CHANGED_BEACON; | 520 | return BSS_CHANGED_BEACON; |
531 | out: | 521 | out: |
532 | return ret; | 522 | return ret; |
@@ -536,7 +526,7 @@ int ieee80211_ibss_finish_csa(struct ieee80211_sub_if_data *sdata) | |||
536 | { | 526 | { |
537 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 527 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
538 | struct cfg80211_bss *cbss; | 528 | struct cfg80211_bss *cbss; |
539 | int err; | 529 | int err, changed = 0; |
540 | u16 capability; | 530 | u16 capability; |
541 | 531 | ||
542 | sdata_assert_lock(sdata); | 532 | sdata_assert_lock(sdata); |
@@ -568,10 +558,9 @@ int ieee80211_ibss_finish_csa(struct ieee80211_sub_if_data *sdata) | |||
568 | if (err < 0) | 558 | if (err < 0) |
569 | return err; | 559 | return err; |
570 | 560 | ||
571 | if (err) | 561 | changed |= err; |
572 | ieee80211_bss_info_change_notify(sdata, err); | ||
573 | 562 | ||
574 | return 0; | 563 | return changed; |
575 | } | 564 | } |
576 | 565 | ||
577 | void ieee80211_ibss_stop(struct ieee80211_sub_if_data *sdata) | 566 | void ieee80211_ibss_stop(struct ieee80211_sub_if_data *sdata) |
@@ -799,6 +788,8 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
799 | int err; | 788 | int err; |
800 | u32 sta_flags; | 789 | u32 sta_flags; |
801 | 790 | ||
791 | sdata_assert_lock(sdata); | ||
792 | |||
802 | sta_flags = IEEE80211_STA_DISABLE_VHT; | 793 | sta_flags = IEEE80211_STA_DISABLE_VHT; |
803 | switch (ifibss->chandef.width) { | 794 | switch (ifibss->chandef.width) { |
804 | case NL80211_CHAN_WIDTH_5: | 795 | case NL80211_CHAN_WIDTH_5: |
@@ -1468,6 +1459,11 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, | |||
1468 | memcpy(((struct ieee80211_mgmt *) skb->data)->da, mgmt->sa, ETH_ALEN); | 1459 | memcpy(((struct ieee80211_mgmt *) skb->data)->da, mgmt->sa, ETH_ALEN); |
1469 | ibss_dbg(sdata, "Sending ProbeResp to %pM\n", mgmt->sa); | 1460 | ibss_dbg(sdata, "Sending ProbeResp to %pM\n", mgmt->sa); |
1470 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 1461 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
1462 | |||
1463 | /* avoid excessive retries for probe request to wildcard SSIDs */ | ||
1464 | if (pos[1] == 0) | ||
1465 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_NO_ACK; | ||
1466 | |||
1471 | ieee80211_tx_skb(sdata, skb); | 1467 | ieee80211_tx_skb(sdata, skb); |
1472 | } | 1468 | } |
1473 | 1469 | ||
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 3701930c6649..0014b5396ce5 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -616,7 +616,11 @@ struct ieee80211_if_mesh { | |||
616 | struct ps_data ps; | 616 | struct ps_data ps; |
617 | /* Channel Switching Support */ | 617 | /* Channel Switching Support */ |
618 | struct mesh_csa_settings __rcu *csa; | 618 | struct mesh_csa_settings __rcu *csa; |
619 | bool chsw_init; | 619 | enum { |
620 | IEEE80211_MESH_CSA_ROLE_NONE, | ||
621 | IEEE80211_MESH_CSA_ROLE_INIT, | ||
622 | IEEE80211_MESH_CSA_ROLE_REPEATER, | ||
623 | } csa_role; | ||
620 | u8 chsw_ttl; | 624 | u8 chsw_ttl; |
621 | u16 pre_value; | 625 | u16 pre_value; |
622 | 626 | ||
@@ -1408,8 +1412,7 @@ void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata); | |||
1408 | void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | 1412 | void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, |
1409 | struct sk_buff *skb); | 1413 | struct sk_buff *skb); |
1410 | int ieee80211_mesh_csa_beacon(struct ieee80211_sub_if_data *sdata, | 1414 | int ieee80211_mesh_csa_beacon(struct ieee80211_sub_if_data *sdata, |
1411 | struct cfg80211_csa_settings *csa_settings, | 1415 | struct cfg80211_csa_settings *csa_settings); |
1412 | bool csa_action); | ||
1413 | int ieee80211_mesh_finish_csa(struct ieee80211_sub_if_data *sdata); | 1416 | int ieee80211_mesh_finish_csa(struct ieee80211_sub_if_data *sdata); |
1414 | 1417 | ||
1415 | /* scan/BSS handling */ | 1418 | /* scan/BSS handling */ |
@@ -1553,6 +1556,9 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, | |||
1553 | struct sta_info *sta); | 1556 | struct sta_info *sta); |
1554 | enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta); | 1557 | enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta); |
1555 | void ieee80211_sta_set_rx_nss(struct sta_info *sta); | 1558 | void ieee80211_sta_set_rx_nss(struct sta_info *sta); |
1559 | u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, | ||
1560 | struct sta_info *sta, u8 opmode, | ||
1561 | enum ieee80211_band band, bool nss_only); | ||
1556 | void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, | 1562 | void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, |
1557 | struct sta_info *sta, u8 opmode, | 1563 | struct sta_info *sta, u8 opmode, |
1558 | enum ieee80211_band band, bool nss_only); | 1564 | enum ieee80211_band band, bool nss_only); |
@@ -1605,7 +1611,7 @@ static inline int __ieee80211_resume(struct ieee80211_hw *hw) | |||
1605 | } | 1611 | } |
1606 | 1612 | ||
1607 | /* utility functions/constants */ | 1613 | /* utility functions/constants */ |
1608 | extern void *mac80211_wiphy_privid; /* for wiphy privid */ | 1614 | extern const void *const mac80211_wiphy_privid; /* for wiphy privid */ |
1609 | u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, | 1615 | u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, |
1610 | enum nl80211_iftype type); | 1616 | enum nl80211_iftype type); |
1611 | int ieee80211_frame_duration(enum ieee80211_band band, size_t len, | 1617 | int ieee80211_frame_duration(enum ieee80211_band band, size_t len, |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index ce1c44370610..088111af6c7c 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -833,7 +833,9 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
833 | cancel_work_sync(&local->dynamic_ps_enable_work); | 833 | cancel_work_sync(&local->dynamic_ps_enable_work); |
834 | 834 | ||
835 | cancel_work_sync(&sdata->recalc_smps); | 835 | cancel_work_sync(&sdata->recalc_smps); |
836 | sdata_lock(sdata); | ||
836 | sdata->vif.csa_active = false; | 837 | sdata->vif.csa_active = false; |
838 | sdata_unlock(sdata); | ||
837 | cancel_work_sync(&sdata->csa_finalize_work); | 839 | cancel_work_sync(&sdata->csa_finalize_work); |
838 | 840 | ||
839 | cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); | 841 | cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index d767cfb9b45f..1f7d8422d62d 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -893,10 +893,15 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
893 | /* mac80211 supports control port protocol changing */ | 893 | /* mac80211 supports control port protocol changing */ |
894 | local->hw.wiphy->flags |= WIPHY_FLAG_CONTROL_PORT_PROTOCOL; | 894 | local->hw.wiphy->flags |= WIPHY_FLAG_CONTROL_PORT_PROTOCOL; |
895 | 895 | ||
896 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) | 896 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) { |
897 | local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; | 897 | local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; |
898 | else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) | 898 | } else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) { |
899 | local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC; | 899 | local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC; |
900 | if (hw->max_signal <= 0) { | ||
901 | result = -EINVAL; | ||
902 | goto fail_wiphy_register; | ||
903 | } | ||
904 | } | ||
900 | 905 | ||
901 | WARN((local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD) | 906 | WARN((local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD) |
902 | && (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK), | 907 | && (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK), |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 5b919cab1de0..f70e9cd10552 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -688,7 +688,7 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh) | |||
688 | *pos++ = csa->settings.count; | 688 | *pos++ = csa->settings.count; |
689 | *pos++ = WLAN_EID_CHAN_SWITCH_PARAM; | 689 | *pos++ = WLAN_EID_CHAN_SWITCH_PARAM; |
690 | *pos++ = 6; | 690 | *pos++ = 6; |
691 | if (ifmsh->chsw_init) { | 691 | if (ifmsh->csa_role == IEEE80211_MESH_CSA_ROLE_INIT) { |
692 | *pos++ = ifmsh->mshcfg.dot11MeshTTL; | 692 | *pos++ = ifmsh->mshcfg.dot11MeshTTL; |
693 | *pos |= WLAN_EID_CHAN_SWITCH_PARAM_INITIATOR; | 693 | *pos |= WLAN_EID_CHAN_SWITCH_PARAM_INITIATOR; |
694 | } else { | 694 | } else { |
@@ -859,18 +859,12 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata, | |||
859 | { | 859 | { |
860 | struct cfg80211_csa_settings params; | 860 | struct cfg80211_csa_settings params; |
861 | struct ieee80211_csa_ie csa_ie; | 861 | struct ieee80211_csa_ie csa_ie; |
862 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
863 | struct ieee80211_chanctx *chanctx; | ||
864 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 862 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
865 | enum ieee80211_band band = ieee80211_get_sdata_band(sdata); | 863 | enum ieee80211_band band = ieee80211_get_sdata_band(sdata); |
866 | int err, num_chanctx; | 864 | int err; |
867 | u32 sta_flags; | 865 | u32 sta_flags; |
868 | 866 | ||
869 | if (sdata->vif.csa_active) | 867 | sdata_assert_lock(sdata); |
870 | return true; | ||
871 | |||
872 | if (!ifmsh->mesh_id) | ||
873 | return false; | ||
874 | 868 | ||
875 | sta_flags = IEEE80211_STA_DISABLE_VHT; | 869 | sta_flags = IEEE80211_STA_DISABLE_VHT; |
876 | switch (sdata->vif.bss_conf.chandef.width) { | 870 | switch (sdata->vif.bss_conf.chandef.width) { |
@@ -896,10 +890,6 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata, | |||
896 | params.chandef = csa_ie.chandef; | 890 | params.chandef = csa_ie.chandef; |
897 | params.count = csa_ie.count; | 891 | params.count = csa_ie.count; |
898 | 892 | ||
899 | if (sdata->vif.bss_conf.chandef.chan->band != | ||
900 | params.chandef.chan->band) | ||
901 | return false; | ||
902 | |||
903 | if (!cfg80211_chandef_usable(sdata->local->hw.wiphy, ¶ms.chandef, | 893 | if (!cfg80211_chandef_usable(sdata->local->hw.wiphy, ¶ms.chandef, |
904 | IEEE80211_CHAN_DISABLED)) { | 894 | IEEE80211_CHAN_DISABLED)) { |
905 | sdata_info(sdata, | 895 | sdata_info(sdata, |
@@ -922,24 +912,12 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata, | |||
922 | return false; | 912 | return false; |
923 | } | 913 | } |
924 | 914 | ||
925 | rcu_read_lock(); | 915 | if (cfg80211_chandef_identical(¶ms.chandef, |
926 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | 916 | &sdata->vif.bss_conf.chandef)) { |
927 | if (!chanctx_conf) | 917 | mcsa_dbg(sdata, |
928 | goto failed_chswitch; | 918 | "received csa with an identical chandef, ignoring\n"); |
929 | 919 | return true; | |
930 | /* don't handle for multi-VIF cases */ | 920 | } |
931 | chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf); | ||
932 | if (chanctx->refcount > 1) | ||
933 | goto failed_chswitch; | ||
934 | |||
935 | num_chanctx = 0; | ||
936 | list_for_each_entry_rcu(chanctx, &sdata->local->chanctx_list, list) | ||
937 | num_chanctx++; | ||
938 | |||
939 | if (num_chanctx > 1) | ||
940 | goto failed_chswitch; | ||
941 | |||
942 | rcu_read_unlock(); | ||
943 | 921 | ||
944 | mcsa_dbg(sdata, | 922 | mcsa_dbg(sdata, |
945 | "received channel switch announcement to go to channel %d MHz\n", | 923 | "received channel switch announcement to go to channel %d MHz\n", |
@@ -953,30 +931,16 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata, | |||
953 | ifmsh->pre_value = csa_ie.pre_value; | 931 | ifmsh->pre_value = csa_ie.pre_value; |
954 | } | 932 | } |
955 | 933 | ||
956 | if (ifmsh->chsw_ttl < ifmsh->mshcfg.dot11MeshTTL) { | 934 | if (ifmsh->chsw_ttl >= ifmsh->mshcfg.dot11MeshTTL) |
957 | if (ieee80211_mesh_csa_beacon(sdata, ¶ms, false) < 0) | ||
958 | return false; | ||
959 | } else { | ||
960 | return false; | 935 | return false; |
961 | } | ||
962 | 936 | ||
963 | sdata->csa_radar_required = params.radar_required; | 937 | ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_REPEATER; |
964 | 938 | ||
965 | if (params.block_tx) | 939 | if (ieee80211_channel_switch(sdata->local->hw.wiphy, sdata->dev, |
966 | ieee80211_stop_queues_by_reason(&sdata->local->hw, | 940 | ¶ms) < 0) |
967 | IEEE80211_MAX_QUEUE_MAP, | 941 | return false; |
968 | IEEE80211_QUEUE_STOP_REASON_CSA); | ||
969 | |||
970 | sdata->csa_chandef = params.chandef; | ||
971 | sdata->vif.csa_active = true; | ||
972 | |||
973 | ieee80211_bss_info_change_notify(sdata, err); | ||
974 | drv_channel_switch_beacon(sdata, ¶ms.chandef); | ||
975 | 942 | ||
976 | return true; | 943 | return true; |
977 | failed_chswitch: | ||
978 | rcu_read_unlock(); | ||
979 | return false; | ||
980 | } | 944 | } |
981 | 945 | ||
982 | static void | 946 | static void |
@@ -1086,7 +1050,8 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, | |||
1086 | ifmsh->sync_ops->rx_bcn_presp(sdata, | 1050 | ifmsh->sync_ops->rx_bcn_presp(sdata, |
1087 | stype, mgmt, &elems, rx_status); | 1051 | stype, mgmt, &elems, rx_status); |
1088 | 1052 | ||
1089 | if (!ifmsh->chsw_init) | 1053 | if (ifmsh->csa_role != IEEE80211_MESH_CSA_ROLE_INIT && |
1054 | !sdata->vif.csa_active) | ||
1090 | ieee80211_mesh_process_chnswitch(sdata, &elems, true); | 1055 | ieee80211_mesh_process_chnswitch(sdata, &elems, true); |
1091 | } | 1056 | } |
1092 | 1057 | ||
@@ -1095,29 +1060,30 @@ int ieee80211_mesh_finish_csa(struct ieee80211_sub_if_data *sdata) | |||
1095 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 1060 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
1096 | struct mesh_csa_settings *tmp_csa_settings; | 1061 | struct mesh_csa_settings *tmp_csa_settings; |
1097 | int ret = 0; | 1062 | int ret = 0; |
1063 | int changed = 0; | ||
1098 | 1064 | ||
1099 | /* Reset the TTL value and Initiator flag */ | 1065 | /* Reset the TTL value and Initiator flag */ |
1100 | ifmsh->chsw_init = false; | 1066 | ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE; |
1101 | ifmsh->chsw_ttl = 0; | 1067 | ifmsh->chsw_ttl = 0; |
1102 | 1068 | ||
1103 | /* Remove the CSA and MCSP elements from the beacon */ | 1069 | /* Remove the CSA and MCSP elements from the beacon */ |
1104 | tmp_csa_settings = rcu_dereference(ifmsh->csa); | 1070 | tmp_csa_settings = rcu_dereference(ifmsh->csa); |
1105 | rcu_assign_pointer(ifmsh->csa, NULL); | 1071 | rcu_assign_pointer(ifmsh->csa, NULL); |
1106 | kfree_rcu(tmp_csa_settings, rcu_head); | 1072 | if (tmp_csa_settings) |
1073 | kfree_rcu(tmp_csa_settings, rcu_head); | ||
1107 | ret = ieee80211_mesh_rebuild_beacon(sdata); | 1074 | ret = ieee80211_mesh_rebuild_beacon(sdata); |
1108 | if (ret) | 1075 | if (ret) |
1109 | return -EINVAL; | 1076 | return -EINVAL; |
1110 | 1077 | ||
1111 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); | 1078 | changed |= BSS_CHANGED_BEACON; |
1112 | 1079 | ||
1113 | mcsa_dbg(sdata, "complete switching to center freq %d MHz", | 1080 | mcsa_dbg(sdata, "complete switching to center freq %d MHz", |
1114 | sdata->vif.bss_conf.chandef.chan->center_freq); | 1081 | sdata->vif.bss_conf.chandef.chan->center_freq); |
1115 | return 0; | 1082 | return changed; |
1116 | } | 1083 | } |
1117 | 1084 | ||
1118 | int ieee80211_mesh_csa_beacon(struct ieee80211_sub_if_data *sdata, | 1085 | int ieee80211_mesh_csa_beacon(struct ieee80211_sub_if_data *sdata, |
1119 | struct cfg80211_csa_settings *csa_settings, | 1086 | struct cfg80211_csa_settings *csa_settings) |
1120 | bool csa_action) | ||
1121 | { | 1087 | { |
1122 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 1088 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
1123 | struct mesh_csa_settings *tmp_csa_settings; | 1089 | struct mesh_csa_settings *tmp_csa_settings; |
@@ -1141,12 +1107,7 @@ int ieee80211_mesh_csa_beacon(struct ieee80211_sub_if_data *sdata, | |||
1141 | return ret; | 1107 | return ret; |
1142 | } | 1108 | } |
1143 | 1109 | ||
1144 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); | 1110 | return BSS_CHANGED_BEACON; |
1145 | |||
1146 | if (csa_action) | ||
1147 | ieee80211_send_action_csa(sdata, csa_settings); | ||
1148 | |||
1149 | return 0; | ||
1150 | } | 1111 | } |
1151 | 1112 | ||
1152 | static int mesh_fwd_csa_frame(struct ieee80211_sub_if_data *sdata, | 1113 | static int mesh_fwd_csa_frame(struct ieee80211_sub_if_data *sdata, |
@@ -1210,7 +1171,8 @@ static void mesh_rx_csa_frame(struct ieee80211_sub_if_data *sdata, | |||
1210 | 1171 | ||
1211 | ifmsh->pre_value = pre_value; | 1172 | ifmsh->pre_value = pre_value; |
1212 | 1173 | ||
1213 | if (!ieee80211_mesh_process_chnswitch(sdata, &elems, false)) { | 1174 | if (!sdata->vif.csa_active && |
1175 | !ieee80211_mesh_process_chnswitch(sdata, &elems, false)) { | ||
1214 | mcsa_dbg(sdata, "Failed to process CSA action frame"); | 1176 | mcsa_dbg(sdata, "Failed to process CSA action frame"); |
1215 | return; | 1177 | return; |
1216 | } | 1178 | } |
@@ -1257,7 +1219,7 @@ void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
1257 | sdata_lock(sdata); | 1219 | sdata_lock(sdata); |
1258 | 1220 | ||
1259 | /* mesh already went down */ | 1221 | /* mesh already went down */ |
1260 | if (!sdata->wdev.mesh_id_len) | 1222 | if (!sdata->u.mesh.mesh_id_len) |
1261 | goto out; | 1223 | goto out; |
1262 | 1224 | ||
1263 | rx_status = IEEE80211_SKB_RXCB(skb); | 1225 | rx_status = IEEE80211_SKB_RXCB(skb); |
@@ -1310,7 +1272,7 @@ void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata) | |||
1310 | sdata_lock(sdata); | 1272 | sdata_lock(sdata); |
1311 | 1273 | ||
1312 | /* mesh already went down */ | 1274 | /* mesh already went down */ |
1313 | if (!sdata->wdev.mesh_id_len) | 1275 | if (!sdata->u.mesh.mesh_id_len) |
1314 | goto out; | 1276 | goto out; |
1315 | 1277 | ||
1316 | if (ifmsh->preq_queue_len && | 1278 | if (ifmsh->preq_queue_len && |
@@ -1365,7 +1327,7 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) | |||
1365 | mesh_rmc_init(sdata); | 1327 | mesh_rmc_init(sdata); |
1366 | ifmsh->last_preq = jiffies; | 1328 | ifmsh->last_preq = jiffies; |
1367 | ifmsh->next_perr = jiffies; | 1329 | ifmsh->next_perr = jiffies; |
1368 | ifmsh->chsw_init = false; | 1330 | ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE; |
1369 | /* Allocate all mesh structures when creating the first mesh interface. */ | 1331 | /* Allocate all mesh structures when creating the first mesh interface. */ |
1370 | if (!mesh_allocated) | 1332 | if (!mesh_allocated) |
1371 | ieee80211s_init(); | 1333 | ieee80211s_init(); |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index fc1d82465b3c..61604834b914 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -508,6 +508,7 @@ static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata, | |||
508 | u8 *pos; | 508 | u8 *pos; |
509 | u32 cap; | 509 | u32 cap; |
510 | struct ieee80211_sta_vht_cap vht_cap; | 510 | struct ieee80211_sta_vht_cap vht_cap; |
511 | u32 mask, ap_bf_sts, our_bf_sts; | ||
511 | 512 | ||
512 | BUILD_BUG_ON(sizeof(vht_cap) != sizeof(sband->vht_cap)); | 513 | BUILD_BUG_ON(sizeof(vht_cap) != sizeof(sband->vht_cap)); |
513 | 514 | ||
@@ -535,6 +536,16 @@ static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata, | |||
535 | cpu_to_le32(IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE))) | 536 | cpu_to_le32(IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE))) |
536 | cap &= ~IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE; | 537 | cap &= ~IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE; |
537 | 538 | ||
539 | mask = IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK; | ||
540 | |||
541 | ap_bf_sts = le32_to_cpu(ap_vht_cap->vht_cap_info) & mask; | ||
542 | our_bf_sts = cap & mask; | ||
543 | |||
544 | if (ap_bf_sts < our_bf_sts) { | ||
545 | cap &= ~mask; | ||
546 | cap |= ap_bf_sts; | ||
547 | } | ||
548 | |||
538 | /* reserve and fill IE */ | 549 | /* reserve and fill IE */ |
539 | pos = skb_put(skb, sizeof(struct ieee80211_vht_cap) + 2); | 550 | pos = skb_put(skb, sizeof(struct ieee80211_vht_cap) + 2); |
540 | ieee80211_ie_build_vht_cap(pos, &vht_cap, cap); | 551 | ieee80211_ie_build_vht_cap(pos, &vht_cap, cap); |
@@ -745,6 +756,34 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
745 | ieee80211_add_ht_ie(sdata, skb, assoc_data->ap_ht_param, | 756 | ieee80211_add_ht_ie(sdata, skb, assoc_data->ap_ht_param, |
746 | sband, chan, sdata->smps_mode); | 757 | sband, chan, sdata->smps_mode); |
747 | 758 | ||
759 | /* if present, add any custom IEs that go before VHT */ | ||
760 | if (assoc_data->ie_len) { | ||
761 | static const u8 before_vht[] = { | ||
762 | WLAN_EID_SSID, | ||
763 | WLAN_EID_SUPP_RATES, | ||
764 | WLAN_EID_EXT_SUPP_RATES, | ||
765 | WLAN_EID_PWR_CAPABILITY, | ||
766 | WLAN_EID_SUPPORTED_CHANNELS, | ||
767 | WLAN_EID_RSN, | ||
768 | WLAN_EID_QOS_CAPA, | ||
769 | WLAN_EID_RRM_ENABLED_CAPABILITIES, | ||
770 | WLAN_EID_MOBILITY_DOMAIN, | ||
771 | WLAN_EID_SUPPORTED_REGULATORY_CLASSES, | ||
772 | WLAN_EID_HT_CAPABILITY, | ||
773 | WLAN_EID_BSS_COEX_2040, | ||
774 | WLAN_EID_EXT_CAPABILITY, | ||
775 | WLAN_EID_QOS_TRAFFIC_CAPA, | ||
776 | WLAN_EID_TIM_BCAST_REQ, | ||
777 | WLAN_EID_INTERWORKING, | ||
778 | }; | ||
779 | noffset = ieee80211_ie_split(assoc_data->ie, assoc_data->ie_len, | ||
780 | before_vht, ARRAY_SIZE(before_vht), | ||
781 | offset); | ||
782 | pos = skb_put(skb, noffset - offset); | ||
783 | memcpy(pos, assoc_data->ie + offset, noffset - offset); | ||
784 | offset = noffset; | ||
785 | } | ||
786 | |||
748 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) | 787 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) |
749 | ieee80211_add_vht_ie(sdata, skb, sband, | 788 | ieee80211_add_vht_ie(sdata, skb, sband, |
750 | &assoc_data->ap_vht_cap); | 789 | &assoc_data->ap_vht_cap); |
@@ -1001,7 +1040,6 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
1001 | } | 1040 | } |
1002 | 1041 | ||
1003 | ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED; | 1042 | ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED; |
1004 | sdata->vif.csa_active = true; | ||
1005 | 1043 | ||
1006 | mutex_lock(&local->chanctx_mtx); | 1044 | mutex_lock(&local->chanctx_mtx); |
1007 | if (local->use_chanctx) { | 1045 | if (local->use_chanctx) { |
@@ -1039,6 +1077,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
1039 | mutex_unlock(&local->chanctx_mtx); | 1077 | mutex_unlock(&local->chanctx_mtx); |
1040 | 1078 | ||
1041 | sdata->csa_chandef = csa_ie.chandef; | 1079 | sdata->csa_chandef = csa_ie.chandef; |
1080 | sdata->vif.csa_active = true; | ||
1042 | 1081 | ||
1043 | if (csa_ie.mode) | 1082 | if (csa_ie.mode) |
1044 | ieee80211_stop_queues_by_reason(&local->hw, | 1083 | ieee80211_stop_queues_by_reason(&local->hw, |
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 22b223f13c9f..8fdadfd94ba8 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
@@ -10,15 +10,15 @@ | |||
10 | 10 | ||
11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
12 | #include <linux/rtnetlink.h> | 12 | #include <linux/rtnetlink.h> |
13 | #include <linux/slab.h> | ||
14 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/slab.h> | ||
15 | #include "rate.h" | 15 | #include "rate.h" |
16 | #include "ieee80211_i.h" | 16 | #include "ieee80211_i.h" |
17 | #include "debugfs.h" | 17 | #include "debugfs.h" |
18 | 18 | ||
19 | struct rate_control_alg { | 19 | struct rate_control_alg { |
20 | struct list_head list; | 20 | struct list_head list; |
21 | struct rate_control_ops *ops; | 21 | const struct rate_control_ops *ops; |
22 | }; | 22 | }; |
23 | 23 | ||
24 | static LIST_HEAD(rate_ctrl_algs); | 24 | static LIST_HEAD(rate_ctrl_algs); |
@@ -29,7 +29,7 @@ module_param(ieee80211_default_rc_algo, charp, 0644); | |||
29 | MODULE_PARM_DESC(ieee80211_default_rc_algo, | 29 | MODULE_PARM_DESC(ieee80211_default_rc_algo, |
30 | "Default rate control algorithm for mac80211 to use"); | 30 | "Default rate control algorithm for mac80211 to use"); |
31 | 31 | ||
32 | int ieee80211_rate_control_register(struct rate_control_ops *ops) | 32 | int ieee80211_rate_control_register(const struct rate_control_ops *ops) |
33 | { | 33 | { |
34 | struct rate_control_alg *alg; | 34 | struct rate_control_alg *alg; |
35 | 35 | ||
@@ -60,7 +60,7 @@ int ieee80211_rate_control_register(struct rate_control_ops *ops) | |||
60 | } | 60 | } |
61 | EXPORT_SYMBOL(ieee80211_rate_control_register); | 61 | EXPORT_SYMBOL(ieee80211_rate_control_register); |
62 | 62 | ||
63 | void ieee80211_rate_control_unregister(struct rate_control_ops *ops) | 63 | void ieee80211_rate_control_unregister(const struct rate_control_ops *ops) |
64 | { | 64 | { |
65 | struct rate_control_alg *alg; | 65 | struct rate_control_alg *alg; |
66 | 66 | ||
@@ -76,32 +76,31 @@ void ieee80211_rate_control_unregister(struct rate_control_ops *ops) | |||
76 | } | 76 | } |
77 | EXPORT_SYMBOL(ieee80211_rate_control_unregister); | 77 | EXPORT_SYMBOL(ieee80211_rate_control_unregister); |
78 | 78 | ||
79 | static struct rate_control_ops * | 79 | static const struct rate_control_ops * |
80 | ieee80211_try_rate_control_ops_get(const char *name) | 80 | ieee80211_try_rate_control_ops_get(const char *name) |
81 | { | 81 | { |
82 | struct rate_control_alg *alg; | 82 | struct rate_control_alg *alg; |
83 | struct rate_control_ops *ops = NULL; | 83 | const struct rate_control_ops *ops = NULL; |
84 | 84 | ||
85 | if (!name) | 85 | if (!name) |
86 | return NULL; | 86 | return NULL; |
87 | 87 | ||
88 | mutex_lock(&rate_ctrl_mutex); | 88 | mutex_lock(&rate_ctrl_mutex); |
89 | list_for_each_entry(alg, &rate_ctrl_algs, list) { | 89 | list_for_each_entry(alg, &rate_ctrl_algs, list) { |
90 | if (!strcmp(alg->ops->name, name)) | 90 | if (!strcmp(alg->ops->name, name)) { |
91 | if (try_module_get(alg->ops->module)) { | 91 | ops = alg->ops; |
92 | ops = alg->ops; | 92 | break; |
93 | break; | 93 | } |
94 | } | ||
95 | } | 94 | } |
96 | mutex_unlock(&rate_ctrl_mutex); | 95 | mutex_unlock(&rate_ctrl_mutex); |
97 | return ops; | 96 | return ops; |
98 | } | 97 | } |
99 | 98 | ||
100 | /* Get the rate control algorithm. */ | 99 | /* Get the rate control algorithm. */ |
101 | static struct rate_control_ops * | 100 | static const struct rate_control_ops * |
102 | ieee80211_rate_control_ops_get(const char *name) | 101 | ieee80211_rate_control_ops_get(const char *name) |
103 | { | 102 | { |
104 | struct rate_control_ops *ops; | 103 | const struct rate_control_ops *ops; |
105 | const char *alg_name; | 104 | const char *alg_name; |
106 | 105 | ||
107 | kparam_block_sysfs_write(ieee80211_default_rc_algo); | 106 | kparam_block_sysfs_write(ieee80211_default_rc_algo); |
@@ -111,10 +110,6 @@ ieee80211_rate_control_ops_get(const char *name) | |||
111 | alg_name = name; | 110 | alg_name = name; |
112 | 111 | ||
113 | ops = ieee80211_try_rate_control_ops_get(alg_name); | 112 | ops = ieee80211_try_rate_control_ops_get(alg_name); |
114 | if (!ops) { | ||
115 | request_module("rc80211_%s", alg_name); | ||
116 | ops = ieee80211_try_rate_control_ops_get(alg_name); | ||
117 | } | ||
118 | if (!ops && name) | 113 | if (!ops && name) |
119 | /* try default if specific alg requested but not found */ | 114 | /* try default if specific alg requested but not found */ |
120 | ops = ieee80211_try_rate_control_ops_get(ieee80211_default_rc_algo); | 115 | ops = ieee80211_try_rate_control_ops_get(ieee80211_default_rc_algo); |
@@ -127,11 +122,6 @@ ieee80211_rate_control_ops_get(const char *name) | |||
127 | return ops; | 122 | return ops; |
128 | } | 123 | } |
129 | 124 | ||
130 | static void ieee80211_rate_control_ops_put(struct rate_control_ops *ops) | ||
131 | { | ||
132 | module_put(ops->module); | ||
133 | } | ||
134 | |||
135 | #ifdef CONFIG_MAC80211_DEBUGFS | 125 | #ifdef CONFIG_MAC80211_DEBUGFS |
136 | static ssize_t rcname_read(struct file *file, char __user *userbuf, | 126 | static ssize_t rcname_read(struct file *file, char __user *userbuf, |
137 | size_t count, loff_t *ppos) | 127 | size_t count, loff_t *ppos) |
@@ -158,11 +148,11 @@ static struct rate_control_ref *rate_control_alloc(const char *name, | |||
158 | 148 | ||
159 | ref = kmalloc(sizeof(struct rate_control_ref), GFP_KERNEL); | 149 | ref = kmalloc(sizeof(struct rate_control_ref), GFP_KERNEL); |
160 | if (!ref) | 150 | if (!ref) |
161 | goto fail_ref; | 151 | return NULL; |
162 | ref->local = local; | 152 | ref->local = local; |
163 | ref->ops = ieee80211_rate_control_ops_get(name); | 153 | ref->ops = ieee80211_rate_control_ops_get(name); |
164 | if (!ref->ops) | 154 | if (!ref->ops) |
165 | goto fail_ops; | 155 | goto free; |
166 | 156 | ||
167 | #ifdef CONFIG_MAC80211_DEBUGFS | 157 | #ifdef CONFIG_MAC80211_DEBUGFS |
168 | debugfsdir = debugfs_create_dir("rc", local->hw.wiphy->debugfsdir); | 158 | debugfsdir = debugfs_create_dir("rc", local->hw.wiphy->debugfsdir); |
@@ -172,14 +162,11 @@ static struct rate_control_ref *rate_control_alloc(const char *name, | |||
172 | 162 | ||
173 | ref->priv = ref->ops->alloc(&local->hw, debugfsdir); | 163 | ref->priv = ref->ops->alloc(&local->hw, debugfsdir); |
174 | if (!ref->priv) | 164 | if (!ref->priv) |
175 | goto fail_priv; | 165 | goto free; |
176 | return ref; | 166 | return ref; |
177 | 167 | ||
178 | fail_priv: | 168 | free: |
179 | ieee80211_rate_control_ops_put(ref->ops); | ||
180 | fail_ops: | ||
181 | kfree(ref); | 169 | kfree(ref); |
182 | fail_ref: | ||
183 | return NULL; | 170 | return NULL; |
184 | } | 171 | } |
185 | 172 | ||
@@ -192,7 +179,6 @@ static void rate_control_free(struct rate_control_ref *ctrl_ref) | |||
192 | ctrl_ref->local->debugfs.rcdir = NULL; | 179 | ctrl_ref->local->debugfs.rcdir = NULL; |
193 | #endif | 180 | #endif |
194 | 181 | ||
195 | ieee80211_rate_control_ops_put(ctrl_ref->ops); | ||
196 | kfree(ctrl_ref); | 182 | kfree(ctrl_ref); |
197 | } | 183 | } |
198 | 184 | ||
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index b95e16c07081..9aa2a1190a86 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h | |||
@@ -21,7 +21,7 @@ | |||
21 | 21 | ||
22 | struct rate_control_ref { | 22 | struct rate_control_ref { |
23 | struct ieee80211_local *local; | 23 | struct ieee80211_local *local; |
24 | struct rate_control_ops *ops; | 24 | const struct rate_control_ops *ops; |
25 | void *priv; | 25 | void *priv; |
26 | }; | 26 | }; |
27 | 27 | ||
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index f3d88b0c054c..26fd94fa0aed 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c | |||
@@ -657,7 +657,7 @@ minstrel_free(void *priv) | |||
657 | kfree(priv); | 657 | kfree(priv); |
658 | } | 658 | } |
659 | 659 | ||
660 | struct rate_control_ops mac80211_minstrel = { | 660 | const struct rate_control_ops mac80211_minstrel = { |
661 | .name = "minstrel", | 661 | .name = "minstrel", |
662 | .tx_status = minstrel_tx_status, | 662 | .tx_status = minstrel_tx_status, |
663 | .get_rate = minstrel_get_rate, | 663 | .get_rate = minstrel_get_rate, |
diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h index f4301f4b2e41..046d1bd598a8 100644 --- a/net/mac80211/rc80211_minstrel.h +++ b/net/mac80211/rc80211_minstrel.h | |||
@@ -123,7 +123,7 @@ struct minstrel_debugfs_info { | |||
123 | char buf[]; | 123 | char buf[]; |
124 | }; | 124 | }; |
125 | 125 | ||
126 | extern struct rate_control_ops mac80211_minstrel; | 126 | extern const struct rate_control_ops mac80211_minstrel; |
127 | void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir); | 127 | void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir); |
128 | void minstrel_remove_sta_debugfs(void *priv, void *priv_sta); | 128 | void minstrel_remove_sta_debugfs(void *priv, void *priv_sta); |
129 | 129 | ||
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index c1b5b73c5b91..bccaf854a309 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c | |||
@@ -124,7 +124,7 @@ const struct mcs_group minstrel_mcs_groups[] = { | |||
124 | 124 | ||
125 | #define MINSTREL_CCK_GROUP (ARRAY_SIZE(minstrel_mcs_groups) - 1) | 125 | #define MINSTREL_CCK_GROUP (ARRAY_SIZE(minstrel_mcs_groups) - 1) |
126 | 126 | ||
127 | static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES]; | 127 | static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES] __read_mostly; |
128 | 128 | ||
129 | static void | 129 | static void |
130 | minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi); | 130 | minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi); |
@@ -1031,7 +1031,7 @@ minstrel_ht_free(void *priv) | |||
1031 | mac80211_minstrel.free(priv); | 1031 | mac80211_minstrel.free(priv); |
1032 | } | 1032 | } |
1033 | 1033 | ||
1034 | static struct rate_control_ops mac80211_minstrel_ht = { | 1034 | static const struct rate_control_ops mac80211_minstrel_ht = { |
1035 | .name = "minstrel_ht", | 1035 | .name = "minstrel_ht", |
1036 | .tx_status = minstrel_ht_tx_status, | 1036 | .tx_status = minstrel_ht_tx_status, |
1037 | .get_rate = minstrel_ht_get_rate, | 1037 | .get_rate = minstrel_ht_get_rate, |
@@ -1048,8 +1048,7 @@ static struct rate_control_ops mac80211_minstrel_ht = { | |||
1048 | }; | 1048 | }; |
1049 | 1049 | ||
1050 | 1050 | ||
1051 | static void | 1051 | static void __init init_sample_table(void) |
1052 | init_sample_table(void) | ||
1053 | { | 1052 | { |
1054 | int col, i, new_idx; | 1053 | int col, i, new_idx; |
1055 | u8 rnd[MCS_GROUP_RATES]; | 1054 | u8 rnd[MCS_GROUP_RATES]; |
diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c index 958fad07b54c..d0da2a70fe68 100644 --- a/net/mac80211/rc80211_pid_algo.c +++ b/net/mac80211/rc80211_pid_algo.c | |||
@@ -452,7 +452,7 @@ static void rate_control_pid_free_sta(void *priv, struct ieee80211_sta *sta, | |||
452 | kfree(priv_sta); | 452 | kfree(priv_sta); |
453 | } | 453 | } |
454 | 454 | ||
455 | static struct rate_control_ops mac80211_rcpid = { | 455 | static const struct rate_control_ops mac80211_rcpid = { |
456 | .name = "pid", | 456 | .name = "pid", |
457 | .tx_status = rate_control_pid_tx_status, | 457 | .tx_status = rate_control_pid_tx_status, |
458 | .get_rate = rate_control_pid_get_rate, | 458 | .get_rate = rate_control_pid_get_rate, |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index c24ca0d0f469..593062109c50 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -40,8 +40,6 @@ | |||
40 | static struct sk_buff *remove_monitor_info(struct ieee80211_local *local, | 40 | static struct sk_buff *remove_monitor_info(struct ieee80211_local *local, |
41 | struct sk_buff *skb) | 41 | struct sk_buff *skb) |
42 | { | 42 | { |
43 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | ||
44 | |||
45 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) { | 43 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) { |
46 | if (likely(skb->len > FCS_LEN)) | 44 | if (likely(skb->len > FCS_LEN)) |
47 | __pskb_trim(skb, skb->len - FCS_LEN); | 45 | __pskb_trim(skb, skb->len - FCS_LEN); |
@@ -53,9 +51,6 @@ static struct sk_buff *remove_monitor_info(struct ieee80211_local *local, | |||
53 | } | 51 | } |
54 | } | 52 | } |
55 | 53 | ||
56 | if (status->vendor_radiotap_len) | ||
57 | __pskb_pull(skb, status->vendor_radiotap_len); | ||
58 | |||
59 | return skb; | 54 | return skb; |
60 | } | 55 | } |
61 | 56 | ||
@@ -64,14 +59,13 @@ static inline int should_drop_frame(struct sk_buff *skb, int present_fcs_len) | |||
64 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | 59 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
65 | struct ieee80211_hdr *hdr; | 60 | struct ieee80211_hdr *hdr; |
66 | 61 | ||
67 | hdr = (void *)(skb->data + status->vendor_radiotap_len); | 62 | hdr = (void *)(skb->data); |
68 | 63 | ||
69 | if (status->flag & (RX_FLAG_FAILED_FCS_CRC | | 64 | if (status->flag & (RX_FLAG_FAILED_FCS_CRC | |
70 | RX_FLAG_FAILED_PLCP_CRC | | 65 | RX_FLAG_FAILED_PLCP_CRC | |
71 | RX_FLAG_AMPDU_IS_ZEROLEN)) | 66 | RX_FLAG_AMPDU_IS_ZEROLEN)) |
72 | return 1; | 67 | return 1; |
73 | if (unlikely(skb->len < 16 + present_fcs_len + | 68 | if (unlikely(skb->len < 16 + present_fcs_len)) |
74 | status->vendor_radiotap_len)) | ||
75 | return 1; | 69 | return 1; |
76 | if (ieee80211_is_ctl(hdr->frame_control) && | 70 | if (ieee80211_is_ctl(hdr->frame_control) && |
77 | !ieee80211_is_pspoll(hdr->frame_control) && | 71 | !ieee80211_is_pspoll(hdr->frame_control) && |
@@ -90,8 +84,6 @@ ieee80211_rx_radiotap_space(struct ieee80211_local *local, | |||
90 | len = sizeof(struct ieee80211_radiotap_header) + 8; | 84 | len = sizeof(struct ieee80211_radiotap_header) + 8; |
91 | 85 | ||
92 | /* allocate extra bitmaps */ | 86 | /* allocate extra bitmaps */ |
93 | if (status->vendor_radiotap_len) | ||
94 | len += 4; | ||
95 | if (status->chains) | 87 | if (status->chains) |
96 | len += 4 * hweight8(status->chains); | 88 | len += 4 * hweight8(status->chains); |
97 | 89 | ||
@@ -127,18 +119,6 @@ ieee80211_rx_radiotap_space(struct ieee80211_local *local, | |||
127 | len += 2 * hweight8(status->chains); | 119 | len += 2 * hweight8(status->chains); |
128 | } | 120 | } |
129 | 121 | ||
130 | if (status->vendor_radiotap_len) { | ||
131 | if (WARN_ON_ONCE(status->vendor_radiotap_align == 0)) | ||
132 | status->vendor_radiotap_align = 1; | ||
133 | /* align standard part of vendor namespace */ | ||
134 | len = ALIGN(len, 2); | ||
135 | /* allocate standard part of vendor namespace */ | ||
136 | len += 6; | ||
137 | /* align vendor-defined part */ | ||
138 | len = ALIGN(len, status->vendor_radiotap_align); | ||
139 | /* vendor-defined part is already in skb */ | ||
140 | } | ||
141 | |||
142 | return len; | 122 | return len; |
143 | } | 123 | } |
144 | 124 | ||
@@ -172,7 +152,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
172 | it_present = &rthdr->it_present; | 152 | it_present = &rthdr->it_present; |
173 | 153 | ||
174 | /* radiotap header, set always present flags */ | 154 | /* radiotap header, set always present flags */ |
175 | rthdr->it_len = cpu_to_le16(rtap_len + status->vendor_radiotap_len); | 155 | rthdr->it_len = cpu_to_le16(rtap_len); |
176 | it_present_val = BIT(IEEE80211_RADIOTAP_FLAGS) | | 156 | it_present_val = BIT(IEEE80211_RADIOTAP_FLAGS) | |
177 | BIT(IEEE80211_RADIOTAP_CHANNEL) | | 157 | BIT(IEEE80211_RADIOTAP_CHANNEL) | |
178 | BIT(IEEE80211_RADIOTAP_RX_FLAGS); | 158 | BIT(IEEE80211_RADIOTAP_RX_FLAGS); |
@@ -190,14 +170,6 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
190 | BIT(IEEE80211_RADIOTAP_DBM_ANTSIGNAL); | 170 | BIT(IEEE80211_RADIOTAP_DBM_ANTSIGNAL); |
191 | } | 171 | } |
192 | 172 | ||
193 | if (status->vendor_radiotap_len) { | ||
194 | it_present_val |= BIT(IEEE80211_RADIOTAP_VENDOR_NAMESPACE) | | ||
195 | BIT(IEEE80211_RADIOTAP_EXT); | ||
196 | put_unaligned_le32(it_present_val, it_present); | ||
197 | it_present++; | ||
198 | it_present_val = status->vendor_radiotap_bitmap; | ||
199 | } | ||
200 | |||
201 | put_unaligned_le32(it_present_val, it_present); | 173 | put_unaligned_le32(it_present_val, it_present); |
202 | 174 | ||
203 | pos = (void *)(it_present + 1); | 175 | pos = (void *)(it_present + 1); |
@@ -307,6 +279,8 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
307 | *pos |= IEEE80211_RADIOTAP_MCS_BW_40; | 279 | *pos |= IEEE80211_RADIOTAP_MCS_BW_40; |
308 | if (status->flag & RX_FLAG_HT_GF) | 280 | if (status->flag & RX_FLAG_HT_GF) |
309 | *pos |= IEEE80211_RADIOTAP_MCS_FMT_GF; | 281 | *pos |= IEEE80211_RADIOTAP_MCS_FMT_GF; |
282 | if (status->flag & RX_FLAG_LDPC) | ||
283 | *pos |= IEEE80211_RADIOTAP_MCS_FEC_LDPC; | ||
310 | stbc = (status->flag & RX_FLAG_STBC_MASK) >> RX_FLAG_STBC_SHIFT; | 284 | stbc = (status->flag & RX_FLAG_STBC_MASK) >> RX_FLAG_STBC_SHIFT; |
311 | *pos |= stbc << IEEE80211_RADIOTAP_MCS_STBC_SHIFT; | 285 | *pos |= stbc << IEEE80211_RADIOTAP_MCS_STBC_SHIFT; |
312 | pos++; | 286 | pos++; |
@@ -349,20 +323,23 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
349 | 323 | ||
350 | rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_VHT); | 324 | rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_VHT); |
351 | /* known field - how to handle 80+80? */ | 325 | /* known field - how to handle 80+80? */ |
352 | if (status->flag & RX_FLAG_80P80MHZ) | 326 | if (status->vht_flag & RX_VHT_FLAG_80P80MHZ) |
353 | known &= ~IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH; | 327 | known &= ~IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH; |
354 | put_unaligned_le16(known, pos); | 328 | put_unaligned_le16(known, pos); |
355 | pos += 2; | 329 | pos += 2; |
356 | /* flags */ | 330 | /* flags */ |
357 | if (status->flag & RX_FLAG_SHORT_GI) | 331 | if (status->flag & RX_FLAG_SHORT_GI) |
358 | *pos |= IEEE80211_RADIOTAP_VHT_FLAG_SGI; | 332 | *pos |= IEEE80211_RADIOTAP_VHT_FLAG_SGI; |
333 | /* in VHT, STBC is binary */ | ||
334 | if (status->flag & RX_FLAG_STBC_MASK) | ||
335 | *pos |= IEEE80211_RADIOTAP_VHT_FLAG_STBC; | ||
359 | pos++; | 336 | pos++; |
360 | /* bandwidth */ | 337 | /* bandwidth */ |
361 | if (status->flag & RX_FLAG_80MHZ) | 338 | if (status->vht_flag & RX_VHT_FLAG_80MHZ) |
362 | *pos++ = 4; | 339 | *pos++ = 4; |
363 | else if (status->flag & RX_FLAG_80P80MHZ) | 340 | else if (status->vht_flag & RX_VHT_FLAG_80P80MHZ) |
364 | *pos++ = 0; /* marked not known above */ | 341 | *pos++ = 0; /* marked not known above */ |
365 | else if (status->flag & RX_FLAG_160MHZ) | 342 | else if (status->vht_flag & RX_VHT_FLAG_160MHZ) |
366 | *pos++ = 11; | 343 | *pos++ = 11; |
367 | else if (status->flag & RX_FLAG_40MHZ) | 344 | else if (status->flag & RX_FLAG_40MHZ) |
368 | *pos++ = 1; | 345 | *pos++ = 1; |
@@ -372,6 +349,8 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
372 | *pos = (status->rate_idx << 4) | status->vht_nss; | 349 | *pos = (status->rate_idx << 4) | status->vht_nss; |
373 | pos += 4; | 350 | pos += 4; |
374 | /* coding field */ | 351 | /* coding field */ |
352 | if (status->flag & RX_FLAG_LDPC) | ||
353 | *pos |= IEEE80211_RADIOTAP_CODING_LDPC_USER0; | ||
375 | pos++; | 354 | pos++; |
376 | /* group ID */ | 355 | /* group ID */ |
377 | pos++; | 356 | pos++; |
@@ -383,21 +362,6 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
383 | *pos++ = status->chain_signal[chain]; | 362 | *pos++ = status->chain_signal[chain]; |
384 | *pos++ = chain; | 363 | *pos++ = chain; |
385 | } | 364 | } |
386 | |||
387 | if (status->vendor_radiotap_len) { | ||
388 | /* ensure 2 byte alignment for the vendor field as required */ | ||
389 | if ((pos - (u8 *)rthdr) & 1) | ||
390 | *pos++ = 0; | ||
391 | *pos++ = status->vendor_radiotap_oui[0]; | ||
392 | *pos++ = status->vendor_radiotap_oui[1]; | ||
393 | *pos++ = status->vendor_radiotap_oui[2]; | ||
394 | *pos++ = status->vendor_radiotap_subns; | ||
395 | put_unaligned_le16(status->vendor_radiotap_len, pos); | ||
396 | pos += 2; | ||
397 | /* align the actual payload as requested */ | ||
398 | while ((pos - (u8 *)rthdr) & (status->vendor_radiotap_align - 1)) | ||
399 | *pos++ = 0; | ||
400 | } | ||
401 | } | 365 | } |
402 | 366 | ||
403 | /* | 367 | /* |
@@ -428,8 +392,8 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, | |||
428 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) | 392 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) |
429 | present_fcs_len = FCS_LEN; | 393 | present_fcs_len = FCS_LEN; |
430 | 394 | ||
431 | /* ensure hdr->frame_control and vendor radiotap data are in skb head */ | 395 | /* ensure hdr->frame_control is in skb head */ |
432 | if (!pskb_may_pull(origskb, 2 + status->vendor_radiotap_len)) { | 396 | if (!pskb_may_pull(origskb, 2)) { |
433 | dev_kfree_skb(origskb); | 397 | dev_kfree_skb(origskb); |
434 | return NULL; | 398 | return NULL; |
435 | } | 399 | } |
@@ -599,10 +563,10 @@ static int ieee80211_is_unicast_robust_mgmt_frame(struct sk_buff *skb) | |||
599 | { | 563 | { |
600 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 564 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
601 | 565 | ||
602 | if (skb->len < 24 || is_multicast_ether_addr(hdr->addr1)) | 566 | if (is_multicast_ether_addr(hdr->addr1)) |
603 | return 0; | 567 | return 0; |
604 | 568 | ||
605 | return ieee80211_is_robust_mgmt_frame(hdr); | 569 | return ieee80211_is_robust_mgmt_frame(skb); |
606 | } | 570 | } |
607 | 571 | ||
608 | 572 | ||
@@ -610,10 +574,10 @@ static int ieee80211_is_multicast_robust_mgmt_frame(struct sk_buff *skb) | |||
610 | { | 574 | { |
611 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 575 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
612 | 576 | ||
613 | if (skb->len < 24 || !is_multicast_ether_addr(hdr->addr1)) | 577 | if (!is_multicast_ether_addr(hdr->addr1)) |
614 | return 0; | 578 | return 0; |
615 | 579 | ||
616 | return ieee80211_is_robust_mgmt_frame(hdr); | 580 | return ieee80211_is_robust_mgmt_frame(skb); |
617 | } | 581 | } |
618 | 582 | ||
619 | 583 | ||
@@ -626,7 +590,7 @@ static int ieee80211_get_mmie_keyidx(struct sk_buff *skb) | |||
626 | if (skb->len < 24 + sizeof(*mmie) || !is_multicast_ether_addr(hdr->da)) | 590 | if (skb->len < 24 + sizeof(*mmie) || !is_multicast_ether_addr(hdr->da)) |
627 | return -1; | 591 | return -1; |
628 | 592 | ||
629 | if (!ieee80211_is_robust_mgmt_frame((struct ieee80211_hdr *) hdr)) | 593 | if (!ieee80211_is_robust_mgmt_frame(skb)) |
630 | return -1; /* not a robust management frame */ | 594 | return -1; /* not a robust management frame */ |
631 | 595 | ||
632 | mmie = (struct ieee80211_mmie *) | 596 | mmie = (struct ieee80211_mmie *) |
@@ -1261,6 +1225,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
1261 | if (ieee80211_is_data(hdr->frame_control)) { | 1225 | if (ieee80211_is_data(hdr->frame_control)) { |
1262 | sta->last_rx_rate_idx = status->rate_idx; | 1226 | sta->last_rx_rate_idx = status->rate_idx; |
1263 | sta->last_rx_rate_flag = status->flag; | 1227 | sta->last_rx_rate_flag = status->flag; |
1228 | sta->last_rx_rate_vht_flag = status->vht_flag; | ||
1264 | sta->last_rx_rate_vht_nss = status->vht_nss; | 1229 | sta->last_rx_rate_vht_nss = status->vht_nss; |
1265 | } | 1230 | } |
1266 | } | 1231 | } |
@@ -1311,18 +1276,15 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
1311 | !ieee80211_has_morefrags(hdr->frame_control) && | 1276 | !ieee80211_has_morefrags(hdr->frame_control) && |
1312 | !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) && | 1277 | !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) && |
1313 | (rx->sdata->vif.type == NL80211_IFTYPE_AP || | 1278 | (rx->sdata->vif.type == NL80211_IFTYPE_AP || |
1314 | rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) { | 1279 | rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) && |
1280 | /* PM bit is only checked in frames where it isn't reserved, | ||
1281 | * in AP mode it's reserved in non-bufferable management frames | ||
1282 | * (cf. IEEE 802.11-2012 8.2.4.1.7 Power Management field) | ||
1283 | */ | ||
1284 | (!ieee80211_is_mgmt(hdr->frame_control) || | ||
1285 | ieee80211_is_bufferable_mmpdu(hdr->frame_control))) { | ||
1315 | if (test_sta_flag(sta, WLAN_STA_PS_STA)) { | 1286 | if (test_sta_flag(sta, WLAN_STA_PS_STA)) { |
1316 | /* | 1287 | if (!ieee80211_has_pm(hdr->frame_control)) |
1317 | * Ignore doze->wake transitions that are | ||
1318 | * indicated by non-data frames, the standard | ||
1319 | * is unclear here, but for example going to | ||
1320 | * PS mode and then scanning would cause a | ||
1321 | * doze->wake transition for the probe request, | ||
1322 | * and that is clearly undesirable. | ||
1323 | */ | ||
1324 | if (ieee80211_is_data(hdr->frame_control) && | ||
1325 | !ieee80211_has_pm(hdr->frame_control)) | ||
1326 | sta_ps_end(sta); | 1288 | sta_ps_end(sta); |
1327 | } else { | 1289 | } else { |
1328 | if (ieee80211_has_pm(hdr->frame_control)) | 1290 | if (ieee80211_has_pm(hdr->frame_control)) |
@@ -1845,8 +1807,7 @@ static int ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx) | |||
1845 | * having configured keys. | 1807 | * having configured keys. |
1846 | */ | 1808 | */ |
1847 | if (unlikely(ieee80211_is_action(fc) && !rx->key && | 1809 | if (unlikely(ieee80211_is_action(fc) && !rx->key && |
1848 | ieee80211_is_robust_mgmt_frame( | 1810 | ieee80211_is_robust_mgmt_frame(rx->skb))) |
1849 | (struct ieee80211_hdr *) rx->skb->data))) | ||
1850 | return -EACCES; | 1811 | return -EACCES; |
1851 | } | 1812 | } |
1852 | 1813 | ||
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index d77ff7090630..d4d85de0d75d 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -261,6 +261,7 @@ struct ieee80211_tx_latency_stat { | |||
261 | * "the" transmit rate | 261 | * "the" transmit rate |
262 | * @last_rx_rate_idx: rx status rate index of the last data packet | 262 | * @last_rx_rate_idx: rx status rate index of the last data packet |
263 | * @last_rx_rate_flag: rx status flag of the last data packet | 263 | * @last_rx_rate_flag: rx status flag of the last data packet |
264 | * @last_rx_rate_vht_flag: rx status vht flag of the last data packet | ||
264 | * @last_rx_rate_vht_nss: rx status nss of last data packet | 265 | * @last_rx_rate_vht_nss: rx status nss of last data packet |
265 | * @lock: used for locking all fields that require locking, see comments | 266 | * @lock: used for locking all fields that require locking, see comments |
266 | * in the header file. | 267 | * in the header file. |
@@ -397,6 +398,7 @@ struct sta_info { | |||
397 | struct ieee80211_tx_rate last_tx_rate; | 398 | struct ieee80211_tx_rate last_tx_rate; |
398 | int last_rx_rate_idx; | 399 | int last_rx_rate_idx; |
399 | u32 last_rx_rate_flag; | 400 | u32 last_rx_rate_flag; |
401 | u32 last_rx_rate_vht_flag; | ||
400 | u8 last_rx_rate_vht_nss; | 402 | u8 last_rx_rate_vht_nss; |
401 | u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1]; | 403 | u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1]; |
402 | 404 | ||
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 1ee85c402439..e6e574a307c8 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -479,7 +479,7 @@ static void ieee80211_tx_latency_end_msrmnt(struct ieee80211_local *local, | |||
479 | u32 msrmnt; | 479 | u32 msrmnt; |
480 | u16 tid; | 480 | u16 tid; |
481 | u8 *qc; | 481 | u8 *qc; |
482 | int i, bin_range_count, bin_count; | 482 | int i, bin_range_count; |
483 | u32 *bin_ranges; | 483 | u32 *bin_ranges; |
484 | __le16 fc; | 484 | __le16 fc; |
485 | struct ieee80211_tx_latency_stat *tx_lat; | 485 | struct ieee80211_tx_latency_stat *tx_lat; |
@@ -522,7 +522,6 @@ static void ieee80211_tx_latency_end_msrmnt(struct ieee80211_local *local, | |||
522 | /* count how many Tx frames transmitted with the appropriate latency */ | 522 | /* count how many Tx frames transmitted with the appropriate latency */ |
523 | bin_range_count = tx_latency->n_ranges; | 523 | bin_range_count = tx_latency->n_ranges; |
524 | bin_ranges = tx_latency->ranges; | 524 | bin_ranges = tx_latency->ranges; |
525 | bin_count = tx_lat->bin_count; | ||
526 | 525 | ||
527 | for (i = 0; i < bin_range_count; i++) { | 526 | for (i = 0; i < bin_range_count; i++) { |
528 | if (msrmnt <= bin_ranges[i]) { | 527 | if (msrmnt <= bin_ranges[i]) { |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 97a02d3f7d87..722151fa5dce 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -452,8 +452,7 @@ static int ieee80211_use_mfp(__le16 fc, struct sta_info *sta, | |||
452 | if (sta == NULL || !test_sta_flag(sta, WLAN_STA_MFP)) | 452 | if (sta == NULL || !test_sta_flag(sta, WLAN_STA_MFP)) |
453 | return 0; | 453 | return 0; |
454 | 454 | ||
455 | if (!ieee80211_is_robust_mgmt_frame((struct ieee80211_hdr *) | 455 | if (!ieee80211_is_robust_mgmt_frame(skb)) |
456 | skb->data)) | ||
457 | return 0; | 456 | return 0; |
458 | 457 | ||
459 | return 1; | 458 | return 1; |
@@ -523,11 +522,8 @@ ieee80211_tx_h_ps_buf(struct ieee80211_tx_data *tx) | |||
523 | if (unlikely(tx->flags & IEEE80211_TX_PS_BUFFERED)) | 522 | if (unlikely(tx->flags & IEEE80211_TX_PS_BUFFERED)) |
524 | return TX_CONTINUE; | 523 | return TX_CONTINUE; |
525 | 524 | ||
526 | /* only deauth, disassoc and action are bufferable MMPDUs */ | ||
527 | if (ieee80211_is_mgmt(hdr->frame_control) && | 525 | if (ieee80211_is_mgmt(hdr->frame_control) && |
528 | !ieee80211_is_deauth(hdr->frame_control) && | 526 | !ieee80211_is_bufferable_mmpdu(hdr->frame_control)) { |
529 | !ieee80211_is_disassoc(hdr->frame_control) && | ||
530 | !ieee80211_is_action(hdr->frame_control)) { | ||
531 | if (tx->flags & IEEE80211_TX_UNICAST) | 527 | if (tx->flags & IEEE80211_TX_UNICAST) |
532 | info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER; | 528 | info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER; |
533 | return TX_CONTINUE; | 529 | return TX_CONTINUE; |
@@ -567,7 +563,7 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
567 | tx->key = key; | 563 | tx->key = key; |
568 | else if (ieee80211_is_mgmt(hdr->frame_control) && | 564 | else if (ieee80211_is_mgmt(hdr->frame_control) && |
569 | is_multicast_ether_addr(hdr->addr1) && | 565 | is_multicast_ether_addr(hdr->addr1) && |
570 | ieee80211_is_robust_mgmt_frame(hdr) && | 566 | ieee80211_is_robust_mgmt_frame(tx->skb) && |
571 | (key = rcu_dereference(tx->sdata->default_mgmt_key))) | 567 | (key = rcu_dereference(tx->sdata->default_mgmt_key))) |
572 | tx->key = key; | 568 | tx->key = key; |
573 | else if (is_multicast_ether_addr(hdr->addr1) && | 569 | else if (is_multicast_ether_addr(hdr->addr1) && |
@@ -582,12 +578,12 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
582 | tx->key = NULL; | 578 | tx->key = NULL; |
583 | else if (tx->skb->protocol == tx->sdata->control_port_protocol) | 579 | else if (tx->skb->protocol == tx->sdata->control_port_protocol) |
584 | tx->key = NULL; | 580 | tx->key = NULL; |
585 | else if (ieee80211_is_robust_mgmt_frame(hdr) && | 581 | else if (ieee80211_is_robust_mgmt_frame(tx->skb) && |
586 | !(ieee80211_is_action(hdr->frame_control) && | 582 | !(ieee80211_is_action(hdr->frame_control) && |
587 | tx->sta && test_sta_flag(tx->sta, WLAN_STA_MFP))) | 583 | tx->sta && test_sta_flag(tx->sta, WLAN_STA_MFP))) |
588 | tx->key = NULL; | 584 | tx->key = NULL; |
589 | else if (ieee80211_is_mgmt(hdr->frame_control) && | 585 | else if (ieee80211_is_mgmt(hdr->frame_control) && |
590 | !ieee80211_is_robust_mgmt_frame(hdr)) | 586 | !ieee80211_is_robust_mgmt_frame(tx->skb)) |
591 | tx->key = NULL; | 587 | tx->key = NULL; |
592 | else { | 588 | else { |
593 | I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted); | 589 | I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted); |
@@ -2402,15 +2398,6 @@ static int ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata, | |||
2402 | return 0; | 2398 | return 0; |
2403 | } | 2399 | } |
2404 | 2400 | ||
2405 | void ieee80211_csa_finish(struct ieee80211_vif *vif) | ||
2406 | { | ||
2407 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
2408 | |||
2409 | ieee80211_queue_work(&sdata->local->hw, | ||
2410 | &sdata->csa_finalize_work); | ||
2411 | } | ||
2412 | EXPORT_SYMBOL(ieee80211_csa_finish); | ||
2413 | |||
2414 | static void ieee80211_update_csa(struct ieee80211_sub_if_data *sdata, | 2401 | static void ieee80211_update_csa(struct ieee80211_sub_if_data *sdata, |
2415 | struct beacon_data *beacon) | 2402 | struct beacon_data *beacon) |
2416 | { | 2403 | { |
@@ -2439,8 +2426,12 @@ static void ieee80211_update_csa(struct ieee80211_sub_if_data *sdata, | |||
2439 | if (WARN_ON(counter_offset_beacon >= beacon_data_len)) | 2426 | if (WARN_ON(counter_offset_beacon >= beacon_data_len)) |
2440 | return; | 2427 | return; |
2441 | 2428 | ||
2442 | /* warn if the driver did not check for/react to csa completeness */ | 2429 | /* Warn if the driver did not check for/react to csa |
2443 | if (WARN_ON(beacon_data[counter_offset_beacon] == 0)) | 2430 | * completeness. A beacon with CSA counter set to 0 should |
2431 | * never occur, because a counter of 1 means switch just | ||
2432 | * before the next beacon. | ||
2433 | */ | ||
2434 | if (WARN_ON(beacon_data[counter_offset_beacon] == 1)) | ||
2444 | return; | 2435 | return; |
2445 | 2436 | ||
2446 | beacon_data[counter_offset_beacon]--; | 2437 | beacon_data[counter_offset_beacon]--; |
@@ -2506,7 +2497,7 @@ bool ieee80211_csa_is_complete(struct ieee80211_vif *vif) | |||
2506 | if (WARN_ON(counter_beacon > beacon_data_len)) | 2497 | if (WARN_ON(counter_beacon > beacon_data_len)) |
2507 | goto out; | 2498 | goto out; |
2508 | 2499 | ||
2509 | if (beacon_data[counter_beacon] == 0) | 2500 | if (beacon_data[counter_beacon] == 1) |
2510 | ret = true; | 2501 | ret = true; |
2511 | out: | 2502 | out: |
2512 | rcu_read_unlock(); | 2503 | rcu_read_unlock(); |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 676dc0967f37..d842af5c8a95 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -34,7 +34,7 @@ | |||
34 | #include "wep.h" | 34 | #include "wep.h" |
35 | 35 | ||
36 | /* privid for wiphys to determine whether they belong to us or not */ | 36 | /* privid for wiphys to determine whether they belong to us or not */ |
37 | void *mac80211_wiphy_privid = &mac80211_wiphy_privid; | 37 | const void *const mac80211_wiphy_privid = &mac80211_wiphy_privid; |
38 | 38 | ||
39 | struct ieee80211_hw *wiphy_to_ieee80211_hw(struct wiphy *wiphy) | 39 | struct ieee80211_hw *wiphy_to_ieee80211_hw(struct wiphy *wiphy) |
40 | { | 40 | { |
@@ -1281,13 +1281,32 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
1281 | * that calculates local->scan_ies_len. | 1281 | * that calculates local->scan_ies_len. |
1282 | */ | 1282 | */ |
1283 | 1283 | ||
1284 | /* add any remaining custom IEs */ | 1284 | /* insert custom IEs that go before VHT */ |
1285 | if (ie && ie_len) { | 1285 | if (ie && ie_len) { |
1286 | noffset = ie_len; | 1286 | static const u8 before_vht[] = { |
1287 | WLAN_EID_SSID, | ||
1288 | WLAN_EID_SUPP_RATES, | ||
1289 | WLAN_EID_REQUEST, | ||
1290 | WLAN_EID_EXT_SUPP_RATES, | ||
1291 | WLAN_EID_DS_PARAMS, | ||
1292 | WLAN_EID_SUPPORTED_REGULATORY_CLASSES, | ||
1293 | WLAN_EID_HT_CAPABILITY, | ||
1294 | WLAN_EID_BSS_COEX_2040, | ||
1295 | WLAN_EID_EXT_CAPABILITY, | ||
1296 | WLAN_EID_SSID_LIST, | ||
1297 | WLAN_EID_CHANNEL_USAGE, | ||
1298 | WLAN_EID_INTERWORKING, | ||
1299 | /* mesh ID can't happen here */ | ||
1300 | /* 60 GHz can't happen here right now */ | ||
1301 | }; | ||
1302 | noffset = ieee80211_ie_split(ie, ie_len, | ||
1303 | before_vht, ARRAY_SIZE(before_vht), | ||
1304 | offset); | ||
1287 | if (end - pos < noffset - offset) | 1305 | if (end - pos < noffset - offset) |
1288 | goto out_err; | 1306 | goto out_err; |
1289 | memcpy(pos, ie + offset, noffset - offset); | 1307 | memcpy(pos, ie + offset, noffset - offset); |
1290 | pos += noffset - offset; | 1308 | pos += noffset - offset; |
1309 | offset = noffset; | ||
1291 | } | 1310 | } |
1292 | 1311 | ||
1293 | if (sband->vht_cap.vht_supported) { | 1312 | if (sband->vht_cap.vht_supported) { |
@@ -1297,6 +1316,15 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
1297 | sband->vht_cap.cap); | 1316 | sband->vht_cap.cap); |
1298 | } | 1317 | } |
1299 | 1318 | ||
1319 | /* add any remaining custom IEs */ | ||
1320 | if (ie && ie_len) { | ||
1321 | noffset = ie_len; | ||
1322 | if (end - pos < noffset - offset) | ||
1323 | goto out_err; | ||
1324 | memcpy(pos, ie + offset, noffset - offset); | ||
1325 | pos += noffset - offset; | ||
1326 | } | ||
1327 | |||
1300 | return pos - buffer; | 1328 | return pos - buffer; |
1301 | out_err: | 1329 | out_err: |
1302 | WARN_ONCE(1, "not enough space for preq IEs\n"); | 1330 | WARN_ONCE(1, "not enough space for preq IEs\n"); |
@@ -1374,7 +1402,6 @@ u32 ieee80211_sta_get_rates(struct ieee80211_sub_if_data *sdata, | |||
1374 | enum ieee80211_band band, u32 *basic_rates) | 1402 | enum ieee80211_band band, u32 *basic_rates) |
1375 | { | 1403 | { |
1376 | struct ieee80211_supported_band *sband; | 1404 | struct ieee80211_supported_band *sband; |
1377 | struct ieee80211_rate *bitrates; | ||
1378 | size_t num_rates; | 1405 | size_t num_rates; |
1379 | u32 supp_rates, rate_flags; | 1406 | u32 supp_rates, rate_flags; |
1380 | int i, j, shift; | 1407 | int i, j, shift; |
@@ -1386,7 +1413,6 @@ u32 ieee80211_sta_get_rates(struct ieee80211_sub_if_data *sdata, | |||
1386 | if (WARN_ON(!sband)) | 1413 | if (WARN_ON(!sband)) |
1387 | return 1; | 1414 | return 1; |
1388 | 1415 | ||
1389 | bitrates = sband->bitrates; | ||
1390 | num_rates = sband->n_bitrates; | 1416 | num_rates = sband->n_bitrates; |
1391 | supp_rates = 0; | 1417 | supp_rates = 0; |
1392 | for (i = 0; i < elems->supp_rates_len + | 1418 | for (i = 0; i < elems->supp_rates_len + |
@@ -2272,11 +2298,11 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local, | |||
2272 | ri.nss = status->vht_nss; | 2298 | ri.nss = status->vht_nss; |
2273 | if (status->flag & RX_FLAG_40MHZ) | 2299 | if (status->flag & RX_FLAG_40MHZ) |
2274 | ri.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; | 2300 | ri.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; |
2275 | if (status->flag & RX_FLAG_80MHZ) | 2301 | if (status->vht_flag & RX_VHT_FLAG_80MHZ) |
2276 | ri.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; | 2302 | ri.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; |
2277 | if (status->flag & RX_FLAG_80P80MHZ) | 2303 | if (status->vht_flag & RX_VHT_FLAG_80P80MHZ) |
2278 | ri.flags |= RATE_INFO_FLAGS_80P80_MHZ_WIDTH; | 2304 | ri.flags |= RATE_INFO_FLAGS_80P80_MHZ_WIDTH; |
2279 | if (status->flag & RX_FLAG_160MHZ) | 2305 | if (status->vht_flag & RX_VHT_FLAG_160MHZ) |
2280 | ri.flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH; | 2306 | ri.flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH; |
2281 | if (status->flag & RX_FLAG_SHORT_GI) | 2307 | if (status->flag & RX_FLAG_SHORT_GI) |
2282 | ri.flags |= RATE_INFO_FLAGS_SHORT_GI; | 2308 | ri.flags |= RATE_INFO_FLAGS_SHORT_GI; |
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c index d75f35c6e1a0..e9e36a256165 100644 --- a/net/mac80211/vht.c +++ b/net/mac80211/vht.c | |||
@@ -349,9 +349,9 @@ void ieee80211_sta_set_rx_nss(struct sta_info *sta) | |||
349 | sta->sta.rx_nss = max_t(u8, 1, ht_rx_nss); | 349 | sta->sta.rx_nss = max_t(u8, 1, ht_rx_nss); |
350 | } | 350 | } |
351 | 351 | ||
352 | void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, | 352 | u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, |
353 | struct sta_info *sta, u8 opmode, | 353 | struct sta_info *sta, u8 opmode, |
354 | enum ieee80211_band band, bool nss_only) | 354 | enum ieee80211_band band, bool nss_only) |
355 | { | 355 | { |
356 | struct ieee80211_local *local = sdata->local; | 356 | struct ieee80211_local *local = sdata->local; |
357 | struct ieee80211_supported_band *sband; | 357 | struct ieee80211_supported_band *sband; |
@@ -363,7 +363,7 @@ void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, | |||
363 | 363 | ||
364 | /* ignore - no support for BF yet */ | 364 | /* ignore - no support for BF yet */ |
365 | if (opmode & IEEE80211_OPMODE_NOTIF_RX_NSS_TYPE_BF) | 365 | if (opmode & IEEE80211_OPMODE_NOTIF_RX_NSS_TYPE_BF) |
366 | return; | 366 | return 0; |
367 | 367 | ||
368 | nss = opmode & IEEE80211_OPMODE_NOTIF_RX_NSS_MASK; | 368 | nss = opmode & IEEE80211_OPMODE_NOTIF_RX_NSS_MASK; |
369 | nss >>= IEEE80211_OPMODE_NOTIF_RX_NSS_SHIFT; | 369 | nss >>= IEEE80211_OPMODE_NOTIF_RX_NSS_SHIFT; |
@@ -375,7 +375,7 @@ void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, | |||
375 | } | 375 | } |
376 | 376 | ||
377 | if (nss_only) | 377 | if (nss_only) |
378 | goto change; | 378 | return changed; |
379 | 379 | ||
380 | switch (opmode & IEEE80211_OPMODE_NOTIF_CHANWIDTH_MASK) { | 380 | switch (opmode & IEEE80211_OPMODE_NOTIF_CHANWIDTH_MASK) { |
381 | case IEEE80211_OPMODE_NOTIF_CHANWIDTH_20MHZ: | 381 | case IEEE80211_OPMODE_NOTIF_CHANWIDTH_20MHZ: |
@@ -398,7 +398,19 @@ void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, | |||
398 | changed |= IEEE80211_RC_BW_CHANGED; | 398 | changed |= IEEE80211_RC_BW_CHANGED; |
399 | } | 399 | } |
400 | 400 | ||
401 | change: | 401 | return changed; |
402 | if (changed) | 402 | } |
403 | |||
404 | void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, | ||
405 | struct sta_info *sta, u8 opmode, | ||
406 | enum ieee80211_band band, bool nss_only) | ||
407 | { | ||
408 | struct ieee80211_local *local = sdata->local; | ||
409 | struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band]; | ||
410 | |||
411 | u32 changed = __ieee80211_vht_handle_opmode(sdata, sta, opmode, | ||
412 | band, nss_only); | ||
413 | |||
414 | if (changed > 0) | ||
403 | rate_control_rate_update(local, sband, sta, changed); | 415 | rate_control_rate_update(local, sband, sta, changed); |
404 | } | 416 | } |
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 21448d629b15..b8600e3c29c8 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c | |||
@@ -301,8 +301,7 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) | |||
301 | } | 301 | } |
302 | 302 | ||
303 | 303 | ||
304 | static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad, | 304 | static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad) |
305 | int encrypted) | ||
306 | { | 305 | { |
307 | __le16 mask_fc; | 306 | __le16 mask_fc; |
308 | int a4_included, mgmt; | 307 | int a4_included, mgmt; |
@@ -456,7 +455,7 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
456 | return 0; | 455 | return 0; |
457 | 456 | ||
458 | pos += IEEE80211_CCMP_HDR_LEN; | 457 | pos += IEEE80211_CCMP_HDR_LEN; |
459 | ccmp_special_blocks(skb, pn, b_0, aad, 0); | 458 | ccmp_special_blocks(skb, pn, b_0, aad); |
460 | ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len, | 459 | ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len, |
461 | skb_put(skb, IEEE80211_CCMP_MIC_LEN)); | 460 | skb_put(skb, IEEE80211_CCMP_MIC_LEN)); |
462 | 461 | ||
@@ -495,7 +494,7 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) | |||
495 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 494 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
496 | 495 | ||
497 | if (!ieee80211_is_data(hdr->frame_control) && | 496 | if (!ieee80211_is_data(hdr->frame_control) && |
498 | !ieee80211_is_robust_mgmt_frame(hdr)) | 497 | !ieee80211_is_robust_mgmt_frame(skb)) |
499 | return RX_CONTINUE; | 498 | return RX_CONTINUE; |
500 | 499 | ||
501 | data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN - | 500 | data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN - |
@@ -524,7 +523,7 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) | |||
524 | u8 aad[2 * AES_BLOCK_SIZE]; | 523 | u8 aad[2 * AES_BLOCK_SIZE]; |
525 | u8 b_0[AES_BLOCK_SIZE]; | 524 | u8 b_0[AES_BLOCK_SIZE]; |
526 | /* hardware didn't decrypt/verify MIC */ | 525 | /* hardware didn't decrypt/verify MIC */ |
527 | ccmp_special_blocks(skb, pn, b_0, aad, 1); | 526 | ccmp_special_blocks(skb, pn, b_0, aad); |
528 | 527 | ||
529 | if (ieee80211_aes_ccm_decrypt( | 528 | if (ieee80211_aes_ccm_decrypt( |
530 | key->u.ccmp.tfm, b_0, aad, | 529 | key->u.ccmp.tfm, b_0, aad, |