aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2014-04-30 12:04:27 -0400
committerJohn W. Linville <linville@tuxdriver.com>2014-04-30 12:04:27 -0400
commitf6595444c1ee798f9c227107bb3ab14730c6497a (patch)
treee8e06d7c2057c69e19848ee3abd6720927f5f9f9 /net/mac80211
parent0006433a5be9e0e155ad493e33c6e9bf3868a87f (diff)
parentf55ee0834247c88cb6981cb11eb1870392878371 (diff)
Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
Conflicts: net/mac80211/chan.c
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/aes_ccm.c37
-rw-r--r--net/mac80211/cfg.c53
-rw-r--r--net/mac80211/chan.c614
-rw-r--r--net/mac80211/debugfs.c2
-rw-r--r--net/mac80211/debugfs.h2
-rw-r--r--net/mac80211/debugfs_netdev.h2
-rw-r--r--net/mac80211/driver-ops.h8
-rw-r--r--net/mac80211/ht.c22
-rw-r--r--net/mac80211/ibss.c75
-rw-r--r--net/mac80211/ieee80211_i.h33
-rw-r--r--net/mac80211/iface.c36
-rw-r--r--net/mac80211/main.c8
-rw-r--r--net/mac80211/mesh.c36
-rw-r--r--net/mac80211/mesh_hwmp.c5
-rw-r--r--net/mac80211/michael.h1
-rw-r--r--net/mac80211/mlme.c4
-rw-r--r--net/mac80211/rx.c19
-rw-r--r--net/mac80211/scan.c10
-rw-r--r--net/mac80211/sta_info.c3
-rw-r--r--net/mac80211/util.c145
-rw-r--r--net/mac80211/wpa.c5
21 files changed, 874 insertions, 246 deletions
diff --git a/net/mac80211/aes_ccm.c b/net/mac80211/aes_ccm.c
index 7c7df475a401..ec24378caaaf 100644
--- a/net/mac80211/aes_ccm.c
+++ b/net/mac80211/aes_ccm.c
@@ -23,12 +23,13 @@ void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
23 u8 *data, size_t data_len, u8 *mic) 23 u8 *data, size_t data_len, u8 *mic)
24{ 24{
25 struct scatterlist assoc, pt, ct[2]; 25 struct scatterlist assoc, pt, ct[2];
26 struct {
27 struct aead_request req;
28 u8 priv[crypto_aead_reqsize(tfm)];
29 } aead_req;
30 26
31 memset(&aead_req, 0, sizeof(aead_req)); 27 char aead_req_data[sizeof(struct aead_request) +
28 crypto_aead_reqsize(tfm)]
29 __aligned(__alignof__(struct aead_request));
30 struct aead_request *aead_req = (void *) aead_req_data;
31
32 memset(aead_req, 0, sizeof(aead_req_data));
32 33
33 sg_init_one(&pt, data, data_len); 34 sg_init_one(&pt, data, data_len);
34 sg_init_one(&assoc, &aad[2], be16_to_cpup((__be16 *)aad)); 35 sg_init_one(&assoc, &aad[2], be16_to_cpup((__be16 *)aad));
@@ -36,23 +37,23 @@ void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
36 sg_set_buf(&ct[0], data, data_len); 37 sg_set_buf(&ct[0], data, data_len);
37 sg_set_buf(&ct[1], mic, IEEE80211_CCMP_MIC_LEN); 38 sg_set_buf(&ct[1], mic, IEEE80211_CCMP_MIC_LEN);
38 39
39 aead_request_set_tfm(&aead_req.req, tfm); 40 aead_request_set_tfm(aead_req, tfm);
40 aead_request_set_assoc(&aead_req.req, &assoc, assoc.length); 41 aead_request_set_assoc(aead_req, &assoc, assoc.length);
41 aead_request_set_crypt(&aead_req.req, &pt, ct, data_len, b_0); 42 aead_request_set_crypt(aead_req, &pt, ct, data_len, b_0);
42 43
43 crypto_aead_encrypt(&aead_req.req); 44 crypto_aead_encrypt(aead_req);
44} 45}
45 46
46int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, 47int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
47 u8 *data, size_t data_len, u8 *mic) 48 u8 *data, size_t data_len, u8 *mic)
48{ 49{
49 struct scatterlist assoc, pt, ct[2]; 50 struct scatterlist assoc, pt, ct[2];
50 struct { 51 char aead_req_data[sizeof(struct aead_request) +
51 struct aead_request req; 52 crypto_aead_reqsize(tfm)]
52 u8 priv[crypto_aead_reqsize(tfm)]; 53 __aligned(__alignof__(struct aead_request));
53 } aead_req; 54 struct aead_request *aead_req = (void *) aead_req_data;
54 55
55 memset(&aead_req, 0, sizeof(aead_req)); 56 memset(aead_req, 0, sizeof(aead_req_data));
56 57
57 sg_init_one(&pt, data, data_len); 58 sg_init_one(&pt, data, data_len);
58 sg_init_one(&assoc, &aad[2], be16_to_cpup((__be16 *)aad)); 59 sg_init_one(&assoc, &aad[2], be16_to_cpup((__be16 *)aad));
@@ -60,12 +61,12 @@ int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
60 sg_set_buf(&ct[0], data, data_len); 61 sg_set_buf(&ct[0], data, data_len);
61 sg_set_buf(&ct[1], mic, IEEE80211_CCMP_MIC_LEN); 62 sg_set_buf(&ct[1], mic, IEEE80211_CCMP_MIC_LEN);
62 63
63 aead_request_set_tfm(&aead_req.req, tfm); 64 aead_request_set_tfm(aead_req, tfm);
64 aead_request_set_assoc(&aead_req.req, &assoc, assoc.length); 65 aead_request_set_assoc(aead_req, &assoc, assoc.length);
65 aead_request_set_crypt(&aead_req.req, ct, &pt, 66 aead_request_set_crypt(aead_req, ct, &pt,
66 data_len + IEEE80211_CCMP_MIC_LEN, b_0); 67 data_len + IEEE80211_CCMP_MIC_LEN, b_0);
67 68
68 return crypto_aead_decrypt(&aead_req.req); 69 return crypto_aead_decrypt(aead_req);
69} 70}
70 71
71struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[]) 72struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[])
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index aaa59d719592..7b8d3cf89574 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -109,6 +109,15 @@ static int ieee80211_change_iface(struct wiphy *wiphy,
109static int ieee80211_start_p2p_device(struct wiphy *wiphy, 109static int ieee80211_start_p2p_device(struct wiphy *wiphy,
110 struct wireless_dev *wdev) 110 struct wireless_dev *wdev)
111{ 111{
112 struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
113 int ret;
114
115 mutex_lock(&sdata->local->chanctx_mtx);
116 ret = ieee80211_check_combinations(sdata, NULL, 0, 0);
117 mutex_unlock(&sdata->local->chanctx_mtx);
118 if (ret < 0)
119 return ret;
120
112 return ieee80211_do_open(wdev, true); 121 return ieee80211_do_open(wdev, true);
113} 122}
114 123
@@ -972,13 +981,13 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
972 sdata->needed_rx_chains = sdata->local->rx_chains; 981 sdata->needed_rx_chains = sdata->local->rx_chains;
973 982
974 mutex_lock(&local->mtx); 983 mutex_lock(&local->mtx);
975 sdata->radar_required = params->radar_required;
976 err = ieee80211_vif_use_channel(sdata, &params->chandef, 984 err = ieee80211_vif_use_channel(sdata, &params->chandef,
977 IEEE80211_CHANCTX_SHARED); 985 IEEE80211_CHANCTX_SHARED);
986 if (!err)
987 ieee80211_vif_copy_chanctx_to_vlans(sdata, false);
978 mutex_unlock(&local->mtx); 988 mutex_unlock(&local->mtx);
979 if (err) 989 if (err)
980 return err; 990 return err;
981 ieee80211_vif_copy_chanctx_to_vlans(sdata, false);
982 991
983 /* 992 /*
984 * Apply control port protocol, this allows us to 993 * Apply control port protocol, this allows us to
@@ -1131,8 +1140,8 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
1131 local->total_ps_buffered -= skb_queue_len(&sdata->u.ap.ps.bc_buf); 1140 local->total_ps_buffered -= skb_queue_len(&sdata->u.ap.ps.bc_buf);
1132 skb_queue_purge(&sdata->u.ap.ps.bc_buf); 1141 skb_queue_purge(&sdata->u.ap.ps.bc_buf);
1133 1142
1134 ieee80211_vif_copy_chanctx_to_vlans(sdata, true);
1135 mutex_lock(&local->mtx); 1143 mutex_lock(&local->mtx);
1144 ieee80211_vif_copy_chanctx_to_vlans(sdata, true);
1136 ieee80211_vif_release_channel(sdata); 1145 ieee80211_vif_release_channel(sdata);
1137 mutex_unlock(&local->mtx); 1146 mutex_unlock(&local->mtx);
1138 1147
@@ -1566,7 +1575,7 @@ static int ieee80211_change_station(struct wiphy *wiphy,
1566 1575
1567 if (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && 1576 if (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
1568 sta->sdata->u.vlan.sta) { 1577 sta->sdata->u.vlan.sta) {
1569 rcu_assign_pointer(sta->sdata->u.vlan.sta, NULL); 1578 RCU_INIT_POINTER(sta->sdata->u.vlan.sta, NULL);
1570 prev_4addr = true; 1579 prev_4addr = true;
1571 } 1580 }
1572 1581
@@ -2930,7 +2939,6 @@ static int ieee80211_start_radar_detection(struct wiphy *wiphy,
2930 /* whatever, but channel contexts should not complain about that one */ 2939 /* whatever, but channel contexts should not complain about that one */
2931 sdata->smps_mode = IEEE80211_SMPS_OFF; 2940 sdata->smps_mode = IEEE80211_SMPS_OFF;
2932 sdata->needed_rx_chains = local->rx_chains; 2941 sdata->needed_rx_chains = local->rx_chains;
2933 sdata->radar_required = true;
2934 2942
2935 err = ieee80211_vif_use_channel(sdata, chandef, 2943 err = ieee80211_vif_use_channel(sdata, chandef,
2936 IEEE80211_CHANCTX_SHARED); 2944 IEEE80211_CHANCTX_SHARED);
@@ -3217,7 +3225,7 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
3217{ 3225{
3218 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 3226 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
3219 struct ieee80211_local *local = sdata->local; 3227 struct ieee80211_local *local = sdata->local;
3220 struct ieee80211_chanctx_conf *chanctx_conf; 3228 struct ieee80211_chanctx_conf *conf;
3221 struct ieee80211_chanctx *chanctx; 3229 struct ieee80211_chanctx *chanctx;
3222 int err, num_chanctx, changed = 0; 3230 int err, num_chanctx, changed = 0;
3223 3231
@@ -3233,23 +3241,24 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
3233 &sdata->vif.bss_conf.chandef)) 3241 &sdata->vif.bss_conf.chandef))
3234 return -EINVAL; 3242 return -EINVAL;
3235 3243
3236 rcu_read_lock(); 3244 mutex_lock(&local->chanctx_mtx);
3237 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); 3245 conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
3238 if (!chanctx_conf) { 3246 lockdep_is_held(&local->chanctx_mtx));
3239 rcu_read_unlock(); 3247 if (!conf) {
3248 mutex_unlock(&local->chanctx_mtx);
3240 return -EBUSY; 3249 return -EBUSY;
3241 } 3250 }
3242 3251
3243 /* don't handle for multi-VIF cases */ 3252 /* don't handle for multi-VIF cases */
3244 chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf); 3253 chanctx = container_of(conf, struct ieee80211_chanctx, conf);
3245 if (chanctx->refcount > 1) { 3254 if (ieee80211_chanctx_refcount(local, chanctx) > 1) {
3246 rcu_read_unlock(); 3255 mutex_unlock(&local->chanctx_mtx);
3247 return -EBUSY; 3256 return -EBUSY;
3248 } 3257 }
3249 num_chanctx = 0; 3258 num_chanctx = 0;
3250 list_for_each_entry_rcu(chanctx, &local->chanctx_list, list) 3259 list_for_each_entry_rcu(chanctx, &local->chanctx_list, list)
3251 num_chanctx++; 3260 num_chanctx++;
3252 rcu_read_unlock(); 3261 mutex_unlock(&local->chanctx_mtx);
3253 3262
3254 if (num_chanctx > 1) 3263 if (num_chanctx > 1)
3255 return -EBUSY; 3264 return -EBUSY;
@@ -3949,6 +3958,21 @@ static int ieee80211_set_qos_map(struct wiphy *wiphy,
3949 return 0; 3958 return 0;
3950} 3959}
3951 3960
3961static int ieee80211_set_ap_chanwidth(struct wiphy *wiphy,
3962 struct net_device *dev,
3963 struct cfg80211_chan_def *chandef)
3964{
3965 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
3966 int ret;
3967 u32 changed = 0;
3968
3969 ret = ieee80211_vif_change_bandwidth(sdata, chandef, &changed);
3970 if (ret == 0)
3971 ieee80211_bss_info_change_notify(sdata, changed);
3972
3973 return ret;
3974}
3975
3952const struct cfg80211_ops mac80211_config_ops = { 3976const struct cfg80211_ops mac80211_config_ops = {
3953 .add_virtual_intf = ieee80211_add_iface, 3977 .add_virtual_intf = ieee80211_add_iface,
3954 .del_virtual_intf = ieee80211_del_iface, 3978 .del_virtual_intf = ieee80211_del_iface,
@@ -4029,4 +4053,5 @@ const struct cfg80211_ops mac80211_config_ops = {
4029 .start_radar_detection = ieee80211_start_radar_detection, 4053 .start_radar_detection = ieee80211_start_radar_detection,
4030 .channel_switch = ieee80211_channel_switch, 4054 .channel_switch = ieee80211_channel_switch,
4031 .set_qos_map = ieee80211_set_qos_map, 4055 .set_qos_map = ieee80211_set_qos_map,
4056 .set_ap_chanwidth = ieee80211_set_ap_chanwidth,
4032}; 4057};
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index 75b5dd2c9267..48e6d6f010cd 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -9,6 +9,170 @@
9#include "ieee80211_i.h" 9#include "ieee80211_i.h"
10#include "driver-ops.h" 10#include "driver-ops.h"
11 11
12static int ieee80211_chanctx_num_assigned(struct ieee80211_local *local,
13 struct ieee80211_chanctx *ctx)
14{
15 struct ieee80211_sub_if_data *sdata;
16 int num = 0;
17
18 lockdep_assert_held(&local->chanctx_mtx);
19
20 list_for_each_entry(sdata, &ctx->assigned_vifs, assigned_chanctx_list)
21 num++;
22
23 return num;
24}
25
26static int ieee80211_chanctx_num_reserved(struct ieee80211_local *local,
27 struct ieee80211_chanctx *ctx)
28{
29 struct ieee80211_sub_if_data *sdata;
30 int num = 0;
31
32 lockdep_assert_held(&local->chanctx_mtx);
33
34 list_for_each_entry(sdata, &ctx->reserved_vifs, reserved_chanctx_list)
35 num++;
36
37 return num;
38}
39
40int ieee80211_chanctx_refcount(struct ieee80211_local *local,
41 struct ieee80211_chanctx *ctx)
42{
43 return ieee80211_chanctx_num_assigned(local, ctx) +
44 ieee80211_chanctx_num_reserved(local, ctx);
45}
46
47static int ieee80211_num_chanctx(struct ieee80211_local *local)
48{
49 struct ieee80211_chanctx *ctx;
50 int num = 0;
51
52 lockdep_assert_held(&local->chanctx_mtx);
53
54 list_for_each_entry(ctx, &local->chanctx_list, list)
55 num++;
56
57 return num;
58}
59
60static bool ieee80211_can_create_new_chanctx(struct ieee80211_local *local)
61{
62 lockdep_assert_held(&local->chanctx_mtx);
63 return ieee80211_num_chanctx(local) < ieee80211_max_num_channels(local);
64}
65
66static const struct cfg80211_chan_def *
67ieee80211_chanctx_reserved_chandef(struct ieee80211_local *local,
68 struct ieee80211_chanctx *ctx,
69 const struct cfg80211_chan_def *compat)
70{
71 struct ieee80211_sub_if_data *sdata;
72
73 lockdep_assert_held(&local->chanctx_mtx);
74
75 list_for_each_entry(sdata, &ctx->reserved_vifs,
76 reserved_chanctx_list) {
77 if (!compat)
78 compat = &sdata->reserved_chandef;
79
80 compat = cfg80211_chandef_compatible(&sdata->reserved_chandef,
81 compat);
82 if (!compat)
83 break;
84 }
85
86 return compat;
87}
88
89static const struct cfg80211_chan_def *
90ieee80211_chanctx_non_reserved_chandef(struct ieee80211_local *local,
91 struct ieee80211_chanctx *ctx,
92 const struct cfg80211_chan_def *compat)
93{
94 struct ieee80211_sub_if_data *sdata;
95
96 lockdep_assert_held(&local->chanctx_mtx);
97
98 list_for_each_entry(sdata, &ctx->assigned_vifs,
99 assigned_chanctx_list) {
100 if (sdata->reserved_chanctx != NULL)
101 continue;
102
103 if (!compat)
104 compat = &sdata->vif.bss_conf.chandef;
105
106 compat = cfg80211_chandef_compatible(
107 &sdata->vif.bss_conf.chandef, compat);
108 if (!compat)
109 break;
110 }
111
112 return compat;
113}
114
115static const struct cfg80211_chan_def *
116ieee80211_chanctx_combined_chandef(struct ieee80211_local *local,
117 struct ieee80211_chanctx *ctx,
118 const struct cfg80211_chan_def *compat)
119{
120 lockdep_assert_held(&local->chanctx_mtx);
121
122 compat = ieee80211_chanctx_reserved_chandef(local, ctx, compat);
123 if (!compat)
124 return NULL;
125
126 compat = ieee80211_chanctx_non_reserved_chandef(local, ctx, compat);
127 if (!compat)
128 return NULL;
129
130 return compat;
131}
132
133static bool
134ieee80211_chanctx_can_reserve_chandef(struct ieee80211_local *local,
135 struct ieee80211_chanctx *ctx,
136 const struct cfg80211_chan_def *def)
137{
138 lockdep_assert_held(&local->chanctx_mtx);
139
140 if (ieee80211_chanctx_combined_chandef(local, ctx, def))
141 return true;
142
143 if (!list_empty(&ctx->reserved_vifs) &&
144 ieee80211_chanctx_reserved_chandef(local, ctx, def))
145 return true;
146
147 return false;
148}
149
150static struct ieee80211_chanctx *
151ieee80211_find_reservation_chanctx(struct ieee80211_local *local,
152 const struct cfg80211_chan_def *chandef,
153 enum ieee80211_chanctx_mode mode)
154{
155 struct ieee80211_chanctx *ctx;
156
157 lockdep_assert_held(&local->chanctx_mtx);
158
159 if (mode == IEEE80211_CHANCTX_EXCLUSIVE)
160 return NULL;
161
162 list_for_each_entry(ctx, &local->chanctx_list, list) {
163 if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE)
164 continue;
165
166 if (!ieee80211_chanctx_can_reserve_chandef(local, ctx,
167 chandef))
168 continue;
169
170 return ctx;
171 }
172
173 return NULL;
174}
175
12static enum nl80211_chan_width ieee80211_get_sta_bw(struct ieee80211_sta *sta) 176static enum nl80211_chan_width ieee80211_get_sta_bw(struct ieee80211_sta *sta)
13{ 177{
14 switch (sta->bandwidth) { 178 switch (sta->bandwidth) {
@@ -190,6 +354,11 @@ ieee80211_find_chanctx(struct ieee80211_local *local,
190 if (!compat) 354 if (!compat)
191 continue; 355 continue;
192 356
357 compat = ieee80211_chanctx_reserved_chandef(local, ctx,
358 compat);
359 if (!compat)
360 continue;
361
193 ieee80211_change_chanctx(local, ctx, compat); 362 ieee80211_change_chanctx(local, ctx, compat);
194 363
195 return ctx; 364 return ctx;
@@ -217,62 +386,91 @@ static bool ieee80211_is_radar_required(struct ieee80211_local *local)
217} 386}
218 387
219static struct ieee80211_chanctx * 388static struct ieee80211_chanctx *
220ieee80211_new_chanctx(struct ieee80211_local *local, 389ieee80211_alloc_chanctx(struct ieee80211_local *local,
221 const struct cfg80211_chan_def *chandef, 390 const struct cfg80211_chan_def *chandef,
222 enum ieee80211_chanctx_mode mode) 391 enum ieee80211_chanctx_mode mode)
223{ 392{
224 struct ieee80211_chanctx *ctx; 393 struct ieee80211_chanctx *ctx;
225 u32 changed;
226 int err;
227 394
228 lockdep_assert_held(&local->chanctx_mtx); 395 lockdep_assert_held(&local->chanctx_mtx);
229 396
230 ctx = kzalloc(sizeof(*ctx) + local->hw.chanctx_data_size, GFP_KERNEL); 397 ctx = kzalloc(sizeof(*ctx) + local->hw.chanctx_data_size, GFP_KERNEL);
231 if (!ctx) 398 if (!ctx)
232 return ERR_PTR(-ENOMEM); 399 return NULL;
233 400
401 INIT_LIST_HEAD(&ctx->assigned_vifs);
402 INIT_LIST_HEAD(&ctx->reserved_vifs);
234 ctx->conf.def = *chandef; 403 ctx->conf.def = *chandef;
235 ctx->conf.rx_chains_static = 1; 404 ctx->conf.rx_chains_static = 1;
236 ctx->conf.rx_chains_dynamic = 1; 405 ctx->conf.rx_chains_dynamic = 1;
237 ctx->mode = mode; 406 ctx->mode = mode;
238 ctx->conf.radar_enabled = ieee80211_is_radar_required(local); 407 ctx->conf.radar_enabled = ieee80211_is_radar_required(local);
239 ieee80211_recalc_chanctx_min_def(local, ctx); 408 ieee80211_recalc_chanctx_min_def(local, ctx);
409
410 return ctx;
411}
412
413static int ieee80211_add_chanctx(struct ieee80211_local *local,
414 struct ieee80211_chanctx *ctx)
415{
416 u32 changed;
417 int err;
418
419 lockdep_assert_held(&local->mtx);
420 lockdep_assert_held(&local->chanctx_mtx);
421
240 if (!local->use_chanctx) 422 if (!local->use_chanctx)
241 local->hw.conf.radar_enabled = ctx->conf.radar_enabled; 423 local->hw.conf.radar_enabled = ctx->conf.radar_enabled;
242 424
243 /* we hold the mutex to prevent idle from changing */
244 lockdep_assert_held(&local->mtx);
245 /* turn idle off *before* setting channel -- some drivers need that */ 425 /* turn idle off *before* setting channel -- some drivers need that */
246 changed = ieee80211_idle_off(local); 426 changed = ieee80211_idle_off(local);
247 if (changed) 427 if (changed)
248 ieee80211_hw_config(local, changed); 428 ieee80211_hw_config(local, changed);
249 429
250 if (!local->use_chanctx) { 430 if (!local->use_chanctx) {
251 local->_oper_chandef = *chandef; 431 local->_oper_chandef = ctx->conf.def;
252 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); 432 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
253 } else { 433 } else {
254 err = drv_add_chanctx(local, ctx); 434 err = drv_add_chanctx(local, ctx);
255 if (err) { 435 if (err) {
256 kfree(ctx);
257 ieee80211_recalc_idle(local); 436 ieee80211_recalc_idle(local);
258 return ERR_PTR(err); 437 return err;
259 } 438 }
260 } 439 }
261 440
262 /* and keep the mutex held until the new chanctx is on the list */ 441 return 0;
263 list_add_rcu(&ctx->list, &local->chanctx_list); 442}
443
444static struct ieee80211_chanctx *
445ieee80211_new_chanctx(struct ieee80211_local *local,
446 const struct cfg80211_chan_def *chandef,
447 enum ieee80211_chanctx_mode mode)
448{
449 struct ieee80211_chanctx *ctx;
450 int err;
451
452 lockdep_assert_held(&local->mtx);
453 lockdep_assert_held(&local->chanctx_mtx);
264 454
455 ctx = ieee80211_alloc_chanctx(local, chandef, mode);
456 if (!ctx)
457 return ERR_PTR(-ENOMEM);
458
459 err = ieee80211_add_chanctx(local, ctx);
460 if (err) {
461 kfree(ctx);
462 return ERR_PTR(err);
463 }
464
465 list_add_rcu(&ctx->list, &local->chanctx_list);
265 return ctx; 466 return ctx;
266} 467}
267 468
268static void ieee80211_free_chanctx(struct ieee80211_local *local, 469static void ieee80211_del_chanctx(struct ieee80211_local *local,
269 struct ieee80211_chanctx *ctx) 470 struct ieee80211_chanctx *ctx)
270{ 471{
271 bool check_single_channel = false;
272 lockdep_assert_held(&local->chanctx_mtx); 472 lockdep_assert_held(&local->chanctx_mtx);
273 473
274 WARN_ON_ONCE(ctx->refcount != 0);
275
276 if (!local->use_chanctx) { 474 if (!local->use_chanctx) {
277 struct cfg80211_chan_def *chandef = &local->_oper_chandef; 475 struct cfg80211_chan_def *chandef = &local->_oper_chandef;
278 chandef->width = NL80211_CHAN_WIDTH_20_NOHT; 476 chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
@@ -282,8 +480,9 @@ static void ieee80211_free_chanctx(struct ieee80211_local *local,
282 /* NOTE: Disabling radar is only valid here for 480 /* NOTE: Disabling radar is only valid here for
283 * single channel context. To be sure, check it ... 481 * single channel context. To be sure, check it ...
284 */ 482 */
285 if (local->hw.conf.radar_enabled) 483 WARN_ON(local->hw.conf.radar_enabled &&
286 check_single_channel = true; 484 !list_empty(&local->chanctx_list));
485
287 local->hw.conf.radar_enabled = false; 486 local->hw.conf.radar_enabled = false;
288 487
289 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); 488 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
@@ -291,39 +490,19 @@ static void ieee80211_free_chanctx(struct ieee80211_local *local,
291 drv_remove_chanctx(local, ctx); 490 drv_remove_chanctx(local, ctx);
292 } 491 }
293 492
294 list_del_rcu(&ctx->list);
295 kfree_rcu(ctx, rcu_head);
296
297 /* throw a warning if this wasn't the only channel context. */
298 WARN_ON(check_single_channel && !list_empty(&local->chanctx_list));
299
300 ieee80211_recalc_idle(local); 493 ieee80211_recalc_idle(local);
301} 494}
302 495
303static int ieee80211_assign_vif_chanctx(struct ieee80211_sub_if_data *sdata, 496static void ieee80211_free_chanctx(struct ieee80211_local *local,
304 struct ieee80211_chanctx *ctx) 497 struct ieee80211_chanctx *ctx)
305{ 498{
306 struct ieee80211_local *local = sdata->local;
307 int ret;
308
309 lockdep_assert_held(&local->chanctx_mtx); 499 lockdep_assert_held(&local->chanctx_mtx);
310 500
311 ret = drv_assign_vif_chanctx(local, sdata, ctx); 501 WARN_ON_ONCE(ieee80211_chanctx_refcount(local, ctx) != 0);
312 if (ret)
313 return ret;
314
315 rcu_assign_pointer(sdata->vif.chanctx_conf, &ctx->conf);
316 ctx->refcount++;
317
318 ieee80211_recalc_txpower(sdata);
319 ieee80211_recalc_chanctx_min_def(local, ctx);
320 sdata->vif.bss_conf.idle = false;
321 502
322 if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE && 503 list_del_rcu(&ctx->list);
323 sdata->vif.type != NL80211_IFTYPE_MONITOR) 504 ieee80211_del_chanctx(local, ctx);
324 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE); 505 kfree_rcu(ctx, rcu_head);
325
326 return 0;
327} 506}
328 507
329static void ieee80211_recalc_chanctx_chantype(struct ieee80211_local *local, 508static void ieee80211_recalc_chanctx_chantype(struct ieee80211_local *local,
@@ -384,30 +563,58 @@ static void ieee80211_recalc_radar_chanctx(struct ieee80211_local *local,
384 drv_change_chanctx(local, chanctx, IEEE80211_CHANCTX_CHANGE_RADAR); 563 drv_change_chanctx(local, chanctx, IEEE80211_CHANCTX_CHANGE_RADAR);
385} 564}
386 565
387static void ieee80211_unassign_vif_chanctx(struct ieee80211_sub_if_data *sdata, 566static int ieee80211_assign_vif_chanctx(struct ieee80211_sub_if_data *sdata,
388 struct ieee80211_chanctx *ctx) 567 struct ieee80211_chanctx *new_ctx)
389{ 568{
390 struct ieee80211_local *local = sdata->local; 569 struct ieee80211_local *local = sdata->local;
570 struct ieee80211_chanctx_conf *conf;
571 struct ieee80211_chanctx *curr_ctx = NULL;
572 int ret = 0;
391 573
392 lockdep_assert_held(&local->chanctx_mtx); 574 conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
575 lockdep_is_held(&local->chanctx_mtx));
393 576
394 ctx->refcount--; 577 if (conf) {
395 rcu_assign_pointer(sdata->vif.chanctx_conf, NULL); 578 curr_ctx = container_of(conf, struct ieee80211_chanctx, conf);
396 579
397 sdata->vif.bss_conf.idle = true; 580 drv_unassign_vif_chanctx(local, sdata, curr_ctx);
581 conf = NULL;
582 list_del(&sdata->assigned_chanctx_list);
583 }
398 584
399 if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE && 585 if (new_ctx) {
400 sdata->vif.type != NL80211_IFTYPE_MONITOR) 586 ret = drv_assign_vif_chanctx(local, sdata, new_ctx);
401 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE); 587 if (ret)
588 goto out;
402 589
403 drv_unassign_vif_chanctx(local, sdata, ctx); 590 conf = &new_ctx->conf;
591 list_add(&sdata->assigned_chanctx_list,
592 &new_ctx->assigned_vifs);
593 }
404 594
405 if (ctx->refcount > 0) { 595out:
406 ieee80211_recalc_chanctx_chantype(sdata->local, ctx); 596 rcu_assign_pointer(sdata->vif.chanctx_conf, conf);
407 ieee80211_recalc_smps_chanctx(local, ctx); 597
408 ieee80211_recalc_radar_chanctx(local, ctx); 598 sdata->vif.bss_conf.idle = !conf;
409 ieee80211_recalc_chanctx_min_def(local, ctx); 599
600 if (curr_ctx && ieee80211_chanctx_num_assigned(local, curr_ctx) > 0) {
601 ieee80211_recalc_chanctx_chantype(local, curr_ctx);
602 ieee80211_recalc_smps_chanctx(local, curr_ctx);
603 ieee80211_recalc_radar_chanctx(local, curr_ctx);
604 ieee80211_recalc_chanctx_min_def(local, curr_ctx);
410 } 605 }
606
607 if (new_ctx && ieee80211_chanctx_num_assigned(local, new_ctx) > 0) {
608 ieee80211_recalc_txpower(sdata);
609 ieee80211_recalc_chanctx_min_def(local, new_ctx);
610 }
611
612 if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
613 sdata->vif.type != NL80211_IFTYPE_MONITOR)
614 ieee80211_bss_info_change_notify(sdata,
615 BSS_CHANGED_IDLE);
616
617 return ret;
411} 618}
412 619
413static void __ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata) 620static void __ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
@@ -425,8 +632,11 @@ static void __ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
425 632
426 ctx = container_of(conf, struct ieee80211_chanctx, conf); 633 ctx = container_of(conf, struct ieee80211_chanctx, conf);
427 634
428 ieee80211_unassign_vif_chanctx(sdata, ctx); 635 if (sdata->reserved_chanctx)
429 if (ctx->refcount == 0) 636 ieee80211_vif_unreserve_chanctx(sdata);
637
638 ieee80211_assign_vif_chanctx(sdata, NULL);
639 if (ieee80211_chanctx_refcount(local, ctx) == 0)
430 ieee80211_free_chanctx(local, ctx); 640 ieee80211_free_chanctx(local, ctx);
431} 641}
432 642
@@ -526,6 +736,7 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
526{ 736{
527 struct ieee80211_local *local = sdata->local; 737 struct ieee80211_local *local = sdata->local;
528 struct ieee80211_chanctx *ctx; 738 struct ieee80211_chanctx *ctx;
739 u8 radar_detect_width = 0;
529 int ret; 740 int ret;
530 741
531 lockdep_assert_held(&local->mtx); 742 lockdep_assert_held(&local->mtx);
@@ -533,6 +744,22 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
533 WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev)); 744 WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev));
534 745
535 mutex_lock(&local->chanctx_mtx); 746 mutex_lock(&local->chanctx_mtx);
747
748 ret = cfg80211_chandef_dfs_required(local->hw.wiphy,
749 chandef,
750 sdata->wdev.iftype);
751 if (ret < 0)
752 goto out;
753 if (ret > 0)
754 radar_detect_width = BIT(chandef->width);
755
756 sdata->radar_required = ret;
757
758 ret = ieee80211_check_combinations(sdata, chandef, mode,
759 radar_detect_width);
760 if (ret < 0)
761 goto out;
762
536 __ieee80211_vif_release_channel(sdata); 763 __ieee80211_vif_release_channel(sdata);
537 764
538 ctx = ieee80211_find_chanctx(local, chandef, mode); 765 ctx = ieee80211_find_chanctx(local, chandef, mode);
@@ -548,7 +775,7 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
548 ret = ieee80211_assign_vif_chanctx(sdata, ctx); 775 ret = ieee80211_assign_vif_chanctx(sdata, ctx);
549 if (ret) { 776 if (ret) {
550 /* if assign fails refcount stays the same */ 777 /* if assign fails refcount stays the same */
551 if (ctx->refcount == 0) 778 if (ieee80211_chanctx_refcount(local, ctx) == 0)
552 ieee80211_free_chanctx(local, ctx); 779 ieee80211_free_chanctx(local, ctx);
553 goto out; 780 goto out;
554 } 781 }
@@ -560,15 +787,47 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
560 return ret; 787 return ret;
561} 788}
562 789
790static int __ieee80211_vif_change_channel(struct ieee80211_sub_if_data *sdata,
791 struct ieee80211_chanctx *ctx,
792 u32 *changed)
793{
794 struct ieee80211_local *local = sdata->local;
795 const struct cfg80211_chan_def *chandef = &sdata->csa_chandef;
796 u32 chanctx_changed = 0;
797
798 if (!cfg80211_chandef_usable(sdata->local->hw.wiphy, chandef,
799 IEEE80211_CHAN_DISABLED))
800 return -EINVAL;
801
802 if (ieee80211_chanctx_refcount(local, ctx) != 1)
803 return -EINVAL;
804
805 if (sdata->vif.bss_conf.chandef.width != chandef->width) {
806 chanctx_changed = IEEE80211_CHANCTX_CHANGE_WIDTH;
807 *changed |= BSS_CHANGED_BANDWIDTH;
808 }
809
810 sdata->vif.bss_conf.chandef = *chandef;
811 ctx->conf.def = *chandef;
812
813 chanctx_changed |= IEEE80211_CHANCTX_CHANGE_CHANNEL;
814 drv_change_chanctx(local, ctx, chanctx_changed);
815
816 ieee80211_recalc_chanctx_chantype(local, ctx);
817 ieee80211_recalc_smps_chanctx(local, ctx);
818 ieee80211_recalc_radar_chanctx(local, ctx);
819 ieee80211_recalc_chanctx_min_def(local, ctx);
820
821 return 0;
822}
823
563int ieee80211_vif_change_channel(struct ieee80211_sub_if_data *sdata, 824int ieee80211_vif_change_channel(struct ieee80211_sub_if_data *sdata,
564 u32 *changed) 825 u32 *changed)
565{ 826{
566 struct ieee80211_local *local = sdata->local; 827 struct ieee80211_local *local = sdata->local;
567 struct ieee80211_chanctx_conf *conf; 828 struct ieee80211_chanctx_conf *conf;
568 struct ieee80211_chanctx *ctx; 829 struct ieee80211_chanctx *ctx;
569 const struct cfg80211_chan_def *chandef = &sdata->csa_chandef;
570 int ret; 830 int ret;
571 u32 chanctx_changed = 0;
572 831
573 lockdep_assert_held(&local->mtx); 832 lockdep_assert_held(&local->mtx);
574 833
@@ -576,11 +835,94 @@ int ieee80211_vif_change_channel(struct ieee80211_sub_if_data *sdata,
576 if (WARN_ON(!sdata->vif.csa_active)) 835 if (WARN_ON(!sdata->vif.csa_active))
577 return -EINVAL; 836 return -EINVAL;
578 837
579 if (!cfg80211_chandef_usable(sdata->local->hw.wiphy, chandef, 838 mutex_lock(&local->chanctx_mtx);
580 IEEE80211_CHAN_DISABLED)) 839 conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
840 lockdep_is_held(&local->chanctx_mtx));
841 if (!conf) {
842 ret = -EINVAL;
843 goto out;
844 }
845
846 ctx = container_of(conf, struct ieee80211_chanctx, conf);
847
848 ret = __ieee80211_vif_change_channel(sdata, ctx, changed);
849 out:
850 mutex_unlock(&local->chanctx_mtx);
851 return ret;
852}
853
854static void
855__ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata,
856 bool clear)
857{
858 struct ieee80211_local *local = sdata->local;
859 struct ieee80211_sub_if_data *vlan;
860 struct ieee80211_chanctx_conf *conf;
861
862 if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP))
863 return;
864
865 lockdep_assert_held(&local->mtx);
866
867 /* Check that conf exists, even when clearing this function
868 * must be called with the AP's channel context still there
869 * as it would otherwise cause VLANs to have an invalid
870 * channel context pointer for a while, possibly pointing
871 * to a channel context that has already been freed.
872 */
873 conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
874 lockdep_is_held(&local->chanctx_mtx));
875 WARN_ON(!conf);
876
877 if (clear)
878 conf = NULL;
879
880 list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
881 rcu_assign_pointer(vlan->vif.chanctx_conf, conf);
882}
883
884void ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata,
885 bool clear)
886{
887 struct ieee80211_local *local = sdata->local;
888
889 mutex_lock(&local->chanctx_mtx);
890
891 __ieee80211_vif_copy_chanctx_to_vlans(sdata, clear);
892
893 mutex_unlock(&local->chanctx_mtx);
894}
895
896int ieee80211_vif_unreserve_chanctx(struct ieee80211_sub_if_data *sdata)
897{
898 struct ieee80211_chanctx *ctx = sdata->reserved_chanctx;
899
900 lockdep_assert_held(&sdata->local->chanctx_mtx);
901
902 if (WARN_ON(!ctx))
581 return -EINVAL; 903 return -EINVAL;
582 904
905 list_del(&sdata->reserved_chanctx_list);
906 sdata->reserved_chanctx = NULL;
907
908 if (ieee80211_chanctx_refcount(sdata->local, ctx) == 0)
909 ieee80211_free_chanctx(sdata->local, ctx);
910
911 return 0;
912}
913
914int ieee80211_vif_reserve_chanctx(struct ieee80211_sub_if_data *sdata,
915 const struct cfg80211_chan_def *chandef,
916 enum ieee80211_chanctx_mode mode,
917 bool radar_required)
918{
919 struct ieee80211_local *local = sdata->local;
920 struct ieee80211_chanctx_conf *conf;
921 struct ieee80211_chanctx *new_ctx, *curr_ctx;
922 int ret = 0;
923
583 mutex_lock(&local->chanctx_mtx); 924 mutex_lock(&local->chanctx_mtx);
925
584 conf = rcu_dereference_protected(sdata->vif.chanctx_conf, 926 conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
585 lockdep_is_held(&local->chanctx_mtx)); 927 lockdep_is_held(&local->chanctx_mtx));
586 if (!conf) { 928 if (!conf) {
@@ -588,30 +930,108 @@ int ieee80211_vif_change_channel(struct ieee80211_sub_if_data *sdata,
588 goto out; 930 goto out;
589 } 931 }
590 932
591 ctx = container_of(conf, struct ieee80211_chanctx, conf); 933 curr_ctx = container_of(conf, struct ieee80211_chanctx, conf);
592 if (ctx->refcount != 1) { 934
935 new_ctx = ieee80211_find_reservation_chanctx(local, chandef, mode);
936 if (!new_ctx) {
937 if (ieee80211_chanctx_refcount(local, curr_ctx) == 1 &&
938 (local->hw.flags & IEEE80211_HW_CHANGE_RUNNING_CHANCTX)) {
939 /* if we're the only users of the chanctx and
940 * the driver supports changing a running
941 * context, reserve our current context
942 */
943 new_ctx = curr_ctx;
944 } else if (ieee80211_can_create_new_chanctx(local)) {
945 /* create a new context and reserve it */
946 new_ctx = ieee80211_new_chanctx(local, chandef, mode);
947 if (IS_ERR(new_ctx)) {
948 ret = PTR_ERR(new_ctx);
949 goto out;
950 }
951 } else {
952 ret = -EBUSY;
953 goto out;
954 }
955 }
956
957 list_add(&sdata->reserved_chanctx_list, &new_ctx->reserved_vifs);
958 sdata->reserved_chanctx = new_ctx;
959 sdata->reserved_chandef = *chandef;
960 sdata->reserved_radar_required = radar_required;
961out:
962 mutex_unlock(&local->chanctx_mtx);
963 return ret;
964}
965
966int ieee80211_vif_use_reserved_context(struct ieee80211_sub_if_data *sdata,
967 u32 *changed)
968{
969 struct ieee80211_local *local = sdata->local;
970 struct ieee80211_chanctx *ctx;
971 struct ieee80211_chanctx *old_ctx;
972 struct ieee80211_chanctx_conf *conf;
973 int ret;
974 u32 tmp_changed = *changed;
975
976 /* TODO: need to recheck if the chandef is usable etc.? */
977
978 lockdep_assert_held(&local->mtx);
979
980 mutex_lock(&local->chanctx_mtx);
981
982 ctx = sdata->reserved_chanctx;
983 if (WARN_ON(!ctx)) {
593 ret = -EINVAL; 984 ret = -EINVAL;
594 goto out; 985 goto out;
595 } 986 }
596 987
597 if (sdata->vif.bss_conf.chandef.width != chandef->width) { 988 conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
598 chanctx_changed = IEEE80211_CHANCTX_CHANGE_WIDTH; 989 lockdep_is_held(&local->chanctx_mtx));
599 *changed |= BSS_CHANGED_BANDWIDTH; 990 if (!conf) {
991 ret = -EINVAL;
992 goto out;
600 } 993 }
601 994
602 sdata->vif.bss_conf.chandef = *chandef; 995 old_ctx = container_of(conf, struct ieee80211_chanctx, conf);
603 ctx->conf.def = *chandef;
604 996
605 chanctx_changed |= IEEE80211_CHANCTX_CHANGE_CHANNEL; 997 if (sdata->vif.bss_conf.chandef.width != sdata->reserved_chandef.width)
606 drv_change_chanctx(local, ctx, chanctx_changed); 998 tmp_changed |= BSS_CHANGED_BANDWIDTH;
999
1000 sdata->vif.bss_conf.chandef = sdata->reserved_chandef;
1001
1002 /* unref our reservation */
1003 sdata->reserved_chanctx = NULL;
1004 sdata->radar_required = sdata->reserved_radar_required;
1005 list_del(&sdata->reserved_chanctx_list);
1006
1007 if (old_ctx == ctx) {
1008 /* This is our own context, just change it */
1009 ret = __ieee80211_vif_change_channel(sdata, old_ctx,
1010 &tmp_changed);
1011 if (ret)
1012 goto out;
1013 } else {
1014 ret = ieee80211_assign_vif_chanctx(sdata, ctx);
1015 if (ieee80211_chanctx_refcount(local, old_ctx) == 0)
1016 ieee80211_free_chanctx(local, old_ctx);
1017 if (ret) {
1018 /* if assign fails refcount stays the same */
1019 if (ieee80211_chanctx_refcount(local, ctx) == 0)
1020 ieee80211_free_chanctx(local, ctx);
1021 goto out;
1022 }
1023
1024 if (sdata->vif.type == NL80211_IFTYPE_AP)
1025 __ieee80211_vif_copy_chanctx_to_vlans(sdata, false);
1026 }
1027
1028 *changed = tmp_changed;
607 1029
608 ieee80211_recalc_chanctx_chantype(local, ctx); 1030 ieee80211_recalc_chanctx_chantype(local, ctx);
609 ieee80211_recalc_smps_chanctx(local, ctx); 1031 ieee80211_recalc_smps_chanctx(local, ctx);
610 ieee80211_recalc_radar_chanctx(local, ctx); 1032 ieee80211_recalc_radar_chanctx(local, ctx);
611 ieee80211_recalc_chanctx_min_def(local, ctx); 1033 ieee80211_recalc_chanctx_min_def(local, ctx);
612 1034out:
613 ret = 0;
614 out:
615 mutex_unlock(&local->chanctx_mtx); 1035 mutex_unlock(&local->chanctx_mtx);
616 return ret; 1036 return ret;
617} 1037}
@@ -695,40 +1115,6 @@ void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata)
695 mutex_unlock(&local->chanctx_mtx); 1115 mutex_unlock(&local->chanctx_mtx);
696} 1116}
697 1117
698void ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata,
699 bool clear)
700{
701 struct ieee80211_local *local = sdata->local;
702 struct ieee80211_sub_if_data *vlan;
703 struct ieee80211_chanctx_conf *conf;
704
705 ASSERT_RTNL();
706
707 if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP))
708 return;
709
710 mutex_lock(&local->chanctx_mtx);
711
712 /*
713 * Check that conf exists, even when clearing this function
714 * must be called with the AP's channel context still there
715 * as it would otherwise cause VLANs to have an invalid
716 * channel context pointer for a while, possibly pointing
717 * to a channel context that has already been freed.
718 */
719 conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
720 lockdep_is_held(&local->chanctx_mtx));
721 WARN_ON(!conf);
722
723 if (clear)
724 conf = NULL;
725
726 list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
727 rcu_assign_pointer(vlan->vif.chanctx_conf, conf);
728
729 mutex_unlock(&local->chanctx_mtx);
730}
731
732void ieee80211_iter_chan_contexts_atomic( 1118void ieee80211_iter_chan_contexts_atomic(
733 struct ieee80211_hw *hw, 1119 struct ieee80211_hw *hw,
734 void (*iter)(struct ieee80211_hw *hw, 1120 void (*iter)(struct ieee80211_hw *hw,
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index fa16e54980a1..0e963bc1ceac 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -128,7 +128,7 @@ static ssize_t sta_tx_latency_stat_write(struct file *file,
128 if (!strcmp(buf, TX_LATENCY_DISABLED)) { 128 if (!strcmp(buf, TX_LATENCY_DISABLED)) {
129 if (!tx_latency) 129 if (!tx_latency)
130 goto unlock; 130 goto unlock;
131 rcu_assign_pointer(local->tx_latency, NULL); 131 RCU_INIT_POINTER(local->tx_latency, NULL);
132 synchronize_rcu(); 132 synchronize_rcu();
133 kfree(tx_latency); 133 kfree(tx_latency);
134 goto unlock; 134 goto unlock;
diff --git a/net/mac80211/debugfs.h b/net/mac80211/debugfs.h
index 214ed4ecd739..60c35afee29d 100644
--- a/net/mac80211/debugfs.h
+++ b/net/mac80211/debugfs.h
@@ -1,6 +1,8 @@
1#ifndef __MAC80211_DEBUGFS_H 1#ifndef __MAC80211_DEBUGFS_H
2#define __MAC80211_DEBUGFS_H 2#define __MAC80211_DEBUGFS_H
3 3
4#include "ieee80211_i.h"
5
4#ifdef CONFIG_MAC80211_DEBUGFS 6#ifdef CONFIG_MAC80211_DEBUGFS
5void debugfs_hw_add(struct ieee80211_local *local); 7void debugfs_hw_add(struct ieee80211_local *local);
6int __printf(4, 5) mac80211_format_buffer(char __user *userbuf, size_t count, 8int __printf(4, 5) mac80211_format_buffer(char __user *userbuf, size_t count,
diff --git a/net/mac80211/debugfs_netdev.h b/net/mac80211/debugfs_netdev.h
index 79025e79f4d6..9f5501a9a795 100644
--- a/net/mac80211/debugfs_netdev.h
+++ b/net/mac80211/debugfs_netdev.h
@@ -3,6 +3,8 @@
3#ifndef __IEEE80211_DEBUGFS_NETDEV_H 3#ifndef __IEEE80211_DEBUGFS_NETDEV_H
4#define __IEEE80211_DEBUGFS_NETDEV_H 4#define __IEEE80211_DEBUGFS_NETDEV_H
5 5
6#include "ieee80211_i.h"
7
6#ifdef CONFIG_MAC80211_DEBUGFS 8#ifdef CONFIG_MAC80211_DEBUGFS
7void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata); 9void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata);
8void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata); 10void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata);
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index fc689f5d971e..5331582a2c81 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -726,13 +726,19 @@ static inline void drv_rfkill_poll(struct ieee80211_local *local)
726} 726}
727 727
728static inline void drv_flush(struct ieee80211_local *local, 728static inline void drv_flush(struct ieee80211_local *local,
729 struct ieee80211_sub_if_data *sdata,
729 u32 queues, bool drop) 730 u32 queues, bool drop)
730{ 731{
732 struct ieee80211_vif *vif = sdata ? &sdata->vif : NULL;
733
731 might_sleep(); 734 might_sleep();
732 735
736 if (sdata)
737 check_sdata_in_driver(sdata);
738
733 trace_drv_flush(local, queues, drop); 739 trace_drv_flush(local, queues, drop);
734 if (local->ops->flush) 740 if (local->ops->flush)
735 local->ops->flush(&local->hw, queues, drop); 741 local->ops->flush(&local->hw, vif, queues, drop);
736 trace_drv_return_void(local); 742 trace_drv_return_void(local);
737} 743}
738 744
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
index c150b68436d7..15702ff64a4c 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -31,6 +31,18 @@ static void __check_htcap_disable(struct ieee80211_ht_cap *ht_capa,
31 } 31 }
32} 32}
33 33
34static void __check_htcap_enable(struct ieee80211_ht_cap *ht_capa,
35 struct ieee80211_ht_cap *ht_capa_mask,
36 struct ieee80211_sta_ht_cap *ht_cap,
37 u16 flag)
38{
39 __le16 le_flag = cpu_to_le16(flag);
40
41 if ((ht_capa_mask->cap_info & le_flag) &&
42 (ht_capa->cap_info & le_flag))
43 ht_cap->cap |= flag;
44}
45
34void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata, 46void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
35 struct ieee80211_sta_ht_cap *ht_cap) 47 struct ieee80211_sta_ht_cap *ht_cap)
36{ 48{
@@ -59,7 +71,7 @@ void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
59 smask = (u8 *)(&ht_capa_mask->mcs.rx_mask); 71 smask = (u8 *)(&ht_capa_mask->mcs.rx_mask);
60 72
61 /* NOTE: If you add more over-rides here, update register_hw 73 /* NOTE: If you add more over-rides here, update register_hw
62 * ht_capa_mod_msk logic in main.c as well. 74 * ht_capa_mod_mask logic in main.c as well.
63 * And, if this method can ever change ht_cap.ht_supported, fix 75 * And, if this method can ever change ht_cap.ht_supported, fix
64 * the check in ieee80211_add_ht_ie. 76 * the check in ieee80211_add_ht_ie.
65 */ 77 */
@@ -86,6 +98,14 @@ void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
86 __check_htcap_disable(ht_capa, ht_capa_mask, ht_cap, 98 __check_htcap_disable(ht_capa, ht_capa_mask, ht_cap,
87 IEEE80211_HT_CAP_MAX_AMSDU); 99 IEEE80211_HT_CAP_MAX_AMSDU);
88 100
101 /* Allow user to disable LDPC */
102 __check_htcap_disable(ht_capa, ht_capa_mask, ht_cap,
103 IEEE80211_HT_CAP_LDPC_CODING);
104
105 /* Allow user to enable 40 MHz intolerant bit. */
106 __check_htcap_enable(ht_capa, ht_capa_mask, ht_cap,
107 IEEE80211_HT_CAP_40MHZ_INTOLERANT);
108
89 /* Allow user to decrease AMPDU factor */ 109 /* Allow user to decrease AMPDU factor */
90 if (ht_capa_mask->ampdu_params_info & 110 if (ht_capa_mask->ampdu_params_info &
91 IEEE80211_HT_AMPDU_PARM_FACTOR) { 111 IEEE80211_HT_AMPDU_PARM_FACTOR) {
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 06d28787945b..ff4d4155a84d 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -228,7 +228,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
228 struct beacon_data *presp; 228 struct beacon_data *presp;
229 enum nl80211_bss_scan_width scan_width; 229 enum nl80211_bss_scan_width scan_width;
230 bool have_higher_than_11mbit; 230 bool have_higher_than_11mbit;
231 bool radar_required = false; 231 bool radar_required;
232 int err; 232 int err;
233 233
234 sdata_assert_lock(sdata); 234 sdata_assert_lock(sdata);
@@ -253,7 +253,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
253 253
254 presp = rcu_dereference_protected(ifibss->presp, 254 presp = rcu_dereference_protected(ifibss->presp,
255 lockdep_is_held(&sdata->wdev.mtx)); 255 lockdep_is_held(&sdata->wdev.mtx));
256 rcu_assign_pointer(ifibss->presp, NULL); 256 RCU_INIT_POINTER(ifibss->presp, NULL);
257 if (presp) 257 if (presp)
258 kfree_rcu(presp, rcu_head); 258 kfree_rcu(presp, rcu_head);
259 259
@@ -262,7 +262,8 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
262 /* make a copy of the chandef, it could be modified below. */ 262 /* make a copy of the chandef, it could be modified below. */
263 chandef = *req_chandef; 263 chandef = *req_chandef;
264 chan = chandef.chan; 264 chan = chandef.chan;
265 if (!cfg80211_reg_can_beacon(local->hw.wiphy, &chandef)) { 265 if (!cfg80211_reg_can_beacon(local->hw.wiphy, &chandef,
266 NL80211_IFTYPE_ADHOC)) {
266 if (chandef.width == NL80211_CHAN_WIDTH_5 || 267 if (chandef.width == NL80211_CHAN_WIDTH_5 ||
267 chandef.width == NL80211_CHAN_WIDTH_10 || 268 chandef.width == NL80211_CHAN_WIDTH_10 ||
268 chandef.width == NL80211_CHAN_WIDTH_20_NOHT || 269 chandef.width == NL80211_CHAN_WIDTH_20_NOHT ||
@@ -274,7 +275,8 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
274 chandef.width = NL80211_CHAN_WIDTH_20; 275 chandef.width = NL80211_CHAN_WIDTH_20;
275 chandef.center_freq1 = chan->center_freq; 276 chandef.center_freq1 = chan->center_freq;
276 /* check again for downgraded chandef */ 277 /* check again for downgraded chandef */
277 if (!cfg80211_reg_can_beacon(local->hw.wiphy, &chandef)) { 278 if (!cfg80211_reg_can_beacon(local->hw.wiphy, &chandef,
279 NL80211_IFTYPE_ADHOC)) {
278 sdata_info(sdata, 280 sdata_info(sdata,
279 "Failed to join IBSS, beacons forbidden\n"); 281 "Failed to join IBSS, beacons forbidden\n");
280 return; 282 return;
@@ -282,21 +284,20 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
282 } 284 }
283 285
284 err = cfg80211_chandef_dfs_required(sdata->local->hw.wiphy, 286 err = cfg80211_chandef_dfs_required(sdata->local->hw.wiphy,
285 &chandef); 287 &chandef, NL80211_IFTYPE_ADHOC);
286 if (err < 0) { 288 if (err < 0) {
287 sdata_info(sdata, 289 sdata_info(sdata,
288 "Failed to join IBSS, invalid chandef\n"); 290 "Failed to join IBSS, invalid chandef\n");
289 return; 291 return;
290 } 292 }
291 if (err > 0) { 293 if (err > 0 && !ifibss->userspace_handles_dfs) {
292 if (!ifibss->userspace_handles_dfs) { 294 sdata_info(sdata,
293 sdata_info(sdata, 295 "Failed to join IBSS, DFS channel without control program\n");
294 "Failed to join IBSS, DFS channel without control program\n"); 296 return;
295 return;
296 }
297 radar_required = true;
298 } 297 }
299 298
299 radar_required = err;
300
300 mutex_lock(&local->mtx); 301 mutex_lock(&local->mtx);
301 if (ieee80211_vif_use_channel(sdata, &chandef, 302 if (ieee80211_vif_use_channel(sdata, &chandef,
302 ifibss->fixed_channel ? 303 ifibss->fixed_channel ?
@@ -775,7 +776,8 @@ static void ieee80211_ibss_csa_mark_radar(struct ieee80211_sub_if_data *sdata)
775 * unavailable. 776 * unavailable.
776 */ 777 */
777 err = cfg80211_chandef_dfs_required(sdata->local->hw.wiphy, 778 err = cfg80211_chandef_dfs_required(sdata->local->hw.wiphy,
778 &ifibss->chandef); 779 &ifibss->chandef,
780 NL80211_IFTYPE_ADHOC);
779 if (err > 0) 781 if (err > 0)
780 cfg80211_radar_event(sdata->local->hw.wiphy, &ifibss->chandef, 782 cfg80211_radar_event(sdata->local->hw.wiphy, &ifibss->chandef,
781 GFP_ATOMIC); 783 GFP_ATOMIC);
@@ -861,7 +863,8 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
861 goto disconnect; 863 goto disconnect;
862 } 864 }
863 865
864 if (!cfg80211_reg_can_beacon(sdata->local->hw.wiphy, &params.chandef)) { 866 if (!cfg80211_reg_can_beacon(sdata->local->hw.wiphy, &params.chandef,
867 NL80211_IFTYPE_ADHOC)) {
865 sdata_info(sdata, 868 sdata_info(sdata,
866 "IBSS %pM switches to unsupported channel (%d MHz, width:%d, CF1/2: %d/%d MHz), disconnecting\n", 869 "IBSS %pM switches to unsupported channel (%d MHz, width:%d, CF1/2: %d/%d MHz), disconnecting\n",
867 ifibss->bssid, 870 ifibss->bssid,
@@ -873,17 +876,17 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
873 } 876 }
874 877
875 err = cfg80211_chandef_dfs_required(sdata->local->hw.wiphy, 878 err = cfg80211_chandef_dfs_required(sdata->local->hw.wiphy,
876 &params.chandef); 879 &params.chandef,
880 NL80211_IFTYPE_ADHOC);
877 if (err < 0) 881 if (err < 0)
878 goto disconnect; 882 goto disconnect;
879 if (err) { 883 if (err > 0 && !ifibss->userspace_handles_dfs) {
880 /* IBSS-DFS only allowed with a control program */ 884 /* IBSS-DFS only allowed with a control program */
881 if (!ifibss->userspace_handles_dfs) 885 goto disconnect;
882 goto disconnect;
883
884 params.radar_required = true;
885 } 886 }
886 887
888 params.radar_required = err;
889
887 if (cfg80211_chandef_identical(&params.chandef, 890 if (cfg80211_chandef_identical(&params.chandef,
888 &sdata->vif.bss_conf.chandef)) { 891 &sdata->vif.bss_conf.chandef)) {
889 ibss_dbg(sdata, 892 ibss_dbg(sdata,
@@ -1636,7 +1639,33 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
1636 u32 changed = 0; 1639 u32 changed = 0;
1637 u32 rate_flags; 1640 u32 rate_flags;
1638 struct ieee80211_supported_band *sband; 1641 struct ieee80211_supported_band *sband;
1642 enum ieee80211_chanctx_mode chanmode;
1643 struct ieee80211_local *local = sdata->local;
1644 int radar_detect_width = 0;
1639 int i; 1645 int i;
1646 int ret;
1647
1648 ret = cfg80211_chandef_dfs_required(local->hw.wiphy,
1649 &params->chandef,
1650 sdata->wdev.iftype);
1651 if (ret < 0)
1652 return ret;
1653
1654 if (ret > 0) {
1655 if (!params->userspace_handles_dfs)
1656 return -EINVAL;
1657 radar_detect_width = BIT(params->chandef.width);
1658 }
1659
1660 chanmode = (params->channel_fixed && !ret) ?
1661 IEEE80211_CHANCTX_SHARED : IEEE80211_CHANCTX_EXCLUSIVE;
1662
1663 mutex_lock(&local->chanctx_mtx);
1664 ret = ieee80211_check_combinations(sdata, &params->chandef, chanmode,
1665 radar_detect_width);
1666 mutex_unlock(&local->chanctx_mtx);
1667 if (ret < 0)
1668 return ret;
1640 1669
1641 if (params->bssid) { 1670 if (params->bssid) {
1642 memcpy(sdata->u.ibss.bssid, params->bssid, ETH_ALEN); 1671 memcpy(sdata->u.ibss.bssid, params->bssid, ETH_ALEN);
@@ -1651,7 +1680,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
1651 1680
1652 /* fix basic_rates if channel does not support these rates */ 1681 /* fix basic_rates if channel does not support these rates */
1653 rate_flags = ieee80211_chandef_rate_flags(&params->chandef); 1682 rate_flags = ieee80211_chandef_rate_flags(&params->chandef);
1654 sband = sdata->local->hw.wiphy->bands[params->chandef.chan->band]; 1683 sband = local->hw.wiphy->bands[params->chandef.chan->band];
1655 for (i = 0; i < sband->n_bitrates; i++) { 1684 for (i = 0; i < sband->n_bitrates; i++) {
1656 if ((rate_flags & sband->bitrates[i].flags) != rate_flags) 1685 if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
1657 sdata->u.ibss.basic_rates &= ~BIT(i); 1686 sdata->u.ibss.basic_rates &= ~BIT(i);
@@ -1700,9 +1729,9 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
1700 ieee80211_bss_info_change_notify(sdata, changed); 1729 ieee80211_bss_info_change_notify(sdata, changed);
1701 1730
1702 sdata->smps_mode = IEEE80211_SMPS_OFF; 1731 sdata->smps_mode = IEEE80211_SMPS_OFF;
1703 sdata->needed_rx_chains = sdata->local->rx_chains; 1732 sdata->needed_rx_chains = local->rx_chains;
1704 1733
1705 ieee80211_queue_work(&sdata->local->hw, &sdata->work); 1734 ieee80211_queue_work(&local->hw, &sdata->work);
1706 1735
1707 return 0; 1736 return 0;
1708} 1737}
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 222c28b75315..b455f62d357a 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -260,7 +260,7 @@ struct ieee80211_if_ap {
260 260
261 /* to be used after channel switch. */ 261 /* to be used after channel switch. */
262 struct cfg80211_beacon_data *next_beacon; 262 struct cfg80211_beacon_data *next_beacon;
263 struct list_head vlans; 263 struct list_head vlans; /* write-protected with RTNL and local->mtx */
264 264
265 struct ps_data ps; 265 struct ps_data ps;
266 atomic_t num_mcast_sta; /* number of stations receiving multicast */ 266 atomic_t num_mcast_sta; /* number of stations receiving multicast */
@@ -276,7 +276,7 @@ struct ieee80211_if_wds {
276}; 276};
277 277
278struct ieee80211_if_vlan { 278struct ieee80211_if_vlan {
279 struct list_head list; 279 struct list_head list; /* write-protected with RTNL and local->mtx */
280 280
281 /* used for all tx if the VLAN is configured to 4-addr mode */ 281 /* used for all tx if the VLAN is configured to 4-addr mode */
282 struct sta_info __rcu *sta; 282 struct sta_info __rcu *sta;
@@ -691,8 +691,10 @@ struct ieee80211_chanctx {
691 struct list_head list; 691 struct list_head list;
692 struct rcu_head rcu_head; 692 struct rcu_head rcu_head;
693 693
694 struct list_head assigned_vifs;
695 struct list_head reserved_vifs;
696
694 enum ieee80211_chanctx_mode mode; 697 enum ieee80211_chanctx_mode mode;
695 int refcount;
696 bool driver_present; 698 bool driver_present;
697 699
698 struct ieee80211_chanctx_conf conf; 700 struct ieee80211_chanctx_conf conf;
@@ -756,6 +758,14 @@ struct ieee80211_sub_if_data {
756 bool csa_radar_required; 758 bool csa_radar_required;
757 struct cfg80211_chan_def csa_chandef; 759 struct cfg80211_chan_def csa_chandef;
758 760
761 struct list_head assigned_chanctx_list; /* protected by chanctx_mtx */
762 struct list_head reserved_chanctx_list; /* protected by chanctx_mtx */
763
764 /* context reservation -- protected with chanctx_mtx */
765 struct ieee80211_chanctx *reserved_chanctx;
766 struct cfg80211_chan_def reserved_chandef;
767 bool reserved_radar_required;
768
759 /* used to reconfigure hardware SM PS */ 769 /* used to reconfigure hardware SM PS */
760 struct work_struct recalc_smps; 770 struct work_struct recalc_smps;
761 771
@@ -1771,6 +1781,16 @@ ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
1771 const struct cfg80211_chan_def *chandef, 1781 const struct cfg80211_chan_def *chandef,
1772 enum ieee80211_chanctx_mode mode); 1782 enum ieee80211_chanctx_mode mode);
1773int __must_check 1783int __must_check
1784ieee80211_vif_reserve_chanctx(struct ieee80211_sub_if_data *sdata,
1785 const struct cfg80211_chan_def *chandef,
1786 enum ieee80211_chanctx_mode mode,
1787 bool radar_required);
1788int __must_check
1789ieee80211_vif_use_reserved_context(struct ieee80211_sub_if_data *sdata,
1790 u32 *changed);
1791int ieee80211_vif_unreserve_chanctx(struct ieee80211_sub_if_data *sdata);
1792
1793int __must_check
1774ieee80211_vif_change_bandwidth(struct ieee80211_sub_if_data *sdata, 1794ieee80211_vif_change_bandwidth(struct ieee80211_sub_if_data *sdata,
1775 const struct cfg80211_chan_def *chandef, 1795 const struct cfg80211_chan_def *chandef,
1776 u32 *changed); 1796 u32 *changed);
@@ -1782,6 +1802,8 @@ void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata);
1782void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata); 1802void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata);
1783void ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata, 1803void ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata,
1784 bool clear); 1804 bool clear);
1805int ieee80211_chanctx_refcount(struct ieee80211_local *local,
1806 struct ieee80211_chanctx *ctx);
1785 1807
1786void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local, 1808void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
1787 struct ieee80211_chanctx *chanctx); 1809 struct ieee80211_chanctx *chanctx);
@@ -1805,6 +1827,11 @@ int ieee80211_cs_headroom(struct ieee80211_local *local,
1805 enum nl80211_iftype iftype); 1827 enum nl80211_iftype iftype);
1806void ieee80211_recalc_dtim(struct ieee80211_local *local, 1828void ieee80211_recalc_dtim(struct ieee80211_local *local,
1807 struct ieee80211_sub_if_data *sdata); 1829 struct ieee80211_sub_if_data *sdata);
1830int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
1831 const struct cfg80211_chan_def *chandef,
1832 enum ieee80211_chanctx_mode chanmode,
1833 u8 radar_detect);
1834int ieee80211_max_num_channels(struct ieee80211_local *local);
1808 1835
1809#ifdef CONFIG_MAC80211_NOINLINE 1836#ifdef CONFIG_MAC80211_NOINLINE
1810#define debug_noinline noinline 1837#define debug_noinline noinline
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index b8d331e7d883..7fff3dcaac43 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -250,6 +250,7 @@ static int ieee80211_check_concurrent_iface(struct ieee80211_sub_if_data *sdata,
250{ 250{
251 struct ieee80211_local *local = sdata->local; 251 struct ieee80211_local *local = sdata->local;
252 struct ieee80211_sub_if_data *nsdata; 252 struct ieee80211_sub_if_data *nsdata;
253 int ret;
253 254
254 ASSERT_RTNL(); 255 ASSERT_RTNL();
255 256
@@ -300,7 +301,10 @@ static int ieee80211_check_concurrent_iface(struct ieee80211_sub_if_data *sdata,
300 } 301 }
301 } 302 }
302 303
303 return 0; 304 mutex_lock(&local->chanctx_mtx);
305 ret = ieee80211_check_combinations(sdata, NULL, 0, 0);
306 mutex_unlock(&local->chanctx_mtx);
307 return ret;
304} 308}
305 309
306static int ieee80211_check_queues(struct ieee80211_sub_if_data *sdata, 310static int ieee80211_check_queues(struct ieee80211_sub_if_data *sdata,
@@ -423,7 +427,7 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
423 mutex_unlock(&local->mtx); 427 mutex_unlock(&local->mtx);
424 if (ret) { 428 if (ret) {
425 mutex_lock(&local->iflist_mtx); 429 mutex_lock(&local->iflist_mtx);
426 rcu_assign_pointer(local->monitor_sdata, NULL); 430 RCU_INIT_POINTER(local->monitor_sdata, NULL);
427 mutex_unlock(&local->iflist_mtx); 431 mutex_unlock(&local->iflist_mtx);
428 synchronize_net(); 432 synchronize_net();
429 drv_remove_interface(local, sdata); 433 drv_remove_interface(local, sdata);
@@ -452,7 +456,7 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
452 return; 456 return;
453 } 457 }
454 458
455 rcu_assign_pointer(local->monitor_sdata, NULL); 459 RCU_INIT_POINTER(local->monitor_sdata, NULL);
456 mutex_unlock(&local->iflist_mtx); 460 mutex_unlock(&local->iflist_mtx);
457 461
458 synchronize_net(); 462 synchronize_net();
@@ -492,7 +496,9 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
492 if (!sdata->bss) 496 if (!sdata->bss)
493 return -ENOLINK; 497 return -ENOLINK;
494 498
499 mutex_lock(&local->mtx);
495 list_add(&sdata->u.vlan.list, &sdata->bss->vlans); 500 list_add(&sdata->u.vlan.list, &sdata->bss->vlans);
501 mutex_unlock(&local->mtx);
496 502
497 master = container_of(sdata->bss, 503 master = container_of(sdata->bss,
498 struct ieee80211_sub_if_data, u.ap); 504 struct ieee80211_sub_if_data, u.ap);
@@ -722,8 +728,11 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
722 drv_stop(local); 728 drv_stop(local);
723 err_del_bss: 729 err_del_bss:
724 sdata->bss = NULL; 730 sdata->bss = NULL;
725 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 731 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
732 mutex_lock(&local->mtx);
726 list_del(&sdata->u.vlan.list); 733 list_del(&sdata->u.vlan.list);
734 mutex_unlock(&local->mtx);
735 }
727 /* might already be clear but that doesn't matter */ 736 /* might already be clear but that doesn't matter */
728 clear_bit(SDATA_STATE_RUNNING, &sdata->state); 737 clear_bit(SDATA_STATE_RUNNING, &sdata->state);
729 return res; 738 return res;
@@ -875,8 +884,10 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
875 884
876 switch (sdata->vif.type) { 885 switch (sdata->vif.type) {
877 case NL80211_IFTYPE_AP_VLAN: 886 case NL80211_IFTYPE_AP_VLAN:
887 mutex_lock(&local->mtx);
878 list_del(&sdata->u.vlan.list); 888 list_del(&sdata->u.vlan.list);
879 rcu_assign_pointer(sdata->vif.chanctx_conf, NULL); 889 mutex_unlock(&local->mtx);
890 RCU_INIT_POINTER(sdata->vif.chanctx_conf, NULL);
880 /* no need to tell driver */ 891 /* no need to tell driver */
881 break; 892 break;
882 case NL80211_IFTYPE_MONITOR: 893 case NL80211_IFTYPE_MONITOR:
@@ -895,7 +906,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
895 break; 906 break;
896 case NL80211_IFTYPE_P2P_DEVICE: 907 case NL80211_IFTYPE_P2P_DEVICE:
897 /* relies on synchronize_rcu() below */ 908 /* relies on synchronize_rcu() below */
898 rcu_assign_pointer(local->p2p_sdata, NULL); 909 RCU_INIT_POINTER(local->p2p_sdata, NULL);
899 /* fall through */ 910 /* fall through */
900 default: 911 default:
901 cancel_work_sync(&sdata->work); 912 cancel_work_sync(&sdata->work);
@@ -1280,6 +1291,8 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
1280 INIT_WORK(&sdata->work, ieee80211_iface_work); 1291 INIT_WORK(&sdata->work, ieee80211_iface_work);
1281 INIT_WORK(&sdata->recalc_smps, ieee80211_recalc_smps_work); 1292 INIT_WORK(&sdata->recalc_smps, ieee80211_recalc_smps_work);
1282 INIT_WORK(&sdata->csa_finalize_work, ieee80211_csa_finalize_work); 1293 INIT_WORK(&sdata->csa_finalize_work, ieee80211_csa_finalize_work);
1294 INIT_LIST_HEAD(&sdata->assigned_chanctx_list);
1295 INIT_LIST_HEAD(&sdata->reserved_chanctx_list);
1283 1296
1284 switch (type) { 1297 switch (type) {
1285 case NL80211_IFTYPE_P2P_GO: 1298 case NL80211_IFTYPE_P2P_GO:
@@ -1774,20 +1787,19 @@ static int netdev_notify(struct notifier_block *nb,
1774 struct ieee80211_sub_if_data *sdata; 1787 struct ieee80211_sub_if_data *sdata;
1775 1788
1776 if (state != NETDEV_CHANGENAME) 1789 if (state != NETDEV_CHANGENAME)
1777 return 0; 1790 return NOTIFY_DONE;
1778 1791
1779 if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy) 1792 if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy)
1780 return 0; 1793 return NOTIFY_DONE;
1781 1794
1782 if (dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid) 1795 if (dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid)
1783 return 0; 1796 return NOTIFY_DONE;
1784 1797
1785 sdata = IEEE80211_DEV_TO_SUB_IF(dev); 1798 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1786
1787 memcpy(sdata->name, dev->name, IFNAMSIZ); 1799 memcpy(sdata->name, dev->name, IFNAMSIZ);
1788
1789 ieee80211_debugfs_rename_netdev(sdata); 1800 ieee80211_debugfs_rename_netdev(sdata);
1790 return 0; 1801
1802 return NOTIFY_OK;
1791} 1803}
1792 1804
1793static struct notifier_block mac80211_netdev_notifier = { 1805static struct notifier_block mac80211_netdev_notifier = {
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 4c1bf61bc778..27b9364cdf17 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -340,7 +340,7 @@ static int ieee80211_ifa_changed(struct notifier_block *nb,
340 340
341 sdata_unlock(sdata); 341 sdata_unlock(sdata);
342 342
343 return NOTIFY_DONE; 343 return NOTIFY_OK;
344} 344}
345#endif 345#endif
346 346
@@ -371,7 +371,7 @@ static int ieee80211_ifa6_changed(struct notifier_block *nb,
371 371
372 drv_ipv6_addr_change(local, sdata, idev); 372 drv_ipv6_addr_change(local, sdata, idev);
373 373
374 return NOTIFY_DONE; 374 return NOTIFY_OK;
375} 375}
376#endif 376#endif
377 377
@@ -446,7 +446,9 @@ static const struct ieee80211_ht_cap mac80211_ht_capa_mod_mask = {
446 .cap_info = cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40 | 446 .cap_info = cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
447 IEEE80211_HT_CAP_MAX_AMSDU | 447 IEEE80211_HT_CAP_MAX_AMSDU |
448 IEEE80211_HT_CAP_SGI_20 | 448 IEEE80211_HT_CAP_SGI_20 |
449 IEEE80211_HT_CAP_SGI_40), 449 IEEE80211_HT_CAP_SGI_40 |
450 IEEE80211_HT_CAP_LDPC_CODING |
451 IEEE80211_HT_CAP_40MHZ_INTOLERANT),
450 .mcs = { 452 .mcs = {
451 .rx_mask = { 0xff, 0xff, 0xff, 0xff, 0xff, 453 .rx_mask = { 0xff, 0xff, 0xff, 0xff, 0xff,
452 0xff, 0xff, 0xff, 0xff, 0xff, }, 454 0xff, 0xff, 0xff, 0xff, 0xff, },
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index f70e9cd10552..b06ddc9519ce 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -366,20 +366,15 @@ int mesh_add_rsn_ie(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
366 return 0; 366 return 0;
367 367
368 /* find RSN IE */ 368 /* find RSN IE */
369 data = ifmsh->ie; 369 data = cfg80211_find_ie(WLAN_EID_RSN, ifmsh->ie, ifmsh->ie_len);
370 while (data < ifmsh->ie + ifmsh->ie_len) { 370 if (!data)
371 if (*data == WLAN_EID_RSN) { 371 return 0;
372 len = data[1] + 2;
373 break;
374 }
375 data++;
376 }
377 372
378 if (len) { 373 len = data[1] + 2;
379 if (skb_tailroom(skb) < len) 374
380 return -ENOMEM; 375 if (skb_tailroom(skb) < len)
381 memcpy(skb_put(skb, len), data, len); 376 return -ENOMEM;
382 } 377 memcpy(skb_put(skb, len), data, len);
383 378
384 return 0; 379 return 0;
385} 380}
@@ -829,7 +824,7 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
829 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); 824 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);
830 bcn = rcu_dereference_protected(ifmsh->beacon, 825 bcn = rcu_dereference_protected(ifmsh->beacon,
831 lockdep_is_held(&sdata->wdev.mtx)); 826 lockdep_is_held(&sdata->wdev.mtx));
832 rcu_assign_pointer(ifmsh->beacon, NULL); 827 RCU_INIT_POINTER(ifmsh->beacon, NULL);
833 kfree_rcu(bcn, rcu_head); 828 kfree_rcu(bcn, rcu_head);
834 829
835 /* flush STAs and mpaths on this iface */ 830 /* flush STAs and mpaths on this iface */
@@ -903,14 +898,15 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata,
903 } 898 }
904 899
905 err = cfg80211_chandef_dfs_required(sdata->local->hw.wiphy, 900 err = cfg80211_chandef_dfs_required(sdata->local->hw.wiphy,
906 &params.chandef); 901 &params.chandef,
902 NL80211_IFTYPE_MESH_POINT);
907 if (err < 0) 903 if (err < 0)
908 return false; 904 return false;
909 if (err) { 905 if (err > 0)
910 params.radar_required = true;
911 /* TODO: DFS not (yet) supported */ 906 /* TODO: DFS not (yet) supported */
912 return false; 907 return false;
913 } 908
909 params.radar_required = err;
914 910
915 if (cfg80211_chandef_identical(&params.chandef, 911 if (cfg80211_chandef_identical(&params.chandef,
916 &sdata->vif.bss_conf.chandef)) { 912 &sdata->vif.bss_conf.chandef)) {
@@ -1068,7 +1064,7 @@ int ieee80211_mesh_finish_csa(struct ieee80211_sub_if_data *sdata)
1068 1064
1069 /* Remove the CSA and MCSP elements from the beacon */ 1065 /* Remove the CSA and MCSP elements from the beacon */
1070 tmp_csa_settings = rcu_dereference(ifmsh->csa); 1066 tmp_csa_settings = rcu_dereference(ifmsh->csa);
1071 rcu_assign_pointer(ifmsh->csa, NULL); 1067 RCU_INIT_POINTER(ifmsh->csa, NULL);
1072 if (tmp_csa_settings) 1068 if (tmp_csa_settings)
1073 kfree_rcu(tmp_csa_settings, rcu_head); 1069 kfree_rcu(tmp_csa_settings, rcu_head);
1074 ret = ieee80211_mesh_rebuild_beacon(sdata); 1070 ret = ieee80211_mesh_rebuild_beacon(sdata);
@@ -1102,7 +1098,7 @@ int ieee80211_mesh_csa_beacon(struct ieee80211_sub_if_data *sdata,
1102 ret = ieee80211_mesh_rebuild_beacon(sdata); 1098 ret = ieee80211_mesh_rebuild_beacon(sdata);
1103 if (ret) { 1099 if (ret) {
1104 tmp_csa_settings = rcu_dereference(ifmsh->csa); 1100 tmp_csa_settings = rcu_dereference(ifmsh->csa);
1105 rcu_assign_pointer(ifmsh->csa, NULL); 1101 RCU_INIT_POINTER(ifmsh->csa, NULL);
1106 kfree_rcu(tmp_csa_settings, rcu_head); 1102 kfree_rcu(tmp_csa_settings, rcu_head);
1107 return ret; 1103 return ret;
1108 } 1104 }
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index f9514685d45a..94758b9c9ed4 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -37,7 +37,7 @@ static inline u32 u32_field_get(const u8 *preq_elem, int offset, bool ae)
37 return get_unaligned_le32(preq_elem + offset); 37 return get_unaligned_le32(preq_elem + offset);
38} 38}
39 39
40static inline u32 u16_field_get(const u8 *preq_elem, int offset, bool ae) 40static inline u16 u16_field_get(const u8 *preq_elem, int offset, bool ae)
41{ 41{
42 if (ae) 42 if (ae)
43 offset += 6; 43 offset += 6;
@@ -544,9 +544,10 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
544 if (time_after(jiffies, ifmsh->last_sn_update + 544 if (time_after(jiffies, ifmsh->last_sn_update +
545 net_traversal_jiffies(sdata)) || 545 net_traversal_jiffies(sdata)) ||
546 time_before(jiffies, ifmsh->last_sn_update)) { 546 time_before(jiffies, ifmsh->last_sn_update)) {
547 target_sn = ++ifmsh->sn; 547 ++ifmsh->sn;
548 ifmsh->last_sn_update = jiffies; 548 ifmsh->last_sn_update = jiffies;
549 } 549 }
550 target_sn = ifmsh->sn;
550 } else if (is_broadcast_ether_addr(target_addr) && 551 } else if (is_broadcast_ether_addr(target_addr) &&
551 (target_flags & IEEE80211_PREQ_TO_FLAG)) { 552 (target_flags & IEEE80211_PREQ_TO_FLAG)) {
552 rcu_read_lock(); 553 rcu_read_lock();
diff --git a/net/mac80211/michael.h b/net/mac80211/michael.h
index 3b848dad9587..0e4886f881f1 100644
--- a/net/mac80211/michael.h
+++ b/net/mac80211/michael.h
@@ -11,6 +11,7 @@
11#define MICHAEL_H 11#define MICHAEL_H
12 12
13#include <linux/types.h> 13#include <linux/types.h>
14#include <linux/ieee80211.h>
14 15
15#define MICHAEL_MIC_LEN 8 16#define MICHAEL_MIC_LEN 8
16 17
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index dee50aefd6e8..488826f188a7 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1089,7 +1089,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
1089 } 1089 }
1090 chanctx = container_of(rcu_access_pointer(sdata->vif.chanctx_conf), 1090 chanctx = container_of(rcu_access_pointer(sdata->vif.chanctx_conf),
1091 struct ieee80211_chanctx, conf); 1091 struct ieee80211_chanctx, conf);
1092 if (chanctx->refcount > 1) { 1092 if (ieee80211_chanctx_refcount(local, chanctx) > 1) {
1093 sdata_info(sdata, 1093 sdata_info(sdata,
1094 "channel switch with multiple interfaces on the same channel, disconnecting\n"); 1094 "channel switch with multiple interfaces on the same channel, disconnecting\n");
1095 ieee80211_queue_work(&local->hw, 1095 ieee80211_queue_work(&local->hw,
@@ -3701,7 +3701,7 @@ int ieee80211_max_network_latency(struct notifier_block *nb,
3701 ieee80211_recalc_ps(local, latency_usec); 3701 ieee80211_recalc_ps(local, latency_usec);
3702 mutex_unlock(&local->iflist_mtx); 3702 mutex_unlock(&local->iflist_mtx);
3703 3703
3704 return 0; 3704 return NOTIFY_OK;
3705} 3705}
3706 3706
3707static u8 ieee80211_ht_vht_rx_chains(struct ieee80211_sub_if_data *sdata, 3707static u8 ieee80211_ht_vht_rx_chains(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 216c45b949e5..0e5b67015650 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -54,24 +54,25 @@ static struct sk_buff *remove_monitor_info(struct ieee80211_local *local,
54 return skb; 54 return skb;
55} 55}
56 56
57static inline int should_drop_frame(struct sk_buff *skb, int present_fcs_len) 57static inline bool should_drop_frame(struct sk_buff *skb, int present_fcs_len)
58{ 58{
59 struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); 59 struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
60 struct ieee80211_hdr *hdr; 60 struct ieee80211_hdr *hdr = (void *)skb->data;
61
62 hdr = (void *)(skb->data);
63 61
64 if (status->flag & (RX_FLAG_FAILED_FCS_CRC | 62 if (status->flag & (RX_FLAG_FAILED_FCS_CRC |
65 RX_FLAG_FAILED_PLCP_CRC | 63 RX_FLAG_FAILED_PLCP_CRC |
66 RX_FLAG_AMPDU_IS_ZEROLEN)) 64 RX_FLAG_AMPDU_IS_ZEROLEN))
67 return 1; 65 return true;
66
68 if (unlikely(skb->len < 16 + present_fcs_len)) 67 if (unlikely(skb->len < 16 + present_fcs_len))
69 return 1; 68 return true;
69
70 if (ieee80211_is_ctl(hdr->frame_control) && 70 if (ieee80211_is_ctl(hdr->frame_control) &&
71 !ieee80211_is_pspoll(hdr->frame_control) && 71 !ieee80211_is_pspoll(hdr->frame_control) &&
72 !ieee80211_is_back_req(hdr->frame_control)) 72 !ieee80211_is_back_req(hdr->frame_control))
73 return 1; 73 return true;
74 return 0; 74
75 return false;
75} 76}
76 77
77static int 78static int
@@ -3190,7 +3191,7 @@ static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx,
3190} 3191}
3191 3192
3192/* 3193/*
3193 * This is the actual Rx frames handler. as it blongs to Rx path it must 3194 * This is the actual Rx frames handler. as it belongs to Rx path it must
3194 * be called with rcu_read_lock protection. 3195 * be called with rcu_read_lock protection.
3195 */ 3196 */
3196static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, 3197static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 3ce7f2c8539a..28185c8dc19a 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -309,7 +309,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
309 if (local->scan_req != local->int_scan_req) 309 if (local->scan_req != local->int_scan_req)
310 cfg80211_scan_done(local->scan_req, aborted); 310 cfg80211_scan_done(local->scan_req, aborted);
311 local->scan_req = NULL; 311 local->scan_req = NULL;
312 rcu_assign_pointer(local->scan_sdata, NULL); 312 RCU_INIT_POINTER(local->scan_sdata, NULL);
313 313
314 local->scanning = 0; 314 local->scanning = 0;
315 local->scan_chandef.chan = NULL; 315 local->scan_chandef.chan = NULL;
@@ -559,7 +559,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
559 ieee80211_recalc_idle(local); 559 ieee80211_recalc_idle(local);
560 560
561 local->scan_req = NULL; 561 local->scan_req = NULL;
562 rcu_assign_pointer(local->scan_sdata, NULL); 562 RCU_INIT_POINTER(local->scan_sdata, NULL);
563 } 563 }
564 564
565 return rc; 565 return rc;
@@ -773,7 +773,7 @@ void ieee80211_scan_work(struct work_struct *work)
773 int rc; 773 int rc;
774 774
775 local->scan_req = NULL; 775 local->scan_req = NULL;
776 rcu_assign_pointer(local->scan_sdata, NULL); 776 RCU_INIT_POINTER(local->scan_sdata, NULL);
777 777
778 rc = __ieee80211_start_scan(sdata, req); 778 rc = __ieee80211_start_scan(sdata, req);
779 if (rc) { 779 if (rc) {
@@ -1014,7 +1014,7 @@ out_free:
1014 1014
1015 if (ret) { 1015 if (ret) {
1016 /* Clean in case of failure after HW restart or upon resume. */ 1016 /* Clean in case of failure after HW restart or upon resume. */
1017 rcu_assign_pointer(local->sched_scan_sdata, NULL); 1017 RCU_INIT_POINTER(local->sched_scan_sdata, NULL);
1018 local->sched_scan_req = NULL; 1018 local->sched_scan_req = NULL;
1019 } 1019 }
1020 1020
@@ -1089,7 +1089,7 @@ void ieee80211_sched_scan_stopped_work(struct work_struct *work)
1089 return; 1089 return;
1090 } 1090 }
1091 1091
1092 rcu_assign_pointer(local->sched_scan_sdata, NULL); 1092 RCU_INIT_POINTER(local->sched_scan_sdata, NULL);
1093 1093
1094 /* If sched scan was aborted by the driver. */ 1094 /* If sched scan was aborted by the driver. */
1095 local->sched_scan_req = NULL; 1095 local->sched_scan_req = NULL;
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 137a192e64bc..c34a5f97abc7 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -552,7 +552,7 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)
552int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU) 552int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU)
553{ 553{
554 struct ieee80211_local *local = sta->local; 554 struct ieee80211_local *local = sta->local;
555 int err = 0; 555 int err;
556 556
557 might_sleep(); 557 might_sleep();
558 558
@@ -570,7 +570,6 @@ int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU)
570 570
571 return 0; 571 return 0;
572 out_free: 572 out_free:
573 BUG_ON(!err);
574 sta_info_free(local, sta); 573 sta_info_free(local, sta);
575 return err; 574 return err;
576} 575}
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 275c94f995f7..ad058759e85e 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -554,7 +554,7 @@ void ieee80211_flush_queues(struct ieee80211_local *local,
554 ieee80211_stop_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP, 554 ieee80211_stop_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP,
555 IEEE80211_QUEUE_STOP_REASON_FLUSH); 555 IEEE80211_QUEUE_STOP_REASON_FLUSH);
556 556
557 drv_flush(local, queues, false); 557 drv_flush(local, sdata, queues, false);
558 558
559 ieee80211_wake_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP, 559 ieee80211_wake_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP,
560 IEEE80211_QUEUE_STOP_REASON_FLUSH); 560 IEEE80211_QUEUE_STOP_REASON_FLUSH);
@@ -1546,7 +1546,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1546 WARN_ON(local->resuming); 1546 WARN_ON(local->resuming);
1547 res = drv_add_interface(local, sdata); 1547 res = drv_add_interface(local, sdata);
1548 if (WARN_ON(res)) { 1548 if (WARN_ON(res)) {
1549 rcu_assign_pointer(local->monitor_sdata, NULL); 1549 RCU_INIT_POINTER(local->monitor_sdata, NULL);
1550 synchronize_net(); 1550 synchronize_net();
1551 kfree(sdata); 1551 kfree(sdata);
1552 } 1552 }
@@ -1565,17 +1565,17 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1565 list_for_each_entry(ctx, &local->chanctx_list, list) 1565 list_for_each_entry(ctx, &local->chanctx_list, list)
1566 WARN_ON(drv_add_chanctx(local, ctx)); 1566 WARN_ON(drv_add_chanctx(local, ctx));
1567 mutex_unlock(&local->chanctx_mtx); 1567 mutex_unlock(&local->chanctx_mtx);
1568 }
1569 1568
1570 list_for_each_entry(sdata, &local->interfaces, list) { 1569 list_for_each_entry(sdata, &local->interfaces, list) {
1571 if (!ieee80211_sdata_running(sdata)) 1570 if (!ieee80211_sdata_running(sdata))
1572 continue; 1571 continue;
1573 ieee80211_assign_chanctx(local, sdata); 1572 ieee80211_assign_chanctx(local, sdata);
1574 } 1573 }
1575 1574
1576 sdata = rtnl_dereference(local->monitor_sdata); 1575 sdata = rtnl_dereference(local->monitor_sdata);
1577 if (sdata && ieee80211_sdata_running(sdata)) 1576 if (sdata && ieee80211_sdata_running(sdata))
1578 ieee80211_assign_chanctx(local, sdata); 1577 ieee80211_assign_chanctx(local, sdata);
1578 }
1579 1579
1580 /* add STAs back */ 1580 /* add STAs back */
1581 mutex_lock(&local->sta_mtx); 1581 mutex_lock(&local->sta_mtx);
@@ -1671,13 +1671,10 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1671 } 1671 }
1672 break; 1672 break;
1673 case NL80211_IFTYPE_WDS: 1673 case NL80211_IFTYPE_WDS:
1674 break;
1675 case NL80211_IFTYPE_AP_VLAN: 1674 case NL80211_IFTYPE_AP_VLAN:
1676 case NL80211_IFTYPE_MONITOR: 1675 case NL80211_IFTYPE_MONITOR:
1677 /* ignore virtual */
1678 break;
1679 case NL80211_IFTYPE_P2P_DEVICE: 1676 case NL80211_IFTYPE_P2P_DEVICE:
1680 changed = BSS_CHANGED_IDLE; 1677 /* nothing to do */
1681 break; 1678 break;
1682 case NL80211_IFTYPE_UNSPECIFIED: 1679 case NL80211_IFTYPE_UNSPECIFIED:
1683 case NUM_NL80211_IFTYPES: 1680 case NUM_NL80211_IFTYPES:
@@ -2797,3 +2794,121 @@ void ieee80211_recalc_dtim(struct ieee80211_local *local,
2797 2794
2798 ps->dtim_count = dtim_count; 2795 ps->dtim_count = dtim_count;
2799} 2796}
2797
2798int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
2799 const struct cfg80211_chan_def *chandef,
2800 enum ieee80211_chanctx_mode chanmode,
2801 u8 radar_detect)
2802{
2803 struct ieee80211_local *local = sdata->local;
2804 struct ieee80211_sub_if_data *sdata_iter;
2805 enum nl80211_iftype iftype = sdata->wdev.iftype;
2806 int num[NUM_NL80211_IFTYPES];
2807 struct ieee80211_chanctx *ctx;
2808 int num_different_channels = 0;
2809 int total = 1;
2810
2811 lockdep_assert_held(&local->chanctx_mtx);
2812
2813 if (WARN_ON(hweight32(radar_detect) > 1))
2814 return -EINVAL;
2815
2816 if (WARN_ON(chandef && chanmode == IEEE80211_CHANCTX_SHARED &&
2817 !chandef->chan))
2818 return -EINVAL;
2819
2820 if (chandef)
2821 num_different_channels = 1;
2822
2823 if (WARN_ON(iftype >= NUM_NL80211_IFTYPES))
2824 return -EINVAL;
2825
2826 /* Always allow software iftypes */
2827 if (local->hw.wiphy->software_iftypes & BIT(iftype)) {
2828 if (radar_detect)
2829 return -EINVAL;
2830 return 0;
2831 }
2832
2833 memset(num, 0, sizeof(num));
2834
2835 if (iftype != NL80211_IFTYPE_UNSPECIFIED)
2836 num[iftype] = 1;
2837
2838 list_for_each_entry(ctx, &local->chanctx_list, list) {
2839 if (ctx->conf.radar_enabled)
2840 radar_detect |= BIT(ctx->conf.def.width);
2841 if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE) {
2842 num_different_channels++;
2843 continue;
2844 }
2845 if (chandef && chanmode == IEEE80211_CHANCTX_SHARED &&
2846 cfg80211_chandef_compatible(chandef,
2847 &ctx->conf.def))
2848 continue;
2849 num_different_channels++;
2850 }
2851
2852 list_for_each_entry_rcu(sdata_iter, &local->interfaces, list) {
2853 struct wireless_dev *wdev_iter;
2854
2855 wdev_iter = &sdata_iter->wdev;
2856
2857 if (sdata_iter == sdata ||
2858 rcu_access_pointer(sdata_iter->vif.chanctx_conf) == NULL ||
2859 local->hw.wiphy->software_iftypes & BIT(wdev_iter->iftype))
2860 continue;
2861
2862 num[wdev_iter->iftype]++;
2863 total++;
2864 }
2865
2866 if (total == 1 && !radar_detect)
2867 return 0;
2868
2869 return cfg80211_check_combinations(local->hw.wiphy,
2870 num_different_channels,
2871 radar_detect, num);
2872}
2873
2874static void
2875ieee80211_iter_max_chans(const struct ieee80211_iface_combination *c,
2876 void *data)
2877{
2878 u32 *max_num_different_channels = data;
2879
2880 *max_num_different_channels = max(*max_num_different_channels,
2881 c->num_different_channels);
2882}
2883
2884int ieee80211_max_num_channels(struct ieee80211_local *local)
2885{
2886 struct ieee80211_sub_if_data *sdata;
2887 int num[NUM_NL80211_IFTYPES] = {};
2888 struct ieee80211_chanctx *ctx;
2889 int num_different_channels = 0;
2890 u8 radar_detect = 0;
2891 u32 max_num_different_channels = 1;
2892 int err;
2893
2894 lockdep_assert_held(&local->chanctx_mtx);
2895
2896 list_for_each_entry(ctx, &local->chanctx_list, list) {
2897 num_different_channels++;
2898
2899 if (ctx->conf.radar_enabled)
2900 radar_detect |= BIT(ctx->conf.def.width);
2901 }
2902
2903 list_for_each_entry_rcu(sdata, &local->interfaces, list)
2904 num[sdata->wdev.iftype]++;
2905
2906 err = cfg80211_iter_combinations(local->hw.wiphy,
2907 num_different_channels, radar_detect,
2908 num, ieee80211_iter_max_chans,
2909 &max_num_different_channels);
2910 if (err < 0)
2911 return err;
2912
2913 return max_num_different_channels;
2914}
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index b8600e3c29c8..9b3dcc201145 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -406,7 +406,10 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
406 406
407 if (info->control.hw_key && 407 if (info->control.hw_key &&
408 !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) && 408 !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) &&
409 !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE)) { 409 !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE) &&
410 !((info->control.hw_key->flags &
411 IEEE80211_KEY_FLAG_GENERATE_IV_MGMT) &&
412 ieee80211_is_mgmt(hdr->frame_control))) {
410 /* 413 /*
411 * hwaccel has no need for preallocated room for CCMP 414 * hwaccel has no need for preallocated room for CCMP
412 * header or MIC fields 415 * header or MIC fields