aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2013-12-02 14:25:38 -0500
committerJohn W. Linville <linville@tuxdriver.com>2013-12-02 14:25:38 -0500
commit4b074b07625f603d40d4d04937f8874a00415dc4 (patch)
tree2dffdc46e3fea0320524f483cf5ac2c058ab59f2 /net/wireless
parent7d68849f40cd9169088249cc889d95c8998c3fb8 (diff)
parentddcc347b70f298f9d624cd0e250581d831d915fb (diff)
Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/chan.c203
-rw-r--r--net/wireless/core.c6
-rw-r--r--net/wireless/core.h18
-rw-r--r--net/wireless/genregdb.awk45
-rw-r--r--net/wireless/ibss.c4
-rw-r--r--net/wireless/mesh.c3
-rw-r--r--net/wireless/mlme.c20
-rw-r--r--net/wireless/nl80211.c107
-rw-r--r--net/wireless/nl80211.h2
-rw-r--r--net/wireless/rdev-ops.h12
-rw-r--r--net/wireless/reg.c802
-rw-r--r--net/wireless/reg.h3
-rw-r--r--net/wireless/trace.h15
13 files changed, 787 insertions, 453 deletions
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index 9b8cc877eb19..78559b5bbd1f 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -277,6 +277,32 @@ void cfg80211_set_dfs_state(struct wiphy *wiphy,
277 width, dfs_state); 277 width, dfs_state);
278} 278}
279 279
280static u32 cfg80211_get_start_freq(u32 center_freq,
281 u32 bandwidth)
282{
283 u32 start_freq;
284
285 if (bandwidth <= 20)
286 start_freq = center_freq;
287 else
288 start_freq = center_freq - bandwidth/2 + 10;
289
290 return start_freq;
291}
292
293static u32 cfg80211_get_end_freq(u32 center_freq,
294 u32 bandwidth)
295{
296 u32 end_freq;
297
298 if (bandwidth <= 20)
299 end_freq = center_freq;
300 else
301 end_freq = center_freq + bandwidth/2 - 10;
302
303 return end_freq;
304}
305
280static int cfg80211_get_chans_dfs_required(struct wiphy *wiphy, 306static int cfg80211_get_chans_dfs_required(struct wiphy *wiphy,
281 u32 center_freq, 307 u32 center_freq,
282 u32 bandwidth) 308 u32 bandwidth)
@@ -284,13 +310,8 @@ static int cfg80211_get_chans_dfs_required(struct wiphy *wiphy,
284 struct ieee80211_channel *c; 310 struct ieee80211_channel *c;
285 u32 freq, start_freq, end_freq; 311 u32 freq, start_freq, end_freq;
286 312
287 if (bandwidth <= 20) { 313 start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
288 start_freq = center_freq; 314 end_freq = cfg80211_get_end_freq(center_freq, bandwidth);
289 end_freq = center_freq;
290 } else {
291 start_freq = center_freq - bandwidth/2 + 10;
292 end_freq = center_freq + bandwidth/2 - 10;
293 }
294 315
295 for (freq = start_freq; freq <= end_freq; freq += 20) { 316 for (freq = start_freq; freq <= end_freq; freq += 20) {
296 c = ieee80211_get_channel(wiphy, freq); 317 c = ieee80211_get_channel(wiphy, freq);
@@ -330,33 +351,159 @@ int cfg80211_chandef_dfs_required(struct wiphy *wiphy,
330} 351}
331EXPORT_SYMBOL(cfg80211_chandef_dfs_required); 352EXPORT_SYMBOL(cfg80211_chandef_dfs_required);
332 353
333static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, 354static int cfg80211_get_chans_dfs_usable(struct wiphy *wiphy,
334 u32 center_freq, u32 bandwidth, 355 u32 center_freq,
335 u32 prohibited_flags) 356 u32 bandwidth)
336{ 357{
337 struct ieee80211_channel *c; 358 struct ieee80211_channel *c;
338 u32 freq, start_freq, end_freq; 359 u32 freq, start_freq, end_freq;
360 int count = 0;
339 361
340 if (bandwidth <= 20) { 362 start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
341 start_freq = center_freq; 363 end_freq = cfg80211_get_end_freq(center_freq, bandwidth);
342 end_freq = center_freq; 364
343 } else { 365 /*
344 start_freq = center_freq - bandwidth/2 + 10; 366 * Check entire range of channels for the bandwidth.
345 end_freq = center_freq + bandwidth/2 - 10; 367 * Check all channels are DFS channels (DFS_USABLE or
368 * DFS_AVAILABLE). Return number of usable channels
369 * (require CAC). Allow DFS and non-DFS channel mix.
370 */
371 for (freq = start_freq; freq <= end_freq; freq += 20) {
372 c = ieee80211_get_channel(wiphy, freq);
373 if (!c)
374 return -EINVAL;
375
376 if (c->flags & IEEE80211_CHAN_DISABLED)
377 return -EINVAL;
378
379 if (c->flags & IEEE80211_CHAN_RADAR) {
380 if (c->dfs_state == NL80211_DFS_UNAVAILABLE)
381 return -EINVAL;
382
383 if (c->dfs_state == NL80211_DFS_USABLE)
384 count++;
385 }
346 } 386 }
347 387
388 return count;
389}
390
391bool cfg80211_chandef_dfs_usable(struct wiphy *wiphy,
392 const struct cfg80211_chan_def *chandef)
393{
394 int width;
395 int r1, r2 = 0;
396
397 if (WARN_ON(!cfg80211_chandef_valid(chandef)))
398 return false;
399
400 width = cfg80211_chandef_get_width(chandef);
401 if (width < 0)
402 return false;
403
404 r1 = cfg80211_get_chans_dfs_usable(wiphy, chandef->center_freq1,
405 width);
406
407 if (r1 < 0)
408 return false;
409
410 switch (chandef->width) {
411 case NL80211_CHAN_WIDTH_80P80:
412 WARN_ON(!chandef->center_freq2);
413 r2 = cfg80211_get_chans_dfs_usable(wiphy,
414 chandef->center_freq2,
415 width);
416 if (r2 < 0)
417 return false;
418 break;
419 default:
420 WARN_ON(chandef->center_freq2);
421 break;
422 }
423
424 return (r1 + r2 > 0);
425}
426
427
428static bool cfg80211_get_chans_dfs_available(struct wiphy *wiphy,
429 u32 center_freq,
430 u32 bandwidth)
431{
432 struct ieee80211_channel *c;
433 u32 freq, start_freq, end_freq;
434
435 start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
436 end_freq = cfg80211_get_end_freq(center_freq, bandwidth);
437
438 /*
439 * Check entire range of channels for the bandwidth.
440 * If any channel in between is disabled or has not
441 * had gone through CAC return false
442 */
348 for (freq = start_freq; freq <= end_freq; freq += 20) { 443 for (freq = start_freq; freq <= end_freq; freq += 20) {
349 c = ieee80211_get_channel(wiphy, freq); 444 c = ieee80211_get_channel(wiphy, freq);
350 if (!c) 445 if (!c)
351 return false; 446 return false;
352 447
353 /* check for radar flags */ 448 if (c->flags & IEEE80211_CHAN_DISABLED)
354 if ((prohibited_flags & c->flags & IEEE80211_CHAN_RADAR) && 449 return false;
450
451 if ((c->flags & IEEE80211_CHAN_RADAR) &&
355 (c->dfs_state != NL80211_DFS_AVAILABLE)) 452 (c->dfs_state != NL80211_DFS_AVAILABLE))
356 return false; 453 return false;
454 }
455
456 return true;
457}
458
459static bool cfg80211_chandef_dfs_available(struct wiphy *wiphy,
460 const struct cfg80211_chan_def *chandef)
461{
462 int width;
463 int r;
464
465 if (WARN_ON(!cfg80211_chandef_valid(chandef)))
466 return false;
467
468 width = cfg80211_chandef_get_width(chandef);
469 if (width < 0)
470 return false;
471
472 r = cfg80211_get_chans_dfs_available(wiphy, chandef->center_freq1,
473 width);
474
475 /* If any of channels unavailable for cf1 just return */
476 if (!r)
477 return r;
478
479 switch (chandef->width) {
480 case NL80211_CHAN_WIDTH_80P80:
481 WARN_ON(!chandef->center_freq2);
482 r = cfg80211_get_chans_dfs_available(wiphy,
483 chandef->center_freq2,
484 width);
485 default:
486 WARN_ON(chandef->center_freq2);
487 break;
488 }
489
490 return r;
491}
357 492
358 /* check for the other flags */ 493
359 if (c->flags & prohibited_flags & ~IEEE80211_CHAN_RADAR) 494static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
495 u32 center_freq, u32 bandwidth,
496 u32 prohibited_flags)
497{
498 struct ieee80211_channel *c;
499 u32 freq, start_freq, end_freq;
500
501 start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
502 end_freq = cfg80211_get_end_freq(center_freq, bandwidth);
503
504 for (freq = start_freq; freq <= end_freq; freq += 20) {
505 c = ieee80211_get_channel(wiphy, freq);
506 if (!c || c->flags & prohibited_flags)
360 return false; 507 return false;
361 } 508 }
362 509
@@ -462,14 +609,19 @@ bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
462 struct cfg80211_chan_def *chandef) 609 struct cfg80211_chan_def *chandef)
463{ 610{
464 bool res; 611 bool res;
612 u32 prohibited_flags = IEEE80211_CHAN_DISABLED |
613 IEEE80211_CHAN_NO_IR |
614 IEEE80211_CHAN_RADAR;
465 615
466 trace_cfg80211_reg_can_beacon(wiphy, chandef); 616 trace_cfg80211_reg_can_beacon(wiphy, chandef);
467 617
468 res = cfg80211_chandef_usable(wiphy, chandef, 618 if (cfg80211_chandef_dfs_required(wiphy, chandef) > 0 &&
469 IEEE80211_CHAN_DISABLED | 619 cfg80211_chandef_dfs_available(wiphy, chandef)) {
470 IEEE80211_CHAN_PASSIVE_SCAN | 620 /* We can skip IEEE80211_CHAN_NO_IR if chandef dfs available */
471 IEEE80211_CHAN_NO_IBSS | 621 prohibited_flags = IEEE80211_CHAN_DISABLED;
472 IEEE80211_CHAN_RADAR); 622 }
623
624 res = cfg80211_chandef_usable(wiphy, chandef, prohibited_flags);
473 625
474 trace_cfg80211_return_bool(res); 626 trace_cfg80211_return_bool(res);
475 return res; 627 return res;
@@ -510,6 +662,7 @@ cfg80211_get_chan_state(struct wireless_dev *wdev,
510 : CHAN_MODE_EXCLUSIVE; 662 : CHAN_MODE_EXCLUSIVE;
511 return; 663 return;
512 } 664 }
665 break;
513 case NL80211_IFTYPE_STATION: 666 case NL80211_IFTYPE_STATION:
514 case NL80211_IFTYPE_P2P_CLIENT: 667 case NL80211_IFTYPE_P2P_CLIENT:
515 if (wdev->current_bss) { 668 if (wdev->current_bss) {
diff --git a/net/wireless/core.c b/net/wireless/core.c
index aff959e5a1b3..fc968c861ee4 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -357,8 +357,6 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
357 rdev->wiphy.rts_threshold = (u32) -1; 357 rdev->wiphy.rts_threshold = (u32) -1;
358 rdev->wiphy.coverage_class = 0; 358 rdev->wiphy.coverage_class = 0;
359 359
360 rdev->wiphy.features = NL80211_FEATURE_SCAN_FLUSH;
361
362 return &rdev->wiphy; 360 return &rdev->wiphy;
363} 361}
364EXPORT_SYMBOL(wiphy_new); 362EXPORT_SYMBOL(wiphy_new);
@@ -566,6 +564,8 @@ int wiphy_register(struct wiphy *wiphy)
566 /* check and set up bitrates */ 564 /* check and set up bitrates */
567 ieee80211_set_bitrate_flags(wiphy); 565 ieee80211_set_bitrate_flags(wiphy);
568 566
567 rdev->wiphy.features |= NL80211_FEATURE_SCAN_FLUSH;
568
569 rtnl_lock(); 569 rtnl_lock();
570 res = device_add(&rdev->wiphy.dev); 570 res = device_add(&rdev->wiphy.dev);
571 if (res) { 571 if (res) {
@@ -586,7 +586,7 @@ int wiphy_register(struct wiphy *wiphy)
586 if (IS_ERR(rdev->wiphy.debugfsdir)) 586 if (IS_ERR(rdev->wiphy.debugfsdir))
587 rdev->wiphy.debugfsdir = NULL; 587 rdev->wiphy.debugfsdir = NULL;
588 588
589 if (wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY) { 589 if (wiphy->regulatory_flags & REGULATORY_CUSTOM_REG) {
590 struct regulatory_request request; 590 struct regulatory_request request;
591 591
592 request.wiphy_idx = get_wiphy_idx(wiphy); 592 request.wiphy_idx = get_wiphy_idx(wiphy);
diff --git a/net/wireless/core.h b/net/wireless/core.h
index af10e59af2d8..0a277c33bb02 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -317,9 +317,8 @@ void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlpid);
317void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev); 317void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev);
318int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, 318int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
319 struct wireless_dev *wdev, 319 struct wireless_dev *wdev,
320 struct ieee80211_channel *chan, bool offchan, 320 struct cfg80211_mgmt_tx_params *params,
321 unsigned int wait, const u8 *buf, size_t len, 321 u64 *cookie);
322 bool no_cck, bool dont_wait_for_ack, u64 *cookie);
323void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa, 322void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa,
324 const struct ieee80211_ht_cap *ht_capa_mask); 323 const struct ieee80211_ht_cap *ht_capa_mask);
325void cfg80211_oper_and_vht_capa(struct ieee80211_vht_cap *vht_capa, 324void cfg80211_oper_and_vht_capa(struct ieee80211_vht_cap *vht_capa,
@@ -382,6 +381,19 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
382 enum cfg80211_chan_mode chanmode, 381 enum cfg80211_chan_mode chanmode,
383 u8 radar_detect); 382 u8 radar_detect);
384 383
384/**
385 * cfg80211_chandef_dfs_usable - checks if chandef is DFS usable
386 * @wiphy: the wiphy to validate against
387 * @chandef: the channel definition to check
388 *
389 * Checks if chandef is usable and we can/need start CAC on such channel.
390 *
391 * Return: Return true if all channels available and at least
392 * one channel require CAC (NL80211_DFS_USABLE)
393 */
394bool cfg80211_chandef_dfs_usable(struct wiphy *wiphy,
395 const struct cfg80211_chan_def *chandef);
396
385void cfg80211_set_dfs_state(struct wiphy *wiphy, 397void cfg80211_set_dfs_state(struct wiphy *wiphy,
386 const struct cfg80211_chan_def *chandef, 398 const struct cfg80211_chan_def *chandef,
387 enum nl80211_dfs_state dfs_state); 399 enum nl80211_dfs_state dfs_state);
diff --git a/net/wireless/genregdb.awk b/net/wireless/genregdb.awk
index 42ed274e81f4..9a8217d2a908 100644
--- a/net/wireless/genregdb.awk
+++ b/net/wireless/genregdb.awk
@@ -33,15 +33,7 @@ BEGIN {
33 regdb = "const struct ieee80211_regdomain *reg_regdb[] = {\n" 33 regdb = "const struct ieee80211_regdomain *reg_regdb[] = {\n"
34} 34}
35 35
36/^[ \t]*#/ { 36function parse_country_head() {
37 # Ignore
38}
39
40!active && /^[ \t]*$/ {
41 # Ignore
42}
43
44!active && /country/ {
45 country=$2 37 country=$2
46 sub(/:/, "", country) 38 sub(/:/, "", country)
47 printf "static const struct ieee80211_regdomain regdom_%s = {\n", country 39 printf "static const struct ieee80211_regdomain regdom_%s = {\n", country
@@ -57,7 +49,8 @@ BEGIN {
57 regdb = regdb "\t&regdom_" country ",\n" 49 regdb = regdb "\t&regdom_" country ",\n"
58} 50}
59 51
60active && /^[ \t]*\(/ { 52function parse_reg_rule()
53{
61 start = $1 54 start = $1
62 sub(/\(/, "", start) 55 sub(/\(/, "", start)
63 end = $3 56 end = $3
@@ -107,17 +100,21 @@ active && /^[ \t]*\(/ {
107 } else if (flagarray[arg] == "PTMP-ONLY") { 100 } else if (flagarray[arg] == "PTMP-ONLY") {
108 flags = flags "\n\t\t\tNL80211_RRF_PTMP_ONLY | " 101 flags = flags "\n\t\t\tNL80211_RRF_PTMP_ONLY | "
109 } else if (flagarray[arg] == "PASSIVE-SCAN") { 102 } else if (flagarray[arg] == "PASSIVE-SCAN") {
110 flags = flags "\n\t\t\tNL80211_RRF_PASSIVE_SCAN | " 103 flags = flags "\n\t\t\tNL80211_RRF_NO_IR | "
111 } else if (flagarray[arg] == "NO-IBSS") { 104 } else if (flagarray[arg] == "NO-IBSS") {
112 flags = flags "\n\t\t\tNL80211_RRF_NO_IBSS | " 105 flags = flags "\n\t\t\tNL80211_RRF_NO_IR | "
106 } else if (flagarray[arg] == "NO-IR") {
107 flags = flags "\n\t\t\tNL80211_RRF_NO_IR | "
113 } 108 }
109
114 } 110 }
115 flags = flags "0" 111 flags = flags "0"
116 printf "\t\tREG_RULE(%d, %d, %d, %d, %d, %s),\n", start, end, bw, gain, power, flags 112 printf "\t\tREG_RULE(%d, %d, %d, %d, %d, %s),\n", start, end, bw, gain, power, flags
117 rules++ 113 rules++
118} 114}
119 115
120active && /^[ \t]*$/ { 116function print_tail_country()
117{
121 active = 0 118 active = 0
122 printf "\t},\n" 119 printf "\t},\n"
123 printf "\t.n_reg_rules = %d\n", rules 120 printf "\t.n_reg_rules = %d\n", rules
@@ -125,7 +122,29 @@ active && /^[ \t]*$/ {
125 rules = 0; 122 rules = 0;
126} 123}
127 124
125/^[ \t]*#/ {
126 # Ignore
127}
128
129!active && /^[ \t]*$/ {
130 # Ignore
131}
132
133!active && /country/ {
134 parse_country_head()
135}
136
137active && /^[ \t]*\(/ {
138 parse_reg_rule()
139}
140
141active && /^[ \t]*$/ {
142 print_tail_country()
143}
144
128END { 145END {
146 if (active)
147 print_tail_country()
129 print regdb "};" 148 print regdb "};"
130 print "" 149 print ""
131 print "int reg_regdb_size = ARRAY_SIZE(reg_regdb);" 150 print "int reg_regdb_size = ARRAY_SIZE(reg_regdb);"
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c
index 9d797df56649..f79105712949 100644
--- a/net/wireless/ibss.c
+++ b/net/wireless/ibss.c
@@ -274,7 +274,7 @@ int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
274 274
275 for (i = 0; i < sband->n_channels; i++) { 275 for (i = 0; i < sband->n_channels; i++) {
276 chan = &sband->channels[i]; 276 chan = &sband->channels[i];
277 if (chan->flags & IEEE80211_CHAN_NO_IBSS) 277 if (chan->flags & IEEE80211_CHAN_NO_IR)
278 continue; 278 continue;
279 if (chan->flags & IEEE80211_CHAN_DISABLED) 279 if (chan->flags & IEEE80211_CHAN_DISABLED)
280 continue; 280 continue;
@@ -345,7 +345,7 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
345 chan = ieee80211_get_channel(wdev->wiphy, freq); 345 chan = ieee80211_get_channel(wdev->wiphy, freq);
346 if (!chan) 346 if (!chan)
347 return -EINVAL; 347 return -EINVAL;
348 if (chan->flags & IEEE80211_CHAN_NO_IBSS || 348 if (chan->flags & IEEE80211_CHAN_NO_IR ||
349 chan->flags & IEEE80211_CHAN_DISABLED) 349 chan->flags & IEEE80211_CHAN_DISABLED)
350 return -EINVAL; 350 return -EINVAL;
351 } 351 }
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c
index 0553fd4d85ae..b0e1869de7de 100644
--- a/net/wireless/mesh.c
+++ b/net/wireless/mesh.c
@@ -141,8 +141,7 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
141 141
142 for (i = 0; i < sband->n_channels; i++) { 142 for (i = 0; i < sband->n_channels; i++) {
143 chan = &sband->channels[i]; 143 chan = &sband->channels[i];
144 if (chan->flags & (IEEE80211_CHAN_NO_IBSS | 144 if (chan->flags & (IEEE80211_CHAN_NO_IR |
145 IEEE80211_CHAN_PASSIVE_SCAN |
146 IEEE80211_CHAN_DISABLED | 145 IEEE80211_CHAN_DISABLED |
147 IEEE80211_CHAN_RADAR)) 146 IEEE80211_CHAN_RADAR))
148 continue; 147 continue;
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 6a6b1c8e907d..52cca05044a8 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -520,9 +520,7 @@ void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev)
520 520
521int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, 521int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
522 struct wireless_dev *wdev, 522 struct wireless_dev *wdev,
523 struct ieee80211_channel *chan, bool offchan, 523 struct cfg80211_mgmt_tx_params *params, u64 *cookie)
524 unsigned int wait, const u8 *buf, size_t len,
525 bool no_cck, bool dont_wait_for_ack, u64 *cookie)
526{ 524{
527 const struct ieee80211_mgmt *mgmt; 525 const struct ieee80211_mgmt *mgmt;
528 u16 stype; 526 u16 stype;
@@ -533,10 +531,10 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
533 if (!rdev->ops->mgmt_tx) 531 if (!rdev->ops->mgmt_tx)
534 return -EOPNOTSUPP; 532 return -EOPNOTSUPP;
535 533
536 if (len < 24 + 1) 534 if (params->len < 24 + 1)
537 return -EINVAL; 535 return -EINVAL;
538 536
539 mgmt = (const struct ieee80211_mgmt *) buf; 537 mgmt = (const struct ieee80211_mgmt *)params->buf;
540 538
541 if (!ieee80211_is_mgmt(mgmt->frame_control)) 539 if (!ieee80211_is_mgmt(mgmt->frame_control))
542 return -EINVAL; 540 return -EINVAL;
@@ -615,9 +613,7 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
615 return -EINVAL; 613 return -EINVAL;
616 614
617 /* Transmit the Action frame as requested by user space */ 615 /* Transmit the Action frame as requested by user space */
618 return rdev_mgmt_tx(rdev, wdev, chan, offchan, 616 return rdev_mgmt_tx(rdev, wdev, params, cookie);
619 wait, buf, len, no_cck, dont_wait_for_ack,
620 cookie);
621} 617}
622 618
623bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_mbm, 619bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_mbm,
@@ -763,12 +759,12 @@ void cfg80211_radar_event(struct wiphy *wiphy,
763EXPORT_SYMBOL(cfg80211_radar_event); 759EXPORT_SYMBOL(cfg80211_radar_event);
764 760
765void cfg80211_cac_event(struct net_device *netdev, 761void cfg80211_cac_event(struct net_device *netdev,
762 const struct cfg80211_chan_def *chandef,
766 enum nl80211_radar_event event, gfp_t gfp) 763 enum nl80211_radar_event event, gfp_t gfp)
767{ 764{
768 struct wireless_dev *wdev = netdev->ieee80211_ptr; 765 struct wireless_dev *wdev = netdev->ieee80211_ptr;
769 struct wiphy *wiphy = wdev->wiphy; 766 struct wiphy *wiphy = wdev->wiphy;
770 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); 767 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
771 struct cfg80211_chan_def chandef;
772 unsigned long timeout; 768 unsigned long timeout;
773 769
774 trace_cfg80211_cac_event(netdev, event); 770 trace_cfg80211_cac_event(netdev, event);
@@ -779,14 +775,12 @@ void cfg80211_cac_event(struct net_device *netdev,
779 if (WARN_ON(!wdev->channel)) 775 if (WARN_ON(!wdev->channel))
780 return; 776 return;
781 777
782 cfg80211_chandef_create(&chandef, wdev->channel, NL80211_CHAN_NO_HT);
783
784 switch (event) { 778 switch (event) {
785 case NL80211_RADAR_CAC_FINISHED: 779 case NL80211_RADAR_CAC_FINISHED:
786 timeout = wdev->cac_start_time + 780 timeout = wdev->cac_start_time +
787 msecs_to_jiffies(IEEE80211_DFS_MIN_CAC_TIME_MS); 781 msecs_to_jiffies(IEEE80211_DFS_MIN_CAC_TIME_MS);
788 WARN_ON(!time_after_eq(jiffies, timeout)); 782 WARN_ON(!time_after_eq(jiffies, timeout));
789 cfg80211_set_dfs_state(wiphy, &chandef, NL80211_DFS_AVAILABLE); 783 cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_AVAILABLE);
790 break; 784 break;
791 case NL80211_RADAR_CAC_ABORTED: 785 case NL80211_RADAR_CAC_ABORTED:
792 break; 786 break;
@@ -796,6 +790,6 @@ void cfg80211_cac_event(struct net_device *netdev,
796 } 790 }
797 wdev->cac_started = false; 791 wdev->cac_started = false;
798 792
799 nl80211_radar_notify(rdev, &chandef, event, netdev, gfp); 793 nl80211_radar_notify(rdev, chandef, event, netdev, gfp);
800} 794}
801EXPORT_SYMBOL(cfg80211_cac_event); 795EXPORT_SYMBOL(cfg80211_cac_event);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index a1eb21073176..efaa23e562b4 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -564,12 +564,12 @@ static int nl80211_msg_put_channel(struct sk_buff *msg,
564 if ((chan->flags & IEEE80211_CHAN_DISABLED) && 564 if ((chan->flags & IEEE80211_CHAN_DISABLED) &&
565 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_DISABLED)) 565 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_DISABLED))
566 goto nla_put_failure; 566 goto nla_put_failure;
567 if ((chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) && 567 if (chan->flags & IEEE80211_CHAN_NO_IR) {
568 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_PASSIVE_SCAN)) 568 if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_IR))
569 goto nla_put_failure; 569 goto nla_put_failure;
570 if ((chan->flags & IEEE80211_CHAN_NO_IBSS) && 570 if (nla_put_flag(msg, __NL80211_FREQUENCY_ATTR_NO_IBSS))
571 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_IBSS)) 571 goto nla_put_failure;
572 goto nla_put_failure; 572 }
573 if (chan->flags & IEEE80211_CHAN_RADAR) { 573 if (chan->flags & IEEE80211_CHAN_RADAR) {
574 if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR)) 574 if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR))
575 goto nla_put_failure; 575 goto nla_put_failure;
@@ -1247,10 +1247,6 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
1247 if ((dev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP) && 1247 if ((dev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP) &&
1248 nla_put_flag(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP)) 1248 nla_put_flag(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP))
1249 goto nla_put_failure; 1249 goto nla_put_failure;
1250 if ((dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ) &&
1251 nla_put_flag(msg, WIPHY_FLAG_SUPPORTS_5_10_MHZ))
1252 goto nla_put_failure;
1253
1254 state->split_start++; 1250 state->split_start++;
1255 if (state->split) 1251 if (state->split)
1256 break; 1252 break;
@@ -1579,6 +1575,11 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
1579 if (nl80211_send_coalesce(msg, dev)) 1575 if (nl80211_send_coalesce(msg, dev))
1580 goto nla_put_failure; 1576 goto nla_put_failure;
1581 1577
1578 if ((dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ) &&
1579 (nla_put_flag(msg, NL80211_ATTR_SUPPORT_5_MHZ) ||
1580 nla_put_flag(msg, NL80211_ATTR_SUPPORT_10_MHZ)))
1581 goto nla_put_failure;
1582
1582 /* done */ 1583 /* done */
1583 state->split_start = 0; 1584 state->split_start = 0;
1584 break; 1585 break;
@@ -2187,7 +2188,7 @@ static inline u64 wdev_id(struct wireless_dev *wdev)
2187} 2188}
2188 2189
2189static int nl80211_send_chandef(struct sk_buff *msg, 2190static int nl80211_send_chandef(struct sk_buff *msg,
2190 struct cfg80211_chan_def *chandef) 2191 const struct cfg80211_chan_def *chandef)
2191{ 2192{
2192 WARN_ON(!cfg80211_chandef_valid(chandef)); 2193 WARN_ON(!cfg80211_chandef_valid(chandef));
2193 2194
@@ -3236,6 +3237,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
3236 return PTR_ERR(params.acl); 3237 return PTR_ERR(params.acl);
3237 } 3238 }
3238 3239
3240 wdev_lock(wdev);
3239 err = rdev_start_ap(rdev, dev, &params); 3241 err = rdev_start_ap(rdev, dev, &params);
3240 if (!err) { 3242 if (!err) {
3241 wdev->preset_chandef = params.chandef; 3243 wdev->preset_chandef = params.chandef;
@@ -3244,6 +3246,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
3244 wdev->ssid_len = params.ssid_len; 3246 wdev->ssid_len = params.ssid_len;
3245 memcpy(wdev->ssid, params.ssid, wdev->ssid_len); 3247 memcpy(wdev->ssid, params.ssid, wdev->ssid_len);
3246 } 3248 }
3249 wdev_unlock(wdev);
3247 3250
3248 kfree(params.acl); 3251 kfree(params.acl);
3249 3252
@@ -3272,7 +3275,11 @@ static int nl80211_set_beacon(struct sk_buff *skb, struct genl_info *info)
3272 if (err) 3275 if (err)
3273 return err; 3276 return err;
3274 3277
3275 return rdev_change_beacon(rdev, dev, &params); 3278 wdev_lock(wdev);
3279 err = rdev_change_beacon(rdev, dev, &params);
3280 wdev_unlock(wdev);
3281
3282 return err;
3276} 3283}
3277 3284
3278static int nl80211_stop_ap(struct sk_buff *skb, struct genl_info *info) 3285static int nl80211_stop_ap(struct sk_buff *skb, struct genl_info *info)
@@ -4478,7 +4485,9 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
4478{ 4485{
4479 struct cfg80211_registered_device *rdev = info->user_ptr[0]; 4486 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4480 struct net_device *dev = info->user_ptr[1]; 4487 struct net_device *dev = info->user_ptr[1];
4488 struct wireless_dev *wdev = dev->ieee80211_ptr;
4481 struct bss_parameters params; 4489 struct bss_parameters params;
4490 int err;
4482 4491
4483 memset(&params, 0, sizeof(params)); 4492 memset(&params, 0, sizeof(params));
4484 /* default to not changing parameters */ 4493 /* default to not changing parameters */
@@ -4544,7 +4553,11 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
4544 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) 4553 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
4545 return -EOPNOTSUPP; 4554 return -EOPNOTSUPP;
4546 4555
4547 return rdev_change_bss(rdev, dev, &params); 4556 wdev_lock(wdev);
4557 err = rdev_change_bss(rdev, dev, &params);
4558 wdev_unlock(wdev);
4559
4560 return err;
4548} 4561}
4549 4562
4550static const struct nla_policy reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] = { 4563static const struct nla_policy reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] = {
@@ -5098,7 +5111,7 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
5098 char *alpha2 = NULL; 5111 char *alpha2 = NULL;
5099 int rem_reg_rules = 0, r = 0; 5112 int rem_reg_rules = 0, r = 0;
5100 u32 num_rules = 0, rule_idx = 0, size_of_regd; 5113 u32 num_rules = 0, rule_idx = 0, size_of_regd;
5101 u8 dfs_region = 0; 5114 enum nl80211_dfs_regions dfs_region = NL80211_DFS_UNSET;
5102 struct ieee80211_regdomain *rd = NULL; 5115 struct ieee80211_regdomain *rd = NULL;
5103 5116
5104 if (!info->attrs[NL80211_ATTR_REG_ALPHA2]) 5117 if (!info->attrs[NL80211_ATTR_REG_ALPHA2])
@@ -5119,6 +5132,9 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
5119 return -EINVAL; 5132 return -EINVAL;
5120 } 5133 }
5121 5134
5135 if (!reg_is_valid_request(alpha2))
5136 return -EINVAL;
5137
5122 size_of_regd = sizeof(struct ieee80211_regdomain) + 5138 size_of_regd = sizeof(struct ieee80211_regdomain) +
5123 num_rules * sizeof(struct ieee80211_reg_rule); 5139 num_rules * sizeof(struct ieee80211_reg_rule);
5124 5140
@@ -5361,10 +5377,8 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
5361 if (info->attrs[NL80211_ATTR_SCAN_FLAGS]) { 5377 if (info->attrs[NL80211_ATTR_SCAN_FLAGS]) {
5362 request->flags = nla_get_u32( 5378 request->flags = nla_get_u32(
5363 info->attrs[NL80211_ATTR_SCAN_FLAGS]); 5379 info->attrs[NL80211_ATTR_SCAN_FLAGS]);
5364 if (((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) && 5380 if ((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
5365 !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) || 5381 !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) {
5366 ((request->flags & NL80211_SCAN_FLAG_FLUSH) &&
5367 !(wiphy->features & NL80211_FEATURE_SCAN_FLUSH))) {
5368 err = -EOPNOTSUPP; 5382 err = -EOPNOTSUPP;
5369 goto out_free; 5383 goto out_free;
5370 } 5384 }
@@ -5604,10 +5618,8 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
5604 if (info->attrs[NL80211_ATTR_SCAN_FLAGS]) { 5618 if (info->attrs[NL80211_ATTR_SCAN_FLAGS]) {
5605 request->flags = nla_get_u32( 5619 request->flags = nla_get_u32(
5606 info->attrs[NL80211_ATTR_SCAN_FLAGS]); 5620 info->attrs[NL80211_ATTR_SCAN_FLAGS]);
5607 if (((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) && 5621 if ((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
5608 !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) || 5622 !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) {
5609 ((request->flags & NL80211_SCAN_FLAG_FLUSH) &&
5610 !(wiphy->features & NL80211_FEATURE_SCAN_FLUSH))) {
5611 err = -EOPNOTSUPP; 5623 err = -EOPNOTSUPP;
5612 goto out_free; 5624 goto out_free;
5613 } 5625 }
@@ -5670,7 +5682,7 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
5670 if (err == 0) 5682 if (err == 0)
5671 return -EINVAL; 5683 return -EINVAL;
5672 5684
5673 if (chandef.chan->dfs_state != NL80211_DFS_USABLE) 5685 if (!cfg80211_chandef_dfs_usable(wdev->wiphy, &chandef))
5674 return -EINVAL; 5686 return -EINVAL;
5675 5687
5676 if (!rdev->ops->start_radar_detection) 5688 if (!rdev->ops->start_radar_detection)
@@ -5810,7 +5822,11 @@ skip_beacons:
5810 if (info->attrs[NL80211_ATTR_CH_SWITCH_BLOCK_TX]) 5822 if (info->attrs[NL80211_ATTR_CH_SWITCH_BLOCK_TX])
5811 params.block_tx = true; 5823 params.block_tx = true;
5812 5824
5813 return rdev_channel_switch(rdev, dev, &params); 5825 wdev_lock(wdev);
5826 err = rdev_channel_switch(rdev, dev, &params);
5827 wdev_unlock(wdev);
5828
5829 return err;
5814} 5830}
5815 5831
5816static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb, 5832static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
@@ -7443,10 +7459,10 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
7443 void *hdr = NULL; 7459 void *hdr = NULL;
7444 u64 cookie; 7460 u64 cookie;
7445 struct sk_buff *msg = NULL; 7461 struct sk_buff *msg = NULL;
7446 unsigned int wait = 0; 7462 struct cfg80211_mgmt_tx_params params = {
7447 bool offchan, no_cck, dont_wait_for_ack; 7463 .dont_wait_for_ack =
7448 7464 info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK],
7449 dont_wait_for_ack = info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK]; 7465 };
7450 7466
7451 if (!info->attrs[NL80211_ATTR_FRAME]) 7467 if (!info->attrs[NL80211_ATTR_FRAME])
7452 return -EINVAL; 7468 return -EINVAL;
@@ -7473,24 +7489,24 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
7473 if (info->attrs[NL80211_ATTR_DURATION]) { 7489 if (info->attrs[NL80211_ATTR_DURATION]) {
7474 if (!(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX)) 7490 if (!(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX))
7475 return -EINVAL; 7491 return -EINVAL;
7476 wait = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]); 7492 params.wait = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]);
7477 7493
7478 /* 7494 /*
7479 * We should wait on the channel for at least a minimum amount 7495 * We should wait on the channel for at least a minimum amount
7480 * of time (10ms) but no longer than the driver supports. 7496 * of time (10ms) but no longer than the driver supports.
7481 */ 7497 */
7482 if (wait < NL80211_MIN_REMAIN_ON_CHANNEL_TIME || 7498 if (params.wait < NL80211_MIN_REMAIN_ON_CHANNEL_TIME ||
7483 wait > rdev->wiphy.max_remain_on_channel_duration) 7499 params.wait > rdev->wiphy.max_remain_on_channel_duration)
7484 return -EINVAL; 7500 return -EINVAL;
7485 7501
7486 } 7502 }
7487 7503
7488 offchan = info->attrs[NL80211_ATTR_OFFCHANNEL_TX_OK]; 7504 params.offchan = info->attrs[NL80211_ATTR_OFFCHANNEL_TX_OK];
7489 7505
7490 if (offchan && !(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX)) 7506 if (params.offchan && !(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX))
7491 return -EINVAL; 7507 return -EINVAL;
7492 7508
7493 no_cck = nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]); 7509 params.no_cck = nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);
7494 7510
7495 /* get the channel if any has been specified, otherwise pass NULL to 7511 /* get the channel if any has been specified, otherwise pass NULL to
7496 * the driver. The latter will use the current one 7512 * the driver. The latter will use the current one
@@ -7502,10 +7518,10 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
7502 return err; 7518 return err;
7503 } 7519 }
7504 7520
7505 if (!chandef.chan && offchan) 7521 if (!chandef.chan && params.offchan)
7506 return -EINVAL; 7522 return -EINVAL;
7507 7523
7508 if (!dont_wait_for_ack) { 7524 if (!params.dont_wait_for_ack) {
7509 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 7525 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
7510 if (!msg) 7526 if (!msg)
7511 return -ENOMEM; 7527 return -ENOMEM;
@@ -7518,10 +7534,10 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
7518 } 7534 }
7519 } 7535 }
7520 7536
7521 err = cfg80211_mlme_mgmt_tx(rdev, wdev, chandef.chan, offchan, wait, 7537 params.buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
7522 nla_data(info->attrs[NL80211_ATTR_FRAME]), 7538 params.len = nla_len(info->attrs[NL80211_ATTR_FRAME]);
7523 nla_len(info->attrs[NL80211_ATTR_FRAME]), 7539 params.chan = chandef.chan;
7524 no_cck, dont_wait_for_ack, &cookie); 7540 err = cfg80211_mlme_mgmt_tx(rdev, wdev, &params, &cookie);
7525 if (err) 7541 if (err)
7526 goto free_msg; 7542 goto free_msg;
7527 7543
@@ -10805,21 +10821,18 @@ void cfg80211_ch_switch_notify(struct net_device *dev,
10805 struct wiphy *wiphy = wdev->wiphy; 10821 struct wiphy *wiphy = wdev->wiphy;
10806 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); 10822 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
10807 10823
10808 trace_cfg80211_ch_switch_notify(dev, chandef); 10824 ASSERT_WDEV_LOCK(wdev);
10809 10825
10810 wdev_lock(wdev); 10826 trace_cfg80211_ch_switch_notify(dev, chandef);
10811 10827
10812 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && 10828 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
10813 wdev->iftype != NL80211_IFTYPE_P2P_GO && 10829 wdev->iftype != NL80211_IFTYPE_P2P_GO &&
10814 wdev->iftype != NL80211_IFTYPE_ADHOC && 10830 wdev->iftype != NL80211_IFTYPE_ADHOC &&
10815 wdev->iftype != NL80211_IFTYPE_MESH_POINT)) 10831 wdev->iftype != NL80211_IFTYPE_MESH_POINT))
10816 goto out; 10832 return;
10817 10833
10818 wdev->channel = chandef->chan; 10834 wdev->channel = chandef->chan;
10819 nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL); 10835 nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL);
10820out:
10821 wdev_unlock(wdev);
10822 return;
10823} 10836}
10824EXPORT_SYMBOL(cfg80211_ch_switch_notify); 10837EXPORT_SYMBOL(cfg80211_ch_switch_notify);
10825 10838
@@ -10878,7 +10891,7 @@ EXPORT_SYMBOL(cfg80211_cqm_txe_notify);
10878 10891
10879void 10892void
10880nl80211_radar_notify(struct cfg80211_registered_device *rdev, 10893nl80211_radar_notify(struct cfg80211_registered_device *rdev,
10881 struct cfg80211_chan_def *chandef, 10894 const struct cfg80211_chan_def *chandef,
10882 enum nl80211_radar_event event, 10895 enum nl80211_radar_event event,
10883 struct net_device *netdev, gfp_t gfp) 10896 struct net_device *netdev, gfp_t gfp)
10884{ 10897{
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h
index 2c0f2b3c07cb..b1b231324e10 100644
--- a/net/wireless/nl80211.h
+++ b/net/wireless/nl80211.h
@@ -70,7 +70,7 @@ int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
70 70
71void 71void
72nl80211_radar_notify(struct cfg80211_registered_device *rdev, 72nl80211_radar_notify(struct cfg80211_registered_device *rdev,
73 struct cfg80211_chan_def *chandef, 73 const struct cfg80211_chan_def *chandef,
74 enum nl80211_radar_event event, 74 enum nl80211_radar_event event,
75 struct net_device *netdev, gfp_t gfp); 75 struct net_device *netdev, gfp_t gfp);
76 76
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index 37ce9fdfe934..a6c03ab14a0d 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -624,16 +624,12 @@ rdev_cancel_remain_on_channel(struct cfg80211_registered_device *rdev,
624 624
625static inline int rdev_mgmt_tx(struct cfg80211_registered_device *rdev, 625static inline int rdev_mgmt_tx(struct cfg80211_registered_device *rdev,
626 struct wireless_dev *wdev, 626 struct wireless_dev *wdev,
627 struct ieee80211_channel *chan, bool offchan, 627 struct cfg80211_mgmt_tx_params *params,
628 unsigned int wait, const u8 *buf, size_t len, 628 u64 *cookie)
629 bool no_cck, bool dont_wait_for_ack, u64 *cookie)
630{ 629{
631 int ret; 630 int ret;
632 trace_rdev_mgmt_tx(&rdev->wiphy, wdev, chan, offchan, 631 trace_rdev_mgmt_tx(&rdev->wiphy, wdev, params);
633 wait, no_cck, dont_wait_for_ack); 632 ret = rdev->ops->mgmt_tx(&rdev->wiphy, wdev, params, cookie);
634 ret = rdev->ops->mgmt_tx(&rdev->wiphy, wdev, chan, offchan,
635 wait, buf, len, no_cck,
636 dont_wait_for_ack, cookie);
637 trace_rdev_return_int_cookie(&rdev->wiphy, ret, *cookie); 633 trace_rdev_return_int_cookie(&rdev->wiphy, ret, *cookie);
638 return ret; 634 return ret;
639} 635}
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 7da67fd0b418..ec54e1aac8e2 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -120,6 +120,21 @@ static const struct ieee80211_regdomain *get_wiphy_regdom(struct wiphy *wiphy)
120 return rtnl_dereference(wiphy->regd); 120 return rtnl_dereference(wiphy->regd);
121} 121}
122 122
123static const char *reg_dfs_region_str(enum nl80211_dfs_regions dfs_region)
124{
125 switch (dfs_region) {
126 case NL80211_DFS_UNSET:
127 return "unset";
128 case NL80211_DFS_FCC:
129 return "FCC";
130 case NL80211_DFS_ETSI:
131 return "ETSI";
132 case NL80211_DFS_JP:
133 return "JP";
134 }
135 return "Unknown";
136}
137
123static void rcu_free_regdom(const struct ieee80211_regdomain *r) 138static void rcu_free_regdom(const struct ieee80211_regdomain *r)
124{ 139{
125 if (!r) 140 if (!r)
@@ -163,35 +178,29 @@ static const struct ieee80211_regdomain world_regdom = {
163 REG_RULE(2412-10, 2462+10, 40, 6, 20, 0), 178 REG_RULE(2412-10, 2462+10, 40, 6, 20, 0),
164 /* IEEE 802.11b/g, channels 12..13. */ 179 /* IEEE 802.11b/g, channels 12..13. */
165 REG_RULE(2467-10, 2472+10, 40, 6, 20, 180 REG_RULE(2467-10, 2472+10, 40, 6, 20,
166 NL80211_RRF_PASSIVE_SCAN | 181 NL80211_RRF_NO_IR),
167 NL80211_RRF_NO_IBSS),
168 /* IEEE 802.11 channel 14 - Only JP enables 182 /* IEEE 802.11 channel 14 - Only JP enables
169 * this and for 802.11b only */ 183 * this and for 802.11b only */
170 REG_RULE(2484-10, 2484+10, 20, 6, 20, 184 REG_RULE(2484-10, 2484+10, 20, 6, 20,
171 NL80211_RRF_PASSIVE_SCAN | 185 NL80211_RRF_NO_IR |
172 NL80211_RRF_NO_IBSS |
173 NL80211_RRF_NO_OFDM), 186 NL80211_RRF_NO_OFDM),
174 /* IEEE 802.11a, channel 36..48 */ 187 /* IEEE 802.11a, channel 36..48 */
175 REG_RULE(5180-10, 5240+10, 160, 6, 20, 188 REG_RULE(5180-10, 5240+10, 160, 6, 20,
176 NL80211_RRF_PASSIVE_SCAN | 189 NL80211_RRF_NO_IR),
177 NL80211_RRF_NO_IBSS),
178 190
179 /* IEEE 802.11a, channel 52..64 - DFS required */ 191 /* IEEE 802.11a, channel 52..64 - DFS required */
180 REG_RULE(5260-10, 5320+10, 160, 6, 20, 192 REG_RULE(5260-10, 5320+10, 160, 6, 20,
181 NL80211_RRF_PASSIVE_SCAN | 193 NL80211_RRF_NO_IR |
182 NL80211_RRF_NO_IBSS |
183 NL80211_RRF_DFS), 194 NL80211_RRF_DFS),
184 195
185 /* IEEE 802.11a, channel 100..144 - DFS required */ 196 /* IEEE 802.11a, channel 100..144 - DFS required */
186 REG_RULE(5500-10, 5720+10, 160, 6, 20, 197 REG_RULE(5500-10, 5720+10, 160, 6, 20,
187 NL80211_RRF_PASSIVE_SCAN | 198 NL80211_RRF_NO_IR |
188 NL80211_RRF_NO_IBSS |
189 NL80211_RRF_DFS), 199 NL80211_RRF_DFS),
190 200
191 /* IEEE 802.11a, channel 149..165 */ 201 /* IEEE 802.11a, channel 149..165 */
192 REG_RULE(5745-10, 5825+10, 80, 6, 20, 202 REG_RULE(5745-10, 5825+10, 80, 6, 20,
193 NL80211_RRF_PASSIVE_SCAN | 203 NL80211_RRF_NO_IR),
194 NL80211_RRF_NO_IBSS),
195 204
196 /* IEEE 802.11ad (60gHz), channels 1..3 */ 205 /* IEEE 802.11ad (60gHz), channels 1..3 */
197 REG_RULE(56160+2160*1-1080, 56160+2160*3+1080, 2160, 0, 0, 0), 206 REG_RULE(56160+2160*1-1080, 56160+2160*3+1080, 2160, 0, 0, 0),
@@ -208,11 +217,26 @@ static char user_alpha2[2];
208module_param(ieee80211_regdom, charp, 0444); 217module_param(ieee80211_regdom, charp, 0444);
209MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); 218MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code");
210 219
220static void reg_kfree_last_request(void)
221{
222 struct regulatory_request *lr;
223
224 lr = get_last_request();
225
226 if (lr != &core_request_world && lr)
227 kfree_rcu(lr, rcu_head);
228}
229
230static void reg_update_last_request(struct regulatory_request *request)
231{
232 reg_kfree_last_request();
233 rcu_assign_pointer(last_request, request);
234}
235
211static void reset_regdomains(bool full_reset, 236static void reset_regdomains(bool full_reset,
212 const struct ieee80211_regdomain *new_regdom) 237 const struct ieee80211_regdomain *new_regdom)
213{ 238{
214 const struct ieee80211_regdomain *r; 239 const struct ieee80211_regdomain *r;
215 struct regulatory_request *lr;
216 240
217 ASSERT_RTNL(); 241 ASSERT_RTNL();
218 242
@@ -235,10 +259,7 @@ static void reset_regdomains(bool full_reset,
235 if (!full_reset) 259 if (!full_reset)
236 return; 260 return;
237 261
238 lr = get_last_request(); 262 reg_update_last_request(&core_request_world);
239 if (lr != &core_request_world && lr)
240 kfree_rcu(lr, rcu_head);
241 rcu_assign_pointer(last_request, &core_request_world);
242} 263}
243 264
244/* 265/*
@@ -456,7 +477,15 @@ static int call_crda(const char *alpha2)
456 return kobject_uevent(&reg_pdev->dev.kobj, KOBJ_CHANGE); 477 return kobject_uevent(&reg_pdev->dev.kobj, KOBJ_CHANGE);
457} 478}
458 479
459static bool reg_is_valid_request(const char *alpha2) 480static enum reg_request_treatment
481reg_call_crda(struct regulatory_request *request)
482{
483 if (call_crda(request->alpha2))
484 return REG_REQ_IGNORE;
485 return REG_REQ_OK;
486}
487
488bool reg_is_valid_request(const char *alpha2)
460{ 489{
461 struct regulatory_request *lr = get_last_request(); 490 struct regulatory_request *lr = get_last_request();
462 491
@@ -557,6 +586,20 @@ static bool freq_in_rule_band(const struct ieee80211_freq_range *freq_range,
557} 586}
558 587
559/* 588/*
589 * Later on we can perhaps use the more restrictive DFS
590 * region but we don't have information for that yet so
591 * for now simply disallow conflicts.
592 */
593static enum nl80211_dfs_regions
594reg_intersect_dfs_region(const enum nl80211_dfs_regions dfs_region1,
595 const enum nl80211_dfs_regions dfs_region2)
596{
597 if (dfs_region1 != dfs_region2)
598 return NL80211_DFS_UNSET;
599 return dfs_region1;
600}
601
602/*
560 * Helper for regdom_intersect(), this does the real 603 * Helper for regdom_intersect(), this does the real
561 * mathematical intersection fun 604 * mathematical intersection fun
562 */ 605 */
@@ -687,6 +730,8 @@ regdom_intersect(const struct ieee80211_regdomain *rd1,
687 rd->n_reg_rules = num_rules; 730 rd->n_reg_rules = num_rules;
688 rd->alpha2[0] = '9'; 731 rd->alpha2[0] = '9';
689 rd->alpha2[1] = '8'; 732 rd->alpha2[1] = '8';
733 rd->dfs_region = reg_intersect_dfs_region(rd1->dfs_region,
734 rd2->dfs_region);
690 735
691 return rd; 736 return rd;
692} 737}
@@ -698,10 +743,8 @@ regdom_intersect(const struct ieee80211_regdomain *rd1,
698static u32 map_regdom_flags(u32 rd_flags) 743static u32 map_regdom_flags(u32 rd_flags)
699{ 744{
700 u32 channel_flags = 0; 745 u32 channel_flags = 0;
701 if (rd_flags & NL80211_RRF_PASSIVE_SCAN) 746 if (rd_flags & NL80211_RRF_NO_IR_ALL)
702 channel_flags |= IEEE80211_CHAN_PASSIVE_SCAN; 747 channel_flags |= IEEE80211_CHAN_NO_IR;
703 if (rd_flags & NL80211_RRF_NO_IBSS)
704 channel_flags |= IEEE80211_CHAN_NO_IBSS;
705 if (rd_flags & NL80211_RRF_DFS) 748 if (rd_flags & NL80211_RRF_DFS)
706 channel_flags |= IEEE80211_CHAN_RADAR; 749 channel_flags |= IEEE80211_CHAN_RADAR;
707 if (rd_flags & NL80211_RRF_NO_OFDM) 750 if (rd_flags & NL80211_RRF_NO_OFDM)
@@ -854,8 +897,18 @@ static void handle_channel(struct wiphy *wiphy,
854 PTR_ERR(reg_rule) == -ERANGE) 897 PTR_ERR(reg_rule) == -ERANGE)
855 return; 898 return;
856 899
857 REG_DBG_PRINT("Disabling freq %d MHz\n", chan->center_freq); 900 if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
858 chan->flags |= IEEE80211_CHAN_DISABLED; 901 request_wiphy && request_wiphy == wiphy &&
902 request_wiphy->regulatory_flags & REGULATORY_STRICT_REG) {
903 REG_DBG_PRINT("Disabling freq %d MHz for good\n",
904 chan->center_freq);
905 chan->orig_flags |= IEEE80211_CHAN_DISABLED;
906 chan->flags = chan->orig_flags;
907 } else {
908 REG_DBG_PRINT("Disabling freq %d MHz\n",
909 chan->center_freq);
910 chan->flags |= IEEE80211_CHAN_DISABLED;
911 }
859 return; 912 return;
860 } 913 }
861 914
@@ -873,7 +926,7 @@ static void handle_channel(struct wiphy *wiphy,
873 926
874 if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER && 927 if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
875 request_wiphy && request_wiphy == wiphy && 928 request_wiphy && request_wiphy == wiphy &&
876 request_wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) { 929 request_wiphy->regulatory_flags & REGULATORY_STRICT_REG) {
877 /* 930 /*
878 * This guarantees the driver's requested regulatory domain 931 * This guarantees the driver's requested regulatory domain
879 * will always be used as a base for further regulatory 932 * will always be used as a base for further regulatory
@@ -899,13 +952,11 @@ static void handle_channel(struct wiphy *wiphy,
899 chan->max_reg_power = (int) MBM_TO_DBM(power_rule->max_eirp); 952 chan->max_reg_power = (int) MBM_TO_DBM(power_rule->max_eirp);
900 if (chan->orig_mpwr) { 953 if (chan->orig_mpwr) {
901 /* 954 /*
902 * Devices that have their own custom regulatory domain 955 * Devices that use REGULATORY_COUNTRY_IE_FOLLOW_POWER
903 * but also use WIPHY_FLAG_STRICT_REGULATORY will follow the 956 * will always follow the passed country IE power settings.
904 * passed country IE power settings.
905 */ 957 */
906 if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE && 958 if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE &&
907 wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY && 959 wiphy->regulatory_flags & REGULATORY_COUNTRY_IE_FOLLOW_POWER)
908 wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY)
909 chan->max_power = chan->max_reg_power; 960 chan->max_power = chan->max_reg_power;
910 else 961 else
911 chan->max_power = min(chan->orig_mpwr, 962 chan->max_power = min(chan->orig_mpwr,
@@ -975,8 +1026,8 @@ static bool reg_dev_ignore_cell_hint(struct wiphy *wiphy)
975 1026
976static bool wiphy_strict_alpha2_regd(struct wiphy *wiphy) 1027static bool wiphy_strict_alpha2_regd(struct wiphy *wiphy)
977{ 1028{
978 if (wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY && 1029 if (wiphy->regulatory_flags & REGULATORY_STRICT_REG &&
979 !(wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY)) 1030 !(wiphy->regulatory_flags & REGULATORY_CUSTOM_REG))
980 return true; 1031 return true;
981 return false; 1032 return false;
982} 1033}
@@ -994,7 +1045,7 @@ static bool ignore_reg_update(struct wiphy *wiphy,
994 } 1045 }
995 1046
996 if (initiator == NL80211_REGDOM_SET_BY_CORE && 1047 if (initiator == NL80211_REGDOM_SET_BY_CORE &&
997 wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY) { 1048 wiphy->regulatory_flags & REGULATORY_CUSTOM_REG) {
998 REG_DBG_PRINT("Ignoring regulatory request set by %s " 1049 REG_DBG_PRINT("Ignoring regulatory request set by %s "
999 "since the driver uses its own custom " 1050 "since the driver uses its own custom "
1000 "regulatory domain\n", 1051 "regulatory domain\n",
@@ -1032,7 +1083,7 @@ static bool reg_is_world_roaming(struct wiphy *wiphy)
1032 return true; 1083 return true;
1033 1084
1034 if (lr && lr->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE && 1085 if (lr && lr->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE &&
1035 wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY) 1086 wiphy->regulatory_flags & REGULATORY_CUSTOM_REG)
1036 return true; 1087 return true;
1037 1088
1038 return false; 1089 return false;
@@ -1060,19 +1111,14 @@ static void handle_reg_beacon(struct wiphy *wiphy, unsigned int chan_idx,
1060 if (!reg_is_world_roaming(wiphy)) 1111 if (!reg_is_world_roaming(wiphy))
1061 return; 1112 return;
1062 1113
1063 if (wiphy->flags & WIPHY_FLAG_DISABLE_BEACON_HINTS) 1114 if (wiphy->regulatory_flags & REGULATORY_DISABLE_BEACON_HINTS)
1064 return; 1115 return;
1065 1116
1066 chan_before.center_freq = chan->center_freq; 1117 chan_before.center_freq = chan->center_freq;
1067 chan_before.flags = chan->flags; 1118 chan_before.flags = chan->flags;
1068 1119
1069 if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) { 1120 if (chan->flags & IEEE80211_CHAN_NO_IR) {
1070 chan->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; 1121 chan->flags &= ~IEEE80211_CHAN_NO_IR;
1071 channel_changed = true;
1072 }
1073
1074 if (chan->flags & IEEE80211_CHAN_NO_IBSS) {
1075 chan->flags &= ~IEEE80211_CHAN_NO_IBSS;
1076 channel_changed = true; 1122 channel_changed = true;
1077 } 1123 }
1078 1124
@@ -1205,14 +1251,30 @@ static void reg_process_ht_flags(struct wiphy *wiphy)
1205 reg_process_ht_flags_band(wiphy, wiphy->bands[band]); 1251 reg_process_ht_flags_band(wiphy, wiphy->bands[band]);
1206} 1252}
1207 1253
1254static void reg_call_notifier(struct wiphy *wiphy,
1255 struct regulatory_request *request)
1256{
1257 if (wiphy->reg_notifier)
1258 wiphy->reg_notifier(wiphy, request);
1259}
1260
1208static void wiphy_update_regulatory(struct wiphy *wiphy, 1261static void wiphy_update_regulatory(struct wiphy *wiphy,
1209 enum nl80211_reg_initiator initiator) 1262 enum nl80211_reg_initiator initiator)
1210{ 1263{
1211 enum ieee80211_band band; 1264 enum ieee80211_band band;
1212 struct regulatory_request *lr = get_last_request(); 1265 struct regulatory_request *lr = get_last_request();
1213 1266
1214 if (ignore_reg_update(wiphy, initiator)) 1267 if (ignore_reg_update(wiphy, initiator)) {
1268 /*
1269 * Regulatory updates set by CORE are ignored for custom
1270 * regulatory cards. Let us notify the changes to the driver,
1271 * as some drivers used this to restore its orig_* reg domain.
1272 */
1273 if (initiator == NL80211_REGDOM_SET_BY_CORE &&
1274 wiphy->regulatory_flags & REGULATORY_CUSTOM_REG)
1275 reg_call_notifier(wiphy, lr);
1215 return; 1276 return;
1277 }
1216 1278
1217 lr->dfs_region = get_cfg80211_regdom()->dfs_region; 1279 lr->dfs_region = get_cfg80211_regdom()->dfs_region;
1218 1280
@@ -1221,9 +1283,7 @@ static void wiphy_update_regulatory(struct wiphy *wiphy,
1221 1283
1222 reg_process_beacons(wiphy); 1284 reg_process_beacons(wiphy);
1223 reg_process_ht_flags(wiphy); 1285 reg_process_ht_flags(wiphy);
1224 1286 reg_call_notifier(wiphy, lr);
1225 if (wiphy->reg_notifier)
1226 wiphy->reg_notifier(wiphy, lr);
1227} 1287}
1228 1288
1229static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator) 1289static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator)
@@ -1236,15 +1296,6 @@ static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator)
1236 list_for_each_entry(rdev, &cfg80211_rdev_list, list) { 1296 list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
1237 wiphy = &rdev->wiphy; 1297 wiphy = &rdev->wiphy;
1238 wiphy_update_regulatory(wiphy, initiator); 1298 wiphy_update_regulatory(wiphy, initiator);
1239 /*
1240 * Regulatory updates set by CORE are ignored for custom
1241 * regulatory cards. Let us notify the changes to the driver,
1242 * as some drivers used this to restore its orig_* reg domain.
1243 */
1244 if (initiator == NL80211_REGDOM_SET_BY_CORE &&
1245 wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY &&
1246 wiphy->reg_notifier)
1247 wiphy->reg_notifier(wiphy, get_last_request());
1248 } 1299 }
1249} 1300}
1250 1301
@@ -1263,7 +1314,8 @@ static void handle_channel_custom(struct wiphy *wiphy,
1263 if (IS_ERR(reg_rule)) { 1314 if (IS_ERR(reg_rule)) {
1264 REG_DBG_PRINT("Disabling freq %d MHz as custom regd has no rule that fits it\n", 1315 REG_DBG_PRINT("Disabling freq %d MHz as custom regd has no rule that fits it\n",
1265 chan->center_freq); 1316 chan->center_freq);
1266 chan->flags = IEEE80211_CHAN_DISABLED; 1317 chan->orig_flags |= IEEE80211_CHAN_DISABLED;
1318 chan->flags = chan->orig_flags;
1267 return; 1319 return;
1268 } 1320 }
1269 1321
@@ -1305,6 +1357,10 @@ void wiphy_apply_custom_regulatory(struct wiphy *wiphy,
1305 enum ieee80211_band band; 1357 enum ieee80211_band band;
1306 unsigned int bands_set = 0; 1358 unsigned int bands_set = 0;
1307 1359
1360 WARN(!(wiphy->regulatory_flags & REGULATORY_CUSTOM_REG),
1361 "wiphy should have REGULATORY_CUSTOM_REG\n");
1362 wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
1363
1308 for (band = 0; band < IEEE80211_NUM_BANDS; band++) { 1364 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
1309 if (!wiphy->bands[band]) 1365 if (!wiphy->bands[band])
1310 continue; 1366 continue;
@@ -1320,225 +1376,285 @@ void wiphy_apply_custom_regulatory(struct wiphy *wiphy,
1320} 1376}
1321EXPORT_SYMBOL(wiphy_apply_custom_regulatory); 1377EXPORT_SYMBOL(wiphy_apply_custom_regulatory);
1322 1378
1323/* This has the logic which determines when a new request 1379static void reg_set_request_processed(void)
1324 * should be ignored. */
1325static enum reg_request_treatment
1326get_reg_request_treatment(struct wiphy *wiphy,
1327 struct regulatory_request *pending_request)
1328{ 1380{
1329 struct wiphy *last_wiphy = NULL; 1381 bool need_more_processing = false;
1330 struct regulatory_request *lr = get_last_request(); 1382 struct regulatory_request *lr = get_last_request();
1331 1383
1332 /* All initial requests are respected */ 1384 lr->processed = true;
1333 if (!lr)
1334 return REG_REQ_OK;
1335 1385
1336 switch (pending_request->initiator) { 1386 spin_lock(&reg_requests_lock);
1337 case NL80211_REGDOM_SET_BY_CORE: 1387 if (!list_empty(&reg_requests_list))
1338 return REG_REQ_OK; 1388 need_more_processing = true;
1339 case NL80211_REGDOM_SET_BY_COUNTRY_IE: 1389 spin_unlock(&reg_requests_lock);
1340 if (reg_request_cell_base(lr)) {
1341 /* Trust a Cell base station over the AP's country IE */
1342 if (regdom_changes(pending_request->alpha2))
1343 return REG_REQ_IGNORE;
1344 return REG_REQ_ALREADY_SET;
1345 }
1346 1390
1347 last_wiphy = wiphy_idx_to_wiphy(lr->wiphy_idx); 1391 if (lr->initiator == NL80211_REGDOM_SET_BY_USER)
1392 cancel_delayed_work(&reg_timeout);
1348 1393
1349 if (unlikely(!is_an_alpha2(pending_request->alpha2))) 1394 if (need_more_processing)
1350 return -EINVAL; 1395 schedule_work(&reg_work);
1351 if (lr->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) { 1396}
1352 if (last_wiphy != wiphy) {
1353 /*
1354 * Two cards with two APs claiming different
1355 * Country IE alpha2s. We could
1356 * intersect them, but that seems unlikely
1357 * to be correct. Reject second one for now.
1358 */
1359 if (regdom_changes(pending_request->alpha2))
1360 return REG_REQ_IGNORE;
1361 return REG_REQ_ALREADY_SET;
1362 }
1363 /*
1364 * Two consecutive Country IE hints on the same wiphy.
1365 * This should be picked up early by the driver/stack
1366 */
1367 if (WARN_ON(regdom_changes(pending_request->alpha2)))
1368 return REG_REQ_OK;
1369 return REG_REQ_ALREADY_SET;
1370 }
1371 return REG_REQ_OK;
1372 case NL80211_REGDOM_SET_BY_DRIVER:
1373 if (lr->initiator == NL80211_REGDOM_SET_BY_CORE) {
1374 if (regdom_changes(pending_request->alpha2))
1375 return REG_REQ_OK;
1376 return REG_REQ_ALREADY_SET;
1377 }
1378 1397
1379 /* 1398/**
1380 * This would happen if you unplug and plug your card 1399 * reg_process_hint_core - process core regulatory requests
1381 * back in or if you add a new device for which the previously 1400 * @pending_request: a pending core regulatory request
1382 * loaded card also agrees on the regulatory domain. 1401 *
1383 */ 1402 * The wireless subsystem can use this function to process
1384 if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER && 1403 * a regulatory request issued by the regulatory core.
1385 !regdom_changes(pending_request->alpha2)) 1404 *
1386 return REG_REQ_ALREADY_SET; 1405 * Returns one of the different reg request treatment values.
1406 */
1407static enum reg_request_treatment
1408reg_process_hint_core(struct regulatory_request *core_request)
1409{
1410
1411 core_request->intersect = false;
1412 core_request->processed = false;
1413
1414 reg_update_last_request(core_request);
1387 1415
1416 return reg_call_crda(core_request);
1417}
1418
1419static enum reg_request_treatment
1420__reg_process_hint_user(struct regulatory_request *user_request)
1421{
1422 struct regulatory_request *lr = get_last_request();
1423
1424 if (reg_request_cell_base(user_request))
1425 return reg_ignore_cell_hint(user_request);
1426
1427 if (reg_request_cell_base(lr))
1428 return REG_REQ_IGNORE;
1429
1430 if (lr->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE)
1388 return REG_REQ_INTERSECT; 1431 return REG_REQ_INTERSECT;
1389 case NL80211_REGDOM_SET_BY_USER: 1432 /*
1390 if (reg_request_cell_base(pending_request)) 1433 * If the user knows better the user should set the regdom
1391 return reg_ignore_cell_hint(pending_request); 1434 * to their country before the IE is picked up
1435 */
1436 if (lr->initiator == NL80211_REGDOM_SET_BY_USER &&
1437 lr->intersect)
1438 return REG_REQ_IGNORE;
1439 /*
1440 * Process user requests only after previous user/driver/core
1441 * requests have been processed
1442 */
1443 if ((lr->initiator == NL80211_REGDOM_SET_BY_CORE ||
1444 lr->initiator == NL80211_REGDOM_SET_BY_DRIVER ||
1445 lr->initiator == NL80211_REGDOM_SET_BY_USER) &&
1446 regdom_changes(lr->alpha2))
1447 return REG_REQ_IGNORE;
1392 1448
1393 if (reg_request_cell_base(lr)) 1449 if (!regdom_changes(user_request->alpha2))
1394 return REG_REQ_IGNORE; 1450 return REG_REQ_ALREADY_SET;
1395 1451
1396 if (lr->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) 1452 return REG_REQ_OK;
1397 return REG_REQ_INTERSECT; 1453}
1398 /*
1399 * If the user knows better the user should set the regdom
1400 * to their country before the IE is picked up
1401 */
1402 if (lr->initiator == NL80211_REGDOM_SET_BY_USER &&
1403 lr->intersect)
1404 return REG_REQ_IGNORE;
1405 /*
1406 * Process user requests only after previous user/driver/core
1407 * requests have been processed
1408 */
1409 if ((lr->initiator == NL80211_REGDOM_SET_BY_CORE ||
1410 lr->initiator == NL80211_REGDOM_SET_BY_DRIVER ||
1411 lr->initiator == NL80211_REGDOM_SET_BY_USER) &&
1412 regdom_changes(lr->alpha2))
1413 return REG_REQ_IGNORE;
1414 1454
1415 if (!regdom_changes(pending_request->alpha2)) 1455/**
1416 return REG_REQ_ALREADY_SET; 1456 * reg_process_hint_user - process user regulatory requests
1457 * @user_request: a pending user regulatory request
1458 *
1459 * The wireless subsystem can use this function to process
1460 * a regulatory request initiated by userspace.
1461 *
1462 * Returns one of the different reg request treatment values.
1463 */
1464static enum reg_request_treatment
1465reg_process_hint_user(struct regulatory_request *user_request)
1466{
1467 enum reg_request_treatment treatment;
1417 1468
1418 return REG_REQ_OK; 1469 treatment = __reg_process_hint_user(user_request);
1470 if (treatment == REG_REQ_IGNORE ||
1471 treatment == REG_REQ_ALREADY_SET) {
1472 kfree(user_request);
1473 return treatment;
1419 } 1474 }
1420 1475
1421 return REG_REQ_IGNORE; 1476 user_request->intersect = treatment == REG_REQ_INTERSECT;
1477 user_request->processed = false;
1478
1479 reg_update_last_request(user_request);
1480
1481 user_alpha2[0] = user_request->alpha2[0];
1482 user_alpha2[1] = user_request->alpha2[1];
1483
1484 return reg_call_crda(user_request);
1422} 1485}
1423 1486
1424static void reg_set_request_processed(void) 1487static enum reg_request_treatment
1488__reg_process_hint_driver(struct regulatory_request *driver_request)
1425{ 1489{
1426 bool need_more_processing = false;
1427 struct regulatory_request *lr = get_last_request(); 1490 struct regulatory_request *lr = get_last_request();
1428 1491
1429 lr->processed = true; 1492 if (lr->initiator == NL80211_REGDOM_SET_BY_CORE) {
1430 1493 if (regdom_changes(driver_request->alpha2))
1431 spin_lock(&reg_requests_lock); 1494 return REG_REQ_OK;
1432 if (!list_empty(&reg_requests_list)) 1495 return REG_REQ_ALREADY_SET;
1433 need_more_processing = true; 1496 }
1434 spin_unlock(&reg_requests_lock);
1435 1497
1436 if (lr->initiator == NL80211_REGDOM_SET_BY_USER) 1498 /*
1437 cancel_delayed_work(&reg_timeout); 1499 * This would happen if you unplug and plug your card
1500 * back in or if you add a new device for which the previously
1501 * loaded card also agrees on the regulatory domain.
1502 */
1503 if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
1504 !regdom_changes(driver_request->alpha2))
1505 return REG_REQ_ALREADY_SET;
1438 1506
1439 if (need_more_processing) 1507 return REG_REQ_INTERSECT;
1440 schedule_work(&reg_work);
1441} 1508}
1442 1509
1443/** 1510/**
1444 * __regulatory_hint - hint to the wireless core a regulatory domain 1511 * reg_process_hint_driver - process driver regulatory requests
1445 * @wiphy: if the hint comes from country information from an AP, this 1512 * @driver_request: a pending driver regulatory request
1446 * is required to be set to the wiphy that received the information
1447 * @pending_request: the regulatory request currently being processed
1448 * 1513 *
1449 * The Wireless subsystem can use this function to hint to the wireless core 1514 * The wireless subsystem can use this function to process
1450 * what it believes should be the current regulatory domain. 1515 * a regulatory request issued by an 802.11 driver.
1451 * 1516 *
1452 * Returns one of the different reg request treatment values. 1517 * Returns one of the different reg request treatment values.
1453 */ 1518 */
1454static enum reg_request_treatment 1519static enum reg_request_treatment
1455__regulatory_hint(struct wiphy *wiphy, 1520reg_process_hint_driver(struct wiphy *wiphy,
1456 struct regulatory_request *pending_request) 1521 struct regulatory_request *driver_request)
1457{ 1522{
1458 const struct ieee80211_regdomain *regd; 1523 const struct ieee80211_regdomain *regd;
1459 bool intersect = false;
1460 enum reg_request_treatment treatment; 1524 enum reg_request_treatment treatment;
1461 struct regulatory_request *lr;
1462 1525
1463 treatment = get_reg_request_treatment(wiphy, pending_request); 1526 treatment = __reg_process_hint_driver(driver_request);
1464 1527
1465 switch (treatment) { 1528 switch (treatment) {
1466 case REG_REQ_INTERSECT:
1467 if (pending_request->initiator ==
1468 NL80211_REGDOM_SET_BY_DRIVER) {
1469 regd = reg_copy_regd(get_cfg80211_regdom());
1470 if (IS_ERR(regd)) {
1471 kfree(pending_request);
1472 return PTR_ERR(regd);
1473 }
1474 rcu_assign_pointer(wiphy->regd, regd);
1475 }
1476 intersect = true;
1477 break;
1478 case REG_REQ_OK: 1529 case REG_REQ_OK:
1479 break; 1530 break;
1480 default: 1531 case REG_REQ_IGNORE:
1481 /* 1532 kfree(driver_request);
1482 * If the regulatory domain being requested by the
1483 * driver has already been set just copy it to the
1484 * wiphy
1485 */
1486 if (treatment == REG_REQ_ALREADY_SET &&
1487 pending_request->initiator == NL80211_REGDOM_SET_BY_DRIVER) {
1488 regd = reg_copy_regd(get_cfg80211_regdom());
1489 if (IS_ERR(regd)) {
1490 kfree(pending_request);
1491 return REG_REQ_IGNORE;
1492 }
1493 treatment = REG_REQ_ALREADY_SET;
1494 rcu_assign_pointer(wiphy->regd, regd);
1495 goto new_request;
1496 }
1497 kfree(pending_request);
1498 return treatment; 1533 return treatment;
1534 case REG_REQ_INTERSECT:
1535 /* fall through */
1536 case REG_REQ_ALREADY_SET:
1537 regd = reg_copy_regd(get_cfg80211_regdom());
1538 if (IS_ERR(regd)) {
1539 kfree(driver_request);
1540 return REG_REQ_IGNORE;
1541 }
1542 rcu_assign_pointer(wiphy->regd, regd);
1499 } 1543 }
1500 1544
1501new_request:
1502 lr = get_last_request();
1503 if (lr != &core_request_world && lr)
1504 kfree_rcu(lr, rcu_head);
1505 1545
1506 pending_request->intersect = intersect; 1546 driver_request->intersect = treatment == REG_REQ_INTERSECT;
1507 pending_request->processed = false; 1547 driver_request->processed = false;
1508 rcu_assign_pointer(last_request, pending_request);
1509 lr = pending_request;
1510 1548
1511 pending_request = NULL; 1549 reg_update_last_request(driver_request);
1512 1550
1513 if (lr->initiator == NL80211_REGDOM_SET_BY_USER) { 1551 /*
1514 user_alpha2[0] = lr->alpha2[0]; 1552 * Since CRDA will not be called in this case as we already
1515 user_alpha2[1] = lr->alpha2[1]; 1553 * have applied the requested regulatory domain before we just
1554 * inform userspace we have processed the request
1555 */
1556 if (treatment == REG_REQ_ALREADY_SET) {
1557 nl80211_send_reg_change_event(driver_request);
1558 reg_set_request_processed();
1559 return treatment;
1516 } 1560 }
1517 1561
1518 /* When r == REG_REQ_INTERSECT we do need to call CRDA */ 1562 return reg_call_crda(driver_request);
1519 if (treatment != REG_REQ_OK && treatment != REG_REQ_INTERSECT) { 1563}
1564
1565static enum reg_request_treatment
1566__reg_process_hint_country_ie(struct wiphy *wiphy,
1567 struct regulatory_request *country_ie_request)
1568{
1569 struct wiphy *last_wiphy = NULL;
1570 struct regulatory_request *lr = get_last_request();
1571
1572 if (reg_request_cell_base(lr)) {
1573 /* Trust a Cell base station over the AP's country IE */
1574 if (regdom_changes(country_ie_request->alpha2))
1575 return REG_REQ_IGNORE;
1576 return REG_REQ_ALREADY_SET;
1577 } else {
1578 if (wiphy->regulatory_flags & REGULATORY_COUNTRY_IE_IGNORE)
1579 return REG_REQ_IGNORE;
1580 }
1581
1582 if (unlikely(!is_an_alpha2(country_ie_request->alpha2)))
1583 return -EINVAL;
1584
1585 if (lr->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE)
1586 return REG_REQ_OK;
1587
1588 last_wiphy = wiphy_idx_to_wiphy(lr->wiphy_idx);
1589
1590 if (last_wiphy != wiphy) {
1520 /* 1591 /*
1521 * Since CRDA will not be called in this case as we already 1592 * Two cards with two APs claiming different
1522 * have applied the requested regulatory domain before we just 1593 * Country IE alpha2s. We could
1523 * inform userspace we have processed the request 1594 * intersect them, but that seems unlikely
1595 * to be correct. Reject second one for now.
1524 */ 1596 */
1525 if (treatment == REG_REQ_ALREADY_SET) { 1597 if (regdom_changes(country_ie_request->alpha2))
1526 nl80211_send_reg_change_event(lr); 1598 return REG_REQ_IGNORE;
1527 reg_set_request_processed(); 1599 return REG_REQ_ALREADY_SET;
1528 }
1529 return treatment;
1530 } 1600 }
1601 /*
1602 * Two consecutive Country IE hints on the same wiphy.
1603 * This should be picked up early by the driver/stack
1604 */
1605 if (WARN_ON(regdom_changes(country_ie_request->alpha2)))
1606 return REG_REQ_OK;
1607 return REG_REQ_ALREADY_SET;
1608}
1609
1610/**
1611 * reg_process_hint_country_ie - process regulatory requests from country IEs
1612 * @country_ie_request: a regulatory request from a country IE
1613 *
1614 * The wireless subsystem can use this function to process
1615 * a regulatory request issued by a country Information Element.
1616 *
1617 * Returns one of the different reg request treatment values.
1618 */
1619static enum reg_request_treatment
1620reg_process_hint_country_ie(struct wiphy *wiphy,
1621 struct regulatory_request *country_ie_request)
1622{
1623 enum reg_request_treatment treatment;
1624
1625 treatment = __reg_process_hint_country_ie(wiphy, country_ie_request);
1531 1626
1532 if (call_crda(lr->alpha2)) 1627 switch (treatment) {
1628 case REG_REQ_OK:
1629 break;
1630 case REG_REQ_IGNORE:
1631 /* fall through */
1632 case REG_REQ_ALREADY_SET:
1633 kfree(country_ie_request);
1634 return treatment;
1635 case REG_REQ_INTERSECT:
1636 kfree(country_ie_request);
1637 /*
1638 * This doesn't happen yet, not sure we
1639 * ever want to support it for this case.
1640 */
1641 WARN_ONCE(1, "Unexpected intersection for country IEs");
1533 return REG_REQ_IGNORE; 1642 return REG_REQ_IGNORE;
1534 return REG_REQ_OK; 1643 }
1644
1645 country_ie_request->intersect = false;
1646 country_ie_request->processed = false;
1647
1648 reg_update_last_request(country_ie_request);
1649
1650 return reg_call_crda(country_ie_request);
1535} 1651}
1536 1652
1537/* This processes *all* regulatory hints */ 1653/* This processes *all* regulatory hints */
1538static void reg_process_hint(struct regulatory_request *reg_request, 1654static void reg_process_hint(struct regulatory_request *reg_request)
1539 enum nl80211_reg_initiator reg_initiator)
1540{ 1655{
1541 struct wiphy *wiphy = NULL; 1656 struct wiphy *wiphy = NULL;
1657 enum reg_request_treatment treatment;
1542 1658
1543 if (WARN_ON(!reg_request->alpha2)) 1659 if (WARN_ON(!reg_request->alpha2))
1544 return; 1660 return;
@@ -1546,23 +1662,37 @@ static void reg_process_hint(struct regulatory_request *reg_request,
1546 if (reg_request->wiphy_idx != WIPHY_IDX_INVALID) 1662 if (reg_request->wiphy_idx != WIPHY_IDX_INVALID)
1547 wiphy = wiphy_idx_to_wiphy(reg_request->wiphy_idx); 1663 wiphy = wiphy_idx_to_wiphy(reg_request->wiphy_idx);
1548 1664
1549 if (reg_initiator == NL80211_REGDOM_SET_BY_DRIVER && !wiphy) { 1665 if (reg_request->initiator == NL80211_REGDOM_SET_BY_DRIVER && !wiphy) {
1550 kfree(reg_request); 1666 kfree(reg_request);
1551 return; 1667 return;
1552 } 1668 }
1553 1669
1554 switch (__regulatory_hint(wiphy, reg_request)) { 1670 switch (reg_request->initiator) {
1555 case REG_REQ_ALREADY_SET: 1671 case NL80211_REGDOM_SET_BY_CORE:
1556 /* This is required so that the orig_* parameters are saved */ 1672 reg_process_hint_core(reg_request);
1557 if (wiphy && wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) 1673 return;
1558 wiphy_update_regulatory(wiphy, reg_initiator); 1674 case NL80211_REGDOM_SET_BY_USER:
1675 treatment = reg_process_hint_user(reg_request);
1676 if (treatment == REG_REQ_OK ||
1677 treatment == REG_REQ_ALREADY_SET)
1678 return;
1679 schedule_delayed_work(&reg_timeout, msecs_to_jiffies(3142));
1680 return;
1681 case NL80211_REGDOM_SET_BY_DRIVER:
1682 treatment = reg_process_hint_driver(wiphy, reg_request);
1559 break; 1683 break;
1560 default: 1684 case NL80211_REGDOM_SET_BY_COUNTRY_IE:
1561 if (reg_initiator == NL80211_REGDOM_SET_BY_USER) 1685 treatment = reg_process_hint_country_ie(wiphy, reg_request);
1562 schedule_delayed_work(&reg_timeout,
1563 msecs_to_jiffies(3142));
1564 break; 1686 break;
1687 default:
1688 WARN(1, "invalid initiator %d\n", reg_request->initiator);
1689 return;
1565 } 1690 }
1691
1692 /* This is required so that the orig_* parameters are saved */
1693 if (treatment == REG_REQ_ALREADY_SET && wiphy &&
1694 wiphy->regulatory_flags & REGULATORY_STRICT_REG)
1695 wiphy_update_regulatory(wiphy, reg_request->initiator);
1566} 1696}
1567 1697
1568/* 1698/*
@@ -1596,7 +1726,7 @@ static void reg_process_pending_hints(void)
1596 1726
1597 spin_unlock(&reg_requests_lock); 1727 spin_unlock(&reg_requests_lock);
1598 1728
1599 reg_process_hint(reg_request, reg_request->initiator); 1729 reg_process_hint(reg_request);
1600} 1730}
1601 1731
1602/* Processes beacon hints -- this has nothing to do with country IEs */ 1732/* Processes beacon hints -- this has nothing to do with country IEs */
@@ -1888,7 +2018,7 @@ static void restore_regulatory_settings(bool reset_user)
1888 world_alpha2[1] = cfg80211_world_regdom->alpha2[1]; 2018 world_alpha2[1] = cfg80211_world_regdom->alpha2[1];
1889 2019
1890 list_for_each_entry(rdev, &cfg80211_rdev_list, list) { 2020 list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
1891 if (rdev->wiphy.flags & WIPHY_FLAG_CUSTOM_REGULATORY) 2021 if (rdev->wiphy.regulatory_flags & REGULATORY_CUSTOM_REG)
1892 restore_custom_reg_settings(&rdev->wiphy); 2022 restore_custom_reg_settings(&rdev->wiphy);
1893 } 2023 }
1894 2024
@@ -2016,7 +2146,7 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd)
2016 } 2146 }
2017} 2147}
2018 2148
2019bool reg_supported_dfs_region(u8 dfs_region) 2149bool reg_supported_dfs_region(enum nl80211_dfs_regions dfs_region)
2020{ 2150{
2021 switch (dfs_region) { 2151 switch (dfs_region) {
2022 case NL80211_DFS_UNSET: 2152 case NL80211_DFS_UNSET:
@@ -2031,27 +2161,6 @@ bool reg_supported_dfs_region(u8 dfs_region)
2031 } 2161 }
2032} 2162}
2033 2163
2034static void print_dfs_region(u8 dfs_region)
2035{
2036 if (!dfs_region)
2037 return;
2038
2039 switch (dfs_region) {
2040 case NL80211_DFS_FCC:
2041 pr_info(" DFS Master region FCC");
2042 break;
2043 case NL80211_DFS_ETSI:
2044 pr_info(" DFS Master region ETSI");
2045 break;
2046 case NL80211_DFS_JP:
2047 pr_info(" DFS Master region JP");
2048 break;
2049 default:
2050 pr_info(" DFS Master region Unknown");
2051 break;
2052 }
2053}
2054
2055static void print_regdomain(const struct ieee80211_regdomain *rd) 2164static void print_regdomain(const struct ieee80211_regdomain *rd)
2056{ 2165{
2057 struct regulatory_request *lr = get_last_request(); 2166 struct regulatory_request *lr = get_last_request();
@@ -2083,7 +2192,7 @@ static void print_regdomain(const struct ieee80211_regdomain *rd)
2083 } 2192 }
2084 } 2193 }
2085 2194
2086 print_dfs_region(rd->dfs_region); 2195 pr_info(" DFS Master region: %s", reg_dfs_region_str(rd->dfs_region));
2087 print_rd_rules(rd); 2196 print_rd_rules(rd);
2088} 2197}
2089 2198
@@ -2093,48 +2202,60 @@ static void print_regdomain_info(const struct ieee80211_regdomain *rd)
2093 print_rd_rules(rd); 2202 print_rd_rules(rd);
2094} 2203}
2095 2204
2096/* Takes ownership of rd only if it doesn't fail */ 2205static int reg_set_rd_core(const struct ieee80211_regdomain *rd)
2097static int __set_regdom(const struct ieee80211_regdomain *rd) 2206{
2207 if (!is_world_regdom(rd->alpha2))
2208 return -EINVAL;
2209 update_world_regdomain(rd);
2210 return 0;
2211}
2212
2213static int reg_set_rd_user(const struct ieee80211_regdomain *rd,
2214 struct regulatory_request *user_request)
2098{ 2215{
2099 const struct ieee80211_regdomain *regd;
2100 const struct ieee80211_regdomain *intersected_rd = NULL; 2216 const struct ieee80211_regdomain *intersected_rd = NULL;
2101 struct wiphy *request_wiphy;
2102 struct regulatory_request *lr = get_last_request();
2103 2217
2104 /* Some basic sanity checks first */ 2218 if (is_world_regdom(rd->alpha2))
2219 return -EINVAL;
2220
2221 if (!regdom_changes(rd->alpha2))
2222 return -EALREADY;
2105 2223
2106 if (!reg_is_valid_request(rd->alpha2)) 2224 if (!is_valid_rd(rd)) {
2225 pr_err("Invalid regulatory domain detected:\n");
2226 print_regdomain_info(rd);
2107 return -EINVAL; 2227 return -EINVAL;
2228 }
2108 2229
2109 if (is_world_regdom(rd->alpha2)) { 2230 if (!user_request->intersect) {
2110 update_world_regdomain(rd); 2231 reset_regdomains(false, rd);
2111 return 0; 2232 return 0;
2112 } 2233 }
2113 2234
2114 if (!is_alpha2_set(rd->alpha2) && !is_an_alpha2(rd->alpha2) && 2235 intersected_rd = regdom_intersect(rd, get_cfg80211_regdom());
2115 !is_unknown_alpha2(rd->alpha2)) 2236 if (!intersected_rd)
2116 return -EINVAL; 2237 return -EINVAL;
2117 2238
2118 /* 2239 kfree(rd);
2119 * Lets only bother proceeding on the same alpha2 if the current 2240 rd = NULL;
2120 * rd is non static (it means CRDA was present and was used last) 2241 reset_regdomains(false, intersected_rd);
2121 * and the pending request came in from a country IE
2122 */
2123 if (lr->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) {
2124 /*
2125 * If someone else asked us to change the rd lets only bother
2126 * checking if the alpha2 changes if CRDA was already called
2127 */
2128 if (!regdom_changes(rd->alpha2))
2129 return -EALREADY;
2130 }
2131 2242
2132 /* 2243 return 0;
2133 * Now lets set the regulatory domain, update all driver channels 2244}
2134 * and finally inform them of what we have done, in case they want 2245
2135 * to review or adjust their own settings based on their own 2246static int reg_set_rd_driver(const struct ieee80211_regdomain *rd,
2136 * internal EEPROM data 2247 struct regulatory_request *driver_request)
2137 */ 2248{
2249 const struct ieee80211_regdomain *regd;
2250 const struct ieee80211_regdomain *intersected_rd = NULL;
2251 const struct ieee80211_regdomain *tmp;
2252 struct wiphy *request_wiphy;
2253
2254 if (is_world_regdom(rd->alpha2))
2255 return -EINVAL;
2256
2257 if (!regdom_changes(rd->alpha2))
2258 return -EALREADY;
2138 2259
2139 if (!is_valid_rd(rd)) { 2260 if (!is_valid_rd(rd)) {
2140 pr_err("Invalid regulatory domain detected:\n"); 2261 pr_err("Invalid regulatory domain detected:\n");
@@ -2142,29 +2263,13 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
2142 return -EINVAL; 2263 return -EINVAL;
2143 } 2264 }
2144 2265
2145 request_wiphy = wiphy_idx_to_wiphy(lr->wiphy_idx); 2266 request_wiphy = wiphy_idx_to_wiphy(driver_request->wiphy_idx);
2146 if (!request_wiphy && 2267 if (!request_wiphy) {
2147 (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER ||
2148 lr->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE)) {
2149 schedule_delayed_work(&reg_timeout, 0); 2268 schedule_delayed_work(&reg_timeout, 0);
2150 return -ENODEV; 2269 return -ENODEV;
2151 } 2270 }
2152 2271
2153 if (!lr->intersect) { 2272 if (!driver_request->intersect) {
2154 if (lr->initiator != NL80211_REGDOM_SET_BY_DRIVER) {
2155 reset_regdomains(false, rd);
2156 return 0;
2157 }
2158
2159 /*
2160 * For a driver hint, lets copy the regulatory domain the
2161 * driver wanted to the wiphy to deal with conflicts
2162 */
2163
2164 /*
2165 * Userspace could have sent two replies with only
2166 * one kernel request.
2167 */
2168 if (request_wiphy->regd) 2273 if (request_wiphy->regd)
2169 return -EALREADY; 2274 return -EALREADY;
2170 2275
@@ -2177,38 +2282,59 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
2177 return 0; 2282 return 0;
2178 } 2283 }
2179 2284
2180 /* Intersection requires a bit more work */ 2285 intersected_rd = regdom_intersect(rd, get_cfg80211_regdom());
2286 if (!intersected_rd)
2287 return -EINVAL;
2181 2288
2182 if (lr->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) { 2289 /*
2183 intersected_rd = regdom_intersect(rd, get_cfg80211_regdom()); 2290 * We can trash what CRDA provided now.
2184 if (!intersected_rd) 2291 * However if a driver requested this specific regulatory
2185 return -EINVAL; 2292 * domain we keep it for its private use
2293 */
2294 tmp = get_wiphy_regdom(request_wiphy);
2295 rcu_assign_pointer(request_wiphy->regd, rd);
2296 rcu_free_regdom(tmp);
2186 2297
2187 /* 2298 rd = NULL;
2188 * We can trash what CRDA provided now.
2189 * However if a driver requested this specific regulatory
2190 * domain we keep it for its private use
2191 */
2192 if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER) {
2193 const struct ieee80211_regdomain *tmp;
2194 2299
2195 tmp = get_wiphy_regdom(request_wiphy); 2300 reset_regdomains(false, intersected_rd);
2196 rcu_assign_pointer(request_wiphy->regd, rd);
2197 rcu_free_regdom(tmp);
2198 } else {
2199 kfree(rd);
2200 }
2201 2301
2202 rd = NULL; 2302 return 0;
2303}
2203 2304
2204 reset_regdomains(false, intersected_rd); 2305static int reg_set_rd_country_ie(const struct ieee80211_regdomain *rd,
2306 struct regulatory_request *country_ie_request)
2307{
2308 struct wiphy *request_wiphy;
2205 2309
2206 return 0; 2310 if (!is_alpha2_set(rd->alpha2) && !is_an_alpha2(rd->alpha2) &&
2311 !is_unknown_alpha2(rd->alpha2))
2312 return -EINVAL;
2313
2314 /*
2315 * Lets only bother proceeding on the same alpha2 if the current
2316 * rd is non static (it means CRDA was present and was used last)
2317 * and the pending request came in from a country IE
2318 */
2319
2320 if (!is_valid_rd(rd)) {
2321 pr_err("Invalid regulatory domain detected:\n");
2322 print_regdomain_info(rd);
2323 return -EINVAL;
2207 } 2324 }
2208 2325
2209 return -EINVAL; 2326 request_wiphy = wiphy_idx_to_wiphy(country_ie_request->wiphy_idx);
2210} 2327 if (!request_wiphy) {
2328 schedule_delayed_work(&reg_timeout, 0);
2329 return -ENODEV;
2330 }
2331
2332 if (country_ie_request->intersect)
2333 return -EINVAL;
2211 2334
2335 reset_regdomains(false, rd);
2336 return 0;
2337}
2212 2338
2213/* 2339/*
2214 * Use this call to set the current regulatory domain. Conflicts with 2340 * Use this call to set the current regulatory domain. Conflicts with
@@ -2220,10 +2346,32 @@ int set_regdom(const struct ieee80211_regdomain *rd)
2220 struct regulatory_request *lr; 2346 struct regulatory_request *lr;
2221 int r; 2347 int r;
2222 2348
2349 if (!reg_is_valid_request(rd->alpha2)) {
2350 kfree(rd);
2351 return -EINVAL;
2352 }
2353
2223 lr = get_last_request(); 2354 lr = get_last_request();
2224 2355
2225 /* Note that this doesn't update the wiphys, this is done below */ 2356 /* Note that this doesn't update the wiphys, this is done below */
2226 r = __set_regdom(rd); 2357 switch (lr->initiator) {
2358 case NL80211_REGDOM_SET_BY_CORE:
2359 r = reg_set_rd_core(rd);
2360 break;
2361 case NL80211_REGDOM_SET_BY_USER:
2362 r = reg_set_rd_user(rd, lr);
2363 break;
2364 case NL80211_REGDOM_SET_BY_DRIVER:
2365 r = reg_set_rd_driver(rd, lr);
2366 break;
2367 case NL80211_REGDOM_SET_BY_COUNTRY_IE:
2368 r = reg_set_rd_country_ie(rd, lr);
2369 break;
2370 default:
2371 WARN(1, "invalid initiator %d\n", lr->initiator);
2372 return -EINVAL;
2373 }
2374
2227 if (r) { 2375 if (r) {
2228 if (r == -EALREADY) 2376 if (r == -EALREADY)
2229 reg_set_request_processed(); 2377 reg_set_request_processed();
diff --git a/net/wireless/reg.h b/net/wireless/reg.h
index 9677e3c13da9..cc4c2c0a6723 100644
--- a/net/wireless/reg.h
+++ b/net/wireless/reg.h
@@ -18,8 +18,9 @@
18 18
19extern const struct ieee80211_regdomain __rcu *cfg80211_regdomain; 19extern const struct ieee80211_regdomain __rcu *cfg80211_regdomain;
20 20
21bool reg_is_valid_request(const char *alpha2);
21bool is_world_regdom(const char *alpha2); 22bool is_world_regdom(const char *alpha2);
22bool reg_supported_dfs_region(u8 dfs_region); 23bool reg_supported_dfs_region(enum nl80211_dfs_regions dfs_region);
23 24
24int regulatory_hint_user(const char *alpha2, 25int regulatory_hint_user(const char *alpha2,
25 enum nl80211_user_reg_hint_type user_reg_hint_type); 26 enum nl80211_user_reg_hint_type user_reg_hint_type);
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index ba5f0d6614d5..f7aa7a72d9bc 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -1653,9 +1653,8 @@ TRACE_EVENT(rdev_cancel_remain_on_channel,
1653 1653
1654TRACE_EVENT(rdev_mgmt_tx, 1654TRACE_EVENT(rdev_mgmt_tx,
1655 TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev, 1655 TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev,
1656 struct ieee80211_channel *chan, bool offchan, 1656 struct cfg80211_mgmt_tx_params *params),
1657 unsigned int wait, bool no_cck, bool dont_wait_for_ack), 1657 TP_ARGS(wiphy, wdev, params),
1658 TP_ARGS(wiphy, wdev, chan, offchan, wait, no_cck, dont_wait_for_ack),
1659 TP_STRUCT__entry( 1658 TP_STRUCT__entry(
1660 WIPHY_ENTRY 1659 WIPHY_ENTRY
1661 WDEV_ENTRY 1660 WDEV_ENTRY
@@ -1668,11 +1667,11 @@ TRACE_EVENT(rdev_mgmt_tx,
1668 TP_fast_assign( 1667 TP_fast_assign(
1669 WIPHY_ASSIGN; 1668 WIPHY_ASSIGN;
1670 WDEV_ASSIGN; 1669 WDEV_ASSIGN;
1671 CHAN_ASSIGN(chan); 1670 CHAN_ASSIGN(params->chan);
1672 __entry->offchan = offchan; 1671 __entry->offchan = params->offchan;
1673 __entry->wait = wait; 1672 __entry->wait = params->wait;
1674 __entry->no_cck = no_cck; 1673 __entry->no_cck = params->no_cck;
1675 __entry->dont_wait_for_ack = dont_wait_for_ack; 1674 __entry->dont_wait_for_ack = params->dont_wait_for_ack;
1676 ), 1675 ),
1677 TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", " CHAN_PR_FMT ", offchan: %s," 1676 TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", " CHAN_PR_FMT ", offchan: %s,"
1678 " wait: %u, no cck: %s, dont wait for ack: %s", 1677 " wait: %u, no cck: %s, dont wait for ack: %s",