aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/chan.c129
-rw-r--r--net/wireless/core.c3
-rw-r--r--net/wireless/core.h28
-rw-r--r--net/wireless/mlme.c120
-rw-r--r--net/wireless/nl80211.c135
-rw-r--r--net/wireless/nl80211.h7
-rw-r--r--net/wireless/reg.c3
-rw-r--r--net/wireless/scan.c10
-rw-r--r--net/wireless/trace.h45
9 files changed, 463 insertions, 17 deletions
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index 396373f3ec26..810c23cfb894 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -147,6 +147,32 @@ static void chandef_primary_freqs(const struct cfg80211_chan_def *c,
147 } 147 }
148} 148}
149 149
150static int cfg80211_chandef_get_width(const struct cfg80211_chan_def *c)
151{
152 int width;
153
154 switch (c->width) {
155 case NL80211_CHAN_WIDTH_20:
156 case NL80211_CHAN_WIDTH_20_NOHT:
157 width = 20;
158 break;
159 case NL80211_CHAN_WIDTH_40:
160 width = 40;
161 break;
162 case NL80211_CHAN_WIDTH_80P80:
163 case NL80211_CHAN_WIDTH_80:
164 width = 80;
165 break;
166 case NL80211_CHAN_WIDTH_160:
167 width = 160;
168 break;
169 default:
170 WARN_ON_ONCE(1);
171 return -1;
172 }
173 return width;
174}
175
150const struct cfg80211_chan_def * 176const struct cfg80211_chan_def *
151cfg80211_chandef_compatible(const struct cfg80211_chan_def *c1, 177cfg80211_chandef_compatible(const struct cfg80211_chan_def *c1,
152 const struct cfg80211_chan_def *c2) 178 const struct cfg80211_chan_def *c2)
@@ -192,6 +218,93 @@ cfg80211_chandef_compatible(const struct cfg80211_chan_def *c1,
192} 218}
193EXPORT_SYMBOL(cfg80211_chandef_compatible); 219EXPORT_SYMBOL(cfg80211_chandef_compatible);
194 220
221static void cfg80211_set_chans_dfs_state(struct wiphy *wiphy, u32 center_freq,
222 u32 bandwidth,
223 enum nl80211_dfs_state dfs_state)
224{
225 struct ieee80211_channel *c;
226 u32 freq;
227
228 for (freq = center_freq - bandwidth/2 + 10;
229 freq <= center_freq + bandwidth/2 - 10;
230 freq += 20) {
231 c = ieee80211_get_channel(wiphy, freq);
232 if (!c || !(c->flags & IEEE80211_CHAN_RADAR))
233 continue;
234
235 c->dfs_state = dfs_state;
236 c->dfs_state_entered = jiffies;
237 }
238}
239
240void cfg80211_set_dfs_state(struct wiphy *wiphy,
241 const struct cfg80211_chan_def *chandef,
242 enum nl80211_dfs_state dfs_state)
243{
244 int width;
245
246 if (WARN_ON(!cfg80211_chandef_valid(chandef)))
247 return;
248
249 width = cfg80211_chandef_get_width(chandef);
250 if (width < 0)
251 return;
252
253 cfg80211_set_chans_dfs_state(wiphy, chandef->center_freq1,
254 width, dfs_state);
255
256 if (!chandef->center_freq2)
257 return;
258 cfg80211_set_chans_dfs_state(wiphy, chandef->center_freq2,
259 width, dfs_state);
260}
261
262static int cfg80211_get_chans_dfs_required(struct wiphy *wiphy,
263 u32 center_freq,
264 u32 bandwidth)
265{
266 struct ieee80211_channel *c;
267 u32 freq;
268
269 for (freq = center_freq - bandwidth/2 + 10;
270 freq <= center_freq + bandwidth/2 - 10;
271 freq += 20) {
272 c = ieee80211_get_channel(wiphy, freq);
273 if (!c)
274 return -EINVAL;
275
276 if (c->flags & IEEE80211_CHAN_RADAR)
277 return 1;
278 }
279 return 0;
280}
281
282
283int cfg80211_chandef_dfs_required(struct wiphy *wiphy,
284 const struct cfg80211_chan_def *chandef)
285{
286 int width;
287 int r;
288
289 if (WARN_ON(!cfg80211_chandef_valid(chandef)))
290 return -EINVAL;
291
292 width = cfg80211_chandef_get_width(chandef);
293 if (width < 0)
294 return -EINVAL;
295
296 r = cfg80211_get_chans_dfs_required(wiphy, chandef->center_freq1,
297 width);
298 if (r)
299 return r;
300
301 if (!chandef->center_freq2)
302 return 0;
303
304 return cfg80211_get_chans_dfs_required(wiphy, chandef->center_freq2,
305 width);
306}
307
195static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, 308static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
196 u32 center_freq, u32 bandwidth, 309 u32 center_freq, u32 bandwidth,
197 u32 prohibited_flags) 310 u32 prohibited_flags)
@@ -203,7 +316,16 @@ static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
203 freq <= center_freq + bandwidth/2 - 10; 316 freq <= center_freq + bandwidth/2 - 10;
204 freq += 20) { 317 freq += 20) {
205 c = ieee80211_get_channel(wiphy, freq); 318 c = ieee80211_get_channel(wiphy, freq);
206 if (!c || c->flags & prohibited_flags) 319 if (!c)
320 return false;
321
322 /* check for radar flags */
323 if ((prohibited_flags & c->flags & IEEE80211_CHAN_RADAR) &&
324 (c->dfs_state != NL80211_DFS_AVAILABLE))
325 return false;
326
327 /* check for the other flags */
328 if (c->flags & prohibited_flags & ~IEEE80211_CHAN_RADAR)
207 return false; 329 return false;
208 } 330 }
209 331
@@ -344,7 +466,10 @@ cfg80211_get_chan_state(struct wireless_dev *wdev,
344 break; 466 break;
345 case NL80211_IFTYPE_AP: 467 case NL80211_IFTYPE_AP:
346 case NL80211_IFTYPE_P2P_GO: 468 case NL80211_IFTYPE_P2P_GO:
347 if (wdev->beacon_interval) { 469 if (wdev->cac_started) {
470 *chan = wdev->channel;
471 *chanmode = CHAN_MODE_SHARED;
472 } else if (wdev->beacon_interval) {
348 *chan = wdev->channel; 473 *chan = wdev->channel;
349 *chanmode = CHAN_MODE_SHARED; 474 *chanmode = CHAN_MODE_SHARED;
350 } 475 }
diff --git a/net/wireless/core.c b/net/wireless/core.c
index f0a1bbe95cff..922002105062 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -324,6 +324,8 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
324 INIT_LIST_HEAD(&rdev->bss_list); 324 INIT_LIST_HEAD(&rdev->bss_list);
325 INIT_WORK(&rdev->scan_done_wk, __cfg80211_scan_done); 325 INIT_WORK(&rdev->scan_done_wk, __cfg80211_scan_done);
326 INIT_WORK(&rdev->sched_scan_results_wk, __cfg80211_sched_scan_results); 326 INIT_WORK(&rdev->sched_scan_results_wk, __cfg80211_sched_scan_results);
327 INIT_DELAYED_WORK(&rdev->dfs_update_channels_wk,
328 cfg80211_dfs_channels_update_work);
327#ifdef CONFIG_CFG80211_WEXT 329#ifdef CONFIG_CFG80211_WEXT
328 rdev->wiphy.wext = &cfg80211_wext_handler; 330 rdev->wiphy.wext = &cfg80211_wext_handler;
329#endif 331#endif
@@ -695,6 +697,7 @@ void wiphy_unregister(struct wiphy *wiphy)
695 flush_work(&rdev->scan_done_wk); 697 flush_work(&rdev->scan_done_wk);
696 cancel_work_sync(&rdev->conn_work); 698 cancel_work_sync(&rdev->conn_work);
697 flush_work(&rdev->event_work); 699 flush_work(&rdev->event_work);
700 cancel_delayed_work_sync(&rdev->dfs_update_channels_wk);
698 701
699 if (rdev->wowlan && rdev->ops->set_wakeup) 702 if (rdev->wowlan && rdev->ops->set_wakeup)
700 rdev_set_wakeup(rdev, false); 703 rdev_set_wakeup(rdev, false);
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 949c9573d8d7..3aec0e429d8a 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -86,6 +86,8 @@ struct cfg80211_registered_device {
86 86
87 struct cfg80211_wowlan *wowlan; 87 struct cfg80211_wowlan *wowlan;
88 88
89 struct delayed_work dfs_update_channels_wk;
90
89 /* must be last because of the way we do wiphy_priv(), 91 /* must be last because of the way we do wiphy_priv(),
90 * and it should at least be aligned to NETDEV_ALIGN */ 92 * and it should at least be aligned to NETDEV_ALIGN */
91 struct wiphy wiphy __aligned(NETDEV_ALIGN); 93 struct wiphy wiphy __aligned(NETDEV_ALIGN);
@@ -431,6 +433,22 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
431 enum cfg80211_chan_mode chanmode, 433 enum cfg80211_chan_mode chanmode,
432 u8 radar_detect); 434 u8 radar_detect);
433 435
436/**
437 * cfg80211_chandef_dfs_required - checks if radar detection is required
438 * @wiphy: the wiphy to validate against
439 * @chandef: the channel definition to check
440 * Return: 1 if radar detection is required, 0 if it is not, < 0 on error
441 */
442int cfg80211_chandef_dfs_required(struct wiphy *wiphy,
443 const struct cfg80211_chan_def *c);
444
445void cfg80211_set_dfs_state(struct wiphy *wiphy,
446 const struct cfg80211_chan_def *chandef,
447 enum nl80211_dfs_state dfs_state);
448
449void cfg80211_dfs_channels_update_work(struct work_struct *work);
450
451
434static inline int 452static inline int
435cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, 453cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
436 struct wireless_dev *wdev, 454 struct wireless_dev *wdev,
@@ -457,6 +475,16 @@ cfg80211_can_use_chan(struct cfg80211_registered_device *rdev,
457 chan, chanmode, 0); 475 chan, chanmode, 0);
458} 476}
459 477
478static inline unsigned int elapsed_jiffies_msecs(unsigned long start)
479{
480 unsigned long end = jiffies;
481
482 if (end >= start)
483 return jiffies_to_msecs(end - start);
484
485 return jiffies_to_msecs(end + (MAX_JIFFY_OFFSET - start) + 1);
486}
487
460void 488void
461cfg80211_get_chan_state(struct wireless_dev *wdev, 489cfg80211_get_chan_state(struct wireless_dev *wdev,
462 struct ieee80211_channel **chan, 490 struct ieee80211_channel **chan,
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 8e6920728c43..caddca35d686 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -987,3 +987,123 @@ void cfg80211_pmksa_candidate_notify(struct net_device *dev, int index,
987 nl80211_pmksa_candidate_notify(rdev, dev, index, bssid, preauth, gfp); 987 nl80211_pmksa_candidate_notify(rdev, dev, index, bssid, preauth, gfp);
988} 988}
989EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify); 989EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify);
990
991void cfg80211_dfs_channels_update_work(struct work_struct *work)
992{
993 struct delayed_work *delayed_work;
994 struct cfg80211_registered_device *rdev;
995 struct cfg80211_chan_def chandef;
996 struct ieee80211_supported_band *sband;
997 struct ieee80211_channel *c;
998 struct wiphy *wiphy;
999 bool check_again = false;
1000 unsigned long timeout, next_time = 0;
1001 int bandid, i;
1002
1003 delayed_work = container_of(work, struct delayed_work, work);
1004 rdev = container_of(delayed_work, struct cfg80211_registered_device,
1005 dfs_update_channels_wk);
1006 wiphy = &rdev->wiphy;
1007
1008 mutex_lock(&cfg80211_mutex);
1009 for (bandid = 0; bandid < IEEE80211_NUM_BANDS; bandid++) {
1010 sband = wiphy->bands[bandid];
1011 if (!sband)
1012 continue;
1013
1014 for (i = 0; i < sband->n_channels; i++) {
1015 c = &sband->channels[i];
1016
1017 if (c->dfs_state != NL80211_DFS_UNAVAILABLE)
1018 continue;
1019
1020 timeout = c->dfs_state_entered +
1021 IEEE80211_DFS_MIN_NOP_TIME_MS;
1022
1023 if (time_after_eq(jiffies, timeout)) {
1024 c->dfs_state = NL80211_DFS_USABLE;
1025 cfg80211_chandef_create(&chandef, c,
1026 NL80211_CHAN_NO_HT);
1027
1028 nl80211_radar_notify(rdev, &chandef,
1029 NL80211_RADAR_NOP_FINISHED,
1030 NULL, GFP_ATOMIC);
1031 continue;
1032 }
1033
1034 if (!check_again)
1035 next_time = timeout - jiffies;
1036 else
1037 next_time = min(next_time, timeout - jiffies);
1038 check_again = true;
1039 }
1040 }
1041 mutex_unlock(&cfg80211_mutex);
1042
1043 /* reschedule if there are other channels waiting to be cleared again */
1044 if (check_again)
1045 queue_delayed_work(cfg80211_wq, &rdev->dfs_update_channels_wk,
1046 next_time);
1047}
1048
1049
1050void cfg80211_radar_event(struct wiphy *wiphy,
1051 struct cfg80211_chan_def *chandef,
1052 gfp_t gfp)
1053{
1054 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
1055 unsigned long timeout;
1056
1057 trace_cfg80211_radar_event(wiphy, chandef);
1058
1059 /* only set the chandef supplied channel to unavailable, in
1060 * case the radar is detected on only one of multiple channels
1061 * spanned by the chandef.
1062 */
1063 cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_UNAVAILABLE);
1064
1065 timeout = msecs_to_jiffies(IEEE80211_DFS_MIN_NOP_TIME_MS);
1066 queue_delayed_work(cfg80211_wq, &rdev->dfs_update_channels_wk,
1067 timeout);
1068
1069 nl80211_radar_notify(rdev, chandef, NL80211_RADAR_DETECTED, NULL, gfp);
1070}
1071EXPORT_SYMBOL(cfg80211_radar_event);
1072
1073void cfg80211_cac_event(struct net_device *netdev,
1074 enum nl80211_radar_event event, gfp_t gfp)
1075{
1076 struct wireless_dev *wdev = netdev->ieee80211_ptr;
1077 struct wiphy *wiphy = wdev->wiphy;
1078 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
1079 struct cfg80211_chan_def chandef;
1080 unsigned long timeout;
1081
1082 trace_cfg80211_cac_event(netdev, event);
1083
1084 if (WARN_ON(!wdev->cac_started))
1085 return;
1086
1087 if (WARN_ON(!wdev->channel))
1088 return;
1089
1090 cfg80211_chandef_create(&chandef, wdev->channel, NL80211_CHAN_NO_HT);
1091
1092 switch (event) {
1093 case NL80211_RADAR_CAC_FINISHED:
1094 timeout = wdev->cac_start_time +
1095 msecs_to_jiffies(IEEE80211_DFS_MIN_CAC_TIME_MS);
1096 WARN_ON(!time_after_eq(jiffies, timeout));
1097 cfg80211_set_dfs_state(wiphy, &chandef, NL80211_DFS_AVAILABLE);
1098 break;
1099 case NL80211_RADAR_CAC_ABORTED:
1100 break;
1101 default:
1102 WARN_ON(1);
1103 return;
1104 }
1105 wdev->cac_started = false;
1106
1107 nl80211_radar_notify(rdev, &chandef, event, netdev, gfp);
1108}
1109EXPORT_SYMBOL(cfg80211_cac_event);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index d29a461b4981..c1e18ccf4049 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -552,9 +552,16 @@ static int nl80211_msg_put_channel(struct sk_buff *msg,
552 if ((chan->flags & IEEE80211_CHAN_NO_IBSS) && 552 if ((chan->flags & IEEE80211_CHAN_NO_IBSS) &&
553 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_IBSS)) 553 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_IBSS))
554 goto nla_put_failure; 554 goto nla_put_failure;
555 if ((chan->flags & IEEE80211_CHAN_RADAR) && 555 if (chan->flags & IEEE80211_CHAN_RADAR) {
556 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR)) 556 u32 time = elapsed_jiffies_msecs(chan->dfs_state_entered);
557 goto nla_put_failure; 557 if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR))
558 goto nla_put_failure;
559 if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_STATE,
560 chan->dfs_state))
561 goto nla_put_failure;
562 if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_TIME, time))
563 goto nla_put_failure;
564 }
558 565
559 if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER, 566 if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
560 DBM_TO_MBM(chan->max_power))) 567 DBM_TO_MBM(chan->max_power)))
@@ -2775,6 +2782,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
2775 struct wireless_dev *wdev = dev->ieee80211_ptr; 2782 struct wireless_dev *wdev = dev->ieee80211_ptr;
2776 struct cfg80211_ap_settings params; 2783 struct cfg80211_ap_settings params;
2777 int err; 2784 int err;
2785 u8 radar_detect_width = 0;
2778 2786
2779 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && 2787 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
2780 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) 2788 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
@@ -2893,9 +2901,19 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
2893 if (!cfg80211_reg_can_beacon(&rdev->wiphy, &params.chandef)) 2901 if (!cfg80211_reg_can_beacon(&rdev->wiphy, &params.chandef))
2894 return -EINVAL; 2902 return -EINVAL;
2895 2903
2904 err = cfg80211_chandef_dfs_required(wdev->wiphy, &params.chandef);
2905 if (err < 0)
2906 return err;
2907 if (err) {
2908 radar_detect_width = BIT(params.chandef.width);
2909 params.radar_required = true;
2910 }
2911
2896 mutex_lock(&rdev->devlist_mtx); 2912 mutex_lock(&rdev->devlist_mtx);
2897 err = cfg80211_can_use_chan(rdev, wdev, params.chandef.chan, 2913 err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,
2898 CHAN_MODE_SHARED); 2914 params.chandef.chan,
2915 CHAN_MODE_SHARED,
2916 radar_detect_width);
2899 mutex_unlock(&rdev->devlist_mtx); 2917 mutex_unlock(&rdev->devlist_mtx);
2900 2918
2901 if (err) 2919 if (err)
@@ -5055,6 +5073,54 @@ static int nl80211_stop_sched_scan(struct sk_buff *skb,
5055 return err; 5073 return err;
5056} 5074}
5057 5075
5076static int nl80211_start_radar_detection(struct sk_buff *skb,
5077 struct genl_info *info)
5078{
5079 struct cfg80211_registered_device *rdev = info->user_ptr[0];
5080 struct net_device *dev = info->user_ptr[1];
5081 struct wireless_dev *wdev = dev->ieee80211_ptr;
5082 struct cfg80211_chan_def chandef;
5083 int err;
5084
5085 err = nl80211_parse_chandef(rdev, info, &chandef);
5086 if (err)
5087 return err;
5088
5089 if (wdev->cac_started)
5090 return -EBUSY;
5091
5092 err = cfg80211_chandef_dfs_required(wdev->wiphy, &chandef);
5093 if (err < 0)
5094 return err;
5095
5096 if (err == 0)
5097 return -EINVAL;
5098
5099 if (chandef.chan->dfs_state != NL80211_DFS_USABLE)
5100 return -EINVAL;
5101
5102 if (!rdev->ops->start_radar_detection)
5103 return -EOPNOTSUPP;
5104
5105 mutex_lock(&rdev->devlist_mtx);
5106 err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,
5107 chandef.chan, CHAN_MODE_SHARED,
5108 BIT(chandef.width));
5109 if (err)
5110 goto err_locked;
5111
5112 err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef);
5113 if (!err) {
5114 wdev->channel = chandef.chan;
5115 wdev->cac_started = true;
5116 wdev->cac_start_time = jiffies;
5117 }
5118err_locked:
5119 mutex_unlock(&rdev->devlist_mtx);
5120
5121 return err;
5122}
5123
5058static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb, 5124static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
5059 u32 seq, int flags, 5125 u32 seq, int flags,
5060 struct cfg80211_registered_device *rdev, 5126 struct cfg80211_registered_device *rdev,
@@ -8305,6 +8371,14 @@ static struct genl_ops nl80211_ops[] = {
8305 .internal_flags = NL80211_FLAG_NEED_NETDEV | 8371 .internal_flags = NL80211_FLAG_NEED_NETDEV |
8306 NL80211_FLAG_NEED_RTNL, 8372 NL80211_FLAG_NEED_RTNL,
8307 }, 8373 },
8374 {
8375 .cmd = NL80211_CMD_RADAR_DETECT,
8376 .doit = nl80211_start_radar_detection,
8377 .policy = nl80211_policy,
8378 .flags = GENL_ADMIN_PERM,
8379 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
8380 NL80211_FLAG_NEED_RTNL,
8381 },
8308}; 8382};
8309 8383
8310static struct genl_multicast_group nl80211_mlme_mcgrp = { 8384static struct genl_multicast_group nl80211_mlme_mcgrp = {
@@ -9502,6 +9576,57 @@ nl80211_send_cqm_txe_notify(struct cfg80211_registered_device *rdev,
9502} 9576}
9503 9577
9504void 9578void
9579nl80211_radar_notify(struct cfg80211_registered_device *rdev,
9580 struct cfg80211_chan_def *chandef,
9581 enum nl80211_radar_event event,
9582 struct net_device *netdev, gfp_t gfp)
9583{
9584 struct sk_buff *msg;
9585 void *hdr;
9586
9587 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
9588 if (!msg)
9589 return;
9590
9591 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_RADAR_DETECT);
9592 if (!hdr) {
9593 nlmsg_free(msg);
9594 return;
9595 }
9596
9597 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx))
9598 goto nla_put_failure;
9599
9600 /* NOP and radar events don't need a netdev parameter */
9601 if (netdev) {
9602 struct wireless_dev *wdev = netdev->ieee80211_ptr;
9603
9604 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
9605 nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)))
9606 goto nla_put_failure;
9607 }
9608
9609 if (nla_put_u32(msg, NL80211_ATTR_RADAR_EVENT, event))
9610 goto nla_put_failure;
9611
9612 if (nl80211_send_chandef(msg, chandef))
9613 goto nla_put_failure;
9614
9615 if (genlmsg_end(msg, hdr) < 0) {
9616 nlmsg_free(msg);
9617 return;
9618 }
9619
9620 genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
9621 nl80211_mlme_mcgrp.id, gfp);
9622 return;
9623
9624 nla_put_failure:
9625 genlmsg_cancel(msg, hdr);
9626 nlmsg_free(msg);
9627}
9628
9629void
9505nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev, 9630nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev,
9506 struct net_device *netdev, const u8 *peer, 9631 struct net_device *netdev, const u8 *peer,
9507 u32 num_packets, gfp_t gfp) 9632 u32 num_packets, gfp_t gfp)
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h
index 2acba8477e9d..b061da4919e1 100644
--- a/net/wireless/nl80211.h
+++ b/net/wireless/nl80211.h
@@ -108,6 +108,13 @@ nl80211_send_cqm_rssi_notify(struct cfg80211_registered_device *rdev,
108 struct net_device *netdev, 108 struct net_device *netdev,
109 enum nl80211_cqm_rssi_threshold_event rssi_event, 109 enum nl80211_cqm_rssi_threshold_event rssi_event,
110 gfp_t gfp); 110 gfp_t gfp);
111
112void
113nl80211_radar_notify(struct cfg80211_registered_device *rdev,
114 struct cfg80211_chan_def *chandef,
115 enum nl80211_radar_event event,
116 struct net_device *netdev, gfp_t gfp);
117
111void 118void
112nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev, 119nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev,
113 struct net_device *netdev, const u8 *peer, 120 struct net_device *netdev, const u8 *peer,
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 08d3da2c70ab..e97d5b071ab6 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -884,6 +884,9 @@ static void handle_channel(struct wiphy *wiphy,
884 return; 884 return;
885 } 885 }
886 886
887 chan->dfs_state = NL80211_DFS_USABLE;
888 chan->dfs_state_entered = jiffies;
889
887 chan->beacon_found = false; 890 chan->beacon_found = false;
888 chan->flags = flags | bw_flags | map_regdom_flags(reg_rule->flags); 891 chan->flags = flags | bw_flags | map_regdom_flags(reg_rule->flags);
889 chan->max_antenna_gain = 892 chan->max_antenna_gain =
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index d0fc6da2d097..f0d9b5154bab 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -1210,16 +1210,6 @@ static void ieee80211_scan_add_ies(struct iw_request_info *info,
1210 } 1210 }
1211} 1211}
1212 1212
1213static inline unsigned int elapsed_jiffies_msecs(unsigned long start)
1214{
1215 unsigned long end = jiffies;
1216
1217 if (end >= start)
1218 return jiffies_to_msecs(end - start);
1219
1220 return jiffies_to_msecs(end + (MAX_JIFFY_OFFSET - start) + 1);
1221}
1222
1223static char * 1213static char *
1224ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info, 1214ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info,
1225 struct cfg80211_internal_bss *bss, char *current_ev, 1215 struct cfg80211_internal_bss *bss, char *current_ev,
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index c9cafb0ea95f..b7a531380e19 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -2051,6 +2051,21 @@ TRACE_EVENT(cfg80211_reg_can_beacon,
2051 WIPHY_PR_ARG, CHAN_DEF_PR_ARG) 2051 WIPHY_PR_ARG, CHAN_DEF_PR_ARG)
2052); 2052);
2053 2053
2054TRACE_EVENT(cfg80211_chandef_dfs_required,
2055 TP_PROTO(struct wiphy *wiphy, struct cfg80211_chan_def *chandef),
2056 TP_ARGS(wiphy, chandef),
2057 TP_STRUCT__entry(
2058 WIPHY_ENTRY
2059 CHAN_DEF_ENTRY
2060 ),
2061 TP_fast_assign(
2062 WIPHY_ASSIGN;
2063 CHAN_DEF_ASSIGN(chandef);
2064 ),
2065 TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT,
2066 WIPHY_PR_ARG, CHAN_DEF_PR_ARG)
2067);
2068
2054TRACE_EVENT(cfg80211_ch_switch_notify, 2069TRACE_EVENT(cfg80211_ch_switch_notify,
2055 TP_PROTO(struct net_device *netdev, 2070 TP_PROTO(struct net_device *netdev,
2056 struct cfg80211_chan_def *chandef), 2071 struct cfg80211_chan_def *chandef),
@@ -2067,6 +2082,36 @@ TRACE_EVENT(cfg80211_ch_switch_notify,
2067 NETDEV_PR_ARG, CHAN_DEF_PR_ARG) 2082 NETDEV_PR_ARG, CHAN_DEF_PR_ARG)
2068); 2083);
2069 2084
2085TRACE_EVENT(cfg80211_radar_event,
2086 TP_PROTO(struct wiphy *wiphy, struct cfg80211_chan_def *chandef),
2087 TP_ARGS(wiphy, chandef),
2088 TP_STRUCT__entry(
2089 WIPHY_ENTRY
2090 CHAN_DEF_ENTRY
2091 ),
2092 TP_fast_assign(
2093 WIPHY_ASSIGN;
2094 CHAN_DEF_ASSIGN(chandef);
2095 ),
2096 TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT,
2097 WIPHY_PR_ARG, CHAN_DEF_PR_ARG)
2098);
2099
2100TRACE_EVENT(cfg80211_cac_event,
2101 TP_PROTO(struct net_device *netdev, enum nl80211_radar_event evt),
2102 TP_ARGS(netdev, evt),
2103 TP_STRUCT__entry(
2104 NETDEV_ENTRY
2105 __field(enum nl80211_radar_event, evt)
2106 ),
2107 TP_fast_assign(
2108 NETDEV_ASSIGN;
2109 __entry->evt = evt;
2110 ),
2111 TP_printk(NETDEV_PR_FMT ", event: %d",
2112 NETDEV_PR_ARG, __entry->evt)
2113);
2114
2070DECLARE_EVENT_CLASS(cfg80211_rx_evt, 2115DECLARE_EVENT_CLASS(cfg80211_rx_evt,
2071 TP_PROTO(struct net_device *netdev, const u8 *addr), 2116 TP_PROTO(struct net_device *netdev, const u8 *addr),
2072 TP_ARGS(netdev, addr), 2117 TP_ARGS(netdev, addr),