aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2014-03-20 11:53:20 -0400
committerJohn W. Linville <linville@tuxdriver.com>2014-03-20 11:53:20 -0400
commit7eb2450a51ea7606fa69ae4bb2113e0f228223cc (patch)
tree6cd273487574edd2da40ce14b1981e14a5171caa
parent474a41e94dfc85167e1761bfbb8bf180f90633b2 (diff)
parent73fb08e24ae840bc518facc2c605dd6bb3751fec (diff)
Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
-rw-r--r--include/linux/ieee80211.h4
-rw-r--r--include/net/cfg80211.h23
-rw-r--r--include/net/mac80211.h6
-rw-r--r--include/net/regulatory.h21
-rw-r--r--include/uapi/linux/nl80211.h6
-rw-r--r--net/mac80211/cfg.c121
-rw-r--r--net/mac80211/ibss.c12
-rw-r--r--net/mac80211/ieee80211_i.h1
-rw-r--r--net/mac80211/mlme.c70
-rw-r--r--net/mac80211/pm.c14
-rw-r--r--net/mac80211/rx.c3
-rw-r--r--net/mac80211/scan.c6
-rw-r--r--net/mac80211/tx.c2
-rw-r--r--net/wireless/ap.c9
-rw-r--r--net/wireless/chan.c56
-rw-r--r--net/wireless/core.c2
-rw-r--r--net/wireless/core.h10
-rw-r--r--net/wireless/genregdb.awk8
-rw-r--r--net/wireless/ibss.c8
-rw-r--r--net/wireless/mlme.c2
-rw-r--r--net/wireless/nl80211.c24
-rw-r--r--net/wireless/reg.c86
-rw-r--r--net/wireless/reg.h1
-rw-r--r--net/wireless/scan.c31
-rw-r--r--net/wireless/sme.c1
-rw-r--r--net/wireless/util.c5
-rw-r--r--net/wireless/wext-sme.c2
27 files changed, 339 insertions, 195 deletions
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 06299048c4f4..f194ccb8539c 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -154,6 +154,10 @@ static inline u16 ieee80211_sn_sub(u16 sn1, u16 sn2)
154 802.11e clarifies the figure in section 7.1.2. The frame body is 154 802.11e clarifies the figure in section 7.1.2. The frame body is
155 up to 2304 octets long (maximum MSDU size) plus any crypt overhead. */ 155 up to 2304 octets long (maximum MSDU size) plus any crypt overhead. */
156#define IEEE80211_MAX_DATA_LEN 2304 156#define IEEE80211_MAX_DATA_LEN 2304
157/* 802.11ad extends maximum MSDU size for DMG (freq > 40Ghz) networks
158 * to 7920 bytes, see 8.2.3 General frame format
159 */
160#define IEEE80211_MAX_DATA_LEN_DMG 7920
157/* 30 byte 4 addr hdr, 2 byte QoS, 2304 byte MSDU, 12 byte crypt, 4 byte FCS */ 161/* 30 byte 4 addr hdr, 2 byte QoS, 2304 byte MSDU, 12 byte crypt, 4 byte FCS */
158#define IEEE80211_MAX_FRAME_LEN 2352 162#define IEEE80211_MAX_FRAME_LEN 2352
159 163
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 8c9ba44fb7cf..f3539a15c411 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -151,6 +151,7 @@ enum ieee80211_channel_flags {
151 * @dfs_state: current state of this channel. Only relevant if radar is required 151 * @dfs_state: current state of this channel. Only relevant if radar is required
152 * on this channel. 152 * on this channel.
153 * @dfs_state_entered: timestamp (jiffies) when the dfs state was entered. 153 * @dfs_state_entered: timestamp (jiffies) when the dfs state was entered.
154 * @dfs_cac_ms: DFS CAC time in milliseconds, this is valid for DFS channels.
154 */ 155 */
155struct ieee80211_channel { 156struct ieee80211_channel {
156 enum ieee80211_band band; 157 enum ieee80211_band band;
@@ -165,6 +166,7 @@ struct ieee80211_channel {
165 int orig_mag, orig_mpwr; 166 int orig_mag, orig_mpwr;
166 enum nl80211_dfs_state dfs_state; 167 enum nl80211_dfs_state dfs_state;
167 unsigned long dfs_state_entered; 168 unsigned long dfs_state_entered;
169 unsigned int dfs_cac_ms;
168}; 170};
169 171
170/** 172/**
@@ -2503,7 +2505,8 @@ struct cfg80211_ops {
2503 2505
2504 int (*start_radar_detection)(struct wiphy *wiphy, 2506 int (*start_radar_detection)(struct wiphy *wiphy,
2505 struct net_device *dev, 2507 struct net_device *dev,
2506 struct cfg80211_chan_def *chandef); 2508 struct cfg80211_chan_def *chandef,
2509 u32 cac_time_ms);
2507 int (*update_ft_ies)(struct wiphy *wiphy, struct net_device *dev, 2510 int (*update_ft_ies)(struct wiphy *wiphy, struct net_device *dev,
2508 struct cfg80211_update_ft_ies_params *ftie); 2511 struct cfg80211_update_ft_ies_params *ftie);
2509 int (*crit_proto_start)(struct wiphy *wiphy, 2512 int (*crit_proto_start)(struct wiphy *wiphy,
@@ -3180,6 +3183,7 @@ struct cfg80211_cached_keys;
3180 * @p2p_started: true if this is a P2P Device that has been started 3183 * @p2p_started: true if this is a P2P Device that has been started
3181 * @cac_started: true if DFS channel availability check has been started 3184 * @cac_started: true if DFS channel availability check has been started
3182 * @cac_start_time: timestamp (jiffies) when the dfs state was entered. 3185 * @cac_start_time: timestamp (jiffies) when the dfs state was entered.
3186 * @cac_time_ms: CAC time in ms
3183 * @ps: powersave mode is enabled 3187 * @ps: powersave mode is enabled
3184 * @ps_timeout: dynamic powersave timeout 3188 * @ps_timeout: dynamic powersave timeout
3185 * @ap_unexpected_nlportid: (private) netlink port ID of application 3189 * @ap_unexpected_nlportid: (private) netlink port ID of application
@@ -3235,6 +3239,7 @@ struct wireless_dev {
3235 3239
3236 bool cac_started; 3240 bool cac_started;
3237 unsigned long cac_start_time; 3241 unsigned long cac_start_time;
3242 unsigned int cac_time_ms;
3238 3243
3239#ifdef CONFIG_CFG80211_WEXT 3244#ifdef CONFIG_CFG80211_WEXT
3240 /* wext data */ 3245 /* wext data */
@@ -3667,7 +3672,7 @@ void cfg80211_sched_scan_stopped(struct wiphy *wiphy);
3667 * cfg80211_inform_bss_width_frame - inform cfg80211 of a received BSS frame 3672 * cfg80211_inform_bss_width_frame - inform cfg80211 of a received BSS frame
3668 * 3673 *
3669 * @wiphy: the wiphy reporting the BSS 3674 * @wiphy: the wiphy reporting the BSS
3670 * @channel: The channel the frame was received on 3675 * @rx_channel: The channel the frame was received on
3671 * @scan_width: width of the control channel 3676 * @scan_width: width of the control channel
3672 * @mgmt: the management frame (probe response or beacon) 3677 * @mgmt: the management frame (probe response or beacon)
3673 * @len: length of the management frame 3678 * @len: length of the management frame
@@ -3682,18 +3687,18 @@ void cfg80211_sched_scan_stopped(struct wiphy *wiphy);
3682 */ 3687 */
3683struct cfg80211_bss * __must_check 3688struct cfg80211_bss * __must_check
3684cfg80211_inform_bss_width_frame(struct wiphy *wiphy, 3689cfg80211_inform_bss_width_frame(struct wiphy *wiphy,
3685 struct ieee80211_channel *channel, 3690 struct ieee80211_channel *rx_channel,
3686 enum nl80211_bss_scan_width scan_width, 3691 enum nl80211_bss_scan_width scan_width,
3687 struct ieee80211_mgmt *mgmt, size_t len, 3692 struct ieee80211_mgmt *mgmt, size_t len,
3688 s32 signal, gfp_t gfp); 3693 s32 signal, gfp_t gfp);
3689 3694
3690static inline struct cfg80211_bss * __must_check 3695static inline struct cfg80211_bss * __must_check
3691cfg80211_inform_bss_frame(struct wiphy *wiphy, 3696cfg80211_inform_bss_frame(struct wiphy *wiphy,
3692 struct ieee80211_channel *channel, 3697 struct ieee80211_channel *rx_channel,
3693 struct ieee80211_mgmt *mgmt, size_t len, 3698 struct ieee80211_mgmt *mgmt, size_t len,
3694 s32 signal, gfp_t gfp) 3699 s32 signal, gfp_t gfp)
3695{ 3700{
3696 return cfg80211_inform_bss_width_frame(wiphy, channel, 3701 return cfg80211_inform_bss_width_frame(wiphy, rx_channel,
3697 NL80211_BSS_CHAN_WIDTH_20, 3702 NL80211_BSS_CHAN_WIDTH_20,
3698 mgmt, len, signal, gfp); 3703 mgmt, len, signal, gfp);
3699} 3704}
@@ -3702,7 +3707,7 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy,
3702 * cfg80211_inform_bss - inform cfg80211 of a new BSS 3707 * cfg80211_inform_bss - inform cfg80211 of a new BSS
3703 * 3708 *
3704 * @wiphy: the wiphy reporting the BSS 3709 * @wiphy: the wiphy reporting the BSS
3705 * @channel: The channel the frame was received on 3710 * @rx_channel: The channel the frame was received on
3706 * @scan_width: width of the control channel 3711 * @scan_width: width of the control channel
3707 * @bssid: the BSSID of the BSS 3712 * @bssid: the BSSID of the BSS
3708 * @tsf: the TSF sent by the peer in the beacon/probe response (or 0) 3713 * @tsf: the TSF sent by the peer in the beacon/probe response (or 0)
@@ -3721,7 +3726,7 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy,
3721 */ 3726 */
3722struct cfg80211_bss * __must_check 3727struct cfg80211_bss * __must_check
3723cfg80211_inform_bss_width(struct wiphy *wiphy, 3728cfg80211_inform_bss_width(struct wiphy *wiphy,
3724 struct ieee80211_channel *channel, 3729 struct ieee80211_channel *rx_channel,
3725 enum nl80211_bss_scan_width scan_width, 3730 enum nl80211_bss_scan_width scan_width,
3726 const u8 *bssid, u64 tsf, u16 capability, 3731 const u8 *bssid, u64 tsf, u16 capability,
3727 u16 beacon_interval, const u8 *ie, size_t ielen, 3732 u16 beacon_interval, const u8 *ie, size_t ielen,
@@ -3729,12 +3734,12 @@ cfg80211_inform_bss_width(struct wiphy *wiphy,
3729 3734
3730static inline struct cfg80211_bss * __must_check 3735static inline struct cfg80211_bss * __must_check
3731cfg80211_inform_bss(struct wiphy *wiphy, 3736cfg80211_inform_bss(struct wiphy *wiphy,
3732 struct ieee80211_channel *channel, 3737 struct ieee80211_channel *rx_channel,
3733 const u8 *bssid, u64 tsf, u16 capability, 3738 const u8 *bssid, u64 tsf, u16 capability,
3734 u16 beacon_interval, const u8 *ie, size_t ielen, 3739 u16 beacon_interval, const u8 *ie, size_t ielen,
3735 s32 signal, gfp_t gfp) 3740 s32 signal, gfp_t gfp)
3736{ 3741{
3737 return cfg80211_inform_bss_width(wiphy, channel, 3742 return cfg80211_inform_bss_width(wiphy, rx_channel,
3738 NL80211_BSS_CHAN_WIDTH_20, 3743 NL80211_BSS_CHAN_WIDTH_20,
3739 bssid, tsf, capability, 3744 bssid, tsf, capability,
3740 beacon_interval, ie, ielen, signal, 3745 beacon_interval, ie, ielen, signal,
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 86faa413b37d..2de7ff42ff3a 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -697,11 +697,11 @@ struct ieee80211_tx_info {
697 } control; 697 } control;
698 struct { 698 struct {
699 struct ieee80211_tx_rate rates[IEEE80211_TX_MAX_RATES]; 699 struct ieee80211_tx_rate rates[IEEE80211_TX_MAX_RATES];
700 int ack_signal; 700 s32 ack_signal;
701 u8 ampdu_ack_len; 701 u8 ampdu_ack_len;
702 u8 ampdu_len; 702 u8 ampdu_len;
703 u8 antenna; 703 u8 antenna;
704 /* 21 bytes free */ 704 void *status_driver_data[21 / sizeof(void *)];
705 } status; 705 } status;
706 struct { 706 struct {
707 struct ieee80211_tx_rate driver_rates[ 707 struct ieee80211_tx_rate driver_rates[
@@ -877,11 +877,13 @@ enum mac80211_rx_flags {
877 * @RX_VHT_FLAG_80MHZ: 80 MHz was used 877 * @RX_VHT_FLAG_80MHZ: 80 MHz was used
878 * @RX_VHT_FLAG_80P80MHZ: 80+80 MHz was used 878 * @RX_VHT_FLAG_80P80MHZ: 80+80 MHz was used
879 * @RX_VHT_FLAG_160MHZ: 160 MHz was used 879 * @RX_VHT_FLAG_160MHZ: 160 MHz was used
880 * @RX_VHT_FLAG_BF: packet was beamformed
880 */ 881 */
881enum mac80211_rx_vht_flags { 882enum mac80211_rx_vht_flags {
882 RX_VHT_FLAG_80MHZ = BIT(0), 883 RX_VHT_FLAG_80MHZ = BIT(0),
883 RX_VHT_FLAG_80P80MHZ = BIT(1), 884 RX_VHT_FLAG_80P80MHZ = BIT(1),
884 RX_VHT_FLAG_160MHZ = BIT(2), 885 RX_VHT_FLAG_160MHZ = BIT(2),
886 RX_VHT_FLAG_BF = BIT(3),
885}; 887};
886 888
887/** 889/**
diff --git a/include/net/regulatory.h b/include/net/regulatory.h
index b07cdc9fa454..75fc1f5a948d 100644
--- a/include/net/regulatory.h
+++ b/include/net/regulatory.h
@@ -155,6 +155,7 @@ struct ieee80211_reg_rule {
155 struct ieee80211_freq_range freq_range; 155 struct ieee80211_freq_range freq_range;
156 struct ieee80211_power_rule power_rule; 156 struct ieee80211_power_rule power_rule;
157 u32 flags; 157 u32 flags;
158 u32 dfs_cac_ms;
158}; 159};
159 160
160struct ieee80211_regdomain { 161struct ieee80211_regdomain {
@@ -172,14 +173,18 @@ struct ieee80211_regdomain {
172#define DBM_TO_MBM(gain) ((gain) * 100) 173#define DBM_TO_MBM(gain) ((gain) * 100)
173#define MBM_TO_DBM(gain) ((gain) / 100) 174#define MBM_TO_DBM(gain) ((gain) / 100)
174 175
175#define REG_RULE(start, end, bw, gain, eirp, reg_flags) \ 176#define REG_RULE_EXT(start, end, bw, gain, eirp, dfs_cac, reg_flags) \
176{ \ 177{ \
177 .freq_range.start_freq_khz = MHZ_TO_KHZ(start), \ 178 .freq_range.start_freq_khz = MHZ_TO_KHZ(start), \
178 .freq_range.end_freq_khz = MHZ_TO_KHZ(end), \ 179 .freq_range.end_freq_khz = MHZ_TO_KHZ(end), \
179 .freq_range.max_bandwidth_khz = MHZ_TO_KHZ(bw), \ 180 .freq_range.max_bandwidth_khz = MHZ_TO_KHZ(bw), \
180 .power_rule.max_antenna_gain = DBI_TO_MBI(gain),\ 181 .power_rule.max_antenna_gain = DBI_TO_MBI(gain), \
181 .power_rule.max_eirp = DBM_TO_MBM(eirp), \ 182 .power_rule.max_eirp = DBM_TO_MBM(eirp), \
182 .flags = reg_flags, \ 183 .flags = reg_flags, \
184 .dfs_cac_ms = dfs_cac, \
183} 185}
184 186
187#define REG_RULE(start, end, bw, gain, eirp, reg_flags) \
188 REG_RULE_EXT(start, end, bw, gain, eirp, 0, reg_flags)
189
185#endif 190#endif
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index ff72cab3cd3a..1ba9d626aa83 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -2335,6 +2335,7 @@ enum nl80211_band_attr {
2335 * @NL80211_FREQUENCY_ATTR_NO_160MHZ: any 160 MHz (but not 80+80) channel 2335 * @NL80211_FREQUENCY_ATTR_NO_160MHZ: any 160 MHz (but not 80+80) channel
2336 * using this channel as the primary or any of the secondary channels 2336 * using this channel as the primary or any of the secondary channels
2337 * isn't possible 2337 * isn't possible
2338 * @NL80211_FREQUENCY_ATTR_DFS_CAC_TIME: DFS CAC time in milliseconds.
2338 * @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number 2339 * @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number
2339 * currently defined 2340 * currently defined
2340 * @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use 2341 * @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use
@@ -2353,6 +2354,7 @@ enum nl80211_frequency_attr {
2353 NL80211_FREQUENCY_ATTR_NO_HT40_PLUS, 2354 NL80211_FREQUENCY_ATTR_NO_HT40_PLUS,
2354 NL80211_FREQUENCY_ATTR_NO_80MHZ, 2355 NL80211_FREQUENCY_ATTR_NO_80MHZ,
2355 NL80211_FREQUENCY_ATTR_NO_160MHZ, 2356 NL80211_FREQUENCY_ATTR_NO_160MHZ,
2357 NL80211_FREQUENCY_ATTR_DFS_CAC_TIME,
2356 2358
2357 /* keep last */ 2359 /* keep last */
2358 __NL80211_FREQUENCY_ATTR_AFTER_LAST, 2360 __NL80211_FREQUENCY_ATTR_AFTER_LAST,
@@ -2449,6 +2451,8 @@ enum nl80211_reg_type {
2449 * If you don't have one then don't send this. 2451 * If you don't have one then don't send this.
2450 * @NL80211_ATTR_POWER_RULE_MAX_EIRP: the maximum allowed EIRP for 2452 * @NL80211_ATTR_POWER_RULE_MAX_EIRP: the maximum allowed EIRP for
2451 * a given frequency range. The value is in mBm (100 * dBm). 2453 * a given frequency range. The value is in mBm (100 * dBm).
2454 * @NL80211_ATTR_DFS_CAC_TIME: DFS CAC time in milliseconds.
2455 * If not present or 0 default CAC time will be used.
2452 * @NL80211_REG_RULE_ATTR_MAX: highest regulatory rule attribute number 2456 * @NL80211_REG_RULE_ATTR_MAX: highest regulatory rule attribute number
2453 * currently defined 2457 * currently defined
2454 * @__NL80211_REG_RULE_ATTR_AFTER_LAST: internal use 2458 * @__NL80211_REG_RULE_ATTR_AFTER_LAST: internal use
@@ -2464,6 +2468,8 @@ enum nl80211_reg_rule_attr {
2464 NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN, 2468 NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN,
2465 NL80211_ATTR_POWER_RULE_MAX_EIRP, 2469 NL80211_ATTR_POWER_RULE_MAX_EIRP,
2466 2470
2471 NL80211_ATTR_DFS_CAC_TIME,
2472
2467 /* keep last */ 2473 /* keep last */
2468 __NL80211_REG_RULE_ATTR_AFTER_LAST, 2474 __NL80211_REG_RULE_ATTR_AFTER_LAST,
2469 NL80211_REG_RULE_ATTR_MAX = __NL80211_REG_RULE_ATTR_AFTER_LAST - 1 2475 NL80211_REG_RULE_ATTR_MAX = __NL80211_REG_RULE_ATTR_AFTER_LAST - 1
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 1acb29109b45..aaa59d719592 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2914,11 +2914,11 @@ static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy,
2914 2914
2915static int ieee80211_start_radar_detection(struct wiphy *wiphy, 2915static int ieee80211_start_radar_detection(struct wiphy *wiphy,
2916 struct net_device *dev, 2916 struct net_device *dev,
2917 struct cfg80211_chan_def *chandef) 2917 struct cfg80211_chan_def *chandef,
2918 u32 cac_time_ms)
2918{ 2919{
2919 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 2920 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
2920 struct ieee80211_local *local = sdata->local; 2921 struct ieee80211_local *local = sdata->local;
2921 unsigned long timeout;
2922 int err; 2922 int err;
2923 2923
2924 mutex_lock(&local->mtx); 2924 mutex_lock(&local->mtx);
@@ -2937,9 +2937,9 @@ static int ieee80211_start_radar_detection(struct wiphy *wiphy,
2937 if (err) 2937 if (err)
2938 goto out_unlock; 2938 goto out_unlock;
2939 2939
2940 timeout = msecs_to_jiffies(IEEE80211_DFS_MIN_CAC_TIME_MS);
2941 ieee80211_queue_delayed_work(&sdata->local->hw, 2940 ieee80211_queue_delayed_work(&sdata->local->hw,
2942 &sdata->dfs_cac_timer_work, timeout); 2941 &sdata->dfs_cac_timer_work,
2942 msecs_to_jiffies(cac_time_ms));
2943 2943
2944 out_unlock: 2944 out_unlock:
2945 mutex_unlock(&local->mtx); 2945 mutex_unlock(&local->mtx);
@@ -3089,52 +3089,11 @@ unlock:
3089 sdata_unlock(sdata); 3089 sdata_unlock(sdata);
3090} 3090}
3091 3091
3092int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, 3092static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata,
3093 struct cfg80211_csa_settings *params) 3093 struct cfg80211_csa_settings *params,
3094 u32 *changed)
3094{ 3095{
3095 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 3096 int err;
3096 struct ieee80211_local *local = sdata->local;
3097 struct ieee80211_chanctx_conf *chanctx_conf;
3098 struct ieee80211_chanctx *chanctx;
3099 struct ieee80211_if_mesh __maybe_unused *ifmsh;
3100 int err, num_chanctx, changed = 0;
3101
3102 sdata_assert_lock(sdata);
3103
3104 if (!list_empty(&local->roc_list) || local->scanning)
3105 return -EBUSY;
3106
3107 if (sdata->wdev.cac_started)
3108 return -EBUSY;
3109
3110 if (cfg80211_chandef_identical(&params->chandef,
3111 &sdata->vif.bss_conf.chandef))
3112 return -EINVAL;
3113
3114 rcu_read_lock();
3115 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
3116 if (!chanctx_conf) {
3117 rcu_read_unlock();
3118 return -EBUSY;
3119 }
3120
3121 /* don't handle for multi-VIF cases */
3122 chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf);
3123 if (chanctx->refcount > 1) {
3124 rcu_read_unlock();
3125 return -EBUSY;
3126 }
3127 num_chanctx = 0;
3128 list_for_each_entry_rcu(chanctx, &local->chanctx_list, list)
3129 num_chanctx++;
3130 rcu_read_unlock();
3131
3132 if (num_chanctx > 1)
3133 return -EBUSY;
3134
3135 /* don't allow another channel switch if one is already active. */
3136 if (sdata->vif.csa_active)
3137 return -EBUSY;
3138 3097
3139 switch (sdata->vif.type) { 3098 switch (sdata->vif.type) {
3140 case NL80211_IFTYPE_AP: 3099 case NL80211_IFTYPE_AP:
@@ -3170,7 +3129,7 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
3170 kfree(sdata->u.ap.next_beacon); 3129 kfree(sdata->u.ap.next_beacon);
3171 return err; 3130 return err;
3172 } 3131 }
3173 changed |= err; 3132 *changed |= err;
3174 3133
3175 break; 3134 break;
3176 case NL80211_IFTYPE_ADHOC: 3135 case NL80211_IFTYPE_ADHOC:
@@ -3204,15 +3163,15 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
3204 err = ieee80211_ibss_csa_beacon(sdata, params); 3163 err = ieee80211_ibss_csa_beacon(sdata, params);
3205 if (err < 0) 3164 if (err < 0)
3206 return err; 3165 return err;
3207 changed |= err; 3166 *changed |= err;
3208 } 3167 }
3209 3168
3210 ieee80211_send_action_csa(sdata, params); 3169 ieee80211_send_action_csa(sdata, params);
3211 3170
3212 break; 3171 break;
3213#ifdef CONFIG_MAC80211_MESH 3172#ifdef CONFIG_MAC80211_MESH
3214 case NL80211_IFTYPE_MESH_POINT: 3173 case NL80211_IFTYPE_MESH_POINT: {
3215 ifmsh = &sdata->u.mesh; 3174 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
3216 3175
3217 if (params->chandef.width != sdata->vif.bss_conf.chandef.width) 3176 if (params->chandef.width != sdata->vif.bss_conf.chandef.width)
3218 return -EINVAL; 3177 return -EINVAL;
@@ -3237,18 +3196,72 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
3237 ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE; 3196 ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE;
3238 return err; 3197 return err;
3239 } 3198 }
3240 changed |= err; 3199 *changed |= err;
3241 } 3200 }
3242 3201
3243 if (ifmsh->csa_role == IEEE80211_MESH_CSA_ROLE_INIT) 3202 if (ifmsh->csa_role == IEEE80211_MESH_CSA_ROLE_INIT)
3244 ieee80211_send_action_csa(sdata, params); 3203 ieee80211_send_action_csa(sdata, params);
3245 3204
3246 break; 3205 break;
3206 }
3247#endif 3207#endif
3248 default: 3208 default:
3249 return -EOPNOTSUPP; 3209 return -EOPNOTSUPP;
3250 } 3210 }
3251 3211
3212 return 0;
3213}
3214
3215int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
3216 struct cfg80211_csa_settings *params)
3217{
3218 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
3219 struct ieee80211_local *local = sdata->local;
3220 struct ieee80211_chanctx_conf *chanctx_conf;
3221 struct ieee80211_chanctx *chanctx;
3222 int err, num_chanctx, changed = 0;
3223
3224 sdata_assert_lock(sdata);
3225
3226 if (!list_empty(&local->roc_list) || local->scanning)
3227 return -EBUSY;
3228
3229 if (sdata->wdev.cac_started)
3230 return -EBUSY;
3231
3232 if (cfg80211_chandef_identical(&params->chandef,
3233 &sdata->vif.bss_conf.chandef))
3234 return -EINVAL;
3235
3236 rcu_read_lock();
3237 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
3238 if (!chanctx_conf) {
3239 rcu_read_unlock();
3240 return -EBUSY;
3241 }
3242
3243 /* don't handle for multi-VIF cases */
3244 chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf);
3245 if (chanctx->refcount > 1) {
3246 rcu_read_unlock();
3247 return -EBUSY;
3248 }
3249 num_chanctx = 0;
3250 list_for_each_entry_rcu(chanctx, &local->chanctx_list, list)
3251 num_chanctx++;
3252 rcu_read_unlock();
3253
3254 if (num_chanctx > 1)
3255 return -EBUSY;
3256
3257 /* don't allow another channel switch if one is already active. */
3258 if (sdata->vif.csa_active)
3259 return -EBUSY;
3260
3261 err = ieee80211_set_csa_beacon(sdata, params, &changed);
3262 if (err)
3263 return err;
3264
3252 sdata->csa_radar_required = params->radar_required; 3265 sdata->csa_radar_required = params->radar_required;
3253 3266
3254 if (params->block_tx) 3267 if (params->block_tx)
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index e458ca0dffec..06d28787945b 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -991,7 +991,6 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
991 struct ieee802_11_elems *elems) 991 struct ieee802_11_elems *elems)
992{ 992{
993 struct ieee80211_local *local = sdata->local; 993 struct ieee80211_local *local = sdata->local;
994 int freq;
995 struct cfg80211_bss *cbss; 994 struct cfg80211_bss *cbss;
996 struct ieee80211_bss *bss; 995 struct ieee80211_bss *bss;
997 struct sta_info *sta; 996 struct sta_info *sta;
@@ -1003,15 +1002,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
1003 struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band]; 1002 struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band];
1004 bool rates_updated = false; 1003 bool rates_updated = false;
1005 1004
1006 if (elems->ds_params) 1005 channel = ieee80211_get_channel(local->hw.wiphy, rx_status->freq);
1007 freq = ieee80211_channel_to_frequency(elems->ds_params[0], 1006 if (!channel)
1008 band);
1009 else
1010 freq = rx_status->freq;
1011
1012 channel = ieee80211_get_channel(local->hw.wiphy, freq);
1013
1014 if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
1015 return; 1007 return;
1016 1008
1017 if (sdata->vif.type == NL80211_IFTYPE_ADHOC && 1009 if (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 0d1a0f801b94..222c28b75315 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1391,6 +1391,7 @@ void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata);
1391void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata); 1391void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata);
1392void ieee80211_mgd_conn_tx_status(struct ieee80211_sub_if_data *sdata, 1392void ieee80211_mgd_conn_tx_status(struct ieee80211_sub_if_data *sdata,
1393 __le16 fc, bool acked); 1393 __le16 fc, bool acked);
1394void ieee80211_mgd_quiesce(struct ieee80211_sub_if_data *sdata);
1394void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata); 1395void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata);
1395 1396
1396/* IBSS code */ 1397/* IBSS code */
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 94f0af29b742..dee50aefd6e8 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -2783,28 +2783,20 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
2783 struct ieee802_11_elems *elems) 2783 struct ieee802_11_elems *elems)
2784{ 2784{
2785 struct ieee80211_local *local = sdata->local; 2785 struct ieee80211_local *local = sdata->local;
2786 int freq;
2787 struct ieee80211_bss *bss; 2786 struct ieee80211_bss *bss;
2788 struct ieee80211_channel *channel; 2787 struct ieee80211_channel *channel;
2789 2788
2790 sdata_assert_lock(sdata); 2789 sdata_assert_lock(sdata);
2791 2790
2792 if (elems->ds_params) 2791 channel = ieee80211_get_channel(local->hw.wiphy, rx_status->freq);
2793 freq = ieee80211_channel_to_frequency(elems->ds_params[0], 2792 if (!channel)
2794 rx_status->band);
2795 else
2796 freq = rx_status->freq;
2797
2798 channel = ieee80211_get_channel(local->hw.wiphy, freq);
2799
2800 if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
2801 return; 2793 return;
2802 2794
2803 bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems, 2795 bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems,
2804 channel); 2796 channel);
2805 if (bss) { 2797 if (bss) {
2806 ieee80211_rx_bss_put(local, bss);
2807 sdata->vif.bss_conf.beacon_rate = bss->beacon_rate; 2798 sdata->vif.bss_conf.beacon_rate = bss->beacon_rate;
2799 ieee80211_rx_bss_put(local, bss);
2808 } 2800 }
2809} 2801}
2810 2802
@@ -3599,6 +3591,32 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata)
3599} 3591}
3600 3592
3601#ifdef CONFIG_PM 3593#ifdef CONFIG_PM
3594void ieee80211_mgd_quiesce(struct ieee80211_sub_if_data *sdata)
3595{
3596 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
3597 u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
3598
3599 sdata_lock(sdata);
3600
3601 if (ifmgd->auth_data) {
3602 /*
3603 * If we are trying to authenticate while suspending, cfg80211
3604 * won't know and won't actually abort those attempts, thus we
3605 * need to do that ourselves.
3606 */
3607 ieee80211_send_deauth_disassoc(sdata,
3608 ifmgd->auth_data->bss->bssid,
3609 IEEE80211_STYPE_DEAUTH,
3610 WLAN_REASON_DEAUTH_LEAVING,
3611 false, frame_buf);
3612 ieee80211_destroy_auth_data(sdata, false);
3613 cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
3614 IEEE80211_DEAUTH_FRAME_LEN);
3615 }
3616
3617 sdata_unlock(sdata);
3618}
3619
3602void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata) 3620void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
3603{ 3621{
3604 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 3622 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
@@ -4417,37 +4435,41 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
4417 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 4435 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
4418 u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; 4436 u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
4419 bool tx = !req->local_state_change; 4437 bool tx = !req->local_state_change;
4420 bool report_frame = false;
4421 4438
4422 sdata_info(sdata, 4439 if (ifmgd->auth_data &&
4423 "deauthenticating from %pM by local choice (Reason: %u=%s)\n", 4440 ether_addr_equal(ifmgd->auth_data->bss->bssid, req->bssid)) {
4424 req->bssid, req->reason_code, ieee80211_get_reason_code_string(req->reason_code)); 4441 sdata_info(sdata,
4442 "aborting authentication with %pM by local choice (Reason: %u=%s)\n",
4443 req->bssid, req->reason_code,
4444 ieee80211_get_reason_code_string(req->reason_code));
4425 4445
4426 if (ifmgd->auth_data) {
4427 drv_mgd_prepare_tx(sdata->local, sdata); 4446 drv_mgd_prepare_tx(sdata->local, sdata);
4428 ieee80211_send_deauth_disassoc(sdata, req->bssid, 4447 ieee80211_send_deauth_disassoc(sdata, req->bssid,
4429 IEEE80211_STYPE_DEAUTH, 4448 IEEE80211_STYPE_DEAUTH,
4430 req->reason_code, tx, 4449 req->reason_code, tx,
4431 frame_buf); 4450 frame_buf);
4432 ieee80211_destroy_auth_data(sdata, false); 4451 ieee80211_destroy_auth_data(sdata, false);
4452 cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
4453 IEEE80211_DEAUTH_FRAME_LEN);
4433 4454
4434 report_frame = true; 4455 return 0;
4435 goto out;
4436 } 4456 }
4437 4457
4438 if (ifmgd->associated && 4458 if (ifmgd->associated &&
4439 ether_addr_equal(ifmgd->associated->bssid, req->bssid)) { 4459 ether_addr_equal(ifmgd->associated->bssid, req->bssid)) {
4460 sdata_info(sdata,
4461 "deauthenticating from %pM by local choice (Reason: %u=%s)\n",
4462 req->bssid, req->reason_code,
4463 ieee80211_get_reason_code_string(req->reason_code));
4464
4440 ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, 4465 ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
4441 req->reason_code, tx, frame_buf); 4466 req->reason_code, tx, frame_buf);
4442 report_frame = true;
4443 }
4444
4445 out:
4446 if (report_frame)
4447 cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf, 4467 cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
4448 IEEE80211_DEAUTH_FRAME_LEN); 4468 IEEE80211_DEAUTH_FRAME_LEN);
4469 return 0;
4470 }
4449 4471
4450 return 0; 4472 return -ENOTCONN;
4451} 4473}
4452 4474
4453int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, 4475int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index af64fb8e8add..d478b880a0af 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -100,10 +100,18 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
100 100
101 /* remove all interfaces that were created in the driver */ 101 /* remove all interfaces that were created in the driver */
102 list_for_each_entry(sdata, &local->interfaces, list) { 102 list_for_each_entry(sdata, &local->interfaces, list) {
103 if (!ieee80211_sdata_running(sdata) || 103 if (!ieee80211_sdata_running(sdata))
104 sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
105 sdata->vif.type == NL80211_IFTYPE_MONITOR)
106 continue; 104 continue;
105 switch (sdata->vif.type) {
106 case NL80211_IFTYPE_AP_VLAN:
107 case NL80211_IFTYPE_MONITOR:
108 continue;
109 case NL80211_IFTYPE_STATION:
110 ieee80211_mgd_quiesce(sdata);
111 break;
112 default:
113 break;
114 }
107 115
108 drv_remove_interface(local, sdata); 116 drv_remove_interface(local, sdata);
109 } 117 }
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 5b617660b0ba..216c45b949e5 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -333,6 +333,8 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
333 /* in VHT, STBC is binary */ 333 /* in VHT, STBC is binary */
334 if (status->flag & RX_FLAG_STBC_MASK) 334 if (status->flag & RX_FLAG_STBC_MASK)
335 *pos |= IEEE80211_RADIOTAP_VHT_FLAG_STBC; 335 *pos |= IEEE80211_RADIOTAP_VHT_FLAG_STBC;
336 if (status->vht_flag & RX_VHT_FLAG_BF)
337 *pos |= IEEE80211_RADIOTAP_VHT_FLAG_BEAMFORMED;
336 pos++; 338 pos++;
337 /* bandwidth */ 339 /* bandwidth */
338 if (status->vht_flag & RX_VHT_FLAG_80MHZ) 340 if (status->vht_flag & RX_VHT_FLAG_80MHZ)
@@ -1245,6 +1247,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
1245 if (ieee80211_is_data(hdr->frame_control)) { 1247 if (ieee80211_is_data(hdr->frame_control)) {
1246 sta->last_rx_rate_idx = status->rate_idx; 1248 sta->last_rx_rate_idx = status->rate_idx;
1247 sta->last_rx_rate_flag = status->flag; 1249 sta->last_rx_rate_flag = status->flag;
1250 sta->last_rx_rate_vht_flag = status->vht_flag;
1248 sta->last_rx_rate_vht_nss = status->vht_nss; 1251 sta->last_rx_rate_vht_nss = status->vht_nss;
1249 } 1252 }
1250 } 1253 }
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 836f500dfbf3..3ce7f2c8539a 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -1055,9 +1055,11 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata)
1055 /* We don't want to restart sched scan anymore. */ 1055 /* We don't want to restart sched scan anymore. */
1056 local->sched_scan_req = NULL; 1056 local->sched_scan_req = NULL;
1057 1057
1058 if (rcu_access_pointer(local->sched_scan_sdata)) 1058 if (rcu_access_pointer(local->sched_scan_sdata)) {
1059 ret = drv_sched_scan_stop(local, sdata); 1059 ret = drv_sched_scan_stop(local, sdata);
1060 1060 if (!ret)
1061 rcu_assign_pointer(local->sched_scan_sdata, NULL);
1062 }
1061out: 1063out:
1062 mutex_unlock(&local->mtx); 1064 mutex_unlock(&local->mtx);
1063 1065
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index cd9f80498c48..19d36d4117e0 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -2900,7 +2900,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
2900 cpu_to_le16(IEEE80211_FCTL_MOREDATA); 2900 cpu_to_le16(IEEE80211_FCTL_MOREDATA);
2901 } 2901 }
2902 2902
2903 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 2903 if (sdata->vif.type == NL80211_IFTYPE_AP)
2904 sdata = IEEE80211_DEV_TO_SUB_IF(skb->dev); 2904 sdata = IEEE80211_DEV_TO_SUB_IF(skb->dev);
2905 if (!ieee80211_tx_prepare(sdata, &tx, skb)) 2905 if (!ieee80211_tx_prepare(sdata, &tx, skb))
2906 break; 2906 break;
diff --git a/net/wireless/ap.c b/net/wireless/ap.c
index 68602be07cc1..3e02ade508d8 100644
--- a/net/wireless/ap.c
+++ b/net/wireless/ap.c
@@ -7,7 +7,7 @@
7 7
8 8
9static int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev, 9static int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
10 struct net_device *dev) 10 struct net_device *dev, bool notify)
11{ 11{
12 struct wireless_dev *wdev = dev->ieee80211_ptr; 12 struct wireless_dev *wdev = dev->ieee80211_ptr;
13 int err; 13 int err;
@@ -30,20 +30,21 @@ static int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
30 memset(&wdev->chandef, 0, sizeof(wdev->chandef)); 30 memset(&wdev->chandef, 0, sizeof(wdev->chandef));
31 wdev->ssid_len = 0; 31 wdev->ssid_len = 0;
32 rdev_set_qos_map(rdev, dev, NULL); 32 rdev_set_qos_map(rdev, dev, NULL);
33 nl80211_send_ap_stopped(wdev); 33 if (notify)
34 nl80211_send_ap_stopped(wdev);
34 } 35 }
35 36
36 return err; 37 return err;
37} 38}
38 39
39int cfg80211_stop_ap(struct cfg80211_registered_device *rdev, 40int cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
40 struct net_device *dev) 41 struct net_device *dev, bool notify)
41{ 42{
42 struct wireless_dev *wdev = dev->ieee80211_ptr; 43 struct wireless_dev *wdev = dev->ieee80211_ptr;
43 int err; 44 int err;
44 45
45 wdev_lock(wdev); 46 wdev_lock(wdev);
46 err = __cfg80211_stop_ap(rdev, dev); 47 err = __cfg80211_stop_ap(rdev, dev, notify);
47 wdev_unlock(wdev); 48 wdev_unlock(wdev);
48 49
49 return err; 50 return err;
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index 5946450c5406..8659d5cee2a6 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -490,6 +490,62 @@ static bool cfg80211_chandef_dfs_available(struct wiphy *wiphy,
490 return r; 490 return r;
491} 491}
492 492
493static unsigned int cfg80211_get_chans_dfs_cac_time(struct wiphy *wiphy,
494 u32 center_freq,
495 u32 bandwidth)
496{
497 struct ieee80211_channel *c;
498 u32 start_freq, end_freq, freq;
499 unsigned int dfs_cac_ms = 0;
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)
507 return 0;
508
509 if (c->flags & IEEE80211_CHAN_DISABLED)
510 return 0;
511
512 if (!(c->flags & IEEE80211_CHAN_RADAR))
513 continue;
514
515 if (c->dfs_cac_ms > dfs_cac_ms)
516 dfs_cac_ms = c->dfs_cac_ms;
517 }
518
519 return dfs_cac_ms;
520}
521
522unsigned int
523cfg80211_chandef_dfs_cac_time(struct wiphy *wiphy,
524 const struct cfg80211_chan_def *chandef)
525{
526 int width;
527 unsigned int t1 = 0, t2 = 0;
528
529 if (WARN_ON(!cfg80211_chandef_valid(chandef)))
530 return 0;
531
532 width = cfg80211_chandef_get_width(chandef);
533 if (width < 0)
534 return 0;
535
536 t1 = cfg80211_get_chans_dfs_cac_time(wiphy,
537 chandef->center_freq1,
538 width);
539
540 if (!chandef->center_freq2)
541 return t1;
542
543 t2 = cfg80211_get_chans_dfs_cac_time(wiphy,
544 chandef->center_freq2,
545 width);
546
547 return max(t1, t2);
548}
493 549
494static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, 550static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
495 u32 center_freq, u32 bandwidth, 551 u32 center_freq, u32 bandwidth,
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 76ae6a605abb..276cf938f764 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -783,7 +783,7 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev,
783 break; 783 break;
784 case NL80211_IFTYPE_AP: 784 case NL80211_IFTYPE_AP:
785 case NL80211_IFTYPE_P2P_GO: 785 case NL80211_IFTYPE_P2P_GO:
786 cfg80211_stop_ap(rdev, dev); 786 cfg80211_stop_ap(rdev, dev, true);
787 break; 787 break;
788 default: 788 default:
789 break; 789 break;
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 40683004d523..5b1fdcadd469 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -166,7 +166,6 @@ static inline void wdev_unlock(struct wireless_dev *wdev)
166 mutex_unlock(&wdev->mtx); 166 mutex_unlock(&wdev->mtx);
167} 167}
168 168
169#define ASSERT_RDEV_LOCK(rdev) ASSERT_RTNL()
170#define ASSERT_WDEV_LOCK(wdev) lockdep_assert_held(&(wdev)->mtx) 169#define ASSERT_WDEV_LOCK(wdev) lockdep_assert_held(&(wdev)->mtx)
171 170
172static inline bool cfg80211_has_monitors_only(struct cfg80211_registered_device *rdev) 171static inline bool cfg80211_has_monitors_only(struct cfg80211_registered_device *rdev)
@@ -246,10 +245,6 @@ void cfg80211_bss_age(struct cfg80211_registered_device *dev,
246 unsigned long age_secs); 245 unsigned long age_secs);
247 246
248/* IBSS */ 247/* IBSS */
249int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
250 struct net_device *dev,
251 struct cfg80211_ibss_params *params,
252 struct cfg80211_cached_keys *connkeys);
253int cfg80211_join_ibss(struct cfg80211_registered_device *rdev, 248int cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
254 struct net_device *dev, 249 struct net_device *dev,
255 struct cfg80211_ibss_params *params, 250 struct cfg80211_ibss_params *params,
@@ -283,7 +278,7 @@ int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev,
283 278
284/* AP */ 279/* AP */
285int cfg80211_stop_ap(struct cfg80211_registered_device *rdev, 280int cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
286 struct net_device *dev); 281 struct net_device *dev, bool notify);
287 282
288/* MLME */ 283/* MLME */
289int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, 284int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
@@ -402,6 +397,9 @@ void cfg80211_set_dfs_state(struct wiphy *wiphy,
402 397
403void cfg80211_dfs_channels_update_work(struct work_struct *work); 398void cfg80211_dfs_channels_update_work(struct work_struct *work);
404 399
400unsigned int
401cfg80211_chandef_dfs_cac_time(struct wiphy *wiphy,
402 const struct cfg80211_chan_def *chandef);
405 403
406static inline int 404static inline int
407cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, 405cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
diff --git a/net/wireless/genregdb.awk b/net/wireless/genregdb.awk
index fdfd3f063a9b..b35da8dc85de 100644
--- a/net/wireless/genregdb.awk
+++ b/net/wireless/genregdb.awk
@@ -66,6 +66,7 @@ function parse_reg_rule()
66 units = $8 66 units = $8
67 sub(/\)/, "", units) 67 sub(/\)/, "", units)
68 sub(/,/, "", units) 68 sub(/,/, "", units)
69 dfs_cac = $9
69 if (units == "mW") { 70 if (units == "mW") {
70 if (power == 100) { 71 if (power == 100) {
71 power = 20 72 power = 20
@@ -78,7 +79,12 @@ function parse_reg_rule()
78 } else { 79 } else {
79 print "Unknown power value in database!" 80 print "Unknown power value in database!"
80 } 81 }
82 } else {
83 dfs_cac = $8
81 } 84 }
85 sub(/,/, "", dfs_cac)
86 sub(/\(/, "", dfs_cac)
87 sub(/\)/, "", dfs_cac)
82 flagstr = "" 88 flagstr = ""
83 for (i=8; i<=NF; i++) 89 for (i=8; i<=NF; i++)
84 flagstr = flagstr $i 90 flagstr = flagstr $i
@@ -111,7 +117,7 @@ function parse_reg_rule()
111 117
112 } 118 }
113 flags = flags "0" 119 flags = flags "0"
114 printf "\t\tREG_RULE(%d, %d, %d, %d, %d, %s),\n", start, end, bw, gain, power, flags 120 printf "\t\tREG_RULE_EXT(%d, %d, %d, %d, %d, %d, %s),\n", start, end, bw, gain, power, dfs_cac, flags
115 rules++ 121 rules++
116} 122}
117 123
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c
index 349db9ddc0d1..a6b5bdad039c 100644
--- a/net/wireless/ibss.c
+++ b/net/wireless/ibss.c
@@ -82,10 +82,10 @@ void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
82} 82}
83EXPORT_SYMBOL(cfg80211_ibss_joined); 83EXPORT_SYMBOL(cfg80211_ibss_joined);
84 84
85int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, 85static int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
86 struct net_device *dev, 86 struct net_device *dev,
87 struct cfg80211_ibss_params *params, 87 struct cfg80211_ibss_params *params,
88 struct cfg80211_cached_keys *connkeys) 88 struct cfg80211_cached_keys *connkeys)
89{ 89{
90 struct wireless_dev *wdev = dev->ieee80211_ptr; 90 struct wireless_dev *wdev = dev->ieee80211_ptr;
91 struct ieee80211_channel *check_chan; 91 struct ieee80211_channel *check_chan;
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index d47c9d127b1e..c52ff59a3e96 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -778,7 +778,7 @@ void cfg80211_cac_event(struct net_device *netdev,
778 switch (event) { 778 switch (event) {
779 case NL80211_RADAR_CAC_FINISHED: 779 case NL80211_RADAR_CAC_FINISHED:
780 timeout = wdev->cac_start_time + 780 timeout = wdev->cac_start_time +
781 msecs_to_jiffies(IEEE80211_DFS_MIN_CAC_TIME_MS); 781 msecs_to_jiffies(wdev->cac_time_ms);
782 WARN_ON(!time_after_eq(jiffies, timeout)); 782 WARN_ON(!time_after_eq(jiffies, timeout));
783 cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_AVAILABLE); 783 cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_AVAILABLE);
784 break; 784 break;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 2c38b28a85b9..052c1bf8ffac 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -593,6 +593,10 @@ static int nl80211_msg_put_channel(struct sk_buff *msg,
593 if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_TIME, 593 if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_TIME,
594 time)) 594 time))
595 goto nla_put_failure; 595 goto nla_put_failure;
596 if (nla_put_u32(msg,
597 NL80211_FREQUENCY_ATTR_DFS_CAC_TIME,
598 chan->dfs_cac_ms))
599 goto nla_put_failure;
596 } 600 }
597 } 601 }
598 602
@@ -3328,7 +3332,7 @@ static int nl80211_stop_ap(struct sk_buff *skb, struct genl_info *info)
3328 struct cfg80211_registered_device *rdev = info->user_ptr[0]; 3332 struct cfg80211_registered_device *rdev = info->user_ptr[0];
3329 struct net_device *dev = info->user_ptr[1]; 3333 struct net_device *dev = info->user_ptr[1];
3330 3334
3331 return cfg80211_stop_ap(rdev, dev); 3335 return cfg80211_stop_ap(rdev, dev, false);
3332} 3336}
3333 3337
3334static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = { 3338static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = {
@@ -4614,6 +4618,7 @@ static const struct nla_policy reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] =
4614 [NL80211_ATTR_FREQ_RANGE_MAX_BW] = { .type = NLA_U32 }, 4618 [NL80211_ATTR_FREQ_RANGE_MAX_BW] = { .type = NLA_U32 },
4615 [NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN] = { .type = NLA_U32 }, 4619 [NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN] = { .type = NLA_U32 },
4616 [NL80211_ATTR_POWER_RULE_MAX_EIRP] = { .type = NLA_U32 }, 4620 [NL80211_ATTR_POWER_RULE_MAX_EIRP] = { .type = NLA_U32 },
4621 [NL80211_ATTR_DFS_CAC_TIME] = { .type = NLA_U32 },
4617}; 4622};
4618 4623
4619static int parse_reg_rule(struct nlattr *tb[], 4624static int parse_reg_rule(struct nlattr *tb[],
@@ -4649,6 +4654,10 @@ static int parse_reg_rule(struct nlattr *tb[],
4649 power_rule->max_antenna_gain = 4654 power_rule->max_antenna_gain =
4650 nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN]); 4655 nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN]);
4651 4656
4657 if (tb[NL80211_ATTR_DFS_CAC_TIME])
4658 reg_rule->dfs_cac_ms =
4659 nla_get_u32(tb[NL80211_ATTR_DFS_CAC_TIME]);
4660
4652 return 0; 4661 return 0;
4653} 4662}
4654 4663
@@ -5136,7 +5145,9 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
5136 nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN, 5145 nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN,
5137 power_rule->max_antenna_gain) || 5146 power_rule->max_antenna_gain) ||
5138 nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_EIRP, 5147 nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_EIRP,
5139 power_rule->max_eirp)) 5148 power_rule->max_eirp) ||
5149 nla_put_u32(msg, NL80211_ATTR_DFS_CAC_TIME,
5150 reg_rule->dfs_cac_ms))
5140 goto nla_put_failure_rcu; 5151 goto nla_put_failure_rcu;
5141 5152
5142 nla_nest_end(msg, nl_reg_rule); 5153 nla_nest_end(msg, nl_reg_rule);
@@ -5768,6 +5779,7 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
5768 struct wireless_dev *wdev = dev->ieee80211_ptr; 5779 struct wireless_dev *wdev = dev->ieee80211_ptr;
5769 struct cfg80211_chan_def chandef; 5780 struct cfg80211_chan_def chandef;
5770 enum nl80211_dfs_regions dfs_region; 5781 enum nl80211_dfs_regions dfs_region;
5782 unsigned int cac_time_ms;
5771 int err; 5783 int err;
5772 5784
5773 dfs_region = reg_get_dfs_region(wdev->wiphy); 5785 dfs_region = reg_get_dfs_region(wdev->wiphy);
@@ -5803,11 +5815,17 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
5803 if (err) 5815 if (err)
5804 return err; 5816 return err;
5805 5817
5806 err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef); 5818 cac_time_ms = cfg80211_chandef_dfs_cac_time(&rdev->wiphy, &chandef);
5819 if (WARN_ON(!cac_time_ms))
5820 cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
5821
5822 err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef,
5823 cac_time_ms);
5807 if (!err) { 5824 if (!err) {
5808 wdev->chandef = chandef; 5825 wdev->chandef = chandef;
5809 wdev->cac_started = true; 5826 wdev->cac_started = true;
5810 wdev->cac_start_time = jiffies; 5827 wdev->cac_start_time = jiffies;
5828 wdev->cac_time_ms = cac_time_ms;
5811 } 5829 }
5812 return err; 5830 return err;
5813} 5831}
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 90b82e08ae69..f59aaac586f8 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -91,10 +91,6 @@ static struct regulatory_request __rcu *last_request =
91/* To trigger userspace events */ 91/* To trigger userspace events */
92static struct platform_device *reg_pdev; 92static struct platform_device *reg_pdev;
93 93
94static const struct device_type reg_device_type = {
95 .uevent = reg_device_uevent,
96};
97
98/* 94/*
99 * Central wireless core regulatory domains, we only need two, 95 * Central wireless core regulatory domains, we only need two,
100 * the current one and a world regulatory domain in case we have no 96 * the current one and a world regulatory domain in case we have no
@@ -244,19 +240,21 @@ static char user_alpha2[2];
244module_param(ieee80211_regdom, charp, 0444); 240module_param(ieee80211_regdom, charp, 0444);
245MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); 241MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code");
246 242
247static void reg_kfree_last_request(void) 243static void reg_free_request(struct regulatory_request *lr)
248{ 244{
249 struct regulatory_request *lr;
250
251 lr = get_last_request();
252
253 if (lr != &core_request_world && lr) 245 if (lr != &core_request_world && lr)
254 kfree_rcu(lr, rcu_head); 246 kfree_rcu(lr, rcu_head);
255} 247}
256 248
257static void reg_update_last_request(struct regulatory_request *request) 249static void reg_update_last_request(struct regulatory_request *request)
258{ 250{
259 reg_kfree_last_request(); 251 struct regulatory_request *lr;
252
253 lr = get_last_request();
254 if (lr == request)
255 return;
256
257 reg_free_request(lr);
260 rcu_assign_pointer(last_request, request); 258 rcu_assign_pointer(last_request, request);
261} 259}
262 260
@@ -487,11 +485,16 @@ static inline void reg_regdb_query(const char *alpha2) {}
487 485
488/* 486/*
489 * This lets us keep regulatory code which is updated on a regulatory 487 * This lets us keep regulatory code which is updated on a regulatory
490 * basis in userspace. Country information is filled in by 488 * basis in userspace.
491 * reg_device_uevent
492 */ 489 */
493static int call_crda(const char *alpha2) 490static int call_crda(const char *alpha2)
494{ 491{
492 char country[12];
493 char *env[] = { country, NULL };
494
495 snprintf(country, sizeof(country), "COUNTRY=%c%c",
496 alpha2[0], alpha2[1]);
497
495 if (!is_world_regdom((char *) alpha2)) 498 if (!is_world_regdom((char *) alpha2))
496 pr_info("Calling CRDA for country: %c%c\n", 499 pr_info("Calling CRDA for country: %c%c\n",
497 alpha2[0], alpha2[1]); 500 alpha2[0], alpha2[1]);
@@ -501,7 +504,7 @@ static int call_crda(const char *alpha2)
501 /* query internal regulatory database (if it exists) */ 504 /* query internal regulatory database (if it exists) */
502 reg_regdb_query(alpha2); 505 reg_regdb_query(alpha2);
503 506
504 return kobject_uevent(&reg_pdev->dev.kobj, KOBJ_CHANGE); 507 return kobject_uevent_env(&reg_pdev->dev.kobj, KOBJ_CHANGE, env);
505} 508}
506 509
507static enum reg_request_treatment 510static enum reg_request_treatment
@@ -755,6 +758,9 @@ static int reg_rules_intersect(const struct ieee80211_regdomain *rd1,
755 power_rule->max_antenna_gain = min(power_rule1->max_antenna_gain, 758 power_rule->max_antenna_gain = min(power_rule1->max_antenna_gain,
756 power_rule2->max_antenna_gain); 759 power_rule2->max_antenna_gain);
757 760
761 intersected_rule->dfs_cac_ms = max(rule1->dfs_cac_ms,
762 rule2->dfs_cac_ms);
763
758 if (!is_valid_reg_rule(intersected_rule)) 764 if (!is_valid_reg_rule(intersected_rule))
759 return -EINVAL; 765 return -EINVAL;
760 766
@@ -1077,6 +1083,14 @@ static void handle_channel(struct wiphy *wiphy,
1077 min_t(int, chan->orig_mag, 1083 min_t(int, chan->orig_mag,
1078 MBI_TO_DBI(power_rule->max_antenna_gain)); 1084 MBI_TO_DBI(power_rule->max_antenna_gain));
1079 chan->max_reg_power = (int) MBM_TO_DBM(power_rule->max_eirp); 1085 chan->max_reg_power = (int) MBM_TO_DBM(power_rule->max_eirp);
1086
1087 if (chan->flags & IEEE80211_CHAN_RADAR) {
1088 if (reg_rule->dfs_cac_ms)
1089 chan->dfs_cac_ms = reg_rule->dfs_cac_ms;
1090 else
1091 chan->dfs_cac_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
1092 }
1093
1080 if (chan->orig_mpwr) { 1094 if (chan->orig_mpwr) {
1081 /* 1095 /*
1082 * Devices that use REGULATORY_COUNTRY_IE_FOLLOW_POWER 1096 * Devices that use REGULATORY_COUNTRY_IE_FOLLOW_POWER
@@ -2255,9 +2269,9 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd)
2255 const struct ieee80211_reg_rule *reg_rule = NULL; 2269 const struct ieee80211_reg_rule *reg_rule = NULL;
2256 const struct ieee80211_freq_range *freq_range = NULL; 2270 const struct ieee80211_freq_range *freq_range = NULL;
2257 const struct ieee80211_power_rule *power_rule = NULL; 2271 const struct ieee80211_power_rule *power_rule = NULL;
2258 char bw[32]; 2272 char bw[32], cac_time[32];
2259 2273
2260 pr_info(" (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp)\n"); 2274 pr_info(" (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp), (dfs_cac_time)\n");
2261 2275
2262 for (i = 0; i < rd->n_reg_rules; i++) { 2276 for (i = 0; i < rd->n_reg_rules; i++) {
2263 reg_rule = &rd->reg_rules[i]; 2277 reg_rule = &rd->reg_rules[i];
@@ -2272,23 +2286,32 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd)
2272 snprintf(bw, sizeof(bw), "%d KHz", 2286 snprintf(bw, sizeof(bw), "%d KHz",
2273 freq_range->max_bandwidth_khz); 2287 freq_range->max_bandwidth_khz);
2274 2288
2289 if (reg_rule->flags & NL80211_RRF_DFS)
2290 scnprintf(cac_time, sizeof(cac_time), "%u s",
2291 reg_rule->dfs_cac_ms/1000);
2292 else
2293 scnprintf(cac_time, sizeof(cac_time), "N/A");
2294
2295
2275 /* 2296 /*
2276 * There may not be documentation for max antenna gain 2297 * There may not be documentation for max antenna gain
2277 * in certain regions 2298 * in certain regions
2278 */ 2299 */
2279 if (power_rule->max_antenna_gain) 2300 if (power_rule->max_antenna_gain)
2280 pr_info(" (%d KHz - %d KHz @ %s), (%d mBi, %d mBm)\n", 2301 pr_info(" (%d KHz - %d KHz @ %s), (%d mBi, %d mBm), (%s)\n",
2281 freq_range->start_freq_khz, 2302 freq_range->start_freq_khz,
2282 freq_range->end_freq_khz, 2303 freq_range->end_freq_khz,
2283 bw, 2304 bw,
2284 power_rule->max_antenna_gain, 2305 power_rule->max_antenna_gain,
2285 power_rule->max_eirp); 2306 power_rule->max_eirp,
2307 cac_time);
2286 else 2308 else
2287 pr_info(" (%d KHz - %d KHz @ %s), (N/A, %d mBm)\n", 2309 pr_info(" (%d KHz - %d KHz @ %s), (N/A, %d mBm), (%s)\n",
2288 freq_range->start_freq_khz, 2310 freq_range->start_freq_khz,
2289 freq_range->end_freq_khz, 2311 freq_range->end_freq_khz,
2290 bw, 2312 bw,
2291 power_rule->max_eirp); 2313 power_rule->max_eirp,
2314 cac_time);
2292 } 2315 }
2293} 2316}
2294 2317
@@ -2361,9 +2384,6 @@ static int reg_set_rd_user(const struct ieee80211_regdomain *rd,
2361{ 2384{
2362 const struct ieee80211_regdomain *intersected_rd = NULL; 2385 const struct ieee80211_regdomain *intersected_rd = NULL;
2363 2386
2364 if (is_world_regdom(rd->alpha2))
2365 return -EINVAL;
2366
2367 if (!regdom_changes(rd->alpha2)) 2387 if (!regdom_changes(rd->alpha2))
2368 return -EALREADY; 2388 return -EALREADY;
2369 2389
@@ -2552,26 +2572,6 @@ int set_regdom(const struct ieee80211_regdomain *rd)
2552 return 0; 2572 return 0;
2553} 2573}
2554 2574
2555int reg_device_uevent(struct device *dev, struct kobj_uevent_env *env)
2556{
2557 struct regulatory_request *lr;
2558 u8 alpha2[2];
2559 bool add = false;
2560
2561 rcu_read_lock();
2562 lr = get_last_request();
2563 if (lr && !lr->processed) {
2564 memcpy(alpha2, lr->alpha2, 2);
2565 add = true;
2566 }
2567 rcu_read_unlock();
2568
2569 if (add)
2570 return add_uevent_var(env, "COUNTRY=%c%c",
2571 alpha2[0], alpha2[1]);
2572 return 0;
2573}
2574
2575void wiphy_regulatory_register(struct wiphy *wiphy) 2575void wiphy_regulatory_register(struct wiphy *wiphy)
2576{ 2576{
2577 struct regulatory_request *lr; 2577 struct regulatory_request *lr;
@@ -2622,8 +2622,6 @@ int __init regulatory_init(void)
2622 if (IS_ERR(reg_pdev)) 2622 if (IS_ERR(reg_pdev))
2623 return PTR_ERR(reg_pdev); 2623 return PTR_ERR(reg_pdev);
2624 2624
2625 reg_pdev->dev.type = &reg_device_type;
2626
2627 spin_lock_init(&reg_requests_lock); 2625 spin_lock_init(&reg_requests_lock);
2628 spin_lock_init(&reg_pending_beacons_lock); 2626 spin_lock_init(&reg_pending_beacons_lock);
2629 2627
diff --git a/net/wireless/reg.h b/net/wireless/reg.h
index 18524617ab62..37c180df34b7 100644
--- a/net/wireless/reg.h
+++ b/net/wireless/reg.h
@@ -26,7 +26,6 @@ enum nl80211_dfs_regions reg_get_dfs_region(struct wiphy *wiphy);
26int regulatory_hint_user(const char *alpha2, 26int regulatory_hint_user(const char *alpha2,
27 enum nl80211_user_reg_hint_type user_reg_hint_type); 27 enum nl80211_user_reg_hint_type user_reg_hint_type);
28 28
29int reg_device_uevent(struct device *dev, struct kobj_uevent_env *env);
30void wiphy_regulatory_register(struct wiphy *wiphy); 29void wiphy_regulatory_register(struct wiphy *wiphy);
31void wiphy_regulatory_deregister(struct wiphy *wiphy); 30void wiphy_regulatory_deregister(struct wiphy *wiphy);
32 31
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index d1ed4aebbbb7..7d09a712cb1f 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -659,9 +659,6 @@ static bool cfg80211_combine_bsses(struct cfg80211_registered_device *dev,
659 continue; 659 continue;
660 if (ssidlen && ie[1] != ssidlen) 660 if (ssidlen && ie[1] != ssidlen)
661 continue; 661 continue;
662 /* that would be odd ... */
663 if (bss->pub.beacon_ies)
664 continue;
665 if (WARN_ON_ONCE(bss->pub.hidden_beacon_bss)) 662 if (WARN_ON_ONCE(bss->pub.hidden_beacon_bss))
666 continue; 663 continue;
667 if (WARN_ON_ONCE(!list_empty(&bss->hidden_list))) 664 if (WARN_ON_ONCE(!list_empty(&bss->hidden_list)))
@@ -680,7 +677,8 @@ static bool cfg80211_combine_bsses(struct cfg80211_registered_device *dev,
680/* Returned bss is reference counted and must be cleaned up appropriately. */ 677/* Returned bss is reference counted and must be cleaned up appropriately. */
681static struct cfg80211_internal_bss * 678static struct cfg80211_internal_bss *
682cfg80211_bss_update(struct cfg80211_registered_device *dev, 679cfg80211_bss_update(struct cfg80211_registered_device *dev,
683 struct cfg80211_internal_bss *tmp) 680 struct cfg80211_internal_bss *tmp,
681 bool signal_valid)
684{ 682{
685 struct cfg80211_internal_bss *found = NULL; 683 struct cfg80211_internal_bss *found = NULL;
686 684
@@ -765,7 +763,12 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
765 } 763 }
766 764
767 found->pub.beacon_interval = tmp->pub.beacon_interval; 765 found->pub.beacon_interval = tmp->pub.beacon_interval;
768 found->pub.signal = tmp->pub.signal; 766 /*
767 * don't update the signal if beacon was heard on
768 * adjacent channel.
769 */
770 if (signal_valid)
771 found->pub.signal = tmp->pub.signal;
769 found->pub.capability = tmp->pub.capability; 772 found->pub.capability = tmp->pub.capability;
770 found->ts = tmp->ts; 773 found->ts = tmp->ts;
771 } else { 774 } else {
@@ -869,13 +872,14 @@ cfg80211_get_bss_channel(struct wiphy *wiphy, const u8 *ie, size_t ielen,
869/* Returned bss is reference counted and must be cleaned up appropriately. */ 872/* Returned bss is reference counted and must be cleaned up appropriately. */
870struct cfg80211_bss* 873struct cfg80211_bss*
871cfg80211_inform_bss_width(struct wiphy *wiphy, 874cfg80211_inform_bss_width(struct wiphy *wiphy,
872 struct ieee80211_channel *channel, 875 struct ieee80211_channel *rx_channel,
873 enum nl80211_bss_scan_width scan_width, 876 enum nl80211_bss_scan_width scan_width,
874 const u8 *bssid, u64 tsf, u16 capability, 877 const u8 *bssid, u64 tsf, u16 capability,
875 u16 beacon_interval, const u8 *ie, size_t ielen, 878 u16 beacon_interval, const u8 *ie, size_t ielen,
876 s32 signal, gfp_t gfp) 879 s32 signal, gfp_t gfp)
877{ 880{
878 struct cfg80211_bss_ies *ies; 881 struct cfg80211_bss_ies *ies;
882 struct ieee80211_channel *channel;
879 struct cfg80211_internal_bss tmp = {}, *res; 883 struct cfg80211_internal_bss tmp = {}, *res;
880 884
881 if (WARN_ON(!wiphy)) 885 if (WARN_ON(!wiphy))
@@ -885,7 +889,7 @@ cfg80211_inform_bss_width(struct wiphy *wiphy,
885 (signal < 0 || signal > 100))) 889 (signal < 0 || signal > 100)))
886 return NULL; 890 return NULL;
887 891
888 channel = cfg80211_get_bss_channel(wiphy, ie, ielen, channel); 892 channel = cfg80211_get_bss_channel(wiphy, ie, ielen, rx_channel);
889 if (!channel) 893 if (!channel)
890 return NULL; 894 return NULL;
891 895
@@ -913,7 +917,8 @@ cfg80211_inform_bss_width(struct wiphy *wiphy,
913 rcu_assign_pointer(tmp.pub.beacon_ies, ies); 917 rcu_assign_pointer(tmp.pub.beacon_ies, ies);
914 rcu_assign_pointer(tmp.pub.ies, ies); 918 rcu_assign_pointer(tmp.pub.ies, ies);
915 919
916 res = cfg80211_bss_update(wiphy_to_dev(wiphy), &tmp); 920 res = cfg80211_bss_update(wiphy_to_dev(wiphy), &tmp,
921 rx_channel == channel);
917 if (!res) 922 if (!res)
918 return NULL; 923 return NULL;
919 924
@@ -929,20 +934,21 @@ EXPORT_SYMBOL(cfg80211_inform_bss_width);
929/* Returned bss is reference counted and must be cleaned up appropriately. */ 934/* Returned bss is reference counted and must be cleaned up appropriately. */
930struct cfg80211_bss * 935struct cfg80211_bss *
931cfg80211_inform_bss_width_frame(struct wiphy *wiphy, 936cfg80211_inform_bss_width_frame(struct wiphy *wiphy,
932 struct ieee80211_channel *channel, 937 struct ieee80211_channel *rx_channel,
933 enum nl80211_bss_scan_width scan_width, 938 enum nl80211_bss_scan_width scan_width,
934 struct ieee80211_mgmt *mgmt, size_t len, 939 struct ieee80211_mgmt *mgmt, size_t len,
935 s32 signal, gfp_t gfp) 940 s32 signal, gfp_t gfp)
936{ 941{
937 struct cfg80211_internal_bss tmp = {}, *res; 942 struct cfg80211_internal_bss tmp = {}, *res;
938 struct cfg80211_bss_ies *ies; 943 struct cfg80211_bss_ies *ies;
944 struct ieee80211_channel *channel;
939 size_t ielen = len - offsetof(struct ieee80211_mgmt, 945 size_t ielen = len - offsetof(struct ieee80211_mgmt,
940 u.probe_resp.variable); 946 u.probe_resp.variable);
941 947
942 BUILD_BUG_ON(offsetof(struct ieee80211_mgmt, u.probe_resp.variable) != 948 BUILD_BUG_ON(offsetof(struct ieee80211_mgmt, u.probe_resp.variable) !=
943 offsetof(struct ieee80211_mgmt, u.beacon.variable)); 949 offsetof(struct ieee80211_mgmt, u.beacon.variable));
944 950
945 trace_cfg80211_inform_bss_width_frame(wiphy, channel, scan_width, mgmt, 951 trace_cfg80211_inform_bss_width_frame(wiphy, rx_channel, scan_width, mgmt,
946 len, signal); 952 len, signal);
947 953
948 if (WARN_ON(!mgmt)) 954 if (WARN_ON(!mgmt))
@@ -959,7 +965,7 @@ cfg80211_inform_bss_width_frame(struct wiphy *wiphy,
959 return NULL; 965 return NULL;
960 966
961 channel = cfg80211_get_bss_channel(wiphy, mgmt->u.beacon.variable, 967 channel = cfg80211_get_bss_channel(wiphy, mgmt->u.beacon.variable,
962 ielen, channel); 968 ielen, rx_channel);
963 if (!channel) 969 if (!channel)
964 return NULL; 970 return NULL;
965 971
@@ -983,7 +989,8 @@ cfg80211_inform_bss_width_frame(struct wiphy *wiphy,
983 tmp.pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int); 989 tmp.pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int);
984 tmp.pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info); 990 tmp.pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info);
985 991
986 res = cfg80211_bss_update(wiphy_to_dev(wiphy), &tmp); 992 res = cfg80211_bss_update(wiphy_to_dev(wiphy), &tmp,
993 rx_channel == channel);
987 if (!res) 994 if (!res)
988 return NULL; 995 return NULL;
989 996
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index f04d4c32e96e..acdcb4a81817 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -64,7 +64,6 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev)
64 int n_channels, err; 64 int n_channels, err;
65 65
66 ASSERT_RTNL(); 66 ASSERT_RTNL();
67 ASSERT_RDEV_LOCK(rdev);
68 ASSERT_WDEV_LOCK(wdev); 67 ASSERT_WDEV_LOCK(wdev);
69 68
70 if (rdev->scan_req || rdev->scan_msg) 69 if (rdev->scan_req || rdev->scan_msg)
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 57b3ce7a6b92..39fc1d70da69 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -838,7 +838,6 @@ void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev)
838 struct wireless_dev *wdev; 838 struct wireless_dev *wdev;
839 839
840 ASSERT_RTNL(); 840 ASSERT_RTNL();
841 ASSERT_RDEV_LOCK(rdev);
842 841
843 list_for_each_entry(wdev, &rdev->wdev_list, list) 842 list_for_each_entry(wdev, &rdev->wdev_list, list)
844 cfg80211_process_wdev_events(wdev); 843 cfg80211_process_wdev_events(wdev);
@@ -851,7 +850,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
851 int err; 850 int err;
852 enum nl80211_iftype otype = dev->ieee80211_ptr->iftype; 851 enum nl80211_iftype otype = dev->ieee80211_ptr->iftype;
853 852
854 ASSERT_RDEV_LOCK(rdev); 853 ASSERT_RTNL();
855 854
856 /* don't support changing VLANs, you just re-create them */ 855 /* don't support changing VLANs, you just re-create them */
857 if (otype == NL80211_IFTYPE_AP_VLAN) 856 if (otype == NL80211_IFTYPE_AP_VLAN)
@@ -886,7 +885,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
886 885
887 switch (otype) { 886 switch (otype) {
888 case NL80211_IFTYPE_AP: 887 case NL80211_IFTYPE_AP:
889 cfg80211_stop_ap(rdev, dev); 888 cfg80211_stop_ap(rdev, dev, true);
890 break; 889 break;
891 case NL80211_IFTYPE_ADHOC: 890 case NL80211_IFTYPE_ADHOC:
892 cfg80211_leave_ibss(rdev, dev, false); 891 cfg80211_leave_ibss(rdev, dev, false);
diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c
index 14c9a2583ba0..86c331a65664 100644
--- a/net/wireless/wext-sme.c
+++ b/net/wireless/wext-sme.c
@@ -21,7 +21,7 @@ int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
21 const u8 *prev_bssid = NULL; 21 const u8 *prev_bssid = NULL;
22 int err, i; 22 int err, i;
23 23
24 ASSERT_RDEV_LOCK(rdev); 24 ASSERT_RTNL();
25 ASSERT_WDEV_LOCK(wdev); 25 ASSERT_WDEV_LOCK(wdev);
26 26
27 if (!netif_running(wdev->netdev)) 27 if (!netif_running(wdev->netdev))