diff options
author | John W. Linville <linville@tuxdriver.com> | 2014-03-20 11:53:20 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2014-03-20 11:53:20 -0400 |
commit | 7eb2450a51ea7606fa69ae4bb2113e0f228223cc (patch) | |
tree | 6cd273487574edd2da40ce14b1981e14a5171caa | |
parent | 474a41e94dfc85167e1761bfbb8bf180f90633b2 (diff) | |
parent | 73fb08e24ae840bc518facc2c605dd6bb3751fec (diff) |
Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
-rw-r--r-- | include/linux/ieee80211.h | 4 | ||||
-rw-r--r-- | include/net/cfg80211.h | 23 | ||||
-rw-r--r-- | include/net/mac80211.h | 6 | ||||
-rw-r--r-- | include/net/regulatory.h | 21 | ||||
-rw-r--r-- | include/uapi/linux/nl80211.h | 6 | ||||
-rw-r--r-- | net/mac80211/cfg.c | 121 | ||||
-rw-r--r-- | net/mac80211/ibss.c | 12 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 1 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 70 | ||||
-rw-r--r-- | net/mac80211/pm.c | 14 | ||||
-rw-r--r-- | net/mac80211/rx.c | 3 | ||||
-rw-r--r-- | net/mac80211/scan.c | 6 | ||||
-rw-r--r-- | net/mac80211/tx.c | 2 | ||||
-rw-r--r-- | net/wireless/ap.c | 9 | ||||
-rw-r--r-- | net/wireless/chan.c | 56 | ||||
-rw-r--r-- | net/wireless/core.c | 2 | ||||
-rw-r--r-- | net/wireless/core.h | 10 | ||||
-rw-r--r-- | net/wireless/genregdb.awk | 8 | ||||
-rw-r--r-- | net/wireless/ibss.c | 8 | ||||
-rw-r--r-- | net/wireless/mlme.c | 2 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 24 | ||||
-rw-r--r-- | net/wireless/reg.c | 86 | ||||
-rw-r--r-- | net/wireless/reg.h | 1 | ||||
-rw-r--r-- | net/wireless/scan.c | 31 | ||||
-rw-r--r-- | net/wireless/sme.c | 1 | ||||
-rw-r--r-- | net/wireless/util.c | 5 | ||||
-rw-r--r-- | net/wireless/wext-sme.c | 2 |
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 | */ |
155 | struct ieee80211_channel { | 156 | struct 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 | */ |
3683 | struct cfg80211_bss * __must_check | 3688 | struct cfg80211_bss * __must_check |
3684 | cfg80211_inform_bss_width_frame(struct wiphy *wiphy, | 3689 | cfg80211_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 | ||
3690 | static inline struct cfg80211_bss * __must_check | 3695 | static inline struct cfg80211_bss * __must_check |
3691 | cfg80211_inform_bss_frame(struct wiphy *wiphy, | 3696 | cfg80211_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 | */ |
3722 | struct cfg80211_bss * __must_check | 3727 | struct cfg80211_bss * __must_check |
3723 | cfg80211_inform_bss_width(struct wiphy *wiphy, | 3728 | cfg80211_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 | ||
3730 | static inline struct cfg80211_bss * __must_check | 3735 | static inline struct cfg80211_bss * __must_check |
3731 | cfg80211_inform_bss(struct wiphy *wiphy, | 3736 | cfg80211_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 | */ |
881 | enum mac80211_rx_vht_flags { | 882 | enum 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 | ||
160 | struct ieee80211_regdomain { | 161 | struct 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 | ||
2915 | static int ieee80211_start_radar_detection(struct wiphy *wiphy, | 2915 | static 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 | ||
3092 | int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | 3092 | static 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(¶ms->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 | |||
3215 | int 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(¶ms->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); | |||
1391 | void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata); | 1391 | void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata); |
1392 | void ieee80211_mgd_conn_tx_status(struct ieee80211_sub_if_data *sdata, | 1392 | void ieee80211_mgd_conn_tx_status(struct ieee80211_sub_if_data *sdata, |
1393 | __le16 fc, bool acked); | 1393 | __le16 fc, bool acked); |
1394 | void ieee80211_mgd_quiesce(struct ieee80211_sub_if_data *sdata); | ||
1394 | void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata); | 1395 | void 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 |
3594 | void 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 | |||
3602 | void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata) | 3620 | void 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 | ||
4453 | int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, | 4475 | int 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 | } | ||
1061 | out: | 1063 | out: |
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 | ||
9 | static int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev, | 9 | static 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 | ||
39 | int cfg80211_stop_ap(struct cfg80211_registered_device *rdev, | 40 | int 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 | ||
493 | static 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 | |||
522 | unsigned int | ||
523 | cfg80211_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 | ||
494 | static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, | 550 | static 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 | ||
172 | static inline bool cfg80211_has_monitors_only(struct cfg80211_registered_device *rdev) | 171 | static 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 */ |
249 | int __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); | ||
253 | int cfg80211_join_ibss(struct cfg80211_registered_device *rdev, | 248 | int 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 */ |
285 | int cfg80211_stop_ap(struct cfg80211_registered_device *rdev, | 280 | int 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 */ |
289 | int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | 284 | int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, |
@@ -402,6 +397,9 @@ void cfg80211_set_dfs_state(struct wiphy *wiphy, | |||
402 | 397 | ||
403 | void cfg80211_dfs_channels_update_work(struct work_struct *work); | 398 | void cfg80211_dfs_channels_update_work(struct work_struct *work); |
404 | 399 | ||
400 | unsigned int | ||
401 | cfg80211_chandef_dfs_cac_time(struct wiphy *wiphy, | ||
402 | const struct cfg80211_chan_def *chandef); | ||
405 | 403 | ||
406 | static inline int | 404 | static inline int |
407 | cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, | 405 | cfg80211_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 | } |
83 | EXPORT_SYMBOL(cfg80211_ibss_joined); | 83 | EXPORT_SYMBOL(cfg80211_ibss_joined); |
84 | 84 | ||
85 | int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, | 85 | static 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 | ||
3334 | static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = { | 3338 | static 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 | ||
4619 | static int parse_reg_rule(struct nlattr *tb[], | 4624 | static 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 */ |
92 | static struct platform_device *reg_pdev; | 92 | static struct platform_device *reg_pdev; |
93 | 93 | ||
94 | static 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]; | |||
244 | module_param(ieee80211_regdom, charp, 0444); | 240 | module_param(ieee80211_regdom, charp, 0444); |
245 | MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); | 241 | MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); |
246 | 242 | ||
247 | static void reg_kfree_last_request(void) | 243 | static 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 | ||
257 | static void reg_update_last_request(struct regulatory_request *request) | 249 | static 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 | */ |
493 | static int call_crda(const char *alpha2) | 490 | static 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(®_pdev->dev.kobj, KOBJ_CHANGE); | 507 | return kobject_uevent_env(®_pdev->dev.kobj, KOBJ_CHANGE, env); |
505 | } | 508 | } |
506 | 509 | ||
507 | static enum reg_request_treatment | 510 | static 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 | ||
2555 | int 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 | |||
2575 | void wiphy_regulatory_register(struct wiphy *wiphy) | 2575 | void 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 = ®_device_type; | ||
2626 | |||
2627 | spin_lock_init(®_requests_lock); | 2625 | spin_lock_init(®_requests_lock); |
2628 | spin_lock_init(®_pending_beacons_lock); | 2626 | spin_lock_init(®_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); | |||
26 | int regulatory_hint_user(const char *alpha2, | 26 | int 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 | ||
29 | int reg_device_uevent(struct device *dev, struct kobj_uevent_env *env); | ||
30 | void wiphy_regulatory_register(struct wiphy *wiphy); | 29 | void wiphy_regulatory_register(struct wiphy *wiphy); |
31 | void wiphy_regulatory_deregister(struct wiphy *wiphy); | 30 | void 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. */ |
681 | static struct cfg80211_internal_bss * | 678 | static struct cfg80211_internal_bss * |
682 | cfg80211_bss_update(struct cfg80211_registered_device *dev, | 679 | cfg80211_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. */ |
870 | struct cfg80211_bss* | 873 | struct cfg80211_bss* |
871 | cfg80211_inform_bss_width(struct wiphy *wiphy, | 874 | cfg80211_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. */ |
930 | struct cfg80211_bss * | 935 | struct cfg80211_bss * |
931 | cfg80211_inform_bss_width_frame(struct wiphy *wiphy, | 936 | cfg80211_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)) |