diff options
-rw-r--r-- | include/net/cfg80211.h | 46 | ||||
-rw-r--r-- | include/uapi/linux/nl80211.h | 61 | ||||
-rw-r--r-- | net/wireless/chan.c | 129 | ||||
-rw-r--r-- | net/wireless/core.c | 3 | ||||
-rw-r--r-- | net/wireless/core.h | 28 | ||||
-rw-r--r-- | net/wireless/mlme.c | 120 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 135 | ||||
-rw-r--r-- | net/wireless/nl80211.h | 7 | ||||
-rw-r--r-- | net/wireless/reg.c | 3 | ||||
-rw-r--r-- | net/wireless/scan.c | 10 | ||||
-rw-r--r-- | net/wireless/trace.h | 45 |
11 files changed, 570 insertions, 17 deletions
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 7e6569e1f16f..ee11a3db730b 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -114,6 +114,9 @@ enum ieee80211_channel_flags { | |||
114 | #define IEEE80211_CHAN_NO_HT40 \ | 114 | #define IEEE80211_CHAN_NO_HT40 \ |
115 | (IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS) | 115 | (IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS) |
116 | 116 | ||
117 | #define IEEE80211_DFS_MIN_CAC_TIME_MS 60000 | ||
118 | #define IEEE80211_DFS_MIN_NOP_TIME_MS (30 * 60 * 1000) | ||
119 | |||
117 | /** | 120 | /** |
118 | * struct ieee80211_channel - channel definition | 121 | * struct ieee80211_channel - channel definition |
119 | * | 122 | * |
@@ -134,6 +137,9 @@ enum ieee80211_channel_flags { | |||
134 | * to enable this, this is useful only on 5 GHz band. | 137 | * to enable this, this is useful only on 5 GHz band. |
135 | * @orig_mag: internal use | 138 | * @orig_mag: internal use |
136 | * @orig_mpwr: internal use | 139 | * @orig_mpwr: internal use |
140 | * @dfs_state: current state of this channel. Only relevant if radar is required | ||
141 | * on this channel. | ||
142 | * @dfs_state_entered: timestamp (jiffies) when the dfs state was entered. | ||
137 | */ | 143 | */ |
138 | struct ieee80211_channel { | 144 | struct ieee80211_channel { |
139 | enum ieee80211_band band; | 145 | enum ieee80211_band band; |
@@ -146,6 +152,8 @@ struct ieee80211_channel { | |||
146 | bool beacon_found; | 152 | bool beacon_found; |
147 | u32 orig_flags; | 153 | u32 orig_flags; |
148 | int orig_mag, orig_mpwr; | 154 | int orig_mag, orig_mpwr; |
155 | enum nl80211_dfs_state dfs_state; | ||
156 | unsigned long dfs_state_entered; | ||
149 | }; | 157 | }; |
150 | 158 | ||
151 | /** | 159 | /** |
@@ -569,6 +577,7 @@ struct cfg80211_acl_data { | |||
569 | * @p2p_opp_ps: P2P opportunistic PS | 577 | * @p2p_opp_ps: P2P opportunistic PS |
570 | * @acl: ACL configuration used by the drivers which has support for | 578 | * @acl: ACL configuration used by the drivers which has support for |
571 | * MAC address based access control | 579 | * MAC address based access control |
580 | * @radar_required: set if radar detection is required | ||
572 | */ | 581 | */ |
573 | struct cfg80211_ap_settings { | 582 | struct cfg80211_ap_settings { |
574 | struct cfg80211_chan_def chandef; | 583 | struct cfg80211_chan_def chandef; |
@@ -586,6 +595,7 @@ struct cfg80211_ap_settings { | |||
586 | u8 p2p_ctwindow; | 595 | u8 p2p_ctwindow; |
587 | bool p2p_opp_ps; | 596 | bool p2p_opp_ps; |
588 | const struct cfg80211_acl_data *acl; | 597 | const struct cfg80211_acl_data *acl; |
598 | bool radar_required; | ||
589 | }; | 599 | }; |
590 | 600 | ||
591 | /** | 601 | /** |
@@ -1909,6 +1919,8 @@ struct cfg80211_gtk_rekey_data { | |||
1909 | * this new list replaces the existing one. Driver has to clear its ACL | 1919 | * this new list replaces the existing one. Driver has to clear its ACL |
1910 | * when number of MAC addresses entries is passed as 0. Drivers which | 1920 | * when number of MAC addresses entries is passed as 0. Drivers which |
1911 | * advertise the support for MAC based ACL have to implement this callback. | 1921 | * advertise the support for MAC based ACL have to implement this callback. |
1922 | * | ||
1923 | * @start_radar_detection: Start radar detection in the driver. | ||
1912 | */ | 1924 | */ |
1913 | struct cfg80211_ops { | 1925 | struct cfg80211_ops { |
1914 | int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow); | 1926 | int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow); |
@@ -2132,6 +2144,10 @@ struct cfg80211_ops { | |||
2132 | 2144 | ||
2133 | int (*set_mac_acl)(struct wiphy *wiphy, struct net_device *dev, | 2145 | int (*set_mac_acl)(struct wiphy *wiphy, struct net_device *dev, |
2134 | const struct cfg80211_acl_data *params); | 2146 | const struct cfg80211_acl_data *params); |
2147 | |||
2148 | int (*start_radar_detection)(struct wiphy *wiphy, | ||
2149 | struct net_device *dev, | ||
2150 | struct cfg80211_chan_def *chandef); | ||
2135 | }; | 2151 | }; |
2136 | 2152 | ||
2137 | /* | 2153 | /* |
@@ -2715,6 +2731,8 @@ struct cfg80211_cached_keys; | |||
2715 | * beacons, 0 when not valid | 2731 | * beacons, 0 when not valid |
2716 | * @address: The address for this device, valid only if @netdev is %NULL | 2732 | * @address: The address for this device, valid only if @netdev is %NULL |
2717 | * @p2p_started: true if this is a P2P Device that has been started | 2733 | * @p2p_started: true if this is a P2P Device that has been started |
2734 | * @cac_started: true if DFS channel availability check has been started | ||
2735 | * @cac_start_time: timestamp (jiffies) when the dfs state was entered. | ||
2718 | */ | 2736 | */ |
2719 | struct wireless_dev { | 2737 | struct wireless_dev { |
2720 | struct wiphy *wiphy; | 2738 | struct wiphy *wiphy; |
@@ -2766,6 +2784,9 @@ struct wireless_dev { | |||
2766 | 2784 | ||
2767 | u32 ap_unexpected_nlportid; | 2785 | u32 ap_unexpected_nlportid; |
2768 | 2786 | ||
2787 | bool cac_started; | ||
2788 | unsigned long cac_start_time; | ||
2789 | |||
2769 | #ifdef CONFIG_CFG80211_WEXT | 2790 | #ifdef CONFIG_CFG80211_WEXT |
2770 | /* wext data */ | 2791 | /* wext data */ |
2771 | struct { | 2792 | struct { |
@@ -3755,6 +3776,31 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev, | |||
3755 | gfp_t gfp); | 3776 | gfp_t gfp); |
3756 | 3777 | ||
3757 | /** | 3778 | /** |
3779 | * cfg80211_radar_event - radar detection event | ||
3780 | * @wiphy: the wiphy | ||
3781 | * @chandef: chandef for the current channel | ||
3782 | * @gfp: context flags | ||
3783 | * | ||
3784 | * This function is called when a radar is detected on the current chanenl. | ||
3785 | */ | ||
3786 | void cfg80211_radar_event(struct wiphy *wiphy, | ||
3787 | struct cfg80211_chan_def *chandef, gfp_t gfp); | ||
3788 | |||
3789 | /** | ||
3790 | * cfg80211_cac_event - Channel availability check (CAC) event | ||
3791 | * @netdev: network device | ||
3792 | * @event: type of event | ||
3793 | * @gfp: context flags | ||
3794 | * | ||
3795 | * This function is called when a Channel availability check (CAC) is finished | ||
3796 | * or aborted. This must be called to notify the completion of a CAC process, | ||
3797 | * also by full-MAC drivers. | ||
3798 | */ | ||
3799 | void cfg80211_cac_event(struct net_device *netdev, | ||
3800 | enum nl80211_radar_event event, gfp_t gfp); | ||
3801 | |||
3802 | |||
3803 | /** | ||
3758 | * cfg80211_cqm_pktloss_notify - notify userspace about packetloss to peer | 3804 | * cfg80211_cqm_pktloss_notify - notify userspace about packetloss to peer |
3759 | * @dev: network device | 3805 | * @dev: network device |
3760 | * @peer: peer's MAC address | 3806 | * @peer: peer's MAC address |
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 5309b34930ea..90b7af86f392 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h | |||
@@ -603,6 +603,14 @@ | |||
603 | * command is used in AP/P2P GO mode. Driver has to make sure to clear its | 603 | * command is used in AP/P2P GO mode. Driver has to make sure to clear its |
604 | * ACL list during %NL80211_CMD_STOP_AP. | 604 | * ACL list during %NL80211_CMD_STOP_AP. |
605 | * | 605 | * |
606 | * @NL80211_CMD_RADAR_DETECT: Start a Channel availability check (CAC). Once | ||
607 | * a radar is detected or the channel availability scan (CAC) has finished | ||
608 | * or was aborted, or a radar was detected, usermode will be notified with | ||
609 | * this event. This command is also used to notify userspace about radars | ||
610 | * while operating on this channel. | ||
611 | * %NL80211_ATTR_RADAR_EVENT is used to inform about the type of the | ||
612 | * event. | ||
613 | * | ||
606 | * @NL80211_CMD_MAX: highest used command number | 614 | * @NL80211_CMD_MAX: highest used command number |
607 | * @__NL80211_CMD_AFTER_LAST: internal use | 615 | * @__NL80211_CMD_AFTER_LAST: internal use |
608 | */ | 616 | */ |
@@ -755,6 +763,8 @@ enum nl80211_commands { | |||
755 | 763 | ||
756 | NL80211_CMD_SET_MAC_ACL, | 764 | NL80211_CMD_SET_MAC_ACL, |
757 | 765 | ||
766 | NL80211_CMD_RADAR_DETECT, | ||
767 | |||
758 | /* add new commands above here */ | 768 | /* add new commands above here */ |
759 | 769 | ||
760 | /* used to define NL80211_CMD_MAX below */ | 770 | /* used to define NL80211_CMD_MAX below */ |
@@ -1342,6 +1352,9 @@ enum nl80211_commands { | |||
1342 | * number of MAC addresses that a device can support for MAC | 1352 | * number of MAC addresses that a device can support for MAC |
1343 | * ACL. | 1353 | * ACL. |
1344 | * | 1354 | * |
1355 | * @NL80211_ATTR_RADAR_EVENT: Type of radar event for notification to userspace, | ||
1356 | * contains a value of enum nl80211_radar_event (u32). | ||
1357 | * | ||
1345 | * @NL80211_ATTR_MAX: highest attribute number currently defined | 1358 | * @NL80211_ATTR_MAX: highest attribute number currently defined |
1346 | * @__NL80211_ATTR_AFTER_LAST: internal use | 1359 | * @__NL80211_ATTR_AFTER_LAST: internal use |
1347 | */ | 1360 | */ |
@@ -1620,6 +1633,8 @@ enum nl80211_attrs { | |||
1620 | 1633 | ||
1621 | NL80211_ATTR_MAC_ACL_MAX, | 1634 | NL80211_ATTR_MAC_ACL_MAX, |
1622 | 1635 | ||
1636 | NL80211_ATTR_RADAR_EVENT, | ||
1637 | |||
1623 | /* add attributes here, update the policy in nl80211.c */ | 1638 | /* add attributes here, update the policy in nl80211.c */ |
1624 | 1639 | ||
1625 | __NL80211_ATTR_AFTER_LAST, | 1640 | __NL80211_ATTR_AFTER_LAST, |
@@ -2022,6 +2037,10 @@ enum nl80211_band_attr { | |||
2022 | * on this channel in current regulatory domain. | 2037 | * on this channel in current regulatory domain. |
2023 | * @NL80211_FREQUENCY_ATTR_MAX_TX_POWER: Maximum transmission power in mBm | 2038 | * @NL80211_FREQUENCY_ATTR_MAX_TX_POWER: Maximum transmission power in mBm |
2024 | * (100 * dBm). | 2039 | * (100 * dBm). |
2040 | * @NL80211_FREQUENCY_ATTR_DFS_STATE: current state for DFS | ||
2041 | * (enum nl80211_dfs_state) | ||
2042 | * @NL80211_FREQUENCY_ATTR_DFS_TIME: time in miliseconds for how long | ||
2043 | * this channel is in this DFS state. | ||
2025 | * @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number | 2044 | * @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number |
2026 | * currently defined | 2045 | * currently defined |
2027 | * @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use | 2046 | * @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use |
@@ -2034,6 +2053,8 @@ enum nl80211_frequency_attr { | |||
2034 | NL80211_FREQUENCY_ATTR_NO_IBSS, | 2053 | NL80211_FREQUENCY_ATTR_NO_IBSS, |
2035 | NL80211_FREQUENCY_ATTR_RADAR, | 2054 | NL80211_FREQUENCY_ATTR_RADAR, |
2036 | NL80211_FREQUENCY_ATTR_MAX_TX_POWER, | 2055 | NL80211_FREQUENCY_ATTR_MAX_TX_POWER, |
2056 | NL80211_FREQUENCY_ATTR_DFS_STATE, | ||
2057 | NL80211_FREQUENCY_ATTR_DFS_TIME, | ||
2037 | 2058 | ||
2038 | /* keep last */ | 2059 | /* keep last */ |
2039 | __NL80211_FREQUENCY_ATTR_AFTER_LAST, | 2060 | __NL80211_FREQUENCY_ATTR_AFTER_LAST, |
@@ -3489,4 +3510,44 @@ enum nl80211_acl_policy { | |||
3489 | NL80211_ACL_POLICY_DENY_UNLESS_LISTED, | 3510 | NL80211_ACL_POLICY_DENY_UNLESS_LISTED, |
3490 | }; | 3511 | }; |
3491 | 3512 | ||
3513 | /** | ||
3514 | * enum nl80211_radar_event - type of radar event for DFS operation | ||
3515 | * | ||
3516 | * Type of event to be used with NL80211_ATTR_RADAR_EVENT to inform userspace | ||
3517 | * about detected radars or success of the channel available check (CAC) | ||
3518 | * | ||
3519 | * @NL80211_RADAR_DETECTED: A radar pattern has been detected. The channel is | ||
3520 | * now unusable. | ||
3521 | * @NL80211_RADAR_CAC_FINISHED: Channel Availability Check has been finished, | ||
3522 | * the channel is now available. | ||
3523 | * @NL80211_RADAR_CAC_ABORTED: Channel Availability Check has been aborted, no | ||
3524 | * change to the channel status. | ||
3525 | * @NL80211_RADAR_NOP_FINISHED: The Non-Occupancy Period for this channel is | ||
3526 | * over, channel becomes usable. | ||
3527 | */ | ||
3528 | enum nl80211_radar_event { | ||
3529 | NL80211_RADAR_DETECTED, | ||
3530 | NL80211_RADAR_CAC_FINISHED, | ||
3531 | NL80211_RADAR_CAC_ABORTED, | ||
3532 | NL80211_RADAR_NOP_FINISHED, | ||
3533 | }; | ||
3534 | |||
3535 | /** | ||
3536 | * enum nl80211_dfs_state - DFS states for channels | ||
3537 | * | ||
3538 | * Channel states used by the DFS code. | ||
3539 | * | ||
3540 | * @IEEE80211_DFS_USABLE: The channel can be used, but channel availability | ||
3541 | * check (CAC) must be performed before using it for AP or IBSS. | ||
3542 | * @IEEE80211_DFS_UNAVAILABLE: A radar has been detected on this channel, it | ||
3543 | * is therefore marked as not available. | ||
3544 | * @IEEE80211_DFS_AVAILABLE: The channel has been CAC checked and is available. | ||
3545 | */ | ||
3546 | |||
3547 | enum nl80211_dfs_state { | ||
3548 | NL80211_DFS_USABLE, | ||
3549 | NL80211_DFS_UNAVAILABLE, | ||
3550 | NL80211_DFS_AVAILABLE, | ||
3551 | }; | ||
3552 | |||
3492 | #endif /* __LINUX_NL80211_H */ | 3553 | #endif /* __LINUX_NL80211_H */ |
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 | ||
150 | static 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 | |||
150 | const struct cfg80211_chan_def * | 176 | const struct cfg80211_chan_def * |
151 | cfg80211_chandef_compatible(const struct cfg80211_chan_def *c1, | 177 | cfg80211_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 | } |
193 | EXPORT_SYMBOL(cfg80211_chandef_compatible); | 219 | EXPORT_SYMBOL(cfg80211_chandef_compatible); |
194 | 220 | ||
221 | static 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 | |||
240 | void 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 | |||
262 | static 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 | |||
283 | int 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 | |||
195 | static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, | 308 | static 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 | */ | ||
442 | int cfg80211_chandef_dfs_required(struct wiphy *wiphy, | ||
443 | const struct cfg80211_chan_def *c); | ||
444 | |||
445 | void cfg80211_set_dfs_state(struct wiphy *wiphy, | ||
446 | const struct cfg80211_chan_def *chandef, | ||
447 | enum nl80211_dfs_state dfs_state); | ||
448 | |||
449 | void cfg80211_dfs_channels_update_work(struct work_struct *work); | ||
450 | |||
451 | |||
434 | static inline int | 452 | static inline int |
435 | cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, | 453 | cfg80211_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 | ||
478 | static 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 | |||
460 | void | 488 | void |
461 | cfg80211_get_chan_state(struct wireless_dev *wdev, | 489 | cfg80211_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 | } |
989 | EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify); | 989 | EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify); |
990 | |||
991 | void 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 | |||
1050 | void 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 | } | ||
1071 | EXPORT_SYMBOL(cfg80211_radar_event); | ||
1072 | |||
1073 | void 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 | } | ||
1109 | EXPORT_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, ¶ms.chandef)) | 2901 | if (!cfg80211_reg_can_beacon(&rdev->wiphy, ¶ms.chandef)) |
2894 | return -EINVAL; | 2902 | return -EINVAL; |
2895 | 2903 | ||
2904 | err = cfg80211_chandef_dfs_required(wdev->wiphy, ¶ms.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 | ||
5076 | static 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 | } | ||
5118 | err_locked: | ||
5119 | mutex_unlock(&rdev->devlist_mtx); | ||
5120 | |||
5121 | return err; | ||
5122 | } | ||
5123 | |||
5058 | static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb, | 5124 | static 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 | ||
8310 | static struct genl_multicast_group nl80211_mlme_mcgrp = { | 8384 | static 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 | ||
9504 | void | 9578 | void |
9579 | nl80211_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 | |||
9629 | void | ||
9505 | nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev, | 9630 | nl80211_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 | |||
112 | void | ||
113 | nl80211_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 | |||
111 | void | 118 | void |
112 | nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev, | 119 | nl80211_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 | ||
1213 | static 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 | |||
1223 | static char * | 1213 | static char * |
1224 | ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info, | 1214 | ieee80211_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 | ||
2054 | TRACE_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 | |||
2054 | TRACE_EVENT(cfg80211_ch_switch_notify, | 2069 | TRACE_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 | ||
2085 | TRACE_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 | |||
2100 | TRACE_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 | |||
2070 | DECLARE_EVENT_CLASS(cfg80211_rx_evt, | 2115 | DECLARE_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), |