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)) |
