xref: /freebsd/sys/contrib/dev/athk/ath11k/mac.c (revision 28348caeee6ee98251b0aaa026e8d52b5032e92c)
1dd4f32aeSBjoern A. Zeeb // SPDX-License-Identifier: BSD-3-Clause-Clear
2dd4f32aeSBjoern A. Zeeb /*
3dd4f32aeSBjoern A. Zeeb  * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
4*28348caeSBjoern A. Zeeb  * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
5dd4f32aeSBjoern A. Zeeb  */
6dd4f32aeSBjoern A. Zeeb 
7dd4f32aeSBjoern A. Zeeb #include <net/mac80211.h>
8dd4f32aeSBjoern A. Zeeb #include <linux/etherdevice.h>
9*28348caeSBjoern A. Zeeb #include <linux/bitfield.h>
10*28348caeSBjoern A. Zeeb #include <linux/inetdevice.h>
11*28348caeSBjoern A. Zeeb #include <net/if_inet6.h>
12*28348caeSBjoern A. Zeeb #include <net/ipv6.h>
13*28348caeSBjoern A. Zeeb 
14dd4f32aeSBjoern A. Zeeb #include "mac.h"
15dd4f32aeSBjoern A. Zeeb #include "core.h"
16dd4f32aeSBjoern A. Zeeb #include "debug.h"
17dd4f32aeSBjoern A. Zeeb #include "wmi.h"
18dd4f32aeSBjoern A. Zeeb #include "hw.h"
19dd4f32aeSBjoern A. Zeeb #include "dp_tx.h"
20dd4f32aeSBjoern A. Zeeb #include "dp_rx.h"
21dd4f32aeSBjoern A. Zeeb #include "testmode.h"
22dd4f32aeSBjoern A. Zeeb #include "peer.h"
23dd4f32aeSBjoern A. Zeeb #include "debugfs_sta.h"
24*28348caeSBjoern A. Zeeb #include "hif.h"
25*28348caeSBjoern A. Zeeb #include "wow.h"
26dd4f32aeSBjoern A. Zeeb 
27dd4f32aeSBjoern A. Zeeb #define CHAN2G(_channel, _freq, _flags) { \
28dd4f32aeSBjoern A. Zeeb 	.band                   = NL80211_BAND_2GHZ, \
29dd4f32aeSBjoern A. Zeeb 	.hw_value               = (_channel), \
30dd4f32aeSBjoern A. Zeeb 	.center_freq            = (_freq), \
31dd4f32aeSBjoern A. Zeeb 	.flags                  = (_flags), \
32dd4f32aeSBjoern A. Zeeb 	.max_antenna_gain       = 0, \
33dd4f32aeSBjoern A. Zeeb 	.max_power              = 30, \
34dd4f32aeSBjoern A. Zeeb }
35dd4f32aeSBjoern A. Zeeb 
36dd4f32aeSBjoern A. Zeeb #define CHAN5G(_channel, _freq, _flags) { \
37dd4f32aeSBjoern A. Zeeb 	.band                   = NL80211_BAND_5GHZ, \
38dd4f32aeSBjoern A. Zeeb 	.hw_value               = (_channel), \
39dd4f32aeSBjoern A. Zeeb 	.center_freq            = (_freq), \
40dd4f32aeSBjoern A. Zeeb 	.flags                  = (_flags), \
41dd4f32aeSBjoern A. Zeeb 	.max_antenna_gain       = 0, \
42dd4f32aeSBjoern A. Zeeb 	.max_power              = 30, \
43dd4f32aeSBjoern A. Zeeb }
44dd4f32aeSBjoern A. Zeeb 
45dd4f32aeSBjoern A. Zeeb #define CHAN6G(_channel, _freq, _flags) { \
46dd4f32aeSBjoern A. Zeeb 	.band                   = NL80211_BAND_6GHZ, \
47dd4f32aeSBjoern A. Zeeb 	.hw_value               = (_channel), \
48dd4f32aeSBjoern A. Zeeb 	.center_freq            = (_freq), \
49dd4f32aeSBjoern A. Zeeb 	.flags                  = (_flags), \
50dd4f32aeSBjoern A. Zeeb 	.max_antenna_gain       = 0, \
51dd4f32aeSBjoern A. Zeeb 	.max_power              = 30, \
52dd4f32aeSBjoern A. Zeeb }
53dd4f32aeSBjoern A. Zeeb 
54dd4f32aeSBjoern A. Zeeb static const struct ieee80211_channel ath11k_2ghz_channels[] = {
55dd4f32aeSBjoern A. Zeeb 	CHAN2G(1, 2412, 0),
56dd4f32aeSBjoern A. Zeeb 	CHAN2G(2, 2417, 0),
57dd4f32aeSBjoern A. Zeeb 	CHAN2G(3, 2422, 0),
58dd4f32aeSBjoern A. Zeeb 	CHAN2G(4, 2427, 0),
59dd4f32aeSBjoern A. Zeeb 	CHAN2G(5, 2432, 0),
60dd4f32aeSBjoern A. Zeeb 	CHAN2G(6, 2437, 0),
61dd4f32aeSBjoern A. Zeeb 	CHAN2G(7, 2442, 0),
62dd4f32aeSBjoern A. Zeeb 	CHAN2G(8, 2447, 0),
63dd4f32aeSBjoern A. Zeeb 	CHAN2G(9, 2452, 0),
64dd4f32aeSBjoern A. Zeeb 	CHAN2G(10, 2457, 0),
65dd4f32aeSBjoern A. Zeeb 	CHAN2G(11, 2462, 0),
66dd4f32aeSBjoern A. Zeeb 	CHAN2G(12, 2467, 0),
67dd4f32aeSBjoern A. Zeeb 	CHAN2G(13, 2472, 0),
68dd4f32aeSBjoern A. Zeeb 	CHAN2G(14, 2484, 0),
69dd4f32aeSBjoern A. Zeeb };
70dd4f32aeSBjoern A. Zeeb 
71dd4f32aeSBjoern A. Zeeb static const struct ieee80211_channel ath11k_5ghz_channels[] = {
72dd4f32aeSBjoern A. Zeeb 	CHAN5G(36, 5180, 0),
73dd4f32aeSBjoern A. Zeeb 	CHAN5G(40, 5200, 0),
74dd4f32aeSBjoern A. Zeeb 	CHAN5G(44, 5220, 0),
75dd4f32aeSBjoern A. Zeeb 	CHAN5G(48, 5240, 0),
76dd4f32aeSBjoern A. Zeeb 	CHAN5G(52, 5260, 0),
77dd4f32aeSBjoern A. Zeeb 	CHAN5G(56, 5280, 0),
78dd4f32aeSBjoern A. Zeeb 	CHAN5G(60, 5300, 0),
79dd4f32aeSBjoern A. Zeeb 	CHAN5G(64, 5320, 0),
80dd4f32aeSBjoern A. Zeeb 	CHAN5G(100, 5500, 0),
81dd4f32aeSBjoern A. Zeeb 	CHAN5G(104, 5520, 0),
82dd4f32aeSBjoern A. Zeeb 	CHAN5G(108, 5540, 0),
83dd4f32aeSBjoern A. Zeeb 	CHAN5G(112, 5560, 0),
84dd4f32aeSBjoern A. Zeeb 	CHAN5G(116, 5580, 0),
85dd4f32aeSBjoern A. Zeeb 	CHAN5G(120, 5600, 0),
86dd4f32aeSBjoern A. Zeeb 	CHAN5G(124, 5620, 0),
87dd4f32aeSBjoern A. Zeeb 	CHAN5G(128, 5640, 0),
88dd4f32aeSBjoern A. Zeeb 	CHAN5G(132, 5660, 0),
89dd4f32aeSBjoern A. Zeeb 	CHAN5G(136, 5680, 0),
90dd4f32aeSBjoern A. Zeeb 	CHAN5G(140, 5700, 0),
91dd4f32aeSBjoern A. Zeeb 	CHAN5G(144, 5720, 0),
92dd4f32aeSBjoern A. Zeeb 	CHAN5G(149, 5745, 0),
93dd4f32aeSBjoern A. Zeeb 	CHAN5G(153, 5765, 0),
94dd4f32aeSBjoern A. Zeeb 	CHAN5G(157, 5785, 0),
95dd4f32aeSBjoern A. Zeeb 	CHAN5G(161, 5805, 0),
96dd4f32aeSBjoern A. Zeeb 	CHAN5G(165, 5825, 0),
97dd4f32aeSBjoern A. Zeeb 	CHAN5G(169, 5845, 0),
98dd4f32aeSBjoern A. Zeeb 	CHAN5G(173, 5865, 0),
99*28348caeSBjoern A. Zeeb 	CHAN5G(177, 5885, 0),
100dd4f32aeSBjoern A. Zeeb };
101dd4f32aeSBjoern A. Zeeb 
102dd4f32aeSBjoern A. Zeeb static const struct ieee80211_channel ath11k_6ghz_channels[] = {
103dd4f32aeSBjoern A. Zeeb 	CHAN6G(1, 5955, 0),
104dd4f32aeSBjoern A. Zeeb 	CHAN6G(5, 5975, 0),
105dd4f32aeSBjoern A. Zeeb 	CHAN6G(9, 5995, 0),
106dd4f32aeSBjoern A. Zeeb 	CHAN6G(13, 6015, 0),
107dd4f32aeSBjoern A. Zeeb 	CHAN6G(17, 6035, 0),
108dd4f32aeSBjoern A. Zeeb 	CHAN6G(21, 6055, 0),
109dd4f32aeSBjoern A. Zeeb 	CHAN6G(25, 6075, 0),
110dd4f32aeSBjoern A. Zeeb 	CHAN6G(29, 6095, 0),
111dd4f32aeSBjoern A. Zeeb 	CHAN6G(33, 6115, 0),
112dd4f32aeSBjoern A. Zeeb 	CHAN6G(37, 6135, 0),
113dd4f32aeSBjoern A. Zeeb 	CHAN6G(41, 6155, 0),
114dd4f32aeSBjoern A. Zeeb 	CHAN6G(45, 6175, 0),
115dd4f32aeSBjoern A. Zeeb 	CHAN6G(49, 6195, 0),
116dd4f32aeSBjoern A. Zeeb 	CHAN6G(53, 6215, 0),
117dd4f32aeSBjoern A. Zeeb 	CHAN6G(57, 6235, 0),
118dd4f32aeSBjoern A. Zeeb 	CHAN6G(61, 6255, 0),
119dd4f32aeSBjoern A. Zeeb 	CHAN6G(65, 6275, 0),
120dd4f32aeSBjoern A. Zeeb 	CHAN6G(69, 6295, 0),
121dd4f32aeSBjoern A. Zeeb 	CHAN6G(73, 6315, 0),
122dd4f32aeSBjoern A. Zeeb 	CHAN6G(77, 6335, 0),
123dd4f32aeSBjoern A. Zeeb 	CHAN6G(81, 6355, 0),
124dd4f32aeSBjoern A. Zeeb 	CHAN6G(85, 6375, 0),
125dd4f32aeSBjoern A. Zeeb 	CHAN6G(89, 6395, 0),
126dd4f32aeSBjoern A. Zeeb 	CHAN6G(93, 6415, 0),
127dd4f32aeSBjoern A. Zeeb 	CHAN6G(97, 6435, 0),
128dd4f32aeSBjoern A. Zeeb 	CHAN6G(101, 6455, 0),
129dd4f32aeSBjoern A. Zeeb 	CHAN6G(105, 6475, 0),
130dd4f32aeSBjoern A. Zeeb 	CHAN6G(109, 6495, 0),
131dd4f32aeSBjoern A. Zeeb 	CHAN6G(113, 6515, 0),
132dd4f32aeSBjoern A. Zeeb 	CHAN6G(117, 6535, 0),
133dd4f32aeSBjoern A. Zeeb 	CHAN6G(121, 6555, 0),
134dd4f32aeSBjoern A. Zeeb 	CHAN6G(125, 6575, 0),
135dd4f32aeSBjoern A. Zeeb 	CHAN6G(129, 6595, 0),
136dd4f32aeSBjoern A. Zeeb 	CHAN6G(133, 6615, 0),
137dd4f32aeSBjoern A. Zeeb 	CHAN6G(137, 6635, 0),
138dd4f32aeSBjoern A. Zeeb 	CHAN6G(141, 6655, 0),
139dd4f32aeSBjoern A. Zeeb 	CHAN6G(145, 6675, 0),
140dd4f32aeSBjoern A. Zeeb 	CHAN6G(149, 6695, 0),
141dd4f32aeSBjoern A. Zeeb 	CHAN6G(153, 6715, 0),
142dd4f32aeSBjoern A. Zeeb 	CHAN6G(157, 6735, 0),
143dd4f32aeSBjoern A. Zeeb 	CHAN6G(161, 6755, 0),
144dd4f32aeSBjoern A. Zeeb 	CHAN6G(165, 6775, 0),
145dd4f32aeSBjoern A. Zeeb 	CHAN6G(169, 6795, 0),
146dd4f32aeSBjoern A. Zeeb 	CHAN6G(173, 6815, 0),
147dd4f32aeSBjoern A. Zeeb 	CHAN6G(177, 6835, 0),
148dd4f32aeSBjoern A. Zeeb 	CHAN6G(181, 6855, 0),
149dd4f32aeSBjoern A. Zeeb 	CHAN6G(185, 6875, 0),
150dd4f32aeSBjoern A. Zeeb 	CHAN6G(189, 6895, 0),
151dd4f32aeSBjoern A. Zeeb 	CHAN6G(193, 6915, 0),
152dd4f32aeSBjoern A. Zeeb 	CHAN6G(197, 6935, 0),
153dd4f32aeSBjoern A. Zeeb 	CHAN6G(201, 6955, 0),
154dd4f32aeSBjoern A. Zeeb 	CHAN6G(205, 6975, 0),
155dd4f32aeSBjoern A. Zeeb 	CHAN6G(209, 6995, 0),
156dd4f32aeSBjoern A. Zeeb 	CHAN6G(213, 7015, 0),
157dd4f32aeSBjoern A. Zeeb 	CHAN6G(217, 7035, 0),
158dd4f32aeSBjoern A. Zeeb 	CHAN6G(221, 7055, 0),
159dd4f32aeSBjoern A. Zeeb 	CHAN6G(225, 7075, 0),
160dd4f32aeSBjoern A. Zeeb 	CHAN6G(229, 7095, 0),
161dd4f32aeSBjoern A. Zeeb 	CHAN6G(233, 7115, 0),
162dd4f32aeSBjoern A. Zeeb 
163dd4f32aeSBjoern A. Zeeb 	/* new addition in IEEE Std 802.11ax-2021 */
164dd4f32aeSBjoern A. Zeeb 	CHAN6G(2, 5935, 0),
165dd4f32aeSBjoern A. Zeeb };
166dd4f32aeSBjoern A. Zeeb 
167dd4f32aeSBjoern A. Zeeb static struct ieee80211_rate ath11k_legacy_rates[] = {
168dd4f32aeSBjoern A. Zeeb 	{ .bitrate = 10,
169dd4f32aeSBjoern A. Zeeb 	  .hw_value = ATH11K_HW_RATE_CCK_LP_1M },
170dd4f32aeSBjoern A. Zeeb 	{ .bitrate = 20,
171dd4f32aeSBjoern A. Zeeb 	  .hw_value = ATH11K_HW_RATE_CCK_LP_2M,
172dd4f32aeSBjoern A. Zeeb 	  .hw_value_short = ATH11K_HW_RATE_CCK_SP_2M,
173dd4f32aeSBjoern A. Zeeb 	  .flags = IEEE80211_RATE_SHORT_PREAMBLE },
174dd4f32aeSBjoern A. Zeeb 	{ .bitrate = 55,
175dd4f32aeSBjoern A. Zeeb 	  .hw_value = ATH11K_HW_RATE_CCK_LP_5_5M,
176dd4f32aeSBjoern A. Zeeb 	  .hw_value_short = ATH11K_HW_RATE_CCK_SP_5_5M,
177dd4f32aeSBjoern A. Zeeb 	  .flags = IEEE80211_RATE_SHORT_PREAMBLE },
178dd4f32aeSBjoern A. Zeeb 	{ .bitrate = 110,
179dd4f32aeSBjoern A. Zeeb 	  .hw_value = ATH11K_HW_RATE_CCK_LP_11M,
180dd4f32aeSBjoern A. Zeeb 	  .hw_value_short = ATH11K_HW_RATE_CCK_SP_11M,
181dd4f32aeSBjoern A. Zeeb 	  .flags = IEEE80211_RATE_SHORT_PREAMBLE },
182dd4f32aeSBjoern A. Zeeb 
183dd4f32aeSBjoern A. Zeeb 	{ .bitrate = 60, .hw_value = ATH11K_HW_RATE_OFDM_6M },
184dd4f32aeSBjoern A. Zeeb 	{ .bitrate = 90, .hw_value = ATH11K_HW_RATE_OFDM_9M },
185dd4f32aeSBjoern A. Zeeb 	{ .bitrate = 120, .hw_value = ATH11K_HW_RATE_OFDM_12M },
186dd4f32aeSBjoern A. Zeeb 	{ .bitrate = 180, .hw_value = ATH11K_HW_RATE_OFDM_18M },
187dd4f32aeSBjoern A. Zeeb 	{ .bitrate = 240, .hw_value = ATH11K_HW_RATE_OFDM_24M },
188dd4f32aeSBjoern A. Zeeb 	{ .bitrate = 360, .hw_value = ATH11K_HW_RATE_OFDM_36M },
189dd4f32aeSBjoern A. Zeeb 	{ .bitrate = 480, .hw_value = ATH11K_HW_RATE_OFDM_48M },
190dd4f32aeSBjoern A. Zeeb 	{ .bitrate = 540, .hw_value = ATH11K_HW_RATE_OFDM_54M },
191dd4f32aeSBjoern A. Zeeb };
192dd4f32aeSBjoern A. Zeeb 
193dd4f32aeSBjoern A. Zeeb static const int
194dd4f32aeSBjoern A. Zeeb ath11k_phymodes[NUM_NL80211_BANDS][ATH11K_CHAN_WIDTH_NUM] = {
195dd4f32aeSBjoern A. Zeeb 	[NL80211_BAND_2GHZ] = {
196dd4f32aeSBjoern A. Zeeb 			[NL80211_CHAN_WIDTH_5] = MODE_UNKNOWN,
197dd4f32aeSBjoern A. Zeeb 			[NL80211_CHAN_WIDTH_10] = MODE_UNKNOWN,
198dd4f32aeSBjoern A. Zeeb 			[NL80211_CHAN_WIDTH_20_NOHT] = MODE_11AX_HE20_2G,
199dd4f32aeSBjoern A. Zeeb 			[NL80211_CHAN_WIDTH_20] = MODE_11AX_HE20_2G,
200dd4f32aeSBjoern A. Zeeb 			[NL80211_CHAN_WIDTH_40] = MODE_11AX_HE40_2G,
201dd4f32aeSBjoern A. Zeeb 			[NL80211_CHAN_WIDTH_80] = MODE_11AX_HE80_2G,
202dd4f32aeSBjoern A. Zeeb 			[NL80211_CHAN_WIDTH_80P80] = MODE_UNKNOWN,
203dd4f32aeSBjoern A. Zeeb 			[NL80211_CHAN_WIDTH_160] = MODE_UNKNOWN,
204dd4f32aeSBjoern A. Zeeb 	},
205dd4f32aeSBjoern A. Zeeb 	[NL80211_BAND_5GHZ] = {
206dd4f32aeSBjoern A. Zeeb 			[NL80211_CHAN_WIDTH_5] = MODE_UNKNOWN,
207dd4f32aeSBjoern A. Zeeb 			[NL80211_CHAN_WIDTH_10] = MODE_UNKNOWN,
208dd4f32aeSBjoern A. Zeeb 			[NL80211_CHAN_WIDTH_20_NOHT] = MODE_11AX_HE20,
209dd4f32aeSBjoern A. Zeeb 			[NL80211_CHAN_WIDTH_20] = MODE_11AX_HE20,
210dd4f32aeSBjoern A. Zeeb 			[NL80211_CHAN_WIDTH_40] = MODE_11AX_HE40,
211dd4f32aeSBjoern A. Zeeb 			[NL80211_CHAN_WIDTH_80] = MODE_11AX_HE80,
212dd4f32aeSBjoern A. Zeeb 			[NL80211_CHAN_WIDTH_160] = MODE_11AX_HE160,
213dd4f32aeSBjoern A. Zeeb 			[NL80211_CHAN_WIDTH_80P80] = MODE_11AX_HE80_80,
214dd4f32aeSBjoern A. Zeeb 	},
215dd4f32aeSBjoern A. Zeeb 	[NL80211_BAND_6GHZ] = {
216dd4f32aeSBjoern A. Zeeb 			[NL80211_CHAN_WIDTH_5] = MODE_UNKNOWN,
217dd4f32aeSBjoern A. Zeeb 			[NL80211_CHAN_WIDTH_10] = MODE_UNKNOWN,
218dd4f32aeSBjoern A. Zeeb 			[NL80211_CHAN_WIDTH_20_NOHT] = MODE_11AX_HE20,
219dd4f32aeSBjoern A. Zeeb 			[NL80211_CHAN_WIDTH_20] = MODE_11AX_HE20,
220dd4f32aeSBjoern A. Zeeb 			[NL80211_CHAN_WIDTH_40] = MODE_11AX_HE40,
221dd4f32aeSBjoern A. Zeeb 			[NL80211_CHAN_WIDTH_80] = MODE_11AX_HE80,
222dd4f32aeSBjoern A. Zeeb 			[NL80211_CHAN_WIDTH_160] = MODE_11AX_HE160,
223dd4f32aeSBjoern A. Zeeb 			[NL80211_CHAN_WIDTH_80P80] = MODE_11AX_HE80_80,
224dd4f32aeSBjoern A. Zeeb 	},
225dd4f32aeSBjoern A. Zeeb 
226dd4f32aeSBjoern A. Zeeb };
227dd4f32aeSBjoern A. Zeeb 
228dd4f32aeSBjoern A. Zeeb const struct htt_rx_ring_tlv_filter ath11k_mac_mon_status_filter_default = {
229dd4f32aeSBjoern A. Zeeb 	.rx_filter = HTT_RX_FILTER_TLV_FLAGS_MPDU_START |
230dd4f32aeSBjoern A. Zeeb 		     HTT_RX_FILTER_TLV_FLAGS_PPDU_END |
231dd4f32aeSBjoern A. Zeeb 		     HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE,
232dd4f32aeSBjoern A. Zeeb 	.pkt_filter_flags0 = HTT_RX_FP_MGMT_FILTER_FLAGS0,
233dd4f32aeSBjoern A. Zeeb 	.pkt_filter_flags1 = HTT_RX_FP_MGMT_FILTER_FLAGS1,
234dd4f32aeSBjoern A. Zeeb 	.pkt_filter_flags2 = HTT_RX_FP_CTRL_FILTER_FLASG2,
235dd4f32aeSBjoern A. Zeeb 	.pkt_filter_flags3 = HTT_RX_FP_DATA_FILTER_FLASG3 |
236dd4f32aeSBjoern A. Zeeb 			     HTT_RX_FP_CTRL_FILTER_FLASG3
237dd4f32aeSBjoern A. Zeeb };
238dd4f32aeSBjoern A. Zeeb 
239dd4f32aeSBjoern A. Zeeb #define ATH11K_MAC_FIRST_OFDM_RATE_IDX 4
240dd4f32aeSBjoern A. Zeeb #define ath11k_g_rates ath11k_legacy_rates
241dd4f32aeSBjoern A. Zeeb #define ath11k_g_rates_size (ARRAY_SIZE(ath11k_legacy_rates))
242dd4f32aeSBjoern A. Zeeb #define ath11k_a_rates (ath11k_legacy_rates + 4)
243dd4f32aeSBjoern A. Zeeb #define ath11k_a_rates_size (ARRAY_SIZE(ath11k_legacy_rates) - 4)
244dd4f32aeSBjoern A. Zeeb 
245*28348caeSBjoern A. Zeeb #define ATH11K_MAC_SCAN_CMD_EVT_OVERHEAD		200 /* in msecs */
246*28348caeSBjoern A. Zeeb 
247*28348caeSBjoern A. Zeeb /* Overhead due to the processing of channel switch events from FW */
248*28348caeSBjoern A. Zeeb #define ATH11K_SCAN_CHANNEL_SWITCH_WMI_EVT_OVERHEAD	10 /* in msecs */
249dd4f32aeSBjoern A. Zeeb 
250dd4f32aeSBjoern A. Zeeb static const u32 ath11k_smps_map[] = {
251dd4f32aeSBjoern A. Zeeb 	[WLAN_HT_CAP_SM_PS_STATIC] = WMI_PEER_SMPS_STATIC,
252dd4f32aeSBjoern A. Zeeb 	[WLAN_HT_CAP_SM_PS_DYNAMIC] = WMI_PEER_SMPS_DYNAMIC,
253dd4f32aeSBjoern A. Zeeb 	[WLAN_HT_CAP_SM_PS_INVALID] = WMI_PEER_SMPS_PS_NONE,
254dd4f32aeSBjoern A. Zeeb 	[WLAN_HT_CAP_SM_PS_DISABLED] = WMI_PEER_SMPS_PS_NONE,
255dd4f32aeSBjoern A. Zeeb };
256dd4f32aeSBjoern A. Zeeb 
257dd4f32aeSBjoern A. Zeeb static int ath11k_start_vdev_delay(struct ieee80211_hw *hw,
258dd4f32aeSBjoern A. Zeeb 				   struct ieee80211_vif *vif);
259dd4f32aeSBjoern A. Zeeb 
ath11k_mac_phy_he_ru_to_nl80211_he_ru_alloc(u16 ru_phy)260dd4f32aeSBjoern A. Zeeb enum nl80211_he_ru_alloc ath11k_mac_phy_he_ru_to_nl80211_he_ru_alloc(u16 ru_phy)
261dd4f32aeSBjoern A. Zeeb {
262dd4f32aeSBjoern A. Zeeb 	enum nl80211_he_ru_alloc ret;
263dd4f32aeSBjoern A. Zeeb 
264dd4f32aeSBjoern A. Zeeb 	switch (ru_phy) {
265dd4f32aeSBjoern A. Zeeb 	case RU_26:
266dd4f32aeSBjoern A. Zeeb 		ret = NL80211_RATE_INFO_HE_RU_ALLOC_26;
267dd4f32aeSBjoern A. Zeeb 		break;
268dd4f32aeSBjoern A. Zeeb 	case RU_52:
269dd4f32aeSBjoern A. Zeeb 		ret = NL80211_RATE_INFO_HE_RU_ALLOC_52;
270dd4f32aeSBjoern A. Zeeb 		break;
271dd4f32aeSBjoern A. Zeeb 	case RU_106:
272dd4f32aeSBjoern A. Zeeb 		ret = NL80211_RATE_INFO_HE_RU_ALLOC_106;
273dd4f32aeSBjoern A. Zeeb 		break;
274dd4f32aeSBjoern A. Zeeb 	case RU_242:
275dd4f32aeSBjoern A. Zeeb 		ret = NL80211_RATE_INFO_HE_RU_ALLOC_242;
276dd4f32aeSBjoern A. Zeeb 		break;
277dd4f32aeSBjoern A. Zeeb 	case RU_484:
278dd4f32aeSBjoern A. Zeeb 		ret = NL80211_RATE_INFO_HE_RU_ALLOC_484;
279dd4f32aeSBjoern A. Zeeb 		break;
280dd4f32aeSBjoern A. Zeeb 	case RU_996:
281dd4f32aeSBjoern A. Zeeb 		ret = NL80211_RATE_INFO_HE_RU_ALLOC_996;
282dd4f32aeSBjoern A. Zeeb 		break;
283dd4f32aeSBjoern A. Zeeb 	default:
284dd4f32aeSBjoern A. Zeeb 		ret = NL80211_RATE_INFO_HE_RU_ALLOC_26;
285dd4f32aeSBjoern A. Zeeb 		break;
286dd4f32aeSBjoern A. Zeeb 	}
287dd4f32aeSBjoern A. Zeeb 
288dd4f32aeSBjoern A. Zeeb 	return ret;
289dd4f32aeSBjoern A. Zeeb }
290dd4f32aeSBjoern A. Zeeb 
ath11k_mac_he_ru_tones_to_nl80211_he_ru_alloc(u16 ru_tones)291dd4f32aeSBjoern A. Zeeb enum nl80211_he_ru_alloc ath11k_mac_he_ru_tones_to_nl80211_he_ru_alloc(u16 ru_tones)
292dd4f32aeSBjoern A. Zeeb {
293dd4f32aeSBjoern A. Zeeb 	enum nl80211_he_ru_alloc ret;
294dd4f32aeSBjoern A. Zeeb 
295dd4f32aeSBjoern A. Zeeb 	switch (ru_tones) {
296dd4f32aeSBjoern A. Zeeb 	case 26:
297dd4f32aeSBjoern A. Zeeb 		ret = NL80211_RATE_INFO_HE_RU_ALLOC_26;
298dd4f32aeSBjoern A. Zeeb 		break;
299dd4f32aeSBjoern A. Zeeb 	case 52:
300dd4f32aeSBjoern A. Zeeb 		ret = NL80211_RATE_INFO_HE_RU_ALLOC_52;
301dd4f32aeSBjoern A. Zeeb 		break;
302dd4f32aeSBjoern A. Zeeb 	case 106:
303dd4f32aeSBjoern A. Zeeb 		ret = NL80211_RATE_INFO_HE_RU_ALLOC_106;
304dd4f32aeSBjoern A. Zeeb 		break;
305dd4f32aeSBjoern A. Zeeb 	case 242:
306dd4f32aeSBjoern A. Zeeb 		ret = NL80211_RATE_INFO_HE_RU_ALLOC_242;
307dd4f32aeSBjoern A. Zeeb 		break;
308dd4f32aeSBjoern A. Zeeb 	case 484:
309dd4f32aeSBjoern A. Zeeb 		ret = NL80211_RATE_INFO_HE_RU_ALLOC_484;
310dd4f32aeSBjoern A. Zeeb 		break;
311dd4f32aeSBjoern A. Zeeb 	case 996:
312dd4f32aeSBjoern A. Zeeb 		ret = NL80211_RATE_INFO_HE_RU_ALLOC_996;
313dd4f32aeSBjoern A. Zeeb 		break;
314dd4f32aeSBjoern A. Zeeb 	case (996 * 2):
315dd4f32aeSBjoern A. Zeeb 		ret = NL80211_RATE_INFO_HE_RU_ALLOC_2x996;
316dd4f32aeSBjoern A. Zeeb 		break;
317dd4f32aeSBjoern A. Zeeb 	default:
318dd4f32aeSBjoern A. Zeeb 		ret = NL80211_RATE_INFO_HE_RU_ALLOC_26;
319dd4f32aeSBjoern A. Zeeb 		break;
320dd4f32aeSBjoern A. Zeeb 	}
321dd4f32aeSBjoern A. Zeeb 
322dd4f32aeSBjoern A. Zeeb 	return ret;
323dd4f32aeSBjoern A. Zeeb }
324dd4f32aeSBjoern A. Zeeb 
ath11k_mac_he_gi_to_nl80211_he_gi(u8 sgi)325dd4f32aeSBjoern A. Zeeb enum nl80211_he_gi ath11k_mac_he_gi_to_nl80211_he_gi(u8 sgi)
326dd4f32aeSBjoern A. Zeeb {
327dd4f32aeSBjoern A. Zeeb 	enum nl80211_he_gi ret;
328dd4f32aeSBjoern A. Zeeb 
329dd4f32aeSBjoern A. Zeeb 	switch (sgi) {
330dd4f32aeSBjoern A. Zeeb 	case RX_MSDU_START_SGI_0_8_US:
331dd4f32aeSBjoern A. Zeeb 		ret = NL80211_RATE_INFO_HE_GI_0_8;
332dd4f32aeSBjoern A. Zeeb 		break;
333dd4f32aeSBjoern A. Zeeb 	case RX_MSDU_START_SGI_1_6_US:
334dd4f32aeSBjoern A. Zeeb 		ret = NL80211_RATE_INFO_HE_GI_1_6;
335dd4f32aeSBjoern A. Zeeb 		break;
336dd4f32aeSBjoern A. Zeeb 	case RX_MSDU_START_SGI_3_2_US:
337dd4f32aeSBjoern A. Zeeb 		ret = NL80211_RATE_INFO_HE_GI_3_2;
338dd4f32aeSBjoern A. Zeeb 		break;
339dd4f32aeSBjoern A. Zeeb 	default:
340dd4f32aeSBjoern A. Zeeb 		ret = NL80211_RATE_INFO_HE_GI_0_8;
341dd4f32aeSBjoern A. Zeeb 		break;
342dd4f32aeSBjoern A. Zeeb 	}
343dd4f32aeSBjoern A. Zeeb 
344dd4f32aeSBjoern A. Zeeb 	return ret;
345dd4f32aeSBjoern A. Zeeb }
346dd4f32aeSBjoern A. Zeeb 
ath11k_mac_bw_to_mac80211_bw(u8 bw)347dd4f32aeSBjoern A. Zeeb u8 ath11k_mac_bw_to_mac80211_bw(u8 bw)
348dd4f32aeSBjoern A. Zeeb {
349dd4f32aeSBjoern A. Zeeb 	u8 ret = 0;
350dd4f32aeSBjoern A. Zeeb 
351dd4f32aeSBjoern A. Zeeb 	switch (bw) {
352dd4f32aeSBjoern A. Zeeb 	case ATH11K_BW_20:
353dd4f32aeSBjoern A. Zeeb 		ret = RATE_INFO_BW_20;
354dd4f32aeSBjoern A. Zeeb 		break;
355dd4f32aeSBjoern A. Zeeb 	case ATH11K_BW_40:
356dd4f32aeSBjoern A. Zeeb 		ret = RATE_INFO_BW_40;
357dd4f32aeSBjoern A. Zeeb 		break;
358dd4f32aeSBjoern A. Zeeb 	case ATH11K_BW_80:
359dd4f32aeSBjoern A. Zeeb 		ret = RATE_INFO_BW_80;
360dd4f32aeSBjoern A. Zeeb 		break;
361dd4f32aeSBjoern A. Zeeb 	case ATH11K_BW_160:
362dd4f32aeSBjoern A. Zeeb 		ret = RATE_INFO_BW_160;
363dd4f32aeSBjoern A. Zeeb 		break;
364dd4f32aeSBjoern A. Zeeb 	}
365dd4f32aeSBjoern A. Zeeb 
366dd4f32aeSBjoern A. Zeeb 	return ret;
367dd4f32aeSBjoern A. Zeeb }
368dd4f32aeSBjoern A. Zeeb 
ath11k_mac_mac80211_bw_to_ath11k_bw(enum rate_info_bw bw)369dd4f32aeSBjoern A. Zeeb enum ath11k_supported_bw ath11k_mac_mac80211_bw_to_ath11k_bw(enum rate_info_bw bw)
370dd4f32aeSBjoern A. Zeeb {
371dd4f32aeSBjoern A. Zeeb 	switch (bw) {
372dd4f32aeSBjoern A. Zeeb 	case RATE_INFO_BW_20:
373dd4f32aeSBjoern A. Zeeb 		return ATH11K_BW_20;
374dd4f32aeSBjoern A. Zeeb 	case RATE_INFO_BW_40:
375dd4f32aeSBjoern A. Zeeb 		return ATH11K_BW_40;
376dd4f32aeSBjoern A. Zeeb 	case RATE_INFO_BW_80:
377dd4f32aeSBjoern A. Zeeb 		return ATH11K_BW_80;
378dd4f32aeSBjoern A. Zeeb 	case RATE_INFO_BW_160:
379dd4f32aeSBjoern A. Zeeb 		return ATH11K_BW_160;
380dd4f32aeSBjoern A. Zeeb 	default:
381dd4f32aeSBjoern A. Zeeb 		return ATH11K_BW_20;
382dd4f32aeSBjoern A. Zeeb 	}
383dd4f32aeSBjoern A. Zeeb }
384dd4f32aeSBjoern A. Zeeb 
ath11k_mac_hw_ratecode_to_legacy_rate(u8 hw_rc,u8 preamble,u8 * rateidx,u16 * rate)385dd4f32aeSBjoern A. Zeeb int ath11k_mac_hw_ratecode_to_legacy_rate(u8 hw_rc, u8 preamble, u8 *rateidx,
386dd4f32aeSBjoern A. Zeeb 					  u16 *rate)
387dd4f32aeSBjoern A. Zeeb {
388dd4f32aeSBjoern A. Zeeb 	/* As default, it is OFDM rates */
389dd4f32aeSBjoern A. Zeeb 	int i = ATH11K_MAC_FIRST_OFDM_RATE_IDX;
390dd4f32aeSBjoern A. Zeeb 	int max_rates_idx = ath11k_g_rates_size;
391dd4f32aeSBjoern A. Zeeb 
392dd4f32aeSBjoern A. Zeeb 	if (preamble == WMI_RATE_PREAMBLE_CCK) {
393dd4f32aeSBjoern A. Zeeb 		hw_rc &= ~ATH11k_HW_RATECODE_CCK_SHORT_PREAM_MASK;
394dd4f32aeSBjoern A. Zeeb 		i = 0;
395dd4f32aeSBjoern A. Zeeb 		max_rates_idx = ATH11K_MAC_FIRST_OFDM_RATE_IDX;
396dd4f32aeSBjoern A. Zeeb 	}
397dd4f32aeSBjoern A. Zeeb 
398dd4f32aeSBjoern A. Zeeb 	while (i < max_rates_idx) {
399dd4f32aeSBjoern A. Zeeb 		if (hw_rc == ath11k_legacy_rates[i].hw_value) {
400dd4f32aeSBjoern A. Zeeb 			*rateidx = i;
401dd4f32aeSBjoern A. Zeeb 			*rate = ath11k_legacy_rates[i].bitrate;
402dd4f32aeSBjoern A. Zeeb 			return 0;
403dd4f32aeSBjoern A. Zeeb 		}
404dd4f32aeSBjoern A. Zeeb 		i++;
405dd4f32aeSBjoern A. Zeeb 	}
406dd4f32aeSBjoern A. Zeeb 
407dd4f32aeSBjoern A. Zeeb 	return -EINVAL;
408dd4f32aeSBjoern A. Zeeb }
409dd4f32aeSBjoern A. Zeeb 
get_num_chains(u32 mask)410dd4f32aeSBjoern A. Zeeb static int get_num_chains(u32 mask)
411dd4f32aeSBjoern A. Zeeb {
412dd4f32aeSBjoern A. Zeeb 	int num_chains = 0;
413dd4f32aeSBjoern A. Zeeb 
414dd4f32aeSBjoern A. Zeeb 	while (mask) {
415dd4f32aeSBjoern A. Zeeb 		if (mask & BIT(0))
416dd4f32aeSBjoern A. Zeeb 			num_chains++;
417dd4f32aeSBjoern A. Zeeb 		mask >>= 1;
418dd4f32aeSBjoern A. Zeeb 	}
419dd4f32aeSBjoern A. Zeeb 
420dd4f32aeSBjoern A. Zeeb 	return num_chains;
421dd4f32aeSBjoern A. Zeeb }
422dd4f32aeSBjoern A. Zeeb 
ath11k_mac_bitrate_to_idx(const struct ieee80211_supported_band * sband,u32 bitrate)423dd4f32aeSBjoern A. Zeeb u8 ath11k_mac_bitrate_to_idx(const struct ieee80211_supported_band *sband,
424dd4f32aeSBjoern A. Zeeb 			     u32 bitrate)
425dd4f32aeSBjoern A. Zeeb {
426dd4f32aeSBjoern A. Zeeb 	int i;
427dd4f32aeSBjoern A. Zeeb 
428dd4f32aeSBjoern A. Zeeb 	for (i = 0; i < sband->n_bitrates; i++)
429dd4f32aeSBjoern A. Zeeb 		if (sband->bitrates[i].bitrate == bitrate)
430dd4f32aeSBjoern A. Zeeb 			return i;
431dd4f32aeSBjoern A. Zeeb 
432dd4f32aeSBjoern A. Zeeb 	return 0;
433dd4f32aeSBjoern A. Zeeb }
434dd4f32aeSBjoern A. Zeeb 
435dd4f32aeSBjoern A. Zeeb static u32
ath11k_mac_max_ht_nss(const u8 * ht_mcs_mask)436*28348caeSBjoern A. Zeeb ath11k_mac_max_ht_nss(const u8 *ht_mcs_mask)
437dd4f32aeSBjoern A. Zeeb {
438dd4f32aeSBjoern A. Zeeb 	int nss;
439dd4f32aeSBjoern A. Zeeb 
440dd4f32aeSBjoern A. Zeeb 	for (nss = IEEE80211_HT_MCS_MASK_LEN - 1; nss >= 0; nss--)
441dd4f32aeSBjoern A. Zeeb 		if (ht_mcs_mask[nss])
442dd4f32aeSBjoern A. Zeeb 			return nss + 1;
443dd4f32aeSBjoern A. Zeeb 
444dd4f32aeSBjoern A. Zeeb 	return 1;
445dd4f32aeSBjoern A. Zeeb }
446dd4f32aeSBjoern A. Zeeb 
447dd4f32aeSBjoern A. Zeeb static u32
ath11k_mac_max_vht_nss(const u16 * vht_mcs_mask)448*28348caeSBjoern A. Zeeb ath11k_mac_max_vht_nss(const u16 *vht_mcs_mask)
449dd4f32aeSBjoern A. Zeeb {
450dd4f32aeSBjoern A. Zeeb 	int nss;
451dd4f32aeSBjoern A. Zeeb 
452dd4f32aeSBjoern A. Zeeb 	for (nss = NL80211_VHT_NSS_MAX - 1; nss >= 0; nss--)
453dd4f32aeSBjoern A. Zeeb 		if (vht_mcs_mask[nss])
454dd4f32aeSBjoern A. Zeeb 			return nss + 1;
455dd4f32aeSBjoern A. Zeeb 
456dd4f32aeSBjoern A. Zeeb 	return 1;
457dd4f32aeSBjoern A. Zeeb }
458dd4f32aeSBjoern A. Zeeb 
459dd4f32aeSBjoern A. Zeeb static u32
ath11k_mac_max_he_nss(const u16 * he_mcs_mask)460*28348caeSBjoern A. Zeeb ath11k_mac_max_he_nss(const u16 *he_mcs_mask)
461dd4f32aeSBjoern A. Zeeb {
462dd4f32aeSBjoern A. Zeeb 	int nss;
463dd4f32aeSBjoern A. Zeeb 
464dd4f32aeSBjoern A. Zeeb 	for (nss = NL80211_HE_NSS_MAX - 1; nss >= 0; nss--)
465dd4f32aeSBjoern A. Zeeb 		if (he_mcs_mask[nss])
466dd4f32aeSBjoern A. Zeeb 			return nss + 1;
467dd4f32aeSBjoern A. Zeeb 
468dd4f32aeSBjoern A. Zeeb 	return 1;
469dd4f32aeSBjoern A. Zeeb }
470dd4f32aeSBjoern A. Zeeb 
ath11k_parse_mpdudensity(u8 mpdudensity)471dd4f32aeSBjoern A. Zeeb static u8 ath11k_parse_mpdudensity(u8 mpdudensity)
472dd4f32aeSBjoern A. Zeeb {
473dd4f32aeSBjoern A. Zeeb /* 802.11n D2.0 defined values for "Minimum MPDU Start Spacing":
474dd4f32aeSBjoern A. Zeeb  *   0 for no restriction
475dd4f32aeSBjoern A. Zeeb  *   1 for 1/4 us
476dd4f32aeSBjoern A. Zeeb  *   2 for 1/2 us
477dd4f32aeSBjoern A. Zeeb  *   3 for 1 us
478dd4f32aeSBjoern A. Zeeb  *   4 for 2 us
479dd4f32aeSBjoern A. Zeeb  *   5 for 4 us
480dd4f32aeSBjoern A. Zeeb  *   6 for 8 us
481dd4f32aeSBjoern A. Zeeb  *   7 for 16 us
482dd4f32aeSBjoern A. Zeeb  */
483dd4f32aeSBjoern A. Zeeb 	switch (mpdudensity) {
484dd4f32aeSBjoern A. Zeeb 	case 0:
485dd4f32aeSBjoern A. Zeeb 		return 0;
486dd4f32aeSBjoern A. Zeeb 	case 1:
487dd4f32aeSBjoern A. Zeeb 	case 2:
488dd4f32aeSBjoern A. Zeeb 	case 3:
489dd4f32aeSBjoern A. Zeeb 	/* Our lower layer calculations limit our precision to
490dd4f32aeSBjoern A. Zeeb 	 * 1 microsecond
491dd4f32aeSBjoern A. Zeeb 	 */
492dd4f32aeSBjoern A. Zeeb 		return 1;
493dd4f32aeSBjoern A. Zeeb 	case 4:
494dd4f32aeSBjoern A. Zeeb 		return 2;
495dd4f32aeSBjoern A. Zeeb 	case 5:
496dd4f32aeSBjoern A. Zeeb 		return 4;
497dd4f32aeSBjoern A. Zeeb 	case 6:
498dd4f32aeSBjoern A. Zeeb 		return 8;
499dd4f32aeSBjoern A. Zeeb 	case 7:
500dd4f32aeSBjoern A. Zeeb 		return 16;
501dd4f32aeSBjoern A. Zeeb 	default:
502dd4f32aeSBjoern A. Zeeb 		return 0;
503dd4f32aeSBjoern A. Zeeb 	}
504dd4f32aeSBjoern A. Zeeb }
505dd4f32aeSBjoern A. Zeeb 
ath11k_mac_vif_chan(struct ieee80211_vif * vif,struct cfg80211_chan_def * def)506dd4f32aeSBjoern A. Zeeb static int ath11k_mac_vif_chan(struct ieee80211_vif *vif,
507dd4f32aeSBjoern A. Zeeb 			       struct cfg80211_chan_def *def)
508dd4f32aeSBjoern A. Zeeb {
509dd4f32aeSBjoern A. Zeeb 	struct ieee80211_chanctx_conf *conf;
510dd4f32aeSBjoern A. Zeeb 
511dd4f32aeSBjoern A. Zeeb 	rcu_read_lock();
512*28348caeSBjoern A. Zeeb 	conf = rcu_dereference(vif->bss_conf.chanctx_conf);
513dd4f32aeSBjoern A. Zeeb 	if (!conf) {
514dd4f32aeSBjoern A. Zeeb 		rcu_read_unlock();
515dd4f32aeSBjoern A. Zeeb 		return -ENOENT;
516dd4f32aeSBjoern A. Zeeb 	}
517dd4f32aeSBjoern A. Zeeb 
518dd4f32aeSBjoern A. Zeeb 	*def = conf->def;
519dd4f32aeSBjoern A. Zeeb 	rcu_read_unlock();
520dd4f32aeSBjoern A. Zeeb 
521dd4f32aeSBjoern A. Zeeb 	return 0;
522dd4f32aeSBjoern A. Zeeb }
523dd4f32aeSBjoern A. Zeeb 
ath11k_mac_bitrate_is_cck(int bitrate)524dd4f32aeSBjoern A. Zeeb static bool ath11k_mac_bitrate_is_cck(int bitrate)
525dd4f32aeSBjoern A. Zeeb {
526dd4f32aeSBjoern A. Zeeb 	switch (bitrate) {
527dd4f32aeSBjoern A. Zeeb 	case 10:
528dd4f32aeSBjoern A. Zeeb 	case 20:
529dd4f32aeSBjoern A. Zeeb 	case 55:
530dd4f32aeSBjoern A. Zeeb 	case 110:
531dd4f32aeSBjoern A. Zeeb 		return true;
532dd4f32aeSBjoern A. Zeeb 	}
533dd4f32aeSBjoern A. Zeeb 
534dd4f32aeSBjoern A. Zeeb 	return false;
535dd4f32aeSBjoern A. Zeeb }
536dd4f32aeSBjoern A. Zeeb 
ath11k_mac_hw_rate_to_idx(const struct ieee80211_supported_band * sband,u8 hw_rate,bool cck)537dd4f32aeSBjoern A. Zeeb u8 ath11k_mac_hw_rate_to_idx(const struct ieee80211_supported_band *sband,
538dd4f32aeSBjoern A. Zeeb 			     u8 hw_rate, bool cck)
539dd4f32aeSBjoern A. Zeeb {
540dd4f32aeSBjoern A. Zeeb 	const struct ieee80211_rate *rate;
541dd4f32aeSBjoern A. Zeeb 	int i;
542dd4f32aeSBjoern A. Zeeb 
543dd4f32aeSBjoern A. Zeeb 	for (i = 0; i < sband->n_bitrates; i++) {
544dd4f32aeSBjoern A. Zeeb 		rate = &sband->bitrates[i];
545dd4f32aeSBjoern A. Zeeb 
546dd4f32aeSBjoern A. Zeeb 		if (ath11k_mac_bitrate_is_cck(rate->bitrate) != cck)
547dd4f32aeSBjoern A. Zeeb 			continue;
548dd4f32aeSBjoern A. Zeeb 
549dd4f32aeSBjoern A. Zeeb 		if (rate->hw_value == hw_rate)
550dd4f32aeSBjoern A. Zeeb 			return i;
551dd4f32aeSBjoern A. Zeeb 		else if (rate->flags & IEEE80211_RATE_SHORT_PREAMBLE &&
552dd4f32aeSBjoern A. Zeeb 			 rate->hw_value_short == hw_rate)
553dd4f32aeSBjoern A. Zeeb 			return i;
554dd4f32aeSBjoern A. Zeeb 	}
555dd4f32aeSBjoern A. Zeeb 
556dd4f32aeSBjoern A. Zeeb 	return 0;
557dd4f32aeSBjoern A. Zeeb }
558dd4f32aeSBjoern A. Zeeb 
ath11k_mac_bitrate_to_rate(int bitrate)559dd4f32aeSBjoern A. Zeeb static u8 ath11k_mac_bitrate_to_rate(int bitrate)
560dd4f32aeSBjoern A. Zeeb {
561dd4f32aeSBjoern A. Zeeb 	return DIV_ROUND_UP(bitrate, 5) |
562dd4f32aeSBjoern A. Zeeb 	       (ath11k_mac_bitrate_is_cck(bitrate) ? BIT(7) : 0);
563dd4f32aeSBjoern A. Zeeb }
564dd4f32aeSBjoern A. Zeeb 
ath11k_get_arvif_iter(void * data,u8 * mac,struct ieee80211_vif * vif)565dd4f32aeSBjoern A. Zeeb static void ath11k_get_arvif_iter(void *data, u8 *mac,
566dd4f32aeSBjoern A. Zeeb 				  struct ieee80211_vif *vif)
567dd4f32aeSBjoern A. Zeeb {
568dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif_iter *arvif_iter = data;
569dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif = (void *)vif->drv_priv;
570dd4f32aeSBjoern A. Zeeb 
571dd4f32aeSBjoern A. Zeeb 	if (arvif->vdev_id == arvif_iter->vdev_id)
572dd4f32aeSBjoern A. Zeeb 		arvif_iter->arvif = arvif;
573dd4f32aeSBjoern A. Zeeb }
574dd4f32aeSBjoern A. Zeeb 
ath11k_mac_get_arvif(struct ath11k * ar,u32 vdev_id)575dd4f32aeSBjoern A. Zeeb struct ath11k_vif *ath11k_mac_get_arvif(struct ath11k *ar, u32 vdev_id)
576dd4f32aeSBjoern A. Zeeb {
577dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif_iter arvif_iter;
578dd4f32aeSBjoern A. Zeeb 	u32 flags;
579dd4f32aeSBjoern A. Zeeb 
580dd4f32aeSBjoern A. Zeeb 	memset(&arvif_iter, 0, sizeof(struct ath11k_vif_iter));
581dd4f32aeSBjoern A. Zeeb 	arvif_iter.vdev_id = vdev_id;
582dd4f32aeSBjoern A. Zeeb 
583dd4f32aeSBjoern A. Zeeb 	flags = IEEE80211_IFACE_ITER_RESUME_ALL;
584dd4f32aeSBjoern A. Zeeb 	ieee80211_iterate_active_interfaces_atomic(ar->hw,
585dd4f32aeSBjoern A. Zeeb 						   flags,
586dd4f32aeSBjoern A. Zeeb 						   ath11k_get_arvif_iter,
587dd4f32aeSBjoern A. Zeeb 						   &arvif_iter);
588dd4f32aeSBjoern A. Zeeb 	if (!arvif_iter.arvif) {
589dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "No VIF found for vdev %d\n", vdev_id);
590dd4f32aeSBjoern A. Zeeb 		return NULL;
591dd4f32aeSBjoern A. Zeeb 	}
592dd4f32aeSBjoern A. Zeeb 
593dd4f32aeSBjoern A. Zeeb 	return arvif_iter.arvif;
594dd4f32aeSBjoern A. Zeeb }
595dd4f32aeSBjoern A. Zeeb 
ath11k_mac_get_arvif_by_vdev_id(struct ath11k_base * ab,u32 vdev_id)596dd4f32aeSBjoern A. Zeeb struct ath11k_vif *ath11k_mac_get_arvif_by_vdev_id(struct ath11k_base *ab,
597dd4f32aeSBjoern A. Zeeb 						   u32 vdev_id)
598dd4f32aeSBjoern A. Zeeb {
599dd4f32aeSBjoern A. Zeeb 	int i;
600dd4f32aeSBjoern A. Zeeb 	struct ath11k_pdev *pdev;
601dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif;
602dd4f32aeSBjoern A. Zeeb 
603dd4f32aeSBjoern A. Zeeb 	for (i = 0; i < ab->num_radios; i++) {
604dd4f32aeSBjoern A. Zeeb 		pdev = rcu_dereference(ab->pdevs_active[i]);
605dd4f32aeSBjoern A. Zeeb 		if (pdev && pdev->ar &&
606dd4f32aeSBjoern A. Zeeb 		    (pdev->ar->allocated_vdev_map & (1LL << vdev_id))) {
607dd4f32aeSBjoern A. Zeeb 			arvif = ath11k_mac_get_arvif(pdev->ar, vdev_id);
608dd4f32aeSBjoern A. Zeeb 			if (arvif)
609dd4f32aeSBjoern A. Zeeb 				return arvif;
610dd4f32aeSBjoern A. Zeeb 		}
611dd4f32aeSBjoern A. Zeeb 	}
612dd4f32aeSBjoern A. Zeeb 
613dd4f32aeSBjoern A. Zeeb 	return NULL;
614dd4f32aeSBjoern A. Zeeb }
615dd4f32aeSBjoern A. Zeeb 
ath11k_mac_get_ar_by_vdev_id(struct ath11k_base * ab,u32 vdev_id)616dd4f32aeSBjoern A. Zeeb struct ath11k *ath11k_mac_get_ar_by_vdev_id(struct ath11k_base *ab, u32 vdev_id)
617dd4f32aeSBjoern A. Zeeb {
618dd4f32aeSBjoern A. Zeeb 	int i;
619dd4f32aeSBjoern A. Zeeb 	struct ath11k_pdev *pdev;
620dd4f32aeSBjoern A. Zeeb 
621dd4f32aeSBjoern A. Zeeb 	for (i = 0; i < ab->num_radios; i++) {
622dd4f32aeSBjoern A. Zeeb 		pdev = rcu_dereference(ab->pdevs_active[i]);
623dd4f32aeSBjoern A. Zeeb 		if (pdev && pdev->ar) {
624dd4f32aeSBjoern A. Zeeb 			if (pdev->ar->allocated_vdev_map & (1LL << vdev_id))
625dd4f32aeSBjoern A. Zeeb 				return pdev->ar;
626dd4f32aeSBjoern A. Zeeb 		}
627dd4f32aeSBjoern A. Zeeb 	}
628dd4f32aeSBjoern A. Zeeb 
629dd4f32aeSBjoern A. Zeeb 	return NULL;
630dd4f32aeSBjoern A. Zeeb }
631dd4f32aeSBjoern A. Zeeb 
ath11k_mac_get_ar_by_pdev_id(struct ath11k_base * ab,u32 pdev_id)632dd4f32aeSBjoern A. Zeeb struct ath11k *ath11k_mac_get_ar_by_pdev_id(struct ath11k_base *ab, u32 pdev_id)
633dd4f32aeSBjoern A. Zeeb {
634dd4f32aeSBjoern A. Zeeb 	int i;
635dd4f32aeSBjoern A. Zeeb 	struct ath11k_pdev *pdev;
636dd4f32aeSBjoern A. Zeeb 
637dd4f32aeSBjoern A. Zeeb 	if (ab->hw_params.single_pdev_only) {
638dd4f32aeSBjoern A. Zeeb 		pdev = rcu_dereference(ab->pdevs_active[0]);
639dd4f32aeSBjoern A. Zeeb 		return pdev ? pdev->ar : NULL;
640dd4f32aeSBjoern A. Zeeb 	}
641dd4f32aeSBjoern A. Zeeb 
642dd4f32aeSBjoern A. Zeeb 	if (WARN_ON(pdev_id > ab->num_radios))
643dd4f32aeSBjoern A. Zeeb 		return NULL;
644dd4f32aeSBjoern A. Zeeb 
645dd4f32aeSBjoern A. Zeeb 	for (i = 0; i < ab->num_radios; i++) {
646*28348caeSBjoern A. Zeeb 		if (ab->fw_mode == ATH11K_FIRMWARE_MODE_FTM)
647*28348caeSBjoern A. Zeeb 			pdev = &ab->pdevs[i];
648*28348caeSBjoern A. Zeeb 		else
649dd4f32aeSBjoern A. Zeeb 			pdev = rcu_dereference(ab->pdevs_active[i]);
650dd4f32aeSBjoern A. Zeeb 
651dd4f32aeSBjoern A. Zeeb 		if (pdev && pdev->pdev_id == pdev_id)
652dd4f32aeSBjoern A. Zeeb 			return (pdev->ar ? pdev->ar : NULL);
653dd4f32aeSBjoern A. Zeeb 	}
654dd4f32aeSBjoern A. Zeeb 
655dd4f32aeSBjoern A. Zeeb 	return NULL;
656dd4f32aeSBjoern A. Zeeb }
657dd4f32aeSBjoern A. Zeeb 
ath11k_mac_get_vif_up(struct ath11k_base * ab)658dd4f32aeSBjoern A. Zeeb struct ath11k_vif *ath11k_mac_get_vif_up(struct ath11k_base *ab)
659dd4f32aeSBjoern A. Zeeb {
660dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar;
661dd4f32aeSBjoern A. Zeeb 	struct ath11k_pdev *pdev;
662dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif;
663dd4f32aeSBjoern A. Zeeb 	int i;
664dd4f32aeSBjoern A. Zeeb 
665dd4f32aeSBjoern A. Zeeb 	for (i = 0; i < ab->num_radios; i++) {
666dd4f32aeSBjoern A. Zeeb 		pdev = &ab->pdevs[i];
667dd4f32aeSBjoern A. Zeeb 		ar = pdev->ar;
668dd4f32aeSBjoern A. Zeeb 		list_for_each_entry(arvif, &ar->arvifs, list) {
669dd4f32aeSBjoern A. Zeeb 			if (arvif->is_up)
670dd4f32aeSBjoern A. Zeeb 				return arvif;
671dd4f32aeSBjoern A. Zeeb 		}
672dd4f32aeSBjoern A. Zeeb 	}
673dd4f32aeSBjoern A. Zeeb 
674dd4f32aeSBjoern A. Zeeb 	return NULL;
675dd4f32aeSBjoern A. Zeeb }
676dd4f32aeSBjoern A. Zeeb 
ath11k_mac_band_match(enum nl80211_band band1,enum WMI_HOST_WLAN_BAND band2)677dd4f32aeSBjoern A. Zeeb static bool ath11k_mac_band_match(enum nl80211_band band1, enum WMI_HOST_WLAN_BAND band2)
678dd4f32aeSBjoern A. Zeeb {
679dd4f32aeSBjoern A. Zeeb 	return (((band1 == NL80211_BAND_2GHZ) && (band2 & WMI_HOST_WLAN_2G_CAP)) ||
680dd4f32aeSBjoern A. Zeeb 		(((band1 == NL80211_BAND_5GHZ) || (band1 == NL80211_BAND_6GHZ)) &&
681dd4f32aeSBjoern A. Zeeb 		   (band2 & WMI_HOST_WLAN_5G_CAP)));
682dd4f32aeSBjoern A. Zeeb }
683dd4f32aeSBjoern A. Zeeb 
ath11k_mac_get_target_pdev_id_from_vif(struct ath11k_vif * arvif)684dd4f32aeSBjoern A. Zeeb u8 ath11k_mac_get_target_pdev_id_from_vif(struct ath11k_vif *arvif)
685dd4f32aeSBjoern A. Zeeb {
686dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = arvif->ar;
687dd4f32aeSBjoern A. Zeeb 	struct ath11k_base *ab = ar->ab;
688dd4f32aeSBjoern A. Zeeb 	struct ieee80211_vif *vif = arvif->vif;
689dd4f32aeSBjoern A. Zeeb 	struct cfg80211_chan_def def;
690dd4f32aeSBjoern A. Zeeb 	enum nl80211_band band;
691dd4f32aeSBjoern A. Zeeb 	u8 pdev_id = ab->target_pdev_ids[0].pdev_id;
692dd4f32aeSBjoern A. Zeeb 	int i;
693dd4f32aeSBjoern A. Zeeb 
694dd4f32aeSBjoern A. Zeeb 	if (WARN_ON(ath11k_mac_vif_chan(vif, &def)))
695dd4f32aeSBjoern A. Zeeb 		return pdev_id;
696dd4f32aeSBjoern A. Zeeb 
697dd4f32aeSBjoern A. Zeeb 	band = def.chan->band;
698dd4f32aeSBjoern A. Zeeb 
699dd4f32aeSBjoern A. Zeeb 	for (i = 0; i < ab->target_pdev_count; i++) {
700dd4f32aeSBjoern A. Zeeb 		if (ath11k_mac_band_match(band, ab->target_pdev_ids[i].supported_bands))
701dd4f32aeSBjoern A. Zeeb 			return ab->target_pdev_ids[i].pdev_id;
702dd4f32aeSBjoern A. Zeeb 	}
703dd4f32aeSBjoern A. Zeeb 
704dd4f32aeSBjoern A. Zeeb 	return pdev_id;
705dd4f32aeSBjoern A. Zeeb }
706dd4f32aeSBjoern A. Zeeb 
ath11k_mac_get_target_pdev_id(struct ath11k * ar)707dd4f32aeSBjoern A. Zeeb u8 ath11k_mac_get_target_pdev_id(struct ath11k *ar)
708dd4f32aeSBjoern A. Zeeb {
709dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif;
710dd4f32aeSBjoern A. Zeeb 
711dd4f32aeSBjoern A. Zeeb 	arvif = ath11k_mac_get_vif_up(ar->ab);
712dd4f32aeSBjoern A. Zeeb 
713dd4f32aeSBjoern A. Zeeb 	if (arvif)
714dd4f32aeSBjoern A. Zeeb 		return ath11k_mac_get_target_pdev_id_from_vif(arvif);
715dd4f32aeSBjoern A. Zeeb 	else
716dd4f32aeSBjoern A. Zeeb 		return ar->ab->target_pdev_ids[0].pdev_id;
717dd4f32aeSBjoern A. Zeeb }
718dd4f32aeSBjoern A. Zeeb 
ath11k_pdev_caps_update(struct ath11k * ar)719dd4f32aeSBjoern A. Zeeb static void ath11k_pdev_caps_update(struct ath11k *ar)
720dd4f32aeSBjoern A. Zeeb {
721dd4f32aeSBjoern A. Zeeb 	struct ath11k_base *ab = ar->ab;
722dd4f32aeSBjoern A. Zeeb 
723dd4f32aeSBjoern A. Zeeb 	ar->max_tx_power = ab->target_caps.hw_max_tx_power;
724dd4f32aeSBjoern A. Zeeb 
725dd4f32aeSBjoern A. Zeeb 	/* FIXME Set min_tx_power to ab->target_caps.hw_min_tx_power.
726dd4f32aeSBjoern A. Zeeb 	 * But since the received value in svcrdy is same as hw_max_tx_power,
727dd4f32aeSBjoern A. Zeeb 	 * we can set ar->min_tx_power to 0 currently until
728dd4f32aeSBjoern A. Zeeb 	 * this is fixed in firmware
729dd4f32aeSBjoern A. Zeeb 	 */
730dd4f32aeSBjoern A. Zeeb 	ar->min_tx_power = 0;
731dd4f32aeSBjoern A. Zeeb 
732dd4f32aeSBjoern A. Zeeb 	ar->txpower_limit_2g = ar->max_tx_power;
733dd4f32aeSBjoern A. Zeeb 	ar->txpower_limit_5g = ar->max_tx_power;
734dd4f32aeSBjoern A. Zeeb 	ar->txpower_scale = WMI_HOST_TP_SCALE_MAX;
735dd4f32aeSBjoern A. Zeeb }
736dd4f32aeSBjoern A. Zeeb 
ath11k_mac_txpower_recalc(struct ath11k * ar)737dd4f32aeSBjoern A. Zeeb static int ath11k_mac_txpower_recalc(struct ath11k *ar)
738dd4f32aeSBjoern A. Zeeb {
739dd4f32aeSBjoern A. Zeeb 	struct ath11k_pdev *pdev = ar->pdev;
740dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif;
741dd4f32aeSBjoern A. Zeeb 	int ret, txpower = -1;
742dd4f32aeSBjoern A. Zeeb 	u32 param;
743dd4f32aeSBjoern A. Zeeb 
744dd4f32aeSBjoern A. Zeeb 	lockdep_assert_held(&ar->conf_mutex);
745dd4f32aeSBjoern A. Zeeb 
746dd4f32aeSBjoern A. Zeeb 	list_for_each_entry(arvif, &ar->arvifs, list) {
747dd4f32aeSBjoern A. Zeeb 		if (arvif->txpower <= 0)
748dd4f32aeSBjoern A. Zeeb 			continue;
749dd4f32aeSBjoern A. Zeeb 
750dd4f32aeSBjoern A. Zeeb 		if (txpower == -1)
751dd4f32aeSBjoern A. Zeeb 			txpower = arvif->txpower;
752dd4f32aeSBjoern A. Zeeb 		else
753dd4f32aeSBjoern A. Zeeb 			txpower = min(txpower, arvif->txpower);
754dd4f32aeSBjoern A. Zeeb 	}
755dd4f32aeSBjoern A. Zeeb 
756dd4f32aeSBjoern A. Zeeb 	if (txpower == -1)
757dd4f32aeSBjoern A. Zeeb 		return 0;
758dd4f32aeSBjoern A. Zeeb 
759dd4f32aeSBjoern A. Zeeb 	/* txpwr is set as 2 units per dBm in FW*/
760dd4f32aeSBjoern A. Zeeb 	txpower = min_t(u32, max_t(u32, ar->min_tx_power, txpower),
761dd4f32aeSBjoern A. Zeeb 			ar->max_tx_power) * 2;
762dd4f32aeSBjoern A. Zeeb 
763dd4f32aeSBjoern A. Zeeb 	ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "txpower to set in hw %d\n",
764dd4f32aeSBjoern A. Zeeb 		   txpower / 2);
765dd4f32aeSBjoern A. Zeeb 
766dd4f32aeSBjoern A. Zeeb 	if ((pdev->cap.supported_bands & WMI_HOST_WLAN_2G_CAP) &&
767dd4f32aeSBjoern A. Zeeb 	    ar->txpower_limit_2g != txpower) {
768dd4f32aeSBjoern A. Zeeb 		param = WMI_PDEV_PARAM_TXPOWER_LIMIT2G;
769dd4f32aeSBjoern A. Zeeb 		ret = ath11k_wmi_pdev_set_param(ar, param,
770dd4f32aeSBjoern A. Zeeb 						txpower, ar->pdev->pdev_id);
771dd4f32aeSBjoern A. Zeeb 		if (ret)
772dd4f32aeSBjoern A. Zeeb 			goto fail;
773dd4f32aeSBjoern A. Zeeb 		ar->txpower_limit_2g = txpower;
774dd4f32aeSBjoern A. Zeeb 	}
775dd4f32aeSBjoern A. Zeeb 
776dd4f32aeSBjoern A. Zeeb 	if ((pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP) &&
777dd4f32aeSBjoern A. Zeeb 	    ar->txpower_limit_5g != txpower) {
778dd4f32aeSBjoern A. Zeeb 		param = WMI_PDEV_PARAM_TXPOWER_LIMIT5G;
779dd4f32aeSBjoern A. Zeeb 		ret = ath11k_wmi_pdev_set_param(ar, param,
780dd4f32aeSBjoern A. Zeeb 						txpower, ar->pdev->pdev_id);
781dd4f32aeSBjoern A. Zeeb 		if (ret)
782dd4f32aeSBjoern A. Zeeb 			goto fail;
783dd4f32aeSBjoern A. Zeeb 		ar->txpower_limit_5g = txpower;
784dd4f32aeSBjoern A. Zeeb 	}
785dd4f32aeSBjoern A. Zeeb 
786dd4f32aeSBjoern A. Zeeb 	return 0;
787dd4f32aeSBjoern A. Zeeb 
788dd4f32aeSBjoern A. Zeeb fail:
789dd4f32aeSBjoern A. Zeeb 	ath11k_warn(ar->ab, "failed to recalc txpower limit %d using pdev param %d: %d\n",
790dd4f32aeSBjoern A. Zeeb 		    txpower / 2, param, ret);
791dd4f32aeSBjoern A. Zeeb 	return ret;
792dd4f32aeSBjoern A. Zeeb }
793dd4f32aeSBjoern A. Zeeb 
ath11k_recalc_rtscts_prot(struct ath11k_vif * arvif)794dd4f32aeSBjoern A. Zeeb static int ath11k_recalc_rtscts_prot(struct ath11k_vif *arvif)
795dd4f32aeSBjoern A. Zeeb {
796dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = arvif->ar;
797dd4f32aeSBjoern A. Zeeb 	u32 vdev_param, rts_cts = 0;
798dd4f32aeSBjoern A. Zeeb 	int ret;
799dd4f32aeSBjoern A. Zeeb 
800dd4f32aeSBjoern A. Zeeb 	lockdep_assert_held(&ar->conf_mutex);
801dd4f32aeSBjoern A. Zeeb 
802dd4f32aeSBjoern A. Zeeb 	vdev_param = WMI_VDEV_PARAM_ENABLE_RTSCTS;
803dd4f32aeSBjoern A. Zeeb 
804dd4f32aeSBjoern A. Zeeb 	/* Enable RTS/CTS protection for sw retries (when legacy stations
805dd4f32aeSBjoern A. Zeeb 	 * are in BSS) or by default only for second rate series.
806dd4f32aeSBjoern A. Zeeb 	 * TODO: Check if we need to enable CTS 2 Self in any case
807dd4f32aeSBjoern A. Zeeb 	 */
808dd4f32aeSBjoern A. Zeeb 	rts_cts = WMI_USE_RTS_CTS;
809dd4f32aeSBjoern A. Zeeb 
810dd4f32aeSBjoern A. Zeeb 	if (arvif->num_legacy_stations > 0)
811dd4f32aeSBjoern A. Zeeb 		rts_cts |= WMI_RTSCTS_ACROSS_SW_RETRIES << 4;
812dd4f32aeSBjoern A. Zeeb 	else
813dd4f32aeSBjoern A. Zeeb 		rts_cts |= WMI_RTSCTS_FOR_SECOND_RATESERIES << 4;
814dd4f32aeSBjoern A. Zeeb 
815dd4f32aeSBjoern A. Zeeb 	/* Need not send duplicate param value to firmware */
816dd4f32aeSBjoern A. Zeeb 	if (arvif->rtscts_prot_mode == rts_cts)
817dd4f32aeSBjoern A. Zeeb 		return 0;
818dd4f32aeSBjoern A. Zeeb 
819dd4f32aeSBjoern A. Zeeb 	arvif->rtscts_prot_mode = rts_cts;
820dd4f32aeSBjoern A. Zeeb 
821*28348caeSBjoern A. Zeeb 	ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev %d recalc rts/cts prot %d\n",
822dd4f32aeSBjoern A. Zeeb 		   arvif->vdev_id, rts_cts);
823dd4f32aeSBjoern A. Zeeb 
824dd4f32aeSBjoern A. Zeeb 	ret =  ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
825dd4f32aeSBjoern A. Zeeb 					     vdev_param, rts_cts);
826dd4f32aeSBjoern A. Zeeb 	if (ret)
827dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to recalculate rts/cts prot for vdev %d: %d\n",
828dd4f32aeSBjoern A. Zeeb 			    arvif->vdev_id, ret);
829dd4f32aeSBjoern A. Zeeb 
830dd4f32aeSBjoern A. Zeeb 	return ret;
831dd4f32aeSBjoern A. Zeeb }
832dd4f32aeSBjoern A. Zeeb 
ath11k_mac_set_kickout(struct ath11k_vif * arvif)833dd4f32aeSBjoern A. Zeeb static int ath11k_mac_set_kickout(struct ath11k_vif *arvif)
834dd4f32aeSBjoern A. Zeeb {
835dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = arvif->ar;
836dd4f32aeSBjoern A. Zeeb 	u32 param;
837dd4f32aeSBjoern A. Zeeb 	int ret;
838dd4f32aeSBjoern A. Zeeb 
839dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_STA_KICKOUT_TH,
840dd4f32aeSBjoern A. Zeeb 					ATH11K_KICKOUT_THRESHOLD,
841dd4f32aeSBjoern A. Zeeb 					ar->pdev->pdev_id);
842dd4f32aeSBjoern A. Zeeb 	if (ret) {
843dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to set kickout threshold on vdev %i: %d\n",
844dd4f32aeSBjoern A. Zeeb 			    arvif->vdev_id, ret);
845dd4f32aeSBjoern A. Zeeb 		return ret;
846dd4f32aeSBjoern A. Zeeb 	}
847dd4f32aeSBjoern A. Zeeb 
848dd4f32aeSBjoern A. Zeeb 	param = WMI_VDEV_PARAM_AP_KEEPALIVE_MIN_IDLE_INACTIVE_TIME_SECS;
849dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, param,
850dd4f32aeSBjoern A. Zeeb 					    ATH11K_KEEPALIVE_MIN_IDLE);
851dd4f32aeSBjoern A. Zeeb 	if (ret) {
852dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to set keepalive minimum idle time on vdev %i: %d\n",
853dd4f32aeSBjoern A. Zeeb 			    arvif->vdev_id, ret);
854dd4f32aeSBjoern A. Zeeb 		return ret;
855dd4f32aeSBjoern A. Zeeb 	}
856dd4f32aeSBjoern A. Zeeb 
857dd4f32aeSBjoern A. Zeeb 	param = WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_IDLE_INACTIVE_TIME_SECS;
858dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, param,
859dd4f32aeSBjoern A. Zeeb 					    ATH11K_KEEPALIVE_MAX_IDLE);
860dd4f32aeSBjoern A. Zeeb 	if (ret) {
861dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to set keepalive maximum idle time on vdev %i: %d\n",
862dd4f32aeSBjoern A. Zeeb 			    arvif->vdev_id, ret);
863dd4f32aeSBjoern A. Zeeb 		return ret;
864dd4f32aeSBjoern A. Zeeb 	}
865dd4f32aeSBjoern A. Zeeb 
866dd4f32aeSBjoern A. Zeeb 	param = WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS;
867dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, param,
868dd4f32aeSBjoern A. Zeeb 					    ATH11K_KEEPALIVE_MAX_UNRESPONSIVE);
869dd4f32aeSBjoern A. Zeeb 	if (ret) {
870dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to set keepalive maximum unresponsive time on vdev %i: %d\n",
871dd4f32aeSBjoern A. Zeeb 			    arvif->vdev_id, ret);
872dd4f32aeSBjoern A. Zeeb 		return ret;
873dd4f32aeSBjoern A. Zeeb 	}
874dd4f32aeSBjoern A. Zeeb 
875dd4f32aeSBjoern A. Zeeb 	return 0;
876dd4f32aeSBjoern A. Zeeb }
877dd4f32aeSBjoern A. Zeeb 
ath11k_mac_peer_cleanup_all(struct ath11k * ar)878dd4f32aeSBjoern A. Zeeb void ath11k_mac_peer_cleanup_all(struct ath11k *ar)
879dd4f32aeSBjoern A. Zeeb {
880dd4f32aeSBjoern A. Zeeb 	struct ath11k_peer *peer, *tmp;
881dd4f32aeSBjoern A. Zeeb 	struct ath11k_base *ab = ar->ab;
882dd4f32aeSBjoern A. Zeeb 
883dd4f32aeSBjoern A. Zeeb 	lockdep_assert_held(&ar->conf_mutex);
884dd4f32aeSBjoern A. Zeeb 
885*28348caeSBjoern A. Zeeb 	mutex_lock(&ab->tbl_mtx_lock);
886dd4f32aeSBjoern A. Zeeb 	spin_lock_bh(&ab->base_lock);
887dd4f32aeSBjoern A. Zeeb 	list_for_each_entry_safe(peer, tmp, &ab->peers, list) {
888dd4f32aeSBjoern A. Zeeb 		ath11k_peer_rx_tid_cleanup(ar, peer);
889*28348caeSBjoern A. Zeeb 		ath11k_peer_rhash_delete(ab, peer);
890dd4f32aeSBjoern A. Zeeb 		list_del(&peer->list);
891dd4f32aeSBjoern A. Zeeb 		kfree(peer);
892dd4f32aeSBjoern A. Zeeb 	}
893dd4f32aeSBjoern A. Zeeb 	spin_unlock_bh(&ab->base_lock);
894*28348caeSBjoern A. Zeeb 	mutex_unlock(&ab->tbl_mtx_lock);
895dd4f32aeSBjoern A. Zeeb 
896dd4f32aeSBjoern A. Zeeb 	ar->num_peers = 0;
897dd4f32aeSBjoern A. Zeeb 	ar->num_stations = 0;
898dd4f32aeSBjoern A. Zeeb }
899dd4f32aeSBjoern A. Zeeb 
ath11k_mac_vdev_setup_sync(struct ath11k * ar)900dd4f32aeSBjoern A. Zeeb static inline int ath11k_mac_vdev_setup_sync(struct ath11k *ar)
901dd4f32aeSBjoern A. Zeeb {
902dd4f32aeSBjoern A. Zeeb 	lockdep_assert_held(&ar->conf_mutex);
903dd4f32aeSBjoern A. Zeeb 
904dd4f32aeSBjoern A. Zeeb 	if (test_bit(ATH11K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))
905dd4f32aeSBjoern A. Zeeb 		return -ESHUTDOWN;
906dd4f32aeSBjoern A. Zeeb 
907dd4f32aeSBjoern A. Zeeb 	if (!wait_for_completion_timeout(&ar->vdev_setup_done,
908dd4f32aeSBjoern A. Zeeb 					 ATH11K_VDEV_SETUP_TIMEOUT_HZ))
909dd4f32aeSBjoern A. Zeeb 		return -ETIMEDOUT;
910dd4f32aeSBjoern A. Zeeb 
911dd4f32aeSBjoern A. Zeeb 	return ar->last_wmi_vdev_start_status ? -EINVAL : 0;
912dd4f32aeSBjoern A. Zeeb }
913dd4f32aeSBjoern A. Zeeb 
914dd4f32aeSBjoern A. Zeeb static void
ath11k_mac_get_any_chandef_iter(struct ieee80211_hw * hw,struct ieee80211_chanctx_conf * conf,void * data)915dd4f32aeSBjoern A. Zeeb ath11k_mac_get_any_chandef_iter(struct ieee80211_hw *hw,
916dd4f32aeSBjoern A. Zeeb 				struct ieee80211_chanctx_conf *conf,
917dd4f32aeSBjoern A. Zeeb 				void *data)
918dd4f32aeSBjoern A. Zeeb {
919dd4f32aeSBjoern A. Zeeb 	struct cfg80211_chan_def **def = data;
920dd4f32aeSBjoern A. Zeeb 
921dd4f32aeSBjoern A. Zeeb 	*def = &conf->def;
922dd4f32aeSBjoern A. Zeeb }
923dd4f32aeSBjoern A. Zeeb 
ath11k_mac_monitor_vdev_start(struct ath11k * ar,int vdev_id,struct cfg80211_chan_def * chandef)924dd4f32aeSBjoern A. Zeeb static int ath11k_mac_monitor_vdev_start(struct ath11k *ar, int vdev_id,
925dd4f32aeSBjoern A. Zeeb 					 struct cfg80211_chan_def *chandef)
926dd4f32aeSBjoern A. Zeeb {
927dd4f32aeSBjoern A. Zeeb 	struct ieee80211_channel *channel;
928dd4f32aeSBjoern A. Zeeb 	struct wmi_vdev_start_req_arg arg = {};
929dd4f32aeSBjoern A. Zeeb 	int ret;
930dd4f32aeSBjoern A. Zeeb 
931dd4f32aeSBjoern A. Zeeb 	lockdep_assert_held(&ar->conf_mutex);
932dd4f32aeSBjoern A. Zeeb 
933dd4f32aeSBjoern A. Zeeb 	channel = chandef->chan;
934dd4f32aeSBjoern A. Zeeb 
935dd4f32aeSBjoern A. Zeeb 	arg.vdev_id = vdev_id;
936dd4f32aeSBjoern A. Zeeb 	arg.channel.freq = channel->center_freq;
937dd4f32aeSBjoern A. Zeeb 	arg.channel.band_center_freq1 = chandef->center_freq1;
938dd4f32aeSBjoern A. Zeeb 	arg.channel.band_center_freq2 = chandef->center_freq2;
939dd4f32aeSBjoern A. Zeeb 
940dd4f32aeSBjoern A. Zeeb 	arg.channel.mode = ath11k_phymodes[chandef->chan->band][chandef->width];
941dd4f32aeSBjoern A. Zeeb 	arg.channel.chan_radar = !!(channel->flags & IEEE80211_CHAN_RADAR);
942dd4f32aeSBjoern A. Zeeb 
943dd4f32aeSBjoern A. Zeeb 	arg.channel.min_power = 0;
944dd4f32aeSBjoern A. Zeeb 	arg.channel.max_power = channel->max_power;
945dd4f32aeSBjoern A. Zeeb 	arg.channel.max_reg_power = channel->max_reg_power;
946dd4f32aeSBjoern A. Zeeb 	arg.channel.max_antenna_gain = channel->max_antenna_gain;
947dd4f32aeSBjoern A. Zeeb 
948dd4f32aeSBjoern A. Zeeb 	arg.pref_tx_streams = ar->num_tx_chains;
949dd4f32aeSBjoern A. Zeeb 	arg.pref_rx_streams = ar->num_rx_chains;
950dd4f32aeSBjoern A. Zeeb 
951dd4f32aeSBjoern A. Zeeb 	arg.channel.passive = !!(chandef->chan->flags & IEEE80211_CHAN_NO_IR);
952dd4f32aeSBjoern A. Zeeb 
953dd4f32aeSBjoern A. Zeeb 	reinit_completion(&ar->vdev_setup_done);
954dd4f32aeSBjoern A. Zeeb 	reinit_completion(&ar->vdev_delete_done);
955dd4f32aeSBjoern A. Zeeb 
956dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_vdev_start(ar, &arg, false);
957dd4f32aeSBjoern A. Zeeb 	if (ret) {
958dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to request monitor vdev %i start: %d\n",
959dd4f32aeSBjoern A. Zeeb 			    vdev_id, ret);
960dd4f32aeSBjoern A. Zeeb 		return ret;
961dd4f32aeSBjoern A. Zeeb 	}
962dd4f32aeSBjoern A. Zeeb 
963dd4f32aeSBjoern A. Zeeb 	ret = ath11k_mac_vdev_setup_sync(ar);
964dd4f32aeSBjoern A. Zeeb 	if (ret) {
965dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to synchronize setup for monitor vdev %i start: %d\n",
966dd4f32aeSBjoern A. Zeeb 			    vdev_id, ret);
967dd4f32aeSBjoern A. Zeeb 		return ret;
968dd4f32aeSBjoern A. Zeeb 	}
969dd4f32aeSBjoern A. Zeeb 
970*28348caeSBjoern A. Zeeb 	ret = ath11k_wmi_vdev_up(ar, vdev_id, 0, ar->mac_addr, NULL, 0, 0);
971dd4f32aeSBjoern A. Zeeb 	if (ret) {
972dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to put up monitor vdev %i: %d\n",
973dd4f32aeSBjoern A. Zeeb 			    vdev_id, ret);
974dd4f32aeSBjoern A. Zeeb 		goto vdev_stop;
975dd4f32aeSBjoern A. Zeeb 	}
976dd4f32aeSBjoern A. Zeeb 
977*28348caeSBjoern A. Zeeb 	ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "monitor vdev %i started\n",
978dd4f32aeSBjoern A. Zeeb 		   vdev_id);
979dd4f32aeSBjoern A. Zeeb 
980dd4f32aeSBjoern A. Zeeb 	return 0;
981dd4f32aeSBjoern A. Zeeb 
982dd4f32aeSBjoern A. Zeeb vdev_stop:
983dd4f32aeSBjoern A. Zeeb 	reinit_completion(&ar->vdev_setup_done);
984dd4f32aeSBjoern A. Zeeb 
985dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_vdev_stop(ar, vdev_id);
986dd4f32aeSBjoern A. Zeeb 	if (ret) {
987dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to stop monitor vdev %i after start failure: %d\n",
988dd4f32aeSBjoern A. Zeeb 			    vdev_id, ret);
989dd4f32aeSBjoern A. Zeeb 		return ret;
990dd4f32aeSBjoern A. Zeeb 	}
991dd4f32aeSBjoern A. Zeeb 
992dd4f32aeSBjoern A. Zeeb 	ret = ath11k_mac_vdev_setup_sync(ar);
993dd4f32aeSBjoern A. Zeeb 	if (ret) {
994dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to synchronize setup for vdev %i stop: %d\n",
995dd4f32aeSBjoern A. Zeeb 			    vdev_id, ret);
996dd4f32aeSBjoern A. Zeeb 		return ret;
997dd4f32aeSBjoern A. Zeeb 	}
998dd4f32aeSBjoern A. Zeeb 
999dd4f32aeSBjoern A. Zeeb 	return -EIO;
1000dd4f32aeSBjoern A. Zeeb }
1001dd4f32aeSBjoern A. Zeeb 
ath11k_mac_monitor_vdev_stop(struct ath11k * ar)1002dd4f32aeSBjoern A. Zeeb static int ath11k_mac_monitor_vdev_stop(struct ath11k *ar)
1003dd4f32aeSBjoern A. Zeeb {
1004dd4f32aeSBjoern A. Zeeb 	int ret;
1005dd4f32aeSBjoern A. Zeeb 
1006dd4f32aeSBjoern A. Zeeb 	lockdep_assert_held(&ar->conf_mutex);
1007dd4f32aeSBjoern A. Zeeb 
1008dd4f32aeSBjoern A. Zeeb 	reinit_completion(&ar->vdev_setup_done);
1009dd4f32aeSBjoern A. Zeeb 
1010dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_vdev_stop(ar, ar->monitor_vdev_id);
1011dd4f32aeSBjoern A. Zeeb 	if (ret) {
1012dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to request monitor vdev %i stop: %d\n",
1013dd4f32aeSBjoern A. Zeeb 			    ar->monitor_vdev_id, ret);
1014dd4f32aeSBjoern A. Zeeb 		return ret;
1015dd4f32aeSBjoern A. Zeeb 	}
1016dd4f32aeSBjoern A. Zeeb 
1017dd4f32aeSBjoern A. Zeeb 	ret = ath11k_mac_vdev_setup_sync(ar);
1018dd4f32aeSBjoern A. Zeeb 	if (ret) {
1019dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to synchronize monitor vdev %i stop: %d\n",
1020dd4f32aeSBjoern A. Zeeb 			    ar->monitor_vdev_id, ret);
1021dd4f32aeSBjoern A. Zeeb 		return ret;
1022dd4f32aeSBjoern A. Zeeb 	}
1023dd4f32aeSBjoern A. Zeeb 
1024dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_vdev_down(ar, ar->monitor_vdev_id);
1025dd4f32aeSBjoern A. Zeeb 	if (ret) {
1026dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to put down monitor vdev %i: %d\n",
1027dd4f32aeSBjoern A. Zeeb 			    ar->monitor_vdev_id, ret);
1028dd4f32aeSBjoern A. Zeeb 		return ret;
1029dd4f32aeSBjoern A. Zeeb 	}
1030dd4f32aeSBjoern A. Zeeb 
1031*28348caeSBjoern A. Zeeb 	ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "monitor vdev %i stopped\n",
1032dd4f32aeSBjoern A. Zeeb 		   ar->monitor_vdev_id);
1033dd4f32aeSBjoern A. Zeeb 
1034dd4f32aeSBjoern A. Zeeb 	return 0;
1035dd4f32aeSBjoern A. Zeeb }
1036dd4f32aeSBjoern A. Zeeb 
ath11k_mac_monitor_vdev_create(struct ath11k * ar)1037dd4f32aeSBjoern A. Zeeb static int ath11k_mac_monitor_vdev_create(struct ath11k *ar)
1038dd4f32aeSBjoern A. Zeeb {
1039dd4f32aeSBjoern A. Zeeb 	struct ath11k_pdev *pdev = ar->pdev;
1040dd4f32aeSBjoern A. Zeeb 	struct vdev_create_params param = {};
1041dd4f32aeSBjoern A. Zeeb 	int bit, ret;
1042dd4f32aeSBjoern A. Zeeb 	u8 tmp_addr[6] = {0};
1043dd4f32aeSBjoern A. Zeeb 	u16 nss;
1044dd4f32aeSBjoern A. Zeeb 
1045dd4f32aeSBjoern A. Zeeb 	lockdep_assert_held(&ar->conf_mutex);
1046dd4f32aeSBjoern A. Zeeb 
1047dd4f32aeSBjoern A. Zeeb 	if (test_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags))
1048dd4f32aeSBjoern A. Zeeb 		return 0;
1049dd4f32aeSBjoern A. Zeeb 
1050dd4f32aeSBjoern A. Zeeb 	if (ar->ab->free_vdev_map == 0) {
1051dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to find free vdev id for monitor vdev\n");
1052dd4f32aeSBjoern A. Zeeb 		return -ENOMEM;
1053dd4f32aeSBjoern A. Zeeb 	}
1054dd4f32aeSBjoern A. Zeeb 
1055dd4f32aeSBjoern A. Zeeb 	bit = __ffs64(ar->ab->free_vdev_map);
1056dd4f32aeSBjoern A. Zeeb 
1057dd4f32aeSBjoern A. Zeeb 	ar->monitor_vdev_id = bit;
1058dd4f32aeSBjoern A. Zeeb 
1059dd4f32aeSBjoern A. Zeeb 	param.if_id = ar->monitor_vdev_id;
1060dd4f32aeSBjoern A. Zeeb 	param.type = WMI_VDEV_TYPE_MONITOR;
1061dd4f32aeSBjoern A. Zeeb 	param.subtype = WMI_VDEV_SUBTYPE_NONE;
1062dd4f32aeSBjoern A. Zeeb 	param.pdev_id = pdev->pdev_id;
1063dd4f32aeSBjoern A. Zeeb 
1064dd4f32aeSBjoern A. Zeeb 	if (pdev->cap.supported_bands & WMI_HOST_WLAN_2G_CAP) {
1065dd4f32aeSBjoern A. Zeeb 		param.chains[NL80211_BAND_2GHZ].tx = ar->num_tx_chains;
1066dd4f32aeSBjoern A. Zeeb 		param.chains[NL80211_BAND_2GHZ].rx = ar->num_rx_chains;
1067dd4f32aeSBjoern A. Zeeb 	}
1068dd4f32aeSBjoern A. Zeeb 	if (pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP) {
1069dd4f32aeSBjoern A. Zeeb 		param.chains[NL80211_BAND_5GHZ].tx = ar->num_tx_chains;
1070dd4f32aeSBjoern A. Zeeb 		param.chains[NL80211_BAND_5GHZ].rx = ar->num_rx_chains;
1071dd4f32aeSBjoern A. Zeeb 	}
1072dd4f32aeSBjoern A. Zeeb 
1073dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_vdev_create(ar, tmp_addr, &param);
1074dd4f32aeSBjoern A. Zeeb 	if (ret) {
1075dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to request monitor vdev %i creation: %d\n",
1076dd4f32aeSBjoern A. Zeeb 			    ar->monitor_vdev_id, ret);
1077dd4f32aeSBjoern A. Zeeb 		ar->monitor_vdev_id = -1;
1078dd4f32aeSBjoern A. Zeeb 		return ret;
1079dd4f32aeSBjoern A. Zeeb 	}
1080dd4f32aeSBjoern A. Zeeb 
1081dd4f32aeSBjoern A. Zeeb 	nss = get_num_chains(ar->cfg_tx_chainmask) ? : 1;
1082dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_vdev_set_param_cmd(ar, ar->monitor_vdev_id,
1083dd4f32aeSBjoern A. Zeeb 					    WMI_VDEV_PARAM_NSS, nss);
1084dd4f32aeSBjoern A. Zeeb 	if (ret) {
1085dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to set vdev %d chainmask 0x%x, nss %d :%d\n",
1086dd4f32aeSBjoern A. Zeeb 			    ar->monitor_vdev_id, ar->cfg_tx_chainmask, nss, ret);
1087dd4f32aeSBjoern A. Zeeb 		goto err_vdev_del;
1088dd4f32aeSBjoern A. Zeeb 	}
1089dd4f32aeSBjoern A. Zeeb 
1090dd4f32aeSBjoern A. Zeeb 	ret = ath11k_mac_txpower_recalc(ar);
1091dd4f32aeSBjoern A. Zeeb 	if (ret) {
1092dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to recalc txpower for monitor vdev %d: %d\n",
1093dd4f32aeSBjoern A. Zeeb 			    ar->monitor_vdev_id, ret);
1094dd4f32aeSBjoern A. Zeeb 		goto err_vdev_del;
1095dd4f32aeSBjoern A. Zeeb 	}
1096dd4f32aeSBjoern A. Zeeb 
1097dd4f32aeSBjoern A. Zeeb 	ar->allocated_vdev_map |= 1LL << ar->monitor_vdev_id;
1098dd4f32aeSBjoern A. Zeeb 	ar->ab->free_vdev_map &= ~(1LL << ar->monitor_vdev_id);
1099dd4f32aeSBjoern A. Zeeb 	ar->num_created_vdevs++;
1100dd4f32aeSBjoern A. Zeeb 	set_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags);
1101dd4f32aeSBjoern A. Zeeb 
1102*28348caeSBjoern A. Zeeb 	ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "monitor vdev %d created\n",
1103dd4f32aeSBjoern A. Zeeb 		   ar->monitor_vdev_id);
1104dd4f32aeSBjoern A. Zeeb 
1105dd4f32aeSBjoern A. Zeeb 	return 0;
1106dd4f32aeSBjoern A. Zeeb 
1107dd4f32aeSBjoern A. Zeeb err_vdev_del:
1108dd4f32aeSBjoern A. Zeeb 	ath11k_wmi_vdev_delete(ar, ar->monitor_vdev_id);
1109dd4f32aeSBjoern A. Zeeb 	ar->monitor_vdev_id = -1;
1110dd4f32aeSBjoern A. Zeeb 	return ret;
1111dd4f32aeSBjoern A. Zeeb }
1112dd4f32aeSBjoern A. Zeeb 
ath11k_mac_monitor_vdev_delete(struct ath11k * ar)1113dd4f32aeSBjoern A. Zeeb static int ath11k_mac_monitor_vdev_delete(struct ath11k *ar)
1114dd4f32aeSBjoern A. Zeeb {
1115dd4f32aeSBjoern A. Zeeb 	int ret;
1116dd4f32aeSBjoern A. Zeeb 	unsigned long time_left;
1117dd4f32aeSBjoern A. Zeeb 
1118dd4f32aeSBjoern A. Zeeb 	lockdep_assert_held(&ar->conf_mutex);
1119dd4f32aeSBjoern A. Zeeb 
1120dd4f32aeSBjoern A. Zeeb 	if (!test_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags))
1121dd4f32aeSBjoern A. Zeeb 		return 0;
1122dd4f32aeSBjoern A. Zeeb 
1123dd4f32aeSBjoern A. Zeeb 	reinit_completion(&ar->vdev_delete_done);
1124dd4f32aeSBjoern A. Zeeb 
1125dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_vdev_delete(ar, ar->monitor_vdev_id);
1126dd4f32aeSBjoern A. Zeeb 	if (ret) {
1127dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to request wmi monitor vdev %i removal: %d\n",
1128dd4f32aeSBjoern A. Zeeb 			    ar->monitor_vdev_id, ret);
1129dd4f32aeSBjoern A. Zeeb 		return ret;
1130dd4f32aeSBjoern A. Zeeb 	}
1131dd4f32aeSBjoern A. Zeeb 
1132dd4f32aeSBjoern A. Zeeb 	time_left = wait_for_completion_timeout(&ar->vdev_delete_done,
1133dd4f32aeSBjoern A. Zeeb 						ATH11K_VDEV_DELETE_TIMEOUT_HZ);
1134dd4f32aeSBjoern A. Zeeb 	if (time_left == 0) {
1135dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "Timeout in receiving vdev delete response\n");
1136dd4f32aeSBjoern A. Zeeb 	} else {
1137*28348caeSBjoern A. Zeeb 		ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "monitor vdev %d deleted\n",
1138dd4f32aeSBjoern A. Zeeb 			   ar->monitor_vdev_id);
1139dd4f32aeSBjoern A. Zeeb 
1140dd4f32aeSBjoern A. Zeeb 		ar->allocated_vdev_map &= ~(1LL << ar->monitor_vdev_id);
1141dd4f32aeSBjoern A. Zeeb 		ar->ab->free_vdev_map |= 1LL << (ar->monitor_vdev_id);
1142dd4f32aeSBjoern A. Zeeb 		ar->num_created_vdevs--;
1143dd4f32aeSBjoern A. Zeeb 		ar->monitor_vdev_id = -1;
1144dd4f32aeSBjoern A. Zeeb 		clear_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags);
1145dd4f32aeSBjoern A. Zeeb 	}
1146dd4f32aeSBjoern A. Zeeb 
1147dd4f32aeSBjoern A. Zeeb 	return ret;
1148dd4f32aeSBjoern A. Zeeb }
1149dd4f32aeSBjoern A. Zeeb 
ath11k_mac_monitor_start(struct ath11k * ar)1150dd4f32aeSBjoern A. Zeeb static int ath11k_mac_monitor_start(struct ath11k *ar)
1151dd4f32aeSBjoern A. Zeeb {
1152dd4f32aeSBjoern A. Zeeb 	struct cfg80211_chan_def *chandef = NULL;
1153dd4f32aeSBjoern A. Zeeb 	int ret;
1154dd4f32aeSBjoern A. Zeeb 
1155dd4f32aeSBjoern A. Zeeb 	lockdep_assert_held(&ar->conf_mutex);
1156dd4f32aeSBjoern A. Zeeb 
1157dd4f32aeSBjoern A. Zeeb 	if (test_bit(ATH11K_FLAG_MONITOR_STARTED, &ar->monitor_flags))
1158dd4f32aeSBjoern A. Zeeb 		return 0;
1159dd4f32aeSBjoern A. Zeeb 
1160dd4f32aeSBjoern A. Zeeb 	ieee80211_iter_chan_contexts_atomic(ar->hw,
1161dd4f32aeSBjoern A. Zeeb 					    ath11k_mac_get_any_chandef_iter,
1162dd4f32aeSBjoern A. Zeeb 					    &chandef);
1163dd4f32aeSBjoern A. Zeeb 	if (!chandef)
1164dd4f32aeSBjoern A. Zeeb 		return 0;
1165dd4f32aeSBjoern A. Zeeb 
1166dd4f32aeSBjoern A. Zeeb 	ret = ath11k_mac_monitor_vdev_start(ar, ar->monitor_vdev_id, chandef);
1167dd4f32aeSBjoern A. Zeeb 	if (ret) {
1168dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to start monitor vdev: %d\n", ret);
1169dd4f32aeSBjoern A. Zeeb 		ath11k_mac_monitor_vdev_delete(ar);
1170dd4f32aeSBjoern A. Zeeb 		return ret;
1171dd4f32aeSBjoern A. Zeeb 	}
1172dd4f32aeSBjoern A. Zeeb 
1173dd4f32aeSBjoern A. Zeeb 	set_bit(ATH11K_FLAG_MONITOR_STARTED, &ar->monitor_flags);
1174dd4f32aeSBjoern A. Zeeb 
1175dd4f32aeSBjoern A. Zeeb 	ar->num_started_vdevs++;
1176dd4f32aeSBjoern A. Zeeb 	ret = ath11k_dp_tx_htt_monitor_mode_ring_config(ar, false);
1177dd4f32aeSBjoern A. Zeeb 	if (ret) {
1178dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to configure htt monitor mode ring during start: %d",
1179dd4f32aeSBjoern A. Zeeb 			    ret);
1180dd4f32aeSBjoern A. Zeeb 		return ret;
1181dd4f32aeSBjoern A. Zeeb 	}
1182dd4f32aeSBjoern A. Zeeb 
1183*28348caeSBjoern A. Zeeb 	ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "monitor started\n");
1184dd4f32aeSBjoern A. Zeeb 
1185dd4f32aeSBjoern A. Zeeb 	return 0;
1186dd4f32aeSBjoern A. Zeeb }
1187dd4f32aeSBjoern A. Zeeb 
ath11k_mac_monitor_stop(struct ath11k * ar)1188dd4f32aeSBjoern A. Zeeb static int ath11k_mac_monitor_stop(struct ath11k *ar)
1189dd4f32aeSBjoern A. Zeeb {
1190dd4f32aeSBjoern A. Zeeb 	int ret;
1191dd4f32aeSBjoern A. Zeeb 
1192dd4f32aeSBjoern A. Zeeb 	lockdep_assert_held(&ar->conf_mutex);
1193dd4f32aeSBjoern A. Zeeb 
1194dd4f32aeSBjoern A. Zeeb 	if (!test_bit(ATH11K_FLAG_MONITOR_STARTED, &ar->monitor_flags))
1195dd4f32aeSBjoern A. Zeeb 		return 0;
1196dd4f32aeSBjoern A. Zeeb 
1197dd4f32aeSBjoern A. Zeeb 	ret = ath11k_mac_monitor_vdev_stop(ar);
1198dd4f32aeSBjoern A. Zeeb 	if (ret) {
1199dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to stop monitor vdev: %d\n", ret);
1200dd4f32aeSBjoern A. Zeeb 		return ret;
1201dd4f32aeSBjoern A. Zeeb 	}
1202dd4f32aeSBjoern A. Zeeb 
1203dd4f32aeSBjoern A. Zeeb 	clear_bit(ATH11K_FLAG_MONITOR_STARTED, &ar->monitor_flags);
1204dd4f32aeSBjoern A. Zeeb 	ar->num_started_vdevs--;
1205dd4f32aeSBjoern A. Zeeb 
1206dd4f32aeSBjoern A. Zeeb 	ret = ath11k_dp_tx_htt_monitor_mode_ring_config(ar, true);
1207dd4f32aeSBjoern A. Zeeb 	if (ret) {
1208dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to configure htt monitor mode ring during stop: %d",
1209dd4f32aeSBjoern A. Zeeb 			    ret);
1210dd4f32aeSBjoern A. Zeeb 		return ret;
1211dd4f32aeSBjoern A. Zeeb 	}
1212dd4f32aeSBjoern A. Zeeb 
1213*28348caeSBjoern A. Zeeb 	ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "monitor stopped ret %d\n", ret);
1214dd4f32aeSBjoern A. Zeeb 
1215dd4f32aeSBjoern A. Zeeb 	return 0;
1216dd4f32aeSBjoern A. Zeeb }
1217dd4f32aeSBjoern A. Zeeb 
ath11k_mac_vif_setup_ps(struct ath11k_vif * arvif)1218dd4f32aeSBjoern A. Zeeb static int ath11k_mac_vif_setup_ps(struct ath11k_vif *arvif)
1219dd4f32aeSBjoern A. Zeeb {
1220dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = arvif->ar;
1221dd4f32aeSBjoern A. Zeeb 	struct ieee80211_vif *vif = arvif->vif;
1222dd4f32aeSBjoern A. Zeeb 	struct ieee80211_conf *conf = &ar->hw->conf;
1223dd4f32aeSBjoern A. Zeeb 	enum wmi_sta_powersave_param param;
1224dd4f32aeSBjoern A. Zeeb 	enum wmi_sta_ps_mode psmode;
1225dd4f32aeSBjoern A. Zeeb 	int ret;
1226dd4f32aeSBjoern A. Zeeb 	int timeout;
1227dd4f32aeSBjoern A. Zeeb 	bool enable_ps;
1228dd4f32aeSBjoern A. Zeeb 
1229dd4f32aeSBjoern A. Zeeb 	lockdep_assert_held(&arvif->ar->conf_mutex);
1230dd4f32aeSBjoern A. Zeeb 
1231dd4f32aeSBjoern A. Zeeb 	if (arvif->vif->type != NL80211_IFTYPE_STATION)
1232dd4f32aeSBjoern A. Zeeb 		return 0;
1233dd4f32aeSBjoern A. Zeeb 
1234dd4f32aeSBjoern A. Zeeb 	enable_ps = arvif->ps;
1235dd4f32aeSBjoern A. Zeeb 
1236dd4f32aeSBjoern A. Zeeb 	if (!arvif->is_started) {
1237dd4f32aeSBjoern A. Zeeb 		/* mac80211 can update vif powersave state while disconnected.
1238dd4f32aeSBjoern A. Zeeb 		 * Firmware doesn't behave nicely and consumes more power than
1239dd4f32aeSBjoern A. Zeeb 		 * necessary if PS is disabled on a non-started vdev. Hence
1240dd4f32aeSBjoern A. Zeeb 		 * force-enable PS for non-running vdevs.
1241dd4f32aeSBjoern A. Zeeb 		 */
1242dd4f32aeSBjoern A. Zeeb 		psmode = WMI_STA_PS_MODE_ENABLED;
1243dd4f32aeSBjoern A. Zeeb 	} else if (enable_ps) {
1244dd4f32aeSBjoern A. Zeeb 		psmode = WMI_STA_PS_MODE_ENABLED;
1245dd4f32aeSBjoern A. Zeeb 		param = WMI_STA_PS_PARAM_INACTIVITY_TIME;
1246dd4f32aeSBjoern A. Zeeb 
1247dd4f32aeSBjoern A. Zeeb 		timeout = conf->dynamic_ps_timeout;
1248dd4f32aeSBjoern A. Zeeb 		if (timeout == 0) {
1249dd4f32aeSBjoern A. Zeeb 			/* firmware doesn't like 0 */
1250dd4f32aeSBjoern A. Zeeb 			timeout = ieee80211_tu_to_usec(vif->bss_conf.beacon_int) / 1000;
1251dd4f32aeSBjoern A. Zeeb 		}
1252dd4f32aeSBjoern A. Zeeb 
1253dd4f32aeSBjoern A. Zeeb 		ret = ath11k_wmi_set_sta_ps_param(ar, arvif->vdev_id, param,
1254dd4f32aeSBjoern A. Zeeb 						  timeout);
1255dd4f32aeSBjoern A. Zeeb 		if (ret) {
1256dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "failed to set inactivity time for vdev %d: %i\n",
1257dd4f32aeSBjoern A. Zeeb 				    arvif->vdev_id, ret);
1258dd4f32aeSBjoern A. Zeeb 			return ret;
1259dd4f32aeSBjoern A. Zeeb 		}
1260dd4f32aeSBjoern A. Zeeb 	} else {
1261dd4f32aeSBjoern A. Zeeb 		psmode = WMI_STA_PS_MODE_DISABLED;
1262dd4f32aeSBjoern A. Zeeb 	}
1263dd4f32aeSBjoern A. Zeeb 
1264*28348caeSBjoern A. Zeeb 	ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev %d psmode %s\n",
1265dd4f32aeSBjoern A. Zeeb 		   arvif->vdev_id, psmode ? "enable" : "disable");
1266dd4f32aeSBjoern A. Zeeb 
1267dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_pdev_set_ps_mode(ar, arvif->vdev_id, psmode);
1268dd4f32aeSBjoern A. Zeeb 	if (ret) {
1269dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to set sta power save mode %d for vdev %d: %d\n",
1270dd4f32aeSBjoern A. Zeeb 			    psmode, arvif->vdev_id, ret);
1271dd4f32aeSBjoern A. Zeeb 		return ret;
1272dd4f32aeSBjoern A. Zeeb 	}
1273dd4f32aeSBjoern A. Zeeb 
1274dd4f32aeSBjoern A. Zeeb 	return 0;
1275dd4f32aeSBjoern A. Zeeb }
1276dd4f32aeSBjoern A. Zeeb 
ath11k_mac_config_ps(struct ath11k * ar)1277dd4f32aeSBjoern A. Zeeb static int ath11k_mac_config_ps(struct ath11k *ar)
1278dd4f32aeSBjoern A. Zeeb {
1279dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif;
1280dd4f32aeSBjoern A. Zeeb 	int ret = 0;
1281dd4f32aeSBjoern A. Zeeb 
1282dd4f32aeSBjoern A. Zeeb 	lockdep_assert_held(&ar->conf_mutex);
1283dd4f32aeSBjoern A. Zeeb 
1284dd4f32aeSBjoern A. Zeeb 	list_for_each_entry(arvif, &ar->arvifs, list) {
1285dd4f32aeSBjoern A. Zeeb 		ret = ath11k_mac_vif_setup_ps(arvif);
1286dd4f32aeSBjoern A. Zeeb 		if (ret) {
1287dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "failed to setup powersave: %d\n", ret);
1288dd4f32aeSBjoern A. Zeeb 			break;
1289dd4f32aeSBjoern A. Zeeb 		}
1290dd4f32aeSBjoern A. Zeeb 	}
1291dd4f32aeSBjoern A. Zeeb 
1292dd4f32aeSBjoern A. Zeeb 	return ret;
1293dd4f32aeSBjoern A. Zeeb }
1294dd4f32aeSBjoern A. Zeeb 
ath11k_mac_op_config(struct ieee80211_hw * hw,u32 changed)1295dd4f32aeSBjoern A. Zeeb static int ath11k_mac_op_config(struct ieee80211_hw *hw, u32 changed)
1296dd4f32aeSBjoern A. Zeeb {
1297dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = hw->priv;
1298dd4f32aeSBjoern A. Zeeb 	struct ieee80211_conf *conf = &hw->conf;
1299dd4f32aeSBjoern A. Zeeb 	int ret = 0;
1300dd4f32aeSBjoern A. Zeeb 
1301dd4f32aeSBjoern A. Zeeb 	mutex_lock(&ar->conf_mutex);
1302dd4f32aeSBjoern A. Zeeb 
1303dd4f32aeSBjoern A. Zeeb 	if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
1304dd4f32aeSBjoern A. Zeeb 		if (conf->flags & IEEE80211_CONF_MONITOR) {
1305dd4f32aeSBjoern A. Zeeb 			set_bit(ATH11K_FLAG_MONITOR_CONF_ENABLED, &ar->monitor_flags);
1306dd4f32aeSBjoern A. Zeeb 
1307dd4f32aeSBjoern A. Zeeb 			if (test_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED,
1308dd4f32aeSBjoern A. Zeeb 				     &ar->monitor_flags))
1309dd4f32aeSBjoern A. Zeeb 				goto out;
1310dd4f32aeSBjoern A. Zeeb 
1311dd4f32aeSBjoern A. Zeeb 			ret = ath11k_mac_monitor_vdev_create(ar);
1312dd4f32aeSBjoern A. Zeeb 			if (ret) {
1313dd4f32aeSBjoern A. Zeeb 				ath11k_warn(ar->ab, "failed to create monitor vdev: %d",
1314dd4f32aeSBjoern A. Zeeb 					    ret);
1315dd4f32aeSBjoern A. Zeeb 				goto out;
1316dd4f32aeSBjoern A. Zeeb 			}
1317dd4f32aeSBjoern A. Zeeb 
1318dd4f32aeSBjoern A. Zeeb 			ret = ath11k_mac_monitor_start(ar);
1319dd4f32aeSBjoern A. Zeeb 			if (ret) {
1320dd4f32aeSBjoern A. Zeeb 				ath11k_warn(ar->ab, "failed to start monitor: %d",
1321dd4f32aeSBjoern A. Zeeb 					    ret);
1322dd4f32aeSBjoern A. Zeeb 				goto err_mon_del;
1323dd4f32aeSBjoern A. Zeeb 			}
1324dd4f32aeSBjoern A. Zeeb 		} else {
1325dd4f32aeSBjoern A. Zeeb 			clear_bit(ATH11K_FLAG_MONITOR_CONF_ENABLED, &ar->monitor_flags);
1326dd4f32aeSBjoern A. Zeeb 
1327dd4f32aeSBjoern A. Zeeb 			if (!test_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED,
1328dd4f32aeSBjoern A. Zeeb 				      &ar->monitor_flags))
1329dd4f32aeSBjoern A. Zeeb 				goto out;
1330dd4f32aeSBjoern A. Zeeb 
1331dd4f32aeSBjoern A. Zeeb 			ret = ath11k_mac_monitor_stop(ar);
1332dd4f32aeSBjoern A. Zeeb 			if (ret) {
1333dd4f32aeSBjoern A. Zeeb 				ath11k_warn(ar->ab, "failed to stop monitor: %d",
1334dd4f32aeSBjoern A. Zeeb 					    ret);
1335dd4f32aeSBjoern A. Zeeb 				goto out;
1336dd4f32aeSBjoern A. Zeeb 			}
1337dd4f32aeSBjoern A. Zeeb 
1338dd4f32aeSBjoern A. Zeeb 			ret = ath11k_mac_monitor_vdev_delete(ar);
1339dd4f32aeSBjoern A. Zeeb 			if (ret) {
1340dd4f32aeSBjoern A. Zeeb 				ath11k_warn(ar->ab, "failed to delete monitor vdev: %d",
1341dd4f32aeSBjoern A. Zeeb 					    ret);
1342dd4f32aeSBjoern A. Zeeb 				goto out;
1343dd4f32aeSBjoern A. Zeeb 			}
1344dd4f32aeSBjoern A. Zeeb 		}
1345dd4f32aeSBjoern A. Zeeb 	}
1346dd4f32aeSBjoern A. Zeeb 
1347dd4f32aeSBjoern A. Zeeb out:
1348dd4f32aeSBjoern A. Zeeb 	mutex_unlock(&ar->conf_mutex);
1349dd4f32aeSBjoern A. Zeeb 	return ret;
1350dd4f32aeSBjoern A. Zeeb 
1351dd4f32aeSBjoern A. Zeeb err_mon_del:
1352dd4f32aeSBjoern A. Zeeb 	ath11k_mac_monitor_vdev_delete(ar);
1353dd4f32aeSBjoern A. Zeeb 	mutex_unlock(&ar->conf_mutex);
1354dd4f32aeSBjoern A. Zeeb 	return ret;
1355dd4f32aeSBjoern A. Zeeb }
1356dd4f32aeSBjoern A. Zeeb 
ath11k_mac_setup_nontx_vif_rsnie(struct ath11k_vif * arvif,bool tx_arvif_rsnie_present,const u8 * profile,u8 profile_len)1357*28348caeSBjoern A. Zeeb static void ath11k_mac_setup_nontx_vif_rsnie(struct ath11k_vif *arvif,
1358*28348caeSBjoern A. Zeeb 					     bool tx_arvif_rsnie_present,
1359*28348caeSBjoern A. Zeeb 					     const u8 *profile, u8 profile_len)
1360dd4f32aeSBjoern A. Zeeb {
1361*28348caeSBjoern A. Zeeb 	if (cfg80211_find_ie(WLAN_EID_RSN, profile, profile_len)) {
1362*28348caeSBjoern A. Zeeb 		arvif->rsnie_present = true;
1363*28348caeSBjoern A. Zeeb 	} else if (tx_arvif_rsnie_present) {
1364*28348caeSBjoern A. Zeeb 		int i;
1365*28348caeSBjoern A. Zeeb 		u8 nie_len;
1366*28348caeSBjoern A. Zeeb 		const u8 *nie = cfg80211_find_ext_ie(WLAN_EID_EXT_NON_INHERITANCE,
1367*28348caeSBjoern A. Zeeb 						     profile, profile_len);
1368*28348caeSBjoern A. Zeeb 		if (!nie)
1369*28348caeSBjoern A. Zeeb 			return;
1370dd4f32aeSBjoern A. Zeeb 
1371*28348caeSBjoern A. Zeeb 		nie_len = nie[1];
1372*28348caeSBjoern A. Zeeb 		nie += 2;
1373*28348caeSBjoern A. Zeeb 		for (i = 0; i < nie_len; i++) {
1374*28348caeSBjoern A. Zeeb 			if (nie[i] == WLAN_EID_RSN) {
1375*28348caeSBjoern A. Zeeb 				arvif->rsnie_present = false;
1376*28348caeSBjoern A. Zeeb 				break;
1377*28348caeSBjoern A. Zeeb 			}
1378*28348caeSBjoern A. Zeeb 		}
1379*28348caeSBjoern A. Zeeb 	}
1380dd4f32aeSBjoern A. Zeeb }
1381dd4f32aeSBjoern A. Zeeb 
ath11k_mac_set_nontx_vif_params(struct ath11k_vif * tx_arvif,struct ath11k_vif * arvif,struct sk_buff * bcn)1382*28348caeSBjoern A. Zeeb static bool ath11k_mac_set_nontx_vif_params(struct ath11k_vif *tx_arvif,
1383*28348caeSBjoern A. Zeeb 					    struct ath11k_vif *arvif,
1384*28348caeSBjoern A. Zeeb 					    struct sk_buff *bcn)
1385*28348caeSBjoern A. Zeeb {
1386*28348caeSBjoern A. Zeeb 	struct ieee80211_mgmt *mgmt;
1387*28348caeSBjoern A. Zeeb 	const u8 *ies, *profile, *next_profile;
1388*28348caeSBjoern A. Zeeb 	int ies_len;
1389*28348caeSBjoern A. Zeeb 
1390dd4f32aeSBjoern A. Zeeb 	ies = bcn->data + ieee80211_get_hdrlen_from_skb(bcn);
1391*28348caeSBjoern A. Zeeb 	mgmt = (struct ieee80211_mgmt *)bcn->data;
1392*28348caeSBjoern A. Zeeb 	ies += sizeof(mgmt->u.beacon);
1393*28348caeSBjoern A. Zeeb 	ies_len = skb_tail_pointer(bcn) - ies;
1394*28348caeSBjoern A. Zeeb 
1395*28348caeSBjoern A. Zeeb 	ies = cfg80211_find_ie(WLAN_EID_MULTIPLE_BSSID, ies, ies_len);
1396*28348caeSBjoern A. Zeeb 	arvif->rsnie_present = tx_arvif->rsnie_present;
1397*28348caeSBjoern A. Zeeb 
1398*28348caeSBjoern A. Zeeb 	while (ies) {
1399*28348caeSBjoern A. Zeeb 		u8 mbssid_len;
1400*28348caeSBjoern A. Zeeb 
1401*28348caeSBjoern A. Zeeb 		ies_len -= (2 + ies[1]);
1402*28348caeSBjoern A. Zeeb 		mbssid_len = ies[1] - 1;
1403*28348caeSBjoern A. Zeeb 		profile = &ies[3];
1404*28348caeSBjoern A. Zeeb 
1405*28348caeSBjoern A. Zeeb 		while (mbssid_len) {
1406*28348caeSBjoern A. Zeeb 			u8 profile_len;
1407*28348caeSBjoern A. Zeeb 
1408*28348caeSBjoern A. Zeeb 			profile_len = profile[1];
1409*28348caeSBjoern A. Zeeb 			next_profile = profile + (2 + profile_len);
1410*28348caeSBjoern A. Zeeb 			mbssid_len -= (2 + profile_len);
1411*28348caeSBjoern A. Zeeb 
1412*28348caeSBjoern A. Zeeb 			profile += 2;
1413*28348caeSBjoern A. Zeeb 			profile_len -= (2 + profile[1]);
1414*28348caeSBjoern A. Zeeb 			profile += (2 + profile[1]); /* nontx capabilities */
1415*28348caeSBjoern A. Zeeb 			profile_len -= (2 + profile[1]);
1416*28348caeSBjoern A. Zeeb 			profile += (2 + profile[1]); /* SSID */
1417*28348caeSBjoern A. Zeeb 			if (profile[2] == arvif->vif->bss_conf.bssid_index) {
1418*28348caeSBjoern A. Zeeb 				profile_len -= 5;
1419*28348caeSBjoern A. Zeeb 				profile = profile + 5;
1420*28348caeSBjoern A. Zeeb 				ath11k_mac_setup_nontx_vif_rsnie(arvif,
1421*28348caeSBjoern A. Zeeb 								 tx_arvif->rsnie_present,
1422*28348caeSBjoern A. Zeeb 								 profile,
1423*28348caeSBjoern A. Zeeb 								 profile_len);
1424*28348caeSBjoern A. Zeeb 				return true;
1425*28348caeSBjoern A. Zeeb 			}
1426*28348caeSBjoern A. Zeeb 			profile = next_profile;
1427*28348caeSBjoern A. Zeeb 		}
1428*28348caeSBjoern A. Zeeb 		ies = cfg80211_find_ie(WLAN_EID_MULTIPLE_BSSID, profile,
1429*28348caeSBjoern A. Zeeb 				       ies_len);
1430*28348caeSBjoern A. Zeeb 	}
1431*28348caeSBjoern A. Zeeb 
1432*28348caeSBjoern A. Zeeb 	return false;
1433*28348caeSBjoern A. Zeeb }
1434*28348caeSBjoern A. Zeeb 
ath11k_mac_set_vif_params(struct ath11k_vif * arvif,struct sk_buff * bcn)1435*28348caeSBjoern A. Zeeb static void ath11k_mac_set_vif_params(struct ath11k_vif *arvif,
1436*28348caeSBjoern A. Zeeb 				      struct sk_buff *bcn)
1437*28348caeSBjoern A. Zeeb {
1438*28348caeSBjoern A. Zeeb 	struct ieee80211_mgmt *mgmt;
1439*28348caeSBjoern A. Zeeb 	u8 *ies;
1440*28348caeSBjoern A. Zeeb 
1441*28348caeSBjoern A. Zeeb 	ies = bcn->data + ieee80211_get_hdrlen_from_skb(bcn);
1442*28348caeSBjoern A. Zeeb 	mgmt = (struct ieee80211_mgmt *)bcn->data;
1443dd4f32aeSBjoern A. Zeeb 	ies += sizeof(mgmt->u.beacon);
1444dd4f32aeSBjoern A. Zeeb 
1445dd4f32aeSBjoern A. Zeeb 	if (cfg80211_find_ie(WLAN_EID_RSN, ies, (skb_tail_pointer(bcn) - ies)))
1446dd4f32aeSBjoern A. Zeeb 		arvif->rsnie_present = true;
1447dd4f32aeSBjoern A. Zeeb 	else
1448dd4f32aeSBjoern A. Zeeb 		arvif->rsnie_present = false;
1449dd4f32aeSBjoern A. Zeeb 
1450dd4f32aeSBjoern A. Zeeb 	if (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1451dd4f32aeSBjoern A. Zeeb 				    WLAN_OUI_TYPE_MICROSOFT_WPA,
1452dd4f32aeSBjoern A. Zeeb 				    ies, (skb_tail_pointer(bcn) - ies)))
1453dd4f32aeSBjoern A. Zeeb 		arvif->wpaie_present = true;
1454dd4f32aeSBjoern A. Zeeb 	else
1455dd4f32aeSBjoern A. Zeeb 		arvif->wpaie_present = false;
1456*28348caeSBjoern A. Zeeb }
1457dd4f32aeSBjoern A. Zeeb 
ath11k_mac_setup_bcn_tmpl_ema(struct ath11k_vif * arvif)1458*28348caeSBjoern A. Zeeb static int ath11k_mac_setup_bcn_tmpl_ema(struct ath11k_vif *arvif)
1459*28348caeSBjoern A. Zeeb {
1460*28348caeSBjoern A. Zeeb 	struct ath11k_vif *tx_arvif;
1461*28348caeSBjoern A. Zeeb 	struct ieee80211_ema_beacons *beacons;
1462*28348caeSBjoern A. Zeeb 	int ret = 0;
1463*28348caeSBjoern A. Zeeb 	bool nontx_vif_params_set = false;
1464*28348caeSBjoern A. Zeeb 	u32 params = 0;
1465*28348caeSBjoern A. Zeeb 	u8 i = 0;
1466dd4f32aeSBjoern A. Zeeb 
1467*28348caeSBjoern A. Zeeb 	tx_arvif = (void *)arvif->vif->mbssid_tx_vif->drv_priv;
1468*28348caeSBjoern A. Zeeb 
1469*28348caeSBjoern A. Zeeb 	beacons = ieee80211_beacon_get_template_ema_list(tx_arvif->ar->hw,
1470*28348caeSBjoern A. Zeeb 							 tx_arvif->vif, 0);
1471*28348caeSBjoern A. Zeeb 	if (!beacons || !beacons->cnt) {
1472*28348caeSBjoern A. Zeeb 		ath11k_warn(arvif->ar->ab,
1473*28348caeSBjoern A. Zeeb 			    "failed to get ema beacon templates from mac80211\n");
1474*28348caeSBjoern A. Zeeb 		return -EPERM;
1475*28348caeSBjoern A. Zeeb 	}
1476*28348caeSBjoern A. Zeeb 
1477*28348caeSBjoern A. Zeeb 	if (tx_arvif == arvif)
1478*28348caeSBjoern A. Zeeb 		ath11k_mac_set_vif_params(tx_arvif, beacons->bcn[0].skb);
1479*28348caeSBjoern A. Zeeb 	else
1480*28348caeSBjoern A. Zeeb 		arvif->wpaie_present = tx_arvif->wpaie_present;
1481*28348caeSBjoern A. Zeeb 
1482*28348caeSBjoern A. Zeeb 	for (i = 0; i < beacons->cnt; i++) {
1483*28348caeSBjoern A. Zeeb 		if (tx_arvif != arvif && !nontx_vif_params_set)
1484*28348caeSBjoern A. Zeeb 			nontx_vif_params_set =
1485*28348caeSBjoern A. Zeeb 				ath11k_mac_set_nontx_vif_params(tx_arvif, arvif,
1486*28348caeSBjoern A. Zeeb 								beacons->bcn[i].skb);
1487*28348caeSBjoern A. Zeeb 
1488*28348caeSBjoern A. Zeeb 		params = beacons->cnt;
1489*28348caeSBjoern A. Zeeb 		params |= (i << WMI_EMA_TMPL_IDX_SHIFT);
1490*28348caeSBjoern A. Zeeb 		params |= ((!i ? 1 : 0) << WMI_EMA_FIRST_TMPL_SHIFT);
1491*28348caeSBjoern A. Zeeb 		params |= ((i + 1 == beacons->cnt ? 1 : 0) << WMI_EMA_LAST_TMPL_SHIFT);
1492*28348caeSBjoern A. Zeeb 
1493*28348caeSBjoern A. Zeeb 		ret = ath11k_wmi_bcn_tmpl(tx_arvif->ar, tx_arvif->vdev_id,
1494*28348caeSBjoern A. Zeeb 					  &beacons->bcn[i].offs,
1495*28348caeSBjoern A. Zeeb 					  beacons->bcn[i].skb, params);
1496*28348caeSBjoern A. Zeeb 		if (ret) {
1497*28348caeSBjoern A. Zeeb 			ath11k_warn(tx_arvif->ar->ab,
1498*28348caeSBjoern A. Zeeb 				    "failed to set ema beacon template id %i error %d\n",
1499*28348caeSBjoern A. Zeeb 				    i, ret);
1500*28348caeSBjoern A. Zeeb 			break;
1501*28348caeSBjoern A. Zeeb 		}
1502*28348caeSBjoern A. Zeeb 	}
1503*28348caeSBjoern A. Zeeb 
1504*28348caeSBjoern A. Zeeb 	ieee80211_beacon_free_ema_list(beacons);
1505*28348caeSBjoern A. Zeeb 
1506*28348caeSBjoern A. Zeeb 	if (tx_arvif != arvif && !nontx_vif_params_set)
1507*28348caeSBjoern A. Zeeb 		return -EINVAL; /* Profile not found in the beacons */
1508*28348caeSBjoern A. Zeeb 
1509*28348caeSBjoern A. Zeeb 	return ret;
1510*28348caeSBjoern A. Zeeb }
1511*28348caeSBjoern A. Zeeb 
ath11k_mac_setup_bcn_tmpl_mbssid(struct ath11k_vif * arvif)1512*28348caeSBjoern A. Zeeb static int ath11k_mac_setup_bcn_tmpl_mbssid(struct ath11k_vif *arvif)
1513*28348caeSBjoern A. Zeeb {
1514*28348caeSBjoern A. Zeeb 	struct ath11k *ar = arvif->ar;
1515*28348caeSBjoern A. Zeeb 	struct ath11k_base *ab = ar->ab;
1516*28348caeSBjoern A. Zeeb 	struct ath11k_vif *tx_arvif = arvif;
1517*28348caeSBjoern A. Zeeb 	struct ieee80211_hw *hw = ar->hw;
1518*28348caeSBjoern A. Zeeb 	struct ieee80211_vif *vif = arvif->vif;
1519*28348caeSBjoern A. Zeeb 	struct ieee80211_mutable_offsets offs = {};
1520*28348caeSBjoern A. Zeeb 	struct sk_buff *bcn;
1521*28348caeSBjoern A. Zeeb 	int ret;
1522*28348caeSBjoern A. Zeeb 
1523*28348caeSBjoern A. Zeeb 	if (arvif->vif->mbssid_tx_vif) {
1524*28348caeSBjoern A. Zeeb 		tx_arvif = (void *)arvif->vif->mbssid_tx_vif->drv_priv;
1525*28348caeSBjoern A. Zeeb 		if (tx_arvif != arvif) {
1526*28348caeSBjoern A. Zeeb 			ar = tx_arvif->ar;
1527*28348caeSBjoern A. Zeeb 			ab = ar->ab;
1528*28348caeSBjoern A. Zeeb 			hw = ar->hw;
1529*28348caeSBjoern A. Zeeb 			vif = tx_arvif->vif;
1530*28348caeSBjoern A. Zeeb 		}
1531*28348caeSBjoern A. Zeeb 	}
1532*28348caeSBjoern A. Zeeb 
1533*28348caeSBjoern A. Zeeb 	bcn = ieee80211_beacon_get_template(hw, vif, &offs, 0);
1534*28348caeSBjoern A. Zeeb 	if (!bcn) {
1535*28348caeSBjoern A. Zeeb 		ath11k_warn(ab, "failed to get beacon template from mac80211\n");
1536*28348caeSBjoern A. Zeeb 		return -EPERM;
1537*28348caeSBjoern A. Zeeb 	}
1538*28348caeSBjoern A. Zeeb 
1539*28348caeSBjoern A. Zeeb 	if (tx_arvif == arvif)
1540*28348caeSBjoern A. Zeeb 		ath11k_mac_set_vif_params(tx_arvif, bcn);
1541*28348caeSBjoern A. Zeeb 	else if (!ath11k_mac_set_nontx_vif_params(tx_arvif, arvif, bcn))
1542*28348caeSBjoern A. Zeeb 		return -EINVAL;
1543*28348caeSBjoern A. Zeeb 
1544*28348caeSBjoern A. Zeeb 	ret = ath11k_wmi_bcn_tmpl(ar, arvif->vdev_id, &offs, bcn, 0);
1545dd4f32aeSBjoern A. Zeeb 	kfree_skb(bcn);
1546dd4f32aeSBjoern A. Zeeb 
1547dd4f32aeSBjoern A. Zeeb 	if (ret)
1548dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ab, "failed to submit beacon template command: %d\n",
1549dd4f32aeSBjoern A. Zeeb 			    ret);
1550dd4f32aeSBjoern A. Zeeb 
1551dd4f32aeSBjoern A. Zeeb 	return ret;
1552dd4f32aeSBjoern A. Zeeb }
1553dd4f32aeSBjoern A. Zeeb 
ath11k_mac_setup_bcn_tmpl(struct ath11k_vif * arvif)1554*28348caeSBjoern A. Zeeb static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif)
1555*28348caeSBjoern A. Zeeb {
1556*28348caeSBjoern A. Zeeb 	struct ieee80211_vif *vif = arvif->vif;
1557*28348caeSBjoern A. Zeeb 
1558*28348caeSBjoern A. Zeeb 	if (arvif->vdev_type != WMI_VDEV_TYPE_AP)
1559*28348caeSBjoern A. Zeeb 		return 0;
1560*28348caeSBjoern A. Zeeb 
1561*28348caeSBjoern A. Zeeb 	/* Target does not expect beacon templates for the already up
1562*28348caeSBjoern A. Zeeb 	 * non-transmitting interfaces, and results in a crash if sent.
1563*28348caeSBjoern A. Zeeb 	 */
1564*28348caeSBjoern A. Zeeb 	if (vif->mbssid_tx_vif &&
1565*28348caeSBjoern A. Zeeb 	    arvif != (void *)vif->mbssid_tx_vif->drv_priv && arvif->is_up)
1566*28348caeSBjoern A. Zeeb 		return 0;
1567*28348caeSBjoern A. Zeeb 
1568*28348caeSBjoern A. Zeeb 	if (vif->bss_conf.ema_ap && vif->mbssid_tx_vif)
1569*28348caeSBjoern A. Zeeb 		return ath11k_mac_setup_bcn_tmpl_ema(arvif);
1570*28348caeSBjoern A. Zeeb 
1571*28348caeSBjoern A. Zeeb 	return ath11k_mac_setup_bcn_tmpl_mbssid(arvif);
1572*28348caeSBjoern A. Zeeb }
1573*28348caeSBjoern A. Zeeb 
ath11k_mac_bcn_tx_event(struct ath11k_vif * arvif)1574dd4f32aeSBjoern A. Zeeb void ath11k_mac_bcn_tx_event(struct ath11k_vif *arvif)
1575dd4f32aeSBjoern A. Zeeb {
1576dd4f32aeSBjoern A. Zeeb 	struct ieee80211_vif *vif = arvif->vif;
1577dd4f32aeSBjoern A. Zeeb 
1578*28348caeSBjoern A. Zeeb 	if (!vif->bss_conf.color_change_active && !arvif->bcca_zero_sent)
1579dd4f32aeSBjoern A. Zeeb 		return;
1580dd4f32aeSBjoern A. Zeeb 
1581*28348caeSBjoern A. Zeeb 	if (vif->bss_conf.color_change_active &&
1582*28348caeSBjoern A. Zeeb 	    ieee80211_beacon_cntdwn_is_complete(vif)) {
1583dd4f32aeSBjoern A. Zeeb 		arvif->bcca_zero_sent = true;
1584dd4f32aeSBjoern A. Zeeb 		ieee80211_color_change_finish(vif);
1585dd4f32aeSBjoern A. Zeeb 		return;
1586dd4f32aeSBjoern A. Zeeb 	}
1587dd4f32aeSBjoern A. Zeeb 
1588dd4f32aeSBjoern A. Zeeb 	arvif->bcca_zero_sent = false;
1589dd4f32aeSBjoern A. Zeeb 
1590*28348caeSBjoern A. Zeeb 	if (vif->bss_conf.color_change_active)
1591dd4f32aeSBjoern A. Zeeb 		ieee80211_beacon_update_cntdwn(vif);
1592dd4f32aeSBjoern A. Zeeb 	ath11k_mac_setup_bcn_tmpl(arvif);
1593dd4f32aeSBjoern A. Zeeb }
1594dd4f32aeSBjoern A. Zeeb 
ath11k_control_beaconing(struct ath11k_vif * arvif,struct ieee80211_bss_conf * info)1595dd4f32aeSBjoern A. Zeeb static void ath11k_control_beaconing(struct ath11k_vif *arvif,
1596dd4f32aeSBjoern A. Zeeb 				     struct ieee80211_bss_conf *info)
1597dd4f32aeSBjoern A. Zeeb {
1598dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = arvif->ar;
1599*28348caeSBjoern A. Zeeb 	struct ath11k_vif *tx_arvif = NULL;
1600dd4f32aeSBjoern A. Zeeb 	int ret = 0;
1601dd4f32aeSBjoern A. Zeeb 
1602dd4f32aeSBjoern A. Zeeb 	lockdep_assert_held(&arvif->ar->conf_mutex);
1603dd4f32aeSBjoern A. Zeeb 
1604dd4f32aeSBjoern A. Zeeb 	if (!info->enable_beacon) {
1605dd4f32aeSBjoern A. Zeeb 		ret = ath11k_wmi_vdev_down(ar, arvif->vdev_id);
1606dd4f32aeSBjoern A. Zeeb 		if (ret)
1607dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "failed to down vdev_id %i: %d\n",
1608dd4f32aeSBjoern A. Zeeb 				    arvif->vdev_id, ret);
1609dd4f32aeSBjoern A. Zeeb 
1610dd4f32aeSBjoern A. Zeeb 		arvif->is_up = false;
1611dd4f32aeSBjoern A. Zeeb 		return;
1612dd4f32aeSBjoern A. Zeeb 	}
1613dd4f32aeSBjoern A. Zeeb 
1614dd4f32aeSBjoern A. Zeeb 	/* Install the beacon template to the FW */
1615dd4f32aeSBjoern A. Zeeb 	ret = ath11k_mac_setup_bcn_tmpl(arvif);
1616dd4f32aeSBjoern A. Zeeb 	if (ret) {
1617dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to update bcn tmpl during vdev up: %d\n",
1618dd4f32aeSBjoern A. Zeeb 			    ret);
1619dd4f32aeSBjoern A. Zeeb 		return;
1620dd4f32aeSBjoern A. Zeeb 	}
1621dd4f32aeSBjoern A. Zeeb 
1622dd4f32aeSBjoern A. Zeeb 	arvif->tx_seq_no = 0x1000;
1623dd4f32aeSBjoern A. Zeeb 
1624dd4f32aeSBjoern A. Zeeb 	arvif->aid = 0;
1625dd4f32aeSBjoern A. Zeeb 
1626dd4f32aeSBjoern A. Zeeb 	ether_addr_copy(arvif->bssid, info->bssid);
1627dd4f32aeSBjoern A. Zeeb 
1628*28348caeSBjoern A. Zeeb 	if (arvif->vif->mbssid_tx_vif)
1629*28348caeSBjoern A. Zeeb 		tx_arvif = (struct ath11k_vif *)arvif->vif->mbssid_tx_vif->drv_priv;
1630*28348caeSBjoern A. Zeeb 
1631dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid,
1632*28348caeSBjoern A. Zeeb 				 arvif->bssid,
1633*28348caeSBjoern A. Zeeb 				 tx_arvif ? tx_arvif->bssid : NULL,
1634*28348caeSBjoern A. Zeeb 				 info->bssid_index,
1635*28348caeSBjoern A. Zeeb 				 1 << info->bssid_indicator);
1636dd4f32aeSBjoern A. Zeeb 	if (ret) {
1637dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to bring up vdev %d: %i\n",
1638dd4f32aeSBjoern A. Zeeb 			    arvif->vdev_id, ret);
1639dd4f32aeSBjoern A. Zeeb 		return;
1640dd4f32aeSBjoern A. Zeeb 	}
1641dd4f32aeSBjoern A. Zeeb 
1642dd4f32aeSBjoern A. Zeeb 	arvif->is_up = true;
1643dd4f32aeSBjoern A. Zeeb 
1644*28348caeSBjoern A. Zeeb 	ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev %d up\n", arvif->vdev_id);
1645dd4f32aeSBjoern A. Zeeb }
1646dd4f32aeSBjoern A. Zeeb 
ath11k_mac_handle_beacon_iter(void * data,u8 * mac,struct ieee80211_vif * vif)1647dd4f32aeSBjoern A. Zeeb static void ath11k_mac_handle_beacon_iter(void *data, u8 *mac,
1648dd4f32aeSBjoern A. Zeeb 					  struct ieee80211_vif *vif)
1649dd4f32aeSBjoern A. Zeeb {
1650dd4f32aeSBjoern A. Zeeb 	struct sk_buff *skb = data;
1651dd4f32aeSBjoern A. Zeeb 	struct ieee80211_mgmt *mgmt = (void *)skb->data;
1652dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif = (void *)vif->drv_priv;
1653dd4f32aeSBjoern A. Zeeb 
1654dd4f32aeSBjoern A. Zeeb 	if (vif->type != NL80211_IFTYPE_STATION)
1655dd4f32aeSBjoern A. Zeeb 		return;
1656dd4f32aeSBjoern A. Zeeb 
1657dd4f32aeSBjoern A. Zeeb 	if (!ether_addr_equal(mgmt->bssid, vif->bss_conf.bssid))
1658dd4f32aeSBjoern A. Zeeb 		return;
1659dd4f32aeSBjoern A. Zeeb 
1660dd4f32aeSBjoern A. Zeeb 	cancel_delayed_work(&arvif->connection_loss_work);
1661dd4f32aeSBjoern A. Zeeb }
1662dd4f32aeSBjoern A. Zeeb 
ath11k_mac_handle_beacon(struct ath11k * ar,struct sk_buff * skb)1663dd4f32aeSBjoern A. Zeeb void ath11k_mac_handle_beacon(struct ath11k *ar, struct sk_buff *skb)
1664dd4f32aeSBjoern A. Zeeb {
1665dd4f32aeSBjoern A. Zeeb 	ieee80211_iterate_active_interfaces_atomic(ar->hw,
1666dd4f32aeSBjoern A. Zeeb 						   IEEE80211_IFACE_ITER_NORMAL,
1667dd4f32aeSBjoern A. Zeeb 						   ath11k_mac_handle_beacon_iter,
1668dd4f32aeSBjoern A. Zeeb 						   skb);
1669dd4f32aeSBjoern A. Zeeb }
1670dd4f32aeSBjoern A. Zeeb 
ath11k_mac_handle_beacon_miss_iter(void * data,u8 * mac,struct ieee80211_vif * vif)1671dd4f32aeSBjoern A. Zeeb static void ath11k_mac_handle_beacon_miss_iter(void *data, u8 *mac,
1672dd4f32aeSBjoern A. Zeeb 					       struct ieee80211_vif *vif)
1673dd4f32aeSBjoern A. Zeeb {
1674dd4f32aeSBjoern A. Zeeb 	u32 *vdev_id = data;
1675dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif = (void *)vif->drv_priv;
1676dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = arvif->ar;
1677dd4f32aeSBjoern A. Zeeb 	struct ieee80211_hw *hw = ar->hw;
1678dd4f32aeSBjoern A. Zeeb 
1679dd4f32aeSBjoern A. Zeeb 	if (arvif->vdev_id != *vdev_id)
1680dd4f32aeSBjoern A. Zeeb 		return;
1681dd4f32aeSBjoern A. Zeeb 
1682dd4f32aeSBjoern A. Zeeb 	if (!arvif->is_up)
1683dd4f32aeSBjoern A. Zeeb 		return;
1684dd4f32aeSBjoern A. Zeeb 
1685dd4f32aeSBjoern A. Zeeb 	ieee80211_beacon_loss(vif);
1686dd4f32aeSBjoern A. Zeeb 
1687dd4f32aeSBjoern A. Zeeb 	/* Firmware doesn't report beacon loss events repeatedly. If AP probe
1688dd4f32aeSBjoern A. Zeeb 	 * (done by mac80211) succeeds but beacons do not resume then it
1689dd4f32aeSBjoern A. Zeeb 	 * doesn't make sense to continue operation. Queue connection loss work
1690dd4f32aeSBjoern A. Zeeb 	 * which can be cancelled when beacon is received.
1691dd4f32aeSBjoern A. Zeeb 	 */
1692dd4f32aeSBjoern A. Zeeb 	ieee80211_queue_delayed_work(hw, &arvif->connection_loss_work,
1693dd4f32aeSBjoern A. Zeeb 				     ATH11K_CONNECTION_LOSS_HZ);
1694dd4f32aeSBjoern A. Zeeb }
1695dd4f32aeSBjoern A. Zeeb 
ath11k_mac_handle_beacon_miss(struct ath11k * ar,u32 vdev_id)1696dd4f32aeSBjoern A. Zeeb void ath11k_mac_handle_beacon_miss(struct ath11k *ar, u32 vdev_id)
1697dd4f32aeSBjoern A. Zeeb {
1698dd4f32aeSBjoern A. Zeeb 	ieee80211_iterate_active_interfaces_atomic(ar->hw,
1699dd4f32aeSBjoern A. Zeeb 						   IEEE80211_IFACE_ITER_NORMAL,
1700dd4f32aeSBjoern A. Zeeb 						   ath11k_mac_handle_beacon_miss_iter,
1701dd4f32aeSBjoern A. Zeeb 						   &vdev_id);
1702dd4f32aeSBjoern A. Zeeb }
1703dd4f32aeSBjoern A. Zeeb 
ath11k_mac_vif_sta_connection_loss_work(struct work_struct * work)1704dd4f32aeSBjoern A. Zeeb static void ath11k_mac_vif_sta_connection_loss_work(struct work_struct *work)
1705dd4f32aeSBjoern A. Zeeb {
1706dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif = container_of(work, struct ath11k_vif,
1707dd4f32aeSBjoern A. Zeeb 						connection_loss_work.work);
1708dd4f32aeSBjoern A. Zeeb 	struct ieee80211_vif *vif = arvif->vif;
1709dd4f32aeSBjoern A. Zeeb 
1710dd4f32aeSBjoern A. Zeeb 	if (!arvif->is_up)
1711dd4f32aeSBjoern A. Zeeb 		return;
1712dd4f32aeSBjoern A. Zeeb 
1713dd4f32aeSBjoern A. Zeeb 	ieee80211_connection_loss(vif);
1714dd4f32aeSBjoern A. Zeeb }
1715dd4f32aeSBjoern A. Zeeb 
ath11k_peer_assoc_h_basic(struct ath11k * ar,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct peer_assoc_params * arg)1716dd4f32aeSBjoern A. Zeeb static void ath11k_peer_assoc_h_basic(struct ath11k *ar,
1717dd4f32aeSBjoern A. Zeeb 				      struct ieee80211_vif *vif,
1718dd4f32aeSBjoern A. Zeeb 				      struct ieee80211_sta *sta,
1719dd4f32aeSBjoern A. Zeeb 				      struct peer_assoc_params *arg)
1720dd4f32aeSBjoern A. Zeeb {
1721dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif = (void *)vif->drv_priv;
1722dd4f32aeSBjoern A. Zeeb 	u32 aid;
1723dd4f32aeSBjoern A. Zeeb 
1724dd4f32aeSBjoern A. Zeeb 	lockdep_assert_held(&ar->conf_mutex);
1725dd4f32aeSBjoern A. Zeeb 
1726dd4f32aeSBjoern A. Zeeb 	if (vif->type == NL80211_IFTYPE_STATION)
1727*28348caeSBjoern A. Zeeb 		aid = vif->cfg.aid;
1728dd4f32aeSBjoern A. Zeeb 	else
1729dd4f32aeSBjoern A. Zeeb 		aid = sta->aid;
1730dd4f32aeSBjoern A. Zeeb 
1731dd4f32aeSBjoern A. Zeeb 	ether_addr_copy(arg->peer_mac, sta->addr);
1732dd4f32aeSBjoern A. Zeeb 	arg->vdev_id = arvif->vdev_id;
1733dd4f32aeSBjoern A. Zeeb 	arg->peer_associd = aid;
1734dd4f32aeSBjoern A. Zeeb 	arg->auth_flag = true;
1735dd4f32aeSBjoern A. Zeeb 	/* TODO: STA WAR in ath10k for listen interval required? */
1736dd4f32aeSBjoern A. Zeeb 	arg->peer_listen_intval = ar->hw->conf.listen_interval;
1737dd4f32aeSBjoern A. Zeeb 	arg->peer_nss = 1;
1738dd4f32aeSBjoern A. Zeeb 	arg->peer_caps = vif->bss_conf.assoc_capability;
1739dd4f32aeSBjoern A. Zeeb }
1740dd4f32aeSBjoern A. Zeeb 
ath11k_peer_assoc_h_crypto(struct ath11k * ar,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct peer_assoc_params * arg)1741dd4f32aeSBjoern A. Zeeb static void ath11k_peer_assoc_h_crypto(struct ath11k *ar,
1742dd4f32aeSBjoern A. Zeeb 				       struct ieee80211_vif *vif,
1743dd4f32aeSBjoern A. Zeeb 				       struct ieee80211_sta *sta,
1744dd4f32aeSBjoern A. Zeeb 				       struct peer_assoc_params *arg)
1745dd4f32aeSBjoern A. Zeeb {
1746dd4f32aeSBjoern A. Zeeb 	struct ieee80211_bss_conf *info = &vif->bss_conf;
1747dd4f32aeSBjoern A. Zeeb 	struct cfg80211_chan_def def;
1748dd4f32aeSBjoern A. Zeeb 	struct cfg80211_bss *bss;
1749dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif = (struct ath11k_vif *)vif->drv_priv;
1750dd4f32aeSBjoern A. Zeeb 	const u8 *rsnie = NULL;
1751dd4f32aeSBjoern A. Zeeb 	const u8 *wpaie = NULL;
1752dd4f32aeSBjoern A. Zeeb 
1753dd4f32aeSBjoern A. Zeeb 	lockdep_assert_held(&ar->conf_mutex);
1754dd4f32aeSBjoern A. Zeeb 
1755dd4f32aeSBjoern A. Zeeb 	if (WARN_ON(ath11k_mac_vif_chan(vif, &def)))
1756dd4f32aeSBjoern A. Zeeb 		return;
1757dd4f32aeSBjoern A. Zeeb 
1758dd4f32aeSBjoern A. Zeeb 	bss = cfg80211_get_bss(ar->hw->wiphy, def.chan, info->bssid, NULL, 0,
1759dd4f32aeSBjoern A. Zeeb 			       IEEE80211_BSS_TYPE_ANY, IEEE80211_PRIVACY_ANY);
1760dd4f32aeSBjoern A. Zeeb 
1761dd4f32aeSBjoern A. Zeeb 	if (arvif->rsnie_present || arvif->wpaie_present) {
1762dd4f32aeSBjoern A. Zeeb 		arg->need_ptk_4_way = true;
1763dd4f32aeSBjoern A. Zeeb 		if (arvif->wpaie_present)
1764dd4f32aeSBjoern A. Zeeb 			arg->need_gtk_2_way = true;
1765dd4f32aeSBjoern A. Zeeb 	} else if (bss) {
1766dd4f32aeSBjoern A. Zeeb 		const struct cfg80211_bss_ies *ies;
1767dd4f32aeSBjoern A. Zeeb 
1768dd4f32aeSBjoern A. Zeeb 		rcu_read_lock();
1769dd4f32aeSBjoern A. Zeeb 		rsnie = ieee80211_bss_get_ie(bss, WLAN_EID_RSN);
1770dd4f32aeSBjoern A. Zeeb 
1771dd4f32aeSBjoern A. Zeeb 		ies = rcu_dereference(bss->ies);
1772dd4f32aeSBjoern A. Zeeb 
1773dd4f32aeSBjoern A. Zeeb 		wpaie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1774dd4f32aeSBjoern A. Zeeb 						WLAN_OUI_TYPE_MICROSOFT_WPA,
1775dd4f32aeSBjoern A. Zeeb 						ies->data,
1776dd4f32aeSBjoern A. Zeeb 						ies->len);
1777dd4f32aeSBjoern A. Zeeb 		rcu_read_unlock();
1778dd4f32aeSBjoern A. Zeeb 		cfg80211_put_bss(ar->hw->wiphy, bss);
1779dd4f32aeSBjoern A. Zeeb 	}
1780dd4f32aeSBjoern A. Zeeb 
1781dd4f32aeSBjoern A. Zeeb 	/* FIXME: base on RSN IE/WPA IE is a correct idea? */
1782dd4f32aeSBjoern A. Zeeb 	if (rsnie || wpaie) {
1783dd4f32aeSBjoern A. Zeeb 		ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
1784dd4f32aeSBjoern A. Zeeb 			   "%s: rsn ie found\n", __func__);
1785dd4f32aeSBjoern A. Zeeb 		arg->need_ptk_4_way = true;
1786dd4f32aeSBjoern A. Zeeb 	}
1787dd4f32aeSBjoern A. Zeeb 
1788dd4f32aeSBjoern A. Zeeb 	if (wpaie) {
1789dd4f32aeSBjoern A. Zeeb 		ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
1790dd4f32aeSBjoern A. Zeeb 			   "%s: wpa ie found\n", __func__);
1791dd4f32aeSBjoern A. Zeeb 		arg->need_gtk_2_way = true;
1792dd4f32aeSBjoern A. Zeeb 	}
1793dd4f32aeSBjoern A. Zeeb 
1794dd4f32aeSBjoern A. Zeeb 	if (sta->mfp) {
1795dd4f32aeSBjoern A. Zeeb 		/* TODO: Need to check if FW supports PMF? */
1796dd4f32aeSBjoern A. Zeeb 		arg->is_pmf_enabled = true;
1797dd4f32aeSBjoern A. Zeeb 	}
1798dd4f32aeSBjoern A. Zeeb 
1799dd4f32aeSBjoern A. Zeeb 	/* TODO: safe_mode_enabled (bypass 4-way handshake) flag req? */
1800dd4f32aeSBjoern A. Zeeb }
1801dd4f32aeSBjoern A. Zeeb 
ath11k_peer_assoc_h_rates(struct ath11k * ar,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct peer_assoc_params * arg)1802dd4f32aeSBjoern A. Zeeb static void ath11k_peer_assoc_h_rates(struct ath11k *ar,
1803dd4f32aeSBjoern A. Zeeb 				      struct ieee80211_vif *vif,
1804dd4f32aeSBjoern A. Zeeb 				      struct ieee80211_sta *sta,
1805dd4f32aeSBjoern A. Zeeb 				      struct peer_assoc_params *arg)
1806dd4f32aeSBjoern A. Zeeb {
1807dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif = (void *)vif->drv_priv;
1808dd4f32aeSBjoern A. Zeeb 	struct wmi_rate_set_arg *rateset = &arg->peer_legacy_rates;
1809dd4f32aeSBjoern A. Zeeb 	struct cfg80211_chan_def def;
1810dd4f32aeSBjoern A. Zeeb 	const struct ieee80211_supported_band *sband;
1811dd4f32aeSBjoern A. Zeeb 	const struct ieee80211_rate *rates;
1812dd4f32aeSBjoern A. Zeeb 	enum nl80211_band band;
1813dd4f32aeSBjoern A. Zeeb 	u32 ratemask;
1814dd4f32aeSBjoern A. Zeeb 	u8 rate;
1815dd4f32aeSBjoern A. Zeeb 	int i;
1816dd4f32aeSBjoern A. Zeeb 
1817dd4f32aeSBjoern A. Zeeb 	lockdep_assert_held(&ar->conf_mutex);
1818dd4f32aeSBjoern A. Zeeb 
1819dd4f32aeSBjoern A. Zeeb 	if (WARN_ON(ath11k_mac_vif_chan(vif, &def)))
1820dd4f32aeSBjoern A. Zeeb 		return;
1821dd4f32aeSBjoern A. Zeeb 
1822dd4f32aeSBjoern A. Zeeb 	band = def.chan->band;
1823dd4f32aeSBjoern A. Zeeb 	sband = ar->hw->wiphy->bands[band];
1824dd4f32aeSBjoern A. Zeeb 	ratemask = sta->deflink.supp_rates[band];
1825dd4f32aeSBjoern A. Zeeb 	ratemask &= arvif->bitrate_mask.control[band].legacy;
1826dd4f32aeSBjoern A. Zeeb 	rates = sband->bitrates;
1827dd4f32aeSBjoern A. Zeeb 
1828dd4f32aeSBjoern A. Zeeb 	rateset->num_rates = 0;
1829dd4f32aeSBjoern A. Zeeb 
1830dd4f32aeSBjoern A. Zeeb 	for (i = 0; i < 32; i++, ratemask >>= 1, rates++) {
1831dd4f32aeSBjoern A. Zeeb 		if (!(ratemask & 1))
1832dd4f32aeSBjoern A. Zeeb 			continue;
1833dd4f32aeSBjoern A. Zeeb 
1834dd4f32aeSBjoern A. Zeeb 		rate = ath11k_mac_bitrate_to_rate(rates->bitrate);
1835dd4f32aeSBjoern A. Zeeb 		rateset->rates[rateset->num_rates] = rate;
1836dd4f32aeSBjoern A. Zeeb 		rateset->num_rates++;
1837dd4f32aeSBjoern A. Zeeb 	}
1838dd4f32aeSBjoern A. Zeeb }
1839dd4f32aeSBjoern A. Zeeb 
1840dd4f32aeSBjoern A. Zeeb static bool
ath11k_peer_assoc_h_ht_masked(const u8 * ht_mcs_mask)1841*28348caeSBjoern A. Zeeb ath11k_peer_assoc_h_ht_masked(const u8 *ht_mcs_mask)
1842dd4f32aeSBjoern A. Zeeb {
1843dd4f32aeSBjoern A. Zeeb 	int nss;
1844dd4f32aeSBjoern A. Zeeb 
1845dd4f32aeSBjoern A. Zeeb 	for (nss = 0; nss < IEEE80211_HT_MCS_MASK_LEN; nss++)
1846dd4f32aeSBjoern A. Zeeb 		if (ht_mcs_mask[nss])
1847dd4f32aeSBjoern A. Zeeb 			return false;
1848dd4f32aeSBjoern A. Zeeb 
1849dd4f32aeSBjoern A. Zeeb 	return true;
1850dd4f32aeSBjoern A. Zeeb }
1851dd4f32aeSBjoern A. Zeeb 
1852dd4f32aeSBjoern A. Zeeb static bool
ath11k_peer_assoc_h_vht_masked(const u16 * vht_mcs_mask)1853*28348caeSBjoern A. Zeeb ath11k_peer_assoc_h_vht_masked(const u16 *vht_mcs_mask)
1854dd4f32aeSBjoern A. Zeeb {
1855dd4f32aeSBjoern A. Zeeb 	int nss;
1856dd4f32aeSBjoern A. Zeeb 
1857dd4f32aeSBjoern A. Zeeb 	for (nss = 0; nss < NL80211_VHT_NSS_MAX; nss++)
1858dd4f32aeSBjoern A. Zeeb 		if (vht_mcs_mask[nss])
1859dd4f32aeSBjoern A. Zeeb 			return false;
1860dd4f32aeSBjoern A. Zeeb 
1861dd4f32aeSBjoern A. Zeeb 	return true;
1862dd4f32aeSBjoern A. Zeeb }
1863dd4f32aeSBjoern A. Zeeb 
ath11k_peer_assoc_h_ht(struct ath11k * ar,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct peer_assoc_params * arg)1864dd4f32aeSBjoern A. Zeeb static void ath11k_peer_assoc_h_ht(struct ath11k *ar,
1865dd4f32aeSBjoern A. Zeeb 				   struct ieee80211_vif *vif,
1866dd4f32aeSBjoern A. Zeeb 				   struct ieee80211_sta *sta,
1867dd4f32aeSBjoern A. Zeeb 				   struct peer_assoc_params *arg)
1868dd4f32aeSBjoern A. Zeeb {
1869dd4f32aeSBjoern A. Zeeb 	const struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap;
1870dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif = (void *)vif->drv_priv;
1871dd4f32aeSBjoern A. Zeeb 	struct cfg80211_chan_def def;
1872dd4f32aeSBjoern A. Zeeb 	enum nl80211_band band;
1873dd4f32aeSBjoern A. Zeeb 	const u8 *ht_mcs_mask;
1874dd4f32aeSBjoern A. Zeeb 	int i, n;
1875dd4f32aeSBjoern A. Zeeb 	u8 max_nss;
1876dd4f32aeSBjoern A. Zeeb 	u32 stbc;
1877dd4f32aeSBjoern A. Zeeb 
1878dd4f32aeSBjoern A. Zeeb 	lockdep_assert_held(&ar->conf_mutex);
1879dd4f32aeSBjoern A. Zeeb 
1880dd4f32aeSBjoern A. Zeeb 	if (WARN_ON(ath11k_mac_vif_chan(vif, &def)))
1881dd4f32aeSBjoern A. Zeeb 		return;
1882dd4f32aeSBjoern A. Zeeb 
1883dd4f32aeSBjoern A. Zeeb 	if (!ht_cap->ht_supported)
1884dd4f32aeSBjoern A. Zeeb 		return;
1885dd4f32aeSBjoern A. Zeeb 
1886dd4f32aeSBjoern A. Zeeb 	band = def.chan->band;
1887dd4f32aeSBjoern A. Zeeb 	ht_mcs_mask = arvif->bitrate_mask.control[band].ht_mcs;
1888dd4f32aeSBjoern A. Zeeb 
1889dd4f32aeSBjoern A. Zeeb 	if (ath11k_peer_assoc_h_ht_masked(ht_mcs_mask))
1890dd4f32aeSBjoern A. Zeeb 		return;
1891dd4f32aeSBjoern A. Zeeb 
1892dd4f32aeSBjoern A. Zeeb 	arg->ht_flag = true;
1893dd4f32aeSBjoern A. Zeeb 
1894dd4f32aeSBjoern A. Zeeb 	arg->peer_max_mpdu = (1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
1895dd4f32aeSBjoern A. Zeeb 				    ht_cap->ampdu_factor)) - 1;
1896dd4f32aeSBjoern A. Zeeb 
1897dd4f32aeSBjoern A. Zeeb 	arg->peer_mpdu_density =
1898dd4f32aeSBjoern A. Zeeb 		ath11k_parse_mpdudensity(ht_cap->ampdu_density);
1899dd4f32aeSBjoern A. Zeeb 
1900dd4f32aeSBjoern A. Zeeb 	arg->peer_ht_caps = ht_cap->cap;
1901dd4f32aeSBjoern A. Zeeb 	arg->peer_rate_caps |= WMI_HOST_RC_HT_FLAG;
1902dd4f32aeSBjoern A. Zeeb 
1903dd4f32aeSBjoern A. Zeeb 	if (ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING)
1904dd4f32aeSBjoern A. Zeeb 		arg->ldpc_flag = true;
1905dd4f32aeSBjoern A. Zeeb 
1906dd4f32aeSBjoern A. Zeeb 	if (sta->deflink.bandwidth >= IEEE80211_STA_RX_BW_40) {
1907dd4f32aeSBjoern A. Zeeb 		arg->bw_40 = true;
1908dd4f32aeSBjoern A. Zeeb 		arg->peer_rate_caps |= WMI_HOST_RC_CW40_FLAG;
1909dd4f32aeSBjoern A. Zeeb 	}
1910dd4f32aeSBjoern A. Zeeb 
1911dd4f32aeSBjoern A. Zeeb 	/* As firmware handles this two flags (IEEE80211_HT_CAP_SGI_20
1912dd4f32aeSBjoern A. Zeeb 	 * and IEEE80211_HT_CAP_SGI_40) for enabling SGI, we reset
1913dd4f32aeSBjoern A. Zeeb 	 * both flags if guard interval is Default GI
1914dd4f32aeSBjoern A. Zeeb 	 */
1915dd4f32aeSBjoern A. Zeeb 	if (arvif->bitrate_mask.control[band].gi == NL80211_TXRATE_DEFAULT_GI)
1916dd4f32aeSBjoern A. Zeeb 		arg->peer_ht_caps &= ~(IEEE80211_HT_CAP_SGI_20 |
1917dd4f32aeSBjoern A. Zeeb 				IEEE80211_HT_CAP_SGI_40);
1918dd4f32aeSBjoern A. Zeeb 
1919dd4f32aeSBjoern A. Zeeb 	if (arvif->bitrate_mask.control[band].gi != NL80211_TXRATE_FORCE_LGI) {
1920dd4f32aeSBjoern A. Zeeb 		if (ht_cap->cap & (IEEE80211_HT_CAP_SGI_20 |
1921dd4f32aeSBjoern A. Zeeb 		    IEEE80211_HT_CAP_SGI_40))
1922dd4f32aeSBjoern A. Zeeb 			arg->peer_rate_caps |= WMI_HOST_RC_SGI_FLAG;
1923dd4f32aeSBjoern A. Zeeb 	}
1924dd4f32aeSBjoern A. Zeeb 
1925dd4f32aeSBjoern A. Zeeb 	if (ht_cap->cap & IEEE80211_HT_CAP_TX_STBC) {
1926dd4f32aeSBjoern A. Zeeb 		arg->peer_rate_caps |= WMI_HOST_RC_TX_STBC_FLAG;
1927dd4f32aeSBjoern A. Zeeb 		arg->stbc_flag = true;
1928dd4f32aeSBjoern A. Zeeb 	}
1929dd4f32aeSBjoern A. Zeeb 
1930dd4f32aeSBjoern A. Zeeb 	if (ht_cap->cap & IEEE80211_HT_CAP_RX_STBC) {
1931dd4f32aeSBjoern A. Zeeb 		stbc = ht_cap->cap & IEEE80211_HT_CAP_RX_STBC;
1932dd4f32aeSBjoern A. Zeeb 		stbc = stbc >> IEEE80211_HT_CAP_RX_STBC_SHIFT;
1933dd4f32aeSBjoern A. Zeeb 		stbc = stbc << WMI_HOST_RC_RX_STBC_FLAG_S;
1934dd4f32aeSBjoern A. Zeeb 		arg->peer_rate_caps |= stbc;
1935dd4f32aeSBjoern A. Zeeb 		arg->stbc_flag = true;
1936dd4f32aeSBjoern A. Zeeb 	}
1937dd4f32aeSBjoern A. Zeeb 
1938dd4f32aeSBjoern A. Zeeb 	if (ht_cap->mcs.rx_mask[1] && ht_cap->mcs.rx_mask[2])
1939dd4f32aeSBjoern A. Zeeb 		arg->peer_rate_caps |= WMI_HOST_RC_TS_FLAG;
1940dd4f32aeSBjoern A. Zeeb 	else if (ht_cap->mcs.rx_mask[1])
1941dd4f32aeSBjoern A. Zeeb 		arg->peer_rate_caps |= WMI_HOST_RC_DS_FLAG;
1942dd4f32aeSBjoern A. Zeeb 
1943dd4f32aeSBjoern A. Zeeb 	for (i = 0, n = 0, max_nss = 0; i < IEEE80211_HT_MCS_MASK_LEN * 8; i++)
1944dd4f32aeSBjoern A. Zeeb 		if ((ht_cap->mcs.rx_mask[i / 8] & BIT(i % 8)) &&
1945dd4f32aeSBjoern A. Zeeb 		    (ht_mcs_mask[i / 8] & BIT(i % 8))) {
1946dd4f32aeSBjoern A. Zeeb 			max_nss = (i / 8) + 1;
1947dd4f32aeSBjoern A. Zeeb 			arg->peer_ht_rates.rates[n++] = i;
1948dd4f32aeSBjoern A. Zeeb 		}
1949dd4f32aeSBjoern A. Zeeb 
1950dd4f32aeSBjoern A. Zeeb 	/* This is a workaround for HT-enabled STAs which break the spec
1951dd4f32aeSBjoern A. Zeeb 	 * and have no HT capabilities RX mask (no HT RX MCS map).
1952dd4f32aeSBjoern A. Zeeb 	 *
1953dd4f32aeSBjoern A. Zeeb 	 * As per spec, in section 20.3.5 Modulation and coding scheme (MCS),
1954dd4f32aeSBjoern A. Zeeb 	 * MCS 0 through 7 are mandatory in 20MHz with 800 ns GI at all STAs.
1955dd4f32aeSBjoern A. Zeeb 	 *
1956dd4f32aeSBjoern A. Zeeb 	 * Firmware asserts if such situation occurs.
1957dd4f32aeSBjoern A. Zeeb 	 */
1958dd4f32aeSBjoern A. Zeeb 	if (n == 0) {
1959dd4f32aeSBjoern A. Zeeb 		arg->peer_ht_rates.num_rates = 8;
1960dd4f32aeSBjoern A. Zeeb 		for (i = 0; i < arg->peer_ht_rates.num_rates; i++)
1961dd4f32aeSBjoern A. Zeeb 			arg->peer_ht_rates.rates[i] = i;
1962dd4f32aeSBjoern A. Zeeb 	} else {
1963dd4f32aeSBjoern A. Zeeb 		arg->peer_ht_rates.num_rates = n;
1964dd4f32aeSBjoern A. Zeeb 		arg->peer_nss = min(sta->deflink.rx_nss, max_nss);
1965dd4f32aeSBjoern A. Zeeb 	}
1966dd4f32aeSBjoern A. Zeeb 
1967*28348caeSBjoern A. Zeeb 	ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "ht peer %pM mcs cnt %d nss %d\n",
1968dd4f32aeSBjoern A. Zeeb 		   arg->peer_mac,
1969dd4f32aeSBjoern A. Zeeb 		   arg->peer_ht_rates.num_rates,
1970dd4f32aeSBjoern A. Zeeb 		   arg->peer_nss);
1971dd4f32aeSBjoern A. Zeeb }
1972dd4f32aeSBjoern A. Zeeb 
ath11k_mac_get_max_vht_mcs_map(u16 mcs_map,int nss)1973dd4f32aeSBjoern A. Zeeb static int ath11k_mac_get_max_vht_mcs_map(u16 mcs_map, int nss)
1974dd4f32aeSBjoern A. Zeeb {
1975dd4f32aeSBjoern A. Zeeb 	switch ((mcs_map >> (2 * nss)) & 0x3) {
1976dd4f32aeSBjoern A. Zeeb 	case IEEE80211_VHT_MCS_SUPPORT_0_7: return BIT(8) - 1;
1977dd4f32aeSBjoern A. Zeeb 	case IEEE80211_VHT_MCS_SUPPORT_0_8: return BIT(9) - 1;
1978dd4f32aeSBjoern A. Zeeb 	case IEEE80211_VHT_MCS_SUPPORT_0_9: return BIT(10) - 1;
1979dd4f32aeSBjoern A. Zeeb 	}
1980dd4f32aeSBjoern A. Zeeb 	return 0;
1981dd4f32aeSBjoern A. Zeeb }
1982dd4f32aeSBjoern A. Zeeb 
1983dd4f32aeSBjoern A. Zeeb static u16
ath11k_peer_assoc_h_vht_limit(u16 tx_mcs_set,const u16 vht_mcs_limit[NL80211_VHT_NSS_MAX])1984dd4f32aeSBjoern A. Zeeb ath11k_peer_assoc_h_vht_limit(u16 tx_mcs_set,
1985dd4f32aeSBjoern A. Zeeb 			      const u16 vht_mcs_limit[NL80211_VHT_NSS_MAX])
1986dd4f32aeSBjoern A. Zeeb {
1987dd4f32aeSBjoern A. Zeeb 	int idx_limit;
1988dd4f32aeSBjoern A. Zeeb 	int nss;
1989dd4f32aeSBjoern A. Zeeb 	u16 mcs_map;
1990dd4f32aeSBjoern A. Zeeb 	u16 mcs;
1991dd4f32aeSBjoern A. Zeeb 
1992dd4f32aeSBjoern A. Zeeb 	for (nss = 0; nss < NL80211_VHT_NSS_MAX; nss++) {
1993dd4f32aeSBjoern A. Zeeb 		mcs_map = ath11k_mac_get_max_vht_mcs_map(tx_mcs_set, nss) &
1994dd4f32aeSBjoern A. Zeeb 			  vht_mcs_limit[nss];
1995dd4f32aeSBjoern A. Zeeb 
1996dd4f32aeSBjoern A. Zeeb 		if (mcs_map)
1997dd4f32aeSBjoern A. Zeeb 			idx_limit = fls(mcs_map) - 1;
1998dd4f32aeSBjoern A. Zeeb 		else
1999dd4f32aeSBjoern A. Zeeb 			idx_limit = -1;
2000dd4f32aeSBjoern A. Zeeb 
2001dd4f32aeSBjoern A. Zeeb 		switch (idx_limit) {
2002dd4f32aeSBjoern A. Zeeb 		case 0:
2003dd4f32aeSBjoern A. Zeeb 		case 1:
2004dd4f32aeSBjoern A. Zeeb 		case 2:
2005dd4f32aeSBjoern A. Zeeb 		case 3:
2006dd4f32aeSBjoern A. Zeeb 		case 4:
2007dd4f32aeSBjoern A. Zeeb 		case 5:
2008dd4f32aeSBjoern A. Zeeb 		case 6:
2009dd4f32aeSBjoern A. Zeeb 		case 7:
2010dd4f32aeSBjoern A. Zeeb 			mcs = IEEE80211_VHT_MCS_SUPPORT_0_7;
2011dd4f32aeSBjoern A. Zeeb 			break;
2012dd4f32aeSBjoern A. Zeeb 		case 8:
2013dd4f32aeSBjoern A. Zeeb 			mcs = IEEE80211_VHT_MCS_SUPPORT_0_8;
2014dd4f32aeSBjoern A. Zeeb 			break;
2015dd4f32aeSBjoern A. Zeeb 		case 9:
2016dd4f32aeSBjoern A. Zeeb 			mcs = IEEE80211_VHT_MCS_SUPPORT_0_9;
2017dd4f32aeSBjoern A. Zeeb 			break;
2018dd4f32aeSBjoern A. Zeeb 		default:
2019dd4f32aeSBjoern A. Zeeb 			WARN_ON(1);
2020dd4f32aeSBjoern A. Zeeb 			fallthrough;
2021dd4f32aeSBjoern A. Zeeb 		case -1:
2022dd4f32aeSBjoern A. Zeeb 			mcs = IEEE80211_VHT_MCS_NOT_SUPPORTED;
2023dd4f32aeSBjoern A. Zeeb 			break;
2024dd4f32aeSBjoern A. Zeeb 		}
2025dd4f32aeSBjoern A. Zeeb 
2026dd4f32aeSBjoern A. Zeeb 		tx_mcs_set &= ~(0x3 << (nss * 2));
2027dd4f32aeSBjoern A. Zeeb 		tx_mcs_set |= mcs << (nss * 2);
2028dd4f32aeSBjoern A. Zeeb 	}
2029dd4f32aeSBjoern A. Zeeb 
2030dd4f32aeSBjoern A. Zeeb 	return tx_mcs_set;
2031dd4f32aeSBjoern A. Zeeb }
2032dd4f32aeSBjoern A. Zeeb 
ath11k_get_nss_160mhz(struct ath11k * ar,u8 max_nss)2033dd4f32aeSBjoern A. Zeeb static u8 ath11k_get_nss_160mhz(struct ath11k *ar,
2034dd4f32aeSBjoern A. Zeeb 				u8 max_nss)
2035dd4f32aeSBjoern A. Zeeb {
2036dd4f32aeSBjoern A. Zeeb 	u8 nss_ratio_info = ar->pdev->cap.nss_ratio_info;
2037dd4f32aeSBjoern A. Zeeb 	u8 max_sup_nss = 0;
2038dd4f32aeSBjoern A. Zeeb 
2039dd4f32aeSBjoern A. Zeeb 	switch (nss_ratio_info) {
2040dd4f32aeSBjoern A. Zeeb 	case WMI_NSS_RATIO_1BY2_NSS:
2041dd4f32aeSBjoern A. Zeeb 		max_sup_nss = max_nss >> 1;
2042dd4f32aeSBjoern A. Zeeb 		break;
2043dd4f32aeSBjoern A. Zeeb 	case WMI_NSS_RATIO_3BY4_NSS:
2044dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "WMI_NSS_RATIO_3BY4_NSS not supported\n");
2045dd4f32aeSBjoern A. Zeeb 		break;
2046dd4f32aeSBjoern A. Zeeb 	case WMI_NSS_RATIO_1_NSS:
2047dd4f32aeSBjoern A. Zeeb 		max_sup_nss = max_nss;
2048dd4f32aeSBjoern A. Zeeb 		break;
2049dd4f32aeSBjoern A. Zeeb 	case WMI_NSS_RATIO_2_NSS:
2050dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "WMI_NSS_RATIO_2_NSS not supported\n");
2051dd4f32aeSBjoern A. Zeeb 		break;
2052dd4f32aeSBjoern A. Zeeb 	default:
2053dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "invalid nss ratio received from firmware: %d\n",
2054dd4f32aeSBjoern A. Zeeb 			    nss_ratio_info);
2055dd4f32aeSBjoern A. Zeeb 		break;
2056dd4f32aeSBjoern A. Zeeb 	}
2057dd4f32aeSBjoern A. Zeeb 
2058dd4f32aeSBjoern A. Zeeb 	return max_sup_nss;
2059dd4f32aeSBjoern A. Zeeb }
2060dd4f32aeSBjoern A. Zeeb 
ath11k_peer_assoc_h_vht(struct ath11k * ar,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct peer_assoc_params * arg)2061dd4f32aeSBjoern A. Zeeb static void ath11k_peer_assoc_h_vht(struct ath11k *ar,
2062dd4f32aeSBjoern A. Zeeb 				    struct ieee80211_vif *vif,
2063dd4f32aeSBjoern A. Zeeb 				    struct ieee80211_sta *sta,
2064dd4f32aeSBjoern A. Zeeb 				    struct peer_assoc_params *arg)
2065dd4f32aeSBjoern A. Zeeb {
2066dd4f32aeSBjoern A. Zeeb 	const struct ieee80211_sta_vht_cap *vht_cap = &sta->deflink.vht_cap;
2067dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif = (void *)vif->drv_priv;
2068dd4f32aeSBjoern A. Zeeb 	struct cfg80211_chan_def def;
2069dd4f32aeSBjoern A. Zeeb 	enum nl80211_band band;
2070dd4f32aeSBjoern A. Zeeb 	u16 *vht_mcs_mask;
2071dd4f32aeSBjoern A. Zeeb 	u8 ampdu_factor;
2072dd4f32aeSBjoern A. Zeeb 	u8 max_nss, vht_mcs;
2073dd4f32aeSBjoern A. Zeeb 	int i, vht_nss, nss_idx;
2074dd4f32aeSBjoern A. Zeeb 	bool user_rate_valid = true;
2075dd4f32aeSBjoern A. Zeeb 	u32 rx_nss, tx_nss, nss_160;
2076dd4f32aeSBjoern A. Zeeb 
2077dd4f32aeSBjoern A. Zeeb 	if (WARN_ON(ath11k_mac_vif_chan(vif, &def)))
2078dd4f32aeSBjoern A. Zeeb 		return;
2079dd4f32aeSBjoern A. Zeeb 
2080dd4f32aeSBjoern A. Zeeb 	if (!vht_cap->vht_supported)
2081dd4f32aeSBjoern A. Zeeb 		return;
2082dd4f32aeSBjoern A. Zeeb 
2083dd4f32aeSBjoern A. Zeeb 	band = def.chan->band;
2084dd4f32aeSBjoern A. Zeeb 	vht_mcs_mask = arvif->bitrate_mask.control[band].vht_mcs;
2085dd4f32aeSBjoern A. Zeeb 
2086dd4f32aeSBjoern A. Zeeb 	if (ath11k_peer_assoc_h_vht_masked(vht_mcs_mask))
2087dd4f32aeSBjoern A. Zeeb 		return;
2088dd4f32aeSBjoern A. Zeeb 
2089dd4f32aeSBjoern A. Zeeb 	arg->vht_flag = true;
2090dd4f32aeSBjoern A. Zeeb 
2091dd4f32aeSBjoern A. Zeeb 	/* TODO: similar flags required? */
2092dd4f32aeSBjoern A. Zeeb 	arg->vht_capable = true;
2093dd4f32aeSBjoern A. Zeeb 
2094dd4f32aeSBjoern A. Zeeb 	if (def.chan->band == NL80211_BAND_2GHZ)
2095dd4f32aeSBjoern A. Zeeb 		arg->vht_ng_flag = true;
2096dd4f32aeSBjoern A. Zeeb 
2097dd4f32aeSBjoern A. Zeeb 	arg->peer_vht_caps = vht_cap->cap;
2098dd4f32aeSBjoern A. Zeeb 
2099dd4f32aeSBjoern A. Zeeb 	ampdu_factor = (vht_cap->cap &
2100dd4f32aeSBjoern A. Zeeb 			IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK) >>
2101dd4f32aeSBjoern A. Zeeb 		       IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;
2102dd4f32aeSBjoern A. Zeeb 
2103dd4f32aeSBjoern A. Zeeb 	/* Workaround: Some Netgear/Linksys 11ac APs set Rx A-MPDU factor to
2104dd4f32aeSBjoern A. Zeeb 	 * zero in VHT IE. Using it would result in degraded throughput.
2105dd4f32aeSBjoern A. Zeeb 	 * arg->peer_max_mpdu at this point contains HT max_mpdu so keep
2106dd4f32aeSBjoern A. Zeeb 	 * it if VHT max_mpdu is smaller.
2107dd4f32aeSBjoern A. Zeeb 	 */
2108dd4f32aeSBjoern A. Zeeb 	arg->peer_max_mpdu = max(arg->peer_max_mpdu,
2109dd4f32aeSBjoern A. Zeeb 				 (1U << (IEEE80211_HT_MAX_AMPDU_FACTOR +
2110dd4f32aeSBjoern A. Zeeb 					ampdu_factor)) - 1);
2111dd4f32aeSBjoern A. Zeeb 
2112dd4f32aeSBjoern A. Zeeb 	if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80)
2113dd4f32aeSBjoern A. Zeeb 		arg->bw_80 = true;
2114dd4f32aeSBjoern A. Zeeb 
2115dd4f32aeSBjoern A. Zeeb 	if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160)
2116dd4f32aeSBjoern A. Zeeb 		arg->bw_160 = true;
2117dd4f32aeSBjoern A. Zeeb 
2118dd4f32aeSBjoern A. Zeeb 	vht_nss =  ath11k_mac_max_vht_nss(vht_mcs_mask);
2119dd4f32aeSBjoern A. Zeeb 
2120dd4f32aeSBjoern A. Zeeb 	if (vht_nss > sta->deflink.rx_nss) {
2121dd4f32aeSBjoern A. Zeeb 		user_rate_valid = false;
2122dd4f32aeSBjoern A. Zeeb 		for (nss_idx = sta->deflink.rx_nss - 1; nss_idx >= 0; nss_idx--) {
2123dd4f32aeSBjoern A. Zeeb 			if (vht_mcs_mask[nss_idx]) {
2124dd4f32aeSBjoern A. Zeeb 				user_rate_valid = true;
2125dd4f32aeSBjoern A. Zeeb 				break;
2126dd4f32aeSBjoern A. Zeeb 			}
2127dd4f32aeSBjoern A. Zeeb 		}
2128dd4f32aeSBjoern A. Zeeb 	}
2129dd4f32aeSBjoern A. Zeeb 
2130dd4f32aeSBjoern A. Zeeb 	if (!user_rate_valid) {
2131*28348caeSBjoern A. Zeeb 		ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "setting vht range mcs value to peer supported nss %d for peer %pM\n",
2132dd4f32aeSBjoern A. Zeeb 			   sta->deflink.rx_nss, sta->addr);
2133dd4f32aeSBjoern A. Zeeb 		vht_mcs_mask[sta->deflink.rx_nss - 1] = vht_mcs_mask[vht_nss - 1];
2134dd4f32aeSBjoern A. Zeeb 	}
2135dd4f32aeSBjoern A. Zeeb 
2136dd4f32aeSBjoern A. Zeeb 	/* Calculate peer NSS capability from VHT capabilities if STA
2137dd4f32aeSBjoern A. Zeeb 	 * supports VHT.
2138dd4f32aeSBjoern A. Zeeb 	 */
2139*28348caeSBjoern A. Zeeb 	for (i = 0, max_nss = 0; i < NL80211_VHT_NSS_MAX; i++) {
2140dd4f32aeSBjoern A. Zeeb 		vht_mcs = __le16_to_cpu(vht_cap->vht_mcs.rx_mcs_map) >>
2141dd4f32aeSBjoern A. Zeeb 			  (2 * i) & 3;
2142dd4f32aeSBjoern A. Zeeb 
2143dd4f32aeSBjoern A. Zeeb 		if (vht_mcs != IEEE80211_VHT_MCS_NOT_SUPPORTED &&
2144dd4f32aeSBjoern A. Zeeb 		    vht_mcs_mask[i])
2145dd4f32aeSBjoern A. Zeeb 			max_nss = i + 1;
2146dd4f32aeSBjoern A. Zeeb 	}
2147dd4f32aeSBjoern A. Zeeb 	arg->peer_nss = min(sta->deflink.rx_nss, max_nss);
2148dd4f32aeSBjoern A. Zeeb 	arg->rx_max_rate = __le16_to_cpu(vht_cap->vht_mcs.rx_highest);
2149dd4f32aeSBjoern A. Zeeb 	arg->rx_mcs_set = __le16_to_cpu(vht_cap->vht_mcs.rx_mcs_map);
2150dd4f32aeSBjoern A. Zeeb 	arg->tx_max_rate = __le16_to_cpu(vht_cap->vht_mcs.tx_highest);
2151dd4f32aeSBjoern A. Zeeb 	arg->tx_mcs_set = ath11k_peer_assoc_h_vht_limit(
2152dd4f32aeSBjoern A. Zeeb 		__le16_to_cpu(vht_cap->vht_mcs.tx_mcs_map), vht_mcs_mask);
2153dd4f32aeSBjoern A. Zeeb 
2154dd4f32aeSBjoern A. Zeeb 	/* In IPQ8074 platform, VHT mcs rate 10 and 11 is enabled by default.
2155dd4f32aeSBjoern A. Zeeb 	 * VHT mcs rate 10 and 11 is not suppoerted in 11ac standard.
2156dd4f32aeSBjoern A. Zeeb 	 * so explicitly disable the VHT MCS rate 10 and 11 in 11ac mode.
2157dd4f32aeSBjoern A. Zeeb 	 */
2158dd4f32aeSBjoern A. Zeeb 	arg->tx_mcs_set &= ~IEEE80211_VHT_MCS_SUPPORT_0_11_MASK;
2159dd4f32aeSBjoern A. Zeeb 	arg->tx_mcs_set |= IEEE80211_DISABLE_VHT_MCS_SUPPORT_0_11;
2160dd4f32aeSBjoern A. Zeeb 
2161dd4f32aeSBjoern A. Zeeb 	if ((arg->tx_mcs_set & IEEE80211_VHT_MCS_NOT_SUPPORTED) ==
2162dd4f32aeSBjoern A. Zeeb 			IEEE80211_VHT_MCS_NOT_SUPPORTED)
2163dd4f32aeSBjoern A. Zeeb 		arg->peer_vht_caps &= ~IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
2164dd4f32aeSBjoern A. Zeeb 
2165dd4f32aeSBjoern A. Zeeb 	/* TODO:  Check */
2166dd4f32aeSBjoern A. Zeeb 	arg->tx_max_mcs_nss = 0xFF;
2167dd4f32aeSBjoern A. Zeeb 
2168dd4f32aeSBjoern A. Zeeb 	if (arg->peer_phymode == MODE_11AC_VHT160 ||
2169dd4f32aeSBjoern A. Zeeb 	    arg->peer_phymode == MODE_11AC_VHT80_80) {
2170dd4f32aeSBjoern A. Zeeb 		tx_nss = ath11k_get_nss_160mhz(ar, max_nss);
2171dd4f32aeSBjoern A. Zeeb 		rx_nss = min(arg->peer_nss, tx_nss);
2172dd4f32aeSBjoern A. Zeeb 		arg->peer_bw_rxnss_override = ATH11K_BW_NSS_MAP_ENABLE;
2173dd4f32aeSBjoern A. Zeeb 
2174dd4f32aeSBjoern A. Zeeb 		if (!rx_nss) {
2175dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "invalid max_nss\n");
2176dd4f32aeSBjoern A. Zeeb 			return;
2177dd4f32aeSBjoern A. Zeeb 		}
2178dd4f32aeSBjoern A. Zeeb 
2179dd4f32aeSBjoern A. Zeeb 		if (arg->peer_phymode == MODE_11AC_VHT160)
2180dd4f32aeSBjoern A. Zeeb 			nss_160 = FIELD_PREP(ATH11K_PEER_RX_NSS_160MHZ, rx_nss - 1);
2181dd4f32aeSBjoern A. Zeeb 		else
2182dd4f32aeSBjoern A. Zeeb 			nss_160 = FIELD_PREP(ATH11K_PEER_RX_NSS_80_80MHZ, rx_nss - 1);
2183dd4f32aeSBjoern A. Zeeb 
2184dd4f32aeSBjoern A. Zeeb 		arg->peer_bw_rxnss_override |= nss_160;
2185dd4f32aeSBjoern A. Zeeb 	}
2186dd4f32aeSBjoern A. Zeeb 
2187dd4f32aeSBjoern A. Zeeb 	ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
2188*28348caeSBjoern A. Zeeb 		   "vht peer %pM max_mpdu %d flags 0x%x nss_override 0x%x\n",
2189dd4f32aeSBjoern A. Zeeb 		   sta->addr, arg->peer_max_mpdu, arg->peer_flags,
2190dd4f32aeSBjoern A. Zeeb 		   arg->peer_bw_rxnss_override);
2191dd4f32aeSBjoern A. Zeeb }
2192dd4f32aeSBjoern A. Zeeb 
ath11k_mac_get_max_he_mcs_map(u16 mcs_map,int nss)2193dd4f32aeSBjoern A. Zeeb static int ath11k_mac_get_max_he_mcs_map(u16 mcs_map, int nss)
2194dd4f32aeSBjoern A. Zeeb {
2195dd4f32aeSBjoern A. Zeeb 	switch ((mcs_map >> (2 * nss)) & 0x3) {
2196dd4f32aeSBjoern A. Zeeb 	case IEEE80211_HE_MCS_SUPPORT_0_7: return BIT(8) - 1;
2197dd4f32aeSBjoern A. Zeeb 	case IEEE80211_HE_MCS_SUPPORT_0_9: return BIT(10) - 1;
2198dd4f32aeSBjoern A. Zeeb 	case IEEE80211_HE_MCS_SUPPORT_0_11: return BIT(12) - 1;
2199dd4f32aeSBjoern A. Zeeb 	}
2200dd4f32aeSBjoern A. Zeeb 	return 0;
2201dd4f32aeSBjoern A. Zeeb }
2202dd4f32aeSBjoern A. Zeeb 
ath11k_peer_assoc_h_he_limit(u16 tx_mcs_set,const u16 he_mcs_limit[NL80211_HE_NSS_MAX])2203dd4f32aeSBjoern A. Zeeb static u16 ath11k_peer_assoc_h_he_limit(u16 tx_mcs_set,
2204dd4f32aeSBjoern A. Zeeb 					const u16 he_mcs_limit[NL80211_HE_NSS_MAX])
2205dd4f32aeSBjoern A. Zeeb {
2206dd4f32aeSBjoern A. Zeeb 	int idx_limit;
2207dd4f32aeSBjoern A. Zeeb 	int nss;
2208dd4f32aeSBjoern A. Zeeb 	u16 mcs_map;
2209dd4f32aeSBjoern A. Zeeb 	u16 mcs;
2210dd4f32aeSBjoern A. Zeeb 
2211dd4f32aeSBjoern A. Zeeb 	for (nss = 0; nss < NL80211_HE_NSS_MAX; nss++) {
2212dd4f32aeSBjoern A. Zeeb 		mcs_map = ath11k_mac_get_max_he_mcs_map(tx_mcs_set, nss) &
2213dd4f32aeSBjoern A. Zeeb 			he_mcs_limit[nss];
2214dd4f32aeSBjoern A. Zeeb 
2215dd4f32aeSBjoern A. Zeeb 		if (mcs_map)
2216dd4f32aeSBjoern A. Zeeb 			idx_limit = fls(mcs_map) - 1;
2217dd4f32aeSBjoern A. Zeeb 		else
2218dd4f32aeSBjoern A. Zeeb 			idx_limit = -1;
2219dd4f32aeSBjoern A. Zeeb 
2220dd4f32aeSBjoern A. Zeeb 		switch (idx_limit) {
2221dd4f32aeSBjoern A. Zeeb 		case 0 ... 7:
2222dd4f32aeSBjoern A. Zeeb 			mcs = IEEE80211_HE_MCS_SUPPORT_0_7;
2223dd4f32aeSBjoern A. Zeeb 			break;
2224dd4f32aeSBjoern A. Zeeb 		case 8:
2225dd4f32aeSBjoern A. Zeeb 		case 9:
2226dd4f32aeSBjoern A. Zeeb 			mcs = IEEE80211_HE_MCS_SUPPORT_0_9;
2227dd4f32aeSBjoern A. Zeeb 			break;
2228dd4f32aeSBjoern A. Zeeb 		case 10:
2229dd4f32aeSBjoern A. Zeeb 		case 11:
2230dd4f32aeSBjoern A. Zeeb 			mcs = IEEE80211_HE_MCS_SUPPORT_0_11;
2231dd4f32aeSBjoern A. Zeeb 			break;
2232dd4f32aeSBjoern A. Zeeb 		default:
2233dd4f32aeSBjoern A. Zeeb 			WARN_ON(1);
2234dd4f32aeSBjoern A. Zeeb 			fallthrough;
2235dd4f32aeSBjoern A. Zeeb 		case -1:
2236dd4f32aeSBjoern A. Zeeb 			mcs = IEEE80211_HE_MCS_NOT_SUPPORTED;
2237dd4f32aeSBjoern A. Zeeb 			break;
2238dd4f32aeSBjoern A. Zeeb 		}
2239dd4f32aeSBjoern A. Zeeb 
2240dd4f32aeSBjoern A. Zeeb 		tx_mcs_set &= ~(0x3 << (nss * 2));
2241dd4f32aeSBjoern A. Zeeb 		tx_mcs_set |= mcs << (nss * 2);
2242dd4f32aeSBjoern A. Zeeb 	}
2243dd4f32aeSBjoern A. Zeeb 
2244dd4f32aeSBjoern A. Zeeb 	return tx_mcs_set;
2245dd4f32aeSBjoern A. Zeeb }
2246dd4f32aeSBjoern A. Zeeb 
2247dd4f32aeSBjoern A. Zeeb static bool
ath11k_peer_assoc_h_he_masked(const u16 * he_mcs_mask)2248*28348caeSBjoern A. Zeeb ath11k_peer_assoc_h_he_masked(const u16 *he_mcs_mask)
2249dd4f32aeSBjoern A. Zeeb {
2250dd4f32aeSBjoern A. Zeeb 	int nss;
2251dd4f32aeSBjoern A. Zeeb 
2252dd4f32aeSBjoern A. Zeeb 	for (nss = 0; nss < NL80211_HE_NSS_MAX; nss++)
2253dd4f32aeSBjoern A. Zeeb 		if (he_mcs_mask[nss])
2254dd4f32aeSBjoern A. Zeeb 			return false;
2255dd4f32aeSBjoern A. Zeeb 
2256dd4f32aeSBjoern A. Zeeb 	return true;
2257dd4f32aeSBjoern A. Zeeb }
2258dd4f32aeSBjoern A. Zeeb 
ath11k_peer_assoc_h_he(struct ath11k * ar,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct peer_assoc_params * arg)2259dd4f32aeSBjoern A. Zeeb static void ath11k_peer_assoc_h_he(struct ath11k *ar,
2260dd4f32aeSBjoern A. Zeeb 				   struct ieee80211_vif *vif,
2261dd4f32aeSBjoern A. Zeeb 				   struct ieee80211_sta *sta,
2262dd4f32aeSBjoern A. Zeeb 				   struct peer_assoc_params *arg)
2263dd4f32aeSBjoern A. Zeeb {
2264dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif = (void *)vif->drv_priv;
2265dd4f32aeSBjoern A. Zeeb 	struct cfg80211_chan_def def;
2266dd4f32aeSBjoern A. Zeeb 	const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap;
2267dd4f32aeSBjoern A. Zeeb 	enum nl80211_band band;
2268*28348caeSBjoern A. Zeeb 	u16 he_mcs_mask[NL80211_HE_NSS_MAX];
2269dd4f32aeSBjoern A. Zeeb 	u8 max_nss, he_mcs;
2270dd4f32aeSBjoern A. Zeeb 	u16 he_tx_mcs = 0, v = 0;
2271dd4f32aeSBjoern A. Zeeb 	int i, he_nss, nss_idx;
2272dd4f32aeSBjoern A. Zeeb 	bool user_rate_valid = true;
2273dd4f32aeSBjoern A. Zeeb 	u32 rx_nss, tx_nss, nss_160;
2274dd4f32aeSBjoern A. Zeeb 	u8 ampdu_factor, rx_mcs_80, rx_mcs_160;
2275dd4f32aeSBjoern A. Zeeb 	u16 mcs_160_map, mcs_80_map;
2276dd4f32aeSBjoern A. Zeeb 	bool support_160;
2277dd4f32aeSBjoern A. Zeeb 
2278dd4f32aeSBjoern A. Zeeb 	if (WARN_ON(ath11k_mac_vif_chan(vif, &def)))
2279dd4f32aeSBjoern A. Zeeb 		return;
2280dd4f32aeSBjoern A. Zeeb 
2281dd4f32aeSBjoern A. Zeeb 	if (!he_cap->has_he)
2282dd4f32aeSBjoern A. Zeeb 		return;
2283dd4f32aeSBjoern A. Zeeb 
2284dd4f32aeSBjoern A. Zeeb 	band = def.chan->band;
2285*28348caeSBjoern A. Zeeb 	memcpy(he_mcs_mask, arvif->bitrate_mask.control[band].he_mcs,
2286*28348caeSBjoern A. Zeeb 	       sizeof(he_mcs_mask));
2287dd4f32aeSBjoern A. Zeeb 
2288dd4f32aeSBjoern A. Zeeb 	if (ath11k_peer_assoc_h_he_masked(he_mcs_mask))
2289dd4f32aeSBjoern A. Zeeb 		return;
2290dd4f32aeSBjoern A. Zeeb 
2291dd4f32aeSBjoern A. Zeeb 	arg->he_flag = true;
2292dd4f32aeSBjoern A. Zeeb 	support_160 = !!(he_cap->he_cap_elem.phy_cap_info[0] &
2293dd4f32aeSBjoern A. Zeeb 		  IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G);
2294dd4f32aeSBjoern A. Zeeb 
2295dd4f32aeSBjoern A. Zeeb 	/* Supported HE-MCS and NSS Set of peer he_cap is intersection with self he_cp */
2296dd4f32aeSBjoern A. Zeeb 	mcs_160_map = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160);
2297dd4f32aeSBjoern A. Zeeb 	mcs_80_map = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80);
2298dd4f32aeSBjoern A. Zeeb 
2299dd4f32aeSBjoern A. Zeeb 	if (support_160) {
2300dd4f32aeSBjoern A. Zeeb 		for (i = 7; i >= 0; i--) {
2301dd4f32aeSBjoern A. Zeeb 			u8 mcs_160 = (mcs_160_map >> (2 * i)) & 3;
2302dd4f32aeSBjoern A. Zeeb 
2303dd4f32aeSBjoern A. Zeeb 			if (mcs_160 != IEEE80211_VHT_MCS_NOT_SUPPORTED) {
2304dd4f32aeSBjoern A. Zeeb 				rx_mcs_160 = i + 1;
2305dd4f32aeSBjoern A. Zeeb 				break;
2306dd4f32aeSBjoern A. Zeeb 			}
2307dd4f32aeSBjoern A. Zeeb 		}
2308dd4f32aeSBjoern A. Zeeb 	}
2309dd4f32aeSBjoern A. Zeeb 
2310dd4f32aeSBjoern A. Zeeb 	for (i = 7; i >= 0; i--) {
2311dd4f32aeSBjoern A. Zeeb 		u8 mcs_80 = (mcs_80_map >> (2 * i)) & 3;
2312dd4f32aeSBjoern A. Zeeb 
2313dd4f32aeSBjoern A. Zeeb 		if (mcs_80 != IEEE80211_VHT_MCS_NOT_SUPPORTED) {
2314dd4f32aeSBjoern A. Zeeb 			rx_mcs_80 = i + 1;
2315dd4f32aeSBjoern A. Zeeb 			break;
2316dd4f32aeSBjoern A. Zeeb 		}
2317dd4f32aeSBjoern A. Zeeb 	}
2318dd4f32aeSBjoern A. Zeeb 
2319dd4f32aeSBjoern A. Zeeb 	if (support_160)
2320dd4f32aeSBjoern A. Zeeb 		max_nss = min(rx_mcs_80, rx_mcs_160);
2321dd4f32aeSBjoern A. Zeeb 	else
2322dd4f32aeSBjoern A. Zeeb 		max_nss = rx_mcs_80;
2323dd4f32aeSBjoern A. Zeeb 
2324dd4f32aeSBjoern A. Zeeb 	arg->peer_nss = min(sta->deflink.rx_nss, max_nss);
2325dd4f32aeSBjoern A. Zeeb 
2326dd4f32aeSBjoern A. Zeeb 	memcpy_and_pad(&arg->peer_he_cap_macinfo,
2327dd4f32aeSBjoern A. Zeeb 		       sizeof(arg->peer_he_cap_macinfo),
2328dd4f32aeSBjoern A. Zeeb 		       he_cap->he_cap_elem.mac_cap_info,
2329dd4f32aeSBjoern A. Zeeb 		       sizeof(he_cap->he_cap_elem.mac_cap_info),
2330dd4f32aeSBjoern A. Zeeb 		       0);
2331dd4f32aeSBjoern A. Zeeb 	memcpy_and_pad(&arg->peer_he_cap_phyinfo,
2332dd4f32aeSBjoern A. Zeeb 		       sizeof(arg->peer_he_cap_phyinfo),
2333dd4f32aeSBjoern A. Zeeb 		       he_cap->he_cap_elem.phy_cap_info,
2334dd4f32aeSBjoern A. Zeeb 		       sizeof(he_cap->he_cap_elem.phy_cap_info),
2335dd4f32aeSBjoern A. Zeeb 		       0);
2336dd4f32aeSBjoern A. Zeeb 	arg->peer_he_ops = vif->bss_conf.he_oper.params;
2337dd4f32aeSBjoern A. Zeeb 
2338dd4f32aeSBjoern A. Zeeb 	/* the top most byte is used to indicate BSS color info */
2339dd4f32aeSBjoern A. Zeeb 	arg->peer_he_ops &= 0xffffff;
2340dd4f32aeSBjoern A. Zeeb 
2341dd4f32aeSBjoern A. Zeeb 	/* As per section 26.6.1 11ax Draft5.0, if the Max AMPDU Exponent Extension
2342dd4f32aeSBjoern A. Zeeb 	 * in HE cap is zero, use the arg->peer_max_mpdu as calculated while parsing
2343dd4f32aeSBjoern A. Zeeb 	 * VHT caps(if VHT caps is present) or HT caps (if VHT caps is not present).
2344dd4f32aeSBjoern A. Zeeb 	 *
2345dd4f32aeSBjoern A. Zeeb 	 * For non-zero value of Max AMPDU Extponent Extension in HE MAC caps,
2346dd4f32aeSBjoern A. Zeeb 	 * if a HE STA sends VHT cap and HE cap IE in assoc request then, use
2347dd4f32aeSBjoern A. Zeeb 	 * MAX_AMPDU_LEN_FACTOR as 20 to calculate max_ampdu length.
2348dd4f32aeSBjoern A. Zeeb 	 * If a HE STA that does not send VHT cap, but HE and HT cap in assoc
2349dd4f32aeSBjoern A. Zeeb 	 * request, then use MAX_AMPDU_LEN_FACTOR as 16 to calculate max_ampdu
2350dd4f32aeSBjoern A. Zeeb 	 * length.
2351dd4f32aeSBjoern A. Zeeb 	 */
2352dd4f32aeSBjoern A. Zeeb 	ampdu_factor = u8_get_bits(he_cap->he_cap_elem.mac_cap_info[3],
2353dd4f32aeSBjoern A. Zeeb 				   IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_MASK);
2354dd4f32aeSBjoern A. Zeeb 
2355dd4f32aeSBjoern A. Zeeb 	if (ampdu_factor) {
2356dd4f32aeSBjoern A. Zeeb 		if (sta->deflink.vht_cap.vht_supported)
2357dd4f32aeSBjoern A. Zeeb 			arg->peer_max_mpdu = (1 << (IEEE80211_HE_VHT_MAX_AMPDU_FACTOR +
2358dd4f32aeSBjoern A. Zeeb 						    ampdu_factor)) - 1;
2359dd4f32aeSBjoern A. Zeeb 		else if (sta->deflink.ht_cap.ht_supported)
2360dd4f32aeSBjoern A. Zeeb 			arg->peer_max_mpdu = (1 << (IEEE80211_HE_HT_MAX_AMPDU_FACTOR +
2361dd4f32aeSBjoern A. Zeeb 						    ampdu_factor)) - 1;
2362dd4f32aeSBjoern A. Zeeb 	}
2363dd4f32aeSBjoern A. Zeeb 
2364dd4f32aeSBjoern A. Zeeb 	if (he_cap->he_cap_elem.phy_cap_info[6] &
2365dd4f32aeSBjoern A. Zeeb 	    IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) {
2366dd4f32aeSBjoern A. Zeeb 		int bit = 7;
2367dd4f32aeSBjoern A. Zeeb 		int nss, ru;
2368dd4f32aeSBjoern A. Zeeb 
2369dd4f32aeSBjoern A. Zeeb 		arg->peer_ppet.numss_m1 = he_cap->ppe_thres[0] &
2370dd4f32aeSBjoern A. Zeeb 					  IEEE80211_PPE_THRES_NSS_MASK;
2371dd4f32aeSBjoern A. Zeeb 		arg->peer_ppet.ru_bit_mask =
2372dd4f32aeSBjoern A. Zeeb 			(he_cap->ppe_thres[0] &
2373dd4f32aeSBjoern A. Zeeb 			 IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK) >>
2374dd4f32aeSBjoern A. Zeeb 			IEEE80211_PPE_THRES_RU_INDEX_BITMASK_POS;
2375dd4f32aeSBjoern A. Zeeb 
2376dd4f32aeSBjoern A. Zeeb 		for (nss = 0; nss <= arg->peer_ppet.numss_m1; nss++) {
2377dd4f32aeSBjoern A. Zeeb 			for (ru = 0; ru < 4; ru++) {
2378dd4f32aeSBjoern A. Zeeb 				u32 val = 0;
2379dd4f32aeSBjoern A. Zeeb 				int i;
2380dd4f32aeSBjoern A. Zeeb 
2381dd4f32aeSBjoern A. Zeeb 				if ((arg->peer_ppet.ru_bit_mask & BIT(ru)) == 0)
2382dd4f32aeSBjoern A. Zeeb 					continue;
2383dd4f32aeSBjoern A. Zeeb 				for (i = 0; i < 6; i++) {
2384dd4f32aeSBjoern A. Zeeb 					val >>= 1;
2385dd4f32aeSBjoern A. Zeeb 					val |= ((he_cap->ppe_thres[bit / 8] >>
2386dd4f32aeSBjoern A. Zeeb 						 (bit % 8)) & 0x1) << 5;
2387dd4f32aeSBjoern A. Zeeb 					bit++;
2388dd4f32aeSBjoern A. Zeeb 				}
2389dd4f32aeSBjoern A. Zeeb 				arg->peer_ppet.ppet16_ppet8_ru3_ru0[nss] |=
2390dd4f32aeSBjoern A. Zeeb 								val << (ru * 6);
2391dd4f32aeSBjoern A. Zeeb 			}
2392dd4f32aeSBjoern A. Zeeb 		}
2393dd4f32aeSBjoern A. Zeeb 	}
2394dd4f32aeSBjoern A. Zeeb 
2395dd4f32aeSBjoern A. Zeeb 	if (he_cap->he_cap_elem.mac_cap_info[0] & IEEE80211_HE_MAC_CAP0_TWT_RES)
2396dd4f32aeSBjoern A. Zeeb 		arg->twt_responder = true;
2397dd4f32aeSBjoern A. Zeeb 	if (he_cap->he_cap_elem.mac_cap_info[0] & IEEE80211_HE_MAC_CAP0_TWT_REQ)
2398dd4f32aeSBjoern A. Zeeb 		arg->twt_requester = true;
2399dd4f32aeSBjoern A. Zeeb 
2400dd4f32aeSBjoern A. Zeeb 	he_nss =  ath11k_mac_max_he_nss(he_mcs_mask);
2401dd4f32aeSBjoern A. Zeeb 
2402dd4f32aeSBjoern A. Zeeb 	if (he_nss > sta->deflink.rx_nss) {
2403dd4f32aeSBjoern A. Zeeb 		user_rate_valid = false;
2404dd4f32aeSBjoern A. Zeeb 		for (nss_idx = sta->deflink.rx_nss - 1; nss_idx >= 0; nss_idx--) {
2405dd4f32aeSBjoern A. Zeeb 			if (he_mcs_mask[nss_idx]) {
2406dd4f32aeSBjoern A. Zeeb 				user_rate_valid = true;
2407dd4f32aeSBjoern A. Zeeb 				break;
2408dd4f32aeSBjoern A. Zeeb 			}
2409dd4f32aeSBjoern A. Zeeb 		}
2410dd4f32aeSBjoern A. Zeeb 	}
2411dd4f32aeSBjoern A. Zeeb 
2412dd4f32aeSBjoern A. Zeeb 	if (!user_rate_valid) {
2413*28348caeSBjoern A. Zeeb 		ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "setting he range mcs value to peer supported nss %d for peer %pM\n",
2414dd4f32aeSBjoern A. Zeeb 			   sta->deflink.rx_nss, sta->addr);
2415dd4f32aeSBjoern A. Zeeb 		he_mcs_mask[sta->deflink.rx_nss - 1] = he_mcs_mask[he_nss - 1];
2416dd4f32aeSBjoern A. Zeeb 	}
2417dd4f32aeSBjoern A. Zeeb 
2418dd4f32aeSBjoern A. Zeeb 	switch (sta->deflink.bandwidth) {
2419dd4f32aeSBjoern A. Zeeb 	case IEEE80211_STA_RX_BW_160:
2420dd4f32aeSBjoern A. Zeeb 		if (he_cap->he_cap_elem.phy_cap_info[0] &
2421dd4f32aeSBjoern A. Zeeb 		    IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G) {
2422dd4f32aeSBjoern A. Zeeb 			v = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80p80);
2423dd4f32aeSBjoern A. Zeeb 			v = ath11k_peer_assoc_h_he_limit(v, he_mcs_mask);
2424dd4f32aeSBjoern A. Zeeb 			arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80_80] = v;
2425dd4f32aeSBjoern A. Zeeb 
2426dd4f32aeSBjoern A. Zeeb 			v = le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_80p80);
2427dd4f32aeSBjoern A. Zeeb 			arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80_80] = v;
2428dd4f32aeSBjoern A. Zeeb 
2429dd4f32aeSBjoern A. Zeeb 			arg->peer_he_mcs_count++;
2430dd4f32aeSBjoern A. Zeeb 			he_tx_mcs = v;
2431dd4f32aeSBjoern A. Zeeb 		}
2432dd4f32aeSBjoern A. Zeeb 		v = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160);
2433dd4f32aeSBjoern A. Zeeb 		arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_160] = v;
2434dd4f32aeSBjoern A. Zeeb 
2435dd4f32aeSBjoern A. Zeeb 		v = le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_160);
2436dd4f32aeSBjoern A. Zeeb 		v = ath11k_peer_assoc_h_he_limit(v, he_mcs_mask);
2437dd4f32aeSBjoern A. Zeeb 		arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_160] = v;
2438dd4f32aeSBjoern A. Zeeb 
2439dd4f32aeSBjoern A. Zeeb 		arg->peer_he_mcs_count++;
2440dd4f32aeSBjoern A. Zeeb 		if (!he_tx_mcs)
2441dd4f32aeSBjoern A. Zeeb 			he_tx_mcs = v;
2442dd4f32aeSBjoern A. Zeeb 		fallthrough;
2443dd4f32aeSBjoern A. Zeeb 
2444dd4f32aeSBjoern A. Zeeb 	default:
2445dd4f32aeSBjoern A. Zeeb 		v = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80);
2446dd4f32aeSBjoern A. Zeeb 		arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80] = v;
2447dd4f32aeSBjoern A. Zeeb 
2448dd4f32aeSBjoern A. Zeeb 		v = le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_80);
2449dd4f32aeSBjoern A. Zeeb 		v = ath11k_peer_assoc_h_he_limit(v, he_mcs_mask);
2450dd4f32aeSBjoern A. Zeeb 		arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80] = v;
2451dd4f32aeSBjoern A. Zeeb 
2452dd4f32aeSBjoern A. Zeeb 		arg->peer_he_mcs_count++;
2453dd4f32aeSBjoern A. Zeeb 		if (!he_tx_mcs)
2454dd4f32aeSBjoern A. Zeeb 			he_tx_mcs = v;
2455dd4f32aeSBjoern A. Zeeb 		break;
2456dd4f32aeSBjoern A. Zeeb 	}
2457dd4f32aeSBjoern A. Zeeb 
2458dd4f32aeSBjoern A. Zeeb 	/* Calculate peer NSS capability from HE capabilities if STA
2459dd4f32aeSBjoern A. Zeeb 	 * supports HE.
2460dd4f32aeSBjoern A. Zeeb 	 */
2461*28348caeSBjoern A. Zeeb 	for (i = 0, max_nss = 0; i < NL80211_HE_NSS_MAX; i++) {
2462dd4f32aeSBjoern A. Zeeb 		he_mcs = he_tx_mcs >> (2 * i) & 3;
2463dd4f32aeSBjoern A. Zeeb 
2464dd4f32aeSBjoern A. Zeeb 		/* In case of fixed rates, MCS Range in he_tx_mcs might have
2465dd4f32aeSBjoern A. Zeeb 		 * unsupported range, with he_mcs_mask set, so check either of them
2466dd4f32aeSBjoern A. Zeeb 		 * to find nss.
2467dd4f32aeSBjoern A. Zeeb 		 */
2468dd4f32aeSBjoern A. Zeeb 		if (he_mcs != IEEE80211_HE_MCS_NOT_SUPPORTED ||
2469dd4f32aeSBjoern A. Zeeb 		    he_mcs_mask[i])
2470dd4f32aeSBjoern A. Zeeb 			max_nss = i + 1;
2471dd4f32aeSBjoern A. Zeeb 	}
2472dd4f32aeSBjoern A. Zeeb 	arg->peer_nss = min(sta->deflink.rx_nss, max_nss);
2473dd4f32aeSBjoern A. Zeeb 
2474dd4f32aeSBjoern A. Zeeb 	if (arg->peer_phymode == MODE_11AX_HE160 ||
2475dd4f32aeSBjoern A. Zeeb 	    arg->peer_phymode == MODE_11AX_HE80_80) {
2476dd4f32aeSBjoern A. Zeeb 		tx_nss = ath11k_get_nss_160mhz(ar, max_nss);
2477dd4f32aeSBjoern A. Zeeb 		rx_nss = min(arg->peer_nss, tx_nss);
2478dd4f32aeSBjoern A. Zeeb 		arg->peer_bw_rxnss_override = ATH11K_BW_NSS_MAP_ENABLE;
2479dd4f32aeSBjoern A. Zeeb 
2480dd4f32aeSBjoern A. Zeeb 		if (!rx_nss) {
2481dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "invalid max_nss\n");
2482dd4f32aeSBjoern A. Zeeb 			return;
2483dd4f32aeSBjoern A. Zeeb 		}
2484dd4f32aeSBjoern A. Zeeb 
2485dd4f32aeSBjoern A. Zeeb 		if (arg->peer_phymode == MODE_11AX_HE160)
2486dd4f32aeSBjoern A. Zeeb 			nss_160 = FIELD_PREP(ATH11K_PEER_RX_NSS_160MHZ, rx_nss - 1);
2487dd4f32aeSBjoern A. Zeeb 		else
2488dd4f32aeSBjoern A. Zeeb 			nss_160 = FIELD_PREP(ATH11K_PEER_RX_NSS_80_80MHZ, rx_nss - 1);
2489dd4f32aeSBjoern A. Zeeb 
2490dd4f32aeSBjoern A. Zeeb 		arg->peer_bw_rxnss_override |= nss_160;
2491dd4f32aeSBjoern A. Zeeb 	}
2492dd4f32aeSBjoern A. Zeeb 
2493dd4f32aeSBjoern A. Zeeb 	ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
2494*28348caeSBjoern A. Zeeb 		   "he peer %pM nss %d mcs cnt %d nss_override 0x%x\n",
2495dd4f32aeSBjoern A. Zeeb 		   sta->addr, arg->peer_nss,
2496dd4f32aeSBjoern A. Zeeb 		   arg->peer_he_mcs_count,
2497dd4f32aeSBjoern A. Zeeb 		   arg->peer_bw_rxnss_override);
2498dd4f32aeSBjoern A. Zeeb }
2499dd4f32aeSBjoern A. Zeeb 
ath11k_peer_assoc_h_he_6ghz(struct ath11k * ar,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct peer_assoc_params * arg)2500dd4f32aeSBjoern A. Zeeb static void ath11k_peer_assoc_h_he_6ghz(struct ath11k *ar,
2501dd4f32aeSBjoern A. Zeeb 					struct ieee80211_vif *vif,
2502dd4f32aeSBjoern A. Zeeb 					struct ieee80211_sta *sta,
2503dd4f32aeSBjoern A. Zeeb 					struct peer_assoc_params *arg)
2504dd4f32aeSBjoern A. Zeeb {
2505dd4f32aeSBjoern A. Zeeb 	const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap;
2506dd4f32aeSBjoern A. Zeeb 	struct cfg80211_chan_def def;
2507dd4f32aeSBjoern A. Zeeb 	enum nl80211_band band;
2508dd4f32aeSBjoern A. Zeeb 	u8  ampdu_factor;
2509dd4f32aeSBjoern A. Zeeb 
2510dd4f32aeSBjoern A. Zeeb 	if (WARN_ON(ath11k_mac_vif_chan(vif, &def)))
2511dd4f32aeSBjoern A. Zeeb 		return;
2512dd4f32aeSBjoern A. Zeeb 
2513dd4f32aeSBjoern A. Zeeb 	band = def.chan->band;
2514dd4f32aeSBjoern A. Zeeb 
2515dd4f32aeSBjoern A. Zeeb 	if (!arg->he_flag || band != NL80211_BAND_6GHZ || !sta->deflink.he_6ghz_capa.capa)
2516dd4f32aeSBjoern A. Zeeb 		return;
2517dd4f32aeSBjoern A. Zeeb 
2518*28348caeSBjoern A. Zeeb 	if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
2519*28348caeSBjoern A. Zeeb 		arg->bw_40 = true;
2520*28348caeSBjoern A. Zeeb 
2521dd4f32aeSBjoern A. Zeeb 	if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80)
2522dd4f32aeSBjoern A. Zeeb 		arg->bw_80 = true;
2523dd4f32aeSBjoern A. Zeeb 
2524dd4f32aeSBjoern A. Zeeb 	if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160)
2525dd4f32aeSBjoern A. Zeeb 		arg->bw_160 = true;
2526dd4f32aeSBjoern A. Zeeb 
2527dd4f32aeSBjoern A. Zeeb 	arg->peer_he_caps_6ghz = le16_to_cpu(sta->deflink.he_6ghz_capa.capa);
2528dd4f32aeSBjoern A. Zeeb 	arg->peer_mpdu_density =
2529dd4f32aeSBjoern A. Zeeb 		ath11k_parse_mpdudensity(FIELD_GET(IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START,
2530dd4f32aeSBjoern A. Zeeb 						   arg->peer_he_caps_6ghz));
2531dd4f32aeSBjoern A. Zeeb 
2532dd4f32aeSBjoern A. Zeeb 	/* From IEEE Std 802.11ax-2021 - Section 10.12.2: An HE STA shall be capable of
2533dd4f32aeSBjoern A. Zeeb 	 * receiving A-MPDU where the A-MPDU pre-EOF padding length is up to the value
2534dd4f32aeSBjoern A. Zeeb 	 * indicated by the Maximum A-MPDU Length Exponent Extension field in the HE
2535dd4f32aeSBjoern A. Zeeb 	 * Capabilities element and the Maximum A-MPDU Length Exponent field in HE 6 GHz
2536dd4f32aeSBjoern A. Zeeb 	 * Band Capabilities element in the 6 GHz band.
2537dd4f32aeSBjoern A. Zeeb 	 *
2538dd4f32aeSBjoern A. Zeeb 	 * Here, we are extracting the Max A-MPDU Exponent Extension from HE caps and
2539dd4f32aeSBjoern A. Zeeb 	 * factor is the Maximum A-MPDU Length Exponent from HE 6 GHZ Band capability.
2540dd4f32aeSBjoern A. Zeeb 	 */
2541dd4f32aeSBjoern A. Zeeb 	ampdu_factor = FIELD_GET(IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_MASK,
2542dd4f32aeSBjoern A. Zeeb 				 he_cap->he_cap_elem.mac_cap_info[3]) +
2543dd4f32aeSBjoern A. Zeeb 			FIELD_GET(IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP,
2544dd4f32aeSBjoern A. Zeeb 				  arg->peer_he_caps_6ghz);
2545dd4f32aeSBjoern A. Zeeb 
2546dd4f32aeSBjoern A. Zeeb 	arg->peer_max_mpdu = (1u << (IEEE80211_HE_6GHZ_MAX_AMPDU_FACTOR +
2547dd4f32aeSBjoern A. Zeeb 				     ampdu_factor)) - 1;
2548dd4f32aeSBjoern A. Zeeb }
2549dd4f32aeSBjoern A. Zeeb 
ath11k_peer_assoc_h_smps(struct ieee80211_sta * sta,struct peer_assoc_params * arg)2550dd4f32aeSBjoern A. Zeeb static void ath11k_peer_assoc_h_smps(struct ieee80211_sta *sta,
2551dd4f32aeSBjoern A. Zeeb 				     struct peer_assoc_params *arg)
2552dd4f32aeSBjoern A. Zeeb {
2553dd4f32aeSBjoern A. Zeeb 	const struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap;
2554dd4f32aeSBjoern A. Zeeb 	int smps;
2555dd4f32aeSBjoern A. Zeeb 
2556dd4f32aeSBjoern A. Zeeb 	if (!ht_cap->ht_supported && !sta->deflink.he_6ghz_capa.capa)
2557dd4f32aeSBjoern A. Zeeb 		return;
2558dd4f32aeSBjoern A. Zeeb 
2559dd4f32aeSBjoern A. Zeeb 	if (ht_cap->ht_supported) {
2560dd4f32aeSBjoern A. Zeeb 		smps = ht_cap->cap & IEEE80211_HT_CAP_SM_PS;
2561dd4f32aeSBjoern A. Zeeb 		smps >>= IEEE80211_HT_CAP_SM_PS_SHIFT;
2562dd4f32aeSBjoern A. Zeeb 	} else {
2563dd4f32aeSBjoern A. Zeeb 		smps = le16_get_bits(sta->deflink.he_6ghz_capa.capa,
2564dd4f32aeSBjoern A. Zeeb 				     IEEE80211_HE_6GHZ_CAP_SM_PS);
2565dd4f32aeSBjoern A. Zeeb 	}
2566dd4f32aeSBjoern A. Zeeb 
2567dd4f32aeSBjoern A. Zeeb 	switch (smps) {
2568dd4f32aeSBjoern A. Zeeb 	case WLAN_HT_CAP_SM_PS_STATIC:
2569dd4f32aeSBjoern A. Zeeb 		arg->static_mimops_flag = true;
2570dd4f32aeSBjoern A. Zeeb 		break;
2571dd4f32aeSBjoern A. Zeeb 	case WLAN_HT_CAP_SM_PS_DYNAMIC:
2572dd4f32aeSBjoern A. Zeeb 		arg->dynamic_mimops_flag = true;
2573dd4f32aeSBjoern A. Zeeb 		break;
2574dd4f32aeSBjoern A. Zeeb 	case WLAN_HT_CAP_SM_PS_DISABLED:
2575dd4f32aeSBjoern A. Zeeb 		arg->spatial_mux_flag = true;
2576dd4f32aeSBjoern A. Zeeb 		break;
2577dd4f32aeSBjoern A. Zeeb 	default:
2578dd4f32aeSBjoern A. Zeeb 		break;
2579dd4f32aeSBjoern A. Zeeb 	}
2580dd4f32aeSBjoern A. Zeeb }
2581dd4f32aeSBjoern A. Zeeb 
ath11k_peer_assoc_h_qos(struct ath11k * ar,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct peer_assoc_params * arg)2582dd4f32aeSBjoern A. Zeeb static void ath11k_peer_assoc_h_qos(struct ath11k *ar,
2583dd4f32aeSBjoern A. Zeeb 				    struct ieee80211_vif *vif,
2584dd4f32aeSBjoern A. Zeeb 				    struct ieee80211_sta *sta,
2585dd4f32aeSBjoern A. Zeeb 				    struct peer_assoc_params *arg)
2586dd4f32aeSBjoern A. Zeeb {
2587dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif = (void *)vif->drv_priv;
2588dd4f32aeSBjoern A. Zeeb 
2589dd4f32aeSBjoern A. Zeeb 	switch (arvif->vdev_type) {
2590dd4f32aeSBjoern A. Zeeb 	case WMI_VDEV_TYPE_AP:
2591dd4f32aeSBjoern A. Zeeb 		if (sta->wme) {
2592dd4f32aeSBjoern A. Zeeb 			/* TODO: Check WME vs QoS */
2593dd4f32aeSBjoern A. Zeeb 			arg->is_wme_set = true;
2594dd4f32aeSBjoern A. Zeeb 			arg->qos_flag = true;
2595dd4f32aeSBjoern A. Zeeb 		}
2596dd4f32aeSBjoern A. Zeeb 
2597dd4f32aeSBjoern A. Zeeb 		if (sta->wme && sta->uapsd_queues) {
2598dd4f32aeSBjoern A. Zeeb 			/* TODO: Check WME vs QoS */
2599dd4f32aeSBjoern A. Zeeb 			arg->is_wme_set = true;
2600dd4f32aeSBjoern A. Zeeb 			arg->apsd_flag = true;
2601dd4f32aeSBjoern A. Zeeb 			arg->peer_rate_caps |= WMI_HOST_RC_UAPSD_FLAG;
2602dd4f32aeSBjoern A. Zeeb 		}
2603dd4f32aeSBjoern A. Zeeb 		break;
2604dd4f32aeSBjoern A. Zeeb 	case WMI_VDEV_TYPE_STA:
2605dd4f32aeSBjoern A. Zeeb 		if (sta->wme) {
2606dd4f32aeSBjoern A. Zeeb 			arg->is_wme_set = true;
2607dd4f32aeSBjoern A. Zeeb 			arg->qos_flag = true;
2608dd4f32aeSBjoern A. Zeeb 		}
2609dd4f32aeSBjoern A. Zeeb 		break;
2610dd4f32aeSBjoern A. Zeeb 	default:
2611dd4f32aeSBjoern A. Zeeb 		break;
2612dd4f32aeSBjoern A. Zeeb 	}
2613dd4f32aeSBjoern A. Zeeb 
2614*28348caeSBjoern A. Zeeb 	ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "peer %pM qos %d\n",
2615dd4f32aeSBjoern A. Zeeb 		   sta->addr, arg->qos_flag);
2616dd4f32aeSBjoern A. Zeeb }
2617dd4f32aeSBjoern A. Zeeb 
ath11k_peer_assoc_qos_ap(struct ath11k * ar,struct ath11k_vif * arvif,struct ieee80211_sta * sta)2618dd4f32aeSBjoern A. Zeeb static int ath11k_peer_assoc_qos_ap(struct ath11k *ar,
2619dd4f32aeSBjoern A. Zeeb 				    struct ath11k_vif *arvif,
2620dd4f32aeSBjoern A. Zeeb 				    struct ieee80211_sta *sta)
2621dd4f32aeSBjoern A. Zeeb {
2622dd4f32aeSBjoern A. Zeeb 	struct ap_ps_params params;
2623dd4f32aeSBjoern A. Zeeb 	u32 max_sp;
2624dd4f32aeSBjoern A. Zeeb 	u32 uapsd;
2625dd4f32aeSBjoern A. Zeeb 	int ret;
2626dd4f32aeSBjoern A. Zeeb 
2627dd4f32aeSBjoern A. Zeeb 	lockdep_assert_held(&ar->conf_mutex);
2628dd4f32aeSBjoern A. Zeeb 
2629dd4f32aeSBjoern A. Zeeb 	params.vdev_id = arvif->vdev_id;
2630dd4f32aeSBjoern A. Zeeb 
2631*28348caeSBjoern A. Zeeb 	ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "uapsd_queues 0x%x max_sp %d\n",
2632dd4f32aeSBjoern A. Zeeb 		   sta->uapsd_queues, sta->max_sp);
2633dd4f32aeSBjoern A. Zeeb 
2634dd4f32aeSBjoern A. Zeeb 	uapsd = 0;
2635dd4f32aeSBjoern A. Zeeb 	if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO)
2636dd4f32aeSBjoern A. Zeeb 		uapsd |= WMI_AP_PS_UAPSD_AC3_DELIVERY_EN |
2637dd4f32aeSBjoern A. Zeeb 			 WMI_AP_PS_UAPSD_AC3_TRIGGER_EN;
2638dd4f32aeSBjoern A. Zeeb 	if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VI)
2639dd4f32aeSBjoern A. Zeeb 		uapsd |= WMI_AP_PS_UAPSD_AC2_DELIVERY_EN |
2640dd4f32aeSBjoern A. Zeeb 			 WMI_AP_PS_UAPSD_AC2_TRIGGER_EN;
2641dd4f32aeSBjoern A. Zeeb 	if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BK)
2642dd4f32aeSBjoern A. Zeeb 		uapsd |= WMI_AP_PS_UAPSD_AC1_DELIVERY_EN |
2643dd4f32aeSBjoern A. Zeeb 			 WMI_AP_PS_UAPSD_AC1_TRIGGER_EN;
2644dd4f32aeSBjoern A. Zeeb 	if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BE)
2645dd4f32aeSBjoern A. Zeeb 		uapsd |= WMI_AP_PS_UAPSD_AC0_DELIVERY_EN |
2646dd4f32aeSBjoern A. Zeeb 			 WMI_AP_PS_UAPSD_AC0_TRIGGER_EN;
2647dd4f32aeSBjoern A. Zeeb 
2648dd4f32aeSBjoern A. Zeeb 	max_sp = 0;
2649dd4f32aeSBjoern A. Zeeb 	if (sta->max_sp < MAX_WMI_AP_PS_PEER_PARAM_MAX_SP)
2650dd4f32aeSBjoern A. Zeeb 		max_sp = sta->max_sp;
2651dd4f32aeSBjoern A. Zeeb 
2652dd4f32aeSBjoern A. Zeeb 	params.param = WMI_AP_PS_PEER_PARAM_UAPSD;
2653dd4f32aeSBjoern A. Zeeb 	params.value = uapsd;
2654dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_send_set_ap_ps_param_cmd(ar, sta->addr, &params);
2655dd4f32aeSBjoern A. Zeeb 	if (ret)
2656dd4f32aeSBjoern A. Zeeb 		goto err;
2657dd4f32aeSBjoern A. Zeeb 
2658dd4f32aeSBjoern A. Zeeb 	params.param = WMI_AP_PS_PEER_PARAM_MAX_SP;
2659dd4f32aeSBjoern A. Zeeb 	params.value = max_sp;
2660dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_send_set_ap_ps_param_cmd(ar, sta->addr, &params);
2661dd4f32aeSBjoern A. Zeeb 	if (ret)
2662dd4f32aeSBjoern A. Zeeb 		goto err;
2663dd4f32aeSBjoern A. Zeeb 
2664dd4f32aeSBjoern A. Zeeb 	/* TODO revisit during testing */
2665dd4f32aeSBjoern A. Zeeb 	params.param = WMI_AP_PS_PEER_PARAM_SIFS_RESP_FRMTYPE;
2666dd4f32aeSBjoern A. Zeeb 	params.value = DISABLE_SIFS_RESPONSE_TRIGGER;
2667dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_send_set_ap_ps_param_cmd(ar, sta->addr, &params);
2668dd4f32aeSBjoern A. Zeeb 	if (ret)
2669dd4f32aeSBjoern A. Zeeb 		goto err;
2670dd4f32aeSBjoern A. Zeeb 
2671dd4f32aeSBjoern A. Zeeb 	params.param = WMI_AP_PS_PEER_PARAM_SIFS_RESP_UAPSD;
2672dd4f32aeSBjoern A. Zeeb 	params.value = DISABLE_SIFS_RESPONSE_TRIGGER;
2673dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_send_set_ap_ps_param_cmd(ar, sta->addr, &params);
2674dd4f32aeSBjoern A. Zeeb 	if (ret)
2675dd4f32aeSBjoern A. Zeeb 		goto err;
2676dd4f32aeSBjoern A. Zeeb 
2677dd4f32aeSBjoern A. Zeeb 	return 0;
2678dd4f32aeSBjoern A. Zeeb 
2679dd4f32aeSBjoern A. Zeeb err:
2680dd4f32aeSBjoern A. Zeeb 	ath11k_warn(ar->ab, "failed to set ap ps peer param %d for vdev %i: %d\n",
2681dd4f32aeSBjoern A. Zeeb 		    params.param, arvif->vdev_id, ret);
2682dd4f32aeSBjoern A. Zeeb 	return ret;
2683dd4f32aeSBjoern A. Zeeb }
2684dd4f32aeSBjoern A. Zeeb 
ath11k_mac_sta_has_ofdm_only(struct ieee80211_sta * sta)2685dd4f32aeSBjoern A. Zeeb static bool ath11k_mac_sta_has_ofdm_only(struct ieee80211_sta *sta)
2686dd4f32aeSBjoern A. Zeeb {
2687dd4f32aeSBjoern A. Zeeb 	return sta->deflink.supp_rates[NL80211_BAND_2GHZ] >>
2688dd4f32aeSBjoern A. Zeeb 	       ATH11K_MAC_FIRST_OFDM_RATE_IDX;
2689dd4f32aeSBjoern A. Zeeb }
2690dd4f32aeSBjoern A. Zeeb 
ath11k_mac_get_phymode_vht(struct ath11k * ar,struct ieee80211_sta * sta)2691dd4f32aeSBjoern A. Zeeb static enum wmi_phy_mode ath11k_mac_get_phymode_vht(struct ath11k *ar,
2692dd4f32aeSBjoern A. Zeeb 						    struct ieee80211_sta *sta)
2693dd4f32aeSBjoern A. Zeeb {
2694dd4f32aeSBjoern A. Zeeb 	if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) {
2695dd4f32aeSBjoern A. Zeeb 		switch (sta->deflink.vht_cap.cap &
2696dd4f32aeSBjoern A. Zeeb 			IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) {
2697dd4f32aeSBjoern A. Zeeb 		case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ:
2698dd4f32aeSBjoern A. Zeeb 			return MODE_11AC_VHT160;
2699dd4f32aeSBjoern A. Zeeb 		case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ:
2700dd4f32aeSBjoern A. Zeeb 			return MODE_11AC_VHT80_80;
2701dd4f32aeSBjoern A. Zeeb 		default:
2702dd4f32aeSBjoern A. Zeeb 			/* not sure if this is a valid case? */
2703dd4f32aeSBjoern A. Zeeb 			return MODE_11AC_VHT160;
2704dd4f32aeSBjoern A. Zeeb 		}
2705dd4f32aeSBjoern A. Zeeb 	}
2706dd4f32aeSBjoern A. Zeeb 
2707dd4f32aeSBjoern A. Zeeb 	if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80)
2708dd4f32aeSBjoern A. Zeeb 		return MODE_11AC_VHT80;
2709dd4f32aeSBjoern A. Zeeb 
2710dd4f32aeSBjoern A. Zeeb 	if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
2711dd4f32aeSBjoern A. Zeeb 		return MODE_11AC_VHT40;
2712dd4f32aeSBjoern A. Zeeb 
2713dd4f32aeSBjoern A. Zeeb 	if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_20)
2714dd4f32aeSBjoern A. Zeeb 		return MODE_11AC_VHT20;
2715dd4f32aeSBjoern A. Zeeb 
2716dd4f32aeSBjoern A. Zeeb 	return MODE_UNKNOWN;
2717dd4f32aeSBjoern A. Zeeb }
2718dd4f32aeSBjoern A. Zeeb 
ath11k_mac_get_phymode_he(struct ath11k * ar,struct ieee80211_sta * sta)2719dd4f32aeSBjoern A. Zeeb static enum wmi_phy_mode ath11k_mac_get_phymode_he(struct ath11k *ar,
2720dd4f32aeSBjoern A. Zeeb 						   struct ieee80211_sta *sta)
2721dd4f32aeSBjoern A. Zeeb {
2722dd4f32aeSBjoern A. Zeeb 	if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) {
2723dd4f32aeSBjoern A. Zeeb 		if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[0] &
2724dd4f32aeSBjoern A. Zeeb 		     IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G)
2725dd4f32aeSBjoern A. Zeeb 			return MODE_11AX_HE160;
2726dd4f32aeSBjoern A. Zeeb 		else if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[0] &
2727dd4f32aeSBjoern A. Zeeb 			 IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)
2728dd4f32aeSBjoern A. Zeeb 			return MODE_11AX_HE80_80;
2729dd4f32aeSBjoern A. Zeeb 		/* not sure if this is a valid case? */
2730dd4f32aeSBjoern A. Zeeb 		return MODE_11AX_HE160;
2731dd4f32aeSBjoern A. Zeeb 	}
2732dd4f32aeSBjoern A. Zeeb 
2733dd4f32aeSBjoern A. Zeeb 	if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80)
2734dd4f32aeSBjoern A. Zeeb 		return MODE_11AX_HE80;
2735dd4f32aeSBjoern A. Zeeb 
2736dd4f32aeSBjoern A. Zeeb 	if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
2737dd4f32aeSBjoern A. Zeeb 		return MODE_11AX_HE40;
2738dd4f32aeSBjoern A. Zeeb 
2739dd4f32aeSBjoern A. Zeeb 	if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_20)
2740dd4f32aeSBjoern A. Zeeb 		return MODE_11AX_HE20;
2741dd4f32aeSBjoern A. Zeeb 
2742dd4f32aeSBjoern A. Zeeb 	return MODE_UNKNOWN;
2743dd4f32aeSBjoern A. Zeeb }
2744dd4f32aeSBjoern A. Zeeb 
ath11k_peer_assoc_h_phymode(struct ath11k * ar,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct peer_assoc_params * arg)2745dd4f32aeSBjoern A. Zeeb static void ath11k_peer_assoc_h_phymode(struct ath11k *ar,
2746dd4f32aeSBjoern A. Zeeb 					struct ieee80211_vif *vif,
2747dd4f32aeSBjoern A. Zeeb 					struct ieee80211_sta *sta,
2748dd4f32aeSBjoern A. Zeeb 					struct peer_assoc_params *arg)
2749dd4f32aeSBjoern A. Zeeb {
2750dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif = (void *)vif->drv_priv;
2751dd4f32aeSBjoern A. Zeeb 	struct cfg80211_chan_def def;
2752dd4f32aeSBjoern A. Zeeb 	enum nl80211_band band;
2753dd4f32aeSBjoern A. Zeeb 	const u8 *ht_mcs_mask;
2754dd4f32aeSBjoern A. Zeeb 	const u16 *vht_mcs_mask;
2755dd4f32aeSBjoern A. Zeeb 	const u16 *he_mcs_mask;
2756dd4f32aeSBjoern A. Zeeb 	enum wmi_phy_mode phymode = MODE_UNKNOWN;
2757dd4f32aeSBjoern A. Zeeb 
2758dd4f32aeSBjoern A. Zeeb 	if (WARN_ON(ath11k_mac_vif_chan(vif, &def)))
2759dd4f32aeSBjoern A. Zeeb 		return;
2760dd4f32aeSBjoern A. Zeeb 
2761dd4f32aeSBjoern A. Zeeb 	band = def.chan->band;
2762dd4f32aeSBjoern A. Zeeb 	ht_mcs_mask = arvif->bitrate_mask.control[band].ht_mcs;
2763dd4f32aeSBjoern A. Zeeb 	vht_mcs_mask = arvif->bitrate_mask.control[band].vht_mcs;
2764dd4f32aeSBjoern A. Zeeb 	he_mcs_mask = arvif->bitrate_mask.control[band].he_mcs;
2765dd4f32aeSBjoern A. Zeeb 
2766dd4f32aeSBjoern A. Zeeb 	switch (band) {
2767dd4f32aeSBjoern A. Zeeb 	case NL80211_BAND_2GHZ:
2768dd4f32aeSBjoern A. Zeeb 		if (sta->deflink.he_cap.has_he &&
2769dd4f32aeSBjoern A. Zeeb 		    !ath11k_peer_assoc_h_he_masked(he_mcs_mask)) {
2770dd4f32aeSBjoern A. Zeeb 			if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80)
2771dd4f32aeSBjoern A. Zeeb 				phymode = MODE_11AX_HE80_2G;
2772dd4f32aeSBjoern A. Zeeb 			else if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
2773dd4f32aeSBjoern A. Zeeb 				phymode = MODE_11AX_HE40_2G;
2774dd4f32aeSBjoern A. Zeeb 			else
2775dd4f32aeSBjoern A. Zeeb 				phymode = MODE_11AX_HE20_2G;
2776dd4f32aeSBjoern A. Zeeb 		} else if (sta->deflink.vht_cap.vht_supported &&
2777dd4f32aeSBjoern A. Zeeb 			   !ath11k_peer_assoc_h_vht_masked(vht_mcs_mask)) {
2778dd4f32aeSBjoern A. Zeeb 			if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
2779dd4f32aeSBjoern A. Zeeb 				phymode = MODE_11AC_VHT40;
2780dd4f32aeSBjoern A. Zeeb 			else
2781dd4f32aeSBjoern A. Zeeb 				phymode = MODE_11AC_VHT20;
2782dd4f32aeSBjoern A. Zeeb 		} else if (sta->deflink.ht_cap.ht_supported &&
2783dd4f32aeSBjoern A. Zeeb 			   !ath11k_peer_assoc_h_ht_masked(ht_mcs_mask)) {
2784dd4f32aeSBjoern A. Zeeb 			if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
2785dd4f32aeSBjoern A. Zeeb 				phymode = MODE_11NG_HT40;
2786dd4f32aeSBjoern A. Zeeb 			else
2787dd4f32aeSBjoern A. Zeeb 				phymode = MODE_11NG_HT20;
2788dd4f32aeSBjoern A. Zeeb 		} else if (ath11k_mac_sta_has_ofdm_only(sta)) {
2789dd4f32aeSBjoern A. Zeeb 			phymode = MODE_11G;
2790dd4f32aeSBjoern A. Zeeb 		} else {
2791dd4f32aeSBjoern A. Zeeb 			phymode = MODE_11B;
2792dd4f32aeSBjoern A. Zeeb 		}
2793dd4f32aeSBjoern A. Zeeb 		break;
2794dd4f32aeSBjoern A. Zeeb 	case NL80211_BAND_5GHZ:
2795dd4f32aeSBjoern A. Zeeb 	case NL80211_BAND_6GHZ:
2796dd4f32aeSBjoern A. Zeeb 		/* Check HE first */
2797dd4f32aeSBjoern A. Zeeb 		if (sta->deflink.he_cap.has_he &&
2798dd4f32aeSBjoern A. Zeeb 		    !ath11k_peer_assoc_h_he_masked(he_mcs_mask)) {
2799dd4f32aeSBjoern A. Zeeb 			phymode = ath11k_mac_get_phymode_he(ar, sta);
2800dd4f32aeSBjoern A. Zeeb 		} else if (sta->deflink.vht_cap.vht_supported &&
2801dd4f32aeSBjoern A. Zeeb 			   !ath11k_peer_assoc_h_vht_masked(vht_mcs_mask)) {
2802dd4f32aeSBjoern A. Zeeb 			phymode = ath11k_mac_get_phymode_vht(ar, sta);
2803dd4f32aeSBjoern A. Zeeb 		} else if (sta->deflink.ht_cap.ht_supported &&
2804dd4f32aeSBjoern A. Zeeb 			   !ath11k_peer_assoc_h_ht_masked(ht_mcs_mask)) {
2805dd4f32aeSBjoern A. Zeeb 			if (sta->deflink.bandwidth >= IEEE80211_STA_RX_BW_40)
2806dd4f32aeSBjoern A. Zeeb 				phymode = MODE_11NA_HT40;
2807dd4f32aeSBjoern A. Zeeb 			else
2808dd4f32aeSBjoern A. Zeeb 				phymode = MODE_11NA_HT20;
2809dd4f32aeSBjoern A. Zeeb 		} else {
2810dd4f32aeSBjoern A. Zeeb 			phymode = MODE_11A;
2811dd4f32aeSBjoern A. Zeeb 		}
2812dd4f32aeSBjoern A. Zeeb 		break;
2813dd4f32aeSBjoern A. Zeeb 	default:
2814dd4f32aeSBjoern A. Zeeb 		break;
2815dd4f32aeSBjoern A. Zeeb 	}
2816dd4f32aeSBjoern A. Zeeb 
2817*28348caeSBjoern A. Zeeb 	ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "peer %pM phymode %s\n",
2818dd4f32aeSBjoern A. Zeeb 		   sta->addr, ath11k_wmi_phymode_str(phymode));
2819dd4f32aeSBjoern A. Zeeb 
2820dd4f32aeSBjoern A. Zeeb 	arg->peer_phymode = phymode;
2821dd4f32aeSBjoern A. Zeeb 	WARN_ON(phymode == MODE_UNKNOWN);
2822dd4f32aeSBjoern A. Zeeb }
2823dd4f32aeSBjoern A. Zeeb 
ath11k_peer_assoc_prepare(struct ath11k * ar,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct peer_assoc_params * arg,bool reassoc)2824dd4f32aeSBjoern A. Zeeb static void ath11k_peer_assoc_prepare(struct ath11k *ar,
2825dd4f32aeSBjoern A. Zeeb 				      struct ieee80211_vif *vif,
2826dd4f32aeSBjoern A. Zeeb 				      struct ieee80211_sta *sta,
2827dd4f32aeSBjoern A. Zeeb 				      struct peer_assoc_params *arg,
2828dd4f32aeSBjoern A. Zeeb 				      bool reassoc)
2829dd4f32aeSBjoern A. Zeeb {
2830dd4f32aeSBjoern A. Zeeb 	struct ath11k_sta *arsta;
2831dd4f32aeSBjoern A. Zeeb 
2832dd4f32aeSBjoern A. Zeeb 	lockdep_assert_held(&ar->conf_mutex);
2833dd4f32aeSBjoern A. Zeeb 
2834dd4f32aeSBjoern A. Zeeb 	arsta = (struct ath11k_sta *)sta->drv_priv;
2835dd4f32aeSBjoern A. Zeeb 
2836dd4f32aeSBjoern A. Zeeb 	memset(arg, 0, sizeof(*arg));
2837dd4f32aeSBjoern A. Zeeb 
2838dd4f32aeSBjoern A. Zeeb 	reinit_completion(&ar->peer_assoc_done);
2839dd4f32aeSBjoern A. Zeeb 
2840dd4f32aeSBjoern A. Zeeb 	arg->peer_new_assoc = !reassoc;
2841dd4f32aeSBjoern A. Zeeb 	ath11k_peer_assoc_h_basic(ar, vif, sta, arg);
2842dd4f32aeSBjoern A. Zeeb 	ath11k_peer_assoc_h_crypto(ar, vif, sta, arg);
2843dd4f32aeSBjoern A. Zeeb 	ath11k_peer_assoc_h_rates(ar, vif, sta, arg);
2844dd4f32aeSBjoern A. Zeeb 	ath11k_peer_assoc_h_phymode(ar, vif, sta, arg);
2845dd4f32aeSBjoern A. Zeeb 	ath11k_peer_assoc_h_ht(ar, vif, sta, arg);
2846dd4f32aeSBjoern A. Zeeb 	ath11k_peer_assoc_h_vht(ar, vif, sta, arg);
2847dd4f32aeSBjoern A. Zeeb 	ath11k_peer_assoc_h_he(ar, vif, sta, arg);
2848dd4f32aeSBjoern A. Zeeb 	ath11k_peer_assoc_h_he_6ghz(ar, vif, sta, arg);
2849dd4f32aeSBjoern A. Zeeb 	ath11k_peer_assoc_h_qos(ar, vif, sta, arg);
2850dd4f32aeSBjoern A. Zeeb 	ath11k_peer_assoc_h_smps(sta, arg);
2851dd4f32aeSBjoern A. Zeeb 
2852dd4f32aeSBjoern A. Zeeb 	arsta->peer_nss = arg->peer_nss;
2853dd4f32aeSBjoern A. Zeeb 
2854dd4f32aeSBjoern A. Zeeb 	/* TODO: amsdu_disable req? */
2855dd4f32aeSBjoern A. Zeeb }
2856dd4f32aeSBjoern A. Zeeb 
ath11k_setup_peer_smps(struct ath11k * ar,struct ath11k_vif * arvif,const u8 * addr,const struct ieee80211_sta_ht_cap * ht_cap,u16 he_6ghz_capa)2857dd4f32aeSBjoern A. Zeeb static int ath11k_setup_peer_smps(struct ath11k *ar, struct ath11k_vif *arvif,
2858dd4f32aeSBjoern A. Zeeb 				  const u8 *addr,
2859dd4f32aeSBjoern A. Zeeb 				  const struct ieee80211_sta_ht_cap *ht_cap,
2860dd4f32aeSBjoern A. Zeeb 				  u16 he_6ghz_capa)
2861dd4f32aeSBjoern A. Zeeb {
2862dd4f32aeSBjoern A. Zeeb 	int smps;
2863dd4f32aeSBjoern A. Zeeb 
2864dd4f32aeSBjoern A. Zeeb 	if (!ht_cap->ht_supported && !he_6ghz_capa)
2865dd4f32aeSBjoern A. Zeeb 		return 0;
2866dd4f32aeSBjoern A. Zeeb 
2867dd4f32aeSBjoern A. Zeeb 	if (ht_cap->ht_supported) {
2868dd4f32aeSBjoern A. Zeeb 		smps = ht_cap->cap & IEEE80211_HT_CAP_SM_PS;
2869dd4f32aeSBjoern A. Zeeb 		smps >>= IEEE80211_HT_CAP_SM_PS_SHIFT;
2870dd4f32aeSBjoern A. Zeeb 	} else {
2871dd4f32aeSBjoern A. Zeeb 		smps = FIELD_GET(IEEE80211_HE_6GHZ_CAP_SM_PS, he_6ghz_capa);
2872dd4f32aeSBjoern A. Zeeb 	}
2873dd4f32aeSBjoern A. Zeeb 
2874dd4f32aeSBjoern A. Zeeb 	if (smps >= ARRAY_SIZE(ath11k_smps_map))
2875dd4f32aeSBjoern A. Zeeb 		return -EINVAL;
2876dd4f32aeSBjoern A. Zeeb 
2877dd4f32aeSBjoern A. Zeeb 	return ath11k_wmi_set_peer_param(ar, addr, arvif->vdev_id,
2878dd4f32aeSBjoern A. Zeeb 					 WMI_PEER_MIMO_PS_STATE,
2879dd4f32aeSBjoern A. Zeeb 					 ath11k_smps_map[smps]);
2880dd4f32aeSBjoern A. Zeeb }
2881dd4f32aeSBjoern A. Zeeb 
ath11k_mac_set_he_txbf_conf(struct ath11k_vif * arvif)2882*28348caeSBjoern A. Zeeb static bool ath11k_mac_set_he_txbf_conf(struct ath11k_vif *arvif)
2883*28348caeSBjoern A. Zeeb {
2884*28348caeSBjoern A. Zeeb 	struct ath11k *ar = arvif->ar;
2885*28348caeSBjoern A. Zeeb 	u32 param, value;
2886*28348caeSBjoern A. Zeeb 	int ret;
2887*28348caeSBjoern A. Zeeb 
2888*28348caeSBjoern A. Zeeb 	if (!arvif->vif->bss_conf.he_support)
2889*28348caeSBjoern A. Zeeb 		return true;
2890*28348caeSBjoern A. Zeeb 
2891*28348caeSBjoern A. Zeeb 	param = WMI_VDEV_PARAM_SET_HEMU_MODE;
2892*28348caeSBjoern A. Zeeb 	value = 0;
2893*28348caeSBjoern A. Zeeb 	if (arvif->vif->bss_conf.he_su_beamformer) {
2894*28348caeSBjoern A. Zeeb 		value |= FIELD_PREP(HE_MODE_SU_TX_BFER, HE_SU_BFER_ENABLE);
2895*28348caeSBjoern A. Zeeb 		if (arvif->vif->bss_conf.he_mu_beamformer &&
2896*28348caeSBjoern A. Zeeb 		    arvif->vdev_type == WMI_VDEV_TYPE_AP)
2897*28348caeSBjoern A. Zeeb 			value |= FIELD_PREP(HE_MODE_MU_TX_BFER, HE_MU_BFER_ENABLE);
2898*28348caeSBjoern A. Zeeb 	}
2899*28348caeSBjoern A. Zeeb 
2900*28348caeSBjoern A. Zeeb 	if (arvif->vif->type != NL80211_IFTYPE_MESH_POINT) {
2901*28348caeSBjoern A. Zeeb 		value |= FIELD_PREP(HE_MODE_DL_OFDMA, HE_DL_MUOFDMA_ENABLE) |
2902*28348caeSBjoern A. Zeeb 			 FIELD_PREP(HE_MODE_UL_OFDMA, HE_UL_MUOFDMA_ENABLE);
2903*28348caeSBjoern A. Zeeb 
2904*28348caeSBjoern A. Zeeb 		if (arvif->vif->bss_conf.he_full_ul_mumimo)
2905*28348caeSBjoern A. Zeeb 			value |= FIELD_PREP(HE_MODE_UL_MUMIMO, HE_UL_MUMIMO_ENABLE);
2906*28348caeSBjoern A. Zeeb 
2907*28348caeSBjoern A. Zeeb 		if (arvif->vif->bss_conf.he_su_beamformee)
2908*28348caeSBjoern A. Zeeb 			value |= FIELD_PREP(HE_MODE_SU_TX_BFEE, HE_SU_BFEE_ENABLE);
2909*28348caeSBjoern A. Zeeb 	}
2910*28348caeSBjoern A. Zeeb 
2911*28348caeSBjoern A. Zeeb 	ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, param, value);
2912*28348caeSBjoern A. Zeeb 	if (ret) {
2913*28348caeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to set vdev %d HE MU mode: %d\n",
2914*28348caeSBjoern A. Zeeb 			    arvif->vdev_id, ret);
2915*28348caeSBjoern A. Zeeb 		return false;
2916*28348caeSBjoern A. Zeeb 	}
2917*28348caeSBjoern A. Zeeb 
2918*28348caeSBjoern A. Zeeb 	param = WMI_VDEV_PARAM_SET_HE_SOUNDING_MODE;
2919*28348caeSBjoern A. Zeeb 	value =	FIELD_PREP(HE_VHT_SOUNDING_MODE, HE_VHT_SOUNDING_MODE_ENABLE) |
2920*28348caeSBjoern A. Zeeb 		FIELD_PREP(HE_TRIG_NONTRIG_SOUNDING_MODE,
2921*28348caeSBjoern A. Zeeb 			   HE_TRIG_NONTRIG_SOUNDING_MODE_ENABLE);
2922*28348caeSBjoern A. Zeeb 	ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
2923*28348caeSBjoern A. Zeeb 					    param, value);
2924*28348caeSBjoern A. Zeeb 	if (ret) {
2925*28348caeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to set vdev %d sounding mode: %d\n",
2926*28348caeSBjoern A. Zeeb 			    arvif->vdev_id, ret);
2927*28348caeSBjoern A. Zeeb 		return false;
2928*28348caeSBjoern A. Zeeb 	}
2929*28348caeSBjoern A. Zeeb 	return true;
2930*28348caeSBjoern A. Zeeb }
2931*28348caeSBjoern A. Zeeb 
ath11k_mac_vif_recalc_sta_he_txbf(struct ath11k * ar,struct ieee80211_vif * vif,struct ieee80211_sta_he_cap * he_cap)2932*28348caeSBjoern A. Zeeb static bool ath11k_mac_vif_recalc_sta_he_txbf(struct ath11k *ar,
2933*28348caeSBjoern A. Zeeb 					      struct ieee80211_vif *vif,
2934*28348caeSBjoern A. Zeeb 					      struct ieee80211_sta_he_cap *he_cap)
2935*28348caeSBjoern A. Zeeb {
2936*28348caeSBjoern A. Zeeb 	struct ath11k_vif *arvif = (void *)vif->drv_priv;
2937*28348caeSBjoern A. Zeeb 	struct ieee80211_he_cap_elem he_cap_elem = {0};
2938*28348caeSBjoern A. Zeeb 	struct ieee80211_sta_he_cap *cap_band = NULL;
2939*28348caeSBjoern A. Zeeb 	struct cfg80211_chan_def def;
2940*28348caeSBjoern A. Zeeb 	u32 param = WMI_VDEV_PARAM_SET_HEMU_MODE;
2941*28348caeSBjoern A. Zeeb 	u32 hemode = 0;
2942*28348caeSBjoern A. Zeeb 	int ret;
2943*28348caeSBjoern A. Zeeb 
2944*28348caeSBjoern A. Zeeb 	if (!vif->bss_conf.he_support)
2945*28348caeSBjoern A. Zeeb 		return true;
2946*28348caeSBjoern A. Zeeb 
2947*28348caeSBjoern A. Zeeb 	if (vif->type != NL80211_IFTYPE_STATION)
2948*28348caeSBjoern A. Zeeb 		return false;
2949*28348caeSBjoern A. Zeeb 
2950*28348caeSBjoern A. Zeeb 	if (WARN_ON(ath11k_mac_vif_chan(vif, &def)))
2951*28348caeSBjoern A. Zeeb 		return false;
2952*28348caeSBjoern A. Zeeb 
2953*28348caeSBjoern A. Zeeb 	if (def.chan->band == NL80211_BAND_2GHZ)
2954*28348caeSBjoern A. Zeeb 		cap_band = &ar->mac.iftype[NL80211_BAND_2GHZ][vif->type].he_cap;
2955*28348caeSBjoern A. Zeeb 	else
2956*28348caeSBjoern A. Zeeb 		cap_band = &ar->mac.iftype[NL80211_BAND_5GHZ][vif->type].he_cap;
2957*28348caeSBjoern A. Zeeb 
2958*28348caeSBjoern A. Zeeb 	memcpy(&he_cap_elem, &cap_band->he_cap_elem, sizeof(he_cap_elem));
2959*28348caeSBjoern A. Zeeb 
2960*28348caeSBjoern A. Zeeb 	if (HECAP_PHY_SUBFME_GET(he_cap_elem.phy_cap_info)) {
2961*28348caeSBjoern A. Zeeb 		if (HECAP_PHY_SUBFMR_GET(he_cap->he_cap_elem.phy_cap_info))
2962*28348caeSBjoern A. Zeeb 			hemode |= FIELD_PREP(HE_MODE_SU_TX_BFEE, HE_SU_BFEE_ENABLE);
2963*28348caeSBjoern A. Zeeb 		if (HECAP_PHY_MUBFMR_GET(he_cap->he_cap_elem.phy_cap_info))
2964*28348caeSBjoern A. Zeeb 			hemode |= FIELD_PREP(HE_MODE_MU_TX_BFEE, HE_MU_BFEE_ENABLE);
2965*28348caeSBjoern A. Zeeb 	}
2966*28348caeSBjoern A. Zeeb 
2967*28348caeSBjoern A. Zeeb 	if (vif->type != NL80211_IFTYPE_MESH_POINT) {
2968*28348caeSBjoern A. Zeeb 		hemode |= FIELD_PREP(HE_MODE_DL_OFDMA, HE_DL_MUOFDMA_ENABLE) |
2969*28348caeSBjoern A. Zeeb 			  FIELD_PREP(HE_MODE_UL_OFDMA, HE_UL_MUOFDMA_ENABLE);
2970*28348caeSBjoern A. Zeeb 
2971*28348caeSBjoern A. Zeeb 		if (HECAP_PHY_ULMUMIMO_GET(he_cap_elem.phy_cap_info))
2972*28348caeSBjoern A. Zeeb 			if (HECAP_PHY_ULMUMIMO_GET(he_cap->he_cap_elem.phy_cap_info))
2973*28348caeSBjoern A. Zeeb 				hemode |= FIELD_PREP(HE_MODE_UL_MUMIMO,
2974*28348caeSBjoern A. Zeeb 						     HE_UL_MUMIMO_ENABLE);
2975*28348caeSBjoern A. Zeeb 
2976*28348caeSBjoern A. Zeeb 		if (FIELD_GET(HE_MODE_MU_TX_BFEE, hemode))
2977*28348caeSBjoern A. Zeeb 			hemode |= FIELD_PREP(HE_MODE_SU_TX_BFEE, HE_SU_BFEE_ENABLE);
2978*28348caeSBjoern A. Zeeb 
2979*28348caeSBjoern A. Zeeb 		if (FIELD_GET(HE_MODE_MU_TX_BFER, hemode))
2980*28348caeSBjoern A. Zeeb 			hemode |= FIELD_PREP(HE_MODE_SU_TX_BFER, HE_SU_BFER_ENABLE);
2981*28348caeSBjoern A. Zeeb 	}
2982*28348caeSBjoern A. Zeeb 
2983*28348caeSBjoern A. Zeeb 	ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, param, hemode);
2984*28348caeSBjoern A. Zeeb 	if (ret) {
2985*28348caeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to submit vdev param txbf 0x%x: %d\n",
2986*28348caeSBjoern A. Zeeb 			    hemode, ret);
2987*28348caeSBjoern A. Zeeb 		return false;
2988*28348caeSBjoern A. Zeeb 	}
2989*28348caeSBjoern A. Zeeb 
2990*28348caeSBjoern A. Zeeb 	return true;
2991*28348caeSBjoern A. Zeeb }
2992*28348caeSBjoern A. Zeeb 
ath11k_bss_assoc(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_bss_conf * bss_conf)2993dd4f32aeSBjoern A. Zeeb static void ath11k_bss_assoc(struct ieee80211_hw *hw,
2994dd4f32aeSBjoern A. Zeeb 			     struct ieee80211_vif *vif,
2995dd4f32aeSBjoern A. Zeeb 			     struct ieee80211_bss_conf *bss_conf)
2996dd4f32aeSBjoern A. Zeeb {
2997dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = hw->priv;
2998dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif = (void *)vif->drv_priv;
2999dd4f32aeSBjoern A. Zeeb 	struct peer_assoc_params peer_arg;
3000dd4f32aeSBjoern A. Zeeb 	struct ieee80211_sta *ap_sta;
3001dd4f32aeSBjoern A. Zeeb 	struct ath11k_peer *peer;
3002dd4f32aeSBjoern A. Zeeb 	bool is_auth = false;
3003*28348caeSBjoern A. Zeeb 	struct ieee80211_sta_he_cap  he_cap;
3004dd4f32aeSBjoern A. Zeeb 	int ret;
3005dd4f32aeSBjoern A. Zeeb 
3006dd4f32aeSBjoern A. Zeeb 	lockdep_assert_held(&ar->conf_mutex);
3007dd4f32aeSBjoern A. Zeeb 
3008*28348caeSBjoern A. Zeeb 	ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev %i assoc bssid %pM aid %d\n",
3009dd4f32aeSBjoern A. Zeeb 		   arvif->vdev_id, arvif->bssid, arvif->aid);
3010dd4f32aeSBjoern A. Zeeb 
3011dd4f32aeSBjoern A. Zeeb 	rcu_read_lock();
3012dd4f32aeSBjoern A. Zeeb 
3013dd4f32aeSBjoern A. Zeeb 	ap_sta = ieee80211_find_sta(vif, bss_conf->bssid);
3014dd4f32aeSBjoern A. Zeeb 	if (!ap_sta) {
3015dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to find station entry for bss %pM vdev %i\n",
3016dd4f32aeSBjoern A. Zeeb 			    bss_conf->bssid, arvif->vdev_id);
3017dd4f32aeSBjoern A. Zeeb 		rcu_read_unlock();
3018dd4f32aeSBjoern A. Zeeb 		return;
3019dd4f32aeSBjoern A. Zeeb 	}
3020dd4f32aeSBjoern A. Zeeb 
3021*28348caeSBjoern A. Zeeb 	/* he_cap here is updated at assoc success for sta mode only */
3022*28348caeSBjoern A. Zeeb 	he_cap  = ap_sta->deflink.he_cap;
3023*28348caeSBjoern A. Zeeb 
3024dd4f32aeSBjoern A. Zeeb 	ath11k_peer_assoc_prepare(ar, vif, ap_sta, &peer_arg, false);
3025dd4f32aeSBjoern A. Zeeb 
3026dd4f32aeSBjoern A. Zeeb 	rcu_read_unlock();
3027dd4f32aeSBjoern A. Zeeb 
3028dd4f32aeSBjoern A. Zeeb 	peer_arg.is_assoc = true;
3029dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_send_peer_assoc_cmd(ar, &peer_arg);
3030dd4f32aeSBjoern A. Zeeb 	if (ret) {
3031dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to run peer assoc for %pM vdev %i: %d\n",
3032dd4f32aeSBjoern A. Zeeb 			    bss_conf->bssid, arvif->vdev_id, ret);
3033dd4f32aeSBjoern A. Zeeb 		return;
3034dd4f32aeSBjoern A. Zeeb 	}
3035dd4f32aeSBjoern A. Zeeb 
3036dd4f32aeSBjoern A. Zeeb 	if (!wait_for_completion_timeout(&ar->peer_assoc_done, 1 * HZ)) {
3037dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to get peer assoc conf event for %pM vdev %i\n",
3038dd4f32aeSBjoern A. Zeeb 			    bss_conf->bssid, arvif->vdev_id);
3039dd4f32aeSBjoern A. Zeeb 		return;
3040dd4f32aeSBjoern A. Zeeb 	}
3041dd4f32aeSBjoern A. Zeeb 
3042dd4f32aeSBjoern A. Zeeb 	ret = ath11k_setup_peer_smps(ar, arvif, bss_conf->bssid,
3043dd4f32aeSBjoern A. Zeeb 				     &ap_sta->deflink.ht_cap,
3044dd4f32aeSBjoern A. Zeeb 				     le16_to_cpu(ap_sta->deflink.he_6ghz_capa.capa));
3045dd4f32aeSBjoern A. Zeeb 	if (ret) {
3046dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to setup peer SMPS for vdev %d: %d\n",
3047dd4f32aeSBjoern A. Zeeb 			    arvif->vdev_id, ret);
3048dd4f32aeSBjoern A. Zeeb 		return;
3049dd4f32aeSBjoern A. Zeeb 	}
3050dd4f32aeSBjoern A. Zeeb 
3051*28348caeSBjoern A. Zeeb 	if (!ath11k_mac_vif_recalc_sta_he_txbf(ar, vif, &he_cap)) {
3052*28348caeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to recalc he txbf for vdev %i on bss %pM\n",
3053*28348caeSBjoern A. Zeeb 			    arvif->vdev_id, bss_conf->bssid);
3054*28348caeSBjoern A. Zeeb 		return;
3055*28348caeSBjoern A. Zeeb 	}
3056*28348caeSBjoern A. Zeeb 
3057dd4f32aeSBjoern A. Zeeb 	WARN_ON(arvif->is_up);
3058dd4f32aeSBjoern A. Zeeb 
3059*28348caeSBjoern A. Zeeb 	arvif->aid = vif->cfg.aid;
3060dd4f32aeSBjoern A. Zeeb 	ether_addr_copy(arvif->bssid, bss_conf->bssid);
3061dd4f32aeSBjoern A. Zeeb 
3062*28348caeSBjoern A. Zeeb 	ret = ath11k_wmi_vdev_up(ar, arvif->vdev_id, arvif->aid, arvif->bssid,
3063*28348caeSBjoern A. Zeeb 				 NULL, 0, 0);
3064dd4f32aeSBjoern A. Zeeb 	if (ret) {
3065dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to set vdev %d up: %d\n",
3066dd4f32aeSBjoern A. Zeeb 			    arvif->vdev_id, ret);
3067dd4f32aeSBjoern A. Zeeb 		return;
3068dd4f32aeSBjoern A. Zeeb 	}
3069dd4f32aeSBjoern A. Zeeb 
3070dd4f32aeSBjoern A. Zeeb 	arvif->is_up = true;
3071*28348caeSBjoern A. Zeeb 	arvif->rekey_data.enable_offload = false;
3072dd4f32aeSBjoern A. Zeeb 
3073dd4f32aeSBjoern A. Zeeb 	ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
3074*28348caeSBjoern A. Zeeb 		   "vdev %d up (associated) bssid %pM aid %d\n",
3075*28348caeSBjoern A. Zeeb 		   arvif->vdev_id, bss_conf->bssid, vif->cfg.aid);
3076dd4f32aeSBjoern A. Zeeb 
3077dd4f32aeSBjoern A. Zeeb 	spin_lock_bh(&ar->ab->base_lock);
3078dd4f32aeSBjoern A. Zeeb 
3079dd4f32aeSBjoern A. Zeeb 	peer = ath11k_peer_find(ar->ab, arvif->vdev_id, arvif->bssid);
3080dd4f32aeSBjoern A. Zeeb 	if (peer && peer->is_authorized)
3081dd4f32aeSBjoern A. Zeeb 		is_auth = true;
3082dd4f32aeSBjoern A. Zeeb 
3083dd4f32aeSBjoern A. Zeeb 	spin_unlock_bh(&ar->ab->base_lock);
3084dd4f32aeSBjoern A. Zeeb 
3085dd4f32aeSBjoern A. Zeeb 	if (is_auth) {
3086dd4f32aeSBjoern A. Zeeb 		ret = ath11k_wmi_set_peer_param(ar, arvif->bssid,
3087dd4f32aeSBjoern A. Zeeb 						arvif->vdev_id,
3088dd4f32aeSBjoern A. Zeeb 						WMI_PEER_AUTHORIZE,
3089dd4f32aeSBjoern A. Zeeb 						1);
3090dd4f32aeSBjoern A. Zeeb 		if (ret)
3091dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "Unable to authorize BSS peer: %d\n", ret);
3092dd4f32aeSBjoern A. Zeeb 	}
3093dd4f32aeSBjoern A. Zeeb 
3094dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_send_obss_spr_cmd(ar, arvif->vdev_id,
3095dd4f32aeSBjoern A. Zeeb 					   &bss_conf->he_obss_pd);
3096dd4f32aeSBjoern A. Zeeb 	if (ret)
3097dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to set vdev %i OBSS PD parameters: %d\n",
3098dd4f32aeSBjoern A. Zeeb 			    arvif->vdev_id, ret);
3099dd4f32aeSBjoern A. Zeeb 
3100dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
3101dd4f32aeSBjoern A. Zeeb 					    WMI_VDEV_PARAM_DTIM_POLICY,
3102dd4f32aeSBjoern A. Zeeb 					    WMI_DTIM_POLICY_STICK);
3103dd4f32aeSBjoern A. Zeeb 	if (ret)
3104dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to set vdev %d dtim policy: %d\n",
3105dd4f32aeSBjoern A. Zeeb 			    arvif->vdev_id, ret);
3106dd4f32aeSBjoern A. Zeeb 
3107dd4f32aeSBjoern A. Zeeb 	ath11k_mac_11d_scan_stop_all(ar->ab);
3108dd4f32aeSBjoern A. Zeeb }
3109dd4f32aeSBjoern A. Zeeb 
ath11k_bss_disassoc(struct ieee80211_hw * hw,struct ieee80211_vif * vif)3110dd4f32aeSBjoern A. Zeeb static void ath11k_bss_disassoc(struct ieee80211_hw *hw,
3111dd4f32aeSBjoern A. Zeeb 				struct ieee80211_vif *vif)
3112dd4f32aeSBjoern A. Zeeb {
3113dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = hw->priv;
3114dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif = (void *)vif->drv_priv;
3115dd4f32aeSBjoern A. Zeeb 	int ret;
3116dd4f32aeSBjoern A. Zeeb 
3117dd4f32aeSBjoern A. Zeeb 	lockdep_assert_held(&ar->conf_mutex);
3118dd4f32aeSBjoern A. Zeeb 
3119*28348caeSBjoern A. Zeeb 	ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev %i disassoc bssid %pM\n",
3120dd4f32aeSBjoern A. Zeeb 		   arvif->vdev_id, arvif->bssid);
3121dd4f32aeSBjoern A. Zeeb 
3122dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_vdev_down(ar, arvif->vdev_id);
3123dd4f32aeSBjoern A. Zeeb 	if (ret)
3124dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to down vdev %i: %d\n",
3125dd4f32aeSBjoern A. Zeeb 			    arvif->vdev_id, ret);
3126dd4f32aeSBjoern A. Zeeb 
3127dd4f32aeSBjoern A. Zeeb 	arvif->is_up = false;
3128dd4f32aeSBjoern A. Zeeb 
3129*28348caeSBjoern A. Zeeb 	memset(&arvif->rekey_data, 0, sizeof(arvif->rekey_data));
3130*28348caeSBjoern A. Zeeb 
3131dd4f32aeSBjoern A. Zeeb 	cancel_delayed_work_sync(&arvif->connection_loss_work);
3132dd4f32aeSBjoern A. Zeeb }
3133dd4f32aeSBjoern A. Zeeb 
ath11k_mac_get_rate_hw_value(int bitrate)3134dd4f32aeSBjoern A. Zeeb static u32 ath11k_mac_get_rate_hw_value(int bitrate)
3135dd4f32aeSBjoern A. Zeeb {
3136dd4f32aeSBjoern A. Zeeb 	u32 preamble;
3137dd4f32aeSBjoern A. Zeeb 	u16 hw_value;
3138dd4f32aeSBjoern A. Zeeb 	int rate;
3139dd4f32aeSBjoern A. Zeeb 	size_t i;
3140dd4f32aeSBjoern A. Zeeb 
3141dd4f32aeSBjoern A. Zeeb 	if (ath11k_mac_bitrate_is_cck(bitrate))
3142dd4f32aeSBjoern A. Zeeb 		preamble = WMI_RATE_PREAMBLE_CCK;
3143dd4f32aeSBjoern A. Zeeb 	else
3144dd4f32aeSBjoern A. Zeeb 		preamble = WMI_RATE_PREAMBLE_OFDM;
3145dd4f32aeSBjoern A. Zeeb 
3146dd4f32aeSBjoern A. Zeeb 	for (i = 0; i < ARRAY_SIZE(ath11k_legacy_rates); i++) {
3147dd4f32aeSBjoern A. Zeeb 		if (ath11k_legacy_rates[i].bitrate != bitrate)
3148dd4f32aeSBjoern A. Zeeb 			continue;
3149dd4f32aeSBjoern A. Zeeb 
3150dd4f32aeSBjoern A. Zeeb 		hw_value = ath11k_legacy_rates[i].hw_value;
3151dd4f32aeSBjoern A. Zeeb 		rate = ATH11K_HW_RATE_CODE(hw_value, 0, preamble);
3152dd4f32aeSBjoern A. Zeeb 
3153dd4f32aeSBjoern A. Zeeb 		return rate;
3154dd4f32aeSBjoern A. Zeeb 	}
3155dd4f32aeSBjoern A. Zeeb 
3156dd4f32aeSBjoern A. Zeeb 	return -EINVAL;
3157dd4f32aeSBjoern A. Zeeb }
3158dd4f32aeSBjoern A. Zeeb 
ath11k_recalculate_mgmt_rate(struct ath11k * ar,struct ieee80211_vif * vif,struct cfg80211_chan_def * def)3159dd4f32aeSBjoern A. Zeeb static void ath11k_recalculate_mgmt_rate(struct ath11k *ar,
3160dd4f32aeSBjoern A. Zeeb 					 struct ieee80211_vif *vif,
3161dd4f32aeSBjoern A. Zeeb 					 struct cfg80211_chan_def *def)
3162dd4f32aeSBjoern A. Zeeb {
3163dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif = (void *)vif->drv_priv;
3164dd4f32aeSBjoern A. Zeeb 	const struct ieee80211_supported_band *sband;
3165dd4f32aeSBjoern A. Zeeb 	u8 basic_rate_idx;
3166dd4f32aeSBjoern A. Zeeb 	int hw_rate_code;
3167dd4f32aeSBjoern A. Zeeb 	u32 vdev_param;
3168dd4f32aeSBjoern A. Zeeb 	u16 bitrate;
3169dd4f32aeSBjoern A. Zeeb 	int ret;
3170dd4f32aeSBjoern A. Zeeb 
3171dd4f32aeSBjoern A. Zeeb 	lockdep_assert_held(&ar->conf_mutex);
3172dd4f32aeSBjoern A. Zeeb 
3173dd4f32aeSBjoern A. Zeeb 	sband = ar->hw->wiphy->bands[def->chan->band];
3174dd4f32aeSBjoern A. Zeeb 	basic_rate_idx = ffs(vif->bss_conf.basic_rates) - 1;
3175dd4f32aeSBjoern A. Zeeb 	bitrate = sband->bitrates[basic_rate_idx].bitrate;
3176dd4f32aeSBjoern A. Zeeb 
3177dd4f32aeSBjoern A. Zeeb 	hw_rate_code = ath11k_mac_get_rate_hw_value(bitrate);
3178dd4f32aeSBjoern A. Zeeb 	if (hw_rate_code < 0) {
3179dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "bitrate not supported %d\n", bitrate);
3180dd4f32aeSBjoern A. Zeeb 		return;
3181dd4f32aeSBjoern A. Zeeb 	}
3182dd4f32aeSBjoern A. Zeeb 
3183dd4f32aeSBjoern A. Zeeb 	vdev_param = WMI_VDEV_PARAM_MGMT_RATE;
3184dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, vdev_param,
3185dd4f32aeSBjoern A. Zeeb 					    hw_rate_code);
3186dd4f32aeSBjoern A. Zeeb 	if (ret)
3187dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to set mgmt tx rate %d\n", ret);
3188dd4f32aeSBjoern A. Zeeb 
3189dd4f32aeSBjoern A. Zeeb 	/* For WCN6855, firmware will clear this param when vdev starts, hence
3190dd4f32aeSBjoern A. Zeeb 	 * cache it here so that we can reconfigure it once vdev starts.
3191dd4f32aeSBjoern A. Zeeb 	 */
3192dd4f32aeSBjoern A. Zeeb 	ar->hw_rate_code = hw_rate_code;
3193dd4f32aeSBjoern A. Zeeb 
3194dd4f32aeSBjoern A. Zeeb 	vdev_param = WMI_VDEV_PARAM_BEACON_RATE;
3195dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, vdev_param,
3196dd4f32aeSBjoern A. Zeeb 					    hw_rate_code);
3197dd4f32aeSBjoern A. Zeeb 	if (ret)
3198dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to set beacon tx rate %d\n", ret);
3199dd4f32aeSBjoern A. Zeeb }
3200dd4f32aeSBjoern A. Zeeb 
ath11k_mac_fils_discovery(struct ath11k_vif * arvif,struct ieee80211_bss_conf * info)3201dd4f32aeSBjoern A. Zeeb static int ath11k_mac_fils_discovery(struct ath11k_vif *arvif,
3202dd4f32aeSBjoern A. Zeeb 				     struct ieee80211_bss_conf *info)
3203dd4f32aeSBjoern A. Zeeb {
3204dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = arvif->ar;
3205dd4f32aeSBjoern A. Zeeb 	struct sk_buff *tmpl;
3206dd4f32aeSBjoern A. Zeeb 	int ret;
3207dd4f32aeSBjoern A. Zeeb 	u32 interval;
3208dd4f32aeSBjoern A. Zeeb 	bool unsol_bcast_probe_resp_enabled = false;
3209dd4f32aeSBjoern A. Zeeb 
3210dd4f32aeSBjoern A. Zeeb 	if (info->fils_discovery.max_interval) {
3211dd4f32aeSBjoern A. Zeeb 		interval = info->fils_discovery.max_interval;
3212dd4f32aeSBjoern A. Zeeb 
3213dd4f32aeSBjoern A. Zeeb 		tmpl = ieee80211_get_fils_discovery_tmpl(ar->hw, arvif->vif);
3214dd4f32aeSBjoern A. Zeeb 		if (tmpl)
3215dd4f32aeSBjoern A. Zeeb 			ret = ath11k_wmi_fils_discovery_tmpl(ar, arvif->vdev_id,
3216dd4f32aeSBjoern A. Zeeb 							     tmpl);
3217dd4f32aeSBjoern A. Zeeb 	} else if (info->unsol_bcast_probe_resp_interval) {
3218dd4f32aeSBjoern A. Zeeb 		unsol_bcast_probe_resp_enabled = 1;
3219dd4f32aeSBjoern A. Zeeb 		interval = info->unsol_bcast_probe_resp_interval;
3220dd4f32aeSBjoern A. Zeeb 
3221dd4f32aeSBjoern A. Zeeb 		tmpl = ieee80211_get_unsol_bcast_probe_resp_tmpl(ar->hw,
3222dd4f32aeSBjoern A. Zeeb 								 arvif->vif);
3223dd4f32aeSBjoern A. Zeeb 		if (tmpl)
3224dd4f32aeSBjoern A. Zeeb 			ret = ath11k_wmi_probe_resp_tmpl(ar, arvif->vdev_id,
3225dd4f32aeSBjoern A. Zeeb 							 tmpl);
3226dd4f32aeSBjoern A. Zeeb 	} else { /* Disable */
3227dd4f32aeSBjoern A. Zeeb 		return ath11k_wmi_fils_discovery(ar, arvif->vdev_id, 0, false);
3228dd4f32aeSBjoern A. Zeeb 	}
3229dd4f32aeSBjoern A. Zeeb 
3230dd4f32aeSBjoern A. Zeeb 	if (!tmpl) {
3231dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab,
3232dd4f32aeSBjoern A. Zeeb 			    "mac vdev %i failed to retrieve %s template\n",
3233dd4f32aeSBjoern A. Zeeb 			    arvif->vdev_id, (unsol_bcast_probe_resp_enabled ?
3234dd4f32aeSBjoern A. Zeeb 			    "unsolicited broadcast probe response" :
3235dd4f32aeSBjoern A. Zeeb 			    "FILS discovery"));
3236dd4f32aeSBjoern A. Zeeb 		return -EPERM;
3237dd4f32aeSBjoern A. Zeeb 	}
3238dd4f32aeSBjoern A. Zeeb 	kfree_skb(tmpl);
3239dd4f32aeSBjoern A. Zeeb 
3240dd4f32aeSBjoern A. Zeeb 	if (!ret)
3241dd4f32aeSBjoern A. Zeeb 		ret = ath11k_wmi_fils_discovery(ar, arvif->vdev_id, interval,
3242dd4f32aeSBjoern A. Zeeb 						unsol_bcast_probe_resp_enabled);
3243dd4f32aeSBjoern A. Zeeb 
3244dd4f32aeSBjoern A. Zeeb 	return ret;
3245dd4f32aeSBjoern A. Zeeb }
3246dd4f32aeSBjoern A. Zeeb 
ath11k_mac_config_obss_pd(struct ath11k * ar,struct ieee80211_he_obss_pd * he_obss_pd)3247dd4f32aeSBjoern A. Zeeb static int ath11k_mac_config_obss_pd(struct ath11k *ar,
3248dd4f32aeSBjoern A. Zeeb 				     struct ieee80211_he_obss_pd *he_obss_pd)
3249dd4f32aeSBjoern A. Zeeb {
3250dd4f32aeSBjoern A. Zeeb 	u32 bitmap[2], param_id, param_val, pdev_id;
3251dd4f32aeSBjoern A. Zeeb 	int ret;
3252dd4f32aeSBjoern A. Zeeb 	s8 non_srg_th = 0, srg_th = 0;
3253dd4f32aeSBjoern A. Zeeb 
3254dd4f32aeSBjoern A. Zeeb 	pdev_id = ar->pdev->pdev_id;
3255dd4f32aeSBjoern A. Zeeb 
3256dd4f32aeSBjoern A. Zeeb 	/* Set and enable SRG/non-SRG OBSS PD Threshold */
3257dd4f32aeSBjoern A. Zeeb 	param_id = WMI_PDEV_PARAM_SET_CMD_OBSS_PD_THRESHOLD;
3258dd4f32aeSBjoern A. Zeeb 	if (test_bit(ATH11K_FLAG_MONITOR_STARTED, &ar->monitor_flags)) {
3259dd4f32aeSBjoern A. Zeeb 		ret = ath11k_wmi_pdev_set_param(ar, param_id, 0, pdev_id);
3260dd4f32aeSBjoern A. Zeeb 		if (ret)
3261dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab,
3262dd4f32aeSBjoern A. Zeeb 				    "failed to set obss_pd_threshold for pdev: %u\n",
3263dd4f32aeSBjoern A. Zeeb 				    pdev_id);
3264dd4f32aeSBjoern A. Zeeb 		return ret;
3265dd4f32aeSBjoern A. Zeeb 	}
3266dd4f32aeSBjoern A. Zeeb 
3267dd4f32aeSBjoern A. Zeeb 	ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
3268*28348caeSBjoern A. Zeeb 		   "obss pd sr_ctrl %x non_srg_thres %u srg_max %u\n",
3269dd4f32aeSBjoern A. Zeeb 		   he_obss_pd->sr_ctrl, he_obss_pd->non_srg_max_offset,
3270dd4f32aeSBjoern A. Zeeb 		   he_obss_pd->max_offset);
3271dd4f32aeSBjoern A. Zeeb 
3272dd4f32aeSBjoern A. Zeeb 	param_val = 0;
3273dd4f32aeSBjoern A. Zeeb 
3274dd4f32aeSBjoern A. Zeeb 	if (he_obss_pd->sr_ctrl &
3275dd4f32aeSBjoern A. Zeeb 	    IEEE80211_HE_SPR_NON_SRG_OBSS_PD_SR_DISALLOWED) {
3276dd4f32aeSBjoern A. Zeeb 		non_srg_th = ATH11K_OBSS_PD_MAX_THRESHOLD;
3277dd4f32aeSBjoern A. Zeeb 	} else {
3278dd4f32aeSBjoern A. Zeeb 		if (he_obss_pd->sr_ctrl & IEEE80211_HE_SPR_NON_SRG_OFFSET_PRESENT)
3279dd4f32aeSBjoern A. Zeeb 			non_srg_th = (ATH11K_OBSS_PD_MAX_THRESHOLD +
3280dd4f32aeSBjoern A. Zeeb 				      he_obss_pd->non_srg_max_offset);
3281dd4f32aeSBjoern A. Zeeb 		else
3282dd4f32aeSBjoern A. Zeeb 			non_srg_th = ATH11K_OBSS_PD_NON_SRG_MAX_THRESHOLD;
3283dd4f32aeSBjoern A. Zeeb 
3284dd4f32aeSBjoern A. Zeeb 		param_val |= ATH11K_OBSS_PD_NON_SRG_EN;
3285dd4f32aeSBjoern A. Zeeb 	}
3286dd4f32aeSBjoern A. Zeeb 
3287dd4f32aeSBjoern A. Zeeb 	if (he_obss_pd->sr_ctrl & IEEE80211_HE_SPR_SRG_INFORMATION_PRESENT) {
3288dd4f32aeSBjoern A. Zeeb 		srg_th = ATH11K_OBSS_PD_MAX_THRESHOLD + he_obss_pd->max_offset;
3289dd4f32aeSBjoern A. Zeeb 		param_val |= ATH11K_OBSS_PD_SRG_EN;
3290dd4f32aeSBjoern A. Zeeb 	}
3291dd4f32aeSBjoern A. Zeeb 
3292dd4f32aeSBjoern A. Zeeb 	if (test_bit(WMI_TLV_SERVICE_SRG_SRP_SPATIAL_REUSE_SUPPORT,
3293dd4f32aeSBjoern A. Zeeb 		     ar->ab->wmi_ab.svc_map)) {
3294dd4f32aeSBjoern A. Zeeb 		param_val |= ATH11K_OBSS_PD_THRESHOLD_IN_DBM;
3295dd4f32aeSBjoern A. Zeeb 		param_val |= FIELD_PREP(GENMASK(15, 8), srg_th);
3296dd4f32aeSBjoern A. Zeeb 	} else {
3297dd4f32aeSBjoern A. Zeeb 		non_srg_th -= ATH11K_DEFAULT_NOISE_FLOOR;
3298dd4f32aeSBjoern A. Zeeb 		/* SRG not supported and threshold in dB */
3299dd4f32aeSBjoern A. Zeeb 		param_val &= ~(ATH11K_OBSS_PD_SRG_EN |
3300dd4f32aeSBjoern A. Zeeb 			       ATH11K_OBSS_PD_THRESHOLD_IN_DBM);
3301dd4f32aeSBjoern A. Zeeb 	}
3302dd4f32aeSBjoern A. Zeeb 
3303dd4f32aeSBjoern A. Zeeb 	param_val |= (non_srg_th & GENMASK(7, 0));
3304dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_pdev_set_param(ar, param_id, param_val, pdev_id);
3305dd4f32aeSBjoern A. Zeeb 	if (ret) {
3306dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab,
3307dd4f32aeSBjoern A. Zeeb 			    "failed to set obss_pd_threshold for pdev: %u\n",
3308dd4f32aeSBjoern A. Zeeb 			    pdev_id);
3309dd4f32aeSBjoern A. Zeeb 		return ret;
3310dd4f32aeSBjoern A. Zeeb 	}
3311dd4f32aeSBjoern A. Zeeb 
3312dd4f32aeSBjoern A. Zeeb 	/* Enable OBSS PD for all access category */
3313dd4f32aeSBjoern A. Zeeb 	param_id  = WMI_PDEV_PARAM_SET_CMD_OBSS_PD_PER_AC;
3314dd4f32aeSBjoern A. Zeeb 	param_val = 0xf;
3315dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_pdev_set_param(ar, param_id, param_val, pdev_id);
3316dd4f32aeSBjoern A. Zeeb 	if (ret) {
3317dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab,
3318dd4f32aeSBjoern A. Zeeb 			    "failed to set obss_pd_per_ac for pdev: %u\n",
3319dd4f32aeSBjoern A. Zeeb 			    pdev_id);
3320dd4f32aeSBjoern A. Zeeb 		return ret;
3321dd4f32aeSBjoern A. Zeeb 	}
3322dd4f32aeSBjoern A. Zeeb 
3323dd4f32aeSBjoern A. Zeeb 	/* Set SR Prohibit */
3324dd4f32aeSBjoern A. Zeeb 	param_id  = WMI_PDEV_PARAM_ENABLE_SR_PROHIBIT;
3325dd4f32aeSBjoern A. Zeeb 	param_val = !!(he_obss_pd->sr_ctrl &
3326dd4f32aeSBjoern A. Zeeb 		       IEEE80211_HE_SPR_HESIGA_SR_VAL15_ALLOWED);
3327dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_pdev_set_param(ar, param_id, param_val, pdev_id);
3328dd4f32aeSBjoern A. Zeeb 	if (ret) {
3329dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to set sr_prohibit for pdev: %u\n",
3330dd4f32aeSBjoern A. Zeeb 			    pdev_id);
3331dd4f32aeSBjoern A. Zeeb 		return ret;
3332dd4f32aeSBjoern A. Zeeb 	}
3333dd4f32aeSBjoern A. Zeeb 
3334dd4f32aeSBjoern A. Zeeb 	if (!test_bit(WMI_TLV_SERVICE_SRG_SRP_SPATIAL_REUSE_SUPPORT,
3335dd4f32aeSBjoern A. Zeeb 		      ar->ab->wmi_ab.svc_map))
3336dd4f32aeSBjoern A. Zeeb 		return 0;
3337dd4f32aeSBjoern A. Zeeb 
3338dd4f32aeSBjoern A. Zeeb 	/* Set SRG BSS Color Bitmap */
3339dd4f32aeSBjoern A. Zeeb 	memcpy(bitmap, he_obss_pd->bss_color_bitmap, sizeof(bitmap));
3340dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_pdev_set_srg_bss_color_bitmap(ar, bitmap);
3341dd4f32aeSBjoern A. Zeeb 	if (ret) {
3342dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab,
3343dd4f32aeSBjoern A. Zeeb 			    "failed to set bss_color_bitmap for pdev: %u\n",
3344dd4f32aeSBjoern A. Zeeb 			    pdev_id);
3345dd4f32aeSBjoern A. Zeeb 		return ret;
3346dd4f32aeSBjoern A. Zeeb 	}
3347dd4f32aeSBjoern A. Zeeb 
3348dd4f32aeSBjoern A. Zeeb 	/* Set SRG Partial BSSID Bitmap */
3349dd4f32aeSBjoern A. Zeeb 	memcpy(bitmap, he_obss_pd->partial_bssid_bitmap, sizeof(bitmap));
3350dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_pdev_set_srg_patial_bssid_bitmap(ar, bitmap);
3351dd4f32aeSBjoern A. Zeeb 	if (ret) {
3352dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab,
3353dd4f32aeSBjoern A. Zeeb 			    "failed to set partial_bssid_bitmap for pdev: %u\n",
3354dd4f32aeSBjoern A. Zeeb 			    pdev_id);
3355dd4f32aeSBjoern A. Zeeb 		return ret;
3356dd4f32aeSBjoern A. Zeeb 	}
3357dd4f32aeSBjoern A. Zeeb 
3358dd4f32aeSBjoern A. Zeeb 	memset(bitmap, 0xff, sizeof(bitmap));
3359dd4f32aeSBjoern A. Zeeb 
3360dd4f32aeSBjoern A. Zeeb 	/* Enable all BSS Colors for SRG */
3361dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_pdev_srg_obss_color_enable_bitmap(ar, bitmap);
3362dd4f32aeSBjoern A. Zeeb 	if (ret) {
3363dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab,
3364dd4f32aeSBjoern A. Zeeb 			    "failed to set srg_color_en_bitmap pdev: %u\n",
3365dd4f32aeSBjoern A. Zeeb 			    pdev_id);
3366dd4f32aeSBjoern A. Zeeb 		return ret;
3367dd4f32aeSBjoern A. Zeeb 	}
3368dd4f32aeSBjoern A. Zeeb 
3369*28348caeSBjoern A. Zeeb 	/* Enable all partial BSSID mask for SRG */
3370dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_pdev_srg_obss_bssid_enable_bitmap(ar, bitmap);
3371dd4f32aeSBjoern A. Zeeb 	if (ret) {
3372dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab,
3373dd4f32aeSBjoern A. Zeeb 			    "failed to set srg_bssid_en_bitmap pdev: %u\n",
3374dd4f32aeSBjoern A. Zeeb 			    pdev_id);
3375dd4f32aeSBjoern A. Zeeb 		return ret;
3376dd4f32aeSBjoern A. Zeeb 	}
3377dd4f32aeSBjoern A. Zeeb 
3378dd4f32aeSBjoern A. Zeeb 	/* Enable all BSS Colors for non-SRG */
3379dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_pdev_non_srg_obss_color_enable_bitmap(ar, bitmap);
3380dd4f32aeSBjoern A. Zeeb 	if (ret) {
3381dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab,
3382dd4f32aeSBjoern A. Zeeb 			    "failed to set non_srg_color_en_bitmap pdev: %u\n",
3383dd4f32aeSBjoern A. Zeeb 			    pdev_id);
3384dd4f32aeSBjoern A. Zeeb 		return ret;
3385dd4f32aeSBjoern A. Zeeb 	}
3386dd4f32aeSBjoern A. Zeeb 
3387*28348caeSBjoern A. Zeeb 	/* Enable all partial BSSID mask for non-SRG */
3388dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_pdev_non_srg_obss_bssid_enable_bitmap(ar, bitmap);
3389dd4f32aeSBjoern A. Zeeb 	if (ret) {
3390dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab,
3391dd4f32aeSBjoern A. Zeeb 			    "failed to set non_srg_bssid_en_bitmap pdev: %u\n",
3392dd4f32aeSBjoern A. Zeeb 			    pdev_id);
3393dd4f32aeSBjoern A. Zeeb 		return ret;
3394dd4f32aeSBjoern A. Zeeb 	}
3395dd4f32aeSBjoern A. Zeeb 
3396dd4f32aeSBjoern A. Zeeb 	return 0;
3397dd4f32aeSBjoern A. Zeeb }
3398dd4f32aeSBjoern A. Zeeb 
ath11k_mac_op_bss_info_changed(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_bss_conf * info,u64 changed)3399dd4f32aeSBjoern A. Zeeb static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
3400dd4f32aeSBjoern A. Zeeb 					   struct ieee80211_vif *vif,
3401dd4f32aeSBjoern A. Zeeb 					   struct ieee80211_bss_conf *info,
3402dd4f32aeSBjoern A. Zeeb 					   u64 changed)
3403dd4f32aeSBjoern A. Zeeb {
3404dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = hw->priv;
3405dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
3406dd4f32aeSBjoern A. Zeeb 	struct cfg80211_chan_def def;
3407dd4f32aeSBjoern A. Zeeb 	u32 param_id, param_value;
3408dd4f32aeSBjoern A. Zeeb 	enum nl80211_band band;
3409dd4f32aeSBjoern A. Zeeb 	u32 vdev_param;
3410dd4f32aeSBjoern A. Zeeb 	int mcast_rate;
3411dd4f32aeSBjoern A. Zeeb 	u32 preamble;
3412dd4f32aeSBjoern A. Zeeb 	u16 hw_value;
3413dd4f32aeSBjoern A. Zeeb 	u16 bitrate;
3414dd4f32aeSBjoern A. Zeeb 	int ret = 0;
3415dd4f32aeSBjoern A. Zeeb 	u8 rateidx;
3416*28348caeSBjoern A. Zeeb 	u32 rate, param;
3417*28348caeSBjoern A. Zeeb 	u32 ipv4_cnt;
3418dd4f32aeSBjoern A. Zeeb 
3419dd4f32aeSBjoern A. Zeeb 	mutex_lock(&ar->conf_mutex);
3420dd4f32aeSBjoern A. Zeeb 
3421dd4f32aeSBjoern A. Zeeb 	if (changed & BSS_CHANGED_BEACON_INT) {
3422dd4f32aeSBjoern A. Zeeb 		arvif->beacon_interval = info->beacon_int;
3423dd4f32aeSBjoern A. Zeeb 
3424dd4f32aeSBjoern A. Zeeb 		param_id = WMI_VDEV_PARAM_BEACON_INTERVAL;
3425dd4f32aeSBjoern A. Zeeb 		ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
3426dd4f32aeSBjoern A. Zeeb 						    param_id,
3427dd4f32aeSBjoern A. Zeeb 						    arvif->beacon_interval);
3428dd4f32aeSBjoern A. Zeeb 		if (ret)
3429dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "Failed to set beacon interval for VDEV: %d\n",
3430dd4f32aeSBjoern A. Zeeb 				    arvif->vdev_id);
3431dd4f32aeSBjoern A. Zeeb 		else
3432dd4f32aeSBjoern A. Zeeb 			ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
3433dd4f32aeSBjoern A. Zeeb 				   "Beacon interval: %d set for VDEV: %d\n",
3434dd4f32aeSBjoern A. Zeeb 				   arvif->beacon_interval, arvif->vdev_id);
3435dd4f32aeSBjoern A. Zeeb 	}
3436dd4f32aeSBjoern A. Zeeb 
3437dd4f32aeSBjoern A. Zeeb 	if (changed & BSS_CHANGED_BEACON) {
3438dd4f32aeSBjoern A. Zeeb 		param_id = WMI_PDEV_PARAM_BEACON_TX_MODE;
3439dd4f32aeSBjoern A. Zeeb 		param_value = WMI_BEACON_STAGGERED_MODE;
3440dd4f32aeSBjoern A. Zeeb 		ret = ath11k_wmi_pdev_set_param(ar, param_id,
3441dd4f32aeSBjoern A. Zeeb 						param_value, ar->pdev->pdev_id);
3442dd4f32aeSBjoern A. Zeeb 		if (ret)
3443dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "Failed to set beacon mode for VDEV: %d\n",
3444dd4f32aeSBjoern A. Zeeb 				    arvif->vdev_id);
3445dd4f32aeSBjoern A. Zeeb 		else
3446dd4f32aeSBjoern A. Zeeb 			ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
3447dd4f32aeSBjoern A. Zeeb 				   "Set staggered beacon mode for VDEV: %d\n",
3448dd4f32aeSBjoern A. Zeeb 				   arvif->vdev_id);
3449dd4f32aeSBjoern A. Zeeb 
3450dd4f32aeSBjoern A. Zeeb 		if (!arvif->do_not_send_tmpl || !arvif->bcca_zero_sent) {
3451dd4f32aeSBjoern A. Zeeb 			ret = ath11k_mac_setup_bcn_tmpl(arvif);
3452dd4f32aeSBjoern A. Zeeb 			if (ret)
3453dd4f32aeSBjoern A. Zeeb 				ath11k_warn(ar->ab, "failed to update bcn template: %d\n",
3454dd4f32aeSBjoern A. Zeeb 					    ret);
3455dd4f32aeSBjoern A. Zeeb 		}
3456dd4f32aeSBjoern A. Zeeb 
3457dd4f32aeSBjoern A. Zeeb 		if (arvif->bcca_zero_sent)
3458dd4f32aeSBjoern A. Zeeb 			arvif->do_not_send_tmpl = true;
3459dd4f32aeSBjoern A. Zeeb 		else
3460dd4f32aeSBjoern A. Zeeb 			arvif->do_not_send_tmpl = false;
3461*28348caeSBjoern A. Zeeb 
3462*28348caeSBjoern A. Zeeb 		if (vif->bss_conf.he_support) {
3463*28348caeSBjoern A. Zeeb 			ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
3464*28348caeSBjoern A. Zeeb 							    WMI_VDEV_PARAM_BA_MODE,
3465*28348caeSBjoern A. Zeeb 							    WMI_BA_MODE_BUFFER_SIZE_256);
3466*28348caeSBjoern A. Zeeb 			if (ret)
3467*28348caeSBjoern A. Zeeb 				ath11k_warn(ar->ab,
3468*28348caeSBjoern A. Zeeb 					    "failed to set BA BUFFER SIZE 256 for vdev: %d\n",
3469*28348caeSBjoern A. Zeeb 					    arvif->vdev_id);
3470*28348caeSBjoern A. Zeeb 			else
3471*28348caeSBjoern A. Zeeb 				ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
3472*28348caeSBjoern A. Zeeb 					   "Set BA BUFFER SIZE 256 for VDEV: %d\n",
3473*28348caeSBjoern A. Zeeb 					   arvif->vdev_id);
3474*28348caeSBjoern A. Zeeb 		}
3475dd4f32aeSBjoern A. Zeeb 	}
3476dd4f32aeSBjoern A. Zeeb 
3477dd4f32aeSBjoern A. Zeeb 	if (changed & (BSS_CHANGED_BEACON_INFO | BSS_CHANGED_BEACON)) {
3478dd4f32aeSBjoern A. Zeeb 		arvif->dtim_period = info->dtim_period;
3479dd4f32aeSBjoern A. Zeeb 
3480dd4f32aeSBjoern A. Zeeb 		param_id = WMI_VDEV_PARAM_DTIM_PERIOD;
3481dd4f32aeSBjoern A. Zeeb 		ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
3482dd4f32aeSBjoern A. Zeeb 						    param_id,
3483dd4f32aeSBjoern A. Zeeb 						    arvif->dtim_period);
3484dd4f32aeSBjoern A. Zeeb 
3485dd4f32aeSBjoern A. Zeeb 		if (ret)
3486dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "Failed to set dtim period for VDEV %d: %i\n",
3487dd4f32aeSBjoern A. Zeeb 				    arvif->vdev_id, ret);
3488dd4f32aeSBjoern A. Zeeb 		else
3489dd4f32aeSBjoern A. Zeeb 			ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
3490dd4f32aeSBjoern A. Zeeb 				   "DTIM period: %d set for VDEV: %d\n",
3491dd4f32aeSBjoern A. Zeeb 				   arvif->dtim_period, arvif->vdev_id);
3492dd4f32aeSBjoern A. Zeeb 	}
3493dd4f32aeSBjoern A. Zeeb 
3494dd4f32aeSBjoern A. Zeeb 	if (changed & BSS_CHANGED_SSID &&
3495dd4f32aeSBjoern A. Zeeb 	    vif->type == NL80211_IFTYPE_AP) {
3496*28348caeSBjoern A. Zeeb 		arvif->u.ap.ssid_len = vif->cfg.ssid_len;
3497*28348caeSBjoern A. Zeeb 		if (vif->cfg.ssid_len)
3498*28348caeSBjoern A. Zeeb 			memcpy(arvif->u.ap.ssid, vif->cfg.ssid,
3499*28348caeSBjoern A. Zeeb 			       vif->cfg.ssid_len);
3500dd4f32aeSBjoern A. Zeeb 		arvif->u.ap.hidden_ssid = info->hidden_ssid;
3501dd4f32aeSBjoern A. Zeeb 	}
3502dd4f32aeSBjoern A. Zeeb 
3503dd4f32aeSBjoern A. Zeeb 	if (changed & BSS_CHANGED_BSSID && !is_zero_ether_addr(info->bssid))
3504dd4f32aeSBjoern A. Zeeb 		ether_addr_copy(arvif->bssid, info->bssid);
3505dd4f32aeSBjoern A. Zeeb 
3506dd4f32aeSBjoern A. Zeeb 	if (changed & BSS_CHANGED_BEACON_ENABLED) {
3507*28348caeSBjoern A. Zeeb 		if (info->enable_beacon)
3508*28348caeSBjoern A. Zeeb 			ath11k_mac_set_he_txbf_conf(arvif);
3509dd4f32aeSBjoern A. Zeeb 		ath11k_control_beaconing(arvif, info);
3510dd4f32aeSBjoern A. Zeeb 
3511dd4f32aeSBjoern A. Zeeb 		if (arvif->is_up && vif->bss_conf.he_support &&
3512dd4f32aeSBjoern A. Zeeb 		    vif->bss_conf.he_oper.params) {
3513dd4f32aeSBjoern A. Zeeb 			param_id = WMI_VDEV_PARAM_HEOPS_0_31;
3514dd4f32aeSBjoern A. Zeeb 			param_value = vif->bss_conf.he_oper.params;
3515dd4f32aeSBjoern A. Zeeb 			ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
3516dd4f32aeSBjoern A. Zeeb 							    param_id, param_value);
3517dd4f32aeSBjoern A. Zeeb 			ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
3518dd4f32aeSBjoern A. Zeeb 				   "he oper param: %x set for VDEV: %d\n",
3519dd4f32aeSBjoern A. Zeeb 				   param_value, arvif->vdev_id);
3520dd4f32aeSBjoern A. Zeeb 
3521dd4f32aeSBjoern A. Zeeb 			if (ret)
3522dd4f32aeSBjoern A. Zeeb 				ath11k_warn(ar->ab, "Failed to set he oper params %x for VDEV %d: %i\n",
3523dd4f32aeSBjoern A. Zeeb 					    param_value, arvif->vdev_id, ret);
3524dd4f32aeSBjoern A. Zeeb 		}
3525dd4f32aeSBjoern A. Zeeb 	}
3526dd4f32aeSBjoern A. Zeeb 
3527dd4f32aeSBjoern A. Zeeb 	if (changed & BSS_CHANGED_ERP_CTS_PROT) {
3528dd4f32aeSBjoern A. Zeeb 		u32 cts_prot;
3529dd4f32aeSBjoern A. Zeeb 
3530dd4f32aeSBjoern A. Zeeb 		cts_prot = !!(info->use_cts_prot);
3531dd4f32aeSBjoern A. Zeeb 		param_id = WMI_VDEV_PARAM_PROTECTION_MODE;
3532dd4f32aeSBjoern A. Zeeb 
3533dd4f32aeSBjoern A. Zeeb 		if (arvif->is_started) {
3534dd4f32aeSBjoern A. Zeeb 			ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
3535dd4f32aeSBjoern A. Zeeb 							    param_id, cts_prot);
3536dd4f32aeSBjoern A. Zeeb 			if (ret)
3537dd4f32aeSBjoern A. Zeeb 				ath11k_warn(ar->ab, "Failed to set CTS prot for VDEV: %d\n",
3538dd4f32aeSBjoern A. Zeeb 					    arvif->vdev_id);
3539dd4f32aeSBjoern A. Zeeb 			else
3540dd4f32aeSBjoern A. Zeeb 				ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "Set CTS prot: %d for VDEV: %d\n",
3541dd4f32aeSBjoern A. Zeeb 					   cts_prot, arvif->vdev_id);
3542dd4f32aeSBjoern A. Zeeb 		} else {
3543dd4f32aeSBjoern A. Zeeb 			ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "defer protection mode setup, vdev is not ready yet\n");
3544dd4f32aeSBjoern A. Zeeb 		}
3545dd4f32aeSBjoern A. Zeeb 	}
3546dd4f32aeSBjoern A. Zeeb 
3547dd4f32aeSBjoern A. Zeeb 	if (changed & BSS_CHANGED_ERP_SLOT) {
3548dd4f32aeSBjoern A. Zeeb 		u32 slottime;
3549dd4f32aeSBjoern A. Zeeb 
3550dd4f32aeSBjoern A. Zeeb 		if (info->use_short_slot)
3551dd4f32aeSBjoern A. Zeeb 			slottime = WMI_VDEV_SLOT_TIME_SHORT; /* 9us */
3552dd4f32aeSBjoern A. Zeeb 
3553dd4f32aeSBjoern A. Zeeb 		else
3554dd4f32aeSBjoern A. Zeeb 			slottime = WMI_VDEV_SLOT_TIME_LONG; /* 20us */
3555dd4f32aeSBjoern A. Zeeb 
3556dd4f32aeSBjoern A. Zeeb 		param_id = WMI_VDEV_PARAM_SLOT_TIME;
3557dd4f32aeSBjoern A. Zeeb 		ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
3558dd4f32aeSBjoern A. Zeeb 						    param_id, slottime);
3559dd4f32aeSBjoern A. Zeeb 		if (ret)
3560dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "Failed to set erp slot for VDEV: %d\n",
3561dd4f32aeSBjoern A. Zeeb 				    arvif->vdev_id);
3562dd4f32aeSBjoern A. Zeeb 		else
3563dd4f32aeSBjoern A. Zeeb 			ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
3564dd4f32aeSBjoern A. Zeeb 				   "Set slottime: %d for VDEV: %d\n",
3565dd4f32aeSBjoern A. Zeeb 				   slottime, arvif->vdev_id);
3566dd4f32aeSBjoern A. Zeeb 	}
3567dd4f32aeSBjoern A. Zeeb 
3568dd4f32aeSBjoern A. Zeeb 	if (changed & BSS_CHANGED_ERP_PREAMBLE) {
3569dd4f32aeSBjoern A. Zeeb 		u32 preamble;
3570dd4f32aeSBjoern A. Zeeb 
3571dd4f32aeSBjoern A. Zeeb 		if (info->use_short_preamble)
3572dd4f32aeSBjoern A. Zeeb 			preamble = WMI_VDEV_PREAMBLE_SHORT;
3573dd4f32aeSBjoern A. Zeeb 		else
3574dd4f32aeSBjoern A. Zeeb 			preamble = WMI_VDEV_PREAMBLE_LONG;
3575dd4f32aeSBjoern A. Zeeb 
3576dd4f32aeSBjoern A. Zeeb 		param_id = WMI_VDEV_PARAM_PREAMBLE;
3577dd4f32aeSBjoern A. Zeeb 		ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
3578dd4f32aeSBjoern A. Zeeb 						    param_id, preamble);
3579dd4f32aeSBjoern A. Zeeb 		if (ret)
3580dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "Failed to set preamble for VDEV: %d\n",
3581dd4f32aeSBjoern A. Zeeb 				    arvif->vdev_id);
3582dd4f32aeSBjoern A. Zeeb 		else
3583dd4f32aeSBjoern A. Zeeb 			ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
3584dd4f32aeSBjoern A. Zeeb 				   "Set preamble: %d for VDEV: %d\n",
3585dd4f32aeSBjoern A. Zeeb 				   preamble, arvif->vdev_id);
3586dd4f32aeSBjoern A. Zeeb 	}
3587dd4f32aeSBjoern A. Zeeb 
3588dd4f32aeSBjoern A. Zeeb 	if (changed & BSS_CHANGED_ASSOC) {
3589*28348caeSBjoern A. Zeeb 		if (vif->cfg.assoc)
3590dd4f32aeSBjoern A. Zeeb 			ath11k_bss_assoc(hw, vif, info);
3591dd4f32aeSBjoern A. Zeeb 		else
3592dd4f32aeSBjoern A. Zeeb 			ath11k_bss_disassoc(hw, vif);
3593dd4f32aeSBjoern A. Zeeb 	}
3594dd4f32aeSBjoern A. Zeeb 
3595dd4f32aeSBjoern A. Zeeb 	if (changed & BSS_CHANGED_TXPOWER) {
3596*28348caeSBjoern A. Zeeb 		ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev_id %i txpower %d\n",
3597dd4f32aeSBjoern A. Zeeb 			   arvif->vdev_id, info->txpower);
3598dd4f32aeSBjoern A. Zeeb 
3599dd4f32aeSBjoern A. Zeeb 		arvif->txpower = info->txpower;
3600dd4f32aeSBjoern A. Zeeb 		ath11k_mac_txpower_recalc(ar);
3601dd4f32aeSBjoern A. Zeeb 	}
3602dd4f32aeSBjoern A. Zeeb 
3603dd4f32aeSBjoern A. Zeeb 	if (changed & BSS_CHANGED_PS &&
3604dd4f32aeSBjoern A. Zeeb 	    ar->ab->hw_params.supports_sta_ps) {
3605*28348caeSBjoern A. Zeeb 		arvif->ps = vif->cfg.ps;
3606dd4f32aeSBjoern A. Zeeb 
3607dd4f32aeSBjoern A. Zeeb 		ret = ath11k_mac_config_ps(ar);
3608dd4f32aeSBjoern A. Zeeb 		if (ret)
3609dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "failed to setup ps on vdev %i: %d\n",
3610dd4f32aeSBjoern A. Zeeb 				    arvif->vdev_id, ret);
3611dd4f32aeSBjoern A. Zeeb 	}
3612dd4f32aeSBjoern A. Zeeb 
3613dd4f32aeSBjoern A. Zeeb 	if (changed & BSS_CHANGED_MCAST_RATE &&
3614dd4f32aeSBjoern A. Zeeb 	    !ath11k_mac_vif_chan(arvif->vif, &def)) {
3615dd4f32aeSBjoern A. Zeeb 		band = def.chan->band;
3616dd4f32aeSBjoern A. Zeeb 		mcast_rate = vif->bss_conf.mcast_rate[band];
3617dd4f32aeSBjoern A. Zeeb 
3618dd4f32aeSBjoern A. Zeeb 		if (mcast_rate > 0)
3619dd4f32aeSBjoern A. Zeeb 			rateidx = mcast_rate - 1;
3620dd4f32aeSBjoern A. Zeeb 		else
3621dd4f32aeSBjoern A. Zeeb 			rateidx = ffs(vif->bss_conf.basic_rates) - 1;
3622dd4f32aeSBjoern A. Zeeb 
3623dd4f32aeSBjoern A. Zeeb 		if (ar->pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP)
3624dd4f32aeSBjoern A. Zeeb 			rateidx += ATH11K_MAC_FIRST_OFDM_RATE_IDX;
3625dd4f32aeSBjoern A. Zeeb 
3626dd4f32aeSBjoern A. Zeeb 		bitrate = ath11k_legacy_rates[rateidx].bitrate;
3627dd4f32aeSBjoern A. Zeeb 		hw_value = ath11k_legacy_rates[rateidx].hw_value;
3628dd4f32aeSBjoern A. Zeeb 
3629dd4f32aeSBjoern A. Zeeb 		if (ath11k_mac_bitrate_is_cck(bitrate))
3630dd4f32aeSBjoern A. Zeeb 			preamble = WMI_RATE_PREAMBLE_CCK;
3631dd4f32aeSBjoern A. Zeeb 		else
3632dd4f32aeSBjoern A. Zeeb 			preamble = WMI_RATE_PREAMBLE_OFDM;
3633dd4f32aeSBjoern A. Zeeb 
3634dd4f32aeSBjoern A. Zeeb 		rate = ATH11K_HW_RATE_CODE(hw_value, 0, preamble);
3635dd4f32aeSBjoern A. Zeeb 
3636dd4f32aeSBjoern A. Zeeb 		ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
3637*28348caeSBjoern A. Zeeb 			   "vdev %d mcast_rate %x\n",
3638dd4f32aeSBjoern A. Zeeb 			   arvif->vdev_id, rate);
3639dd4f32aeSBjoern A. Zeeb 
3640dd4f32aeSBjoern A. Zeeb 		vdev_param = WMI_VDEV_PARAM_MCAST_DATA_RATE;
3641dd4f32aeSBjoern A. Zeeb 		ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
3642dd4f32aeSBjoern A. Zeeb 						    vdev_param, rate);
3643dd4f32aeSBjoern A. Zeeb 		if (ret)
3644dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab,
3645dd4f32aeSBjoern A. Zeeb 				    "failed to set mcast rate on vdev %i: %d\n",
3646dd4f32aeSBjoern A. Zeeb 				    arvif->vdev_id,  ret);
3647dd4f32aeSBjoern A. Zeeb 
3648dd4f32aeSBjoern A. Zeeb 		vdev_param = WMI_VDEV_PARAM_BCAST_DATA_RATE;
3649dd4f32aeSBjoern A. Zeeb 		ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
3650dd4f32aeSBjoern A. Zeeb 						    vdev_param, rate);
3651dd4f32aeSBjoern A. Zeeb 		if (ret)
3652dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab,
3653dd4f32aeSBjoern A. Zeeb 				    "failed to set bcast rate on vdev %i: %d\n",
3654dd4f32aeSBjoern A. Zeeb 				    arvif->vdev_id,  ret);
3655dd4f32aeSBjoern A. Zeeb 	}
3656dd4f32aeSBjoern A. Zeeb 
3657dd4f32aeSBjoern A. Zeeb 	if (changed & BSS_CHANGED_BASIC_RATES &&
3658dd4f32aeSBjoern A. Zeeb 	    !ath11k_mac_vif_chan(arvif->vif, &def))
3659dd4f32aeSBjoern A. Zeeb 		ath11k_recalculate_mgmt_rate(ar, vif, &def);
3660dd4f32aeSBjoern A. Zeeb 
3661dd4f32aeSBjoern A. Zeeb 	if (changed & BSS_CHANGED_TWT) {
3662*28348caeSBjoern A. Zeeb 		struct wmi_twt_enable_params twt_params = {0};
3663*28348caeSBjoern A. Zeeb 
3664*28348caeSBjoern A. Zeeb 		if (info->twt_requester || info->twt_responder) {
3665*28348caeSBjoern A. Zeeb 			ath11k_wmi_fill_default_twt_params(&twt_params);
3666*28348caeSBjoern A. Zeeb 			ath11k_wmi_send_twt_enable_cmd(ar, ar->pdev->pdev_id,
3667*28348caeSBjoern A. Zeeb 						       &twt_params);
3668*28348caeSBjoern A. Zeeb 		} else {
3669dd4f32aeSBjoern A. Zeeb 			ath11k_wmi_send_twt_disable_cmd(ar, ar->pdev->pdev_id);
3670dd4f32aeSBjoern A. Zeeb 		}
3671*28348caeSBjoern A. Zeeb 	}
3672dd4f32aeSBjoern A. Zeeb 
3673dd4f32aeSBjoern A. Zeeb 	if (changed & BSS_CHANGED_HE_OBSS_PD)
3674dd4f32aeSBjoern A. Zeeb 		ath11k_mac_config_obss_pd(ar, &info->he_obss_pd);
3675dd4f32aeSBjoern A. Zeeb 
3676dd4f32aeSBjoern A. Zeeb 	if (changed & BSS_CHANGED_HE_BSS_COLOR) {
3677dd4f32aeSBjoern A. Zeeb 		if (vif->type == NL80211_IFTYPE_AP) {
3678dd4f32aeSBjoern A. Zeeb 			ret = ath11k_wmi_send_obss_color_collision_cfg_cmd(
3679dd4f32aeSBjoern A. Zeeb 				ar, arvif->vdev_id, info->he_bss_color.color,
3680dd4f32aeSBjoern A. Zeeb 				ATH11K_BSS_COLOR_COLLISION_DETECTION_AP_PERIOD_MS,
3681dd4f32aeSBjoern A. Zeeb 				info->he_bss_color.enabled);
3682dd4f32aeSBjoern A. Zeeb 			if (ret)
3683dd4f32aeSBjoern A. Zeeb 				ath11k_warn(ar->ab, "failed to set bss color collision on vdev %i: %d\n",
3684dd4f32aeSBjoern A. Zeeb 					    arvif->vdev_id,  ret);
3685dd4f32aeSBjoern A. Zeeb 
3686dd4f32aeSBjoern A. Zeeb 			param_id = WMI_VDEV_PARAM_BSS_COLOR;
3687dd4f32aeSBjoern A. Zeeb 			if (info->he_bss_color.enabled)
3688dd4f32aeSBjoern A. Zeeb 				param_value = info->he_bss_color.color <<
3689dd4f32aeSBjoern A. Zeeb 						IEEE80211_HE_OPERATION_BSS_COLOR_OFFSET;
3690dd4f32aeSBjoern A. Zeeb 			else
3691dd4f32aeSBjoern A. Zeeb 				param_value = IEEE80211_HE_OPERATION_BSS_COLOR_DISABLED;
3692dd4f32aeSBjoern A. Zeeb 
3693dd4f32aeSBjoern A. Zeeb 			ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
3694dd4f32aeSBjoern A. Zeeb 							    param_id,
3695dd4f32aeSBjoern A. Zeeb 							    param_value);
3696dd4f32aeSBjoern A. Zeeb 			if (ret)
3697dd4f32aeSBjoern A. Zeeb 				ath11k_warn(ar->ab,
3698dd4f32aeSBjoern A. Zeeb 					    "failed to set bss color param on vdev %i: %d\n",
3699dd4f32aeSBjoern A. Zeeb 					    arvif->vdev_id,  ret);
3700dd4f32aeSBjoern A. Zeeb 
3701dd4f32aeSBjoern A. Zeeb 			ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
3702dd4f32aeSBjoern A. Zeeb 				   "bss color param 0x%x set on vdev %i\n",
3703dd4f32aeSBjoern A. Zeeb 				   param_value, arvif->vdev_id);
3704dd4f32aeSBjoern A. Zeeb 		} else if (vif->type == NL80211_IFTYPE_STATION) {
3705dd4f32aeSBjoern A. Zeeb 			ret = ath11k_wmi_send_bss_color_change_enable_cmd(ar,
3706dd4f32aeSBjoern A. Zeeb 									  arvif->vdev_id,
3707dd4f32aeSBjoern A. Zeeb 									  1);
3708dd4f32aeSBjoern A. Zeeb 			if (ret)
3709dd4f32aeSBjoern A. Zeeb 				ath11k_warn(ar->ab, "failed to enable bss color change on vdev %i: %d\n",
3710dd4f32aeSBjoern A. Zeeb 					    arvif->vdev_id,  ret);
3711dd4f32aeSBjoern A. Zeeb 			ret = ath11k_wmi_send_obss_color_collision_cfg_cmd(
3712dd4f32aeSBjoern A. Zeeb 				ar, arvif->vdev_id, 0,
3713dd4f32aeSBjoern A. Zeeb 				ATH11K_BSS_COLOR_COLLISION_DETECTION_STA_PERIOD_MS, 1);
3714dd4f32aeSBjoern A. Zeeb 			if (ret)
3715dd4f32aeSBjoern A. Zeeb 				ath11k_warn(ar->ab, "failed to set bss color collision on vdev %i: %d\n",
3716dd4f32aeSBjoern A. Zeeb 					    arvif->vdev_id,  ret);
3717dd4f32aeSBjoern A. Zeeb 		}
3718dd4f32aeSBjoern A. Zeeb 	}
3719dd4f32aeSBjoern A. Zeeb 
3720*28348caeSBjoern A. Zeeb 	if (changed & BSS_CHANGED_FTM_RESPONDER &&
3721*28348caeSBjoern A. Zeeb 	    arvif->ftm_responder != info->ftm_responder &&
3722*28348caeSBjoern A. Zeeb 	    test_bit(WMI_TLV_SERVICE_RTT, ar->ab->wmi_ab.svc_map) &&
3723*28348caeSBjoern A. Zeeb 	    (vif->type == NL80211_IFTYPE_AP ||
3724*28348caeSBjoern A. Zeeb 	     vif->type == NL80211_IFTYPE_MESH_POINT)) {
3725*28348caeSBjoern A. Zeeb 		arvif->ftm_responder = info->ftm_responder;
3726*28348caeSBjoern A. Zeeb 		param = WMI_VDEV_PARAM_ENABLE_DISABLE_RTT_RESPONDER_ROLE;
3727*28348caeSBjoern A. Zeeb 		ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, param,
3728*28348caeSBjoern A. Zeeb 						    arvif->ftm_responder);
3729*28348caeSBjoern A. Zeeb 		if (ret)
3730*28348caeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "Failed to set ftm responder %i: %d\n",
3731*28348caeSBjoern A. Zeeb 				    arvif->vdev_id, ret);
3732*28348caeSBjoern A. Zeeb 	}
3733*28348caeSBjoern A. Zeeb 
3734dd4f32aeSBjoern A. Zeeb 	if (changed & BSS_CHANGED_FILS_DISCOVERY ||
3735dd4f32aeSBjoern A. Zeeb 	    changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP)
3736dd4f32aeSBjoern A. Zeeb 		ath11k_mac_fils_discovery(arvif, info);
3737dd4f32aeSBjoern A. Zeeb 
3738*28348caeSBjoern A. Zeeb 	if (changed & BSS_CHANGED_ARP_FILTER) {
3739*28348caeSBjoern A. Zeeb 		ipv4_cnt = min(vif->cfg.arp_addr_cnt, ATH11K_IPV4_MAX_COUNT);
3740*28348caeSBjoern A. Zeeb 		memcpy(arvif->arp_ns_offload.ipv4_addr,
3741*28348caeSBjoern A. Zeeb 		       vif->cfg.arp_addr_list,
3742*28348caeSBjoern A. Zeeb 		       ipv4_cnt * sizeof(u32));
3743*28348caeSBjoern A. Zeeb 		memcpy(arvif->arp_ns_offload.mac_addr, vif->addr, ETH_ALEN);
3744*28348caeSBjoern A. Zeeb 		arvif->arp_ns_offload.ipv4_count = ipv4_cnt;
3745*28348caeSBjoern A. Zeeb 
3746*28348caeSBjoern A. Zeeb 		ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "arp_addr_cnt %d vif->addr %pM, offload_addr %pI4\n",
3747*28348caeSBjoern A. Zeeb 			   vif->cfg.arp_addr_cnt,
3748*28348caeSBjoern A. Zeeb 			   vif->addr, arvif->arp_ns_offload.ipv4_addr);
3749*28348caeSBjoern A. Zeeb 	}
3750*28348caeSBjoern A. Zeeb 
3751dd4f32aeSBjoern A. Zeeb 	mutex_unlock(&ar->conf_mutex);
3752dd4f32aeSBjoern A. Zeeb }
3753dd4f32aeSBjoern A. Zeeb 
__ath11k_mac_scan_finish(struct ath11k * ar)3754dd4f32aeSBjoern A. Zeeb void __ath11k_mac_scan_finish(struct ath11k *ar)
3755dd4f32aeSBjoern A. Zeeb {
3756dd4f32aeSBjoern A. Zeeb 	lockdep_assert_held(&ar->data_lock);
3757dd4f32aeSBjoern A. Zeeb 
3758dd4f32aeSBjoern A. Zeeb 	switch (ar->scan.state) {
3759dd4f32aeSBjoern A. Zeeb 	case ATH11K_SCAN_IDLE:
3760dd4f32aeSBjoern A. Zeeb 		break;
3761dd4f32aeSBjoern A. Zeeb 	case ATH11K_SCAN_RUNNING:
3762dd4f32aeSBjoern A. Zeeb 	case ATH11K_SCAN_ABORTING:
3763dd4f32aeSBjoern A. Zeeb 		if (ar->scan.is_roc && ar->scan.roc_notify)
3764dd4f32aeSBjoern A. Zeeb 			ieee80211_remain_on_channel_expired(ar->hw);
3765dd4f32aeSBjoern A. Zeeb 		fallthrough;
3766dd4f32aeSBjoern A. Zeeb 	case ATH11K_SCAN_STARTING:
3767dd4f32aeSBjoern A. Zeeb 		if (!ar->scan.is_roc) {
3768dd4f32aeSBjoern A. Zeeb 			struct cfg80211_scan_info info = {
3769dd4f32aeSBjoern A. Zeeb 				.aborted = ((ar->scan.state ==
3770dd4f32aeSBjoern A. Zeeb 					    ATH11K_SCAN_ABORTING) ||
3771dd4f32aeSBjoern A. Zeeb 					    (ar->scan.state ==
3772dd4f32aeSBjoern A. Zeeb 					    ATH11K_SCAN_STARTING)),
3773dd4f32aeSBjoern A. Zeeb 			};
3774dd4f32aeSBjoern A. Zeeb 
3775dd4f32aeSBjoern A. Zeeb 			ieee80211_scan_completed(ar->hw, &info);
3776dd4f32aeSBjoern A. Zeeb 		}
3777dd4f32aeSBjoern A. Zeeb 
3778dd4f32aeSBjoern A. Zeeb 		ar->scan.state = ATH11K_SCAN_IDLE;
3779dd4f32aeSBjoern A. Zeeb 		ar->scan_channel = NULL;
3780dd4f32aeSBjoern A. Zeeb 		ar->scan.roc_freq = 0;
3781dd4f32aeSBjoern A. Zeeb 		cancel_delayed_work(&ar->scan.timeout);
3782*28348caeSBjoern A. Zeeb 		complete_all(&ar->scan.completed);
3783dd4f32aeSBjoern A. Zeeb 		break;
3784dd4f32aeSBjoern A. Zeeb 	}
3785dd4f32aeSBjoern A. Zeeb }
3786dd4f32aeSBjoern A. Zeeb 
ath11k_mac_scan_finish(struct ath11k * ar)3787dd4f32aeSBjoern A. Zeeb void ath11k_mac_scan_finish(struct ath11k *ar)
3788dd4f32aeSBjoern A. Zeeb {
3789dd4f32aeSBjoern A. Zeeb 	spin_lock_bh(&ar->data_lock);
3790dd4f32aeSBjoern A. Zeeb 	__ath11k_mac_scan_finish(ar);
3791dd4f32aeSBjoern A. Zeeb 	spin_unlock_bh(&ar->data_lock);
3792dd4f32aeSBjoern A. Zeeb }
3793dd4f32aeSBjoern A. Zeeb 
ath11k_scan_stop(struct ath11k * ar)3794dd4f32aeSBjoern A. Zeeb static int ath11k_scan_stop(struct ath11k *ar)
3795dd4f32aeSBjoern A. Zeeb {
3796dd4f32aeSBjoern A. Zeeb 	struct scan_cancel_param arg = {
3797dd4f32aeSBjoern A. Zeeb 		.req_type = WLAN_SCAN_CANCEL_SINGLE,
3798dd4f32aeSBjoern A. Zeeb 		.scan_id = ATH11K_SCAN_ID,
3799dd4f32aeSBjoern A. Zeeb 	};
3800dd4f32aeSBjoern A. Zeeb 	int ret;
3801dd4f32aeSBjoern A. Zeeb 
3802dd4f32aeSBjoern A. Zeeb 	lockdep_assert_held(&ar->conf_mutex);
3803dd4f32aeSBjoern A. Zeeb 
3804dd4f32aeSBjoern A. Zeeb 	/* TODO: Fill other STOP Params */
3805dd4f32aeSBjoern A. Zeeb 	arg.pdev_id = ar->pdev->pdev_id;
3806dd4f32aeSBjoern A. Zeeb 
3807dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_send_scan_stop_cmd(ar, &arg);
3808dd4f32aeSBjoern A. Zeeb 	if (ret) {
3809dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to stop wmi scan: %d\n", ret);
3810dd4f32aeSBjoern A. Zeeb 		goto out;
3811dd4f32aeSBjoern A. Zeeb 	}
3812dd4f32aeSBjoern A. Zeeb 
3813dd4f32aeSBjoern A. Zeeb 	ret = wait_for_completion_timeout(&ar->scan.completed, 3 * HZ);
3814dd4f32aeSBjoern A. Zeeb 	if (ret == 0) {
3815dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab,
3816dd4f32aeSBjoern A. Zeeb 			    "failed to receive scan abort comple: timed out\n");
3817dd4f32aeSBjoern A. Zeeb 		ret = -ETIMEDOUT;
3818dd4f32aeSBjoern A. Zeeb 	} else if (ret > 0) {
3819dd4f32aeSBjoern A. Zeeb 		ret = 0;
3820dd4f32aeSBjoern A. Zeeb 	}
3821dd4f32aeSBjoern A. Zeeb 
3822dd4f32aeSBjoern A. Zeeb out:
3823dd4f32aeSBjoern A. Zeeb 	/* Scan state should be updated upon scan completion but in case
3824dd4f32aeSBjoern A. Zeeb 	 * firmware fails to deliver the event (for whatever reason) it is
3825dd4f32aeSBjoern A. Zeeb 	 * desired to clean up scan state anyway. Firmware may have just
3826dd4f32aeSBjoern A. Zeeb 	 * dropped the scan completion event delivery due to transport pipe
3827dd4f32aeSBjoern A. Zeeb 	 * being overflown with data and/or it can recover on its own before
3828dd4f32aeSBjoern A. Zeeb 	 * next scan request is submitted.
3829dd4f32aeSBjoern A. Zeeb 	 */
3830dd4f32aeSBjoern A. Zeeb 	spin_lock_bh(&ar->data_lock);
3831dd4f32aeSBjoern A. Zeeb 	if (ar->scan.state != ATH11K_SCAN_IDLE)
3832dd4f32aeSBjoern A. Zeeb 		__ath11k_mac_scan_finish(ar);
3833dd4f32aeSBjoern A. Zeeb 	spin_unlock_bh(&ar->data_lock);
3834dd4f32aeSBjoern A. Zeeb 
3835dd4f32aeSBjoern A. Zeeb 	return ret;
3836dd4f32aeSBjoern A. Zeeb }
3837dd4f32aeSBjoern A. Zeeb 
ath11k_scan_abort(struct ath11k * ar)3838dd4f32aeSBjoern A. Zeeb static void ath11k_scan_abort(struct ath11k *ar)
3839dd4f32aeSBjoern A. Zeeb {
3840dd4f32aeSBjoern A. Zeeb 	int ret;
3841dd4f32aeSBjoern A. Zeeb 
3842dd4f32aeSBjoern A. Zeeb 	lockdep_assert_held(&ar->conf_mutex);
3843dd4f32aeSBjoern A. Zeeb 
3844dd4f32aeSBjoern A. Zeeb 	spin_lock_bh(&ar->data_lock);
3845dd4f32aeSBjoern A. Zeeb 
3846dd4f32aeSBjoern A. Zeeb 	switch (ar->scan.state) {
3847dd4f32aeSBjoern A. Zeeb 	case ATH11K_SCAN_IDLE:
3848dd4f32aeSBjoern A. Zeeb 		/* This can happen if timeout worker kicked in and called
3849dd4f32aeSBjoern A. Zeeb 		 * abortion while scan completion was being processed.
3850dd4f32aeSBjoern A. Zeeb 		 */
3851dd4f32aeSBjoern A. Zeeb 		break;
3852dd4f32aeSBjoern A. Zeeb 	case ATH11K_SCAN_STARTING:
3853dd4f32aeSBjoern A. Zeeb 	case ATH11K_SCAN_ABORTING:
3854dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "refusing scan abortion due to invalid scan state: %d\n",
3855dd4f32aeSBjoern A. Zeeb 			    ar->scan.state);
3856dd4f32aeSBjoern A. Zeeb 		break;
3857dd4f32aeSBjoern A. Zeeb 	case ATH11K_SCAN_RUNNING:
3858dd4f32aeSBjoern A. Zeeb 		ar->scan.state = ATH11K_SCAN_ABORTING;
3859dd4f32aeSBjoern A. Zeeb 		spin_unlock_bh(&ar->data_lock);
3860dd4f32aeSBjoern A. Zeeb 
3861dd4f32aeSBjoern A. Zeeb 		ret = ath11k_scan_stop(ar);
3862dd4f32aeSBjoern A. Zeeb 		if (ret)
3863dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "failed to abort scan: %d\n", ret);
3864dd4f32aeSBjoern A. Zeeb 
3865dd4f32aeSBjoern A. Zeeb 		spin_lock_bh(&ar->data_lock);
3866dd4f32aeSBjoern A. Zeeb 		break;
3867dd4f32aeSBjoern A. Zeeb 	}
3868dd4f32aeSBjoern A. Zeeb 
3869dd4f32aeSBjoern A. Zeeb 	spin_unlock_bh(&ar->data_lock);
3870dd4f32aeSBjoern A. Zeeb }
3871dd4f32aeSBjoern A. Zeeb 
ath11k_scan_timeout_work(struct work_struct * work)3872dd4f32aeSBjoern A. Zeeb static void ath11k_scan_timeout_work(struct work_struct *work)
3873dd4f32aeSBjoern A. Zeeb {
3874dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = container_of(work, struct ath11k,
3875dd4f32aeSBjoern A. Zeeb 					 scan.timeout.work);
3876dd4f32aeSBjoern A. Zeeb 
3877dd4f32aeSBjoern A. Zeeb 	mutex_lock(&ar->conf_mutex);
3878dd4f32aeSBjoern A. Zeeb 	ath11k_scan_abort(ar);
3879dd4f32aeSBjoern A. Zeeb 	mutex_unlock(&ar->conf_mutex);
3880dd4f32aeSBjoern A. Zeeb }
3881dd4f32aeSBjoern A. Zeeb 
ath11k_start_scan(struct ath11k * ar,struct scan_req_params * arg)3882dd4f32aeSBjoern A. Zeeb static int ath11k_start_scan(struct ath11k *ar,
3883dd4f32aeSBjoern A. Zeeb 			     struct scan_req_params *arg)
3884dd4f32aeSBjoern A. Zeeb {
3885dd4f32aeSBjoern A. Zeeb 	int ret;
3886dd4f32aeSBjoern A. Zeeb 	unsigned long timeout = 1 * HZ;
3887dd4f32aeSBjoern A. Zeeb 
3888dd4f32aeSBjoern A. Zeeb 	lockdep_assert_held(&ar->conf_mutex);
3889dd4f32aeSBjoern A. Zeeb 
3890dd4f32aeSBjoern A. Zeeb 	if (ath11k_spectral_get_mode(ar) == ATH11K_SPECTRAL_BACKGROUND)
3891dd4f32aeSBjoern A. Zeeb 		ath11k_spectral_reset_buffer(ar);
3892dd4f32aeSBjoern A. Zeeb 
3893dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_send_scan_start_cmd(ar, arg);
3894dd4f32aeSBjoern A. Zeeb 	if (ret)
3895dd4f32aeSBjoern A. Zeeb 		return ret;
3896dd4f32aeSBjoern A. Zeeb 
3897dd4f32aeSBjoern A. Zeeb 	if (test_bit(WMI_TLV_SERVICE_11D_OFFLOAD, ar->ab->wmi_ab.svc_map)) {
3898dd4f32aeSBjoern A. Zeeb 		timeout = 5 * HZ;
3899dd4f32aeSBjoern A. Zeeb 
3900dd4f32aeSBjoern A. Zeeb 		if (ar->supports_6ghz)
3901dd4f32aeSBjoern A. Zeeb 			timeout += 5 * HZ;
3902dd4f32aeSBjoern A. Zeeb 	}
3903dd4f32aeSBjoern A. Zeeb 
3904dd4f32aeSBjoern A. Zeeb 	ret = wait_for_completion_timeout(&ar->scan.started, timeout);
3905dd4f32aeSBjoern A. Zeeb 	if (ret == 0) {
3906dd4f32aeSBjoern A. Zeeb 		ret = ath11k_scan_stop(ar);
3907dd4f32aeSBjoern A. Zeeb 		if (ret)
3908dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "failed to stop scan: %d\n", ret);
3909dd4f32aeSBjoern A. Zeeb 
3910dd4f32aeSBjoern A. Zeeb 		return -ETIMEDOUT;
3911dd4f32aeSBjoern A. Zeeb 	}
3912dd4f32aeSBjoern A. Zeeb 
3913dd4f32aeSBjoern A. Zeeb 	/* If we failed to start the scan, return error code at
3914dd4f32aeSBjoern A. Zeeb 	 * this point.  This is probably due to some issue in the
3915dd4f32aeSBjoern A. Zeeb 	 * firmware, but no need to wedge the driver due to that...
3916dd4f32aeSBjoern A. Zeeb 	 */
3917dd4f32aeSBjoern A. Zeeb 	spin_lock_bh(&ar->data_lock);
3918dd4f32aeSBjoern A. Zeeb 	if (ar->scan.state == ATH11K_SCAN_IDLE) {
3919dd4f32aeSBjoern A. Zeeb 		spin_unlock_bh(&ar->data_lock);
3920dd4f32aeSBjoern A. Zeeb 		return -EINVAL;
3921dd4f32aeSBjoern A. Zeeb 	}
3922dd4f32aeSBjoern A. Zeeb 	spin_unlock_bh(&ar->data_lock);
3923dd4f32aeSBjoern A. Zeeb 
3924dd4f32aeSBjoern A. Zeeb 	return 0;
3925dd4f32aeSBjoern A. Zeeb }
3926dd4f32aeSBjoern A. Zeeb 
ath11k_mac_op_hw_scan(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_scan_request * hw_req)3927dd4f32aeSBjoern A. Zeeb static int ath11k_mac_op_hw_scan(struct ieee80211_hw *hw,
3928dd4f32aeSBjoern A. Zeeb 				 struct ieee80211_vif *vif,
3929dd4f32aeSBjoern A. Zeeb 				 struct ieee80211_scan_request *hw_req)
3930dd4f32aeSBjoern A. Zeeb {
3931dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = hw->priv;
3932dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
3933dd4f32aeSBjoern A. Zeeb 	struct cfg80211_scan_request *req = &hw_req->req;
3934*28348caeSBjoern A. Zeeb 	struct scan_req_params *arg = NULL;
3935dd4f32aeSBjoern A. Zeeb 	int ret = 0;
3936dd4f32aeSBjoern A. Zeeb 	int i;
3937*28348caeSBjoern A. Zeeb 	u32 scan_timeout;
3938*28348caeSBjoern A. Zeeb 
3939*28348caeSBjoern A. Zeeb 	/* Firmwares advertising the support of triggering 11D algorithm
3940*28348caeSBjoern A. Zeeb 	 * on the scan results of a regular scan expects driver to send
3941*28348caeSBjoern A. Zeeb 	 * WMI_11D_SCAN_START_CMDID before sending WMI_START_SCAN_CMDID.
3942*28348caeSBjoern A. Zeeb 	 * With this feature, separate 11D scan can be avoided since
3943*28348caeSBjoern A. Zeeb 	 * regdomain can be determined with the scan results of the
3944*28348caeSBjoern A. Zeeb 	 * regular scan.
3945*28348caeSBjoern A. Zeeb 	 */
3946*28348caeSBjoern A. Zeeb 	if (ar->state_11d == ATH11K_11D_PREPARING &&
3947*28348caeSBjoern A. Zeeb 	    test_bit(WMI_TLV_SERVICE_SUPPORT_11D_FOR_HOST_SCAN,
3948*28348caeSBjoern A. Zeeb 		     ar->ab->wmi_ab.svc_map))
3949*28348caeSBjoern A. Zeeb 		ath11k_mac_11d_scan_start(ar, arvif->vdev_id);
3950dd4f32aeSBjoern A. Zeeb 
3951dd4f32aeSBjoern A. Zeeb 	mutex_lock(&ar->conf_mutex);
3952dd4f32aeSBjoern A. Zeeb 
3953dd4f32aeSBjoern A. Zeeb 	spin_lock_bh(&ar->data_lock);
3954dd4f32aeSBjoern A. Zeeb 	switch (ar->scan.state) {
3955dd4f32aeSBjoern A. Zeeb 	case ATH11K_SCAN_IDLE:
3956dd4f32aeSBjoern A. Zeeb 		reinit_completion(&ar->scan.started);
3957dd4f32aeSBjoern A. Zeeb 		reinit_completion(&ar->scan.completed);
3958dd4f32aeSBjoern A. Zeeb 		ar->scan.state = ATH11K_SCAN_STARTING;
3959dd4f32aeSBjoern A. Zeeb 		ar->scan.is_roc = false;
3960dd4f32aeSBjoern A. Zeeb 		ar->scan.vdev_id = arvif->vdev_id;
3961dd4f32aeSBjoern A. Zeeb 		ret = 0;
3962dd4f32aeSBjoern A. Zeeb 		break;
3963dd4f32aeSBjoern A. Zeeb 	case ATH11K_SCAN_STARTING:
3964dd4f32aeSBjoern A. Zeeb 	case ATH11K_SCAN_RUNNING:
3965dd4f32aeSBjoern A. Zeeb 	case ATH11K_SCAN_ABORTING:
3966dd4f32aeSBjoern A. Zeeb 		ret = -EBUSY;
3967dd4f32aeSBjoern A. Zeeb 		break;
3968dd4f32aeSBjoern A. Zeeb 	}
3969dd4f32aeSBjoern A. Zeeb 	spin_unlock_bh(&ar->data_lock);
3970dd4f32aeSBjoern A. Zeeb 
3971dd4f32aeSBjoern A. Zeeb 	if (ret)
3972dd4f32aeSBjoern A. Zeeb 		goto exit;
3973dd4f32aeSBjoern A. Zeeb 
3974*28348caeSBjoern A. Zeeb 	arg = kzalloc(sizeof(*arg), GFP_KERNEL);
3975dd4f32aeSBjoern A. Zeeb 
3976*28348caeSBjoern A. Zeeb 	if (!arg) {
3977dd4f32aeSBjoern A. Zeeb 		ret = -ENOMEM;
3978dd4f32aeSBjoern A. Zeeb 		goto exit;
3979dd4f32aeSBjoern A. Zeeb 	}
3980*28348caeSBjoern A. Zeeb 
3981*28348caeSBjoern A. Zeeb 	ath11k_wmi_start_scan_init(ar, arg);
3982*28348caeSBjoern A. Zeeb 	arg->vdev_id = arvif->vdev_id;
3983*28348caeSBjoern A. Zeeb 	arg->scan_id = ATH11K_SCAN_ID;
3984*28348caeSBjoern A. Zeeb 
3985*28348caeSBjoern A. Zeeb 	if (req->ie_len) {
3986*28348caeSBjoern A. Zeeb 		arg->extraie.ptr = kmemdup(req->ie, req->ie_len, GFP_KERNEL);
3987*28348caeSBjoern A. Zeeb 		if (!arg->extraie.ptr) {
3988*28348caeSBjoern A. Zeeb 			ret = -ENOMEM;
3989*28348caeSBjoern A. Zeeb 			goto exit;
3990*28348caeSBjoern A. Zeeb 		}
3991*28348caeSBjoern A. Zeeb 		arg->extraie.len = req->ie_len;
3992dd4f32aeSBjoern A. Zeeb 	}
3993dd4f32aeSBjoern A. Zeeb 
3994dd4f32aeSBjoern A. Zeeb 	if (req->n_ssids) {
3995*28348caeSBjoern A. Zeeb 		arg->num_ssids = req->n_ssids;
3996*28348caeSBjoern A. Zeeb 		for (i = 0; i < arg->num_ssids; i++) {
3997*28348caeSBjoern A. Zeeb 			arg->ssid[i].length  = req->ssids[i].ssid_len;
3998*28348caeSBjoern A. Zeeb 			memcpy(&arg->ssid[i].ssid, req->ssids[i].ssid,
3999dd4f32aeSBjoern A. Zeeb 			       req->ssids[i].ssid_len);
4000dd4f32aeSBjoern A. Zeeb 		}
4001dd4f32aeSBjoern A. Zeeb 	} else {
4002*28348caeSBjoern A. Zeeb 		arg->scan_flags |= WMI_SCAN_FLAG_PASSIVE;
4003dd4f32aeSBjoern A. Zeeb 	}
4004dd4f32aeSBjoern A. Zeeb 
4005dd4f32aeSBjoern A. Zeeb 	if (req->n_channels) {
4006*28348caeSBjoern A. Zeeb 		arg->num_chan = req->n_channels;
4007*28348caeSBjoern A. Zeeb 		arg->chan_list = kcalloc(arg->num_chan, sizeof(*arg->chan_list),
4008dd4f32aeSBjoern A. Zeeb 					 GFP_KERNEL);
4009dd4f32aeSBjoern A. Zeeb 
4010*28348caeSBjoern A. Zeeb 		if (!arg->chan_list) {
4011dd4f32aeSBjoern A. Zeeb 			ret = -ENOMEM;
4012dd4f32aeSBjoern A. Zeeb 			goto exit;
4013dd4f32aeSBjoern A. Zeeb 		}
4014dd4f32aeSBjoern A. Zeeb 
4015*28348caeSBjoern A. Zeeb 		for (i = 0; i < arg->num_chan; i++) {
4016*28348caeSBjoern A. Zeeb 			if (test_bit(WMI_TLV_SERVICE_SCAN_CONFIG_PER_CHANNEL,
4017*28348caeSBjoern A. Zeeb 				     ar->ab->wmi_ab.svc_map)) {
4018*28348caeSBjoern A. Zeeb 				arg->chan_list[i] =
4019*28348caeSBjoern A. Zeeb 					u32_encode_bits(req->channels[i]->center_freq,
4020*28348caeSBjoern A. Zeeb 							WMI_SCAN_CONFIG_PER_CHANNEL_MASK);
4021*28348caeSBjoern A. Zeeb 
4022*28348caeSBjoern A. Zeeb 				/* If NL80211_SCAN_FLAG_COLOCATED_6GHZ is set in scan
4023*28348caeSBjoern A. Zeeb 				 * flags, then scan all PSC channels in 6 GHz band and
4024*28348caeSBjoern A. Zeeb 				 * those non-PSC channels where RNR IE is found during
4025*28348caeSBjoern A. Zeeb 				 * the legacy 2.4/5 GHz scan.
4026*28348caeSBjoern A. Zeeb 				 * If NL80211_SCAN_FLAG_COLOCATED_6GHZ is not set,
4027*28348caeSBjoern A. Zeeb 				 * then all channels in 6 GHz will be scanned.
4028*28348caeSBjoern A. Zeeb 				 */
4029*28348caeSBjoern A. Zeeb 				if (req->channels[i]->band == NL80211_BAND_6GHZ &&
4030*28348caeSBjoern A. Zeeb 				    req->flags & NL80211_SCAN_FLAG_COLOCATED_6GHZ &&
4031*28348caeSBjoern A. Zeeb 				    !cfg80211_channel_is_psc(req->channels[i]))
4032*28348caeSBjoern A. Zeeb 					arg->chan_list[i] |=
4033*28348caeSBjoern A. Zeeb 						WMI_SCAN_CH_FLAG_SCAN_ONLY_IF_RNR_FOUND;
4034*28348caeSBjoern A. Zeeb 			} else {
4035*28348caeSBjoern A. Zeeb 				arg->chan_list[i] = req->channels[i]->center_freq;
4036*28348caeSBjoern A. Zeeb 			}
4037*28348caeSBjoern A. Zeeb 		}
4038dd4f32aeSBjoern A. Zeeb 	}
4039dd4f32aeSBjoern A. Zeeb 
4040dd4f32aeSBjoern A. Zeeb 	if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
4041*28348caeSBjoern A. Zeeb 		arg->scan_f_add_spoofed_mac_in_probe = 1;
4042*28348caeSBjoern A. Zeeb 		ether_addr_copy(arg->mac_addr.addr, req->mac_addr);
4043*28348caeSBjoern A. Zeeb 		ether_addr_copy(arg->mac_mask.addr, req->mac_addr_mask);
4044dd4f32aeSBjoern A. Zeeb 	}
4045dd4f32aeSBjoern A. Zeeb 
4046*28348caeSBjoern A. Zeeb 	/* if duration is set, default dwell times will be overwritten */
4047*28348caeSBjoern A. Zeeb 	if (req->duration) {
4048*28348caeSBjoern A. Zeeb 		arg->dwell_time_active = req->duration;
4049*28348caeSBjoern A. Zeeb 		arg->dwell_time_active_2g = req->duration;
4050*28348caeSBjoern A. Zeeb 		arg->dwell_time_active_6g = req->duration;
4051*28348caeSBjoern A. Zeeb 		arg->dwell_time_passive = req->duration;
4052*28348caeSBjoern A. Zeeb 		arg->dwell_time_passive_6g = req->duration;
4053*28348caeSBjoern A. Zeeb 		arg->burst_duration = req->duration;
4054*28348caeSBjoern A. Zeeb 
4055*28348caeSBjoern A. Zeeb 		scan_timeout = min_t(u32, arg->max_rest_time *
4056*28348caeSBjoern A. Zeeb 				(arg->num_chan - 1) + (req->duration +
4057*28348caeSBjoern A. Zeeb 				ATH11K_SCAN_CHANNEL_SWITCH_WMI_EVT_OVERHEAD) *
4058*28348caeSBjoern A. Zeeb 				arg->num_chan, arg->max_scan_time);
4059*28348caeSBjoern A. Zeeb 	} else {
4060*28348caeSBjoern A. Zeeb 		scan_timeout = arg->max_scan_time;
4061*28348caeSBjoern A. Zeeb 	}
4062*28348caeSBjoern A. Zeeb 
4063*28348caeSBjoern A. Zeeb 	/* Add a margin to account for event/command processing */
4064*28348caeSBjoern A. Zeeb 	scan_timeout += ATH11K_MAC_SCAN_CMD_EVT_OVERHEAD;
4065*28348caeSBjoern A. Zeeb 
4066*28348caeSBjoern A. Zeeb 	ret = ath11k_start_scan(ar, arg);
4067dd4f32aeSBjoern A. Zeeb 	if (ret) {
4068dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to start hw scan: %d\n", ret);
4069dd4f32aeSBjoern A. Zeeb 		spin_lock_bh(&ar->data_lock);
4070dd4f32aeSBjoern A. Zeeb 		ar->scan.state = ATH11K_SCAN_IDLE;
4071dd4f32aeSBjoern A. Zeeb 		spin_unlock_bh(&ar->data_lock);
4072dd4f32aeSBjoern A. Zeeb 	}
4073dd4f32aeSBjoern A. Zeeb 
4074dd4f32aeSBjoern A. Zeeb 	ieee80211_queue_delayed_work(ar->hw, &ar->scan.timeout,
4075*28348caeSBjoern A. Zeeb 				     msecs_to_jiffies(scan_timeout));
4076dd4f32aeSBjoern A. Zeeb 
4077dd4f32aeSBjoern A. Zeeb exit:
4078*28348caeSBjoern A. Zeeb 	if (arg) {
4079*28348caeSBjoern A. Zeeb 		kfree(arg->chan_list);
4080*28348caeSBjoern A. Zeeb 		kfree(arg->extraie.ptr);
4081*28348caeSBjoern A. Zeeb 		kfree(arg);
4082*28348caeSBjoern A. Zeeb 	}
4083dd4f32aeSBjoern A. Zeeb 
4084dd4f32aeSBjoern A. Zeeb 	mutex_unlock(&ar->conf_mutex);
4085*28348caeSBjoern A. Zeeb 
4086*28348caeSBjoern A. Zeeb 	if (ar->state_11d == ATH11K_11D_PREPARING)
4087*28348caeSBjoern A. Zeeb 		ath11k_mac_11d_scan_start(ar, arvif->vdev_id);
4088*28348caeSBjoern A. Zeeb 
4089dd4f32aeSBjoern A. Zeeb 	return ret;
4090dd4f32aeSBjoern A. Zeeb }
4091dd4f32aeSBjoern A. Zeeb 
ath11k_mac_op_cancel_hw_scan(struct ieee80211_hw * hw,struct ieee80211_vif * vif)4092dd4f32aeSBjoern A. Zeeb static void ath11k_mac_op_cancel_hw_scan(struct ieee80211_hw *hw,
4093dd4f32aeSBjoern A. Zeeb 					 struct ieee80211_vif *vif)
4094dd4f32aeSBjoern A. Zeeb {
4095dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = hw->priv;
4096dd4f32aeSBjoern A. Zeeb 
4097dd4f32aeSBjoern A. Zeeb 	mutex_lock(&ar->conf_mutex);
4098dd4f32aeSBjoern A. Zeeb 	ath11k_scan_abort(ar);
4099dd4f32aeSBjoern A. Zeeb 	mutex_unlock(&ar->conf_mutex);
4100dd4f32aeSBjoern A. Zeeb 
4101dd4f32aeSBjoern A. Zeeb 	cancel_delayed_work_sync(&ar->scan.timeout);
4102dd4f32aeSBjoern A. Zeeb }
4103dd4f32aeSBjoern A. Zeeb 
ath11k_install_key(struct ath11k_vif * arvif,struct ieee80211_key_conf * key,enum set_key_cmd cmd,const u8 * macaddr,u32 flags)4104dd4f32aeSBjoern A. Zeeb static int ath11k_install_key(struct ath11k_vif *arvif,
4105dd4f32aeSBjoern A. Zeeb 			      struct ieee80211_key_conf *key,
4106dd4f32aeSBjoern A. Zeeb 			      enum set_key_cmd cmd,
4107dd4f32aeSBjoern A. Zeeb 			      const u8 *macaddr, u32 flags)
4108dd4f32aeSBjoern A. Zeeb {
4109dd4f32aeSBjoern A. Zeeb 	int ret;
4110dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = arvif->ar;
4111dd4f32aeSBjoern A. Zeeb 	struct wmi_vdev_install_key_arg arg = {
4112dd4f32aeSBjoern A. Zeeb 		.vdev_id = arvif->vdev_id,
4113dd4f32aeSBjoern A. Zeeb 		.key_idx = key->keyidx,
4114dd4f32aeSBjoern A. Zeeb 		.key_len = key->keylen,
4115dd4f32aeSBjoern A. Zeeb 		.key_data = key->key,
4116dd4f32aeSBjoern A. Zeeb 		.key_flags = flags,
4117dd4f32aeSBjoern A. Zeeb 		.macaddr = macaddr,
4118dd4f32aeSBjoern A. Zeeb 	};
4119dd4f32aeSBjoern A. Zeeb 
4120dd4f32aeSBjoern A. Zeeb 	lockdep_assert_held(&arvif->ar->conf_mutex);
4121dd4f32aeSBjoern A. Zeeb 
4122dd4f32aeSBjoern A. Zeeb 	reinit_completion(&ar->install_key_done);
4123dd4f32aeSBjoern A. Zeeb 
4124dd4f32aeSBjoern A. Zeeb 	if (test_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags))
4125dd4f32aeSBjoern A. Zeeb 		return 0;
4126dd4f32aeSBjoern A. Zeeb 
4127dd4f32aeSBjoern A. Zeeb 	if (cmd == DISABLE_KEY) {
4128dd4f32aeSBjoern A. Zeeb 		arg.key_cipher = WMI_CIPHER_NONE;
4129dd4f32aeSBjoern A. Zeeb 		arg.key_data = NULL;
4130dd4f32aeSBjoern A. Zeeb 		goto install;
4131dd4f32aeSBjoern A. Zeeb 	}
4132dd4f32aeSBjoern A. Zeeb 
4133dd4f32aeSBjoern A. Zeeb 	switch (key->cipher) {
4134dd4f32aeSBjoern A. Zeeb 	case WLAN_CIPHER_SUITE_CCMP:
4135dd4f32aeSBjoern A. Zeeb 		arg.key_cipher = WMI_CIPHER_AES_CCM;
4136dd4f32aeSBjoern A. Zeeb 		/* TODO: Re-check if flag is valid */
4137dd4f32aeSBjoern A. Zeeb 		key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV_MGMT;
4138dd4f32aeSBjoern A. Zeeb 		break;
4139dd4f32aeSBjoern A. Zeeb 	case WLAN_CIPHER_SUITE_TKIP:
4140dd4f32aeSBjoern A. Zeeb 		arg.key_cipher = WMI_CIPHER_TKIP;
4141dd4f32aeSBjoern A. Zeeb 		arg.key_txmic_len = 8;
4142dd4f32aeSBjoern A. Zeeb 		arg.key_rxmic_len = 8;
4143dd4f32aeSBjoern A. Zeeb 		break;
4144dd4f32aeSBjoern A. Zeeb 	case WLAN_CIPHER_SUITE_CCMP_256:
4145dd4f32aeSBjoern A. Zeeb 		arg.key_cipher = WMI_CIPHER_AES_CCM;
4146dd4f32aeSBjoern A. Zeeb 		break;
4147dd4f32aeSBjoern A. Zeeb 	case WLAN_CIPHER_SUITE_GCMP:
4148dd4f32aeSBjoern A. Zeeb 	case WLAN_CIPHER_SUITE_GCMP_256:
4149dd4f32aeSBjoern A. Zeeb 		arg.key_cipher = WMI_CIPHER_AES_GCM;
4150dd4f32aeSBjoern A. Zeeb 		break;
4151dd4f32aeSBjoern A. Zeeb 	default:
4152dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "cipher %d is not supported\n", key->cipher);
4153dd4f32aeSBjoern A. Zeeb 		return -EOPNOTSUPP;
4154dd4f32aeSBjoern A. Zeeb 	}
4155dd4f32aeSBjoern A. Zeeb 
4156dd4f32aeSBjoern A. Zeeb 	if (test_bit(ATH11K_FLAG_RAW_MODE, &ar->ab->dev_flags))
4157dd4f32aeSBjoern A. Zeeb 		key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV |
4158dd4f32aeSBjoern A. Zeeb 			      IEEE80211_KEY_FLAG_RESERVE_TAILROOM;
4159dd4f32aeSBjoern A. Zeeb 
4160dd4f32aeSBjoern A. Zeeb install:
4161dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_vdev_install_key(arvif->ar, &arg);
4162dd4f32aeSBjoern A. Zeeb 
4163dd4f32aeSBjoern A. Zeeb 	if (ret)
4164dd4f32aeSBjoern A. Zeeb 		return ret;
4165dd4f32aeSBjoern A. Zeeb 
4166dd4f32aeSBjoern A. Zeeb 	if (!wait_for_completion_timeout(&ar->install_key_done, 1 * HZ))
4167dd4f32aeSBjoern A. Zeeb 		return -ETIMEDOUT;
4168dd4f32aeSBjoern A. Zeeb 
4169dd4f32aeSBjoern A. Zeeb 	return ar->install_key_status ? -EINVAL : 0;
4170dd4f32aeSBjoern A. Zeeb }
4171dd4f32aeSBjoern A. Zeeb 
ath11k_clear_peer_keys(struct ath11k_vif * arvif,const u8 * addr)4172dd4f32aeSBjoern A. Zeeb static int ath11k_clear_peer_keys(struct ath11k_vif *arvif,
4173dd4f32aeSBjoern A. Zeeb 				  const u8 *addr)
4174dd4f32aeSBjoern A. Zeeb {
4175dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = arvif->ar;
4176dd4f32aeSBjoern A. Zeeb 	struct ath11k_base *ab = ar->ab;
4177dd4f32aeSBjoern A. Zeeb 	struct ath11k_peer *peer;
4178dd4f32aeSBjoern A. Zeeb 	int first_errno = 0;
4179dd4f32aeSBjoern A. Zeeb 	int ret;
4180dd4f32aeSBjoern A. Zeeb 	int i;
4181dd4f32aeSBjoern A. Zeeb 	u32 flags = 0;
4182dd4f32aeSBjoern A. Zeeb 
4183dd4f32aeSBjoern A. Zeeb 	lockdep_assert_held(&ar->conf_mutex);
4184dd4f32aeSBjoern A. Zeeb 
4185dd4f32aeSBjoern A. Zeeb 	spin_lock_bh(&ab->base_lock);
4186dd4f32aeSBjoern A. Zeeb 	peer = ath11k_peer_find(ab, arvif->vdev_id, addr);
4187dd4f32aeSBjoern A. Zeeb 	spin_unlock_bh(&ab->base_lock);
4188dd4f32aeSBjoern A. Zeeb 
4189dd4f32aeSBjoern A. Zeeb 	if (!peer)
4190dd4f32aeSBjoern A. Zeeb 		return -ENOENT;
4191dd4f32aeSBjoern A. Zeeb 
4192dd4f32aeSBjoern A. Zeeb 	for (i = 0; i < ARRAY_SIZE(peer->keys); i++) {
4193dd4f32aeSBjoern A. Zeeb 		if (!peer->keys[i])
4194dd4f32aeSBjoern A. Zeeb 			continue;
4195dd4f32aeSBjoern A. Zeeb 
4196dd4f32aeSBjoern A. Zeeb 		/* key flags are not required to delete the key */
4197dd4f32aeSBjoern A. Zeeb 		ret = ath11k_install_key(arvif, peer->keys[i],
4198dd4f32aeSBjoern A. Zeeb 					 DISABLE_KEY, addr, flags);
4199dd4f32aeSBjoern A. Zeeb 		if (ret < 0 && first_errno == 0)
4200dd4f32aeSBjoern A. Zeeb 			first_errno = ret;
4201dd4f32aeSBjoern A. Zeeb 
4202dd4f32aeSBjoern A. Zeeb 		if (ret < 0)
4203dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ab, "failed to remove peer key %d: %d\n",
4204dd4f32aeSBjoern A. Zeeb 				    i, ret);
4205dd4f32aeSBjoern A. Zeeb 
4206dd4f32aeSBjoern A. Zeeb 		spin_lock_bh(&ab->base_lock);
4207dd4f32aeSBjoern A. Zeeb 		peer->keys[i] = NULL;
4208dd4f32aeSBjoern A. Zeeb 		spin_unlock_bh(&ab->base_lock);
4209dd4f32aeSBjoern A. Zeeb 	}
4210dd4f32aeSBjoern A. Zeeb 
4211dd4f32aeSBjoern A. Zeeb 	return first_errno;
4212dd4f32aeSBjoern A. Zeeb }
4213dd4f32aeSBjoern A. Zeeb 
ath11k_mac_op_set_key(struct ieee80211_hw * hw,enum set_key_cmd cmd,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct ieee80211_key_conf * key)4214dd4f32aeSBjoern A. Zeeb static int ath11k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
4215dd4f32aeSBjoern A. Zeeb 				 struct ieee80211_vif *vif, struct ieee80211_sta *sta,
4216dd4f32aeSBjoern A. Zeeb 				 struct ieee80211_key_conf *key)
4217dd4f32aeSBjoern A. Zeeb {
4218dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = hw->priv;
4219dd4f32aeSBjoern A. Zeeb 	struct ath11k_base *ab = ar->ab;
4220dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
4221dd4f32aeSBjoern A. Zeeb 	struct ath11k_peer *peer;
4222dd4f32aeSBjoern A. Zeeb 	struct ath11k_sta *arsta;
4223dd4f32aeSBjoern A. Zeeb 	const u8 *peer_addr;
4224dd4f32aeSBjoern A. Zeeb 	int ret = 0;
4225dd4f32aeSBjoern A. Zeeb 	u32 flags = 0;
4226dd4f32aeSBjoern A. Zeeb 
4227dd4f32aeSBjoern A. Zeeb 	/* BIP needs to be done in software */
4228dd4f32aeSBjoern A. Zeeb 	if (key->cipher == WLAN_CIPHER_SUITE_AES_CMAC ||
4229dd4f32aeSBjoern A. Zeeb 	    key->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 ||
4230dd4f32aeSBjoern A. Zeeb 	    key->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256 ||
4231dd4f32aeSBjoern A. Zeeb 	    key->cipher == WLAN_CIPHER_SUITE_BIP_CMAC_256)
4232dd4f32aeSBjoern A. Zeeb 		return 1;
4233dd4f32aeSBjoern A. Zeeb 
4234dd4f32aeSBjoern A. Zeeb 	if (test_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags))
4235dd4f32aeSBjoern A. Zeeb 		return 1;
4236dd4f32aeSBjoern A. Zeeb 
4237dd4f32aeSBjoern A. Zeeb 	if (key->keyidx > WMI_MAX_KEY_INDEX)
4238dd4f32aeSBjoern A. Zeeb 		return -ENOSPC;
4239dd4f32aeSBjoern A. Zeeb 
4240dd4f32aeSBjoern A. Zeeb 	mutex_lock(&ar->conf_mutex);
4241dd4f32aeSBjoern A. Zeeb 
4242dd4f32aeSBjoern A. Zeeb 	if (sta)
4243dd4f32aeSBjoern A. Zeeb 		peer_addr = sta->addr;
4244dd4f32aeSBjoern A. Zeeb 	else if (arvif->vdev_type == WMI_VDEV_TYPE_STA)
4245dd4f32aeSBjoern A. Zeeb 		peer_addr = vif->bss_conf.bssid;
4246dd4f32aeSBjoern A. Zeeb 	else
4247dd4f32aeSBjoern A. Zeeb 		peer_addr = vif->addr;
4248dd4f32aeSBjoern A. Zeeb 
4249dd4f32aeSBjoern A. Zeeb 	key->hw_key_idx = key->keyidx;
4250dd4f32aeSBjoern A. Zeeb 
4251dd4f32aeSBjoern A. Zeeb 	/* the peer should not disappear in mid-way (unless FW goes awry) since
4252dd4f32aeSBjoern A. Zeeb 	 * we already hold conf_mutex. we just make sure its there now.
4253dd4f32aeSBjoern A. Zeeb 	 */
4254dd4f32aeSBjoern A. Zeeb 	spin_lock_bh(&ab->base_lock);
4255dd4f32aeSBjoern A. Zeeb 	peer = ath11k_peer_find(ab, arvif->vdev_id, peer_addr);
4256dd4f32aeSBjoern A. Zeeb 
4257dd4f32aeSBjoern A. Zeeb 	/* flush the fragments cache during key (re)install to
4258dd4f32aeSBjoern A. Zeeb 	 * ensure all frags in the new frag list belong to the same key.
4259dd4f32aeSBjoern A. Zeeb 	 */
4260dd4f32aeSBjoern A. Zeeb 	if (peer && sta && cmd == SET_KEY)
4261dd4f32aeSBjoern A. Zeeb 		ath11k_peer_frags_flush(ar, peer);
4262dd4f32aeSBjoern A. Zeeb 	spin_unlock_bh(&ab->base_lock);
4263dd4f32aeSBjoern A. Zeeb 
4264dd4f32aeSBjoern A. Zeeb 	if (!peer) {
4265dd4f32aeSBjoern A. Zeeb 		if (cmd == SET_KEY) {
4266dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ab, "cannot install key for non-existent peer %pM\n",
4267dd4f32aeSBjoern A. Zeeb 				    peer_addr);
4268dd4f32aeSBjoern A. Zeeb 			ret = -EOPNOTSUPP;
4269dd4f32aeSBjoern A. Zeeb 			goto exit;
4270dd4f32aeSBjoern A. Zeeb 		} else {
4271dd4f32aeSBjoern A. Zeeb 			/* if the peer doesn't exist there is no key to disable
4272dd4f32aeSBjoern A. Zeeb 			 * anymore
4273dd4f32aeSBjoern A. Zeeb 			 */
4274dd4f32aeSBjoern A. Zeeb 			goto exit;
4275dd4f32aeSBjoern A. Zeeb 		}
4276dd4f32aeSBjoern A. Zeeb 	}
4277dd4f32aeSBjoern A. Zeeb 
4278dd4f32aeSBjoern A. Zeeb 	if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
4279dd4f32aeSBjoern A. Zeeb 		flags |= WMI_KEY_PAIRWISE;
4280dd4f32aeSBjoern A. Zeeb 	else
4281dd4f32aeSBjoern A. Zeeb 		flags |= WMI_KEY_GROUP;
4282dd4f32aeSBjoern A. Zeeb 
4283dd4f32aeSBjoern A. Zeeb 	ret = ath11k_install_key(arvif, key, cmd, peer_addr, flags);
4284dd4f32aeSBjoern A. Zeeb 	if (ret) {
4285dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ab, "ath11k_install_key failed (%d)\n", ret);
4286dd4f32aeSBjoern A. Zeeb 		goto exit;
4287dd4f32aeSBjoern A. Zeeb 	}
4288dd4f32aeSBjoern A. Zeeb 
4289dd4f32aeSBjoern A. Zeeb 	ret = ath11k_dp_peer_rx_pn_replay_config(arvif, peer_addr, cmd, key);
4290dd4f32aeSBjoern A. Zeeb 	if (ret) {
4291dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ab, "failed to offload PN replay detection %d\n", ret);
4292dd4f32aeSBjoern A. Zeeb 		goto exit;
4293dd4f32aeSBjoern A. Zeeb 	}
4294dd4f32aeSBjoern A. Zeeb 
4295dd4f32aeSBjoern A. Zeeb 	spin_lock_bh(&ab->base_lock);
4296dd4f32aeSBjoern A. Zeeb 	peer = ath11k_peer_find(ab, arvif->vdev_id, peer_addr);
4297dd4f32aeSBjoern A. Zeeb 	if (peer && cmd == SET_KEY) {
4298dd4f32aeSBjoern A. Zeeb 		peer->keys[key->keyidx] = key;
4299dd4f32aeSBjoern A. Zeeb 		if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
4300dd4f32aeSBjoern A. Zeeb 			peer->ucast_keyidx = key->keyidx;
4301dd4f32aeSBjoern A. Zeeb 			peer->sec_type = ath11k_dp_tx_get_encrypt_type(key->cipher);
4302dd4f32aeSBjoern A. Zeeb 		} else {
4303dd4f32aeSBjoern A. Zeeb 			peer->mcast_keyidx = key->keyidx;
4304dd4f32aeSBjoern A. Zeeb 			peer->sec_type_grp = ath11k_dp_tx_get_encrypt_type(key->cipher);
4305dd4f32aeSBjoern A. Zeeb 		}
4306dd4f32aeSBjoern A. Zeeb 	} else if (peer && cmd == DISABLE_KEY) {
4307dd4f32aeSBjoern A. Zeeb 		peer->keys[key->keyidx] = NULL;
4308dd4f32aeSBjoern A. Zeeb 		if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
4309dd4f32aeSBjoern A. Zeeb 			peer->ucast_keyidx = 0;
4310dd4f32aeSBjoern A. Zeeb 		else
4311dd4f32aeSBjoern A. Zeeb 			peer->mcast_keyidx = 0;
4312dd4f32aeSBjoern A. Zeeb 	} else if (!peer)
4313dd4f32aeSBjoern A. Zeeb 		/* impossible unless FW goes crazy */
4314dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ab, "peer %pM disappeared!\n", peer_addr);
4315dd4f32aeSBjoern A. Zeeb 
4316dd4f32aeSBjoern A. Zeeb 	if (sta) {
4317dd4f32aeSBjoern A. Zeeb 		arsta = (struct ath11k_sta *)sta->drv_priv;
4318dd4f32aeSBjoern A. Zeeb 
4319dd4f32aeSBjoern A. Zeeb 		switch (key->cipher) {
4320dd4f32aeSBjoern A. Zeeb 		case WLAN_CIPHER_SUITE_TKIP:
4321dd4f32aeSBjoern A. Zeeb 		case WLAN_CIPHER_SUITE_CCMP:
4322dd4f32aeSBjoern A. Zeeb 		case WLAN_CIPHER_SUITE_CCMP_256:
4323dd4f32aeSBjoern A. Zeeb 		case WLAN_CIPHER_SUITE_GCMP:
4324dd4f32aeSBjoern A. Zeeb 		case WLAN_CIPHER_SUITE_GCMP_256:
4325dd4f32aeSBjoern A. Zeeb 			if (cmd == SET_KEY)
4326dd4f32aeSBjoern A. Zeeb 				arsta->pn_type = HAL_PN_TYPE_WPA;
4327dd4f32aeSBjoern A. Zeeb 			else
4328dd4f32aeSBjoern A. Zeeb 				arsta->pn_type = HAL_PN_TYPE_NONE;
4329dd4f32aeSBjoern A. Zeeb 			break;
4330dd4f32aeSBjoern A. Zeeb 		default:
4331dd4f32aeSBjoern A. Zeeb 			arsta->pn_type = HAL_PN_TYPE_NONE;
4332dd4f32aeSBjoern A. Zeeb 			break;
4333dd4f32aeSBjoern A. Zeeb 		}
4334dd4f32aeSBjoern A. Zeeb 	}
4335dd4f32aeSBjoern A. Zeeb 
4336dd4f32aeSBjoern A. Zeeb 	spin_unlock_bh(&ab->base_lock);
4337dd4f32aeSBjoern A. Zeeb 
4338dd4f32aeSBjoern A. Zeeb exit:
4339dd4f32aeSBjoern A. Zeeb 	mutex_unlock(&ar->conf_mutex);
4340dd4f32aeSBjoern A. Zeeb 	return ret;
4341dd4f32aeSBjoern A. Zeeb }
4342dd4f32aeSBjoern A. Zeeb 
4343dd4f32aeSBjoern A. Zeeb static int
ath11k_mac_bitrate_mask_num_ht_rates(struct ath11k * ar,enum nl80211_band band,const struct cfg80211_bitrate_mask * mask)4344*28348caeSBjoern A. Zeeb ath11k_mac_bitrate_mask_num_ht_rates(struct ath11k *ar,
4345*28348caeSBjoern A. Zeeb 				     enum nl80211_band band,
4346*28348caeSBjoern A. Zeeb 				     const struct cfg80211_bitrate_mask *mask)
4347*28348caeSBjoern A. Zeeb {
4348*28348caeSBjoern A. Zeeb 	int num_rates = 0;
4349*28348caeSBjoern A. Zeeb 	int i;
4350*28348caeSBjoern A. Zeeb 
4351*28348caeSBjoern A. Zeeb 	for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++)
4352*28348caeSBjoern A. Zeeb 		num_rates += hweight8(mask->control[band].ht_mcs[i]);
4353*28348caeSBjoern A. Zeeb 
4354*28348caeSBjoern A. Zeeb 	return num_rates;
4355*28348caeSBjoern A. Zeeb }
4356*28348caeSBjoern A. Zeeb 
4357*28348caeSBjoern A. Zeeb static int
ath11k_mac_bitrate_mask_num_vht_rates(struct ath11k * ar,enum nl80211_band band,const struct cfg80211_bitrate_mask * mask)4358dd4f32aeSBjoern A. Zeeb ath11k_mac_bitrate_mask_num_vht_rates(struct ath11k *ar,
4359dd4f32aeSBjoern A. Zeeb 				      enum nl80211_band band,
4360dd4f32aeSBjoern A. Zeeb 				      const struct cfg80211_bitrate_mask *mask)
4361dd4f32aeSBjoern A. Zeeb {
4362dd4f32aeSBjoern A. Zeeb 	int num_rates = 0;
4363dd4f32aeSBjoern A. Zeeb 	int i;
4364dd4f32aeSBjoern A. Zeeb 
4365dd4f32aeSBjoern A. Zeeb 	for (i = 0; i < ARRAY_SIZE(mask->control[band].vht_mcs); i++)
4366dd4f32aeSBjoern A. Zeeb 		num_rates += hweight16(mask->control[band].vht_mcs[i]);
4367dd4f32aeSBjoern A. Zeeb 
4368dd4f32aeSBjoern A. Zeeb 	return num_rates;
4369dd4f32aeSBjoern A. Zeeb }
4370dd4f32aeSBjoern A. Zeeb 
4371dd4f32aeSBjoern A. Zeeb static int
ath11k_mac_bitrate_mask_num_he_rates(struct ath11k * ar,enum nl80211_band band,const struct cfg80211_bitrate_mask * mask)4372dd4f32aeSBjoern A. Zeeb ath11k_mac_bitrate_mask_num_he_rates(struct ath11k *ar,
4373dd4f32aeSBjoern A. Zeeb 				     enum nl80211_band band,
4374dd4f32aeSBjoern A. Zeeb 				     const struct cfg80211_bitrate_mask *mask)
4375dd4f32aeSBjoern A. Zeeb {
4376dd4f32aeSBjoern A. Zeeb 	int num_rates = 0;
4377dd4f32aeSBjoern A. Zeeb 	int i;
4378dd4f32aeSBjoern A. Zeeb 
4379dd4f32aeSBjoern A. Zeeb 	for (i = 0; i < ARRAY_SIZE(mask->control[band].he_mcs); i++)
4380dd4f32aeSBjoern A. Zeeb 		num_rates += hweight16(mask->control[band].he_mcs[i]);
4381dd4f32aeSBjoern A. Zeeb 
4382dd4f32aeSBjoern A. Zeeb 	return num_rates;
4383dd4f32aeSBjoern A. Zeeb }
4384dd4f32aeSBjoern A. Zeeb 
4385dd4f32aeSBjoern A. Zeeb static int
ath11k_mac_set_peer_vht_fixed_rate(struct ath11k_vif * arvif,struct ieee80211_sta * sta,const struct cfg80211_bitrate_mask * mask,enum nl80211_band band)4386dd4f32aeSBjoern A. Zeeb ath11k_mac_set_peer_vht_fixed_rate(struct ath11k_vif *arvif,
4387dd4f32aeSBjoern A. Zeeb 				   struct ieee80211_sta *sta,
4388dd4f32aeSBjoern A. Zeeb 				   const struct cfg80211_bitrate_mask *mask,
4389dd4f32aeSBjoern A. Zeeb 				   enum nl80211_band band)
4390dd4f32aeSBjoern A. Zeeb {
4391dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = arvif->ar;
4392dd4f32aeSBjoern A. Zeeb 	u8 vht_rate, nss;
4393dd4f32aeSBjoern A. Zeeb 	u32 rate_code;
4394dd4f32aeSBjoern A. Zeeb 	int ret, i;
4395dd4f32aeSBjoern A. Zeeb 
4396dd4f32aeSBjoern A. Zeeb 	lockdep_assert_held(&ar->conf_mutex);
4397dd4f32aeSBjoern A. Zeeb 
4398dd4f32aeSBjoern A. Zeeb 	nss = 0;
4399dd4f32aeSBjoern A. Zeeb 
4400dd4f32aeSBjoern A. Zeeb 	for (i = 0; i < ARRAY_SIZE(mask->control[band].vht_mcs); i++) {
4401dd4f32aeSBjoern A. Zeeb 		if (hweight16(mask->control[band].vht_mcs[i]) == 1) {
4402dd4f32aeSBjoern A. Zeeb 			nss = i + 1;
4403dd4f32aeSBjoern A. Zeeb 			vht_rate = ffs(mask->control[band].vht_mcs[i]) - 1;
4404dd4f32aeSBjoern A. Zeeb 		}
4405dd4f32aeSBjoern A. Zeeb 	}
4406dd4f32aeSBjoern A. Zeeb 
4407dd4f32aeSBjoern A. Zeeb 	if (!nss) {
4408dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "No single VHT Fixed rate found to set for %pM",
4409dd4f32aeSBjoern A. Zeeb 			    sta->addr);
4410dd4f32aeSBjoern A. Zeeb 		return -EINVAL;
4411dd4f32aeSBjoern A. Zeeb 	}
4412dd4f32aeSBjoern A. Zeeb 
4413dd4f32aeSBjoern A. Zeeb 	/* Avoid updating invalid nss as fixed rate*/
4414dd4f32aeSBjoern A. Zeeb 	if (nss > sta->deflink.rx_nss)
4415dd4f32aeSBjoern A. Zeeb 		return -EINVAL;
4416dd4f32aeSBjoern A. Zeeb 
4417dd4f32aeSBjoern A. Zeeb 	ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
4418dd4f32aeSBjoern A. Zeeb 		   "Setting Fixed VHT Rate for peer %pM. Device will not switch to any other selected rates",
4419dd4f32aeSBjoern A. Zeeb 		   sta->addr);
4420dd4f32aeSBjoern A. Zeeb 
4421dd4f32aeSBjoern A. Zeeb 	rate_code = ATH11K_HW_RATE_CODE(vht_rate, nss - 1,
4422dd4f32aeSBjoern A. Zeeb 					WMI_RATE_PREAMBLE_VHT);
4423dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_set_peer_param(ar, sta->addr,
4424dd4f32aeSBjoern A. Zeeb 					arvif->vdev_id,
4425dd4f32aeSBjoern A. Zeeb 					WMI_PEER_PARAM_FIXED_RATE,
4426dd4f32aeSBjoern A. Zeeb 					rate_code);
4427dd4f32aeSBjoern A. Zeeb 	if (ret)
4428dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab,
4429dd4f32aeSBjoern A. Zeeb 			    "failed to update STA %pM Fixed Rate %d: %d\n",
4430dd4f32aeSBjoern A. Zeeb 			     sta->addr, rate_code, ret);
4431dd4f32aeSBjoern A. Zeeb 
4432dd4f32aeSBjoern A. Zeeb 	return ret;
4433dd4f32aeSBjoern A. Zeeb }
4434dd4f32aeSBjoern A. Zeeb 
4435dd4f32aeSBjoern A. Zeeb static int
ath11k_mac_set_peer_he_fixed_rate(struct ath11k_vif * arvif,struct ieee80211_sta * sta,const struct cfg80211_bitrate_mask * mask,enum nl80211_band band)4436dd4f32aeSBjoern A. Zeeb ath11k_mac_set_peer_he_fixed_rate(struct ath11k_vif *arvif,
4437dd4f32aeSBjoern A. Zeeb 				  struct ieee80211_sta *sta,
4438dd4f32aeSBjoern A. Zeeb 				  const struct cfg80211_bitrate_mask *mask,
4439dd4f32aeSBjoern A. Zeeb 				  enum nl80211_band band)
4440dd4f32aeSBjoern A. Zeeb {
4441dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = arvif->ar;
4442dd4f32aeSBjoern A. Zeeb 	u8 he_rate, nss;
4443dd4f32aeSBjoern A. Zeeb 	u32 rate_code;
4444dd4f32aeSBjoern A. Zeeb 	int ret, i;
4445dd4f32aeSBjoern A. Zeeb 
4446dd4f32aeSBjoern A. Zeeb 	lockdep_assert_held(&ar->conf_mutex);
4447dd4f32aeSBjoern A. Zeeb 
4448dd4f32aeSBjoern A. Zeeb 	nss = 0;
4449dd4f32aeSBjoern A. Zeeb 
4450dd4f32aeSBjoern A. Zeeb 	for (i = 0; i < ARRAY_SIZE(mask->control[band].he_mcs); i++) {
4451dd4f32aeSBjoern A. Zeeb 		if (hweight16(mask->control[band].he_mcs[i]) == 1) {
4452dd4f32aeSBjoern A. Zeeb 			nss = i + 1;
4453dd4f32aeSBjoern A. Zeeb 			he_rate = ffs(mask->control[band].he_mcs[i]) - 1;
4454dd4f32aeSBjoern A. Zeeb 		}
4455dd4f32aeSBjoern A. Zeeb 	}
4456dd4f32aeSBjoern A. Zeeb 
4457dd4f32aeSBjoern A. Zeeb 	if (!nss) {
4458dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "No single he fixed rate found to set for %pM",
4459dd4f32aeSBjoern A. Zeeb 			    sta->addr);
4460dd4f32aeSBjoern A. Zeeb 		return -EINVAL;
4461dd4f32aeSBjoern A. Zeeb 	}
4462dd4f32aeSBjoern A. Zeeb 
4463dd4f32aeSBjoern A. Zeeb 	/* Avoid updating invalid nss as fixed rate */
4464dd4f32aeSBjoern A. Zeeb 	if (nss > sta->deflink.rx_nss)
4465dd4f32aeSBjoern A. Zeeb 		return -EINVAL;
4466dd4f32aeSBjoern A. Zeeb 
4467dd4f32aeSBjoern A. Zeeb 	ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
4468*28348caeSBjoern A. Zeeb 		   "setting fixed he rate for peer %pM, device will not switch to any other selected rates",
4469dd4f32aeSBjoern A. Zeeb 		   sta->addr);
4470dd4f32aeSBjoern A. Zeeb 
4471dd4f32aeSBjoern A. Zeeb 	rate_code = ATH11K_HW_RATE_CODE(he_rate, nss - 1,
4472dd4f32aeSBjoern A. Zeeb 					WMI_RATE_PREAMBLE_HE);
4473dd4f32aeSBjoern A. Zeeb 
4474dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_set_peer_param(ar, sta->addr,
4475dd4f32aeSBjoern A. Zeeb 					arvif->vdev_id,
4476dd4f32aeSBjoern A. Zeeb 					WMI_PEER_PARAM_FIXED_RATE,
4477dd4f32aeSBjoern A. Zeeb 					rate_code);
4478dd4f32aeSBjoern A. Zeeb 	if (ret)
4479dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab,
4480dd4f32aeSBjoern A. Zeeb 			    "failed to update sta %pM fixed rate %d: %d\n",
4481dd4f32aeSBjoern A. Zeeb 			    sta->addr, rate_code, ret);
4482dd4f32aeSBjoern A. Zeeb 
4483dd4f32aeSBjoern A. Zeeb 	return ret;
4484dd4f32aeSBjoern A. Zeeb }
4485dd4f32aeSBjoern A. Zeeb 
4486*28348caeSBjoern A. Zeeb static int
ath11k_mac_set_peer_ht_fixed_rate(struct ath11k_vif * arvif,struct ieee80211_sta * sta,const struct cfg80211_bitrate_mask * mask,enum nl80211_band band)4487*28348caeSBjoern A. Zeeb ath11k_mac_set_peer_ht_fixed_rate(struct ath11k_vif *arvif,
4488*28348caeSBjoern A. Zeeb 				  struct ieee80211_sta *sta,
4489*28348caeSBjoern A. Zeeb 				  const struct cfg80211_bitrate_mask *mask,
4490*28348caeSBjoern A. Zeeb 				  enum nl80211_band band)
4491*28348caeSBjoern A. Zeeb {
4492*28348caeSBjoern A. Zeeb 	struct ath11k *ar = arvif->ar;
4493*28348caeSBjoern A. Zeeb 	u8 ht_rate, nss = 0;
4494*28348caeSBjoern A. Zeeb 	u32 rate_code;
4495*28348caeSBjoern A. Zeeb 	int ret, i;
4496*28348caeSBjoern A. Zeeb 
4497*28348caeSBjoern A. Zeeb 	lockdep_assert_held(&ar->conf_mutex);
4498*28348caeSBjoern A. Zeeb 
4499*28348caeSBjoern A. Zeeb 	for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++) {
4500*28348caeSBjoern A. Zeeb 		if (hweight8(mask->control[band].ht_mcs[i]) == 1) {
4501*28348caeSBjoern A. Zeeb 			nss = i + 1;
4502*28348caeSBjoern A. Zeeb 			ht_rate = ffs(mask->control[band].ht_mcs[i]) - 1;
4503*28348caeSBjoern A. Zeeb 		}
4504*28348caeSBjoern A. Zeeb 	}
4505*28348caeSBjoern A. Zeeb 
4506*28348caeSBjoern A. Zeeb 	if (!nss) {
4507*28348caeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "No single HT Fixed rate found to set for %pM",
4508*28348caeSBjoern A. Zeeb 			    sta->addr);
4509*28348caeSBjoern A. Zeeb 		return -EINVAL;
4510*28348caeSBjoern A. Zeeb 	}
4511*28348caeSBjoern A. Zeeb 
4512*28348caeSBjoern A. Zeeb 	/* Avoid updating invalid nss as fixed rate*/
4513*28348caeSBjoern A. Zeeb 	if (nss > sta->deflink.rx_nss)
4514*28348caeSBjoern A. Zeeb 		return -EINVAL;
4515*28348caeSBjoern A. Zeeb 
4516*28348caeSBjoern A. Zeeb 	ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
4517*28348caeSBjoern A. Zeeb 		   "Setting Fixed HT Rate for peer %pM. Device will not switch to any other selected rates",
4518*28348caeSBjoern A. Zeeb 		   sta->addr);
4519*28348caeSBjoern A. Zeeb 
4520*28348caeSBjoern A. Zeeb 	rate_code = ATH11K_HW_RATE_CODE(ht_rate, nss - 1,
4521*28348caeSBjoern A. Zeeb 					WMI_RATE_PREAMBLE_HT);
4522*28348caeSBjoern A. Zeeb 	ret = ath11k_wmi_set_peer_param(ar, sta->addr,
4523*28348caeSBjoern A. Zeeb 					arvif->vdev_id,
4524*28348caeSBjoern A. Zeeb 					WMI_PEER_PARAM_FIXED_RATE,
4525*28348caeSBjoern A. Zeeb 					rate_code);
4526*28348caeSBjoern A. Zeeb 	if (ret)
4527*28348caeSBjoern A. Zeeb 		ath11k_warn(ar->ab,
4528*28348caeSBjoern A. Zeeb 			    "failed to update STA %pM HT Fixed Rate %d: %d\n",
4529*28348caeSBjoern A. Zeeb 			    sta->addr, rate_code, ret);
4530*28348caeSBjoern A. Zeeb 
4531*28348caeSBjoern A. Zeeb 	return ret;
4532*28348caeSBjoern A. Zeeb }
4533*28348caeSBjoern A. Zeeb 
ath11k_station_assoc(struct ath11k * ar,struct ieee80211_vif * vif,struct ieee80211_sta * sta,bool reassoc)4534dd4f32aeSBjoern A. Zeeb static int ath11k_station_assoc(struct ath11k *ar,
4535dd4f32aeSBjoern A. Zeeb 				struct ieee80211_vif *vif,
4536dd4f32aeSBjoern A. Zeeb 				struct ieee80211_sta *sta,
4537dd4f32aeSBjoern A. Zeeb 				bool reassoc)
4538dd4f32aeSBjoern A. Zeeb {
4539dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
4540dd4f32aeSBjoern A. Zeeb 	struct peer_assoc_params peer_arg;
4541dd4f32aeSBjoern A. Zeeb 	int ret = 0;
4542dd4f32aeSBjoern A. Zeeb 	struct cfg80211_chan_def def;
4543dd4f32aeSBjoern A. Zeeb 	enum nl80211_band band;
4544dd4f32aeSBjoern A. Zeeb 	struct cfg80211_bitrate_mask *mask;
4545*28348caeSBjoern A. Zeeb 	u8 num_ht_rates, num_vht_rates, num_he_rates;
4546dd4f32aeSBjoern A. Zeeb 
4547dd4f32aeSBjoern A. Zeeb 	lockdep_assert_held(&ar->conf_mutex);
4548dd4f32aeSBjoern A. Zeeb 
4549dd4f32aeSBjoern A. Zeeb 	if (WARN_ON(ath11k_mac_vif_chan(vif, &def)))
4550dd4f32aeSBjoern A. Zeeb 		return -EPERM;
4551dd4f32aeSBjoern A. Zeeb 
4552dd4f32aeSBjoern A. Zeeb 	band = def.chan->band;
4553dd4f32aeSBjoern A. Zeeb 	mask = &arvif->bitrate_mask;
4554dd4f32aeSBjoern A. Zeeb 
4555dd4f32aeSBjoern A. Zeeb 	ath11k_peer_assoc_prepare(ar, vif, sta, &peer_arg, reassoc);
4556dd4f32aeSBjoern A. Zeeb 
4557dd4f32aeSBjoern A. Zeeb 	peer_arg.is_assoc = true;
4558dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_send_peer_assoc_cmd(ar, &peer_arg);
4559dd4f32aeSBjoern A. Zeeb 	if (ret) {
4560dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to run peer assoc for STA %pM vdev %i: %d\n",
4561dd4f32aeSBjoern A. Zeeb 			    sta->addr, arvif->vdev_id, ret);
4562dd4f32aeSBjoern A. Zeeb 		return ret;
4563dd4f32aeSBjoern A. Zeeb 	}
4564dd4f32aeSBjoern A. Zeeb 
4565dd4f32aeSBjoern A. Zeeb 	if (!wait_for_completion_timeout(&ar->peer_assoc_done, 1 * HZ)) {
4566dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to get peer assoc conf event for %pM vdev %i\n",
4567dd4f32aeSBjoern A. Zeeb 			    sta->addr, arvif->vdev_id);
4568dd4f32aeSBjoern A. Zeeb 		return -ETIMEDOUT;
4569dd4f32aeSBjoern A. Zeeb 	}
4570dd4f32aeSBjoern A. Zeeb 
4571dd4f32aeSBjoern A. Zeeb 	num_vht_rates = ath11k_mac_bitrate_mask_num_vht_rates(ar, band, mask);
4572dd4f32aeSBjoern A. Zeeb 	num_he_rates = ath11k_mac_bitrate_mask_num_he_rates(ar, band, mask);
4573*28348caeSBjoern A. Zeeb 	num_ht_rates = ath11k_mac_bitrate_mask_num_ht_rates(ar, band, mask);
4574dd4f32aeSBjoern A. Zeeb 
4575dd4f32aeSBjoern A. Zeeb 	/* If single VHT/HE rate is configured (by set_bitrate_mask()),
4576dd4f32aeSBjoern A. Zeeb 	 * peer_assoc will disable VHT/HE. This is now enabled by a peer specific
4577dd4f32aeSBjoern A. Zeeb 	 * fixed param.
4578dd4f32aeSBjoern A. Zeeb 	 * Note that all other rates and NSS will be disabled for this peer.
4579dd4f32aeSBjoern A. Zeeb 	 */
4580dd4f32aeSBjoern A. Zeeb 	if (sta->deflink.vht_cap.vht_supported && num_vht_rates == 1) {
4581dd4f32aeSBjoern A. Zeeb 		ret = ath11k_mac_set_peer_vht_fixed_rate(arvif, sta, mask,
4582dd4f32aeSBjoern A. Zeeb 							 band);
4583dd4f32aeSBjoern A. Zeeb 		if (ret)
4584dd4f32aeSBjoern A. Zeeb 			return ret;
4585dd4f32aeSBjoern A. Zeeb 	} else if (sta->deflink.he_cap.has_he && num_he_rates == 1) {
4586dd4f32aeSBjoern A. Zeeb 		ret = ath11k_mac_set_peer_he_fixed_rate(arvif, sta, mask,
4587dd4f32aeSBjoern A. Zeeb 							band);
4588dd4f32aeSBjoern A. Zeeb 		if (ret)
4589dd4f32aeSBjoern A. Zeeb 			return ret;
4590*28348caeSBjoern A. Zeeb 	} else if (sta->deflink.ht_cap.ht_supported && num_ht_rates == 1) {
4591*28348caeSBjoern A. Zeeb 		ret = ath11k_mac_set_peer_ht_fixed_rate(arvif, sta, mask,
4592*28348caeSBjoern A. Zeeb 							band);
4593*28348caeSBjoern A. Zeeb 		if (ret)
4594*28348caeSBjoern A. Zeeb 			return ret;
4595dd4f32aeSBjoern A. Zeeb 	}
4596dd4f32aeSBjoern A. Zeeb 
4597dd4f32aeSBjoern A. Zeeb 	/* Re-assoc is run only to update supported rates for given station. It
4598dd4f32aeSBjoern A. Zeeb 	 * doesn't make much sense to reconfigure the peer completely.
4599dd4f32aeSBjoern A. Zeeb 	 */
4600dd4f32aeSBjoern A. Zeeb 	if (reassoc)
4601dd4f32aeSBjoern A. Zeeb 		return 0;
4602dd4f32aeSBjoern A. Zeeb 
4603dd4f32aeSBjoern A. Zeeb 	ret = ath11k_setup_peer_smps(ar, arvif, sta->addr,
4604dd4f32aeSBjoern A. Zeeb 				     &sta->deflink.ht_cap,
4605dd4f32aeSBjoern A. Zeeb 				     le16_to_cpu(sta->deflink.he_6ghz_capa.capa));
4606dd4f32aeSBjoern A. Zeeb 	if (ret) {
4607dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to setup peer SMPS for vdev %d: %d\n",
4608dd4f32aeSBjoern A. Zeeb 			    arvif->vdev_id, ret);
4609dd4f32aeSBjoern A. Zeeb 		return ret;
4610dd4f32aeSBjoern A. Zeeb 	}
4611dd4f32aeSBjoern A. Zeeb 
4612dd4f32aeSBjoern A. Zeeb 	if (!sta->wme) {
4613dd4f32aeSBjoern A. Zeeb 		arvif->num_legacy_stations++;
4614dd4f32aeSBjoern A. Zeeb 		ret = ath11k_recalc_rtscts_prot(arvif);
4615dd4f32aeSBjoern A. Zeeb 		if (ret)
4616dd4f32aeSBjoern A. Zeeb 			return ret;
4617dd4f32aeSBjoern A. Zeeb 	}
4618dd4f32aeSBjoern A. Zeeb 
4619dd4f32aeSBjoern A. Zeeb 	if (sta->wme && sta->uapsd_queues) {
4620dd4f32aeSBjoern A. Zeeb 		ret = ath11k_peer_assoc_qos_ap(ar, arvif, sta);
4621dd4f32aeSBjoern A. Zeeb 		if (ret) {
4622dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "failed to set qos params for STA %pM for vdev %i: %d\n",
4623dd4f32aeSBjoern A. Zeeb 				    sta->addr, arvif->vdev_id, ret);
4624dd4f32aeSBjoern A. Zeeb 			return ret;
4625dd4f32aeSBjoern A. Zeeb 		}
4626dd4f32aeSBjoern A. Zeeb 	}
4627dd4f32aeSBjoern A. Zeeb 
4628dd4f32aeSBjoern A. Zeeb 	return 0;
4629dd4f32aeSBjoern A. Zeeb }
4630dd4f32aeSBjoern A. Zeeb 
ath11k_station_disassoc(struct ath11k * ar,struct ieee80211_vif * vif,struct ieee80211_sta * sta)4631dd4f32aeSBjoern A. Zeeb static int ath11k_station_disassoc(struct ath11k *ar,
4632dd4f32aeSBjoern A. Zeeb 				   struct ieee80211_vif *vif,
4633dd4f32aeSBjoern A. Zeeb 				   struct ieee80211_sta *sta)
4634dd4f32aeSBjoern A. Zeeb {
4635dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif = (void *)vif->drv_priv;
4636dd4f32aeSBjoern A. Zeeb 	int ret = 0;
4637dd4f32aeSBjoern A. Zeeb 
4638dd4f32aeSBjoern A. Zeeb 	lockdep_assert_held(&ar->conf_mutex);
4639dd4f32aeSBjoern A. Zeeb 
4640dd4f32aeSBjoern A. Zeeb 	if (!sta->wme) {
4641dd4f32aeSBjoern A. Zeeb 		arvif->num_legacy_stations--;
4642dd4f32aeSBjoern A. Zeeb 		ret = ath11k_recalc_rtscts_prot(arvif);
4643dd4f32aeSBjoern A. Zeeb 		if (ret)
4644dd4f32aeSBjoern A. Zeeb 			return ret;
4645dd4f32aeSBjoern A. Zeeb 	}
4646dd4f32aeSBjoern A. Zeeb 
4647dd4f32aeSBjoern A. Zeeb 	ret = ath11k_clear_peer_keys(arvif, sta->addr);
4648dd4f32aeSBjoern A. Zeeb 	if (ret) {
4649dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to clear all peer keys for vdev %i: %d\n",
4650dd4f32aeSBjoern A. Zeeb 			    arvif->vdev_id, ret);
4651dd4f32aeSBjoern A. Zeeb 		return ret;
4652dd4f32aeSBjoern A. Zeeb 	}
4653dd4f32aeSBjoern A. Zeeb 	return 0;
4654dd4f32aeSBjoern A. Zeeb }
4655dd4f32aeSBjoern A. Zeeb 
ath11k_sta_rc_update_wk(struct work_struct * wk)4656dd4f32aeSBjoern A. Zeeb static void ath11k_sta_rc_update_wk(struct work_struct *wk)
4657dd4f32aeSBjoern A. Zeeb {
4658dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar;
4659dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif;
4660dd4f32aeSBjoern A. Zeeb 	struct ath11k_sta *arsta;
4661dd4f32aeSBjoern A. Zeeb 	struct ieee80211_sta *sta;
4662dd4f32aeSBjoern A. Zeeb 	struct cfg80211_chan_def def;
4663dd4f32aeSBjoern A. Zeeb 	enum nl80211_band band;
4664dd4f32aeSBjoern A. Zeeb 	const u8 *ht_mcs_mask;
4665dd4f32aeSBjoern A. Zeeb 	const u16 *vht_mcs_mask;
4666dd4f32aeSBjoern A. Zeeb 	const u16 *he_mcs_mask;
4667*28348caeSBjoern A. Zeeb 	u32 changed, bw, nss, smps, bw_prev;
4668*28348caeSBjoern A. Zeeb 	int err, num_ht_rates, num_vht_rates, num_he_rates;
4669dd4f32aeSBjoern A. Zeeb 	const struct cfg80211_bitrate_mask *mask;
4670dd4f32aeSBjoern A. Zeeb 	struct peer_assoc_params peer_arg;
4671*28348caeSBjoern A. Zeeb 	enum wmi_phy_mode peer_phymode;
4672dd4f32aeSBjoern A. Zeeb 
4673dd4f32aeSBjoern A. Zeeb 	arsta = container_of(wk, struct ath11k_sta, update_wk);
4674dd4f32aeSBjoern A. Zeeb 	sta = container_of((void *)arsta, struct ieee80211_sta, drv_priv);
4675dd4f32aeSBjoern A. Zeeb 	arvif = arsta->arvif;
4676dd4f32aeSBjoern A. Zeeb 	ar = arvif->ar;
4677dd4f32aeSBjoern A. Zeeb 
4678dd4f32aeSBjoern A. Zeeb 	if (WARN_ON(ath11k_mac_vif_chan(arvif->vif, &def)))
4679dd4f32aeSBjoern A. Zeeb 		return;
4680dd4f32aeSBjoern A. Zeeb 
4681dd4f32aeSBjoern A. Zeeb 	band = def.chan->band;
4682dd4f32aeSBjoern A. Zeeb 	ht_mcs_mask = arvif->bitrate_mask.control[band].ht_mcs;
4683dd4f32aeSBjoern A. Zeeb 	vht_mcs_mask = arvif->bitrate_mask.control[band].vht_mcs;
4684dd4f32aeSBjoern A. Zeeb 	he_mcs_mask = arvif->bitrate_mask.control[band].he_mcs;
4685dd4f32aeSBjoern A. Zeeb 
4686dd4f32aeSBjoern A. Zeeb 	spin_lock_bh(&ar->data_lock);
4687dd4f32aeSBjoern A. Zeeb 
4688dd4f32aeSBjoern A. Zeeb 	changed = arsta->changed;
4689dd4f32aeSBjoern A. Zeeb 	arsta->changed = 0;
4690dd4f32aeSBjoern A. Zeeb 
4691dd4f32aeSBjoern A. Zeeb 	bw = arsta->bw;
4692*28348caeSBjoern A. Zeeb 	bw_prev = arsta->bw_prev;
4693dd4f32aeSBjoern A. Zeeb 	nss = arsta->nss;
4694dd4f32aeSBjoern A. Zeeb 	smps = arsta->smps;
4695dd4f32aeSBjoern A. Zeeb 
4696dd4f32aeSBjoern A. Zeeb 	spin_unlock_bh(&ar->data_lock);
4697dd4f32aeSBjoern A. Zeeb 
4698dd4f32aeSBjoern A. Zeeb 	mutex_lock(&ar->conf_mutex);
4699dd4f32aeSBjoern A. Zeeb 
4700dd4f32aeSBjoern A. Zeeb 	nss = max_t(u32, 1, nss);
4701dd4f32aeSBjoern A. Zeeb 	nss = min(nss, max(max(ath11k_mac_max_ht_nss(ht_mcs_mask),
4702dd4f32aeSBjoern A. Zeeb 			       ath11k_mac_max_vht_nss(vht_mcs_mask)),
4703dd4f32aeSBjoern A. Zeeb 			   ath11k_mac_max_he_nss(he_mcs_mask)));
4704dd4f32aeSBjoern A. Zeeb 
4705dd4f32aeSBjoern A. Zeeb 	if (changed & IEEE80211_RC_BW_CHANGED) {
4706*28348caeSBjoern A. Zeeb 		/* Get the peer phymode */
4707*28348caeSBjoern A. Zeeb 		ath11k_peer_assoc_h_phymode(ar, arvif->vif, sta, &peer_arg);
4708*28348caeSBjoern A. Zeeb 		peer_phymode = peer_arg.peer_phymode;
4709dd4f32aeSBjoern A. Zeeb 
4710*28348caeSBjoern A. Zeeb 		ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "update sta %pM peer bw %d phymode %d\n",
4711*28348caeSBjoern A. Zeeb 			   sta->addr, bw, peer_phymode);
4712*28348caeSBjoern A. Zeeb 
4713*28348caeSBjoern A. Zeeb 		if (bw > bw_prev) {
4714*28348caeSBjoern A. Zeeb 			/* BW is upgraded. In this case we send WMI_PEER_PHYMODE
4715*28348caeSBjoern A. Zeeb 			 * followed by WMI_PEER_CHWIDTH
4716*28348caeSBjoern A. Zeeb 			 */
4717*28348caeSBjoern A. Zeeb 			ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "BW upgrade for sta %pM new BW %d, old BW %d\n",
4718*28348caeSBjoern A. Zeeb 				   sta->addr, bw, bw_prev);
4719*28348caeSBjoern A. Zeeb 
4720*28348caeSBjoern A. Zeeb 			err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,
4721*28348caeSBjoern A. Zeeb 							WMI_PEER_PHYMODE, peer_phymode);
4722*28348caeSBjoern A. Zeeb 
4723dd4f32aeSBjoern A. Zeeb 			if (err) {
4724*28348caeSBjoern A. Zeeb 				ath11k_warn(ar->ab, "failed to update STA %pM peer phymode %d: %d\n",
4725*28348caeSBjoern A. Zeeb 					    sta->addr, peer_phymode, err);
4726*28348caeSBjoern A. Zeeb 				goto err_rc_bw_changed;
4727*28348caeSBjoern A. Zeeb 			}
4728*28348caeSBjoern A. Zeeb 
4729dd4f32aeSBjoern A. Zeeb 			err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,
4730dd4f32aeSBjoern A. Zeeb 							WMI_PEER_CHWIDTH, bw);
4731*28348caeSBjoern A. Zeeb 
4732dd4f32aeSBjoern A. Zeeb 			if (err)
4733dd4f32aeSBjoern A. Zeeb 				ath11k_warn(ar->ab, "failed to update STA %pM peer bw %d: %d\n",
4734dd4f32aeSBjoern A. Zeeb 					    sta->addr, bw, err);
4735dd4f32aeSBjoern A. Zeeb 		} else {
4736*28348caeSBjoern A. Zeeb 			/* BW is downgraded. In this case we send WMI_PEER_CHWIDTH
4737*28348caeSBjoern A. Zeeb 			 * followed by WMI_PEER_PHYMODE
4738*28348caeSBjoern A. Zeeb 			 */
4739*28348caeSBjoern A. Zeeb 			ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "BW downgrade for sta %pM new BW %d,old BW %d\n",
4740*28348caeSBjoern A. Zeeb 				   sta->addr, bw, bw_prev);
4741*28348caeSBjoern A. Zeeb 
4742*28348caeSBjoern A. Zeeb 			err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,
4743*28348caeSBjoern A. Zeeb 							WMI_PEER_CHWIDTH, bw);
4744*28348caeSBjoern A. Zeeb 
4745*28348caeSBjoern A. Zeeb 			if (err) {
4746*28348caeSBjoern A. Zeeb 				ath11k_warn(ar->ab, "failed to update STA %pM peer bw %d: %d\n",
4747*28348caeSBjoern A. Zeeb 					    sta->addr, bw, err);
4748*28348caeSBjoern A. Zeeb 				goto err_rc_bw_changed;
4749*28348caeSBjoern A. Zeeb 			}
4750*28348caeSBjoern A. Zeeb 
4751*28348caeSBjoern A. Zeeb 			err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,
4752*28348caeSBjoern A. Zeeb 							WMI_PEER_PHYMODE, peer_phymode);
4753*28348caeSBjoern A. Zeeb 
4754*28348caeSBjoern A. Zeeb 			if (err)
4755*28348caeSBjoern A. Zeeb 				ath11k_warn(ar->ab, "failed to update STA %pM peer phymode %d: %d\n",
4756*28348caeSBjoern A. Zeeb 					    sta->addr, peer_phymode, err);
4757dd4f32aeSBjoern A. Zeeb 		}
4758dd4f32aeSBjoern A. Zeeb 	}
4759dd4f32aeSBjoern A. Zeeb 
4760dd4f32aeSBjoern A. Zeeb 	if (changed & IEEE80211_RC_NSS_CHANGED) {
4761*28348caeSBjoern A. Zeeb 		ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "update sta %pM nss %d\n",
4762dd4f32aeSBjoern A. Zeeb 			   sta->addr, nss);
4763dd4f32aeSBjoern A. Zeeb 
4764dd4f32aeSBjoern A. Zeeb 		err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,
4765dd4f32aeSBjoern A. Zeeb 						WMI_PEER_NSS, nss);
4766dd4f32aeSBjoern A. Zeeb 		if (err)
4767dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "failed to update STA %pM nss %d: %d\n",
4768dd4f32aeSBjoern A. Zeeb 				    sta->addr, nss, err);
4769dd4f32aeSBjoern A. Zeeb 	}
4770dd4f32aeSBjoern A. Zeeb 
4771dd4f32aeSBjoern A. Zeeb 	if (changed & IEEE80211_RC_SMPS_CHANGED) {
4772*28348caeSBjoern A. Zeeb 		ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "update sta %pM smps %d\n",
4773dd4f32aeSBjoern A. Zeeb 			   sta->addr, smps);
4774dd4f32aeSBjoern A. Zeeb 
4775dd4f32aeSBjoern A. Zeeb 		err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,
4776dd4f32aeSBjoern A. Zeeb 						WMI_PEER_MIMO_PS_STATE, smps);
4777dd4f32aeSBjoern A. Zeeb 		if (err)
4778dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "failed to update STA %pM smps %d: %d\n",
4779dd4f32aeSBjoern A. Zeeb 				    sta->addr, smps, err);
4780dd4f32aeSBjoern A. Zeeb 	}
4781dd4f32aeSBjoern A. Zeeb 
4782dd4f32aeSBjoern A. Zeeb 	if (changed & IEEE80211_RC_SUPP_RATES_CHANGED) {
4783dd4f32aeSBjoern A. Zeeb 		mask = &arvif->bitrate_mask;
4784*28348caeSBjoern A. Zeeb 		num_ht_rates = ath11k_mac_bitrate_mask_num_ht_rates(ar, band,
4785*28348caeSBjoern A. Zeeb 								    mask);
4786dd4f32aeSBjoern A. Zeeb 		num_vht_rates = ath11k_mac_bitrate_mask_num_vht_rates(ar, band,
4787dd4f32aeSBjoern A. Zeeb 								      mask);
4788dd4f32aeSBjoern A. Zeeb 		num_he_rates = ath11k_mac_bitrate_mask_num_he_rates(ar, band,
4789dd4f32aeSBjoern A. Zeeb 								    mask);
4790dd4f32aeSBjoern A. Zeeb 
4791dd4f32aeSBjoern A. Zeeb 		/* Peer_assoc_prepare will reject vht rates in
4792dd4f32aeSBjoern A. Zeeb 		 * bitrate_mask if its not available in range format and
4793dd4f32aeSBjoern A. Zeeb 		 * sets vht tx_rateset as unsupported. So multiple VHT MCS
4794dd4f32aeSBjoern A. Zeeb 		 * setting(eg. MCS 4,5,6) per peer is not supported here.
4795dd4f32aeSBjoern A. Zeeb 		 * But, Single rate in VHT mask can be set as per-peer
4796dd4f32aeSBjoern A. Zeeb 		 * fixed rate. But even if any HT rates are configured in
4797dd4f32aeSBjoern A. Zeeb 		 * the bitrate mask, device will not switch to those rates
4798dd4f32aeSBjoern A. Zeeb 		 * when per-peer Fixed rate is set.
4799dd4f32aeSBjoern A. Zeeb 		 * TODO: Check RATEMASK_CMDID to support auto rates selection
4800dd4f32aeSBjoern A. Zeeb 		 * across HT/VHT and for multiple VHT MCS support.
4801dd4f32aeSBjoern A. Zeeb 		 */
4802dd4f32aeSBjoern A. Zeeb 		if (sta->deflink.vht_cap.vht_supported && num_vht_rates == 1) {
4803dd4f32aeSBjoern A. Zeeb 			ath11k_mac_set_peer_vht_fixed_rate(arvif, sta, mask,
4804dd4f32aeSBjoern A. Zeeb 							   band);
4805dd4f32aeSBjoern A. Zeeb 		} else if (sta->deflink.he_cap.has_he && num_he_rates == 1) {
4806dd4f32aeSBjoern A. Zeeb 			ath11k_mac_set_peer_he_fixed_rate(arvif, sta, mask,
4807dd4f32aeSBjoern A. Zeeb 							  band);
4808*28348caeSBjoern A. Zeeb 		} else if (sta->deflink.ht_cap.ht_supported && num_ht_rates == 1) {
4809*28348caeSBjoern A. Zeeb 			ath11k_mac_set_peer_ht_fixed_rate(arvif, sta, mask,
4810*28348caeSBjoern A. Zeeb 							  band);
4811dd4f32aeSBjoern A. Zeeb 		} else {
4812dd4f32aeSBjoern A. Zeeb 			/* If the peer is non-VHT/HE or no fixed VHT/HE rate
4813dd4f32aeSBjoern A. Zeeb 			 * is provided in the new bitrate mask we set the
4814dd4f32aeSBjoern A. Zeeb 			 * other rates using peer_assoc command. Also clear
4815dd4f32aeSBjoern A. Zeeb 			 * the peer fixed rate settings as it has higher proprity
4816dd4f32aeSBjoern A. Zeeb 			 * than peer assoc
4817dd4f32aeSBjoern A. Zeeb 			 */
4818dd4f32aeSBjoern A. Zeeb 			err = ath11k_wmi_set_peer_param(ar, sta->addr,
4819dd4f32aeSBjoern A. Zeeb 							arvif->vdev_id,
4820dd4f32aeSBjoern A. Zeeb 							WMI_PEER_PARAM_FIXED_RATE,
4821dd4f32aeSBjoern A. Zeeb 							WMI_FIXED_RATE_NONE);
4822dd4f32aeSBjoern A. Zeeb 			if (err)
4823dd4f32aeSBjoern A. Zeeb 				ath11k_warn(ar->ab,
4824dd4f32aeSBjoern A. Zeeb 					    "failed to disable peer fixed rate for sta %pM: %d\n",
4825dd4f32aeSBjoern A. Zeeb 					    sta->addr, err);
4826dd4f32aeSBjoern A. Zeeb 
4827dd4f32aeSBjoern A. Zeeb 			ath11k_peer_assoc_prepare(ar, arvif->vif, sta,
4828dd4f32aeSBjoern A. Zeeb 						  &peer_arg, true);
4829dd4f32aeSBjoern A. Zeeb 
4830dd4f32aeSBjoern A. Zeeb 			peer_arg.is_assoc = false;
4831dd4f32aeSBjoern A. Zeeb 			err = ath11k_wmi_send_peer_assoc_cmd(ar, &peer_arg);
4832dd4f32aeSBjoern A. Zeeb 			if (err)
4833dd4f32aeSBjoern A. Zeeb 				ath11k_warn(ar->ab, "failed to run peer assoc for STA %pM vdev %i: %d\n",
4834dd4f32aeSBjoern A. Zeeb 					    sta->addr, arvif->vdev_id, err);
4835dd4f32aeSBjoern A. Zeeb 
4836dd4f32aeSBjoern A. Zeeb 			if (!wait_for_completion_timeout(&ar->peer_assoc_done, 1 * HZ))
4837dd4f32aeSBjoern A. Zeeb 				ath11k_warn(ar->ab, "failed to get peer assoc conf event for %pM vdev %i\n",
4838dd4f32aeSBjoern A. Zeeb 					    sta->addr, arvif->vdev_id);
4839dd4f32aeSBjoern A. Zeeb 		}
4840dd4f32aeSBjoern A. Zeeb 	}
4841dd4f32aeSBjoern A. Zeeb 
4842*28348caeSBjoern A. Zeeb err_rc_bw_changed:
4843dd4f32aeSBjoern A. Zeeb 	mutex_unlock(&ar->conf_mutex);
4844dd4f32aeSBjoern A. Zeeb }
4845dd4f32aeSBjoern A. Zeeb 
ath11k_sta_set_4addr_wk(struct work_struct * wk)4846dd4f32aeSBjoern A. Zeeb static void ath11k_sta_set_4addr_wk(struct work_struct *wk)
4847dd4f32aeSBjoern A. Zeeb {
4848dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar;
4849dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif;
4850dd4f32aeSBjoern A. Zeeb 	struct ath11k_sta *arsta;
4851dd4f32aeSBjoern A. Zeeb 	struct ieee80211_sta *sta;
4852dd4f32aeSBjoern A. Zeeb 	int ret = 0;
4853dd4f32aeSBjoern A. Zeeb 
4854dd4f32aeSBjoern A. Zeeb 	arsta = container_of(wk, struct ath11k_sta, set_4addr_wk);
4855dd4f32aeSBjoern A. Zeeb 	sta = container_of((void *)arsta, struct ieee80211_sta, drv_priv);
4856dd4f32aeSBjoern A. Zeeb 	arvif = arsta->arvif;
4857dd4f32aeSBjoern A. Zeeb 	ar = arvif->ar;
4858dd4f32aeSBjoern A. Zeeb 
4859dd4f32aeSBjoern A. Zeeb 	ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
4860dd4f32aeSBjoern A. Zeeb 		   "setting USE_4ADDR for peer %pM\n", sta->addr);
4861dd4f32aeSBjoern A. Zeeb 
4862dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_set_peer_param(ar, sta->addr,
4863dd4f32aeSBjoern A. Zeeb 					arvif->vdev_id,
4864dd4f32aeSBjoern A. Zeeb 					WMI_PEER_USE_4ADDR, 1);
4865dd4f32aeSBjoern A. Zeeb 
4866dd4f32aeSBjoern A. Zeeb 	if (ret)
4867dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to set peer %pM 4addr capability: %d\n",
4868dd4f32aeSBjoern A. Zeeb 			    sta->addr, ret);
4869dd4f32aeSBjoern A. Zeeb }
4870dd4f32aeSBjoern A. Zeeb 
ath11k_mac_inc_num_stations(struct ath11k_vif * arvif,struct ieee80211_sta * sta)4871dd4f32aeSBjoern A. Zeeb static int ath11k_mac_inc_num_stations(struct ath11k_vif *arvif,
4872dd4f32aeSBjoern A. Zeeb 				       struct ieee80211_sta *sta)
4873dd4f32aeSBjoern A. Zeeb {
4874dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = arvif->ar;
4875dd4f32aeSBjoern A. Zeeb 
4876dd4f32aeSBjoern A. Zeeb 	lockdep_assert_held(&ar->conf_mutex);
4877dd4f32aeSBjoern A. Zeeb 
4878dd4f32aeSBjoern A. Zeeb 	if (arvif->vdev_type == WMI_VDEV_TYPE_STA && !sta->tdls)
4879dd4f32aeSBjoern A. Zeeb 		return 0;
4880dd4f32aeSBjoern A. Zeeb 
4881dd4f32aeSBjoern A. Zeeb 	if (ar->num_stations >= ar->max_num_stations)
4882dd4f32aeSBjoern A. Zeeb 		return -ENOBUFS;
4883dd4f32aeSBjoern A. Zeeb 
4884dd4f32aeSBjoern A. Zeeb 	ar->num_stations++;
4885dd4f32aeSBjoern A. Zeeb 
4886dd4f32aeSBjoern A. Zeeb 	return 0;
4887dd4f32aeSBjoern A. Zeeb }
4888dd4f32aeSBjoern A. Zeeb 
ath11k_mac_dec_num_stations(struct ath11k_vif * arvif,struct ieee80211_sta * sta)4889dd4f32aeSBjoern A. Zeeb static void ath11k_mac_dec_num_stations(struct ath11k_vif *arvif,
4890dd4f32aeSBjoern A. Zeeb 					struct ieee80211_sta *sta)
4891dd4f32aeSBjoern A. Zeeb {
4892dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = arvif->ar;
4893dd4f32aeSBjoern A. Zeeb 
4894dd4f32aeSBjoern A. Zeeb 	lockdep_assert_held(&ar->conf_mutex);
4895dd4f32aeSBjoern A. Zeeb 
4896dd4f32aeSBjoern A. Zeeb 	if (arvif->vdev_type == WMI_VDEV_TYPE_STA && !sta->tdls)
4897dd4f32aeSBjoern A. Zeeb 		return;
4898dd4f32aeSBjoern A. Zeeb 
4899dd4f32aeSBjoern A. Zeeb 	ar->num_stations--;
4900dd4f32aeSBjoern A. Zeeb }
4901dd4f32aeSBjoern A. Zeeb 
ath11k_mac_station_add(struct ath11k * ar,struct ieee80211_vif * vif,struct ieee80211_sta * sta)4902dd4f32aeSBjoern A. Zeeb static int ath11k_mac_station_add(struct ath11k *ar,
4903dd4f32aeSBjoern A. Zeeb 				  struct ieee80211_vif *vif,
4904dd4f32aeSBjoern A. Zeeb 				  struct ieee80211_sta *sta)
4905dd4f32aeSBjoern A. Zeeb {
4906dd4f32aeSBjoern A. Zeeb 	struct ath11k_base *ab = ar->ab;
4907dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
4908dd4f32aeSBjoern A. Zeeb 	struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
4909dd4f32aeSBjoern A. Zeeb 	struct peer_create_params peer_param;
4910dd4f32aeSBjoern A. Zeeb 	int ret;
4911dd4f32aeSBjoern A. Zeeb 
4912dd4f32aeSBjoern A. Zeeb 	lockdep_assert_held(&ar->conf_mutex);
4913dd4f32aeSBjoern A. Zeeb 
4914dd4f32aeSBjoern A. Zeeb 	ret = ath11k_mac_inc_num_stations(arvif, sta);
4915dd4f32aeSBjoern A. Zeeb 	if (ret) {
4916dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ab, "refusing to associate station: too many connected already (%d)\n",
4917dd4f32aeSBjoern A. Zeeb 			    ar->max_num_stations);
4918dd4f32aeSBjoern A. Zeeb 		goto exit;
4919dd4f32aeSBjoern A. Zeeb 	}
4920dd4f32aeSBjoern A. Zeeb 
4921dd4f32aeSBjoern A. Zeeb 	arsta->rx_stats = kzalloc(sizeof(*arsta->rx_stats), GFP_KERNEL);
4922dd4f32aeSBjoern A. Zeeb 	if (!arsta->rx_stats) {
4923dd4f32aeSBjoern A. Zeeb 		ret = -ENOMEM;
4924dd4f32aeSBjoern A. Zeeb 		goto dec_num_station;
4925dd4f32aeSBjoern A. Zeeb 	}
4926dd4f32aeSBjoern A. Zeeb 
4927dd4f32aeSBjoern A. Zeeb 	peer_param.vdev_id = arvif->vdev_id;
4928dd4f32aeSBjoern A. Zeeb 	peer_param.peer_addr = sta->addr;
4929dd4f32aeSBjoern A. Zeeb 	peer_param.peer_type = WMI_PEER_TYPE_DEFAULT;
4930dd4f32aeSBjoern A. Zeeb 
4931dd4f32aeSBjoern A. Zeeb 	ret = ath11k_peer_create(ar, arvif, sta, &peer_param);
4932dd4f32aeSBjoern A. Zeeb 	if (ret) {
4933dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ab, "Failed to add peer: %pM for VDEV: %d\n",
4934dd4f32aeSBjoern A. Zeeb 			    sta->addr, arvif->vdev_id);
4935dd4f32aeSBjoern A. Zeeb 		goto free_rx_stats;
4936dd4f32aeSBjoern A. Zeeb 	}
4937dd4f32aeSBjoern A. Zeeb 
4938dd4f32aeSBjoern A. Zeeb 	ath11k_dbg(ab, ATH11K_DBG_MAC, "Added peer: %pM for VDEV: %d\n",
4939dd4f32aeSBjoern A. Zeeb 		   sta->addr, arvif->vdev_id);
4940dd4f32aeSBjoern A. Zeeb 
4941dd4f32aeSBjoern A. Zeeb 	if (ath11k_debugfs_is_extd_tx_stats_enabled(ar)) {
4942dd4f32aeSBjoern A. Zeeb 		arsta->tx_stats = kzalloc(sizeof(*arsta->tx_stats), GFP_KERNEL);
4943dd4f32aeSBjoern A. Zeeb 		if (!arsta->tx_stats) {
4944dd4f32aeSBjoern A. Zeeb 			ret = -ENOMEM;
4945dd4f32aeSBjoern A. Zeeb 			goto free_peer;
4946dd4f32aeSBjoern A. Zeeb 		}
4947dd4f32aeSBjoern A. Zeeb 	}
4948dd4f32aeSBjoern A. Zeeb 
4949dd4f32aeSBjoern A. Zeeb 	if (ieee80211_vif_is_mesh(vif)) {
4950dd4f32aeSBjoern A. Zeeb 		ath11k_dbg(ab, ATH11K_DBG_MAC,
4951dd4f32aeSBjoern A. Zeeb 			   "setting USE_4ADDR for mesh STA %pM\n", sta->addr);
4952dd4f32aeSBjoern A. Zeeb 		ret = ath11k_wmi_set_peer_param(ar, sta->addr,
4953dd4f32aeSBjoern A. Zeeb 						arvif->vdev_id,
4954dd4f32aeSBjoern A. Zeeb 						WMI_PEER_USE_4ADDR, 1);
4955dd4f32aeSBjoern A. Zeeb 		if (ret) {
4956dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ab, "failed to set mesh STA %pM 4addr capability: %d\n",
4957dd4f32aeSBjoern A. Zeeb 				    sta->addr, ret);
4958dd4f32aeSBjoern A. Zeeb 			goto free_tx_stats;
4959dd4f32aeSBjoern A. Zeeb 		}
4960dd4f32aeSBjoern A. Zeeb 	}
4961dd4f32aeSBjoern A. Zeeb 
4962dd4f32aeSBjoern A. Zeeb 	ret = ath11k_dp_peer_setup(ar, arvif->vdev_id, sta->addr);
4963dd4f32aeSBjoern A. Zeeb 	if (ret) {
4964dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ab, "failed to setup dp for peer %pM on vdev %i (%d)\n",
4965dd4f32aeSBjoern A. Zeeb 			    sta->addr, arvif->vdev_id, ret);
4966dd4f32aeSBjoern A. Zeeb 		goto free_tx_stats;
4967dd4f32aeSBjoern A. Zeeb 	}
4968dd4f32aeSBjoern A. Zeeb 
4969dd4f32aeSBjoern A. Zeeb 	if (ab->hw_params.vdev_start_delay &&
4970dd4f32aeSBjoern A. Zeeb 	    !arvif->is_started &&
4971dd4f32aeSBjoern A. Zeeb 	    arvif->vdev_type != WMI_VDEV_TYPE_AP) {
4972dd4f32aeSBjoern A. Zeeb 		ret = ath11k_start_vdev_delay(ar->hw, vif);
4973dd4f32aeSBjoern A. Zeeb 		if (ret) {
4974dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ab, "failed to delay vdev start: %d\n", ret);
4975dd4f32aeSBjoern A. Zeeb 			goto free_tx_stats;
4976dd4f32aeSBjoern A. Zeeb 		}
4977dd4f32aeSBjoern A. Zeeb 	}
4978dd4f32aeSBjoern A. Zeeb 
4979*28348caeSBjoern A. Zeeb 	ewma_avg_rssi_init(&arsta->avg_rssi);
4980dd4f32aeSBjoern A. Zeeb 	return 0;
4981dd4f32aeSBjoern A. Zeeb 
4982dd4f32aeSBjoern A. Zeeb free_tx_stats:
4983dd4f32aeSBjoern A. Zeeb 	kfree(arsta->tx_stats);
4984dd4f32aeSBjoern A. Zeeb 	arsta->tx_stats = NULL;
4985dd4f32aeSBjoern A. Zeeb free_peer:
4986dd4f32aeSBjoern A. Zeeb 	ath11k_peer_delete(ar, arvif->vdev_id, sta->addr);
4987dd4f32aeSBjoern A. Zeeb free_rx_stats:
4988dd4f32aeSBjoern A. Zeeb 	kfree(arsta->rx_stats);
4989dd4f32aeSBjoern A. Zeeb 	arsta->rx_stats = NULL;
4990dd4f32aeSBjoern A. Zeeb dec_num_station:
4991dd4f32aeSBjoern A. Zeeb 	ath11k_mac_dec_num_stations(arvif, sta);
4992dd4f32aeSBjoern A. Zeeb exit:
4993dd4f32aeSBjoern A. Zeeb 	return ret;
4994dd4f32aeSBjoern A. Zeeb }
4995dd4f32aeSBjoern A. Zeeb 
ath11k_mac_ieee80211_sta_bw_to_wmi(struct ath11k * ar,struct ieee80211_sta * sta)4996*28348caeSBjoern A. Zeeb static u32 ath11k_mac_ieee80211_sta_bw_to_wmi(struct ath11k *ar,
4997*28348caeSBjoern A. Zeeb 					      struct ieee80211_sta *sta)
4998*28348caeSBjoern A. Zeeb {
4999*28348caeSBjoern A. Zeeb 	u32 bw = WMI_PEER_CHWIDTH_20MHZ;
5000*28348caeSBjoern A. Zeeb 
5001*28348caeSBjoern A. Zeeb 	switch (sta->deflink.bandwidth) {
5002*28348caeSBjoern A. Zeeb 	case IEEE80211_STA_RX_BW_20:
5003*28348caeSBjoern A. Zeeb 		bw = WMI_PEER_CHWIDTH_20MHZ;
5004*28348caeSBjoern A. Zeeb 		break;
5005*28348caeSBjoern A. Zeeb 	case IEEE80211_STA_RX_BW_40:
5006*28348caeSBjoern A. Zeeb 		bw = WMI_PEER_CHWIDTH_40MHZ;
5007*28348caeSBjoern A. Zeeb 		break;
5008*28348caeSBjoern A. Zeeb 	case IEEE80211_STA_RX_BW_80:
5009*28348caeSBjoern A. Zeeb 		bw = WMI_PEER_CHWIDTH_80MHZ;
5010*28348caeSBjoern A. Zeeb 		break;
5011*28348caeSBjoern A. Zeeb 	case IEEE80211_STA_RX_BW_160:
5012*28348caeSBjoern A. Zeeb 		bw = WMI_PEER_CHWIDTH_160MHZ;
5013*28348caeSBjoern A. Zeeb 		break;
5014*28348caeSBjoern A. Zeeb 	default:
5015*28348caeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "Invalid bandwidth %d for %pM\n",
5016*28348caeSBjoern A. Zeeb 			    sta->deflink.bandwidth, sta->addr);
5017*28348caeSBjoern A. Zeeb 		bw = WMI_PEER_CHWIDTH_20MHZ;
5018*28348caeSBjoern A. Zeeb 		break;
5019*28348caeSBjoern A. Zeeb 	}
5020*28348caeSBjoern A. Zeeb 
5021*28348caeSBjoern A. Zeeb 	return bw;
5022*28348caeSBjoern A. Zeeb }
5023*28348caeSBjoern A. Zeeb 
ath11k_mac_op_sta_state(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_sta * sta,enum ieee80211_sta_state old_state,enum ieee80211_sta_state new_state)5024dd4f32aeSBjoern A. Zeeb static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw,
5025dd4f32aeSBjoern A. Zeeb 				   struct ieee80211_vif *vif,
5026dd4f32aeSBjoern A. Zeeb 				   struct ieee80211_sta *sta,
5027dd4f32aeSBjoern A. Zeeb 				   enum ieee80211_sta_state old_state,
5028dd4f32aeSBjoern A. Zeeb 				   enum ieee80211_sta_state new_state)
5029dd4f32aeSBjoern A. Zeeb {
5030dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = hw->priv;
5031dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
5032dd4f32aeSBjoern A. Zeeb 	struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
5033dd4f32aeSBjoern A. Zeeb 	struct ath11k_peer *peer;
5034dd4f32aeSBjoern A. Zeeb 	int ret = 0;
5035dd4f32aeSBjoern A. Zeeb 
5036dd4f32aeSBjoern A. Zeeb 	/* cancel must be done outside the mutex to avoid deadlock */
5037dd4f32aeSBjoern A. Zeeb 	if ((old_state == IEEE80211_STA_NONE &&
5038dd4f32aeSBjoern A. Zeeb 	     new_state == IEEE80211_STA_NOTEXIST)) {
5039dd4f32aeSBjoern A. Zeeb 		cancel_work_sync(&arsta->update_wk);
5040dd4f32aeSBjoern A. Zeeb 		cancel_work_sync(&arsta->set_4addr_wk);
5041dd4f32aeSBjoern A. Zeeb 	}
5042dd4f32aeSBjoern A. Zeeb 
5043dd4f32aeSBjoern A. Zeeb 	mutex_lock(&ar->conf_mutex);
5044dd4f32aeSBjoern A. Zeeb 
5045dd4f32aeSBjoern A. Zeeb 	if (old_state == IEEE80211_STA_NOTEXIST &&
5046dd4f32aeSBjoern A. Zeeb 	    new_state == IEEE80211_STA_NONE) {
5047dd4f32aeSBjoern A. Zeeb 		memset(arsta, 0, sizeof(*arsta));
5048dd4f32aeSBjoern A. Zeeb 		arsta->arvif = arvif;
5049*28348caeSBjoern A. Zeeb 		arsta->peer_ps_state = WMI_PEER_PS_STATE_DISABLED;
5050dd4f32aeSBjoern A. Zeeb 		INIT_WORK(&arsta->update_wk, ath11k_sta_rc_update_wk);
5051dd4f32aeSBjoern A. Zeeb 		INIT_WORK(&arsta->set_4addr_wk, ath11k_sta_set_4addr_wk);
5052dd4f32aeSBjoern A. Zeeb 
5053dd4f32aeSBjoern A. Zeeb 		ret = ath11k_mac_station_add(ar, vif, sta);
5054dd4f32aeSBjoern A. Zeeb 		if (ret)
5055dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "Failed to add station: %pM for VDEV: %d\n",
5056dd4f32aeSBjoern A. Zeeb 				    sta->addr, arvif->vdev_id);
5057dd4f32aeSBjoern A. Zeeb 	} else if ((old_state == IEEE80211_STA_NONE &&
5058dd4f32aeSBjoern A. Zeeb 		    new_state == IEEE80211_STA_NOTEXIST)) {
5059dd4f32aeSBjoern A. Zeeb 		bool skip_peer_delete = ar->ab->hw_params.vdev_start_delay &&
5060dd4f32aeSBjoern A. Zeeb 			vif->type == NL80211_IFTYPE_STATION;
5061dd4f32aeSBjoern A. Zeeb 
5062dd4f32aeSBjoern A. Zeeb 		ath11k_dp_peer_cleanup(ar, arvif->vdev_id, sta->addr);
5063dd4f32aeSBjoern A. Zeeb 
5064dd4f32aeSBjoern A. Zeeb 		if (!skip_peer_delete) {
5065dd4f32aeSBjoern A. Zeeb 			ret = ath11k_peer_delete(ar, arvif->vdev_id, sta->addr);
5066dd4f32aeSBjoern A. Zeeb 			if (ret)
5067dd4f32aeSBjoern A. Zeeb 				ath11k_warn(ar->ab,
5068dd4f32aeSBjoern A. Zeeb 					    "Failed to delete peer: %pM for VDEV: %d\n",
5069dd4f32aeSBjoern A. Zeeb 					    sta->addr, arvif->vdev_id);
5070dd4f32aeSBjoern A. Zeeb 			else
5071dd4f32aeSBjoern A. Zeeb 				ath11k_dbg(ar->ab,
5072dd4f32aeSBjoern A. Zeeb 					   ATH11K_DBG_MAC,
5073dd4f32aeSBjoern A. Zeeb 					   "Removed peer: %pM for VDEV: %d\n",
5074dd4f32aeSBjoern A. Zeeb 					   sta->addr, arvif->vdev_id);
5075dd4f32aeSBjoern A. Zeeb 		}
5076dd4f32aeSBjoern A. Zeeb 
5077dd4f32aeSBjoern A. Zeeb 		ath11k_mac_dec_num_stations(arvif, sta);
5078*28348caeSBjoern A. Zeeb 		mutex_lock(&ar->ab->tbl_mtx_lock);
5079dd4f32aeSBjoern A. Zeeb 		spin_lock_bh(&ar->ab->base_lock);
5080dd4f32aeSBjoern A. Zeeb 		peer = ath11k_peer_find(ar->ab, arvif->vdev_id, sta->addr);
5081dd4f32aeSBjoern A. Zeeb 		if (skip_peer_delete && peer) {
5082dd4f32aeSBjoern A. Zeeb 			peer->sta = NULL;
5083dd4f32aeSBjoern A. Zeeb 		} else if (peer && peer->sta == sta) {
5084dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "Found peer entry %pM n vdev %i after it was supposedly removed\n",
5085dd4f32aeSBjoern A. Zeeb 				    vif->addr, arvif->vdev_id);
5086*28348caeSBjoern A. Zeeb 			ath11k_peer_rhash_delete(ar->ab, peer);
5087dd4f32aeSBjoern A. Zeeb 			peer->sta = NULL;
5088dd4f32aeSBjoern A. Zeeb 			list_del(&peer->list);
5089dd4f32aeSBjoern A. Zeeb 			kfree(peer);
5090dd4f32aeSBjoern A. Zeeb 			ar->num_peers--;
5091dd4f32aeSBjoern A. Zeeb 		}
5092dd4f32aeSBjoern A. Zeeb 		spin_unlock_bh(&ar->ab->base_lock);
5093*28348caeSBjoern A. Zeeb 		mutex_unlock(&ar->ab->tbl_mtx_lock);
5094dd4f32aeSBjoern A. Zeeb 
5095dd4f32aeSBjoern A. Zeeb 		kfree(arsta->tx_stats);
5096dd4f32aeSBjoern A. Zeeb 		arsta->tx_stats = NULL;
5097dd4f32aeSBjoern A. Zeeb 
5098dd4f32aeSBjoern A. Zeeb 		kfree(arsta->rx_stats);
5099dd4f32aeSBjoern A. Zeeb 		arsta->rx_stats = NULL;
5100dd4f32aeSBjoern A. Zeeb 	} else if (old_state == IEEE80211_STA_AUTH &&
5101dd4f32aeSBjoern A. Zeeb 		   new_state == IEEE80211_STA_ASSOC &&
5102dd4f32aeSBjoern A. Zeeb 		   (vif->type == NL80211_IFTYPE_AP ||
5103dd4f32aeSBjoern A. Zeeb 		    vif->type == NL80211_IFTYPE_MESH_POINT ||
5104dd4f32aeSBjoern A. Zeeb 		    vif->type == NL80211_IFTYPE_ADHOC)) {
5105dd4f32aeSBjoern A. Zeeb 		ret = ath11k_station_assoc(ar, vif, sta, false);
5106dd4f32aeSBjoern A. Zeeb 		if (ret)
5107dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "Failed to associate station: %pM\n",
5108dd4f32aeSBjoern A. Zeeb 				    sta->addr);
5109*28348caeSBjoern A. Zeeb 
5110*28348caeSBjoern A. Zeeb 		spin_lock_bh(&ar->data_lock);
5111*28348caeSBjoern A. Zeeb 		/* Set arsta bw and prev bw */
5112*28348caeSBjoern A. Zeeb 		arsta->bw = ath11k_mac_ieee80211_sta_bw_to_wmi(ar, sta);
5113*28348caeSBjoern A. Zeeb 		arsta->bw_prev = arsta->bw;
5114*28348caeSBjoern A. Zeeb 		spin_unlock_bh(&ar->data_lock);
5115dd4f32aeSBjoern A. Zeeb 	} else if (old_state == IEEE80211_STA_ASSOC &&
5116dd4f32aeSBjoern A. Zeeb 		   new_state == IEEE80211_STA_AUTHORIZED) {
5117dd4f32aeSBjoern A. Zeeb 		spin_lock_bh(&ar->ab->base_lock);
5118dd4f32aeSBjoern A. Zeeb 
5119dd4f32aeSBjoern A. Zeeb 		peer = ath11k_peer_find(ar->ab, arvif->vdev_id, sta->addr);
5120dd4f32aeSBjoern A. Zeeb 		if (peer)
5121dd4f32aeSBjoern A. Zeeb 			peer->is_authorized = true;
5122dd4f32aeSBjoern A. Zeeb 
5123dd4f32aeSBjoern A. Zeeb 		spin_unlock_bh(&ar->ab->base_lock);
5124dd4f32aeSBjoern A. Zeeb 
5125dd4f32aeSBjoern A. Zeeb 		if (vif->type == NL80211_IFTYPE_STATION && arvif->is_up) {
5126dd4f32aeSBjoern A. Zeeb 			ret = ath11k_wmi_set_peer_param(ar, sta->addr,
5127dd4f32aeSBjoern A. Zeeb 							arvif->vdev_id,
5128dd4f32aeSBjoern A. Zeeb 							WMI_PEER_AUTHORIZE,
5129dd4f32aeSBjoern A. Zeeb 							1);
5130dd4f32aeSBjoern A. Zeeb 			if (ret)
5131dd4f32aeSBjoern A. Zeeb 				ath11k_warn(ar->ab, "Unable to authorize peer %pM vdev %d: %d\n",
5132dd4f32aeSBjoern A. Zeeb 					    sta->addr, arvif->vdev_id, ret);
5133dd4f32aeSBjoern A. Zeeb 		}
5134dd4f32aeSBjoern A. Zeeb 	} else if (old_state == IEEE80211_STA_AUTHORIZED &&
5135dd4f32aeSBjoern A. Zeeb 		   new_state == IEEE80211_STA_ASSOC) {
5136dd4f32aeSBjoern A. Zeeb 		spin_lock_bh(&ar->ab->base_lock);
5137dd4f32aeSBjoern A. Zeeb 
5138dd4f32aeSBjoern A. Zeeb 		peer = ath11k_peer_find(ar->ab, arvif->vdev_id, sta->addr);
5139dd4f32aeSBjoern A. Zeeb 		if (peer)
5140dd4f32aeSBjoern A. Zeeb 			peer->is_authorized = false;
5141dd4f32aeSBjoern A. Zeeb 
5142dd4f32aeSBjoern A. Zeeb 		spin_unlock_bh(&ar->ab->base_lock);
5143dd4f32aeSBjoern A. Zeeb 	} else if (old_state == IEEE80211_STA_ASSOC &&
5144dd4f32aeSBjoern A. Zeeb 		   new_state == IEEE80211_STA_AUTH &&
5145dd4f32aeSBjoern A. Zeeb 		   (vif->type == NL80211_IFTYPE_AP ||
5146dd4f32aeSBjoern A. Zeeb 		    vif->type == NL80211_IFTYPE_MESH_POINT ||
5147dd4f32aeSBjoern A. Zeeb 		    vif->type == NL80211_IFTYPE_ADHOC)) {
5148dd4f32aeSBjoern A. Zeeb 		ret = ath11k_station_disassoc(ar, vif, sta);
5149dd4f32aeSBjoern A. Zeeb 		if (ret)
5150dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "Failed to disassociate station: %pM\n",
5151dd4f32aeSBjoern A. Zeeb 				    sta->addr);
5152dd4f32aeSBjoern A. Zeeb 	}
5153dd4f32aeSBjoern A. Zeeb 
5154dd4f32aeSBjoern A. Zeeb 	mutex_unlock(&ar->conf_mutex);
5155dd4f32aeSBjoern A. Zeeb 	return ret;
5156dd4f32aeSBjoern A. Zeeb }
5157dd4f32aeSBjoern A. Zeeb 
ath11k_mac_op_sta_set_txpwr(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_sta * sta)5158dd4f32aeSBjoern A. Zeeb static int ath11k_mac_op_sta_set_txpwr(struct ieee80211_hw *hw,
5159dd4f32aeSBjoern A. Zeeb 				       struct ieee80211_vif *vif,
5160dd4f32aeSBjoern A. Zeeb 				       struct ieee80211_sta *sta)
5161dd4f32aeSBjoern A. Zeeb {
5162dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = hw->priv;
5163dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif = (void *)vif->drv_priv;
5164dd4f32aeSBjoern A. Zeeb 	int ret = 0;
5165dd4f32aeSBjoern A. Zeeb 	s16 txpwr;
5166dd4f32aeSBjoern A. Zeeb 
5167dd4f32aeSBjoern A. Zeeb 	if (sta->deflink.txpwr.type == NL80211_TX_POWER_AUTOMATIC) {
5168dd4f32aeSBjoern A. Zeeb 		txpwr = 0;
5169dd4f32aeSBjoern A. Zeeb 	} else {
5170dd4f32aeSBjoern A. Zeeb 		txpwr = sta->deflink.txpwr.power;
5171dd4f32aeSBjoern A. Zeeb 		if (!txpwr)
5172dd4f32aeSBjoern A. Zeeb 			return -EINVAL;
5173dd4f32aeSBjoern A. Zeeb 	}
5174dd4f32aeSBjoern A. Zeeb 
5175dd4f32aeSBjoern A. Zeeb 	if (txpwr > ATH11K_TX_POWER_MAX_VAL || txpwr < ATH11K_TX_POWER_MIN_VAL)
5176dd4f32aeSBjoern A. Zeeb 		return -EINVAL;
5177dd4f32aeSBjoern A. Zeeb 
5178dd4f32aeSBjoern A. Zeeb 	mutex_lock(&ar->conf_mutex);
5179dd4f32aeSBjoern A. Zeeb 
5180dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,
5181dd4f32aeSBjoern A. Zeeb 					WMI_PEER_USE_FIXED_PWR, txpwr);
5182dd4f32aeSBjoern A. Zeeb 	if (ret) {
5183dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to set tx power for station ret: %d\n",
5184dd4f32aeSBjoern A. Zeeb 			    ret);
5185dd4f32aeSBjoern A. Zeeb 		goto out;
5186dd4f32aeSBjoern A. Zeeb 	}
5187dd4f32aeSBjoern A. Zeeb 
5188dd4f32aeSBjoern A. Zeeb out:
5189dd4f32aeSBjoern A. Zeeb 	mutex_unlock(&ar->conf_mutex);
5190dd4f32aeSBjoern A. Zeeb 	return ret;
5191dd4f32aeSBjoern A. Zeeb }
5192dd4f32aeSBjoern A. Zeeb 
ath11k_mac_op_sta_set_4addr(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_sta * sta,bool enabled)5193dd4f32aeSBjoern A. Zeeb static void ath11k_mac_op_sta_set_4addr(struct ieee80211_hw *hw,
5194dd4f32aeSBjoern A. Zeeb 					struct ieee80211_vif *vif,
5195dd4f32aeSBjoern A. Zeeb 					struct ieee80211_sta *sta, bool enabled)
5196dd4f32aeSBjoern A. Zeeb {
5197dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = hw->priv;
5198dd4f32aeSBjoern A. Zeeb 	struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
5199dd4f32aeSBjoern A. Zeeb 
5200dd4f32aeSBjoern A. Zeeb 	if (enabled && !arsta->use_4addr_set) {
5201dd4f32aeSBjoern A. Zeeb 		ieee80211_queue_work(ar->hw, &arsta->set_4addr_wk);
5202dd4f32aeSBjoern A. Zeeb 		arsta->use_4addr_set = true;
5203dd4f32aeSBjoern A. Zeeb 	}
5204dd4f32aeSBjoern A. Zeeb }
5205dd4f32aeSBjoern A. Zeeb 
ath11k_mac_op_sta_rc_update(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_sta * sta,u32 changed)5206dd4f32aeSBjoern A. Zeeb static void ath11k_mac_op_sta_rc_update(struct ieee80211_hw *hw,
5207dd4f32aeSBjoern A. Zeeb 					struct ieee80211_vif *vif,
5208dd4f32aeSBjoern A. Zeeb 					struct ieee80211_sta *sta,
5209dd4f32aeSBjoern A. Zeeb 					u32 changed)
5210dd4f32aeSBjoern A. Zeeb {
5211dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = hw->priv;
5212dd4f32aeSBjoern A. Zeeb 	struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
5213dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif = (void *)vif->drv_priv;
5214dd4f32aeSBjoern A. Zeeb 	struct ath11k_peer *peer;
5215dd4f32aeSBjoern A. Zeeb 	u32 bw, smps;
5216dd4f32aeSBjoern A. Zeeb 
5217dd4f32aeSBjoern A. Zeeb 	spin_lock_bh(&ar->ab->base_lock);
5218dd4f32aeSBjoern A. Zeeb 
5219dd4f32aeSBjoern A. Zeeb 	peer = ath11k_peer_find(ar->ab, arvif->vdev_id, sta->addr);
5220dd4f32aeSBjoern A. Zeeb 	if (!peer) {
5221dd4f32aeSBjoern A. Zeeb 		spin_unlock_bh(&ar->ab->base_lock);
5222dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "mac sta rc update failed to find peer %pM on vdev %i\n",
5223dd4f32aeSBjoern A. Zeeb 			    sta->addr, arvif->vdev_id);
5224dd4f32aeSBjoern A. Zeeb 		return;
5225dd4f32aeSBjoern A. Zeeb 	}
5226dd4f32aeSBjoern A. Zeeb 
5227dd4f32aeSBjoern A. Zeeb 	spin_unlock_bh(&ar->ab->base_lock);
5228dd4f32aeSBjoern A. Zeeb 
5229dd4f32aeSBjoern A. Zeeb 	ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
5230*28348caeSBjoern A. Zeeb 		   "sta rc update for %pM changed %08x bw %d nss %d smps %d\n",
5231dd4f32aeSBjoern A. Zeeb 		   sta->addr, changed, sta->deflink.bandwidth,
5232dd4f32aeSBjoern A. Zeeb 		   sta->deflink.rx_nss,
5233*28348caeSBjoern A. Zeeb 		   sta->deflink.smps_mode);
5234dd4f32aeSBjoern A. Zeeb 
5235dd4f32aeSBjoern A. Zeeb 	spin_lock_bh(&ar->data_lock);
5236dd4f32aeSBjoern A. Zeeb 
5237dd4f32aeSBjoern A. Zeeb 	if (changed & IEEE80211_RC_BW_CHANGED) {
5238*28348caeSBjoern A. Zeeb 		bw = ath11k_mac_ieee80211_sta_bw_to_wmi(ar, sta);
5239*28348caeSBjoern A. Zeeb 		arsta->bw_prev = arsta->bw;
5240dd4f32aeSBjoern A. Zeeb 		arsta->bw = bw;
5241dd4f32aeSBjoern A. Zeeb 	}
5242dd4f32aeSBjoern A. Zeeb 
5243dd4f32aeSBjoern A. Zeeb 	if (changed & IEEE80211_RC_NSS_CHANGED)
5244dd4f32aeSBjoern A. Zeeb 		arsta->nss = sta->deflink.rx_nss;
5245dd4f32aeSBjoern A. Zeeb 
5246dd4f32aeSBjoern A. Zeeb 	if (changed & IEEE80211_RC_SMPS_CHANGED) {
5247dd4f32aeSBjoern A. Zeeb 		smps = WMI_PEER_SMPS_PS_NONE;
5248dd4f32aeSBjoern A. Zeeb 
5249*28348caeSBjoern A. Zeeb 		switch (sta->deflink.smps_mode) {
5250dd4f32aeSBjoern A. Zeeb 		case IEEE80211_SMPS_AUTOMATIC:
5251dd4f32aeSBjoern A. Zeeb 		case IEEE80211_SMPS_OFF:
5252dd4f32aeSBjoern A. Zeeb 			smps = WMI_PEER_SMPS_PS_NONE;
5253dd4f32aeSBjoern A. Zeeb 			break;
5254dd4f32aeSBjoern A. Zeeb 		case IEEE80211_SMPS_STATIC:
5255dd4f32aeSBjoern A. Zeeb 			smps = WMI_PEER_SMPS_STATIC;
5256dd4f32aeSBjoern A. Zeeb 			break;
5257dd4f32aeSBjoern A. Zeeb 		case IEEE80211_SMPS_DYNAMIC:
5258dd4f32aeSBjoern A. Zeeb 			smps = WMI_PEER_SMPS_DYNAMIC;
5259dd4f32aeSBjoern A. Zeeb 			break;
5260dd4f32aeSBjoern A. Zeeb 		default:
5261dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "Invalid smps %d in sta rc update for %pM\n",
5262*28348caeSBjoern A. Zeeb 				    sta->deflink.smps_mode, sta->addr);
5263dd4f32aeSBjoern A. Zeeb 			smps = WMI_PEER_SMPS_PS_NONE;
5264dd4f32aeSBjoern A. Zeeb 			break;
5265dd4f32aeSBjoern A. Zeeb 		}
5266dd4f32aeSBjoern A. Zeeb 
5267dd4f32aeSBjoern A. Zeeb 		arsta->smps = smps;
5268dd4f32aeSBjoern A. Zeeb 	}
5269dd4f32aeSBjoern A. Zeeb 
5270dd4f32aeSBjoern A. Zeeb 	arsta->changed |= changed;
5271dd4f32aeSBjoern A. Zeeb 
5272dd4f32aeSBjoern A. Zeeb 	spin_unlock_bh(&ar->data_lock);
5273dd4f32aeSBjoern A. Zeeb 
5274dd4f32aeSBjoern A. Zeeb 	ieee80211_queue_work(hw, &arsta->update_wk);
5275dd4f32aeSBjoern A. Zeeb }
5276dd4f32aeSBjoern A. Zeeb 
ath11k_conf_tx_uapsd(struct ath11k * ar,struct ieee80211_vif * vif,u16 ac,bool enable)5277dd4f32aeSBjoern A. Zeeb static int ath11k_conf_tx_uapsd(struct ath11k *ar, struct ieee80211_vif *vif,
5278dd4f32aeSBjoern A. Zeeb 				u16 ac, bool enable)
5279dd4f32aeSBjoern A. Zeeb {
5280dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
5281dd4f32aeSBjoern A. Zeeb 	u32 value = 0;
5282dd4f32aeSBjoern A. Zeeb 	int ret = 0;
5283dd4f32aeSBjoern A. Zeeb 
5284dd4f32aeSBjoern A. Zeeb 	if (arvif->vdev_type != WMI_VDEV_TYPE_STA)
5285dd4f32aeSBjoern A. Zeeb 		return 0;
5286dd4f32aeSBjoern A. Zeeb 
5287dd4f32aeSBjoern A. Zeeb 	switch (ac) {
5288dd4f32aeSBjoern A. Zeeb 	case IEEE80211_AC_VO:
5289dd4f32aeSBjoern A. Zeeb 		value = WMI_STA_PS_UAPSD_AC3_DELIVERY_EN |
5290dd4f32aeSBjoern A. Zeeb 			WMI_STA_PS_UAPSD_AC3_TRIGGER_EN;
5291dd4f32aeSBjoern A. Zeeb 		break;
5292dd4f32aeSBjoern A. Zeeb 	case IEEE80211_AC_VI:
5293dd4f32aeSBjoern A. Zeeb 		value = WMI_STA_PS_UAPSD_AC2_DELIVERY_EN |
5294dd4f32aeSBjoern A. Zeeb 			WMI_STA_PS_UAPSD_AC2_TRIGGER_EN;
5295dd4f32aeSBjoern A. Zeeb 		break;
5296dd4f32aeSBjoern A. Zeeb 	case IEEE80211_AC_BE:
5297dd4f32aeSBjoern A. Zeeb 		value = WMI_STA_PS_UAPSD_AC1_DELIVERY_EN |
5298dd4f32aeSBjoern A. Zeeb 			WMI_STA_PS_UAPSD_AC1_TRIGGER_EN;
5299dd4f32aeSBjoern A. Zeeb 		break;
5300dd4f32aeSBjoern A. Zeeb 	case IEEE80211_AC_BK:
5301dd4f32aeSBjoern A. Zeeb 		value = WMI_STA_PS_UAPSD_AC0_DELIVERY_EN |
5302dd4f32aeSBjoern A. Zeeb 			WMI_STA_PS_UAPSD_AC0_TRIGGER_EN;
5303dd4f32aeSBjoern A. Zeeb 		break;
5304dd4f32aeSBjoern A. Zeeb 	}
5305dd4f32aeSBjoern A. Zeeb 
5306dd4f32aeSBjoern A. Zeeb 	if (enable)
5307dd4f32aeSBjoern A. Zeeb 		arvif->u.sta.uapsd |= value;
5308dd4f32aeSBjoern A. Zeeb 	else
5309dd4f32aeSBjoern A. Zeeb 		arvif->u.sta.uapsd &= ~value;
5310dd4f32aeSBjoern A. Zeeb 
5311dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_set_sta_ps_param(ar, arvif->vdev_id,
5312dd4f32aeSBjoern A. Zeeb 					  WMI_STA_PS_PARAM_UAPSD,
5313dd4f32aeSBjoern A. Zeeb 					  arvif->u.sta.uapsd);
5314dd4f32aeSBjoern A. Zeeb 	if (ret) {
5315dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "could not set uapsd params %d\n", ret);
5316dd4f32aeSBjoern A. Zeeb 		goto exit;
5317dd4f32aeSBjoern A. Zeeb 	}
5318dd4f32aeSBjoern A. Zeeb 
5319dd4f32aeSBjoern A. Zeeb 	if (arvif->u.sta.uapsd)
5320dd4f32aeSBjoern A. Zeeb 		value = WMI_STA_PS_RX_WAKE_POLICY_POLL_UAPSD;
5321dd4f32aeSBjoern A. Zeeb 	else
5322dd4f32aeSBjoern A. Zeeb 		value = WMI_STA_PS_RX_WAKE_POLICY_WAKE;
5323dd4f32aeSBjoern A. Zeeb 
5324dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_set_sta_ps_param(ar, arvif->vdev_id,
5325dd4f32aeSBjoern A. Zeeb 					  WMI_STA_PS_PARAM_RX_WAKE_POLICY,
5326dd4f32aeSBjoern A. Zeeb 					  value);
5327dd4f32aeSBjoern A. Zeeb 	if (ret)
5328dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "could not set rx wake param %d\n", ret);
5329dd4f32aeSBjoern A. Zeeb 
5330dd4f32aeSBjoern A. Zeeb exit:
5331dd4f32aeSBjoern A. Zeeb 	return ret;
5332dd4f32aeSBjoern A. Zeeb }
5333dd4f32aeSBjoern A. Zeeb 
ath11k_mac_op_conf_tx(struct ieee80211_hw * hw,struct ieee80211_vif * vif,unsigned int link_id,u16 ac,const struct ieee80211_tx_queue_params * params)5334dd4f32aeSBjoern A. Zeeb static int ath11k_mac_op_conf_tx(struct ieee80211_hw *hw,
5335dd4f32aeSBjoern A. Zeeb 				 struct ieee80211_vif *vif,
5336dd4f32aeSBjoern A. Zeeb 				 unsigned int link_id, u16 ac,
5337dd4f32aeSBjoern A. Zeeb 				 const struct ieee80211_tx_queue_params *params)
5338dd4f32aeSBjoern A. Zeeb {
5339dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = hw->priv;
5340dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif = (void *)vif->drv_priv;
5341dd4f32aeSBjoern A. Zeeb 	struct wmi_wmm_params_arg *p = NULL;
5342dd4f32aeSBjoern A. Zeeb 	int ret;
5343dd4f32aeSBjoern A. Zeeb 
5344dd4f32aeSBjoern A. Zeeb 	mutex_lock(&ar->conf_mutex);
5345dd4f32aeSBjoern A. Zeeb 
5346dd4f32aeSBjoern A. Zeeb 	switch (ac) {
5347dd4f32aeSBjoern A. Zeeb 	case IEEE80211_AC_VO:
5348dd4f32aeSBjoern A. Zeeb 		p = &arvif->wmm_params.ac_vo;
5349dd4f32aeSBjoern A. Zeeb 		break;
5350dd4f32aeSBjoern A. Zeeb 	case IEEE80211_AC_VI:
5351dd4f32aeSBjoern A. Zeeb 		p = &arvif->wmm_params.ac_vi;
5352dd4f32aeSBjoern A. Zeeb 		break;
5353dd4f32aeSBjoern A. Zeeb 	case IEEE80211_AC_BE:
5354dd4f32aeSBjoern A. Zeeb 		p = &arvif->wmm_params.ac_be;
5355dd4f32aeSBjoern A. Zeeb 		break;
5356dd4f32aeSBjoern A. Zeeb 	case IEEE80211_AC_BK:
5357dd4f32aeSBjoern A. Zeeb 		p = &arvif->wmm_params.ac_bk;
5358dd4f32aeSBjoern A. Zeeb 		break;
5359dd4f32aeSBjoern A. Zeeb 	}
5360dd4f32aeSBjoern A. Zeeb 
5361dd4f32aeSBjoern A. Zeeb 	if (WARN_ON(!p)) {
5362dd4f32aeSBjoern A. Zeeb 		ret = -EINVAL;
5363dd4f32aeSBjoern A. Zeeb 		goto exit;
5364dd4f32aeSBjoern A. Zeeb 	}
5365dd4f32aeSBjoern A. Zeeb 
5366dd4f32aeSBjoern A. Zeeb 	p->cwmin = params->cw_min;
5367dd4f32aeSBjoern A. Zeeb 	p->cwmax = params->cw_max;
5368dd4f32aeSBjoern A. Zeeb 	p->aifs = params->aifs;
5369dd4f32aeSBjoern A. Zeeb 	p->txop = params->txop;
5370dd4f32aeSBjoern A. Zeeb 
5371dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_send_wmm_update_cmd_tlv(ar, arvif->vdev_id,
5372dd4f32aeSBjoern A. Zeeb 						 &arvif->wmm_params);
5373dd4f32aeSBjoern A. Zeeb 	if (ret) {
5374dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to set wmm params: %d\n", ret);
5375dd4f32aeSBjoern A. Zeeb 		goto exit;
5376dd4f32aeSBjoern A. Zeeb 	}
5377dd4f32aeSBjoern A. Zeeb 
5378dd4f32aeSBjoern A. Zeeb 	ret = ath11k_conf_tx_uapsd(ar, vif, ac, params->uapsd);
5379dd4f32aeSBjoern A. Zeeb 
5380dd4f32aeSBjoern A. Zeeb 	if (ret)
5381dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to set sta uapsd: %d\n", ret);
5382dd4f32aeSBjoern A. Zeeb 
5383dd4f32aeSBjoern A. Zeeb exit:
5384dd4f32aeSBjoern A. Zeeb 	mutex_unlock(&ar->conf_mutex);
5385dd4f32aeSBjoern A. Zeeb 	return ret;
5386dd4f32aeSBjoern A. Zeeb }
5387dd4f32aeSBjoern A. Zeeb 
5388dd4f32aeSBjoern A. Zeeb static struct ieee80211_sta_ht_cap
ath11k_create_ht_cap(struct ath11k * ar,u32 ar_ht_cap,u32 rate_cap_rx_chainmask)5389dd4f32aeSBjoern A. Zeeb ath11k_create_ht_cap(struct ath11k *ar, u32 ar_ht_cap, u32 rate_cap_rx_chainmask)
5390dd4f32aeSBjoern A. Zeeb {
5391dd4f32aeSBjoern A. Zeeb 	int i;
5392dd4f32aeSBjoern A. Zeeb 	struct ieee80211_sta_ht_cap ht_cap = {0};
5393dd4f32aeSBjoern A. Zeeb 	u32 ar_vht_cap = ar->pdev->cap.vht_cap;
5394dd4f32aeSBjoern A. Zeeb 
5395dd4f32aeSBjoern A. Zeeb 	if (!(ar_ht_cap & WMI_HT_CAP_ENABLED))
5396dd4f32aeSBjoern A. Zeeb 		return ht_cap;
5397dd4f32aeSBjoern A. Zeeb 
5398dd4f32aeSBjoern A. Zeeb 	ht_cap.ht_supported = 1;
5399dd4f32aeSBjoern A. Zeeb 	ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
5400dd4f32aeSBjoern A. Zeeb 	ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE;
5401dd4f32aeSBjoern A. Zeeb 	ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
5402dd4f32aeSBjoern A. Zeeb 	ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40;
5403dd4f32aeSBjoern A. Zeeb 	ht_cap.cap |= WLAN_HT_CAP_SM_PS_STATIC << IEEE80211_HT_CAP_SM_PS_SHIFT;
5404dd4f32aeSBjoern A. Zeeb 
5405dd4f32aeSBjoern A. Zeeb 	if (ar_ht_cap & WMI_HT_CAP_HT20_SGI)
5406dd4f32aeSBjoern A. Zeeb 		ht_cap.cap |= IEEE80211_HT_CAP_SGI_20;
5407dd4f32aeSBjoern A. Zeeb 
5408dd4f32aeSBjoern A. Zeeb 	if (ar_ht_cap & WMI_HT_CAP_HT40_SGI)
5409dd4f32aeSBjoern A. Zeeb 		ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
5410dd4f32aeSBjoern A. Zeeb 
5411dd4f32aeSBjoern A. Zeeb 	if (ar_ht_cap & WMI_HT_CAP_DYNAMIC_SMPS) {
5412dd4f32aeSBjoern A. Zeeb 		u32 smps;
5413dd4f32aeSBjoern A. Zeeb 
5414dd4f32aeSBjoern A. Zeeb 		smps   = WLAN_HT_CAP_SM_PS_DYNAMIC;
5415dd4f32aeSBjoern A. Zeeb 		smps <<= IEEE80211_HT_CAP_SM_PS_SHIFT;
5416dd4f32aeSBjoern A. Zeeb 
5417dd4f32aeSBjoern A. Zeeb 		ht_cap.cap |= smps;
5418dd4f32aeSBjoern A. Zeeb 	}
5419dd4f32aeSBjoern A. Zeeb 
5420dd4f32aeSBjoern A. Zeeb 	if (ar_ht_cap & WMI_HT_CAP_TX_STBC)
5421dd4f32aeSBjoern A. Zeeb 		ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC;
5422dd4f32aeSBjoern A. Zeeb 
5423dd4f32aeSBjoern A. Zeeb 	if (ar_ht_cap & WMI_HT_CAP_RX_STBC) {
5424dd4f32aeSBjoern A. Zeeb 		u32 stbc;
5425dd4f32aeSBjoern A. Zeeb 
5426dd4f32aeSBjoern A. Zeeb 		stbc   = ar_ht_cap;
5427dd4f32aeSBjoern A. Zeeb 		stbc  &= WMI_HT_CAP_RX_STBC;
5428dd4f32aeSBjoern A. Zeeb 		stbc >>= WMI_HT_CAP_RX_STBC_MASK_SHIFT;
5429dd4f32aeSBjoern A. Zeeb 		stbc <<= IEEE80211_HT_CAP_RX_STBC_SHIFT;
5430dd4f32aeSBjoern A. Zeeb 		stbc  &= IEEE80211_HT_CAP_RX_STBC;
5431dd4f32aeSBjoern A. Zeeb 
5432dd4f32aeSBjoern A. Zeeb 		ht_cap.cap |= stbc;
5433dd4f32aeSBjoern A. Zeeb 	}
5434dd4f32aeSBjoern A. Zeeb 
5435dd4f32aeSBjoern A. Zeeb 	if (ar_ht_cap & WMI_HT_CAP_RX_LDPC)
5436dd4f32aeSBjoern A. Zeeb 		ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING;
5437dd4f32aeSBjoern A. Zeeb 
5438dd4f32aeSBjoern A. Zeeb 	if (ar_ht_cap & WMI_HT_CAP_L_SIG_TXOP_PROT)
5439dd4f32aeSBjoern A. Zeeb 		ht_cap.cap |= IEEE80211_HT_CAP_LSIG_TXOP_PROT;
5440dd4f32aeSBjoern A. Zeeb 
5441dd4f32aeSBjoern A. Zeeb 	if (ar_vht_cap & WMI_VHT_CAP_MAX_MPDU_LEN_MASK)
5442dd4f32aeSBjoern A. Zeeb 		ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU;
5443dd4f32aeSBjoern A. Zeeb 
5444dd4f32aeSBjoern A. Zeeb 	for (i = 0; i < ar->num_rx_chains; i++) {
5445dd4f32aeSBjoern A. Zeeb 		if (rate_cap_rx_chainmask & BIT(i))
5446dd4f32aeSBjoern A. Zeeb 			ht_cap.mcs.rx_mask[i] = 0xFF;
5447dd4f32aeSBjoern A. Zeeb 	}
5448dd4f32aeSBjoern A. Zeeb 
5449dd4f32aeSBjoern A. Zeeb 	ht_cap.mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
5450dd4f32aeSBjoern A. Zeeb 
5451dd4f32aeSBjoern A. Zeeb 	return ht_cap;
5452dd4f32aeSBjoern A. Zeeb }
5453dd4f32aeSBjoern A. Zeeb 
ath11k_mac_set_txbf_conf(struct ath11k_vif * arvif)5454dd4f32aeSBjoern A. Zeeb static int ath11k_mac_set_txbf_conf(struct ath11k_vif *arvif)
5455dd4f32aeSBjoern A. Zeeb {
5456dd4f32aeSBjoern A. Zeeb 	u32 value = 0;
5457dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = arvif->ar;
5458dd4f32aeSBjoern A. Zeeb 	int nsts;
5459dd4f32aeSBjoern A. Zeeb 	int sound_dim;
5460dd4f32aeSBjoern A. Zeeb 	u32 vht_cap = ar->pdev->cap.vht_cap;
5461dd4f32aeSBjoern A. Zeeb 	u32 vdev_param = WMI_VDEV_PARAM_TXBF;
5462dd4f32aeSBjoern A. Zeeb 
5463dd4f32aeSBjoern A. Zeeb 	if (vht_cap & (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE)) {
5464dd4f32aeSBjoern A. Zeeb 		nsts = vht_cap & IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK;
5465dd4f32aeSBjoern A. Zeeb 		nsts >>= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT;
5466*28348caeSBjoern A. Zeeb 		if (nsts > (ar->num_rx_chains - 1))
5467*28348caeSBjoern A. Zeeb 			nsts = ar->num_rx_chains - 1;
5468dd4f32aeSBjoern A. Zeeb 		value |= SM(nsts, WMI_TXBF_STS_CAP_OFFSET);
5469dd4f32aeSBjoern A. Zeeb 	}
5470dd4f32aeSBjoern A. Zeeb 
5471dd4f32aeSBjoern A. Zeeb 	if (vht_cap & (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)) {
5472dd4f32aeSBjoern A. Zeeb 		sound_dim = vht_cap &
5473dd4f32aeSBjoern A. Zeeb 			    IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK;
5474dd4f32aeSBjoern A. Zeeb 		sound_dim >>= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT;
5475dd4f32aeSBjoern A. Zeeb 		if (sound_dim > (ar->num_tx_chains - 1))
5476dd4f32aeSBjoern A. Zeeb 			sound_dim = ar->num_tx_chains - 1;
5477dd4f32aeSBjoern A. Zeeb 		value |= SM(sound_dim, WMI_BF_SOUND_DIM_OFFSET);
5478dd4f32aeSBjoern A. Zeeb 	}
5479dd4f32aeSBjoern A. Zeeb 
5480dd4f32aeSBjoern A. Zeeb 	if (!value)
5481dd4f32aeSBjoern A. Zeeb 		return 0;
5482dd4f32aeSBjoern A. Zeeb 
5483dd4f32aeSBjoern A. Zeeb 	if (vht_cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE) {
5484dd4f32aeSBjoern A. Zeeb 		value |= WMI_VDEV_PARAM_TXBF_SU_TX_BFER;
5485dd4f32aeSBjoern A. Zeeb 
5486dd4f32aeSBjoern A. Zeeb 		if ((vht_cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) &&
5487dd4f32aeSBjoern A. Zeeb 		    arvif->vdev_type == WMI_VDEV_TYPE_AP)
5488dd4f32aeSBjoern A. Zeeb 			value |= WMI_VDEV_PARAM_TXBF_MU_TX_BFER;
5489dd4f32aeSBjoern A. Zeeb 	}
5490dd4f32aeSBjoern A. Zeeb 
5491dd4f32aeSBjoern A. Zeeb 	/* TODO: SUBFEE not validated in HK, disable here until validated? */
5492dd4f32aeSBjoern A. Zeeb 
5493dd4f32aeSBjoern A. Zeeb 	if (vht_cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE) {
5494dd4f32aeSBjoern A. Zeeb 		value |= WMI_VDEV_PARAM_TXBF_SU_TX_BFEE;
5495dd4f32aeSBjoern A. Zeeb 
5496dd4f32aeSBjoern A. Zeeb 		if ((vht_cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE) &&
5497dd4f32aeSBjoern A. Zeeb 		    arvif->vdev_type == WMI_VDEV_TYPE_STA)
5498dd4f32aeSBjoern A. Zeeb 			value |= WMI_VDEV_PARAM_TXBF_MU_TX_BFEE;
5499dd4f32aeSBjoern A. Zeeb 	}
5500dd4f32aeSBjoern A. Zeeb 
5501dd4f32aeSBjoern A. Zeeb 	return ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
5502dd4f32aeSBjoern A. Zeeb 					     vdev_param, value);
5503dd4f32aeSBjoern A. Zeeb }
5504dd4f32aeSBjoern A. Zeeb 
ath11k_set_vht_txbf_cap(struct ath11k * ar,u32 * vht_cap)5505dd4f32aeSBjoern A. Zeeb static void ath11k_set_vht_txbf_cap(struct ath11k *ar, u32 *vht_cap)
5506dd4f32aeSBjoern A. Zeeb {
5507dd4f32aeSBjoern A. Zeeb 	bool subfer, subfee;
5508*28348caeSBjoern A. Zeeb 	int sound_dim = 0, nsts = 0;
5509dd4f32aeSBjoern A. Zeeb 
5510dd4f32aeSBjoern A. Zeeb 	subfer = !!(*vht_cap & (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE));
5511dd4f32aeSBjoern A. Zeeb 	subfee = !!(*vht_cap & (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE));
5512dd4f32aeSBjoern A. Zeeb 
5513dd4f32aeSBjoern A. Zeeb 	if (ar->num_tx_chains < 2) {
5514dd4f32aeSBjoern A. Zeeb 		*vht_cap &= ~(IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE);
5515dd4f32aeSBjoern A. Zeeb 		subfer = false;
5516dd4f32aeSBjoern A. Zeeb 	}
5517dd4f32aeSBjoern A. Zeeb 
5518*28348caeSBjoern A. Zeeb 	if (ar->num_rx_chains < 2) {
5519*28348caeSBjoern A. Zeeb 		*vht_cap &= ~(IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE);
5520*28348caeSBjoern A. Zeeb 		subfee = false;
5521*28348caeSBjoern A. Zeeb 	}
5522*28348caeSBjoern A. Zeeb 
5523dd4f32aeSBjoern A. Zeeb 	/* If SU Beaformer is not set, then disable MU Beamformer Capability */
5524dd4f32aeSBjoern A. Zeeb 	if (!subfer)
5525dd4f32aeSBjoern A. Zeeb 		*vht_cap &= ~(IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE);
5526dd4f32aeSBjoern A. Zeeb 
5527dd4f32aeSBjoern A. Zeeb 	/* If SU Beaformee is not set, then disable MU Beamformee Capability */
5528dd4f32aeSBjoern A. Zeeb 	if (!subfee)
5529dd4f32aeSBjoern A. Zeeb 		*vht_cap &= ~(IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE);
5530dd4f32aeSBjoern A. Zeeb 
5531dd4f32aeSBjoern A. Zeeb 	sound_dim = (*vht_cap & IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK);
5532dd4f32aeSBjoern A. Zeeb 	sound_dim >>= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT;
5533dd4f32aeSBjoern A. Zeeb 	*vht_cap &= ~IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK;
5534dd4f32aeSBjoern A. Zeeb 
5535*28348caeSBjoern A. Zeeb 	nsts = (*vht_cap & IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK);
5536*28348caeSBjoern A. Zeeb 	nsts >>= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT;
5537*28348caeSBjoern A. Zeeb 	*vht_cap &= ~IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK;
5538dd4f32aeSBjoern A. Zeeb 
5539dd4f32aeSBjoern A. Zeeb 	/* Enable Sounding Dimension Field only if SU BF is enabled */
5540dd4f32aeSBjoern A. Zeeb 	if (subfer) {
5541dd4f32aeSBjoern A. Zeeb 		if (sound_dim > (ar->num_tx_chains - 1))
5542dd4f32aeSBjoern A. Zeeb 			sound_dim = ar->num_tx_chains - 1;
5543dd4f32aeSBjoern A. Zeeb 
5544dd4f32aeSBjoern A. Zeeb 		sound_dim <<= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT;
5545dd4f32aeSBjoern A. Zeeb 		sound_dim &=  IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK;
5546dd4f32aeSBjoern A. Zeeb 		*vht_cap |= sound_dim;
5547dd4f32aeSBjoern A. Zeeb 	}
5548dd4f32aeSBjoern A. Zeeb 
5549*28348caeSBjoern A. Zeeb 	/* Enable Beamformee STS Field only if SU BF is enabled */
5550*28348caeSBjoern A. Zeeb 	if (subfee) {
5551*28348caeSBjoern A. Zeeb 		if (nsts > (ar->num_rx_chains - 1))
5552*28348caeSBjoern A. Zeeb 			nsts = ar->num_rx_chains - 1;
5553*28348caeSBjoern A. Zeeb 
5554*28348caeSBjoern A. Zeeb 		nsts <<= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT;
5555*28348caeSBjoern A. Zeeb 		nsts &=  IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK;
5556*28348caeSBjoern A. Zeeb 		*vht_cap |= nsts;
5557*28348caeSBjoern A. Zeeb 	}
5558dd4f32aeSBjoern A. Zeeb }
5559dd4f32aeSBjoern A. Zeeb 
5560dd4f32aeSBjoern A. Zeeb static struct ieee80211_sta_vht_cap
ath11k_create_vht_cap(struct ath11k * ar,u32 rate_cap_tx_chainmask,u32 rate_cap_rx_chainmask)5561dd4f32aeSBjoern A. Zeeb ath11k_create_vht_cap(struct ath11k *ar, u32 rate_cap_tx_chainmask,
5562dd4f32aeSBjoern A. Zeeb 		      u32 rate_cap_rx_chainmask)
5563dd4f32aeSBjoern A. Zeeb {
5564dd4f32aeSBjoern A. Zeeb 	struct ieee80211_sta_vht_cap vht_cap = {0};
5565dd4f32aeSBjoern A. Zeeb 	u16 txmcs_map, rxmcs_map;
5566dd4f32aeSBjoern A. Zeeb 	int i;
5567dd4f32aeSBjoern A. Zeeb 
5568dd4f32aeSBjoern A. Zeeb 	vht_cap.vht_supported = 1;
5569dd4f32aeSBjoern A. Zeeb 	vht_cap.cap = ar->pdev->cap.vht_cap;
5570dd4f32aeSBjoern A. Zeeb 
5571dd4f32aeSBjoern A. Zeeb 	if (ar->pdev->cap.nss_ratio_enabled)
5572dd4f32aeSBjoern A. Zeeb 		vht_cap.vht_mcs.tx_highest |=
5573dd4f32aeSBjoern A. Zeeb 			cpu_to_le16(IEEE80211_VHT_EXT_NSS_BW_CAPABLE);
5574dd4f32aeSBjoern A. Zeeb 
5575dd4f32aeSBjoern A. Zeeb 	ath11k_set_vht_txbf_cap(ar, &vht_cap.cap);
5576dd4f32aeSBjoern A. Zeeb 
5577dd4f32aeSBjoern A. Zeeb 	rxmcs_map = 0;
5578dd4f32aeSBjoern A. Zeeb 	txmcs_map = 0;
5579dd4f32aeSBjoern A. Zeeb 	for (i = 0; i < 8; i++) {
5580dd4f32aeSBjoern A. Zeeb 		if (i < ar->num_tx_chains && rate_cap_tx_chainmask & BIT(i))
5581dd4f32aeSBjoern A. Zeeb 			txmcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i * 2);
5582dd4f32aeSBjoern A. Zeeb 		else
5583dd4f32aeSBjoern A. Zeeb 			txmcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i * 2);
5584dd4f32aeSBjoern A. Zeeb 
5585dd4f32aeSBjoern A. Zeeb 		if (i < ar->num_rx_chains && rate_cap_rx_chainmask & BIT(i))
5586dd4f32aeSBjoern A. Zeeb 			rxmcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i * 2);
5587dd4f32aeSBjoern A. Zeeb 		else
5588dd4f32aeSBjoern A. Zeeb 			rxmcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i * 2);
5589dd4f32aeSBjoern A. Zeeb 	}
5590dd4f32aeSBjoern A. Zeeb 
5591dd4f32aeSBjoern A. Zeeb 	if (rate_cap_tx_chainmask <= 1)
5592dd4f32aeSBjoern A. Zeeb 		vht_cap.cap &= ~IEEE80211_VHT_CAP_TXSTBC;
5593dd4f32aeSBjoern A. Zeeb 
5594dd4f32aeSBjoern A. Zeeb 	vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(rxmcs_map);
5595dd4f32aeSBjoern A. Zeeb 	vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(txmcs_map);
5596dd4f32aeSBjoern A. Zeeb 
5597dd4f32aeSBjoern A. Zeeb 	return vht_cap;
5598dd4f32aeSBjoern A. Zeeb }
5599dd4f32aeSBjoern A. Zeeb 
ath11k_mac_setup_ht_vht_cap(struct ath11k * ar,struct ath11k_pdev_cap * cap,u32 * ht_cap_info)5600dd4f32aeSBjoern A. Zeeb static void ath11k_mac_setup_ht_vht_cap(struct ath11k *ar,
5601dd4f32aeSBjoern A. Zeeb 					struct ath11k_pdev_cap *cap,
5602dd4f32aeSBjoern A. Zeeb 					u32 *ht_cap_info)
5603dd4f32aeSBjoern A. Zeeb {
5604dd4f32aeSBjoern A. Zeeb 	struct ieee80211_supported_band *band;
5605dd4f32aeSBjoern A. Zeeb 	u32 rate_cap_tx_chainmask;
5606dd4f32aeSBjoern A. Zeeb 	u32 rate_cap_rx_chainmask;
5607dd4f32aeSBjoern A. Zeeb 	u32 ht_cap;
5608dd4f32aeSBjoern A. Zeeb 
5609dd4f32aeSBjoern A. Zeeb 	rate_cap_tx_chainmask = ar->cfg_tx_chainmask >> cap->tx_chain_mask_shift;
5610dd4f32aeSBjoern A. Zeeb 	rate_cap_rx_chainmask = ar->cfg_rx_chainmask >> cap->rx_chain_mask_shift;
5611dd4f32aeSBjoern A. Zeeb 
5612dd4f32aeSBjoern A. Zeeb 	if (cap->supported_bands & WMI_HOST_WLAN_2G_CAP) {
5613dd4f32aeSBjoern A. Zeeb 		band = &ar->mac.sbands[NL80211_BAND_2GHZ];
5614dd4f32aeSBjoern A. Zeeb 		ht_cap = cap->band[NL80211_BAND_2GHZ].ht_cap_info;
5615dd4f32aeSBjoern A. Zeeb 		if (ht_cap_info)
5616dd4f32aeSBjoern A. Zeeb 			*ht_cap_info = ht_cap;
5617dd4f32aeSBjoern A. Zeeb 		band->ht_cap = ath11k_create_ht_cap(ar, ht_cap,
5618dd4f32aeSBjoern A. Zeeb 						    rate_cap_rx_chainmask);
5619dd4f32aeSBjoern A. Zeeb 	}
5620dd4f32aeSBjoern A. Zeeb 
5621dd4f32aeSBjoern A. Zeeb 	if (cap->supported_bands & WMI_HOST_WLAN_5G_CAP &&
5622dd4f32aeSBjoern A. Zeeb 	    (ar->ab->hw_params.single_pdev_only ||
5623dd4f32aeSBjoern A. Zeeb 	     !ar->supports_6ghz)) {
5624dd4f32aeSBjoern A. Zeeb 		band = &ar->mac.sbands[NL80211_BAND_5GHZ];
5625dd4f32aeSBjoern A. Zeeb 		ht_cap = cap->band[NL80211_BAND_5GHZ].ht_cap_info;
5626dd4f32aeSBjoern A. Zeeb 		if (ht_cap_info)
5627dd4f32aeSBjoern A. Zeeb 			*ht_cap_info = ht_cap;
5628dd4f32aeSBjoern A. Zeeb 		band->ht_cap = ath11k_create_ht_cap(ar, ht_cap,
5629dd4f32aeSBjoern A. Zeeb 						    rate_cap_rx_chainmask);
5630dd4f32aeSBjoern A. Zeeb 		band->vht_cap = ath11k_create_vht_cap(ar, rate_cap_tx_chainmask,
5631dd4f32aeSBjoern A. Zeeb 						      rate_cap_rx_chainmask);
5632dd4f32aeSBjoern A. Zeeb 	}
5633dd4f32aeSBjoern A. Zeeb }
5634dd4f32aeSBjoern A. Zeeb 
ath11k_check_chain_mask(struct ath11k * ar,u32 ant,bool is_tx_ant)5635dd4f32aeSBjoern A. Zeeb static int ath11k_check_chain_mask(struct ath11k *ar, u32 ant, bool is_tx_ant)
5636dd4f32aeSBjoern A. Zeeb {
5637dd4f32aeSBjoern A. Zeeb 	/* TODO: Check the request chainmask against the supported
5638dd4f32aeSBjoern A. Zeeb 	 * chainmask table which is advertised in extented_service_ready event
5639dd4f32aeSBjoern A. Zeeb 	 */
5640dd4f32aeSBjoern A. Zeeb 
5641dd4f32aeSBjoern A. Zeeb 	return 0;
5642dd4f32aeSBjoern A. Zeeb }
5643dd4f32aeSBjoern A. Zeeb 
ath11k_gen_ppe_thresh(struct ath11k_ppe_threshold * fw_ppet,u8 * he_ppet)5644dd4f32aeSBjoern A. Zeeb static void ath11k_gen_ppe_thresh(struct ath11k_ppe_threshold *fw_ppet,
5645dd4f32aeSBjoern A. Zeeb 				  u8 *he_ppet)
5646dd4f32aeSBjoern A. Zeeb {
5647dd4f32aeSBjoern A. Zeeb 	int nss, ru;
5648dd4f32aeSBjoern A. Zeeb 	u8 bit = 7;
5649dd4f32aeSBjoern A. Zeeb 
5650dd4f32aeSBjoern A. Zeeb 	he_ppet[0] = fw_ppet->numss_m1 & IEEE80211_PPE_THRES_NSS_MASK;
5651dd4f32aeSBjoern A. Zeeb 	he_ppet[0] |= (fw_ppet->ru_bit_mask <<
5652dd4f32aeSBjoern A. Zeeb 		       IEEE80211_PPE_THRES_RU_INDEX_BITMASK_POS) &
5653dd4f32aeSBjoern A. Zeeb 		      IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK;
5654dd4f32aeSBjoern A. Zeeb 	for (nss = 0; nss <= fw_ppet->numss_m1; nss++) {
5655dd4f32aeSBjoern A. Zeeb 		for (ru = 0; ru < 4; ru++) {
5656dd4f32aeSBjoern A. Zeeb 			u8 val;
5657dd4f32aeSBjoern A. Zeeb 			int i;
5658dd4f32aeSBjoern A. Zeeb 
5659dd4f32aeSBjoern A. Zeeb 			if ((fw_ppet->ru_bit_mask & BIT(ru)) == 0)
5660dd4f32aeSBjoern A. Zeeb 				continue;
5661dd4f32aeSBjoern A. Zeeb 			val = (fw_ppet->ppet16_ppet8_ru3_ru0[nss] >> (ru * 6)) &
5662dd4f32aeSBjoern A. Zeeb 			       0x3f;
5663dd4f32aeSBjoern A. Zeeb 			val = ((val >> 3) & 0x7) | ((val & 0x7) << 3);
5664dd4f32aeSBjoern A. Zeeb 			for (i = 5; i >= 0; i--) {
5665dd4f32aeSBjoern A. Zeeb 				he_ppet[bit / 8] |=
5666dd4f32aeSBjoern A. Zeeb 					((val >> i) & 0x1) << ((bit % 8));
5667dd4f32aeSBjoern A. Zeeb 				bit++;
5668dd4f32aeSBjoern A. Zeeb 			}
5669dd4f32aeSBjoern A. Zeeb 		}
5670dd4f32aeSBjoern A. Zeeb 	}
5671dd4f32aeSBjoern A. Zeeb }
5672dd4f32aeSBjoern A. Zeeb 
5673dd4f32aeSBjoern A. Zeeb static void
ath11k_mac_filter_he_cap_mesh(struct ieee80211_he_cap_elem * he_cap_elem)5674dd4f32aeSBjoern A. Zeeb ath11k_mac_filter_he_cap_mesh(struct ieee80211_he_cap_elem *he_cap_elem)
5675dd4f32aeSBjoern A. Zeeb {
5676dd4f32aeSBjoern A. Zeeb 	u8 m;
5677dd4f32aeSBjoern A. Zeeb 
5678dd4f32aeSBjoern A. Zeeb 	m = IEEE80211_HE_MAC_CAP0_TWT_RES |
5679dd4f32aeSBjoern A. Zeeb 	    IEEE80211_HE_MAC_CAP0_TWT_REQ;
5680dd4f32aeSBjoern A. Zeeb 	he_cap_elem->mac_cap_info[0] &= ~m;
5681dd4f32aeSBjoern A. Zeeb 
5682dd4f32aeSBjoern A. Zeeb 	m = IEEE80211_HE_MAC_CAP2_TRS |
5683dd4f32aeSBjoern A. Zeeb 	    IEEE80211_HE_MAC_CAP2_BCAST_TWT |
5684dd4f32aeSBjoern A. Zeeb 	    IEEE80211_HE_MAC_CAP2_MU_CASCADING;
5685dd4f32aeSBjoern A. Zeeb 	he_cap_elem->mac_cap_info[2] &= ~m;
5686dd4f32aeSBjoern A. Zeeb 
5687dd4f32aeSBjoern A. Zeeb 	m = IEEE80211_HE_MAC_CAP3_FLEX_TWT_SCHED |
5688dd4f32aeSBjoern A. Zeeb 	    IEEE80211_HE_MAC_CAP2_BCAST_TWT |
5689dd4f32aeSBjoern A. Zeeb 	    IEEE80211_HE_MAC_CAP2_MU_CASCADING;
5690dd4f32aeSBjoern A. Zeeb 	he_cap_elem->mac_cap_info[3] &= ~m;
5691dd4f32aeSBjoern A. Zeeb 
5692dd4f32aeSBjoern A. Zeeb 	m = IEEE80211_HE_MAC_CAP4_BSRP_BQRP_A_MPDU_AGG |
5693dd4f32aeSBjoern A. Zeeb 	    IEEE80211_HE_MAC_CAP4_BQR;
5694dd4f32aeSBjoern A. Zeeb 	he_cap_elem->mac_cap_info[4] &= ~m;
5695dd4f32aeSBjoern A. Zeeb 
5696dd4f32aeSBjoern A. Zeeb 	m = IEEE80211_HE_MAC_CAP5_SUBCHAN_SELECTIVE_TRANSMISSION |
5697dd4f32aeSBjoern A. Zeeb 	    IEEE80211_HE_MAC_CAP5_UL_2x996_TONE_RU |
5698dd4f32aeSBjoern A. Zeeb 	    IEEE80211_HE_MAC_CAP5_PUNCTURED_SOUNDING |
5699dd4f32aeSBjoern A. Zeeb 	    IEEE80211_HE_MAC_CAP5_HT_VHT_TRIG_FRAME_RX;
5700dd4f32aeSBjoern A. Zeeb 	he_cap_elem->mac_cap_info[5] &= ~m;
5701dd4f32aeSBjoern A. Zeeb 
5702dd4f32aeSBjoern A. Zeeb 	m = IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO |
5703dd4f32aeSBjoern A. Zeeb 	    IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO;
5704dd4f32aeSBjoern A. Zeeb 	he_cap_elem->phy_cap_info[2] &= ~m;
5705dd4f32aeSBjoern A. Zeeb 
5706dd4f32aeSBjoern A. Zeeb 	m = IEEE80211_HE_PHY_CAP3_RX_PARTIAL_BW_SU_IN_20MHZ_MU |
5707dd4f32aeSBjoern A. Zeeb 	    IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_MASK |
5708dd4f32aeSBjoern A. Zeeb 	    IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_MASK;
5709dd4f32aeSBjoern A. Zeeb 	he_cap_elem->phy_cap_info[3] &= ~m;
5710dd4f32aeSBjoern A. Zeeb 
5711dd4f32aeSBjoern A. Zeeb 	m = IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER;
5712dd4f32aeSBjoern A. Zeeb 	he_cap_elem->phy_cap_info[4] &= ~m;
5713dd4f32aeSBjoern A. Zeeb 
5714dd4f32aeSBjoern A. Zeeb 	m = IEEE80211_HE_PHY_CAP5_NG16_MU_FEEDBACK;
5715dd4f32aeSBjoern A. Zeeb 	he_cap_elem->phy_cap_info[5] &= ~m;
5716dd4f32aeSBjoern A. Zeeb 
5717dd4f32aeSBjoern A. Zeeb 	m = IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU |
5718dd4f32aeSBjoern A. Zeeb 	    IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMING_PARTIAL_BW_FB |
5719dd4f32aeSBjoern A. Zeeb 	    IEEE80211_HE_PHY_CAP6_TRIG_CQI_FB |
5720dd4f32aeSBjoern A. Zeeb 	    IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO;
5721dd4f32aeSBjoern A. Zeeb 	he_cap_elem->phy_cap_info[6] &= ~m;
5722dd4f32aeSBjoern A. Zeeb 
5723dd4f32aeSBjoern A. Zeeb 	m = IEEE80211_HE_PHY_CAP7_PSR_BASED_SR |
5724dd4f32aeSBjoern A. Zeeb 	    IEEE80211_HE_PHY_CAP7_POWER_BOOST_FACTOR_SUPP |
5725dd4f32aeSBjoern A. Zeeb 	    IEEE80211_HE_PHY_CAP7_STBC_TX_ABOVE_80MHZ |
5726dd4f32aeSBjoern A. Zeeb 	    IEEE80211_HE_PHY_CAP7_STBC_RX_ABOVE_80MHZ;
5727dd4f32aeSBjoern A. Zeeb 	he_cap_elem->phy_cap_info[7] &= ~m;
5728dd4f32aeSBjoern A. Zeeb 
5729dd4f32aeSBjoern A. Zeeb 	m = IEEE80211_HE_PHY_CAP8_HE_ER_SU_PPDU_4XLTF_AND_08_US_GI |
5730dd4f32aeSBjoern A. Zeeb 	    IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G |
5731dd4f32aeSBjoern A. Zeeb 	    IEEE80211_HE_PHY_CAP8_20MHZ_IN_160MHZ_HE_PPDU |
5732dd4f32aeSBjoern A. Zeeb 	    IEEE80211_HE_PHY_CAP8_80MHZ_IN_160MHZ_HE_PPDU;
5733dd4f32aeSBjoern A. Zeeb 	he_cap_elem->phy_cap_info[8] &= ~m;
5734dd4f32aeSBjoern A. Zeeb 
5735dd4f32aeSBjoern A. Zeeb 	m = IEEE80211_HE_PHY_CAP9_LONGER_THAN_16_SIGB_OFDM_SYM |
5736dd4f32aeSBjoern A. Zeeb 	    IEEE80211_HE_PHY_CAP9_NON_TRIGGERED_CQI_FEEDBACK |
5737dd4f32aeSBjoern A. Zeeb 	    IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU |
5738dd4f32aeSBjoern A. Zeeb 	    IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU |
5739dd4f32aeSBjoern A. Zeeb 	    IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB |
5740dd4f32aeSBjoern A. Zeeb 	    IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB;
5741dd4f32aeSBjoern A. Zeeb 	he_cap_elem->phy_cap_info[9] &= ~m;
5742dd4f32aeSBjoern A. Zeeb }
5743dd4f32aeSBjoern A. Zeeb 
ath11k_mac_setup_he_6ghz_cap(struct ath11k_pdev_cap * pcap,struct ath11k_band_cap * bcap)5744dd4f32aeSBjoern A. Zeeb static __le16 ath11k_mac_setup_he_6ghz_cap(struct ath11k_pdev_cap *pcap,
5745dd4f32aeSBjoern A. Zeeb 					   struct ath11k_band_cap *bcap)
5746dd4f32aeSBjoern A. Zeeb {
5747dd4f32aeSBjoern A. Zeeb 	u8 val;
5748dd4f32aeSBjoern A. Zeeb 
5749dd4f32aeSBjoern A. Zeeb 	bcap->he_6ghz_capa = IEEE80211_HT_MPDU_DENSITY_NONE;
5750dd4f32aeSBjoern A. Zeeb 	if (bcap->ht_cap_info & WMI_HT_CAP_DYNAMIC_SMPS)
5751dd4f32aeSBjoern A. Zeeb 		bcap->he_6ghz_capa |=
5752dd4f32aeSBjoern A. Zeeb 			FIELD_PREP(IEEE80211_HE_6GHZ_CAP_SM_PS,
5753dd4f32aeSBjoern A. Zeeb 				   WLAN_HT_CAP_SM_PS_DYNAMIC);
5754dd4f32aeSBjoern A. Zeeb 	else
5755dd4f32aeSBjoern A. Zeeb 		bcap->he_6ghz_capa |=
5756dd4f32aeSBjoern A. Zeeb 			FIELD_PREP(IEEE80211_HE_6GHZ_CAP_SM_PS,
5757dd4f32aeSBjoern A. Zeeb 				   WLAN_HT_CAP_SM_PS_DISABLED);
5758dd4f32aeSBjoern A. Zeeb 	val = FIELD_GET(IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK,
5759dd4f32aeSBjoern A. Zeeb 			pcap->vht_cap);
5760dd4f32aeSBjoern A. Zeeb 	bcap->he_6ghz_capa |=
5761dd4f32aeSBjoern A. Zeeb 		FIELD_PREP(IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP, val);
5762dd4f32aeSBjoern A. Zeeb 	val = FIELD_GET(IEEE80211_VHT_CAP_MAX_MPDU_MASK, pcap->vht_cap);
5763dd4f32aeSBjoern A. Zeeb 	bcap->he_6ghz_capa |=
5764dd4f32aeSBjoern A. Zeeb 		FIELD_PREP(IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN, val);
5765dd4f32aeSBjoern A. Zeeb 	if (pcap->vht_cap & IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN)
5766dd4f32aeSBjoern A. Zeeb 		bcap->he_6ghz_capa |= IEEE80211_HE_6GHZ_CAP_RX_ANTPAT_CONS;
5767dd4f32aeSBjoern A. Zeeb 	if (pcap->vht_cap & IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN)
5768dd4f32aeSBjoern A. Zeeb 		bcap->he_6ghz_capa |= IEEE80211_HE_6GHZ_CAP_TX_ANTPAT_CONS;
5769dd4f32aeSBjoern A. Zeeb 
5770dd4f32aeSBjoern A. Zeeb 	return cpu_to_le16(bcap->he_6ghz_capa);
5771dd4f32aeSBjoern A. Zeeb }
5772dd4f32aeSBjoern A. Zeeb 
ath11k_mac_set_hemcsmap(struct ath11k * ar,struct ath11k_pdev_cap * cap,struct ieee80211_sta_he_cap * he_cap,int band)5773*28348caeSBjoern A. Zeeb static void ath11k_mac_set_hemcsmap(struct ath11k *ar,
5774*28348caeSBjoern A. Zeeb 				    struct ath11k_pdev_cap *cap,
5775*28348caeSBjoern A. Zeeb 				    struct ieee80211_sta_he_cap *he_cap,
5776*28348caeSBjoern A. Zeeb 				    int band)
5777*28348caeSBjoern A. Zeeb {
5778*28348caeSBjoern A. Zeeb 	u16 txmcs_map, rxmcs_map;
5779*28348caeSBjoern A. Zeeb 	u32 i;
5780*28348caeSBjoern A. Zeeb 
5781*28348caeSBjoern A. Zeeb 	rxmcs_map = 0;
5782*28348caeSBjoern A. Zeeb 	txmcs_map = 0;
5783*28348caeSBjoern A. Zeeb 	for (i = 0; i < 8; i++) {
5784*28348caeSBjoern A. Zeeb 		if (i < ar->num_tx_chains &&
5785*28348caeSBjoern A. Zeeb 		    (ar->cfg_tx_chainmask >> cap->tx_chain_mask_shift) & BIT(i))
5786*28348caeSBjoern A. Zeeb 			txmcs_map |= IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2);
5787*28348caeSBjoern A. Zeeb 		else
5788*28348caeSBjoern A. Zeeb 			txmcs_map |= IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2);
5789*28348caeSBjoern A. Zeeb 
5790*28348caeSBjoern A. Zeeb 		if (i < ar->num_rx_chains &&
5791*28348caeSBjoern A. Zeeb 		    (ar->cfg_rx_chainmask >> cap->tx_chain_mask_shift) & BIT(i))
5792*28348caeSBjoern A. Zeeb 			rxmcs_map |= IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2);
5793*28348caeSBjoern A. Zeeb 		else
5794*28348caeSBjoern A. Zeeb 			rxmcs_map |= IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2);
5795*28348caeSBjoern A. Zeeb 	}
5796*28348caeSBjoern A. Zeeb 	he_cap->he_mcs_nss_supp.rx_mcs_80 =
5797*28348caeSBjoern A. Zeeb 		cpu_to_le16(rxmcs_map & 0xffff);
5798*28348caeSBjoern A. Zeeb 	he_cap->he_mcs_nss_supp.tx_mcs_80 =
5799*28348caeSBjoern A. Zeeb 		cpu_to_le16(txmcs_map & 0xffff);
5800*28348caeSBjoern A. Zeeb 	he_cap->he_mcs_nss_supp.rx_mcs_160 =
5801*28348caeSBjoern A. Zeeb 		cpu_to_le16(rxmcs_map & 0xffff);
5802*28348caeSBjoern A. Zeeb 	he_cap->he_mcs_nss_supp.tx_mcs_160 =
5803*28348caeSBjoern A. Zeeb 		cpu_to_le16(txmcs_map & 0xffff);
5804*28348caeSBjoern A. Zeeb 	he_cap->he_mcs_nss_supp.rx_mcs_80p80 =
5805*28348caeSBjoern A. Zeeb 		cpu_to_le16(rxmcs_map & 0xffff);
5806*28348caeSBjoern A. Zeeb 	he_cap->he_mcs_nss_supp.tx_mcs_80p80 =
5807*28348caeSBjoern A. Zeeb 		cpu_to_le16(txmcs_map & 0xffff);
5808*28348caeSBjoern A. Zeeb }
5809*28348caeSBjoern A. Zeeb 
ath11k_mac_copy_he_cap(struct ath11k * ar,struct ath11k_pdev_cap * cap,struct ieee80211_sband_iftype_data * data,int band)5810dd4f32aeSBjoern A. Zeeb static int ath11k_mac_copy_he_cap(struct ath11k *ar,
5811dd4f32aeSBjoern A. Zeeb 				  struct ath11k_pdev_cap *cap,
5812dd4f32aeSBjoern A. Zeeb 				  struct ieee80211_sband_iftype_data *data,
5813dd4f32aeSBjoern A. Zeeb 				  int band)
5814dd4f32aeSBjoern A. Zeeb {
5815dd4f32aeSBjoern A. Zeeb 	int i, idx = 0;
5816dd4f32aeSBjoern A. Zeeb 
5817dd4f32aeSBjoern A. Zeeb 	for (i = 0; i < NUM_NL80211_IFTYPES; i++) {
5818dd4f32aeSBjoern A. Zeeb 		struct ieee80211_sta_he_cap *he_cap = &data[idx].he_cap;
5819dd4f32aeSBjoern A. Zeeb 		struct ath11k_band_cap *band_cap = &cap->band[band];
5820dd4f32aeSBjoern A. Zeeb 		struct ieee80211_he_cap_elem *he_cap_elem =
5821dd4f32aeSBjoern A. Zeeb 				&he_cap->he_cap_elem;
5822dd4f32aeSBjoern A. Zeeb 
5823dd4f32aeSBjoern A. Zeeb 		switch (i) {
5824dd4f32aeSBjoern A. Zeeb 		case NL80211_IFTYPE_STATION:
5825dd4f32aeSBjoern A. Zeeb 		case NL80211_IFTYPE_AP:
5826dd4f32aeSBjoern A. Zeeb 		case NL80211_IFTYPE_MESH_POINT:
5827dd4f32aeSBjoern A. Zeeb 			break;
5828dd4f32aeSBjoern A. Zeeb 
5829dd4f32aeSBjoern A. Zeeb 		default:
5830dd4f32aeSBjoern A. Zeeb 			continue;
5831dd4f32aeSBjoern A. Zeeb 		}
5832dd4f32aeSBjoern A. Zeeb 
5833dd4f32aeSBjoern A. Zeeb 		data[idx].types_mask = BIT(i);
5834dd4f32aeSBjoern A. Zeeb 		he_cap->has_he = true;
5835dd4f32aeSBjoern A. Zeeb 		memcpy(he_cap_elem->mac_cap_info, band_cap->he_cap_info,
5836dd4f32aeSBjoern A. Zeeb 		       sizeof(he_cap_elem->mac_cap_info));
5837dd4f32aeSBjoern A. Zeeb 		memcpy(he_cap_elem->phy_cap_info, band_cap->he_cap_phy_info,
5838dd4f32aeSBjoern A. Zeeb 		       sizeof(he_cap_elem->phy_cap_info));
5839dd4f32aeSBjoern A. Zeeb 
5840dd4f32aeSBjoern A. Zeeb 		he_cap_elem->mac_cap_info[1] &=
5841dd4f32aeSBjoern A. Zeeb 			IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_MASK;
5842dd4f32aeSBjoern A. Zeeb 
5843dd4f32aeSBjoern A. Zeeb 		he_cap_elem->phy_cap_info[5] &=
5844dd4f32aeSBjoern A. Zeeb 			~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK;
5845dd4f32aeSBjoern A. Zeeb 		he_cap_elem->phy_cap_info[5] |= ar->num_tx_chains - 1;
5846dd4f32aeSBjoern A. Zeeb 
5847dd4f32aeSBjoern A. Zeeb 		switch (i) {
5848dd4f32aeSBjoern A. Zeeb 		case NL80211_IFTYPE_AP:
5849dd4f32aeSBjoern A. Zeeb 			he_cap_elem->phy_cap_info[3] &=
5850dd4f32aeSBjoern A. Zeeb 				~IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_MASK;
5851dd4f32aeSBjoern A. Zeeb 			he_cap_elem->phy_cap_info[9] |=
5852dd4f32aeSBjoern A. Zeeb 				IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU;
5853dd4f32aeSBjoern A. Zeeb 			break;
5854dd4f32aeSBjoern A. Zeeb 		case NL80211_IFTYPE_STATION:
5855dd4f32aeSBjoern A. Zeeb 			he_cap_elem->mac_cap_info[0] &=
5856dd4f32aeSBjoern A. Zeeb 				~IEEE80211_HE_MAC_CAP0_TWT_RES;
5857dd4f32aeSBjoern A. Zeeb 			he_cap_elem->mac_cap_info[0] |=
5858dd4f32aeSBjoern A. Zeeb 				IEEE80211_HE_MAC_CAP0_TWT_REQ;
5859dd4f32aeSBjoern A. Zeeb 			he_cap_elem->phy_cap_info[9] |=
5860dd4f32aeSBjoern A. Zeeb 				IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU;
5861dd4f32aeSBjoern A. Zeeb 			break;
5862dd4f32aeSBjoern A. Zeeb 		case NL80211_IFTYPE_MESH_POINT:
5863dd4f32aeSBjoern A. Zeeb 			ath11k_mac_filter_he_cap_mesh(he_cap_elem);
5864dd4f32aeSBjoern A. Zeeb 			break;
5865dd4f32aeSBjoern A. Zeeb 		}
5866dd4f32aeSBjoern A. Zeeb 
5867*28348caeSBjoern A. Zeeb 		ath11k_mac_set_hemcsmap(ar, cap, he_cap, band);
5868dd4f32aeSBjoern A. Zeeb 
5869dd4f32aeSBjoern A. Zeeb 		memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres));
5870dd4f32aeSBjoern A. Zeeb 		if (he_cap_elem->phy_cap_info[6] &
5871dd4f32aeSBjoern A. Zeeb 		    IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT)
5872dd4f32aeSBjoern A. Zeeb 			ath11k_gen_ppe_thresh(&band_cap->he_ppet,
5873dd4f32aeSBjoern A. Zeeb 					      he_cap->ppe_thres);
5874dd4f32aeSBjoern A. Zeeb 
5875dd4f32aeSBjoern A. Zeeb 		if (band == NL80211_BAND_6GHZ) {
5876dd4f32aeSBjoern A. Zeeb 			data[idx].he_6ghz_capa.capa =
5877dd4f32aeSBjoern A. Zeeb 				ath11k_mac_setup_he_6ghz_cap(cap, band_cap);
5878dd4f32aeSBjoern A. Zeeb 		}
5879dd4f32aeSBjoern A. Zeeb 		idx++;
5880dd4f32aeSBjoern A. Zeeb 	}
5881dd4f32aeSBjoern A. Zeeb 
5882dd4f32aeSBjoern A. Zeeb 	return idx;
5883dd4f32aeSBjoern A. Zeeb }
5884dd4f32aeSBjoern A. Zeeb 
ath11k_mac_setup_he_cap(struct ath11k * ar,struct ath11k_pdev_cap * cap)5885dd4f32aeSBjoern A. Zeeb static void ath11k_mac_setup_he_cap(struct ath11k *ar,
5886dd4f32aeSBjoern A. Zeeb 				    struct ath11k_pdev_cap *cap)
5887dd4f32aeSBjoern A. Zeeb {
5888dd4f32aeSBjoern A. Zeeb 	struct ieee80211_supported_band *band;
5889dd4f32aeSBjoern A. Zeeb 	int count;
5890dd4f32aeSBjoern A. Zeeb 
5891dd4f32aeSBjoern A. Zeeb 	if (cap->supported_bands & WMI_HOST_WLAN_2G_CAP) {
5892dd4f32aeSBjoern A. Zeeb 		count = ath11k_mac_copy_he_cap(ar, cap,
5893dd4f32aeSBjoern A. Zeeb 					       ar->mac.iftype[NL80211_BAND_2GHZ],
5894dd4f32aeSBjoern A. Zeeb 					       NL80211_BAND_2GHZ);
5895dd4f32aeSBjoern A. Zeeb 		band = &ar->mac.sbands[NL80211_BAND_2GHZ];
5896dd4f32aeSBjoern A. Zeeb 		band->iftype_data = ar->mac.iftype[NL80211_BAND_2GHZ];
5897dd4f32aeSBjoern A. Zeeb 		band->n_iftype_data = count;
5898dd4f32aeSBjoern A. Zeeb 	}
5899dd4f32aeSBjoern A. Zeeb 
5900dd4f32aeSBjoern A. Zeeb 	if (cap->supported_bands & WMI_HOST_WLAN_5G_CAP) {
5901dd4f32aeSBjoern A. Zeeb 		count = ath11k_mac_copy_he_cap(ar, cap,
5902dd4f32aeSBjoern A. Zeeb 					       ar->mac.iftype[NL80211_BAND_5GHZ],
5903dd4f32aeSBjoern A. Zeeb 					       NL80211_BAND_5GHZ);
5904dd4f32aeSBjoern A. Zeeb 		band = &ar->mac.sbands[NL80211_BAND_5GHZ];
5905dd4f32aeSBjoern A. Zeeb 		band->iftype_data = ar->mac.iftype[NL80211_BAND_5GHZ];
5906dd4f32aeSBjoern A. Zeeb 		band->n_iftype_data = count;
5907dd4f32aeSBjoern A. Zeeb 	}
5908dd4f32aeSBjoern A. Zeeb 
5909dd4f32aeSBjoern A. Zeeb 	if (cap->supported_bands & WMI_HOST_WLAN_5G_CAP &&
5910dd4f32aeSBjoern A. Zeeb 	    ar->supports_6ghz) {
5911dd4f32aeSBjoern A. Zeeb 		count = ath11k_mac_copy_he_cap(ar, cap,
5912dd4f32aeSBjoern A. Zeeb 					       ar->mac.iftype[NL80211_BAND_6GHZ],
5913dd4f32aeSBjoern A. Zeeb 					       NL80211_BAND_6GHZ);
5914dd4f32aeSBjoern A. Zeeb 		band = &ar->mac.sbands[NL80211_BAND_6GHZ];
5915dd4f32aeSBjoern A. Zeeb 		band->iftype_data = ar->mac.iftype[NL80211_BAND_6GHZ];
5916dd4f32aeSBjoern A. Zeeb 		band->n_iftype_data = count;
5917dd4f32aeSBjoern A. Zeeb 	}
5918dd4f32aeSBjoern A. Zeeb }
5919dd4f32aeSBjoern A. Zeeb 
__ath11k_set_antenna(struct ath11k * ar,u32 tx_ant,u32 rx_ant)5920dd4f32aeSBjoern A. Zeeb static int __ath11k_set_antenna(struct ath11k *ar, u32 tx_ant, u32 rx_ant)
5921dd4f32aeSBjoern A. Zeeb {
5922dd4f32aeSBjoern A. Zeeb 	int ret;
5923dd4f32aeSBjoern A. Zeeb 
5924dd4f32aeSBjoern A. Zeeb 	lockdep_assert_held(&ar->conf_mutex);
5925dd4f32aeSBjoern A. Zeeb 
5926dd4f32aeSBjoern A. Zeeb 	if (ath11k_check_chain_mask(ar, tx_ant, true))
5927dd4f32aeSBjoern A. Zeeb 		return -EINVAL;
5928dd4f32aeSBjoern A. Zeeb 
5929dd4f32aeSBjoern A. Zeeb 	if (ath11k_check_chain_mask(ar, rx_ant, false))
5930dd4f32aeSBjoern A. Zeeb 		return -EINVAL;
5931dd4f32aeSBjoern A. Zeeb 
5932dd4f32aeSBjoern A. Zeeb 	ar->cfg_tx_chainmask = tx_ant;
5933dd4f32aeSBjoern A. Zeeb 	ar->cfg_rx_chainmask = rx_ant;
5934dd4f32aeSBjoern A. Zeeb 
5935dd4f32aeSBjoern A. Zeeb 	if (ar->state != ATH11K_STATE_ON &&
5936dd4f32aeSBjoern A. Zeeb 	    ar->state != ATH11K_STATE_RESTARTED)
5937dd4f32aeSBjoern A. Zeeb 		return 0;
5938dd4f32aeSBjoern A. Zeeb 
5939dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_TX_CHAIN_MASK,
5940dd4f32aeSBjoern A. Zeeb 					tx_ant, ar->pdev->pdev_id);
5941dd4f32aeSBjoern A. Zeeb 	if (ret) {
5942dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to set tx-chainmask: %d, req 0x%x\n",
5943dd4f32aeSBjoern A. Zeeb 			    ret, tx_ant);
5944dd4f32aeSBjoern A. Zeeb 		return ret;
5945dd4f32aeSBjoern A. Zeeb 	}
5946dd4f32aeSBjoern A. Zeeb 
5947dd4f32aeSBjoern A. Zeeb 	ar->num_tx_chains = get_num_chains(tx_ant);
5948dd4f32aeSBjoern A. Zeeb 
5949dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_RX_CHAIN_MASK,
5950dd4f32aeSBjoern A. Zeeb 					rx_ant, ar->pdev->pdev_id);
5951dd4f32aeSBjoern A. Zeeb 	if (ret) {
5952dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to set rx-chainmask: %d, req 0x%x\n",
5953dd4f32aeSBjoern A. Zeeb 			    ret, rx_ant);
5954dd4f32aeSBjoern A. Zeeb 		return ret;
5955dd4f32aeSBjoern A. Zeeb 	}
5956dd4f32aeSBjoern A. Zeeb 
5957dd4f32aeSBjoern A. Zeeb 	ar->num_rx_chains = get_num_chains(rx_ant);
5958dd4f32aeSBjoern A. Zeeb 
5959dd4f32aeSBjoern A. Zeeb 	/* Reload HT/VHT/HE capability */
5960dd4f32aeSBjoern A. Zeeb 	ath11k_mac_setup_ht_vht_cap(ar, &ar->pdev->cap, NULL);
5961dd4f32aeSBjoern A. Zeeb 	ath11k_mac_setup_he_cap(ar, &ar->pdev->cap);
5962dd4f32aeSBjoern A. Zeeb 
5963dd4f32aeSBjoern A. Zeeb 	return 0;
5964dd4f32aeSBjoern A. Zeeb }
5965dd4f32aeSBjoern A. Zeeb 
ath11k_mgmt_over_wmi_tx_drop(struct ath11k * ar,struct sk_buff * skb)5966dd4f32aeSBjoern A. Zeeb static void ath11k_mgmt_over_wmi_tx_drop(struct ath11k *ar, struct sk_buff *skb)
5967dd4f32aeSBjoern A. Zeeb {
5968dd4f32aeSBjoern A. Zeeb 	int num_mgmt;
5969dd4f32aeSBjoern A. Zeeb 
5970dd4f32aeSBjoern A. Zeeb 	ieee80211_free_txskb(ar->hw, skb);
5971dd4f32aeSBjoern A. Zeeb 
5972dd4f32aeSBjoern A. Zeeb 	num_mgmt = atomic_dec_if_positive(&ar->num_pending_mgmt_tx);
5973dd4f32aeSBjoern A. Zeeb 
5974dd4f32aeSBjoern A. Zeeb 	if (num_mgmt < 0)
5975dd4f32aeSBjoern A. Zeeb 		WARN_ON_ONCE(1);
5976dd4f32aeSBjoern A. Zeeb 
5977dd4f32aeSBjoern A. Zeeb 	if (!num_mgmt)
5978dd4f32aeSBjoern A. Zeeb 		wake_up(&ar->txmgmt_empty_waitq);
5979dd4f32aeSBjoern A. Zeeb }
5980dd4f32aeSBjoern A. Zeeb 
ath11k_mac_tx_mgmt_free(struct ath11k * ar,int buf_id)5981dd4f32aeSBjoern A. Zeeb static void ath11k_mac_tx_mgmt_free(struct ath11k *ar, int buf_id)
5982dd4f32aeSBjoern A. Zeeb {
5983dd4f32aeSBjoern A. Zeeb 	struct sk_buff *msdu;
5984dd4f32aeSBjoern A. Zeeb 	struct ieee80211_tx_info *info;
5985dd4f32aeSBjoern A. Zeeb 
5986dd4f32aeSBjoern A. Zeeb 	spin_lock_bh(&ar->txmgmt_idr_lock);
5987dd4f32aeSBjoern A. Zeeb 	msdu = idr_remove(&ar->txmgmt_idr, buf_id);
5988dd4f32aeSBjoern A. Zeeb 	spin_unlock_bh(&ar->txmgmt_idr_lock);
5989dd4f32aeSBjoern A. Zeeb 
5990dd4f32aeSBjoern A. Zeeb 	if (!msdu)
5991dd4f32aeSBjoern A. Zeeb 		return;
5992dd4f32aeSBjoern A. Zeeb 
5993dd4f32aeSBjoern A. Zeeb 	dma_unmap_single(ar->ab->dev, ATH11K_SKB_CB(msdu)->paddr, msdu->len,
5994dd4f32aeSBjoern A. Zeeb 			 DMA_TO_DEVICE);
5995dd4f32aeSBjoern A. Zeeb 
5996dd4f32aeSBjoern A. Zeeb 	info = IEEE80211_SKB_CB(msdu);
5997dd4f32aeSBjoern A. Zeeb 	memset(&info->status, 0, sizeof(info->status));
5998dd4f32aeSBjoern A. Zeeb 
5999dd4f32aeSBjoern A. Zeeb 	ath11k_mgmt_over_wmi_tx_drop(ar, msdu);
6000dd4f32aeSBjoern A. Zeeb }
6001dd4f32aeSBjoern A. Zeeb 
ath11k_mac_tx_mgmt_pending_free(int buf_id,void * skb,void * ctx)6002dd4f32aeSBjoern A. Zeeb int ath11k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx)
6003dd4f32aeSBjoern A. Zeeb {
6004dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = ctx;
6005dd4f32aeSBjoern A. Zeeb 
6006dd4f32aeSBjoern A. Zeeb 	ath11k_mac_tx_mgmt_free(ar, buf_id);
6007dd4f32aeSBjoern A. Zeeb 
6008dd4f32aeSBjoern A. Zeeb 	return 0;
6009dd4f32aeSBjoern A. Zeeb }
6010dd4f32aeSBjoern A. Zeeb 
ath11k_mac_vif_txmgmt_idr_remove(int buf_id,void * skb,void * ctx)6011dd4f32aeSBjoern A. Zeeb static int ath11k_mac_vif_txmgmt_idr_remove(int buf_id, void *skb, void *ctx)
6012dd4f32aeSBjoern A. Zeeb {
6013dd4f32aeSBjoern A. Zeeb 	struct ieee80211_vif *vif = ctx;
6014dd4f32aeSBjoern A. Zeeb 	struct ath11k_skb_cb *skb_cb = ATH11K_SKB_CB((struct sk_buff *)skb);
6015dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = skb_cb->ar;
6016dd4f32aeSBjoern A. Zeeb 
6017dd4f32aeSBjoern A. Zeeb 	if (skb_cb->vif == vif)
6018dd4f32aeSBjoern A. Zeeb 		ath11k_mac_tx_mgmt_free(ar, buf_id);
6019dd4f32aeSBjoern A. Zeeb 
6020dd4f32aeSBjoern A. Zeeb 	return 0;
6021dd4f32aeSBjoern A. Zeeb }
6022dd4f32aeSBjoern A. Zeeb 
ath11k_mac_mgmt_tx_wmi(struct ath11k * ar,struct ath11k_vif * arvif,struct sk_buff * skb)6023dd4f32aeSBjoern A. Zeeb static int ath11k_mac_mgmt_tx_wmi(struct ath11k *ar, struct ath11k_vif *arvif,
6024dd4f32aeSBjoern A. Zeeb 				  struct sk_buff *skb)
6025dd4f32aeSBjoern A. Zeeb {
6026dd4f32aeSBjoern A. Zeeb 	struct ath11k_base *ab = ar->ab;
6027dd4f32aeSBjoern A. Zeeb 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
6028dd4f32aeSBjoern A. Zeeb 	struct ieee80211_tx_info *info;
6029dd4f32aeSBjoern A. Zeeb 	dma_addr_t paddr;
6030dd4f32aeSBjoern A. Zeeb 	int buf_id;
6031dd4f32aeSBjoern A. Zeeb 	int ret;
6032dd4f32aeSBjoern A. Zeeb 
6033dd4f32aeSBjoern A. Zeeb 	ATH11K_SKB_CB(skb)->ar = ar;
6034dd4f32aeSBjoern A. Zeeb 
6035dd4f32aeSBjoern A. Zeeb 	spin_lock_bh(&ar->txmgmt_idr_lock);
6036dd4f32aeSBjoern A. Zeeb 	buf_id = idr_alloc(&ar->txmgmt_idr, skb, 0,
6037dd4f32aeSBjoern A. Zeeb 			   ATH11K_TX_MGMT_NUM_PENDING_MAX, GFP_ATOMIC);
6038dd4f32aeSBjoern A. Zeeb 	spin_unlock_bh(&ar->txmgmt_idr_lock);
6039dd4f32aeSBjoern A. Zeeb 
6040dd4f32aeSBjoern A. Zeeb 	ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
6041*28348caeSBjoern A. Zeeb 		   "tx mgmt frame, buf id %d\n", buf_id);
6042dd4f32aeSBjoern A. Zeeb 
6043dd4f32aeSBjoern A. Zeeb 	if (buf_id < 0)
6044dd4f32aeSBjoern A. Zeeb 		return -ENOSPC;
6045dd4f32aeSBjoern A. Zeeb 
6046dd4f32aeSBjoern A. Zeeb 	info = IEEE80211_SKB_CB(skb);
6047dd4f32aeSBjoern A. Zeeb 	if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP)) {
6048dd4f32aeSBjoern A. Zeeb 		if ((ieee80211_is_action(hdr->frame_control) ||
6049dd4f32aeSBjoern A. Zeeb 		     ieee80211_is_deauth(hdr->frame_control) ||
6050dd4f32aeSBjoern A. Zeeb 		     ieee80211_is_disassoc(hdr->frame_control)) &&
6051dd4f32aeSBjoern A. Zeeb 		     ieee80211_has_protected(hdr->frame_control)) {
6052dd4f32aeSBjoern A. Zeeb 			skb_put(skb, IEEE80211_CCMP_MIC_LEN);
6053dd4f32aeSBjoern A. Zeeb 		}
6054dd4f32aeSBjoern A. Zeeb 	}
6055dd4f32aeSBjoern A. Zeeb 
6056dd4f32aeSBjoern A. Zeeb 	paddr = dma_map_single(ab->dev, skb->data, skb->len, DMA_TO_DEVICE);
6057dd4f32aeSBjoern A. Zeeb 	if (dma_mapping_error(ab->dev, paddr)) {
6058dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ab, "failed to DMA map mgmt Tx buffer\n");
6059dd4f32aeSBjoern A. Zeeb 		ret = -EIO;
6060dd4f32aeSBjoern A. Zeeb 		goto err_free_idr;
6061dd4f32aeSBjoern A. Zeeb 	}
6062dd4f32aeSBjoern A. Zeeb 
6063dd4f32aeSBjoern A. Zeeb 	ATH11K_SKB_CB(skb)->paddr = paddr;
6064dd4f32aeSBjoern A. Zeeb 
6065dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_mgmt_send(ar, arvif->vdev_id, buf_id, skb);
6066dd4f32aeSBjoern A. Zeeb 	if (ret) {
6067dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to send mgmt frame: %d\n", ret);
6068dd4f32aeSBjoern A. Zeeb 		goto err_unmap_buf;
6069dd4f32aeSBjoern A. Zeeb 	}
6070dd4f32aeSBjoern A. Zeeb 
6071dd4f32aeSBjoern A. Zeeb 	return 0;
6072dd4f32aeSBjoern A. Zeeb 
6073dd4f32aeSBjoern A. Zeeb err_unmap_buf:
6074dd4f32aeSBjoern A. Zeeb 	dma_unmap_single(ab->dev, ATH11K_SKB_CB(skb)->paddr,
6075dd4f32aeSBjoern A. Zeeb 			 skb->len, DMA_TO_DEVICE);
6076dd4f32aeSBjoern A. Zeeb err_free_idr:
6077dd4f32aeSBjoern A. Zeeb 	spin_lock_bh(&ar->txmgmt_idr_lock);
6078dd4f32aeSBjoern A. Zeeb 	idr_remove(&ar->txmgmt_idr, buf_id);
6079dd4f32aeSBjoern A. Zeeb 	spin_unlock_bh(&ar->txmgmt_idr_lock);
6080dd4f32aeSBjoern A. Zeeb 
6081dd4f32aeSBjoern A. Zeeb 	return ret;
6082dd4f32aeSBjoern A. Zeeb }
6083dd4f32aeSBjoern A. Zeeb 
ath11k_mgmt_over_wmi_tx_purge(struct ath11k * ar)6084dd4f32aeSBjoern A. Zeeb static void ath11k_mgmt_over_wmi_tx_purge(struct ath11k *ar)
6085dd4f32aeSBjoern A. Zeeb {
6086dd4f32aeSBjoern A. Zeeb 	struct sk_buff *skb;
6087dd4f32aeSBjoern A. Zeeb 
6088dd4f32aeSBjoern A. Zeeb 	while ((skb = skb_dequeue(&ar->wmi_mgmt_tx_queue)) != NULL)
6089dd4f32aeSBjoern A. Zeeb 		ath11k_mgmt_over_wmi_tx_drop(ar, skb);
6090dd4f32aeSBjoern A. Zeeb }
6091dd4f32aeSBjoern A. Zeeb 
ath11k_mgmt_over_wmi_tx_work(struct work_struct * work)6092dd4f32aeSBjoern A. Zeeb static void ath11k_mgmt_over_wmi_tx_work(struct work_struct *work)
6093dd4f32aeSBjoern A. Zeeb {
6094dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = container_of(work, struct ath11k, wmi_mgmt_tx_work);
6095dd4f32aeSBjoern A. Zeeb 	struct ath11k_skb_cb *skb_cb;
6096dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif;
6097dd4f32aeSBjoern A. Zeeb 	struct sk_buff *skb;
6098dd4f32aeSBjoern A. Zeeb 	int ret;
6099dd4f32aeSBjoern A. Zeeb 
6100dd4f32aeSBjoern A. Zeeb 	while ((skb = skb_dequeue(&ar->wmi_mgmt_tx_queue)) != NULL) {
6101dd4f32aeSBjoern A. Zeeb 		skb_cb = ATH11K_SKB_CB(skb);
6102dd4f32aeSBjoern A. Zeeb 		if (!skb_cb->vif) {
6103dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "no vif found for mgmt frame\n");
6104dd4f32aeSBjoern A. Zeeb 			ath11k_mgmt_over_wmi_tx_drop(ar, skb);
6105dd4f32aeSBjoern A. Zeeb 			continue;
6106dd4f32aeSBjoern A. Zeeb 		}
6107dd4f32aeSBjoern A. Zeeb 
6108dd4f32aeSBjoern A. Zeeb 		arvif = ath11k_vif_to_arvif(skb_cb->vif);
6109*28348caeSBjoern A. Zeeb 		mutex_lock(&ar->conf_mutex);
6110*28348caeSBjoern A. Zeeb 		if (ar->allocated_vdev_map & (1LL << arvif->vdev_id)) {
6111dd4f32aeSBjoern A. Zeeb 			ret = ath11k_mac_mgmt_tx_wmi(ar, arvif, skb);
6112dd4f32aeSBjoern A. Zeeb 			if (ret) {
6113dd4f32aeSBjoern A. Zeeb 				ath11k_warn(ar->ab, "failed to tx mgmt frame, vdev_id %d :%d\n",
6114dd4f32aeSBjoern A. Zeeb 					    arvif->vdev_id, ret);
6115dd4f32aeSBjoern A. Zeeb 				ath11k_mgmt_over_wmi_tx_drop(ar, skb);
6116dd4f32aeSBjoern A. Zeeb 			} else {
6117dd4f32aeSBjoern A. Zeeb 				ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
6118*28348caeSBjoern A. Zeeb 					   "tx mgmt frame, vdev_id %d\n",
6119dd4f32aeSBjoern A. Zeeb 					   arvif->vdev_id);
6120dd4f32aeSBjoern A. Zeeb 			}
6121dd4f32aeSBjoern A. Zeeb 		} else {
6122dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab,
6123dd4f32aeSBjoern A. Zeeb 				    "dropping mgmt frame for vdev %d, is_started %d\n",
6124dd4f32aeSBjoern A. Zeeb 				    arvif->vdev_id,
6125dd4f32aeSBjoern A. Zeeb 				    arvif->is_started);
6126dd4f32aeSBjoern A. Zeeb 			ath11k_mgmt_over_wmi_tx_drop(ar, skb);
6127dd4f32aeSBjoern A. Zeeb 		}
6128*28348caeSBjoern A. Zeeb 		mutex_unlock(&ar->conf_mutex);
6129dd4f32aeSBjoern A. Zeeb 	}
6130dd4f32aeSBjoern A. Zeeb }
6131dd4f32aeSBjoern A. Zeeb 
ath11k_mac_mgmt_tx(struct ath11k * ar,struct sk_buff * skb,bool is_prb_rsp)6132dd4f32aeSBjoern A. Zeeb static int ath11k_mac_mgmt_tx(struct ath11k *ar, struct sk_buff *skb,
6133dd4f32aeSBjoern A. Zeeb 			      bool is_prb_rsp)
6134dd4f32aeSBjoern A. Zeeb {
6135dd4f32aeSBjoern A. Zeeb 	struct sk_buff_head *q = &ar->wmi_mgmt_tx_queue;
6136dd4f32aeSBjoern A. Zeeb 
6137dd4f32aeSBjoern A. Zeeb 	if (test_bit(ATH11K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))
6138dd4f32aeSBjoern A. Zeeb 		return -ESHUTDOWN;
6139dd4f32aeSBjoern A. Zeeb 
6140dd4f32aeSBjoern A. Zeeb 	/* Drop probe response packets when the pending management tx
6141dd4f32aeSBjoern A. Zeeb 	 * count has reached a certain threshold, so as to prioritize
6142dd4f32aeSBjoern A. Zeeb 	 * other mgmt packets like auth and assoc to be sent on time
6143dd4f32aeSBjoern A. Zeeb 	 * for establishing successful connections.
6144dd4f32aeSBjoern A. Zeeb 	 */
6145dd4f32aeSBjoern A. Zeeb 	if (is_prb_rsp &&
6146dd4f32aeSBjoern A. Zeeb 	    atomic_read(&ar->num_pending_mgmt_tx) > ATH11K_PRB_RSP_DROP_THRESHOLD) {
6147dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab,
6148dd4f32aeSBjoern A. Zeeb 			    "dropping probe response as pending queue is almost full\n");
6149dd4f32aeSBjoern A. Zeeb 		return -ENOSPC;
6150dd4f32aeSBjoern A. Zeeb 	}
6151dd4f32aeSBjoern A. Zeeb 
6152dd4f32aeSBjoern A. Zeeb 	if (skb_queue_len_lockless(q) >= ATH11K_TX_MGMT_NUM_PENDING_MAX) {
6153dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "mgmt tx queue is full\n");
6154dd4f32aeSBjoern A. Zeeb 		return -ENOSPC;
6155dd4f32aeSBjoern A. Zeeb 	}
6156dd4f32aeSBjoern A. Zeeb 
6157dd4f32aeSBjoern A. Zeeb 	skb_queue_tail(q, skb);
6158dd4f32aeSBjoern A. Zeeb 	atomic_inc(&ar->num_pending_mgmt_tx);
6159*28348caeSBjoern A. Zeeb 	queue_work(ar->ab->workqueue_aux, &ar->wmi_mgmt_tx_work);
6160dd4f32aeSBjoern A. Zeeb 
6161dd4f32aeSBjoern A. Zeeb 	return 0;
6162dd4f32aeSBjoern A. Zeeb }
6163dd4f32aeSBjoern A. Zeeb 
ath11k_mac_op_tx(struct ieee80211_hw * hw,struct ieee80211_tx_control * control,struct sk_buff * skb)6164dd4f32aeSBjoern A. Zeeb static void ath11k_mac_op_tx(struct ieee80211_hw *hw,
6165dd4f32aeSBjoern A. Zeeb 			     struct ieee80211_tx_control *control,
6166dd4f32aeSBjoern A. Zeeb 			     struct sk_buff *skb)
6167dd4f32aeSBjoern A. Zeeb {
6168dd4f32aeSBjoern A. Zeeb 	struct ath11k_skb_cb *skb_cb = ATH11K_SKB_CB(skb);
6169dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = hw->priv;
6170dd4f32aeSBjoern A. Zeeb 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
6171dd4f32aeSBjoern A. Zeeb 	struct ieee80211_vif *vif = info->control.vif;
6172dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
6173dd4f32aeSBjoern A. Zeeb 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
6174dd4f32aeSBjoern A. Zeeb 	struct ieee80211_key_conf *key = info->control.hw_key;
6175dd4f32aeSBjoern A. Zeeb 	struct ath11k_sta *arsta = NULL;
6176dd4f32aeSBjoern A. Zeeb 	u32 info_flags = info->flags;
6177dd4f32aeSBjoern A. Zeeb 	bool is_prb_rsp;
6178dd4f32aeSBjoern A. Zeeb 	int ret;
6179dd4f32aeSBjoern A. Zeeb 
6180dd4f32aeSBjoern A. Zeeb 	memset(skb_cb, 0, sizeof(*skb_cb));
6181dd4f32aeSBjoern A. Zeeb 	skb_cb->vif = vif;
6182dd4f32aeSBjoern A. Zeeb 
6183dd4f32aeSBjoern A. Zeeb 	if (key) {
6184dd4f32aeSBjoern A. Zeeb 		skb_cb->cipher = key->cipher;
6185dd4f32aeSBjoern A. Zeeb 		skb_cb->flags |= ATH11K_SKB_CIPHER_SET;
6186dd4f32aeSBjoern A. Zeeb 	}
6187dd4f32aeSBjoern A. Zeeb 
6188dd4f32aeSBjoern A. Zeeb 	if (info_flags & IEEE80211_TX_CTL_HW_80211_ENCAP) {
6189dd4f32aeSBjoern A. Zeeb 		skb_cb->flags |= ATH11K_SKB_HW_80211_ENCAP;
6190dd4f32aeSBjoern A. Zeeb 	} else if (ieee80211_is_mgmt(hdr->frame_control)) {
6191dd4f32aeSBjoern A. Zeeb 		is_prb_rsp = ieee80211_is_probe_resp(hdr->frame_control);
6192dd4f32aeSBjoern A. Zeeb 		ret = ath11k_mac_mgmt_tx(ar, skb, is_prb_rsp);
6193dd4f32aeSBjoern A. Zeeb 		if (ret) {
6194dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "failed to queue management frame %d\n",
6195dd4f32aeSBjoern A. Zeeb 				    ret);
6196dd4f32aeSBjoern A. Zeeb 			ieee80211_free_txskb(ar->hw, skb);
6197dd4f32aeSBjoern A. Zeeb 		}
6198dd4f32aeSBjoern A. Zeeb 		return;
6199dd4f32aeSBjoern A. Zeeb 	}
6200dd4f32aeSBjoern A. Zeeb 
6201dd4f32aeSBjoern A. Zeeb 	if (control->sta)
6202dd4f32aeSBjoern A. Zeeb 		arsta = (struct ath11k_sta *)control->sta->drv_priv;
6203dd4f32aeSBjoern A. Zeeb 
6204dd4f32aeSBjoern A. Zeeb 	ret = ath11k_dp_tx(ar, arvif, arsta, skb);
6205dd4f32aeSBjoern A. Zeeb 	if (unlikely(ret)) {
6206dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to transmit frame %d\n", ret);
6207dd4f32aeSBjoern A. Zeeb 		ieee80211_free_txskb(ar->hw, skb);
6208dd4f32aeSBjoern A. Zeeb 	}
6209dd4f32aeSBjoern A. Zeeb }
6210dd4f32aeSBjoern A. Zeeb 
ath11k_mac_drain_tx(struct ath11k * ar)6211dd4f32aeSBjoern A. Zeeb void ath11k_mac_drain_tx(struct ath11k *ar)
6212dd4f32aeSBjoern A. Zeeb {
6213dd4f32aeSBjoern A. Zeeb 	/* make sure rcu-protected mac80211 tx path itself is drained */
6214dd4f32aeSBjoern A. Zeeb 	synchronize_net();
6215dd4f32aeSBjoern A. Zeeb 
6216dd4f32aeSBjoern A. Zeeb 	cancel_work_sync(&ar->wmi_mgmt_tx_work);
6217dd4f32aeSBjoern A. Zeeb 	ath11k_mgmt_over_wmi_tx_purge(ar);
6218dd4f32aeSBjoern A. Zeeb }
6219dd4f32aeSBjoern A. Zeeb 
ath11k_mac_config_mon_status_default(struct ath11k * ar,bool enable)6220dd4f32aeSBjoern A. Zeeb static int ath11k_mac_config_mon_status_default(struct ath11k *ar, bool enable)
6221dd4f32aeSBjoern A. Zeeb {
6222dd4f32aeSBjoern A. Zeeb 	struct htt_rx_ring_tlv_filter tlv_filter = {0};
6223dd4f32aeSBjoern A. Zeeb 	struct ath11k_base *ab = ar->ab;
6224dd4f32aeSBjoern A. Zeeb 	int i, ret = 0;
6225dd4f32aeSBjoern A. Zeeb 	u32 ring_id;
6226dd4f32aeSBjoern A. Zeeb 
6227dd4f32aeSBjoern A. Zeeb 	if (enable) {
6228dd4f32aeSBjoern A. Zeeb 		tlv_filter = ath11k_mac_mon_status_filter_default;
6229dd4f32aeSBjoern A. Zeeb 		if (ath11k_debugfs_rx_filter(ar))
6230dd4f32aeSBjoern A. Zeeb 			tlv_filter.rx_filter = ath11k_debugfs_rx_filter(ar);
6231dd4f32aeSBjoern A. Zeeb 	}
6232dd4f32aeSBjoern A. Zeeb 
6233dd4f32aeSBjoern A. Zeeb 	for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
6234dd4f32aeSBjoern A. Zeeb 		ring_id = ar->dp.rx_mon_status_refill_ring[i].refill_buf_ring.ring_id;
6235dd4f32aeSBjoern A. Zeeb 		ret = ath11k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id,
6236dd4f32aeSBjoern A. Zeeb 						       ar->dp.mac_id + i,
6237dd4f32aeSBjoern A. Zeeb 						       HAL_RXDMA_MONITOR_STATUS,
6238dd4f32aeSBjoern A. Zeeb 						       DP_RX_BUFFER_SIZE,
6239dd4f32aeSBjoern A. Zeeb 						       &tlv_filter);
6240dd4f32aeSBjoern A. Zeeb 	}
6241dd4f32aeSBjoern A. Zeeb 
6242dd4f32aeSBjoern A. Zeeb 	if (enable && !ar->ab->hw_params.rxdma1_enable)
6243dd4f32aeSBjoern A. Zeeb 		mod_timer(&ar->ab->mon_reap_timer, jiffies +
6244dd4f32aeSBjoern A. Zeeb 			  msecs_to_jiffies(ATH11K_MON_TIMER_INTERVAL));
6245dd4f32aeSBjoern A. Zeeb 
6246dd4f32aeSBjoern A. Zeeb 	return ret;
6247dd4f32aeSBjoern A. Zeeb }
6248dd4f32aeSBjoern A. Zeeb 
ath11k_mac_wait_reconfigure(struct ath11k_base * ab)6249*28348caeSBjoern A. Zeeb static void ath11k_mac_wait_reconfigure(struct ath11k_base *ab)
6250*28348caeSBjoern A. Zeeb {
6251*28348caeSBjoern A. Zeeb 	int recovery_start_count;
6252*28348caeSBjoern A. Zeeb 
6253*28348caeSBjoern A. Zeeb 	if (!ab->is_reset)
6254*28348caeSBjoern A. Zeeb 		return;
6255*28348caeSBjoern A. Zeeb 
6256*28348caeSBjoern A. Zeeb 	recovery_start_count = atomic_inc_return(&ab->recovery_start_count);
6257*28348caeSBjoern A. Zeeb 	ath11k_dbg(ab, ATH11K_DBG_MAC, "recovery start count %d\n", recovery_start_count);
6258*28348caeSBjoern A. Zeeb 
6259*28348caeSBjoern A. Zeeb 	if (recovery_start_count == ab->num_radios) {
6260*28348caeSBjoern A. Zeeb 		complete(&ab->recovery_start);
6261*28348caeSBjoern A. Zeeb 		ath11k_dbg(ab, ATH11K_DBG_MAC, "recovery started success\n");
6262*28348caeSBjoern A. Zeeb 	}
6263*28348caeSBjoern A. Zeeb 
6264*28348caeSBjoern A. Zeeb 	ath11k_dbg(ab, ATH11K_DBG_MAC, "waiting reconfigure...\n");
6265*28348caeSBjoern A. Zeeb 
6266*28348caeSBjoern A. Zeeb 	wait_for_completion_timeout(&ab->reconfigure_complete,
6267*28348caeSBjoern A. Zeeb 				    ATH11K_RECONFIGURE_TIMEOUT_HZ);
6268*28348caeSBjoern A. Zeeb }
6269*28348caeSBjoern A. Zeeb 
ath11k_mac_op_start(struct ieee80211_hw * hw)6270dd4f32aeSBjoern A. Zeeb static int ath11k_mac_op_start(struct ieee80211_hw *hw)
6271dd4f32aeSBjoern A. Zeeb {
6272dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = hw->priv;
6273dd4f32aeSBjoern A. Zeeb 	struct ath11k_base *ab = ar->ab;
6274dd4f32aeSBjoern A. Zeeb 	struct ath11k_pdev *pdev = ar->pdev;
6275dd4f32aeSBjoern A. Zeeb 	int ret;
6276dd4f32aeSBjoern A. Zeeb 
6277*28348caeSBjoern A. Zeeb 	if (ath11k_ftm_mode) {
6278*28348caeSBjoern A. Zeeb 		ath11k_warn(ab, "mac operations not supported in factory test mode\n");
6279*28348caeSBjoern A. Zeeb 		return -EOPNOTSUPP;
6280*28348caeSBjoern A. Zeeb 	}
6281*28348caeSBjoern A. Zeeb 
6282dd4f32aeSBjoern A. Zeeb 	ath11k_mac_drain_tx(ar);
6283dd4f32aeSBjoern A. Zeeb 	mutex_lock(&ar->conf_mutex);
6284dd4f32aeSBjoern A. Zeeb 
6285dd4f32aeSBjoern A. Zeeb 	switch (ar->state) {
6286dd4f32aeSBjoern A. Zeeb 	case ATH11K_STATE_OFF:
6287dd4f32aeSBjoern A. Zeeb 		ar->state = ATH11K_STATE_ON;
6288dd4f32aeSBjoern A. Zeeb 		break;
6289dd4f32aeSBjoern A. Zeeb 	case ATH11K_STATE_RESTARTING:
6290dd4f32aeSBjoern A. Zeeb 		ar->state = ATH11K_STATE_RESTARTED;
6291*28348caeSBjoern A. Zeeb 		ath11k_mac_wait_reconfigure(ab);
6292dd4f32aeSBjoern A. Zeeb 		break;
6293dd4f32aeSBjoern A. Zeeb 	case ATH11K_STATE_RESTARTED:
6294dd4f32aeSBjoern A. Zeeb 	case ATH11K_STATE_WEDGED:
6295dd4f32aeSBjoern A. Zeeb 	case ATH11K_STATE_ON:
6296*28348caeSBjoern A. Zeeb 	case ATH11K_STATE_FTM:
6297dd4f32aeSBjoern A. Zeeb 		WARN_ON(1);
6298dd4f32aeSBjoern A. Zeeb 		ret = -EINVAL;
6299dd4f32aeSBjoern A. Zeeb 		goto err;
6300dd4f32aeSBjoern A. Zeeb 	}
6301dd4f32aeSBjoern A. Zeeb 
6302dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_PMF_QOS,
6303dd4f32aeSBjoern A. Zeeb 					1, pdev->pdev_id);
6304dd4f32aeSBjoern A. Zeeb 
6305dd4f32aeSBjoern A. Zeeb 	if (ret) {
6306dd4f32aeSBjoern A. Zeeb 		ath11k_err(ar->ab, "failed to enable PMF QOS: (%d\n", ret);
6307dd4f32aeSBjoern A. Zeeb 		goto err;
6308dd4f32aeSBjoern A. Zeeb 	}
6309dd4f32aeSBjoern A. Zeeb 
6310dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_DYNAMIC_BW, 1,
6311dd4f32aeSBjoern A. Zeeb 					pdev->pdev_id);
6312dd4f32aeSBjoern A. Zeeb 	if (ret) {
6313dd4f32aeSBjoern A. Zeeb 		ath11k_err(ar->ab, "failed to enable dynamic bw: %d\n", ret);
6314dd4f32aeSBjoern A. Zeeb 		goto err;
6315dd4f32aeSBjoern A. Zeeb 	}
6316dd4f32aeSBjoern A. Zeeb 
6317dd4f32aeSBjoern A. Zeeb 	if (test_bit(WMI_TLV_SERVICE_SPOOF_MAC_SUPPORT, ar->wmi->wmi_ab->svc_map)) {
6318dd4f32aeSBjoern A. Zeeb 		ret = ath11k_wmi_scan_prob_req_oui(ar, ar->mac_addr);
6319dd4f32aeSBjoern A. Zeeb 		if (ret) {
6320dd4f32aeSBjoern A. Zeeb 			ath11k_err(ab, "failed to set prob req oui: %i\n", ret);
6321dd4f32aeSBjoern A. Zeeb 			goto err;
6322dd4f32aeSBjoern A. Zeeb 		}
6323dd4f32aeSBjoern A. Zeeb 	}
6324dd4f32aeSBjoern A. Zeeb 
6325dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_ARP_AC_OVERRIDE,
6326dd4f32aeSBjoern A. Zeeb 					0, pdev->pdev_id);
6327dd4f32aeSBjoern A. Zeeb 	if (ret) {
6328dd4f32aeSBjoern A. Zeeb 		ath11k_err(ab, "failed to set ac override for ARP: %d\n",
6329dd4f32aeSBjoern A. Zeeb 			   ret);
6330dd4f32aeSBjoern A. Zeeb 		goto err;
6331dd4f32aeSBjoern A. Zeeb 	}
6332dd4f32aeSBjoern A. Zeeb 
6333dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_send_dfs_phyerr_offload_enable_cmd(ar, pdev->pdev_id);
6334dd4f32aeSBjoern A. Zeeb 	if (ret) {
6335dd4f32aeSBjoern A. Zeeb 		ath11k_err(ab, "failed to offload radar detection: %d\n",
6336dd4f32aeSBjoern A. Zeeb 			   ret);
6337dd4f32aeSBjoern A. Zeeb 		goto err;
6338dd4f32aeSBjoern A. Zeeb 	}
6339dd4f32aeSBjoern A. Zeeb 
6340dd4f32aeSBjoern A. Zeeb 	ret = ath11k_dp_tx_htt_h2t_ppdu_stats_req(ar,
6341dd4f32aeSBjoern A. Zeeb 						  HTT_PPDU_STATS_TAG_DEFAULT);
6342dd4f32aeSBjoern A. Zeeb 	if (ret) {
6343dd4f32aeSBjoern A. Zeeb 		ath11k_err(ab, "failed to req ppdu stats: %d\n", ret);
6344dd4f32aeSBjoern A. Zeeb 		goto err;
6345dd4f32aeSBjoern A. Zeeb 	}
6346dd4f32aeSBjoern A. Zeeb 
6347dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_MESH_MCAST_ENABLE,
6348dd4f32aeSBjoern A. Zeeb 					1, pdev->pdev_id);
6349dd4f32aeSBjoern A. Zeeb 
6350dd4f32aeSBjoern A. Zeeb 	if (ret) {
6351dd4f32aeSBjoern A. Zeeb 		ath11k_err(ar->ab, "failed to enable MESH MCAST ENABLE: (%d\n", ret);
6352dd4f32aeSBjoern A. Zeeb 		goto err;
6353dd4f32aeSBjoern A. Zeeb 	}
6354dd4f32aeSBjoern A. Zeeb 
6355dd4f32aeSBjoern A. Zeeb 	__ath11k_set_antenna(ar, ar->cfg_tx_chainmask, ar->cfg_rx_chainmask);
6356dd4f32aeSBjoern A. Zeeb 
6357dd4f32aeSBjoern A. Zeeb 	/* TODO: Do we need to enable ANI? */
6358dd4f32aeSBjoern A. Zeeb 
6359*28348caeSBjoern A. Zeeb 	ath11k_reg_update_chan_list(ar, false);
6360dd4f32aeSBjoern A. Zeeb 
6361dd4f32aeSBjoern A. Zeeb 	ar->num_started_vdevs = 0;
6362dd4f32aeSBjoern A. Zeeb 	ar->num_created_vdevs = 0;
6363dd4f32aeSBjoern A. Zeeb 	ar->num_peers = 0;
6364dd4f32aeSBjoern A. Zeeb 	ar->allocated_vdev_map = 0;
6365dd4f32aeSBjoern A. Zeeb 
6366dd4f32aeSBjoern A. Zeeb 	/* Configure monitor status ring with default rx_filter to get rx status
6367dd4f32aeSBjoern A. Zeeb 	 * such as rssi, rx_duration.
6368dd4f32aeSBjoern A. Zeeb 	 */
6369dd4f32aeSBjoern A. Zeeb 	ret = ath11k_mac_config_mon_status_default(ar, true);
6370dd4f32aeSBjoern A. Zeeb 	if (ret) {
6371dd4f32aeSBjoern A. Zeeb 		ath11k_err(ab, "failed to configure monitor status ring with default rx_filter: (%d)\n",
6372dd4f32aeSBjoern A. Zeeb 			   ret);
6373dd4f32aeSBjoern A. Zeeb 		goto err;
6374dd4f32aeSBjoern A. Zeeb 	}
6375dd4f32aeSBjoern A. Zeeb 
6376dd4f32aeSBjoern A. Zeeb 	/* Configure the hash seed for hash based reo dest ring selection */
6377dd4f32aeSBjoern A. Zeeb 	ath11k_wmi_pdev_lro_cfg(ar, ar->pdev->pdev_id);
6378dd4f32aeSBjoern A. Zeeb 
6379dd4f32aeSBjoern A. Zeeb 	/* allow device to enter IMPS */
6380dd4f32aeSBjoern A. Zeeb 	if (ab->hw_params.idle_ps) {
6381dd4f32aeSBjoern A. Zeeb 		ret = ath11k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_IDLE_PS_CONFIG,
6382dd4f32aeSBjoern A. Zeeb 						1, pdev->pdev_id);
6383dd4f32aeSBjoern A. Zeeb 		if (ret) {
6384dd4f32aeSBjoern A. Zeeb 			ath11k_err(ab, "failed to enable idle ps: %d\n", ret);
6385dd4f32aeSBjoern A. Zeeb 			goto err;
6386dd4f32aeSBjoern A. Zeeb 		}
6387dd4f32aeSBjoern A. Zeeb 	}
6388dd4f32aeSBjoern A. Zeeb 
6389dd4f32aeSBjoern A. Zeeb 	mutex_unlock(&ar->conf_mutex);
6390dd4f32aeSBjoern A. Zeeb 
6391dd4f32aeSBjoern A. Zeeb 	rcu_assign_pointer(ab->pdevs_active[ar->pdev_idx],
6392dd4f32aeSBjoern A. Zeeb 			   &ab->pdevs[ar->pdev_idx]);
6393dd4f32aeSBjoern A. Zeeb 
6394dd4f32aeSBjoern A. Zeeb 	return 0;
6395dd4f32aeSBjoern A. Zeeb 
6396dd4f32aeSBjoern A. Zeeb err:
6397dd4f32aeSBjoern A. Zeeb 	ar->state = ATH11K_STATE_OFF;
6398dd4f32aeSBjoern A. Zeeb 	mutex_unlock(&ar->conf_mutex);
6399dd4f32aeSBjoern A. Zeeb 
6400dd4f32aeSBjoern A. Zeeb 	return ret;
6401dd4f32aeSBjoern A. Zeeb }
6402dd4f32aeSBjoern A. Zeeb 
ath11k_mac_op_stop(struct ieee80211_hw * hw)6403dd4f32aeSBjoern A. Zeeb static void ath11k_mac_op_stop(struct ieee80211_hw *hw)
6404dd4f32aeSBjoern A. Zeeb {
6405dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = hw->priv;
6406dd4f32aeSBjoern A. Zeeb 	struct htt_ppdu_stats_info *ppdu_stats, *tmp;
6407dd4f32aeSBjoern A. Zeeb 	int ret;
6408dd4f32aeSBjoern A. Zeeb 
6409dd4f32aeSBjoern A. Zeeb 	ath11k_mac_drain_tx(ar);
6410dd4f32aeSBjoern A. Zeeb 
6411dd4f32aeSBjoern A. Zeeb 	mutex_lock(&ar->conf_mutex);
6412dd4f32aeSBjoern A. Zeeb 	ret = ath11k_mac_config_mon_status_default(ar, false);
6413dd4f32aeSBjoern A. Zeeb 	if (ret)
6414dd4f32aeSBjoern A. Zeeb 		ath11k_err(ar->ab, "failed to clear rx_filter for monitor status ring: (%d)\n",
6415dd4f32aeSBjoern A. Zeeb 			   ret);
6416dd4f32aeSBjoern A. Zeeb 
6417dd4f32aeSBjoern A. Zeeb 	clear_bit(ATH11K_CAC_RUNNING, &ar->dev_flags);
6418dd4f32aeSBjoern A. Zeeb 	ar->state = ATH11K_STATE_OFF;
6419dd4f32aeSBjoern A. Zeeb 	mutex_unlock(&ar->conf_mutex);
6420dd4f32aeSBjoern A. Zeeb 
6421dd4f32aeSBjoern A. Zeeb 	cancel_delayed_work_sync(&ar->scan.timeout);
6422dd4f32aeSBjoern A. Zeeb 	cancel_work_sync(&ar->regd_update_work);
6423dd4f32aeSBjoern A. Zeeb 	cancel_work_sync(&ar->ab->update_11d_work);
6424*28348caeSBjoern A. Zeeb 
6425*28348caeSBjoern A. Zeeb 	if (ar->state_11d == ATH11K_11D_PREPARING) {
6426*28348caeSBjoern A. Zeeb 		ar->state_11d = ATH11K_11D_IDLE;
6427*28348caeSBjoern A. Zeeb 		complete(&ar->completed_11d_scan);
6428*28348caeSBjoern A. Zeeb 	}
6429dd4f32aeSBjoern A. Zeeb 
6430dd4f32aeSBjoern A. Zeeb 	spin_lock_bh(&ar->data_lock);
6431dd4f32aeSBjoern A. Zeeb 	list_for_each_entry_safe(ppdu_stats, tmp, &ar->ppdu_stats_info, list) {
6432dd4f32aeSBjoern A. Zeeb 		list_del(&ppdu_stats->list);
6433dd4f32aeSBjoern A. Zeeb 		kfree(ppdu_stats);
6434dd4f32aeSBjoern A. Zeeb 	}
6435dd4f32aeSBjoern A. Zeeb 	spin_unlock_bh(&ar->data_lock);
6436dd4f32aeSBjoern A. Zeeb 
6437dd4f32aeSBjoern A. Zeeb 	rcu_assign_pointer(ar->ab->pdevs_active[ar->pdev_idx], NULL);
6438dd4f32aeSBjoern A. Zeeb 
6439dd4f32aeSBjoern A. Zeeb 	synchronize_rcu();
6440dd4f32aeSBjoern A. Zeeb 
6441dd4f32aeSBjoern A. Zeeb 	atomic_set(&ar->num_pending_mgmt_tx, 0);
6442dd4f32aeSBjoern A. Zeeb }
6443dd4f32aeSBjoern A. Zeeb 
ath11k_mac_setup_vdev_params_mbssid(struct ath11k_vif * arvif,u32 * flags,u32 * tx_vdev_id)6444*28348caeSBjoern A. Zeeb static int ath11k_mac_setup_vdev_params_mbssid(struct ath11k_vif *arvif,
6445*28348caeSBjoern A. Zeeb 					       u32 *flags, u32 *tx_vdev_id)
6446*28348caeSBjoern A. Zeeb {
6447*28348caeSBjoern A. Zeeb 	struct ath11k *ar = arvif->ar;
6448*28348caeSBjoern A. Zeeb 	struct ath11k_vif *tx_arvif;
6449*28348caeSBjoern A. Zeeb 	struct ieee80211_vif *tx_vif;
6450*28348caeSBjoern A. Zeeb 
6451*28348caeSBjoern A. Zeeb 	*tx_vdev_id = 0;
6452*28348caeSBjoern A. Zeeb 	tx_vif = arvif->vif->mbssid_tx_vif;
6453*28348caeSBjoern A. Zeeb 	if (!tx_vif) {
6454*28348caeSBjoern A. Zeeb 		*flags = WMI_HOST_VDEV_FLAGS_NON_MBSSID_AP;
6455*28348caeSBjoern A. Zeeb 		return 0;
6456*28348caeSBjoern A. Zeeb 	}
6457*28348caeSBjoern A. Zeeb 
6458*28348caeSBjoern A. Zeeb 	tx_arvif = (void *)tx_vif->drv_priv;
6459*28348caeSBjoern A. Zeeb 
6460*28348caeSBjoern A. Zeeb 	if (arvif->vif->bss_conf.nontransmitted) {
6461*28348caeSBjoern A. Zeeb 		if (ar->hw->wiphy != ieee80211_vif_to_wdev(tx_vif)->wiphy)
6462*28348caeSBjoern A. Zeeb 			return -EINVAL;
6463*28348caeSBjoern A. Zeeb 
6464*28348caeSBjoern A. Zeeb 		*flags = WMI_HOST_VDEV_FLAGS_NON_TRANSMIT_AP;
6465*28348caeSBjoern A. Zeeb 		*tx_vdev_id = ath11k_vif_to_arvif(tx_vif)->vdev_id;
6466*28348caeSBjoern A. Zeeb 	} else if (tx_arvif == arvif) {
6467*28348caeSBjoern A. Zeeb 		*flags = WMI_HOST_VDEV_FLAGS_TRANSMIT_AP;
6468*28348caeSBjoern A. Zeeb 	} else {
6469*28348caeSBjoern A. Zeeb 		return -EINVAL;
6470*28348caeSBjoern A. Zeeb 	}
6471*28348caeSBjoern A. Zeeb 
6472*28348caeSBjoern A. Zeeb 	if (arvif->vif->bss_conf.ema_ap)
6473*28348caeSBjoern A. Zeeb 		*flags |= WMI_HOST_VDEV_FLAGS_EMA_MODE;
6474*28348caeSBjoern A. Zeeb 
6475*28348caeSBjoern A. Zeeb 	return 0;
6476*28348caeSBjoern A. Zeeb }
6477*28348caeSBjoern A. Zeeb 
ath11k_mac_setup_vdev_create_params(struct ath11k_vif * arvif,struct vdev_create_params * params)6478*28348caeSBjoern A. Zeeb static int ath11k_mac_setup_vdev_create_params(struct ath11k_vif *arvif,
6479dd4f32aeSBjoern A. Zeeb 					       struct vdev_create_params *params)
6480dd4f32aeSBjoern A. Zeeb {
6481dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = arvif->ar;
6482dd4f32aeSBjoern A. Zeeb 	struct ath11k_pdev *pdev = ar->pdev;
6483*28348caeSBjoern A. Zeeb 	int ret;
6484dd4f32aeSBjoern A. Zeeb 
6485dd4f32aeSBjoern A. Zeeb 	params->if_id = arvif->vdev_id;
6486dd4f32aeSBjoern A. Zeeb 	params->type = arvif->vdev_type;
6487dd4f32aeSBjoern A. Zeeb 	params->subtype = arvif->vdev_subtype;
6488dd4f32aeSBjoern A. Zeeb 	params->pdev_id = pdev->pdev_id;
6489*28348caeSBjoern A. Zeeb 	params->mbssid_flags = 0;
6490*28348caeSBjoern A. Zeeb 	params->mbssid_tx_vdev_id = 0;
6491*28348caeSBjoern A. Zeeb 
6492*28348caeSBjoern A. Zeeb 	if (!test_bit(WMI_TLV_SERVICE_MBSS_PARAM_IN_VDEV_START_SUPPORT,
6493*28348caeSBjoern A. Zeeb 		      ar->ab->wmi_ab.svc_map)) {
6494*28348caeSBjoern A. Zeeb 		ret = ath11k_mac_setup_vdev_params_mbssid(arvif,
6495*28348caeSBjoern A. Zeeb 							  &params->mbssid_flags,
6496*28348caeSBjoern A. Zeeb 							  &params->mbssid_tx_vdev_id);
6497*28348caeSBjoern A. Zeeb 		if (ret)
6498*28348caeSBjoern A. Zeeb 			return ret;
6499*28348caeSBjoern A. Zeeb 	}
6500dd4f32aeSBjoern A. Zeeb 
6501dd4f32aeSBjoern A. Zeeb 	if (pdev->cap.supported_bands & WMI_HOST_WLAN_2G_CAP) {
6502dd4f32aeSBjoern A. Zeeb 		params->chains[NL80211_BAND_2GHZ].tx = ar->num_tx_chains;
6503dd4f32aeSBjoern A. Zeeb 		params->chains[NL80211_BAND_2GHZ].rx = ar->num_rx_chains;
6504dd4f32aeSBjoern A. Zeeb 	}
6505dd4f32aeSBjoern A. Zeeb 	if (pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP) {
6506dd4f32aeSBjoern A. Zeeb 		params->chains[NL80211_BAND_5GHZ].tx = ar->num_tx_chains;
6507dd4f32aeSBjoern A. Zeeb 		params->chains[NL80211_BAND_5GHZ].rx = ar->num_rx_chains;
6508dd4f32aeSBjoern A. Zeeb 	}
6509dd4f32aeSBjoern A. Zeeb 	if (pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP &&
6510dd4f32aeSBjoern A. Zeeb 	    ar->supports_6ghz) {
6511dd4f32aeSBjoern A. Zeeb 		params->chains[NL80211_BAND_6GHZ].tx = ar->num_tx_chains;
6512dd4f32aeSBjoern A. Zeeb 		params->chains[NL80211_BAND_6GHZ].rx = ar->num_rx_chains;
6513dd4f32aeSBjoern A. Zeeb 	}
6514*28348caeSBjoern A. Zeeb 	return 0;
6515dd4f32aeSBjoern A. Zeeb }
6516dd4f32aeSBjoern A. Zeeb 
ath11k_mac_op_update_vif_offload(struct ieee80211_hw * hw,struct ieee80211_vif * vif)6517dd4f32aeSBjoern A. Zeeb static void ath11k_mac_op_update_vif_offload(struct ieee80211_hw *hw,
6518dd4f32aeSBjoern A. Zeeb 					     struct ieee80211_vif *vif)
6519dd4f32aeSBjoern A. Zeeb {
6520dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = hw->priv;
6521dd4f32aeSBjoern A. Zeeb 	struct ath11k_base *ab = ar->ab;
6522dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
6523dd4f32aeSBjoern A. Zeeb 	u32 param_id, param_value;
6524dd4f32aeSBjoern A. Zeeb 	int ret;
6525dd4f32aeSBjoern A. Zeeb 
6526dd4f32aeSBjoern A. Zeeb 	param_id = WMI_VDEV_PARAM_TX_ENCAP_TYPE;
6527dd4f32aeSBjoern A. Zeeb 	if (ath11k_frame_mode != ATH11K_HW_TXRX_ETHERNET ||
6528dd4f32aeSBjoern A. Zeeb 	    (vif->type != NL80211_IFTYPE_STATION &&
6529dd4f32aeSBjoern A. Zeeb 	     vif->type != NL80211_IFTYPE_AP))
6530dd4f32aeSBjoern A. Zeeb 		vif->offload_flags &= ~(IEEE80211_OFFLOAD_ENCAP_ENABLED |
6531dd4f32aeSBjoern A. Zeeb 					IEEE80211_OFFLOAD_DECAP_ENABLED);
6532dd4f32aeSBjoern A. Zeeb 
6533dd4f32aeSBjoern A. Zeeb 	if (vif->offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED)
6534dd4f32aeSBjoern A. Zeeb 		param_value = ATH11K_HW_TXRX_ETHERNET;
6535dd4f32aeSBjoern A. Zeeb 	else if (test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags))
6536dd4f32aeSBjoern A. Zeeb 		param_value = ATH11K_HW_TXRX_RAW;
6537dd4f32aeSBjoern A. Zeeb 	else
6538dd4f32aeSBjoern A. Zeeb 		param_value = ATH11K_HW_TXRX_NATIVE_WIFI;
6539dd4f32aeSBjoern A. Zeeb 
6540dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
6541dd4f32aeSBjoern A. Zeeb 					    param_id, param_value);
6542dd4f32aeSBjoern A. Zeeb 	if (ret) {
6543dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ab, "failed to set vdev %d tx encap mode: %d\n",
6544dd4f32aeSBjoern A. Zeeb 			    arvif->vdev_id, ret);
6545dd4f32aeSBjoern A. Zeeb 		vif->offload_flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED;
6546dd4f32aeSBjoern A. Zeeb 	}
6547dd4f32aeSBjoern A. Zeeb 
6548dd4f32aeSBjoern A. Zeeb 	param_id = WMI_VDEV_PARAM_RX_DECAP_TYPE;
6549dd4f32aeSBjoern A. Zeeb 	if (vif->offload_flags & IEEE80211_OFFLOAD_DECAP_ENABLED)
6550dd4f32aeSBjoern A. Zeeb 		param_value = ATH11K_HW_TXRX_ETHERNET;
6551dd4f32aeSBjoern A. Zeeb 	else if (test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags))
6552dd4f32aeSBjoern A. Zeeb 		param_value = ATH11K_HW_TXRX_RAW;
6553dd4f32aeSBjoern A. Zeeb 	else
6554dd4f32aeSBjoern A. Zeeb 		param_value = ATH11K_HW_TXRX_NATIVE_WIFI;
6555dd4f32aeSBjoern A. Zeeb 
6556dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
6557dd4f32aeSBjoern A. Zeeb 					    param_id, param_value);
6558dd4f32aeSBjoern A. Zeeb 	if (ret) {
6559dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ab, "failed to set vdev %d rx decap mode: %d\n",
6560dd4f32aeSBjoern A. Zeeb 			    arvif->vdev_id, ret);
6561dd4f32aeSBjoern A. Zeeb 		vif->offload_flags &= ~IEEE80211_OFFLOAD_DECAP_ENABLED;
6562dd4f32aeSBjoern A. Zeeb 	}
6563dd4f32aeSBjoern A. Zeeb }
6564dd4f32aeSBjoern A. Zeeb 
ath11k_mac_vif_ap_active_any(struct ath11k_base * ab)6565dd4f32aeSBjoern A. Zeeb static bool ath11k_mac_vif_ap_active_any(struct ath11k_base *ab)
6566dd4f32aeSBjoern A. Zeeb {
6567dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar;
6568dd4f32aeSBjoern A. Zeeb 	struct ath11k_pdev *pdev;
6569dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif;
6570dd4f32aeSBjoern A. Zeeb 	int i;
6571dd4f32aeSBjoern A. Zeeb 
6572dd4f32aeSBjoern A. Zeeb 	for (i = 0; i < ab->num_radios; i++) {
6573dd4f32aeSBjoern A. Zeeb 		pdev = &ab->pdevs[i];
6574dd4f32aeSBjoern A. Zeeb 		ar = pdev->ar;
6575dd4f32aeSBjoern A. Zeeb 		list_for_each_entry(arvif, &ar->arvifs, list) {
6576dd4f32aeSBjoern A. Zeeb 			if (arvif->is_up && arvif->vdev_type == WMI_VDEV_TYPE_AP)
6577dd4f32aeSBjoern A. Zeeb 				return true;
6578dd4f32aeSBjoern A. Zeeb 		}
6579dd4f32aeSBjoern A. Zeeb 	}
6580dd4f32aeSBjoern A. Zeeb 	return false;
6581dd4f32aeSBjoern A. Zeeb }
6582dd4f32aeSBjoern A. Zeeb 
ath11k_mac_11d_scan_start(struct ath11k * ar,u32 vdev_id)6583*28348caeSBjoern A. Zeeb void ath11k_mac_11d_scan_start(struct ath11k *ar, u32 vdev_id)
6584dd4f32aeSBjoern A. Zeeb {
6585dd4f32aeSBjoern A. Zeeb 	struct wmi_11d_scan_start_params param;
6586dd4f32aeSBjoern A. Zeeb 	int ret;
6587dd4f32aeSBjoern A. Zeeb 
6588dd4f32aeSBjoern A. Zeeb 	mutex_lock(&ar->ab->vdev_id_11d_lock);
6589dd4f32aeSBjoern A. Zeeb 
6590*28348caeSBjoern A. Zeeb 	ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev id for 11d scan %d\n",
6591dd4f32aeSBjoern A. Zeeb 		   ar->vdev_id_11d_scan);
6592dd4f32aeSBjoern A. Zeeb 
6593dd4f32aeSBjoern A. Zeeb 	if (ar->regdom_set_by_user)
6594dd4f32aeSBjoern A. Zeeb 		goto fin;
6595dd4f32aeSBjoern A. Zeeb 
6596dd4f32aeSBjoern A. Zeeb 	if (ar->vdev_id_11d_scan != ATH11K_11D_INVALID_VDEV_ID)
6597dd4f32aeSBjoern A. Zeeb 		goto fin;
6598dd4f32aeSBjoern A. Zeeb 
6599dd4f32aeSBjoern A. Zeeb 	if (!test_bit(WMI_TLV_SERVICE_11D_OFFLOAD, ar->ab->wmi_ab.svc_map))
6600dd4f32aeSBjoern A. Zeeb 		goto fin;
6601dd4f32aeSBjoern A. Zeeb 
6602dd4f32aeSBjoern A. Zeeb 	if (ath11k_mac_vif_ap_active_any(ar->ab))
6603dd4f32aeSBjoern A. Zeeb 		goto fin;
6604dd4f32aeSBjoern A. Zeeb 
6605dd4f32aeSBjoern A. Zeeb 	param.vdev_id = vdev_id;
6606dd4f32aeSBjoern A. Zeeb 	param.start_interval_msec = 0;
6607dd4f32aeSBjoern A. Zeeb 	param.scan_period_msec = ATH11K_SCAN_11D_INTERVAL;
6608dd4f32aeSBjoern A. Zeeb 
6609*28348caeSBjoern A. Zeeb 	ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "start 11d scan\n");
6610dd4f32aeSBjoern A. Zeeb 
6611dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_send_11d_scan_start_cmd(ar, &param);
6612dd4f32aeSBjoern A. Zeeb 	if (ret) {
6613dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to start 11d scan vdev %d ret: %d\n",
6614dd4f32aeSBjoern A. Zeeb 			    vdev_id, ret);
6615dd4f32aeSBjoern A. Zeeb 	} else {
6616dd4f32aeSBjoern A. Zeeb 		ar->vdev_id_11d_scan = vdev_id;
6617*28348caeSBjoern A. Zeeb 		if (ar->state_11d == ATH11K_11D_PREPARING)
6618*28348caeSBjoern A. Zeeb 			ar->state_11d = ATH11K_11D_RUNNING;
6619dd4f32aeSBjoern A. Zeeb 	}
6620dd4f32aeSBjoern A. Zeeb 
6621dd4f32aeSBjoern A. Zeeb fin:
6622*28348caeSBjoern A. Zeeb 	if (ar->state_11d == ATH11K_11D_PREPARING) {
6623*28348caeSBjoern A. Zeeb 		ar->state_11d = ATH11K_11D_IDLE;
6624*28348caeSBjoern A. Zeeb 		complete(&ar->completed_11d_scan);
6625*28348caeSBjoern A. Zeeb 	}
6626*28348caeSBjoern A. Zeeb 
6627dd4f32aeSBjoern A. Zeeb 	mutex_unlock(&ar->ab->vdev_id_11d_lock);
6628dd4f32aeSBjoern A. Zeeb }
6629dd4f32aeSBjoern A. Zeeb 
ath11k_mac_11d_scan_stop(struct ath11k * ar)6630dd4f32aeSBjoern A. Zeeb void ath11k_mac_11d_scan_stop(struct ath11k *ar)
6631dd4f32aeSBjoern A. Zeeb {
6632dd4f32aeSBjoern A. Zeeb 	int ret;
6633dd4f32aeSBjoern A. Zeeb 	u32 vdev_id;
6634dd4f32aeSBjoern A. Zeeb 
6635dd4f32aeSBjoern A. Zeeb 	if (!test_bit(WMI_TLV_SERVICE_11D_OFFLOAD, ar->ab->wmi_ab.svc_map))
6636dd4f32aeSBjoern A. Zeeb 		return;
6637dd4f32aeSBjoern A. Zeeb 
6638*28348caeSBjoern A. Zeeb 	ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "stop 11d scan\n");
6639dd4f32aeSBjoern A. Zeeb 
6640dd4f32aeSBjoern A. Zeeb 	mutex_lock(&ar->ab->vdev_id_11d_lock);
6641dd4f32aeSBjoern A. Zeeb 
6642*28348caeSBjoern A. Zeeb 	ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "stop 11d vdev id %d\n",
6643dd4f32aeSBjoern A. Zeeb 		   ar->vdev_id_11d_scan);
6644dd4f32aeSBjoern A. Zeeb 
6645*28348caeSBjoern A. Zeeb 	if (ar->state_11d == ATH11K_11D_PREPARING) {
6646*28348caeSBjoern A. Zeeb 		ar->state_11d = ATH11K_11D_IDLE;
6647*28348caeSBjoern A. Zeeb 		complete(&ar->completed_11d_scan);
6648*28348caeSBjoern A. Zeeb 	}
6649*28348caeSBjoern A. Zeeb 
6650dd4f32aeSBjoern A. Zeeb 	if (ar->vdev_id_11d_scan != ATH11K_11D_INVALID_VDEV_ID) {
6651dd4f32aeSBjoern A. Zeeb 		vdev_id = ar->vdev_id_11d_scan;
6652dd4f32aeSBjoern A. Zeeb 
6653dd4f32aeSBjoern A. Zeeb 		ret = ath11k_wmi_send_11d_scan_stop_cmd(ar, vdev_id);
6654*28348caeSBjoern A. Zeeb 		if (ret) {
6655dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab,
6656dd4f32aeSBjoern A. Zeeb 				    "failed to stopt 11d scan vdev %d ret: %d\n",
6657dd4f32aeSBjoern A. Zeeb 				    vdev_id, ret);
6658*28348caeSBjoern A. Zeeb 		} else {
6659dd4f32aeSBjoern A. Zeeb 			ar->vdev_id_11d_scan = ATH11K_11D_INVALID_VDEV_ID;
6660*28348caeSBjoern A. Zeeb 			ar->state_11d = ATH11K_11D_IDLE;
6661*28348caeSBjoern A. Zeeb 			complete(&ar->completed_11d_scan);
6662*28348caeSBjoern A. Zeeb 		}
6663dd4f32aeSBjoern A. Zeeb 	}
6664dd4f32aeSBjoern A. Zeeb 	mutex_unlock(&ar->ab->vdev_id_11d_lock);
6665dd4f32aeSBjoern A. Zeeb }
6666dd4f32aeSBjoern A. Zeeb 
ath11k_mac_11d_scan_stop_all(struct ath11k_base * ab)6667dd4f32aeSBjoern A. Zeeb void ath11k_mac_11d_scan_stop_all(struct ath11k_base *ab)
6668dd4f32aeSBjoern A. Zeeb {
6669dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar;
6670dd4f32aeSBjoern A. Zeeb 	struct ath11k_pdev *pdev;
6671dd4f32aeSBjoern A. Zeeb 	int i;
6672dd4f32aeSBjoern A. Zeeb 
6673*28348caeSBjoern A. Zeeb 	ath11k_dbg(ab, ATH11K_DBG_MAC, "stop soc 11d scan\n");
6674dd4f32aeSBjoern A. Zeeb 
6675dd4f32aeSBjoern A. Zeeb 	for (i = 0; i < ab->num_radios; i++) {
6676dd4f32aeSBjoern A. Zeeb 		pdev = &ab->pdevs[i];
6677dd4f32aeSBjoern A. Zeeb 		ar = pdev->ar;
6678dd4f32aeSBjoern A. Zeeb 
6679dd4f32aeSBjoern A. Zeeb 		ath11k_mac_11d_scan_stop(ar);
6680dd4f32aeSBjoern A. Zeeb 	}
6681dd4f32aeSBjoern A. Zeeb }
6682dd4f32aeSBjoern A. Zeeb 
ath11k_mac_vdev_delete(struct ath11k * ar,struct ath11k_vif * arvif)6683*28348caeSBjoern A. Zeeb static int ath11k_mac_vdev_delete(struct ath11k *ar, struct ath11k_vif *arvif)
6684*28348caeSBjoern A. Zeeb {
6685*28348caeSBjoern A. Zeeb 	unsigned long time_left;
6686*28348caeSBjoern A. Zeeb 	struct ieee80211_vif *vif = arvif->vif;
6687*28348caeSBjoern A. Zeeb 	int ret = 0;
6688*28348caeSBjoern A. Zeeb 
6689*28348caeSBjoern A. Zeeb 	lockdep_assert_held(&ar->conf_mutex);
6690*28348caeSBjoern A. Zeeb 
6691*28348caeSBjoern A. Zeeb 	reinit_completion(&ar->vdev_delete_done);
6692*28348caeSBjoern A. Zeeb 
6693*28348caeSBjoern A. Zeeb 	ret = ath11k_wmi_vdev_delete(ar, arvif->vdev_id);
6694*28348caeSBjoern A. Zeeb 	if (ret) {
6695*28348caeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to delete WMI vdev %d: %d\n",
6696*28348caeSBjoern A. Zeeb 			    arvif->vdev_id, ret);
6697*28348caeSBjoern A. Zeeb 		return ret;
6698*28348caeSBjoern A. Zeeb 	}
6699*28348caeSBjoern A. Zeeb 
6700*28348caeSBjoern A. Zeeb 	time_left = wait_for_completion_timeout(&ar->vdev_delete_done,
6701*28348caeSBjoern A. Zeeb 						ATH11K_VDEV_DELETE_TIMEOUT_HZ);
6702*28348caeSBjoern A. Zeeb 	if (time_left == 0) {
6703*28348caeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "Timeout in receiving vdev delete response\n");
6704*28348caeSBjoern A. Zeeb 		return -ETIMEDOUT;
6705*28348caeSBjoern A. Zeeb 	}
6706*28348caeSBjoern A. Zeeb 
6707*28348caeSBjoern A. Zeeb 	ar->ab->free_vdev_map |= 1LL << (arvif->vdev_id);
6708*28348caeSBjoern A. Zeeb 	ar->allocated_vdev_map &= ~(1LL << arvif->vdev_id);
6709*28348caeSBjoern A. Zeeb 	ar->num_created_vdevs--;
6710*28348caeSBjoern A. Zeeb 
6711*28348caeSBjoern A. Zeeb 	ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev %pM deleted, vdev_id %d\n",
6712*28348caeSBjoern A. Zeeb 		   vif->addr, arvif->vdev_id);
6713*28348caeSBjoern A. Zeeb 
6714*28348caeSBjoern A. Zeeb 	return ret;
6715*28348caeSBjoern A. Zeeb }
6716*28348caeSBjoern A. Zeeb 
ath11k_mac_op_add_interface(struct ieee80211_hw * hw,struct ieee80211_vif * vif)6717dd4f32aeSBjoern A. Zeeb static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,
6718dd4f32aeSBjoern A. Zeeb 				       struct ieee80211_vif *vif)
6719dd4f32aeSBjoern A. Zeeb {
6720dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = hw->priv;
6721dd4f32aeSBjoern A. Zeeb 	struct ath11k_base *ab = ar->ab;
6722dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
6723dd4f32aeSBjoern A. Zeeb 	struct vdev_create_params vdev_param = {0};
6724dd4f32aeSBjoern A. Zeeb 	struct peer_create_params peer_param;
6725dd4f32aeSBjoern A. Zeeb 	u32 param_id, param_value;
6726dd4f32aeSBjoern A. Zeeb 	u16 nss;
6727dd4f32aeSBjoern A. Zeeb 	int i;
6728dd4f32aeSBjoern A. Zeeb 	int ret, fbret;
6729dd4f32aeSBjoern A. Zeeb 	int bit;
6730dd4f32aeSBjoern A. Zeeb 
6731dd4f32aeSBjoern A. Zeeb 	vif->driver_flags |= IEEE80211_VIF_SUPPORTS_UAPSD;
6732dd4f32aeSBjoern A. Zeeb 
6733dd4f32aeSBjoern A. Zeeb 	mutex_lock(&ar->conf_mutex);
6734dd4f32aeSBjoern A. Zeeb 
6735dd4f32aeSBjoern A. Zeeb 	if (vif->type == NL80211_IFTYPE_AP &&
6736dd4f32aeSBjoern A. Zeeb 	    ar->num_peers > (ar->max_num_peers - 1)) {
6737dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ab, "failed to create vdev due to insufficient peer entry resource in firmware\n");
6738dd4f32aeSBjoern A. Zeeb 		ret = -ENOBUFS;
6739dd4f32aeSBjoern A. Zeeb 		goto err;
6740dd4f32aeSBjoern A. Zeeb 	}
6741dd4f32aeSBjoern A. Zeeb 
6742dd4f32aeSBjoern A. Zeeb 	if (ar->num_created_vdevs > (TARGET_NUM_VDEVS(ab) - 1)) {
6743dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ab, "failed to create vdev %u, reached max vdev limit %d\n",
6744dd4f32aeSBjoern A. Zeeb 			    ar->num_created_vdevs, TARGET_NUM_VDEVS(ab));
6745dd4f32aeSBjoern A. Zeeb 		ret = -EBUSY;
6746dd4f32aeSBjoern A. Zeeb 		goto err;
6747dd4f32aeSBjoern A. Zeeb 	}
6748dd4f32aeSBjoern A. Zeeb 
6749*28348caeSBjoern A. Zeeb 	/* In the case of hardware recovery, debugfs files are
6750*28348caeSBjoern A. Zeeb 	 * not deleted since ieee80211_ops.remove_interface() is
6751*28348caeSBjoern A. Zeeb 	 * not invoked. In such cases, try to delete the files.
6752*28348caeSBjoern A. Zeeb 	 * These will be re-created later.
6753*28348caeSBjoern A. Zeeb 	 */
6754*28348caeSBjoern A. Zeeb 	ath11k_debugfs_remove_interface(arvif);
6755*28348caeSBjoern A. Zeeb 
6756dd4f32aeSBjoern A. Zeeb 	memset(arvif, 0, sizeof(*arvif));
6757dd4f32aeSBjoern A. Zeeb 
6758dd4f32aeSBjoern A. Zeeb 	arvif->ar = ar;
6759dd4f32aeSBjoern A. Zeeb 	arvif->vif = vif;
6760dd4f32aeSBjoern A. Zeeb 
6761dd4f32aeSBjoern A. Zeeb 	INIT_LIST_HEAD(&arvif->list);
6762dd4f32aeSBjoern A. Zeeb 	INIT_DELAYED_WORK(&arvif->connection_loss_work,
6763dd4f32aeSBjoern A. Zeeb 			  ath11k_mac_vif_sta_connection_loss_work);
6764dd4f32aeSBjoern A. Zeeb 
6765dd4f32aeSBjoern A. Zeeb 	for (i = 0; i < ARRAY_SIZE(arvif->bitrate_mask.control); i++) {
6766dd4f32aeSBjoern A. Zeeb 		arvif->bitrate_mask.control[i].legacy = 0xffffffff;
6767dd4f32aeSBjoern A. Zeeb 		arvif->bitrate_mask.control[i].gi = NL80211_TXRATE_FORCE_SGI;
6768dd4f32aeSBjoern A. Zeeb 		memset(arvif->bitrate_mask.control[i].ht_mcs, 0xff,
6769dd4f32aeSBjoern A. Zeeb 		       sizeof(arvif->bitrate_mask.control[i].ht_mcs));
6770dd4f32aeSBjoern A. Zeeb 		memset(arvif->bitrate_mask.control[i].vht_mcs, 0xff,
6771dd4f32aeSBjoern A. Zeeb 		       sizeof(arvif->bitrate_mask.control[i].vht_mcs));
6772dd4f32aeSBjoern A. Zeeb 		memset(arvif->bitrate_mask.control[i].he_mcs, 0xff,
6773dd4f32aeSBjoern A. Zeeb 		       sizeof(arvif->bitrate_mask.control[i].he_mcs));
6774dd4f32aeSBjoern A. Zeeb 	}
6775dd4f32aeSBjoern A. Zeeb 
6776dd4f32aeSBjoern A. Zeeb 	bit = __ffs64(ab->free_vdev_map);
6777dd4f32aeSBjoern A. Zeeb 
6778dd4f32aeSBjoern A. Zeeb 	arvif->vdev_id = bit;
6779dd4f32aeSBjoern A. Zeeb 	arvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE;
6780dd4f32aeSBjoern A. Zeeb 
6781dd4f32aeSBjoern A. Zeeb 	switch (vif->type) {
6782dd4f32aeSBjoern A. Zeeb 	case NL80211_IFTYPE_UNSPECIFIED:
6783dd4f32aeSBjoern A. Zeeb 	case NL80211_IFTYPE_STATION:
6784dd4f32aeSBjoern A. Zeeb 		arvif->vdev_type = WMI_VDEV_TYPE_STA;
6785dd4f32aeSBjoern A. Zeeb 		break;
6786dd4f32aeSBjoern A. Zeeb 	case NL80211_IFTYPE_MESH_POINT:
6787dd4f32aeSBjoern A. Zeeb 		arvif->vdev_subtype = WMI_VDEV_SUBTYPE_MESH_11S;
6788dd4f32aeSBjoern A. Zeeb 		fallthrough;
6789dd4f32aeSBjoern A. Zeeb 	case NL80211_IFTYPE_AP:
6790dd4f32aeSBjoern A. Zeeb 		arvif->vdev_type = WMI_VDEV_TYPE_AP;
6791dd4f32aeSBjoern A. Zeeb 		break;
6792dd4f32aeSBjoern A. Zeeb 	case NL80211_IFTYPE_MONITOR:
6793dd4f32aeSBjoern A. Zeeb 		arvif->vdev_type = WMI_VDEV_TYPE_MONITOR;
6794dd4f32aeSBjoern A. Zeeb 		ar->monitor_vdev_id = bit;
6795dd4f32aeSBjoern A. Zeeb 		break;
6796dd4f32aeSBjoern A. Zeeb 	default:
6797dd4f32aeSBjoern A. Zeeb 		WARN_ON(1);
6798dd4f32aeSBjoern A. Zeeb 		break;
6799dd4f32aeSBjoern A. Zeeb 	}
6800dd4f32aeSBjoern A. Zeeb 
6801*28348caeSBjoern A. Zeeb 	ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "add interface id %d type %d subtype %d map %llx\n",
6802dd4f32aeSBjoern A. Zeeb 		   arvif->vdev_id, arvif->vdev_type, arvif->vdev_subtype,
6803dd4f32aeSBjoern A. Zeeb 		   ab->free_vdev_map);
6804dd4f32aeSBjoern A. Zeeb 
6805dd4f32aeSBjoern A. Zeeb 	vif->cab_queue = arvif->vdev_id % (ATH11K_HW_MAX_QUEUES - 1);
6806dd4f32aeSBjoern A. Zeeb 	for (i = 0; i < ARRAY_SIZE(vif->hw_queue); i++)
6807dd4f32aeSBjoern A. Zeeb 		vif->hw_queue[i] = i % (ATH11K_HW_MAX_QUEUES - 1);
6808dd4f32aeSBjoern A. Zeeb 
6809*28348caeSBjoern A. Zeeb 	ret = ath11k_mac_setup_vdev_create_params(arvif, &vdev_param);
6810*28348caeSBjoern A. Zeeb 	if (ret) {
6811*28348caeSBjoern A. Zeeb 		ath11k_warn(ab, "failed to create vdev parameters %d: %d\n",
6812*28348caeSBjoern A. Zeeb 			    arvif->vdev_id, ret);
6813*28348caeSBjoern A. Zeeb 		goto err;
6814*28348caeSBjoern A. Zeeb 	}
6815dd4f32aeSBjoern A. Zeeb 
6816dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_vdev_create(ar, vif->addr, &vdev_param);
6817dd4f32aeSBjoern A. Zeeb 	if (ret) {
6818dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ab, "failed to create WMI vdev %d: %d\n",
6819dd4f32aeSBjoern A. Zeeb 			    arvif->vdev_id, ret);
6820dd4f32aeSBjoern A. Zeeb 		goto err;
6821dd4f32aeSBjoern A. Zeeb 	}
6822dd4f32aeSBjoern A. Zeeb 
6823dd4f32aeSBjoern A. Zeeb 	ar->num_created_vdevs++;
6824dd4f32aeSBjoern A. Zeeb 	ath11k_dbg(ab, ATH11K_DBG_MAC, "vdev %pM created, vdev_id %d\n",
6825dd4f32aeSBjoern A. Zeeb 		   vif->addr, arvif->vdev_id);
6826dd4f32aeSBjoern A. Zeeb 	ar->allocated_vdev_map |= 1LL << arvif->vdev_id;
6827dd4f32aeSBjoern A. Zeeb 	ab->free_vdev_map &= ~(1LL << arvif->vdev_id);
6828dd4f32aeSBjoern A. Zeeb 
6829dd4f32aeSBjoern A. Zeeb 	spin_lock_bh(&ar->data_lock);
6830dd4f32aeSBjoern A. Zeeb 	list_add(&arvif->list, &ar->arvifs);
6831dd4f32aeSBjoern A. Zeeb 	spin_unlock_bh(&ar->data_lock);
6832dd4f32aeSBjoern A. Zeeb 
6833dd4f32aeSBjoern A. Zeeb 	ath11k_mac_op_update_vif_offload(hw, vif);
6834dd4f32aeSBjoern A. Zeeb 
6835dd4f32aeSBjoern A. Zeeb 	nss = get_num_chains(ar->cfg_tx_chainmask) ? : 1;
6836dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
6837dd4f32aeSBjoern A. Zeeb 					    WMI_VDEV_PARAM_NSS, nss);
6838dd4f32aeSBjoern A. Zeeb 	if (ret) {
6839dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ab, "failed to set vdev %d chainmask 0x%x, nss %d :%d\n",
6840dd4f32aeSBjoern A. Zeeb 			    arvif->vdev_id, ar->cfg_tx_chainmask, nss, ret);
6841dd4f32aeSBjoern A. Zeeb 		goto err_vdev_del;
6842dd4f32aeSBjoern A. Zeeb 	}
6843dd4f32aeSBjoern A. Zeeb 
6844dd4f32aeSBjoern A. Zeeb 	switch (arvif->vdev_type) {
6845dd4f32aeSBjoern A. Zeeb 	case WMI_VDEV_TYPE_AP:
6846dd4f32aeSBjoern A. Zeeb 		peer_param.vdev_id = arvif->vdev_id;
6847dd4f32aeSBjoern A. Zeeb 		peer_param.peer_addr = vif->addr;
6848dd4f32aeSBjoern A. Zeeb 		peer_param.peer_type = WMI_PEER_TYPE_DEFAULT;
6849dd4f32aeSBjoern A. Zeeb 		ret = ath11k_peer_create(ar, arvif, NULL, &peer_param);
6850dd4f32aeSBjoern A. Zeeb 		if (ret) {
6851dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ab, "failed to vdev %d create peer for AP: %d\n",
6852dd4f32aeSBjoern A. Zeeb 				    arvif->vdev_id, ret);
6853dd4f32aeSBjoern A. Zeeb 			goto err_vdev_del;
6854dd4f32aeSBjoern A. Zeeb 		}
6855dd4f32aeSBjoern A. Zeeb 
6856dd4f32aeSBjoern A. Zeeb 		ret = ath11k_mac_set_kickout(arvif);
6857dd4f32aeSBjoern A. Zeeb 		if (ret) {
6858dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "failed to set vdev %i kickout parameters: %d\n",
6859dd4f32aeSBjoern A. Zeeb 				    arvif->vdev_id, ret);
6860dd4f32aeSBjoern A. Zeeb 			goto err_peer_del;
6861dd4f32aeSBjoern A. Zeeb 		}
6862dd4f32aeSBjoern A. Zeeb 
6863dd4f32aeSBjoern A. Zeeb 		ath11k_mac_11d_scan_stop_all(ar->ab);
6864dd4f32aeSBjoern A. Zeeb 		break;
6865dd4f32aeSBjoern A. Zeeb 	case WMI_VDEV_TYPE_STA:
6866dd4f32aeSBjoern A. Zeeb 		param_id = WMI_STA_PS_PARAM_RX_WAKE_POLICY;
6867dd4f32aeSBjoern A. Zeeb 		param_value = WMI_STA_PS_RX_WAKE_POLICY_WAKE;
6868dd4f32aeSBjoern A. Zeeb 		ret = ath11k_wmi_set_sta_ps_param(ar, arvif->vdev_id,
6869dd4f32aeSBjoern A. Zeeb 						  param_id, param_value);
6870dd4f32aeSBjoern A. Zeeb 		if (ret) {
6871dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "failed to set vdev %d RX wake policy: %d\n",
6872dd4f32aeSBjoern A. Zeeb 				    arvif->vdev_id, ret);
6873dd4f32aeSBjoern A. Zeeb 			goto err_peer_del;
6874dd4f32aeSBjoern A. Zeeb 		}
6875dd4f32aeSBjoern A. Zeeb 
6876dd4f32aeSBjoern A. Zeeb 		param_id = WMI_STA_PS_PARAM_TX_WAKE_THRESHOLD;
6877dd4f32aeSBjoern A. Zeeb 		param_value = WMI_STA_PS_TX_WAKE_THRESHOLD_ALWAYS;
6878dd4f32aeSBjoern A. Zeeb 		ret = ath11k_wmi_set_sta_ps_param(ar, arvif->vdev_id,
6879dd4f32aeSBjoern A. Zeeb 						  param_id, param_value);
6880dd4f32aeSBjoern A. Zeeb 		if (ret) {
6881dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "failed to set vdev %d TX wake threshold: %d\n",
6882dd4f32aeSBjoern A. Zeeb 				    arvif->vdev_id, ret);
6883dd4f32aeSBjoern A. Zeeb 			goto err_peer_del;
6884dd4f32aeSBjoern A. Zeeb 		}
6885dd4f32aeSBjoern A. Zeeb 
6886dd4f32aeSBjoern A. Zeeb 		param_id = WMI_STA_PS_PARAM_PSPOLL_COUNT;
6887dd4f32aeSBjoern A. Zeeb 		param_value = WMI_STA_PS_PSPOLL_COUNT_NO_MAX;
6888dd4f32aeSBjoern A. Zeeb 		ret = ath11k_wmi_set_sta_ps_param(ar, arvif->vdev_id,
6889dd4f32aeSBjoern A. Zeeb 						  param_id, param_value);
6890dd4f32aeSBjoern A. Zeeb 		if (ret) {
6891dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "failed to set vdev %d pspoll count: %d\n",
6892dd4f32aeSBjoern A. Zeeb 				    arvif->vdev_id, ret);
6893dd4f32aeSBjoern A. Zeeb 			goto err_peer_del;
6894dd4f32aeSBjoern A. Zeeb 		}
6895dd4f32aeSBjoern A. Zeeb 
6896dd4f32aeSBjoern A. Zeeb 		ret = ath11k_wmi_pdev_set_ps_mode(ar, arvif->vdev_id,
6897dd4f32aeSBjoern A. Zeeb 						  WMI_STA_PS_MODE_DISABLED);
6898dd4f32aeSBjoern A. Zeeb 		if (ret) {
6899dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "failed to disable vdev %d ps mode: %d\n",
6900dd4f32aeSBjoern A. Zeeb 				    arvif->vdev_id, ret);
6901dd4f32aeSBjoern A. Zeeb 			goto err_peer_del;
6902dd4f32aeSBjoern A. Zeeb 		}
6903dd4f32aeSBjoern A. Zeeb 
6904*28348caeSBjoern A. Zeeb 		if (test_bit(WMI_TLV_SERVICE_11D_OFFLOAD, ab->wmi_ab.svc_map)) {
6905*28348caeSBjoern A. Zeeb 			reinit_completion(&ar->completed_11d_scan);
6906*28348caeSBjoern A. Zeeb 			ar->state_11d = ATH11K_11D_PREPARING;
6907*28348caeSBjoern A. Zeeb 		}
6908dd4f32aeSBjoern A. Zeeb 		break;
6909dd4f32aeSBjoern A. Zeeb 	case WMI_VDEV_TYPE_MONITOR:
6910dd4f32aeSBjoern A. Zeeb 		set_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags);
6911dd4f32aeSBjoern A. Zeeb 		break;
6912dd4f32aeSBjoern A. Zeeb 	default:
6913dd4f32aeSBjoern A. Zeeb 		break;
6914dd4f32aeSBjoern A. Zeeb 	}
6915dd4f32aeSBjoern A. Zeeb 
6916dd4f32aeSBjoern A. Zeeb 	arvif->txpower = vif->bss_conf.txpower;
6917dd4f32aeSBjoern A. Zeeb 	ret = ath11k_mac_txpower_recalc(ar);
6918dd4f32aeSBjoern A. Zeeb 	if (ret)
6919dd4f32aeSBjoern A. Zeeb 		goto err_peer_del;
6920dd4f32aeSBjoern A. Zeeb 
6921dd4f32aeSBjoern A. Zeeb 	param_id = WMI_VDEV_PARAM_RTS_THRESHOLD;
6922dd4f32aeSBjoern A. Zeeb 	param_value = ar->hw->wiphy->rts_threshold;
6923dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
6924dd4f32aeSBjoern A. Zeeb 					    param_id, param_value);
6925dd4f32aeSBjoern A. Zeeb 	if (ret) {
6926dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to set rts threshold for vdev %d: %d\n",
6927dd4f32aeSBjoern A. Zeeb 			    arvif->vdev_id, ret);
6928dd4f32aeSBjoern A. Zeeb 	}
6929dd4f32aeSBjoern A. Zeeb 
6930dd4f32aeSBjoern A. Zeeb 	ath11k_dp_vdev_tx_attach(ar, arvif);
6931dd4f32aeSBjoern A. Zeeb 
6932*28348caeSBjoern A. Zeeb 	ath11k_debugfs_add_interface(arvif);
6933*28348caeSBjoern A. Zeeb 
6934dd4f32aeSBjoern A. Zeeb 	if (vif->type != NL80211_IFTYPE_MONITOR &&
6935dd4f32aeSBjoern A. Zeeb 	    test_bit(ATH11K_FLAG_MONITOR_CONF_ENABLED, &ar->monitor_flags)) {
6936dd4f32aeSBjoern A. Zeeb 		ret = ath11k_mac_monitor_vdev_create(ar);
6937*28348caeSBjoern A. Zeeb 		if (ret)
6938dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "failed to create monitor vdev during add interface: %d",
6939dd4f32aeSBjoern A. Zeeb 				    ret);
6940dd4f32aeSBjoern A. Zeeb 	}
6941dd4f32aeSBjoern A. Zeeb 
6942dd4f32aeSBjoern A. Zeeb 	mutex_unlock(&ar->conf_mutex);
6943dd4f32aeSBjoern A. Zeeb 
6944dd4f32aeSBjoern A. Zeeb 	return 0;
6945dd4f32aeSBjoern A. Zeeb 
6946dd4f32aeSBjoern A. Zeeb err_peer_del:
6947dd4f32aeSBjoern A. Zeeb 	if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
6948*28348caeSBjoern A. Zeeb 		fbret = ath11k_peer_delete(ar, arvif->vdev_id, vif->addr);
6949dd4f32aeSBjoern A. Zeeb 		if (fbret) {
6950*28348caeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "fallback fail to delete peer addr %pM vdev_id %d ret %d\n",
6951*28348caeSBjoern A. Zeeb 				    vif->addr, arvif->vdev_id, fbret);
6952dd4f32aeSBjoern A. Zeeb 			goto err;
6953dd4f32aeSBjoern A. Zeeb 		}
6954dd4f32aeSBjoern A. Zeeb 	}
6955dd4f32aeSBjoern A. Zeeb 
6956dd4f32aeSBjoern A. Zeeb err_vdev_del:
6957*28348caeSBjoern A. Zeeb 	ath11k_mac_vdev_delete(ar, arvif);
6958dd4f32aeSBjoern A. Zeeb 	spin_lock_bh(&ar->data_lock);
6959dd4f32aeSBjoern A. Zeeb 	list_del(&arvif->list);
6960dd4f32aeSBjoern A. Zeeb 	spin_unlock_bh(&ar->data_lock);
6961dd4f32aeSBjoern A. Zeeb 
6962dd4f32aeSBjoern A. Zeeb err:
6963dd4f32aeSBjoern A. Zeeb 	mutex_unlock(&ar->conf_mutex);
6964dd4f32aeSBjoern A. Zeeb 
6965dd4f32aeSBjoern A. Zeeb 	return ret;
6966dd4f32aeSBjoern A. Zeeb }
6967dd4f32aeSBjoern A. Zeeb 
ath11k_mac_vif_unref(int buf_id,void * skb,void * ctx)6968dd4f32aeSBjoern A. Zeeb static int ath11k_mac_vif_unref(int buf_id, void *skb, void *ctx)
6969dd4f32aeSBjoern A. Zeeb {
6970dd4f32aeSBjoern A. Zeeb 	struct ieee80211_vif *vif = (struct ieee80211_vif *)ctx;
6971dd4f32aeSBjoern A. Zeeb 	struct ath11k_skb_cb *skb_cb = ATH11K_SKB_CB((struct sk_buff *)skb);
6972dd4f32aeSBjoern A. Zeeb 
6973dd4f32aeSBjoern A. Zeeb 	if (skb_cb->vif == vif)
6974dd4f32aeSBjoern A. Zeeb 		skb_cb->vif = NULL;
6975dd4f32aeSBjoern A. Zeeb 
6976dd4f32aeSBjoern A. Zeeb 	return 0;
6977dd4f32aeSBjoern A. Zeeb }
6978dd4f32aeSBjoern A. Zeeb 
ath11k_mac_op_remove_interface(struct ieee80211_hw * hw,struct ieee80211_vif * vif)6979dd4f32aeSBjoern A. Zeeb static void ath11k_mac_op_remove_interface(struct ieee80211_hw *hw,
6980dd4f32aeSBjoern A. Zeeb 					   struct ieee80211_vif *vif)
6981dd4f32aeSBjoern A. Zeeb {
6982dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = hw->priv;
6983dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
6984dd4f32aeSBjoern A. Zeeb 	struct ath11k_base *ab = ar->ab;
6985dd4f32aeSBjoern A. Zeeb 	int ret;
6986dd4f32aeSBjoern A. Zeeb 	int i;
6987dd4f32aeSBjoern A. Zeeb 
6988dd4f32aeSBjoern A. Zeeb 	cancel_delayed_work_sync(&arvif->connection_loss_work);
6989dd4f32aeSBjoern A. Zeeb 
6990dd4f32aeSBjoern A. Zeeb 	mutex_lock(&ar->conf_mutex);
6991dd4f32aeSBjoern A. Zeeb 
6992*28348caeSBjoern A. Zeeb 	ath11k_dbg(ab, ATH11K_DBG_MAC, "remove interface (vdev %d)\n",
6993dd4f32aeSBjoern A. Zeeb 		   arvif->vdev_id);
6994dd4f32aeSBjoern A. Zeeb 
6995*28348caeSBjoern A. Zeeb 	ret = ath11k_spectral_vif_stop(arvif);
6996*28348caeSBjoern A. Zeeb 	if (ret)
6997*28348caeSBjoern A. Zeeb 		ath11k_warn(ab, "failed to stop spectral for vdev %i: %d\n",
6998*28348caeSBjoern A. Zeeb 			    arvif->vdev_id, ret);
6999*28348caeSBjoern A. Zeeb 
7000dd4f32aeSBjoern A. Zeeb 	if (arvif->vdev_type == WMI_VDEV_TYPE_STA)
7001dd4f32aeSBjoern A. Zeeb 		ath11k_mac_11d_scan_stop(ar);
7002dd4f32aeSBjoern A. Zeeb 
7003dd4f32aeSBjoern A. Zeeb 	if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
7004dd4f32aeSBjoern A. Zeeb 		ret = ath11k_peer_delete(ar, arvif->vdev_id, vif->addr);
7005dd4f32aeSBjoern A. Zeeb 		if (ret)
7006dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ab, "failed to submit AP self-peer removal on vdev %d: %d\n",
7007dd4f32aeSBjoern A. Zeeb 				    arvif->vdev_id, ret);
7008dd4f32aeSBjoern A. Zeeb 	}
7009dd4f32aeSBjoern A. Zeeb 
7010*28348caeSBjoern A. Zeeb 	ret = ath11k_mac_vdev_delete(ar, arvif);
7011dd4f32aeSBjoern A. Zeeb 	if (ret) {
7012*28348caeSBjoern A. Zeeb 		ath11k_warn(ab, "failed to delete vdev %d: %d\n",
7013dd4f32aeSBjoern A. Zeeb 			    arvif->vdev_id, ret);
7014dd4f32aeSBjoern A. Zeeb 		goto err_vdev_del;
7015dd4f32aeSBjoern A. Zeeb 	}
7016dd4f32aeSBjoern A. Zeeb 
7017dd4f32aeSBjoern A. Zeeb 	if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
7018dd4f32aeSBjoern A. Zeeb 		clear_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags);
7019dd4f32aeSBjoern A. Zeeb 		ar->monitor_vdev_id = -1;
7020dd4f32aeSBjoern A. Zeeb 	} else if (test_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags) &&
7021dd4f32aeSBjoern A. Zeeb 		   !test_bit(ATH11K_FLAG_MONITOR_STARTED, &ar->monitor_flags)) {
7022dd4f32aeSBjoern A. Zeeb 		ret = ath11k_mac_monitor_vdev_delete(ar);
7023dd4f32aeSBjoern A. Zeeb 		if (ret)
7024dd4f32aeSBjoern A. Zeeb 			/* continue even if there's an error */
7025dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "failed to delete vdev monitor during remove interface: %d",
7026dd4f32aeSBjoern A. Zeeb 				    ret);
7027dd4f32aeSBjoern A. Zeeb 	}
7028dd4f32aeSBjoern A. Zeeb 
7029dd4f32aeSBjoern A. Zeeb err_vdev_del:
7030dd4f32aeSBjoern A. Zeeb 	spin_lock_bh(&ar->data_lock);
7031dd4f32aeSBjoern A. Zeeb 	list_del(&arvif->list);
7032dd4f32aeSBjoern A. Zeeb 	spin_unlock_bh(&ar->data_lock);
7033dd4f32aeSBjoern A. Zeeb 
7034dd4f32aeSBjoern A. Zeeb 	ath11k_peer_cleanup(ar, arvif->vdev_id);
7035dd4f32aeSBjoern A. Zeeb 
7036dd4f32aeSBjoern A. Zeeb 	idr_for_each(&ar->txmgmt_idr,
7037dd4f32aeSBjoern A. Zeeb 		     ath11k_mac_vif_txmgmt_idr_remove, vif);
7038dd4f32aeSBjoern A. Zeeb 
7039dd4f32aeSBjoern A. Zeeb 	for (i = 0; i < ab->hw_params.max_tx_ring; i++) {
7040dd4f32aeSBjoern A. Zeeb 		spin_lock_bh(&ab->dp.tx_ring[i].tx_idr_lock);
7041dd4f32aeSBjoern A. Zeeb 		idr_for_each(&ab->dp.tx_ring[i].txbuf_idr,
7042dd4f32aeSBjoern A. Zeeb 			     ath11k_mac_vif_unref, vif);
7043dd4f32aeSBjoern A. Zeeb 		spin_unlock_bh(&ab->dp.tx_ring[i].tx_idr_lock);
7044dd4f32aeSBjoern A. Zeeb 	}
7045dd4f32aeSBjoern A. Zeeb 
7046dd4f32aeSBjoern A. Zeeb 	/* Recalc txpower for remaining vdev */
7047dd4f32aeSBjoern A. Zeeb 	ath11k_mac_txpower_recalc(ar);
7048dd4f32aeSBjoern A. Zeeb 
7049*28348caeSBjoern A. Zeeb 	ath11k_debugfs_remove_interface(arvif);
7050*28348caeSBjoern A. Zeeb 
7051dd4f32aeSBjoern A. Zeeb 	/* TODO: recal traffic pause state based on the available vdevs */
7052dd4f32aeSBjoern A. Zeeb 
7053dd4f32aeSBjoern A. Zeeb 	mutex_unlock(&ar->conf_mutex);
7054dd4f32aeSBjoern A. Zeeb }
7055dd4f32aeSBjoern A. Zeeb 
7056dd4f32aeSBjoern A. Zeeb /* FIXME: Has to be verified. */
7057dd4f32aeSBjoern A. Zeeb #define SUPPORTED_FILTERS			\
7058dd4f32aeSBjoern A. Zeeb 	(FIF_ALLMULTI |				\
7059dd4f32aeSBjoern A. Zeeb 	FIF_CONTROL |				\
7060dd4f32aeSBjoern A. Zeeb 	FIF_PSPOLL |				\
7061dd4f32aeSBjoern A. Zeeb 	FIF_OTHER_BSS |				\
7062dd4f32aeSBjoern A. Zeeb 	FIF_BCN_PRBRESP_PROMISC |		\
7063dd4f32aeSBjoern A. Zeeb 	FIF_PROBE_REQ |				\
7064dd4f32aeSBjoern A. Zeeb 	FIF_FCSFAIL)
7065dd4f32aeSBjoern A. Zeeb 
ath11k_mac_op_configure_filter(struct ieee80211_hw * hw,unsigned int changed_flags,unsigned int * total_flags,u64 multicast)7066dd4f32aeSBjoern A. Zeeb static void ath11k_mac_op_configure_filter(struct ieee80211_hw *hw,
7067dd4f32aeSBjoern A. Zeeb 					   unsigned int changed_flags,
7068dd4f32aeSBjoern A. Zeeb 					   unsigned int *total_flags,
7069dd4f32aeSBjoern A. Zeeb 					   u64 multicast)
7070dd4f32aeSBjoern A. Zeeb {
7071dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = hw->priv;
7072dd4f32aeSBjoern A. Zeeb 
7073dd4f32aeSBjoern A. Zeeb 	mutex_lock(&ar->conf_mutex);
7074dd4f32aeSBjoern A. Zeeb 
7075dd4f32aeSBjoern A. Zeeb 	*total_flags &= SUPPORTED_FILTERS;
7076dd4f32aeSBjoern A. Zeeb 	ar->filter_flags = *total_flags;
7077dd4f32aeSBjoern A. Zeeb 
7078dd4f32aeSBjoern A. Zeeb 	mutex_unlock(&ar->conf_mutex);
7079dd4f32aeSBjoern A. Zeeb }
7080dd4f32aeSBjoern A. Zeeb 
ath11k_mac_op_get_antenna(struct ieee80211_hw * hw,u32 * tx_ant,u32 * rx_ant)7081dd4f32aeSBjoern A. Zeeb static int ath11k_mac_op_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
7082dd4f32aeSBjoern A. Zeeb {
7083dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = hw->priv;
7084dd4f32aeSBjoern A. Zeeb 
7085dd4f32aeSBjoern A. Zeeb 	mutex_lock(&ar->conf_mutex);
7086dd4f32aeSBjoern A. Zeeb 
7087dd4f32aeSBjoern A. Zeeb 	*tx_ant = ar->cfg_tx_chainmask;
7088dd4f32aeSBjoern A. Zeeb 	*rx_ant = ar->cfg_rx_chainmask;
7089dd4f32aeSBjoern A. Zeeb 
7090dd4f32aeSBjoern A. Zeeb 	mutex_unlock(&ar->conf_mutex);
7091dd4f32aeSBjoern A. Zeeb 
7092dd4f32aeSBjoern A. Zeeb 	return 0;
7093dd4f32aeSBjoern A. Zeeb }
7094dd4f32aeSBjoern A. Zeeb 
ath11k_mac_op_set_antenna(struct ieee80211_hw * hw,u32 tx_ant,u32 rx_ant)7095dd4f32aeSBjoern A. Zeeb static int ath11k_mac_op_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
7096dd4f32aeSBjoern A. Zeeb {
7097dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = hw->priv;
7098dd4f32aeSBjoern A. Zeeb 	int ret;
7099dd4f32aeSBjoern A. Zeeb 
7100dd4f32aeSBjoern A. Zeeb 	mutex_lock(&ar->conf_mutex);
7101dd4f32aeSBjoern A. Zeeb 	ret = __ath11k_set_antenna(ar, tx_ant, rx_ant);
7102dd4f32aeSBjoern A. Zeeb 	mutex_unlock(&ar->conf_mutex);
7103dd4f32aeSBjoern A. Zeeb 
7104dd4f32aeSBjoern A. Zeeb 	return ret;
7105dd4f32aeSBjoern A. Zeeb }
7106dd4f32aeSBjoern A. Zeeb 
ath11k_mac_op_ampdu_action(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_ampdu_params * params)7107dd4f32aeSBjoern A. Zeeb static int ath11k_mac_op_ampdu_action(struct ieee80211_hw *hw,
7108dd4f32aeSBjoern A. Zeeb 				      struct ieee80211_vif *vif,
7109dd4f32aeSBjoern A. Zeeb 				      struct ieee80211_ampdu_params *params)
7110dd4f32aeSBjoern A. Zeeb {
7111dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = hw->priv;
7112dd4f32aeSBjoern A. Zeeb 	int ret = -EINVAL;
7113dd4f32aeSBjoern A. Zeeb 
7114dd4f32aeSBjoern A. Zeeb 	mutex_lock(&ar->conf_mutex);
7115dd4f32aeSBjoern A. Zeeb 
7116dd4f32aeSBjoern A. Zeeb 	switch (params->action) {
7117dd4f32aeSBjoern A. Zeeb 	case IEEE80211_AMPDU_RX_START:
7118dd4f32aeSBjoern A. Zeeb 		ret = ath11k_dp_rx_ampdu_start(ar, params);
7119dd4f32aeSBjoern A. Zeeb 		break;
7120dd4f32aeSBjoern A. Zeeb 	case IEEE80211_AMPDU_RX_STOP:
7121dd4f32aeSBjoern A. Zeeb 		ret = ath11k_dp_rx_ampdu_stop(ar, params);
7122dd4f32aeSBjoern A. Zeeb 		break;
7123dd4f32aeSBjoern A. Zeeb 	case IEEE80211_AMPDU_TX_START:
7124dd4f32aeSBjoern A. Zeeb 	case IEEE80211_AMPDU_TX_STOP_CONT:
7125dd4f32aeSBjoern A. Zeeb 	case IEEE80211_AMPDU_TX_STOP_FLUSH:
7126dd4f32aeSBjoern A. Zeeb 	case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
7127dd4f32aeSBjoern A. Zeeb 	case IEEE80211_AMPDU_TX_OPERATIONAL:
7128dd4f32aeSBjoern A. Zeeb 		/* Tx A-MPDU aggregation offloaded to hw/fw so deny mac80211
7129dd4f32aeSBjoern A. Zeeb 		 * Tx aggregation requests.
7130dd4f32aeSBjoern A. Zeeb 		 */
7131dd4f32aeSBjoern A. Zeeb 		ret = -EOPNOTSUPP;
7132dd4f32aeSBjoern A. Zeeb 		break;
7133dd4f32aeSBjoern A. Zeeb 	}
7134dd4f32aeSBjoern A. Zeeb 
7135dd4f32aeSBjoern A. Zeeb 	mutex_unlock(&ar->conf_mutex);
7136dd4f32aeSBjoern A. Zeeb 
7137dd4f32aeSBjoern A. Zeeb 	return ret;
7138dd4f32aeSBjoern A. Zeeb }
7139dd4f32aeSBjoern A. Zeeb 
ath11k_mac_op_add_chanctx(struct ieee80211_hw * hw,struct ieee80211_chanctx_conf * ctx)7140dd4f32aeSBjoern A. Zeeb static int ath11k_mac_op_add_chanctx(struct ieee80211_hw *hw,
7141dd4f32aeSBjoern A. Zeeb 				     struct ieee80211_chanctx_conf *ctx)
7142dd4f32aeSBjoern A. Zeeb {
7143dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = hw->priv;
7144dd4f32aeSBjoern A. Zeeb 	struct ath11k_base *ab = ar->ab;
7145dd4f32aeSBjoern A. Zeeb 
7146dd4f32aeSBjoern A. Zeeb 	ath11k_dbg(ab, ATH11K_DBG_MAC,
7147*28348caeSBjoern A. Zeeb 		   "chanctx add freq %u width %d ptr %p\n",
7148dd4f32aeSBjoern A. Zeeb 		   ctx->def.chan->center_freq, ctx->def.width, ctx);
7149dd4f32aeSBjoern A. Zeeb 
7150dd4f32aeSBjoern A. Zeeb 	mutex_lock(&ar->conf_mutex);
7151dd4f32aeSBjoern A. Zeeb 
7152dd4f32aeSBjoern A. Zeeb 	spin_lock_bh(&ar->data_lock);
7153dd4f32aeSBjoern A. Zeeb 	/* TODO: In case of multiple channel context, populate rx_channel from
7154dd4f32aeSBjoern A. Zeeb 	 * Rx PPDU desc information.
7155dd4f32aeSBjoern A. Zeeb 	 */
7156dd4f32aeSBjoern A. Zeeb 	ar->rx_channel = ctx->def.chan;
7157dd4f32aeSBjoern A. Zeeb 	spin_unlock_bh(&ar->data_lock);
7158dd4f32aeSBjoern A. Zeeb 
7159dd4f32aeSBjoern A. Zeeb 	mutex_unlock(&ar->conf_mutex);
7160dd4f32aeSBjoern A. Zeeb 
7161dd4f32aeSBjoern A. Zeeb 	return 0;
7162dd4f32aeSBjoern A. Zeeb }
7163dd4f32aeSBjoern A. Zeeb 
ath11k_mac_op_remove_chanctx(struct ieee80211_hw * hw,struct ieee80211_chanctx_conf * ctx)7164dd4f32aeSBjoern A. Zeeb static void ath11k_mac_op_remove_chanctx(struct ieee80211_hw *hw,
7165dd4f32aeSBjoern A. Zeeb 					 struct ieee80211_chanctx_conf *ctx)
7166dd4f32aeSBjoern A. Zeeb {
7167dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = hw->priv;
7168dd4f32aeSBjoern A. Zeeb 	struct ath11k_base *ab = ar->ab;
7169dd4f32aeSBjoern A. Zeeb 
7170dd4f32aeSBjoern A. Zeeb 	ath11k_dbg(ab, ATH11K_DBG_MAC,
7171*28348caeSBjoern A. Zeeb 		   "chanctx remove freq %u width %d ptr %p\n",
7172dd4f32aeSBjoern A. Zeeb 		   ctx->def.chan->center_freq, ctx->def.width, ctx);
7173dd4f32aeSBjoern A. Zeeb 
7174dd4f32aeSBjoern A. Zeeb 	mutex_lock(&ar->conf_mutex);
7175dd4f32aeSBjoern A. Zeeb 
7176dd4f32aeSBjoern A. Zeeb 	spin_lock_bh(&ar->data_lock);
7177dd4f32aeSBjoern A. Zeeb 	/* TODO: In case of there is one more channel context left, populate
7178dd4f32aeSBjoern A. Zeeb 	 * rx_channel with the channel of that remaining channel context.
7179dd4f32aeSBjoern A. Zeeb 	 */
7180dd4f32aeSBjoern A. Zeeb 	ar->rx_channel = NULL;
7181dd4f32aeSBjoern A. Zeeb 	spin_unlock_bh(&ar->data_lock);
7182dd4f32aeSBjoern A. Zeeb 
7183dd4f32aeSBjoern A. Zeeb 	mutex_unlock(&ar->conf_mutex);
7184dd4f32aeSBjoern A. Zeeb }
7185dd4f32aeSBjoern A. Zeeb 
7186dd4f32aeSBjoern A. Zeeb static int
ath11k_mac_vdev_start_restart(struct ath11k_vif * arvif,struct ieee80211_chanctx_conf * ctx,bool restart)7187dd4f32aeSBjoern A. Zeeb ath11k_mac_vdev_start_restart(struct ath11k_vif *arvif,
7188*28348caeSBjoern A. Zeeb 			      struct ieee80211_chanctx_conf *ctx,
7189dd4f32aeSBjoern A. Zeeb 			      bool restart)
7190dd4f32aeSBjoern A. Zeeb {
7191dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = arvif->ar;
7192dd4f32aeSBjoern A. Zeeb 	struct ath11k_base *ab = ar->ab;
7193dd4f32aeSBjoern A. Zeeb 	struct wmi_vdev_start_req_arg arg = {};
7194*28348caeSBjoern A. Zeeb 	const struct cfg80211_chan_def *chandef = &ctx->def;
7195dd4f32aeSBjoern A. Zeeb 	int ret = 0;
7196dd4f32aeSBjoern A. Zeeb 
7197dd4f32aeSBjoern A. Zeeb 	lockdep_assert_held(&ar->conf_mutex);
7198dd4f32aeSBjoern A. Zeeb 
7199dd4f32aeSBjoern A. Zeeb 	reinit_completion(&ar->vdev_setup_done);
7200dd4f32aeSBjoern A. Zeeb 
7201dd4f32aeSBjoern A. Zeeb 	arg.vdev_id = arvif->vdev_id;
7202dd4f32aeSBjoern A. Zeeb 	arg.dtim_period = arvif->dtim_period;
7203dd4f32aeSBjoern A. Zeeb 	arg.bcn_intval = arvif->beacon_interval;
7204dd4f32aeSBjoern A. Zeeb 
7205dd4f32aeSBjoern A. Zeeb 	arg.channel.freq = chandef->chan->center_freq;
7206dd4f32aeSBjoern A. Zeeb 	arg.channel.band_center_freq1 = chandef->center_freq1;
7207dd4f32aeSBjoern A. Zeeb 	arg.channel.band_center_freq2 = chandef->center_freq2;
7208dd4f32aeSBjoern A. Zeeb 	arg.channel.mode =
7209dd4f32aeSBjoern A. Zeeb 		ath11k_phymodes[chandef->chan->band][chandef->width];
7210dd4f32aeSBjoern A. Zeeb 
7211dd4f32aeSBjoern A. Zeeb 	arg.channel.min_power = 0;
7212dd4f32aeSBjoern A. Zeeb 	arg.channel.max_power = chandef->chan->max_power;
7213dd4f32aeSBjoern A. Zeeb 	arg.channel.max_reg_power = chandef->chan->max_reg_power;
7214dd4f32aeSBjoern A. Zeeb 	arg.channel.max_antenna_gain = chandef->chan->max_antenna_gain;
7215dd4f32aeSBjoern A. Zeeb 
7216dd4f32aeSBjoern A. Zeeb 	arg.pref_tx_streams = ar->num_tx_chains;
7217dd4f32aeSBjoern A. Zeeb 	arg.pref_rx_streams = ar->num_rx_chains;
7218dd4f32aeSBjoern A. Zeeb 
7219*28348caeSBjoern A. Zeeb 	arg.mbssid_flags = 0;
7220*28348caeSBjoern A. Zeeb 	arg.mbssid_tx_vdev_id = 0;
7221*28348caeSBjoern A. Zeeb 	if (test_bit(WMI_TLV_SERVICE_MBSS_PARAM_IN_VDEV_START_SUPPORT,
7222*28348caeSBjoern A. Zeeb 		     ar->ab->wmi_ab.svc_map)) {
7223*28348caeSBjoern A. Zeeb 		ret = ath11k_mac_setup_vdev_params_mbssid(arvif,
7224*28348caeSBjoern A. Zeeb 							  &arg.mbssid_flags,
7225*28348caeSBjoern A. Zeeb 							  &arg.mbssid_tx_vdev_id);
7226*28348caeSBjoern A. Zeeb 		if (ret)
7227*28348caeSBjoern A. Zeeb 			return ret;
7228*28348caeSBjoern A. Zeeb 	}
7229*28348caeSBjoern A. Zeeb 
7230dd4f32aeSBjoern A. Zeeb 	if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
7231dd4f32aeSBjoern A. Zeeb 		arg.ssid = arvif->u.ap.ssid;
7232dd4f32aeSBjoern A. Zeeb 		arg.ssid_len = arvif->u.ap.ssid_len;
7233dd4f32aeSBjoern A. Zeeb 		arg.hidden_ssid = arvif->u.ap.hidden_ssid;
7234dd4f32aeSBjoern A. Zeeb 
7235dd4f32aeSBjoern A. Zeeb 		/* For now allow DFS for AP mode */
7236dd4f32aeSBjoern A. Zeeb 		arg.channel.chan_radar =
7237dd4f32aeSBjoern A. Zeeb 			!!(chandef->chan->flags & IEEE80211_CHAN_RADAR);
7238dd4f32aeSBjoern A. Zeeb 
7239*28348caeSBjoern A. Zeeb 		arg.channel.freq2_radar = ctx->radar_enabled;
7240dd4f32aeSBjoern A. Zeeb 
7241dd4f32aeSBjoern A. Zeeb 		arg.channel.passive = arg.channel.chan_radar;
7242dd4f32aeSBjoern A. Zeeb 
7243dd4f32aeSBjoern A. Zeeb 		spin_lock_bh(&ab->base_lock);
7244dd4f32aeSBjoern A. Zeeb 		arg.regdomain = ar->ab->dfs_region;
7245dd4f32aeSBjoern A. Zeeb 		spin_unlock_bh(&ab->base_lock);
7246dd4f32aeSBjoern A. Zeeb 	}
7247dd4f32aeSBjoern A. Zeeb 
7248dd4f32aeSBjoern A. Zeeb 	arg.channel.passive |= !!(chandef->chan->flags & IEEE80211_CHAN_NO_IR);
7249dd4f32aeSBjoern A. Zeeb 
7250dd4f32aeSBjoern A. Zeeb 	ath11k_dbg(ab, ATH11K_DBG_MAC,
7251*28348caeSBjoern A. Zeeb 		   "vdev %d start center_freq %d phymode %s\n",
7252dd4f32aeSBjoern A. Zeeb 		   arg.vdev_id, arg.channel.freq,
7253dd4f32aeSBjoern A. Zeeb 		   ath11k_wmi_phymode_str(arg.channel.mode));
7254dd4f32aeSBjoern A. Zeeb 
7255dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_vdev_start(ar, &arg, restart);
7256dd4f32aeSBjoern A. Zeeb 	if (ret) {
7257dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to %s WMI vdev %i\n",
7258dd4f32aeSBjoern A. Zeeb 			    restart ? "restart" : "start", arg.vdev_id);
7259dd4f32aeSBjoern A. Zeeb 		return ret;
7260dd4f32aeSBjoern A. Zeeb 	}
7261dd4f32aeSBjoern A. Zeeb 
7262dd4f32aeSBjoern A. Zeeb 	ret = ath11k_mac_vdev_setup_sync(ar);
7263dd4f32aeSBjoern A. Zeeb 	if (ret) {
7264dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ab, "failed to synchronize setup for vdev %i %s: %d\n",
7265dd4f32aeSBjoern A. Zeeb 			    arg.vdev_id, restart ? "restart" : "start", ret);
7266dd4f32aeSBjoern A. Zeeb 		return ret;
7267dd4f32aeSBjoern A. Zeeb 	}
7268dd4f32aeSBjoern A. Zeeb 
7269dd4f32aeSBjoern A. Zeeb 	if (!restart)
7270dd4f32aeSBjoern A. Zeeb 		ar->num_started_vdevs++;
7271dd4f32aeSBjoern A. Zeeb 
7272dd4f32aeSBjoern A. Zeeb 	ath11k_dbg(ab, ATH11K_DBG_MAC,  "vdev %pM started, vdev_id %d\n",
7273dd4f32aeSBjoern A. Zeeb 		   arvif->vif->addr, arvif->vdev_id);
7274dd4f32aeSBjoern A. Zeeb 
7275dd4f32aeSBjoern A. Zeeb 	/* Enable CAC Flag in the driver by checking the channel DFS cac time,
7276dd4f32aeSBjoern A. Zeeb 	 * i.e dfs_cac_ms value which will be valid only for radar channels
7277dd4f32aeSBjoern A. Zeeb 	 * and state as NL80211_DFS_USABLE which indicates CAC needs to be
7278dd4f32aeSBjoern A. Zeeb 	 * done before channel usage. This flags is used to drop rx packets.
7279dd4f32aeSBjoern A. Zeeb 	 * during CAC.
7280dd4f32aeSBjoern A. Zeeb 	 */
7281dd4f32aeSBjoern A. Zeeb 	/* TODO Set the flag for other interface types as required */
7282dd4f32aeSBjoern A. Zeeb 	if (arvif->vdev_type == WMI_VDEV_TYPE_AP &&
7283dd4f32aeSBjoern A. Zeeb 	    chandef->chan->dfs_cac_ms &&
7284dd4f32aeSBjoern A. Zeeb 	    chandef->chan->dfs_state == NL80211_DFS_USABLE) {
7285dd4f32aeSBjoern A. Zeeb 		set_bit(ATH11K_CAC_RUNNING, &ar->dev_flags);
7286dd4f32aeSBjoern A. Zeeb 		ath11k_dbg(ab, ATH11K_DBG_MAC,
7287dd4f32aeSBjoern A. Zeeb 			   "CAC Started in chan_freq %d for vdev %d\n",
7288dd4f32aeSBjoern A. Zeeb 			   arg.channel.freq, arg.vdev_id);
7289dd4f32aeSBjoern A. Zeeb 	}
7290dd4f32aeSBjoern A. Zeeb 
7291dd4f32aeSBjoern A. Zeeb 	ret = ath11k_mac_set_txbf_conf(arvif);
7292dd4f32aeSBjoern A. Zeeb 	if (ret)
7293dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ab, "failed to set txbf conf for vdev %d: %d\n",
7294dd4f32aeSBjoern A. Zeeb 			    arvif->vdev_id, ret);
7295dd4f32aeSBjoern A. Zeeb 
7296dd4f32aeSBjoern A. Zeeb 	return 0;
7297dd4f32aeSBjoern A. Zeeb }
7298dd4f32aeSBjoern A. Zeeb 
ath11k_mac_vdev_stop(struct ath11k_vif * arvif)7299dd4f32aeSBjoern A. Zeeb static int ath11k_mac_vdev_stop(struct ath11k_vif *arvif)
7300dd4f32aeSBjoern A. Zeeb {
7301dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = arvif->ar;
7302dd4f32aeSBjoern A. Zeeb 	int ret;
7303dd4f32aeSBjoern A. Zeeb 
7304dd4f32aeSBjoern A. Zeeb 	lockdep_assert_held(&ar->conf_mutex);
7305dd4f32aeSBjoern A. Zeeb 
7306dd4f32aeSBjoern A. Zeeb 	reinit_completion(&ar->vdev_setup_done);
7307dd4f32aeSBjoern A. Zeeb 
7308dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_vdev_stop(ar, arvif->vdev_id);
7309dd4f32aeSBjoern A. Zeeb 	if (ret) {
7310dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to stop WMI vdev %i: %d\n",
7311dd4f32aeSBjoern A. Zeeb 			    arvif->vdev_id, ret);
7312dd4f32aeSBjoern A. Zeeb 		goto err;
7313dd4f32aeSBjoern A. Zeeb 	}
7314dd4f32aeSBjoern A. Zeeb 
7315dd4f32aeSBjoern A. Zeeb 	ret = ath11k_mac_vdev_setup_sync(ar);
7316dd4f32aeSBjoern A. Zeeb 	if (ret) {
7317dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to synchronize setup for vdev %i: %d\n",
7318dd4f32aeSBjoern A. Zeeb 			    arvif->vdev_id, ret);
7319dd4f32aeSBjoern A. Zeeb 		goto err;
7320dd4f32aeSBjoern A. Zeeb 	}
7321dd4f32aeSBjoern A. Zeeb 
7322dd4f32aeSBjoern A. Zeeb 	WARN_ON(ar->num_started_vdevs == 0);
7323dd4f32aeSBjoern A. Zeeb 
7324dd4f32aeSBjoern A. Zeeb 	ar->num_started_vdevs--;
7325dd4f32aeSBjoern A. Zeeb 	ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev %pM stopped, vdev_id %d\n",
7326dd4f32aeSBjoern A. Zeeb 		   arvif->vif->addr, arvif->vdev_id);
7327dd4f32aeSBjoern A. Zeeb 
7328dd4f32aeSBjoern A. Zeeb 	if (test_bit(ATH11K_CAC_RUNNING, &ar->dev_flags)) {
7329dd4f32aeSBjoern A. Zeeb 		clear_bit(ATH11K_CAC_RUNNING, &ar->dev_flags);
7330dd4f32aeSBjoern A. Zeeb 		ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "CAC Stopped for vdev %d\n",
7331dd4f32aeSBjoern A. Zeeb 			   arvif->vdev_id);
7332dd4f32aeSBjoern A. Zeeb 	}
7333dd4f32aeSBjoern A. Zeeb 
7334dd4f32aeSBjoern A. Zeeb 	return 0;
7335dd4f32aeSBjoern A. Zeeb err:
7336dd4f32aeSBjoern A. Zeeb 	return ret;
7337dd4f32aeSBjoern A. Zeeb }
7338dd4f32aeSBjoern A. Zeeb 
ath11k_mac_vdev_start(struct ath11k_vif * arvif,struct ieee80211_chanctx_conf * ctx)7339dd4f32aeSBjoern A. Zeeb static int ath11k_mac_vdev_start(struct ath11k_vif *arvif,
7340*28348caeSBjoern A. Zeeb 				 struct ieee80211_chanctx_conf *ctx)
7341dd4f32aeSBjoern A. Zeeb {
7342*28348caeSBjoern A. Zeeb 	return ath11k_mac_vdev_start_restart(arvif, ctx, false);
7343dd4f32aeSBjoern A. Zeeb }
7344dd4f32aeSBjoern A. Zeeb 
ath11k_mac_vdev_restart(struct ath11k_vif * arvif,struct ieee80211_chanctx_conf * ctx)7345dd4f32aeSBjoern A. Zeeb static int ath11k_mac_vdev_restart(struct ath11k_vif *arvif,
7346*28348caeSBjoern A. Zeeb 				   struct ieee80211_chanctx_conf *ctx)
7347dd4f32aeSBjoern A. Zeeb {
7348*28348caeSBjoern A. Zeeb 	return ath11k_mac_vdev_start_restart(arvif, ctx, true);
7349dd4f32aeSBjoern A. Zeeb }
7350dd4f32aeSBjoern A. Zeeb 
7351dd4f32aeSBjoern A. Zeeb struct ath11k_mac_change_chanctx_arg {
7352dd4f32aeSBjoern A. Zeeb 	struct ieee80211_chanctx_conf *ctx;
7353dd4f32aeSBjoern A. Zeeb 	struct ieee80211_vif_chanctx_switch *vifs;
7354dd4f32aeSBjoern A. Zeeb 	int n_vifs;
7355dd4f32aeSBjoern A. Zeeb 	int next_vif;
7356dd4f32aeSBjoern A. Zeeb };
7357dd4f32aeSBjoern A. Zeeb 
7358dd4f32aeSBjoern A. Zeeb static void
ath11k_mac_change_chanctx_cnt_iter(void * data,u8 * mac,struct ieee80211_vif * vif)7359dd4f32aeSBjoern A. Zeeb ath11k_mac_change_chanctx_cnt_iter(void *data, u8 *mac,
7360dd4f32aeSBjoern A. Zeeb 				   struct ieee80211_vif *vif)
7361dd4f32aeSBjoern A. Zeeb {
7362dd4f32aeSBjoern A. Zeeb 	struct ath11k_mac_change_chanctx_arg *arg = data;
7363dd4f32aeSBjoern A. Zeeb 
7364*28348caeSBjoern A. Zeeb 	if (rcu_access_pointer(vif->bss_conf.chanctx_conf) != arg->ctx)
7365dd4f32aeSBjoern A. Zeeb 		return;
7366dd4f32aeSBjoern A. Zeeb 
7367dd4f32aeSBjoern A. Zeeb 	arg->n_vifs++;
7368dd4f32aeSBjoern A. Zeeb }
7369dd4f32aeSBjoern A. Zeeb 
7370dd4f32aeSBjoern A. Zeeb static void
ath11k_mac_change_chanctx_fill_iter(void * data,u8 * mac,struct ieee80211_vif * vif)7371dd4f32aeSBjoern A. Zeeb ath11k_mac_change_chanctx_fill_iter(void *data, u8 *mac,
7372dd4f32aeSBjoern A. Zeeb 				    struct ieee80211_vif *vif)
7373dd4f32aeSBjoern A. Zeeb {
7374dd4f32aeSBjoern A. Zeeb 	struct ath11k_mac_change_chanctx_arg *arg = data;
7375dd4f32aeSBjoern A. Zeeb 	struct ieee80211_chanctx_conf *ctx;
7376dd4f32aeSBjoern A. Zeeb 
7377*28348caeSBjoern A. Zeeb 	ctx = rcu_access_pointer(vif->bss_conf.chanctx_conf);
7378dd4f32aeSBjoern A. Zeeb 	if (ctx != arg->ctx)
7379dd4f32aeSBjoern A. Zeeb 		return;
7380dd4f32aeSBjoern A. Zeeb 
7381dd4f32aeSBjoern A. Zeeb 	if (WARN_ON(arg->next_vif == arg->n_vifs))
7382dd4f32aeSBjoern A. Zeeb 		return;
7383dd4f32aeSBjoern A. Zeeb 
7384dd4f32aeSBjoern A. Zeeb 	arg->vifs[arg->next_vif].vif = vif;
7385dd4f32aeSBjoern A. Zeeb 	arg->vifs[arg->next_vif].old_ctx = ctx;
7386dd4f32aeSBjoern A. Zeeb 	arg->vifs[arg->next_vif].new_ctx = ctx;
7387dd4f32aeSBjoern A. Zeeb 	arg->next_vif++;
7388dd4f32aeSBjoern A. Zeeb }
7389dd4f32aeSBjoern A. Zeeb 
7390dd4f32aeSBjoern A. Zeeb static void
ath11k_mac_update_vif_chan(struct ath11k * ar,struct ieee80211_vif_chanctx_switch * vifs,int n_vifs)7391dd4f32aeSBjoern A. Zeeb ath11k_mac_update_vif_chan(struct ath11k *ar,
7392dd4f32aeSBjoern A. Zeeb 			   struct ieee80211_vif_chanctx_switch *vifs,
7393dd4f32aeSBjoern A. Zeeb 			   int n_vifs)
7394dd4f32aeSBjoern A. Zeeb {
7395dd4f32aeSBjoern A. Zeeb 	struct ath11k_base *ab = ar->ab;
7396*28348caeSBjoern A. Zeeb 	struct ath11k_vif *arvif, *tx_arvif = NULL;
7397*28348caeSBjoern A. Zeeb 	struct ieee80211_vif *mbssid_tx_vif;
7398dd4f32aeSBjoern A. Zeeb 	int ret;
7399dd4f32aeSBjoern A. Zeeb 	int i;
7400dd4f32aeSBjoern A. Zeeb 	bool monitor_vif = false;
7401dd4f32aeSBjoern A. Zeeb 
7402dd4f32aeSBjoern A. Zeeb 	lockdep_assert_held(&ar->conf_mutex);
7403dd4f32aeSBjoern A. Zeeb 
7404dd4f32aeSBjoern A. Zeeb 	/* Associated channel resources of all relevant vdevs
7405dd4f32aeSBjoern A. Zeeb 	 * should be available for the channel switch now.
7406dd4f32aeSBjoern A. Zeeb 	 */
7407dd4f32aeSBjoern A. Zeeb 
7408dd4f32aeSBjoern A. Zeeb 	/* TODO: Update ar->rx_channel */
7409dd4f32aeSBjoern A. Zeeb 
7410dd4f32aeSBjoern A. Zeeb 	for (i = 0; i < n_vifs; i++) {
7411dd4f32aeSBjoern A. Zeeb 		arvif = (void *)vifs[i].vif->drv_priv;
7412dd4f32aeSBjoern A. Zeeb 
7413dd4f32aeSBjoern A. Zeeb 		if (WARN_ON(!arvif->is_started))
7414dd4f32aeSBjoern A. Zeeb 			continue;
7415dd4f32aeSBjoern A. Zeeb 
7416*28348caeSBjoern A. Zeeb 		/* change_chanctx can be called even before vdev_up from
7417*28348caeSBjoern A. Zeeb 		 * ieee80211_start_ap->ieee80211_vif_use_channel->
7418*28348caeSBjoern A. Zeeb 		 * ieee80211_recalc_radar_chanctx.
7419*28348caeSBjoern A. Zeeb 		 *
7420*28348caeSBjoern A. Zeeb 		 * Firmware expect vdev_restart only if vdev is up.
7421*28348caeSBjoern A. Zeeb 		 * If vdev is down then it expect vdev_stop->vdev_start.
7422*28348caeSBjoern A. Zeeb 		 */
7423*28348caeSBjoern A. Zeeb 		if (arvif->is_up) {
7424*28348caeSBjoern A. Zeeb 			ret = ath11k_mac_vdev_restart(arvif, vifs[i].new_ctx);
7425dd4f32aeSBjoern A. Zeeb 			if (ret) {
7426dd4f32aeSBjoern A. Zeeb 				ath11k_warn(ab, "failed to restart vdev %d: %d\n",
7427dd4f32aeSBjoern A. Zeeb 					    arvif->vdev_id, ret);
7428dd4f32aeSBjoern A. Zeeb 				continue;
7429dd4f32aeSBjoern A. Zeeb 			}
7430*28348caeSBjoern A. Zeeb 		} else {
7431*28348caeSBjoern A. Zeeb 			ret = ath11k_mac_vdev_stop(arvif);
7432*28348caeSBjoern A. Zeeb 			if (ret) {
7433*28348caeSBjoern A. Zeeb 				ath11k_warn(ab, "failed to stop vdev %d: %d\n",
7434*28348caeSBjoern A. Zeeb 					    arvif->vdev_id, ret);
7435*28348caeSBjoern A. Zeeb 				continue;
7436*28348caeSBjoern A. Zeeb 			}
7437*28348caeSBjoern A. Zeeb 
7438*28348caeSBjoern A. Zeeb 			ret = ath11k_mac_vdev_start(arvif, vifs[i].new_ctx);
7439*28348caeSBjoern A. Zeeb 			if (ret)
7440*28348caeSBjoern A. Zeeb 				ath11k_warn(ab, "failed to start vdev %d: %d\n",
7441*28348caeSBjoern A. Zeeb 					    arvif->vdev_id, ret);
7442*28348caeSBjoern A. Zeeb 
7443*28348caeSBjoern A. Zeeb 			continue;
7444*28348caeSBjoern A. Zeeb 		}
7445dd4f32aeSBjoern A. Zeeb 
7446dd4f32aeSBjoern A. Zeeb 		ret = ath11k_mac_setup_bcn_tmpl(arvif);
7447dd4f32aeSBjoern A. Zeeb 		if (ret)
7448dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ab, "failed to update bcn tmpl during csa: %d\n",
7449dd4f32aeSBjoern A. Zeeb 				    ret);
7450dd4f32aeSBjoern A. Zeeb 
7451*28348caeSBjoern A. Zeeb 		mbssid_tx_vif = arvif->vif->mbssid_tx_vif;
7452*28348caeSBjoern A. Zeeb 		if (mbssid_tx_vif)
7453*28348caeSBjoern A. Zeeb 			tx_arvif = (struct ath11k_vif *)mbssid_tx_vif->drv_priv;
7454*28348caeSBjoern A. Zeeb 
7455dd4f32aeSBjoern A. Zeeb 		ret = ath11k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid,
7456*28348caeSBjoern A. Zeeb 					 arvif->bssid,
7457*28348caeSBjoern A. Zeeb 					 tx_arvif ? tx_arvif->bssid : NULL,
7458*28348caeSBjoern A. Zeeb 					 arvif->vif->bss_conf.bssid_index,
7459*28348caeSBjoern A. Zeeb 					 1 << arvif->vif->bss_conf.bssid_indicator);
7460dd4f32aeSBjoern A. Zeeb 		if (ret) {
7461dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ab, "failed to bring vdev up %d: %d\n",
7462dd4f32aeSBjoern A. Zeeb 				    arvif->vdev_id, ret);
7463dd4f32aeSBjoern A. Zeeb 			continue;
7464dd4f32aeSBjoern A. Zeeb 		}
7465dd4f32aeSBjoern A. Zeeb 	}
7466dd4f32aeSBjoern A. Zeeb 
7467dd4f32aeSBjoern A. Zeeb 	/* Restart the internal monitor vdev on new channel */
7468dd4f32aeSBjoern A. Zeeb 	if (!monitor_vif &&
7469dd4f32aeSBjoern A. Zeeb 	    test_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags)) {
7470dd4f32aeSBjoern A. Zeeb 		ret = ath11k_mac_monitor_stop(ar);
7471dd4f32aeSBjoern A. Zeeb 		if (ret) {
7472dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "failed to stop monitor during vif channel update: %d",
7473dd4f32aeSBjoern A. Zeeb 				    ret);
7474dd4f32aeSBjoern A. Zeeb 			return;
7475dd4f32aeSBjoern A. Zeeb 		}
7476dd4f32aeSBjoern A. Zeeb 
7477dd4f32aeSBjoern A. Zeeb 		ret = ath11k_mac_monitor_start(ar);
7478dd4f32aeSBjoern A. Zeeb 		if (ret) {
7479dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "failed to start monitor during vif channel update: %d",
7480dd4f32aeSBjoern A. Zeeb 				    ret);
7481dd4f32aeSBjoern A. Zeeb 			return;
7482dd4f32aeSBjoern A. Zeeb 		}
7483dd4f32aeSBjoern A. Zeeb 	}
7484dd4f32aeSBjoern A. Zeeb }
7485dd4f32aeSBjoern A. Zeeb 
7486dd4f32aeSBjoern A. Zeeb static void
ath11k_mac_update_active_vif_chan(struct ath11k * ar,struct ieee80211_chanctx_conf * ctx)7487dd4f32aeSBjoern A. Zeeb ath11k_mac_update_active_vif_chan(struct ath11k *ar,
7488dd4f32aeSBjoern A. Zeeb 				  struct ieee80211_chanctx_conf *ctx)
7489dd4f32aeSBjoern A. Zeeb {
7490dd4f32aeSBjoern A. Zeeb 	struct ath11k_mac_change_chanctx_arg arg = { .ctx = ctx };
7491dd4f32aeSBjoern A. Zeeb 
7492dd4f32aeSBjoern A. Zeeb 	lockdep_assert_held(&ar->conf_mutex);
7493dd4f32aeSBjoern A. Zeeb 
7494dd4f32aeSBjoern A. Zeeb 	ieee80211_iterate_active_interfaces_atomic(ar->hw,
7495dd4f32aeSBjoern A. Zeeb 						   IEEE80211_IFACE_ITER_NORMAL,
7496dd4f32aeSBjoern A. Zeeb 						   ath11k_mac_change_chanctx_cnt_iter,
7497dd4f32aeSBjoern A. Zeeb 						   &arg);
7498dd4f32aeSBjoern A. Zeeb 	if (arg.n_vifs == 0)
7499dd4f32aeSBjoern A. Zeeb 		return;
7500dd4f32aeSBjoern A. Zeeb 
7501dd4f32aeSBjoern A. Zeeb 	arg.vifs = kcalloc(arg.n_vifs, sizeof(arg.vifs[0]), GFP_KERNEL);
7502dd4f32aeSBjoern A. Zeeb 	if (!arg.vifs)
7503dd4f32aeSBjoern A. Zeeb 		return;
7504dd4f32aeSBjoern A. Zeeb 
7505dd4f32aeSBjoern A. Zeeb 	ieee80211_iterate_active_interfaces_atomic(ar->hw,
7506dd4f32aeSBjoern A. Zeeb 						   IEEE80211_IFACE_ITER_NORMAL,
7507dd4f32aeSBjoern A. Zeeb 						   ath11k_mac_change_chanctx_fill_iter,
7508dd4f32aeSBjoern A. Zeeb 						   &arg);
7509dd4f32aeSBjoern A. Zeeb 
7510dd4f32aeSBjoern A. Zeeb 	ath11k_mac_update_vif_chan(ar, arg.vifs, arg.n_vifs);
7511dd4f32aeSBjoern A. Zeeb 
7512dd4f32aeSBjoern A. Zeeb 	kfree(arg.vifs);
7513dd4f32aeSBjoern A. Zeeb }
7514dd4f32aeSBjoern A. Zeeb 
ath11k_mac_op_change_chanctx(struct ieee80211_hw * hw,struct ieee80211_chanctx_conf * ctx,u32 changed)7515dd4f32aeSBjoern A. Zeeb static void ath11k_mac_op_change_chanctx(struct ieee80211_hw *hw,
7516dd4f32aeSBjoern A. Zeeb 					 struct ieee80211_chanctx_conf *ctx,
7517dd4f32aeSBjoern A. Zeeb 					 u32 changed)
7518dd4f32aeSBjoern A. Zeeb {
7519dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = hw->priv;
7520dd4f32aeSBjoern A. Zeeb 	struct ath11k_base *ab = ar->ab;
7521dd4f32aeSBjoern A. Zeeb 
7522dd4f32aeSBjoern A. Zeeb 	mutex_lock(&ar->conf_mutex);
7523dd4f32aeSBjoern A. Zeeb 
7524dd4f32aeSBjoern A. Zeeb 	ath11k_dbg(ab, ATH11K_DBG_MAC,
7525*28348caeSBjoern A. Zeeb 		   "chanctx change freq %u width %d ptr %p changed %x\n",
7526dd4f32aeSBjoern A. Zeeb 		   ctx->def.chan->center_freq, ctx->def.width, ctx, changed);
7527dd4f32aeSBjoern A. Zeeb 
7528dd4f32aeSBjoern A. Zeeb 	/* This shouldn't really happen because channel switching should use
7529dd4f32aeSBjoern A. Zeeb 	 * switch_vif_chanctx().
7530dd4f32aeSBjoern A. Zeeb 	 */
7531dd4f32aeSBjoern A. Zeeb 	if (WARN_ON(changed & IEEE80211_CHANCTX_CHANGE_CHANNEL))
7532dd4f32aeSBjoern A. Zeeb 		goto unlock;
7533dd4f32aeSBjoern A. Zeeb 
7534*28348caeSBjoern A. Zeeb 	if (changed & IEEE80211_CHANCTX_CHANGE_WIDTH ||
7535*28348caeSBjoern A. Zeeb 	    changed & IEEE80211_CHANCTX_CHANGE_RADAR)
7536dd4f32aeSBjoern A. Zeeb 		ath11k_mac_update_active_vif_chan(ar, ctx);
7537dd4f32aeSBjoern A. Zeeb 
7538dd4f32aeSBjoern A. Zeeb 	/* TODO: Recalc radar detection */
7539dd4f32aeSBjoern A. Zeeb 
7540dd4f32aeSBjoern A. Zeeb unlock:
7541dd4f32aeSBjoern A. Zeeb 	mutex_unlock(&ar->conf_mutex);
7542dd4f32aeSBjoern A. Zeeb }
7543dd4f32aeSBjoern A. Zeeb 
ath11k_start_vdev_delay(struct ieee80211_hw * hw,struct ieee80211_vif * vif)7544dd4f32aeSBjoern A. Zeeb static int ath11k_start_vdev_delay(struct ieee80211_hw *hw,
7545dd4f32aeSBjoern A. Zeeb 				   struct ieee80211_vif *vif)
7546dd4f32aeSBjoern A. Zeeb {
7547dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = hw->priv;
7548dd4f32aeSBjoern A. Zeeb 	struct ath11k_base *ab = ar->ab;
7549dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif = (void *)vif->drv_priv;
7550dd4f32aeSBjoern A. Zeeb 	int ret;
7551dd4f32aeSBjoern A. Zeeb 
7552dd4f32aeSBjoern A. Zeeb 	if (WARN_ON(arvif->is_started))
7553dd4f32aeSBjoern A. Zeeb 		return -EBUSY;
7554dd4f32aeSBjoern A. Zeeb 
7555*28348caeSBjoern A. Zeeb 	ret = ath11k_mac_vdev_start(arvif, &arvif->chanctx);
7556dd4f32aeSBjoern A. Zeeb 	if (ret) {
7557dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ab, "failed to start vdev %i addr %pM on freq %d: %d\n",
7558dd4f32aeSBjoern A. Zeeb 			    arvif->vdev_id, vif->addr,
7559dd4f32aeSBjoern A. Zeeb 			    arvif->chanctx.def.chan->center_freq, ret);
7560dd4f32aeSBjoern A. Zeeb 		return ret;
7561dd4f32aeSBjoern A. Zeeb 	}
7562dd4f32aeSBjoern A. Zeeb 
7563dd4f32aeSBjoern A. Zeeb 	/* Reconfigure hardware rate code since it is cleared by firmware.
7564dd4f32aeSBjoern A. Zeeb 	 */
7565dd4f32aeSBjoern A. Zeeb 	if (ar->hw_rate_code > 0) {
7566dd4f32aeSBjoern A. Zeeb 		u32 vdev_param = WMI_VDEV_PARAM_MGMT_RATE;
7567dd4f32aeSBjoern A. Zeeb 
7568dd4f32aeSBjoern A. Zeeb 		ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, vdev_param,
7569dd4f32aeSBjoern A. Zeeb 						    ar->hw_rate_code);
7570dd4f32aeSBjoern A. Zeeb 		if (ret) {
7571dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "failed to set mgmt tx rate %d\n", ret);
7572dd4f32aeSBjoern A. Zeeb 			return ret;
7573dd4f32aeSBjoern A. Zeeb 		}
7574dd4f32aeSBjoern A. Zeeb 	}
7575dd4f32aeSBjoern A. Zeeb 
7576dd4f32aeSBjoern A. Zeeb 	if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
7577*28348caeSBjoern A. Zeeb 		ret = ath11k_wmi_vdev_up(ar, arvif->vdev_id, 0, ar->mac_addr,
7578*28348caeSBjoern A. Zeeb 					 NULL, 0, 0);
7579dd4f32aeSBjoern A. Zeeb 		if (ret) {
7580dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ab, "failed put monitor up: %d\n", ret);
7581dd4f32aeSBjoern A. Zeeb 			return ret;
7582dd4f32aeSBjoern A. Zeeb 		}
7583dd4f32aeSBjoern A. Zeeb 	}
7584dd4f32aeSBjoern A. Zeeb 
7585dd4f32aeSBjoern A. Zeeb 	arvif->is_started = true;
7586dd4f32aeSBjoern A. Zeeb 
7587dd4f32aeSBjoern A. Zeeb 	/* TODO: Setup ps and cts/rts protection */
7588dd4f32aeSBjoern A. Zeeb 	return 0;
7589dd4f32aeSBjoern A. Zeeb }
7590dd4f32aeSBjoern A. Zeeb 
7591dd4f32aeSBjoern A. Zeeb static int
ath11k_mac_op_assign_vif_chanctx(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_bss_conf * link_conf,struct ieee80211_chanctx_conf * ctx)7592dd4f32aeSBjoern A. Zeeb ath11k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
7593dd4f32aeSBjoern A. Zeeb 				 struct ieee80211_vif *vif,
7594dd4f32aeSBjoern A. Zeeb 				 struct ieee80211_bss_conf *link_conf,
7595dd4f32aeSBjoern A. Zeeb 				 struct ieee80211_chanctx_conf *ctx)
7596dd4f32aeSBjoern A. Zeeb {
7597dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = hw->priv;
7598dd4f32aeSBjoern A. Zeeb 	struct ath11k_base *ab = ar->ab;
7599dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif = (void *)vif->drv_priv;
7600dd4f32aeSBjoern A. Zeeb 	int ret;
7601dd4f32aeSBjoern A. Zeeb 	struct peer_create_params param;
7602dd4f32aeSBjoern A. Zeeb 
7603dd4f32aeSBjoern A. Zeeb 	mutex_lock(&ar->conf_mutex);
7604dd4f32aeSBjoern A. Zeeb 
7605dd4f32aeSBjoern A. Zeeb 	ath11k_dbg(ab, ATH11K_DBG_MAC,
7606*28348caeSBjoern A. Zeeb 		   "chanctx assign ptr %p vdev_id %i\n",
7607dd4f32aeSBjoern A. Zeeb 		   ctx, arvif->vdev_id);
7608dd4f32aeSBjoern A. Zeeb 
7609dd4f32aeSBjoern A. Zeeb 	/* for QCA6390 bss peer must be created before vdev_start */
7610dd4f32aeSBjoern A. Zeeb 	if (ab->hw_params.vdev_start_delay &&
7611dd4f32aeSBjoern A. Zeeb 	    arvif->vdev_type != WMI_VDEV_TYPE_AP &&
7612dd4f32aeSBjoern A. Zeeb 	    arvif->vdev_type != WMI_VDEV_TYPE_MONITOR &&
7613dd4f32aeSBjoern A. Zeeb 	    !ath11k_peer_find_by_vdev_id(ab, arvif->vdev_id)) {
7614dd4f32aeSBjoern A. Zeeb 		memcpy(&arvif->chanctx, ctx, sizeof(*ctx));
7615dd4f32aeSBjoern A. Zeeb 		ret = 0;
7616dd4f32aeSBjoern A. Zeeb 		goto out;
7617dd4f32aeSBjoern A. Zeeb 	}
7618dd4f32aeSBjoern A. Zeeb 
7619dd4f32aeSBjoern A. Zeeb 	if (WARN_ON(arvif->is_started)) {
7620dd4f32aeSBjoern A. Zeeb 		ret = -EBUSY;
7621dd4f32aeSBjoern A. Zeeb 		goto out;
7622dd4f32aeSBjoern A. Zeeb 	}
7623dd4f32aeSBjoern A. Zeeb 
7624dd4f32aeSBjoern A. Zeeb 	if (ab->hw_params.vdev_start_delay &&
7625dd4f32aeSBjoern A. Zeeb 	    arvif->vdev_type != WMI_VDEV_TYPE_AP &&
7626dd4f32aeSBjoern A. Zeeb 	    arvif->vdev_type != WMI_VDEV_TYPE_MONITOR) {
7627dd4f32aeSBjoern A. Zeeb 		param.vdev_id = arvif->vdev_id;
7628dd4f32aeSBjoern A. Zeeb 		param.peer_type = WMI_PEER_TYPE_DEFAULT;
7629dd4f32aeSBjoern A. Zeeb 		param.peer_addr = ar->mac_addr;
7630dd4f32aeSBjoern A. Zeeb 
7631dd4f32aeSBjoern A. Zeeb 		ret = ath11k_peer_create(ar, arvif, NULL, &param);
7632dd4f32aeSBjoern A. Zeeb 		if (ret) {
7633dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ab, "failed to create peer after vdev start delay: %d",
7634dd4f32aeSBjoern A. Zeeb 				    ret);
7635dd4f32aeSBjoern A. Zeeb 			goto out;
7636dd4f32aeSBjoern A. Zeeb 		}
7637dd4f32aeSBjoern A. Zeeb 	}
7638dd4f32aeSBjoern A. Zeeb 
7639dd4f32aeSBjoern A. Zeeb 	if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
7640dd4f32aeSBjoern A. Zeeb 		ret = ath11k_mac_monitor_start(ar);
7641dd4f32aeSBjoern A. Zeeb 		if (ret) {
7642dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "failed to start monitor during vif channel context assignment: %d",
7643dd4f32aeSBjoern A. Zeeb 				    ret);
7644dd4f32aeSBjoern A. Zeeb 			goto out;
7645dd4f32aeSBjoern A. Zeeb 		}
7646dd4f32aeSBjoern A. Zeeb 
7647dd4f32aeSBjoern A. Zeeb 		arvif->is_started = true;
7648dd4f32aeSBjoern A. Zeeb 		goto out;
7649dd4f32aeSBjoern A. Zeeb 	}
7650dd4f32aeSBjoern A. Zeeb 
7651*28348caeSBjoern A. Zeeb 	ret = ath11k_mac_vdev_start(arvif, ctx);
7652dd4f32aeSBjoern A. Zeeb 	if (ret) {
7653dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ab, "failed to start vdev %i addr %pM on freq %d: %d\n",
7654dd4f32aeSBjoern A. Zeeb 			    arvif->vdev_id, vif->addr,
7655dd4f32aeSBjoern A. Zeeb 			    ctx->def.chan->center_freq, ret);
7656dd4f32aeSBjoern A. Zeeb 		goto out;
7657dd4f32aeSBjoern A. Zeeb 	}
7658dd4f32aeSBjoern A. Zeeb 
7659dd4f32aeSBjoern A. Zeeb 	arvif->is_started = true;
7660dd4f32aeSBjoern A. Zeeb 
7661dd4f32aeSBjoern A. Zeeb 	if (arvif->vdev_type != WMI_VDEV_TYPE_MONITOR &&
7662dd4f32aeSBjoern A. Zeeb 	    test_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags)) {
7663dd4f32aeSBjoern A. Zeeb 		ret = ath11k_mac_monitor_start(ar);
7664dd4f32aeSBjoern A. Zeeb 		if (ret) {
7665dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "failed to start monitor during vif channel context assignment: %d",
7666dd4f32aeSBjoern A. Zeeb 				    ret);
7667dd4f32aeSBjoern A. Zeeb 			goto out;
7668dd4f32aeSBjoern A. Zeeb 		}
7669dd4f32aeSBjoern A. Zeeb 	}
7670dd4f32aeSBjoern A. Zeeb 
7671dd4f32aeSBjoern A. Zeeb 	/* TODO: Setup ps and cts/rts protection */
7672dd4f32aeSBjoern A. Zeeb 
7673dd4f32aeSBjoern A. Zeeb 	ret = 0;
7674dd4f32aeSBjoern A. Zeeb 
7675dd4f32aeSBjoern A. Zeeb out:
7676dd4f32aeSBjoern A. Zeeb 	mutex_unlock(&ar->conf_mutex);
7677dd4f32aeSBjoern A. Zeeb 
7678dd4f32aeSBjoern A. Zeeb 	return ret;
7679dd4f32aeSBjoern A. Zeeb }
7680dd4f32aeSBjoern A. Zeeb 
7681dd4f32aeSBjoern A. Zeeb static void
ath11k_mac_op_unassign_vif_chanctx(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_bss_conf * link_conf,struct ieee80211_chanctx_conf * ctx)7682dd4f32aeSBjoern A. Zeeb ath11k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw,
7683dd4f32aeSBjoern A. Zeeb 				   struct ieee80211_vif *vif,
7684dd4f32aeSBjoern A. Zeeb 				   struct ieee80211_bss_conf *link_conf,
7685dd4f32aeSBjoern A. Zeeb 				   struct ieee80211_chanctx_conf *ctx)
7686dd4f32aeSBjoern A. Zeeb {
7687dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = hw->priv;
7688dd4f32aeSBjoern A. Zeeb 	struct ath11k_base *ab = ar->ab;
7689dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif = (void *)vif->drv_priv;
7690*28348caeSBjoern A. Zeeb 	struct ath11k_peer *peer;
7691dd4f32aeSBjoern A. Zeeb 	int ret;
7692dd4f32aeSBjoern A. Zeeb 
7693dd4f32aeSBjoern A. Zeeb 	mutex_lock(&ar->conf_mutex);
7694dd4f32aeSBjoern A. Zeeb 
7695dd4f32aeSBjoern A. Zeeb 	ath11k_dbg(ab, ATH11K_DBG_MAC,
7696*28348caeSBjoern A. Zeeb 		   "chanctx unassign ptr %p vdev_id %i\n",
7697dd4f32aeSBjoern A. Zeeb 		   ctx, arvif->vdev_id);
7698dd4f32aeSBjoern A. Zeeb 
7699dd4f32aeSBjoern A. Zeeb 	WARN_ON(!arvif->is_started);
7700dd4f32aeSBjoern A. Zeeb 
7701dd4f32aeSBjoern A. Zeeb 	if (ab->hw_params.vdev_start_delay &&
7702*28348caeSBjoern A. Zeeb 	    arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
7703*28348caeSBjoern A. Zeeb 		spin_lock_bh(&ab->base_lock);
7704*28348caeSBjoern A. Zeeb 		peer = ath11k_peer_find_by_addr(ab, ar->mac_addr);
7705*28348caeSBjoern A. Zeeb 		spin_unlock_bh(&ab->base_lock);
7706*28348caeSBjoern A. Zeeb 		if (peer)
7707dd4f32aeSBjoern A. Zeeb 			ath11k_peer_delete(ar, arvif->vdev_id, ar->mac_addr);
7708*28348caeSBjoern A. Zeeb 	}
7709dd4f32aeSBjoern A. Zeeb 
7710dd4f32aeSBjoern A. Zeeb 	if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
7711dd4f32aeSBjoern A. Zeeb 		ret = ath11k_mac_monitor_stop(ar);
7712dd4f32aeSBjoern A. Zeeb 		if (ret) {
7713dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "failed to stop monitor during vif channel context unassignment: %d",
7714dd4f32aeSBjoern A. Zeeb 				    ret);
7715dd4f32aeSBjoern A. Zeeb 			mutex_unlock(&ar->conf_mutex);
7716dd4f32aeSBjoern A. Zeeb 			return;
7717dd4f32aeSBjoern A. Zeeb 		}
7718dd4f32aeSBjoern A. Zeeb 
7719dd4f32aeSBjoern A. Zeeb 		arvif->is_started = false;
7720dd4f32aeSBjoern A. Zeeb 		mutex_unlock(&ar->conf_mutex);
7721dd4f32aeSBjoern A. Zeeb 		return;
7722dd4f32aeSBjoern A. Zeeb 	}
7723dd4f32aeSBjoern A. Zeeb 
7724dd4f32aeSBjoern A. Zeeb 	ret = ath11k_mac_vdev_stop(arvif);
7725dd4f32aeSBjoern A. Zeeb 	if (ret)
7726dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ab, "failed to stop vdev %i: %d\n",
7727dd4f32aeSBjoern A. Zeeb 			    arvif->vdev_id, ret);
7728dd4f32aeSBjoern A. Zeeb 
7729dd4f32aeSBjoern A. Zeeb 	arvif->is_started = false;
7730dd4f32aeSBjoern A. Zeeb 
7731dd4f32aeSBjoern A. Zeeb 	if (ab->hw_params.vdev_start_delay &&
7732dd4f32aeSBjoern A. Zeeb 	    arvif->vdev_type == WMI_VDEV_TYPE_STA) {
7733dd4f32aeSBjoern A. Zeeb 		ret = ath11k_peer_delete(ar, arvif->vdev_id, arvif->bssid);
7734dd4f32aeSBjoern A. Zeeb 		if (ret)
7735dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab,
7736dd4f32aeSBjoern A. Zeeb 				    "failed to delete peer %pM for vdev %d: %d\n",
7737dd4f32aeSBjoern A. Zeeb 				    arvif->bssid, arvif->vdev_id, ret);
7738dd4f32aeSBjoern A. Zeeb 		else
7739dd4f32aeSBjoern A. Zeeb 			ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
7740*28348caeSBjoern A. Zeeb 				   "removed peer %pM  vdev %d after vdev stop\n",
7741dd4f32aeSBjoern A. Zeeb 				   arvif->bssid, arvif->vdev_id);
7742dd4f32aeSBjoern A. Zeeb 	}
7743dd4f32aeSBjoern A. Zeeb 
7744dd4f32aeSBjoern A. Zeeb 	if (ab->hw_params.vdev_start_delay &&
7745dd4f32aeSBjoern A. Zeeb 	    arvif->vdev_type == WMI_VDEV_TYPE_MONITOR)
7746dd4f32aeSBjoern A. Zeeb 		ath11k_wmi_vdev_down(ar, arvif->vdev_id);
7747dd4f32aeSBjoern A. Zeeb 
7748dd4f32aeSBjoern A. Zeeb 	if (arvif->vdev_type != WMI_VDEV_TYPE_MONITOR &&
7749dd4f32aeSBjoern A. Zeeb 	    ar->num_started_vdevs == 1 &&
7750dd4f32aeSBjoern A. Zeeb 	    test_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags)) {
7751dd4f32aeSBjoern A. Zeeb 		ret = ath11k_mac_monitor_stop(ar);
7752dd4f32aeSBjoern A. Zeeb 		if (ret)
7753dd4f32aeSBjoern A. Zeeb 			/* continue even if there's an error */
7754dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "failed to stop monitor during vif channel context unassignment: %d",
7755dd4f32aeSBjoern A. Zeeb 				    ret);
7756dd4f32aeSBjoern A. Zeeb 	}
7757dd4f32aeSBjoern A. Zeeb 
7758dd4f32aeSBjoern A. Zeeb 	if (arvif->vdev_type == WMI_VDEV_TYPE_STA)
7759*28348caeSBjoern A. Zeeb 		ath11k_mac_11d_scan_start(ar, arvif->vdev_id);
7760dd4f32aeSBjoern A. Zeeb 
7761dd4f32aeSBjoern A. Zeeb 	mutex_unlock(&ar->conf_mutex);
7762dd4f32aeSBjoern A. Zeeb }
7763dd4f32aeSBjoern A. Zeeb 
7764dd4f32aeSBjoern A. Zeeb static int
ath11k_mac_op_switch_vif_chanctx(struct ieee80211_hw * hw,struct ieee80211_vif_chanctx_switch * vifs,int n_vifs,enum ieee80211_chanctx_switch_mode mode)7765dd4f32aeSBjoern A. Zeeb ath11k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw,
7766dd4f32aeSBjoern A. Zeeb 				 struct ieee80211_vif_chanctx_switch *vifs,
7767dd4f32aeSBjoern A. Zeeb 				 int n_vifs,
7768dd4f32aeSBjoern A. Zeeb 				 enum ieee80211_chanctx_switch_mode mode)
7769dd4f32aeSBjoern A. Zeeb {
7770dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = hw->priv;
7771dd4f32aeSBjoern A. Zeeb 
7772dd4f32aeSBjoern A. Zeeb 	mutex_lock(&ar->conf_mutex);
7773dd4f32aeSBjoern A. Zeeb 
7774dd4f32aeSBjoern A. Zeeb 	ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
7775*28348caeSBjoern A. Zeeb 		   "chanctx switch n_vifs %d mode %d\n",
7776dd4f32aeSBjoern A. Zeeb 		   n_vifs, mode);
7777dd4f32aeSBjoern A. Zeeb 	ath11k_mac_update_vif_chan(ar, vifs, n_vifs);
7778dd4f32aeSBjoern A. Zeeb 
7779dd4f32aeSBjoern A. Zeeb 	mutex_unlock(&ar->conf_mutex);
7780dd4f32aeSBjoern A. Zeeb 
7781dd4f32aeSBjoern A. Zeeb 	return 0;
7782dd4f32aeSBjoern A. Zeeb }
7783dd4f32aeSBjoern A. Zeeb 
7784dd4f32aeSBjoern A. Zeeb static int
ath11k_set_vdev_param_to_all_vifs(struct ath11k * ar,int param,u32 value)7785dd4f32aeSBjoern A. Zeeb ath11k_set_vdev_param_to_all_vifs(struct ath11k *ar, int param, u32 value)
7786dd4f32aeSBjoern A. Zeeb {
7787dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif;
7788dd4f32aeSBjoern A. Zeeb 	int ret = 0;
7789dd4f32aeSBjoern A. Zeeb 
7790dd4f32aeSBjoern A. Zeeb 	mutex_lock(&ar->conf_mutex);
7791dd4f32aeSBjoern A. Zeeb 	list_for_each_entry(arvif, &ar->arvifs, list) {
7792dd4f32aeSBjoern A. Zeeb 		ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "setting mac vdev %d param %d value %d\n",
7793dd4f32aeSBjoern A. Zeeb 			   param, arvif->vdev_id, value);
7794dd4f32aeSBjoern A. Zeeb 
7795dd4f32aeSBjoern A. Zeeb 		ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
7796dd4f32aeSBjoern A. Zeeb 						    param, value);
7797dd4f32aeSBjoern A. Zeeb 		if (ret) {
7798dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "failed to set param %d for vdev %d: %d\n",
7799dd4f32aeSBjoern A. Zeeb 				    param, arvif->vdev_id, ret);
7800dd4f32aeSBjoern A. Zeeb 			break;
7801dd4f32aeSBjoern A. Zeeb 		}
7802dd4f32aeSBjoern A. Zeeb 	}
7803dd4f32aeSBjoern A. Zeeb 	mutex_unlock(&ar->conf_mutex);
7804dd4f32aeSBjoern A. Zeeb 	return ret;
7805dd4f32aeSBjoern A. Zeeb }
7806dd4f32aeSBjoern A. Zeeb 
7807dd4f32aeSBjoern A. Zeeb /* mac80211 stores device specific RTS/Fragmentation threshold value,
7808dd4f32aeSBjoern A. Zeeb  * this is set interface specific to firmware from ath11k driver
7809dd4f32aeSBjoern A. Zeeb  */
ath11k_mac_op_set_rts_threshold(struct ieee80211_hw * hw,u32 value)7810dd4f32aeSBjoern A. Zeeb static int ath11k_mac_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
7811dd4f32aeSBjoern A. Zeeb {
7812dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = hw->priv;
7813dd4f32aeSBjoern A. Zeeb 	int param_id = WMI_VDEV_PARAM_RTS_THRESHOLD;
7814dd4f32aeSBjoern A. Zeeb 
7815dd4f32aeSBjoern A. Zeeb 	return ath11k_set_vdev_param_to_all_vifs(ar, param_id, value);
7816dd4f32aeSBjoern A. Zeeb }
7817dd4f32aeSBjoern A. Zeeb 
ath11k_mac_op_set_frag_threshold(struct ieee80211_hw * hw,u32 value)7818dd4f32aeSBjoern A. Zeeb static int ath11k_mac_op_set_frag_threshold(struct ieee80211_hw *hw, u32 value)
7819dd4f32aeSBjoern A. Zeeb {
7820dd4f32aeSBjoern A. Zeeb 	/* Even though there's a WMI vdev param for fragmentation threshold no
7821dd4f32aeSBjoern A. Zeeb 	 * known firmware actually implements it. Moreover it is not possible to
7822dd4f32aeSBjoern A. Zeeb 	 * rely frame fragmentation to mac80211 because firmware clears the
7823dd4f32aeSBjoern A. Zeeb 	 * "more fragments" bit in frame control making it impossible for remote
7824dd4f32aeSBjoern A. Zeeb 	 * devices to reassemble frames.
7825dd4f32aeSBjoern A. Zeeb 	 *
7826dd4f32aeSBjoern A. Zeeb 	 * Hence implement a dummy callback just to say fragmentation isn't
7827dd4f32aeSBjoern A. Zeeb 	 * supported. This effectively prevents mac80211 from doing frame
7828dd4f32aeSBjoern A. Zeeb 	 * fragmentation in software.
7829dd4f32aeSBjoern A. Zeeb 	 */
7830dd4f32aeSBjoern A. Zeeb 	return -EOPNOTSUPP;
7831dd4f32aeSBjoern A. Zeeb }
7832dd4f32aeSBjoern A. Zeeb 
ath11k_mac_flush_tx_complete(struct ath11k * ar)7833*28348caeSBjoern A. Zeeb static int ath11k_mac_flush_tx_complete(struct ath11k *ar)
7834dd4f32aeSBjoern A. Zeeb {
7835dd4f32aeSBjoern A. Zeeb 	long time_left;
7836*28348caeSBjoern A. Zeeb 	int ret = 0;
7837dd4f32aeSBjoern A. Zeeb 
7838dd4f32aeSBjoern A. Zeeb 	time_left = wait_event_timeout(ar->dp.tx_empty_waitq,
7839dd4f32aeSBjoern A. Zeeb 				       (atomic_read(&ar->dp.num_tx_pending) == 0),
7840dd4f32aeSBjoern A. Zeeb 				       ATH11K_FLUSH_TIMEOUT);
7841*28348caeSBjoern A. Zeeb 	if (time_left == 0) {
7842*28348caeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to flush transmit queue, data pkts pending %d\n",
7843*28348caeSBjoern A. Zeeb 			    atomic_read(&ar->dp.num_tx_pending));
7844*28348caeSBjoern A. Zeeb 		ret = -ETIMEDOUT;
7845*28348caeSBjoern A. Zeeb 	}
7846dd4f32aeSBjoern A. Zeeb 
7847dd4f32aeSBjoern A. Zeeb 	time_left = wait_event_timeout(ar->txmgmt_empty_waitq,
7848dd4f32aeSBjoern A. Zeeb 				       (atomic_read(&ar->num_pending_mgmt_tx) == 0),
7849dd4f32aeSBjoern A. Zeeb 				       ATH11K_FLUSH_TIMEOUT);
7850*28348caeSBjoern A. Zeeb 	if (time_left == 0) {
7851*28348caeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to flush mgmt transmit queue, mgmt pkts pending %d\n",
7852dd4f32aeSBjoern A. Zeeb 			    atomic_read(&ar->num_pending_mgmt_tx));
7853*28348caeSBjoern A. Zeeb 		ret = -ETIMEDOUT;
7854dd4f32aeSBjoern A. Zeeb 	}
7855dd4f32aeSBjoern A. Zeeb 
7856*28348caeSBjoern A. Zeeb 	return ret;
7857*28348caeSBjoern A. Zeeb }
7858*28348caeSBjoern A. Zeeb 
ath11k_mac_wait_tx_complete(struct ath11k * ar)7859*28348caeSBjoern A. Zeeb int ath11k_mac_wait_tx_complete(struct ath11k *ar)
7860dd4f32aeSBjoern A. Zeeb {
7861*28348caeSBjoern A. Zeeb 	ath11k_mac_drain_tx(ar);
7862*28348caeSBjoern A. Zeeb 	return ath11k_mac_flush_tx_complete(ar);
7863*28348caeSBjoern A. Zeeb }
7864dd4f32aeSBjoern A. Zeeb 
ath11k_mac_op_flush(struct ieee80211_hw * hw,struct ieee80211_vif * vif,u32 queues,bool drop)7865*28348caeSBjoern A. Zeeb static void ath11k_mac_op_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
7866*28348caeSBjoern A. Zeeb 				u32 queues, bool drop)
7867*28348caeSBjoern A. Zeeb {
7868*28348caeSBjoern A. Zeeb 	struct ath11k *ar = hw->priv;
7869dd4f32aeSBjoern A. Zeeb 
7870*28348caeSBjoern A. Zeeb 	if (drop)
7871*28348caeSBjoern A. Zeeb 		return;
7872*28348caeSBjoern A. Zeeb 
7873*28348caeSBjoern A. Zeeb 	ath11k_mac_flush_tx_complete(ar);
7874dd4f32aeSBjoern A. Zeeb }
7875dd4f32aeSBjoern A. Zeeb 
7876dd4f32aeSBjoern A. Zeeb static bool
ath11k_mac_has_single_legacy_rate(struct ath11k * ar,enum nl80211_band band,const struct cfg80211_bitrate_mask * mask)7877dd4f32aeSBjoern A. Zeeb ath11k_mac_has_single_legacy_rate(struct ath11k *ar,
7878dd4f32aeSBjoern A. Zeeb 				  enum nl80211_band band,
7879dd4f32aeSBjoern A. Zeeb 				  const struct cfg80211_bitrate_mask *mask)
7880dd4f32aeSBjoern A. Zeeb {
7881dd4f32aeSBjoern A. Zeeb 	int num_rates = 0;
7882dd4f32aeSBjoern A. Zeeb 
7883dd4f32aeSBjoern A. Zeeb 	num_rates = hweight32(mask->control[band].legacy);
7884dd4f32aeSBjoern A. Zeeb 
7885dd4f32aeSBjoern A. Zeeb 	if (ath11k_mac_bitrate_mask_num_ht_rates(ar, band, mask))
7886dd4f32aeSBjoern A. Zeeb 		return false;
7887dd4f32aeSBjoern A. Zeeb 
7888dd4f32aeSBjoern A. Zeeb 	if (ath11k_mac_bitrate_mask_num_vht_rates(ar, band, mask))
7889dd4f32aeSBjoern A. Zeeb 		return false;
7890dd4f32aeSBjoern A. Zeeb 
7891dd4f32aeSBjoern A. Zeeb 	if (ath11k_mac_bitrate_mask_num_he_rates(ar, band, mask))
7892dd4f32aeSBjoern A. Zeeb 		return false;
7893dd4f32aeSBjoern A. Zeeb 
7894dd4f32aeSBjoern A. Zeeb 	return num_rates == 1;
7895dd4f32aeSBjoern A. Zeeb }
7896dd4f32aeSBjoern A. Zeeb 
7897dd4f32aeSBjoern A. Zeeb static __le16
ath11k_mac_get_tx_mcs_map(const struct ieee80211_sta_he_cap * he_cap)7898dd4f32aeSBjoern A. Zeeb ath11k_mac_get_tx_mcs_map(const struct ieee80211_sta_he_cap *he_cap)
7899dd4f32aeSBjoern A. Zeeb {
7900dd4f32aeSBjoern A. Zeeb 	if (he_cap->he_cap_elem.phy_cap_info[0] &
7901dd4f32aeSBjoern A. Zeeb 	    IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)
7902dd4f32aeSBjoern A. Zeeb 		return he_cap->he_mcs_nss_supp.tx_mcs_80p80;
7903dd4f32aeSBjoern A. Zeeb 
7904dd4f32aeSBjoern A. Zeeb 	if (he_cap->he_cap_elem.phy_cap_info[0] &
7905dd4f32aeSBjoern A. Zeeb 	    IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G)
7906dd4f32aeSBjoern A. Zeeb 		return he_cap->he_mcs_nss_supp.tx_mcs_160;
7907dd4f32aeSBjoern A. Zeeb 
7908dd4f32aeSBjoern A. Zeeb 	return he_cap->he_mcs_nss_supp.tx_mcs_80;
7909dd4f32aeSBjoern A. Zeeb }
7910dd4f32aeSBjoern A. Zeeb 
7911dd4f32aeSBjoern A. Zeeb static bool
ath11k_mac_bitrate_mask_get_single_nss(struct ath11k * ar,enum nl80211_band band,const struct cfg80211_bitrate_mask * mask,int * nss)7912dd4f32aeSBjoern A. Zeeb ath11k_mac_bitrate_mask_get_single_nss(struct ath11k *ar,
7913dd4f32aeSBjoern A. Zeeb 				       enum nl80211_band band,
7914dd4f32aeSBjoern A. Zeeb 				       const struct cfg80211_bitrate_mask *mask,
7915dd4f32aeSBjoern A. Zeeb 				       int *nss)
7916dd4f32aeSBjoern A. Zeeb {
7917dd4f32aeSBjoern A. Zeeb 	struct ieee80211_supported_band *sband = &ar->mac.sbands[band];
7918dd4f32aeSBjoern A. Zeeb 	u16 vht_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map);
7919dd4f32aeSBjoern A. Zeeb 	u16 he_mcs_map = 0;
7920dd4f32aeSBjoern A. Zeeb 	u8 ht_nss_mask = 0;
7921dd4f32aeSBjoern A. Zeeb 	u8 vht_nss_mask = 0;
7922dd4f32aeSBjoern A. Zeeb 	u8 he_nss_mask = 0;
7923dd4f32aeSBjoern A. Zeeb 	int i;
7924dd4f32aeSBjoern A. Zeeb 
7925dd4f32aeSBjoern A. Zeeb 	/* No need to consider legacy here. Basic rates are always present
7926dd4f32aeSBjoern A. Zeeb 	 * in bitrate mask
7927dd4f32aeSBjoern A. Zeeb 	 */
7928dd4f32aeSBjoern A. Zeeb 
7929dd4f32aeSBjoern A. Zeeb 	for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++) {
7930dd4f32aeSBjoern A. Zeeb 		if (mask->control[band].ht_mcs[i] == 0)
7931dd4f32aeSBjoern A. Zeeb 			continue;
7932dd4f32aeSBjoern A. Zeeb 		else if (mask->control[band].ht_mcs[i] ==
7933dd4f32aeSBjoern A. Zeeb 			 sband->ht_cap.mcs.rx_mask[i])
7934dd4f32aeSBjoern A. Zeeb 			ht_nss_mask |= BIT(i);
7935dd4f32aeSBjoern A. Zeeb 		else
7936dd4f32aeSBjoern A. Zeeb 			return false;
7937dd4f32aeSBjoern A. Zeeb 	}
7938dd4f32aeSBjoern A. Zeeb 
7939dd4f32aeSBjoern A. Zeeb 	for (i = 0; i < ARRAY_SIZE(mask->control[band].vht_mcs); i++) {
7940dd4f32aeSBjoern A. Zeeb 		if (mask->control[band].vht_mcs[i] == 0)
7941dd4f32aeSBjoern A. Zeeb 			continue;
7942dd4f32aeSBjoern A. Zeeb 		else if (mask->control[band].vht_mcs[i] ==
7943dd4f32aeSBjoern A. Zeeb 			 ath11k_mac_get_max_vht_mcs_map(vht_mcs_map, i))
7944dd4f32aeSBjoern A. Zeeb 			vht_nss_mask |= BIT(i);
7945dd4f32aeSBjoern A. Zeeb 		else
7946dd4f32aeSBjoern A. Zeeb 			return false;
7947dd4f32aeSBjoern A. Zeeb 	}
7948dd4f32aeSBjoern A. Zeeb 
7949dd4f32aeSBjoern A. Zeeb 	he_mcs_map = le16_to_cpu(ath11k_mac_get_tx_mcs_map(&sband->iftype_data->he_cap));
7950dd4f32aeSBjoern A. Zeeb 
7951dd4f32aeSBjoern A. Zeeb 	for (i = 0; i < ARRAY_SIZE(mask->control[band].he_mcs); i++) {
7952dd4f32aeSBjoern A. Zeeb 		if (mask->control[band].he_mcs[i] == 0)
7953dd4f32aeSBjoern A. Zeeb 			continue;
7954dd4f32aeSBjoern A. Zeeb 
7955dd4f32aeSBjoern A. Zeeb 		if (mask->control[band].he_mcs[i] ==
7956dd4f32aeSBjoern A. Zeeb 		    ath11k_mac_get_max_he_mcs_map(he_mcs_map, i))
7957dd4f32aeSBjoern A. Zeeb 			he_nss_mask |= BIT(i);
7958dd4f32aeSBjoern A. Zeeb 		else
7959dd4f32aeSBjoern A. Zeeb 			return false;
7960dd4f32aeSBjoern A. Zeeb 	}
7961dd4f32aeSBjoern A. Zeeb 
7962dd4f32aeSBjoern A. Zeeb 	if (ht_nss_mask != vht_nss_mask || ht_nss_mask != he_nss_mask)
7963dd4f32aeSBjoern A. Zeeb 		return false;
7964dd4f32aeSBjoern A. Zeeb 
7965dd4f32aeSBjoern A. Zeeb 	if (ht_nss_mask == 0)
7966dd4f32aeSBjoern A. Zeeb 		return false;
7967dd4f32aeSBjoern A. Zeeb 
7968dd4f32aeSBjoern A. Zeeb 	if (BIT(fls(ht_nss_mask)) - 1 != ht_nss_mask)
7969dd4f32aeSBjoern A. Zeeb 		return false;
7970dd4f32aeSBjoern A. Zeeb 
7971dd4f32aeSBjoern A. Zeeb 	*nss = fls(ht_nss_mask);
7972dd4f32aeSBjoern A. Zeeb 
7973dd4f32aeSBjoern A. Zeeb 	return true;
7974dd4f32aeSBjoern A. Zeeb }
7975dd4f32aeSBjoern A. Zeeb 
7976dd4f32aeSBjoern A. Zeeb static int
ath11k_mac_get_single_legacy_rate(struct ath11k * ar,enum nl80211_band band,const struct cfg80211_bitrate_mask * mask,u32 * rate,u8 * nss)7977dd4f32aeSBjoern A. Zeeb ath11k_mac_get_single_legacy_rate(struct ath11k *ar,
7978dd4f32aeSBjoern A. Zeeb 				  enum nl80211_band band,
7979dd4f32aeSBjoern A. Zeeb 				  const struct cfg80211_bitrate_mask *mask,
7980dd4f32aeSBjoern A. Zeeb 				  u32 *rate, u8 *nss)
7981dd4f32aeSBjoern A. Zeeb {
7982dd4f32aeSBjoern A. Zeeb 	int rate_idx;
7983dd4f32aeSBjoern A. Zeeb 	u16 bitrate;
7984dd4f32aeSBjoern A. Zeeb 	u8 preamble;
7985dd4f32aeSBjoern A. Zeeb 	u8 hw_rate;
7986dd4f32aeSBjoern A. Zeeb 
7987dd4f32aeSBjoern A. Zeeb 	if (hweight32(mask->control[band].legacy) != 1)
7988dd4f32aeSBjoern A. Zeeb 		return -EINVAL;
7989dd4f32aeSBjoern A. Zeeb 
7990dd4f32aeSBjoern A. Zeeb 	rate_idx = ffs(mask->control[band].legacy) - 1;
7991dd4f32aeSBjoern A. Zeeb 
7992dd4f32aeSBjoern A. Zeeb 	if (band == NL80211_BAND_5GHZ || band == NL80211_BAND_6GHZ)
7993dd4f32aeSBjoern A. Zeeb 		rate_idx += ATH11K_MAC_FIRST_OFDM_RATE_IDX;
7994dd4f32aeSBjoern A. Zeeb 
7995dd4f32aeSBjoern A. Zeeb 	hw_rate = ath11k_legacy_rates[rate_idx].hw_value;
7996dd4f32aeSBjoern A. Zeeb 	bitrate = ath11k_legacy_rates[rate_idx].bitrate;
7997dd4f32aeSBjoern A. Zeeb 
7998dd4f32aeSBjoern A. Zeeb 	if (ath11k_mac_bitrate_is_cck(bitrate))
7999dd4f32aeSBjoern A. Zeeb 		preamble = WMI_RATE_PREAMBLE_CCK;
8000dd4f32aeSBjoern A. Zeeb 	else
8001dd4f32aeSBjoern A. Zeeb 		preamble = WMI_RATE_PREAMBLE_OFDM;
8002dd4f32aeSBjoern A. Zeeb 
8003dd4f32aeSBjoern A. Zeeb 	*nss = 1;
8004dd4f32aeSBjoern A. Zeeb 	*rate = ATH11K_HW_RATE_CODE(hw_rate, 0, preamble);
8005dd4f32aeSBjoern A. Zeeb 
8006dd4f32aeSBjoern A. Zeeb 	return 0;
8007dd4f32aeSBjoern A. Zeeb }
8008dd4f32aeSBjoern A. Zeeb 
8009dd4f32aeSBjoern A. Zeeb static int
ath11k_mac_set_fixed_rate_gi_ltf(struct ath11k_vif * arvif,u8 he_gi,u8 he_ltf)8010dd4f32aeSBjoern A. Zeeb ath11k_mac_set_fixed_rate_gi_ltf(struct ath11k_vif *arvif, u8 he_gi, u8 he_ltf)
8011dd4f32aeSBjoern A. Zeeb {
8012dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = arvif->ar;
8013dd4f32aeSBjoern A. Zeeb 	int ret;
8014dd4f32aeSBjoern A. Zeeb 
8015dd4f32aeSBjoern A. Zeeb 	/* 0.8 = 0, 1.6 = 2 and 3.2 = 3. */
8016dd4f32aeSBjoern A. Zeeb 	if (he_gi && he_gi != 0xFF)
8017dd4f32aeSBjoern A. Zeeb 		he_gi += 1;
8018dd4f32aeSBjoern A. Zeeb 
8019dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
8020dd4f32aeSBjoern A. Zeeb 					    WMI_VDEV_PARAM_SGI, he_gi);
8021dd4f32aeSBjoern A. Zeeb 	if (ret) {
8022dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to set he gi %d: %d\n",
8023dd4f32aeSBjoern A. Zeeb 			    he_gi, ret);
8024dd4f32aeSBjoern A. Zeeb 		return ret;
8025dd4f32aeSBjoern A. Zeeb 	}
8026dd4f32aeSBjoern A. Zeeb 	/* start from 1 */
8027dd4f32aeSBjoern A. Zeeb 	if (he_ltf != 0xFF)
8028dd4f32aeSBjoern A. Zeeb 		he_ltf += 1;
8029dd4f32aeSBjoern A. Zeeb 
8030dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
8031dd4f32aeSBjoern A. Zeeb 					    WMI_VDEV_PARAM_HE_LTF, he_ltf);
8032dd4f32aeSBjoern A. Zeeb 	if (ret) {
8033dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to set he ltf %d: %d\n",
8034dd4f32aeSBjoern A. Zeeb 			    he_ltf, ret);
8035dd4f32aeSBjoern A. Zeeb 		return ret;
8036dd4f32aeSBjoern A. Zeeb 	}
8037dd4f32aeSBjoern A. Zeeb 
8038dd4f32aeSBjoern A. Zeeb 	return 0;
8039dd4f32aeSBjoern A. Zeeb }
8040dd4f32aeSBjoern A. Zeeb 
8041dd4f32aeSBjoern A. Zeeb static int
ath11k_mac_set_auto_rate_gi_ltf(struct ath11k_vif * arvif,u16 he_gi,u8 he_ltf)8042dd4f32aeSBjoern A. Zeeb ath11k_mac_set_auto_rate_gi_ltf(struct ath11k_vif *arvif, u16 he_gi, u8 he_ltf)
8043dd4f32aeSBjoern A. Zeeb {
8044dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = arvif->ar;
8045dd4f32aeSBjoern A. Zeeb 	int ret;
8046dd4f32aeSBjoern A. Zeeb 	u32 he_ar_gi_ltf;
8047dd4f32aeSBjoern A. Zeeb 
8048dd4f32aeSBjoern A. Zeeb 	if (he_gi != 0xFF) {
8049dd4f32aeSBjoern A. Zeeb 		switch (he_gi) {
8050dd4f32aeSBjoern A. Zeeb 		case NL80211_RATE_INFO_HE_GI_0_8:
8051dd4f32aeSBjoern A. Zeeb 			he_gi = WMI_AUTORATE_800NS_GI;
8052dd4f32aeSBjoern A. Zeeb 			break;
8053dd4f32aeSBjoern A. Zeeb 		case NL80211_RATE_INFO_HE_GI_1_6:
8054dd4f32aeSBjoern A. Zeeb 			he_gi = WMI_AUTORATE_1600NS_GI;
8055dd4f32aeSBjoern A. Zeeb 			break;
8056dd4f32aeSBjoern A. Zeeb 		case NL80211_RATE_INFO_HE_GI_3_2:
8057dd4f32aeSBjoern A. Zeeb 			he_gi = WMI_AUTORATE_3200NS_GI;
8058dd4f32aeSBjoern A. Zeeb 			break;
8059dd4f32aeSBjoern A. Zeeb 		default:
8060dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "invalid he gi: %d\n", he_gi);
8061dd4f32aeSBjoern A. Zeeb 			return -EINVAL;
8062dd4f32aeSBjoern A. Zeeb 		}
8063dd4f32aeSBjoern A. Zeeb 	}
8064dd4f32aeSBjoern A. Zeeb 
8065dd4f32aeSBjoern A. Zeeb 	if (he_ltf != 0xFF) {
8066dd4f32aeSBjoern A. Zeeb 		switch (he_ltf) {
8067dd4f32aeSBjoern A. Zeeb 		case NL80211_RATE_INFO_HE_1XLTF:
8068dd4f32aeSBjoern A. Zeeb 			he_ltf = WMI_HE_AUTORATE_LTF_1X;
8069dd4f32aeSBjoern A. Zeeb 			break;
8070dd4f32aeSBjoern A. Zeeb 		case NL80211_RATE_INFO_HE_2XLTF:
8071dd4f32aeSBjoern A. Zeeb 			he_ltf = WMI_HE_AUTORATE_LTF_2X;
8072dd4f32aeSBjoern A. Zeeb 			break;
8073dd4f32aeSBjoern A. Zeeb 		case NL80211_RATE_INFO_HE_4XLTF:
8074dd4f32aeSBjoern A. Zeeb 			he_ltf = WMI_HE_AUTORATE_LTF_4X;
8075dd4f32aeSBjoern A. Zeeb 			break;
8076dd4f32aeSBjoern A. Zeeb 		default:
8077dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "invalid he ltf: %d\n", he_ltf);
8078dd4f32aeSBjoern A. Zeeb 			return -EINVAL;
8079dd4f32aeSBjoern A. Zeeb 		}
8080dd4f32aeSBjoern A. Zeeb 	}
8081dd4f32aeSBjoern A. Zeeb 
8082dd4f32aeSBjoern A. Zeeb 	he_ar_gi_ltf = he_gi | he_ltf;
8083dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
8084dd4f32aeSBjoern A. Zeeb 					    WMI_VDEV_PARAM_AUTORATE_MISC_CFG,
8085dd4f32aeSBjoern A. Zeeb 					    he_ar_gi_ltf);
8086dd4f32aeSBjoern A. Zeeb 	if (ret) {
8087dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab,
8088dd4f32aeSBjoern A. Zeeb 			    "failed to set he autorate gi %u ltf %u: %d\n",
8089dd4f32aeSBjoern A. Zeeb 			    he_gi, he_ltf, ret);
8090dd4f32aeSBjoern A. Zeeb 		return ret;
8091dd4f32aeSBjoern A. Zeeb 	}
8092dd4f32aeSBjoern A. Zeeb 
8093dd4f32aeSBjoern A. Zeeb 	return 0;
8094dd4f32aeSBjoern A. Zeeb }
8095dd4f32aeSBjoern A. Zeeb 
ath11k_mac_set_rate_params(struct ath11k_vif * arvif,u32 rate,u8 nss,u8 sgi,u8 ldpc,u8 he_gi,u8 he_ltf,bool he_fixed_rate)8096dd4f32aeSBjoern A. Zeeb static int ath11k_mac_set_rate_params(struct ath11k_vif *arvif,
8097dd4f32aeSBjoern A. Zeeb 				      u32 rate, u8 nss, u8 sgi, u8 ldpc,
8098dd4f32aeSBjoern A. Zeeb 				      u8 he_gi, u8 he_ltf, bool he_fixed_rate)
8099dd4f32aeSBjoern A. Zeeb {
8100dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = arvif->ar;
8101dd4f32aeSBjoern A. Zeeb 	u32 vdev_param;
8102dd4f32aeSBjoern A. Zeeb 	int ret;
8103dd4f32aeSBjoern A. Zeeb 
8104dd4f32aeSBjoern A. Zeeb 	lockdep_assert_held(&ar->conf_mutex);
8105dd4f32aeSBjoern A. Zeeb 
8106dd4f32aeSBjoern A. Zeeb 	ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
8107*28348caeSBjoern A. Zeeb 		   "set rate params vdev %i rate 0x%02x nss 0x%02x sgi 0x%02x ldpc 0x%02x he_gi 0x%02x he_ltf 0x%02x he_fixed_rate %d\n",
8108dd4f32aeSBjoern A. Zeeb 		   arvif->vdev_id, rate, nss, sgi, ldpc, he_gi,
8109dd4f32aeSBjoern A. Zeeb 		   he_ltf, he_fixed_rate);
8110dd4f32aeSBjoern A. Zeeb 
8111dd4f32aeSBjoern A. Zeeb 	if (!arvif->vif->bss_conf.he_support) {
8112dd4f32aeSBjoern A. Zeeb 		vdev_param = WMI_VDEV_PARAM_FIXED_RATE;
8113dd4f32aeSBjoern A. Zeeb 		ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
8114dd4f32aeSBjoern A. Zeeb 						    vdev_param, rate);
8115dd4f32aeSBjoern A. Zeeb 		if (ret) {
8116dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "failed to set fixed rate param 0x%02x: %d\n",
8117dd4f32aeSBjoern A. Zeeb 				    rate, ret);
8118dd4f32aeSBjoern A. Zeeb 			return ret;
8119dd4f32aeSBjoern A. Zeeb 		}
8120dd4f32aeSBjoern A. Zeeb 	}
8121dd4f32aeSBjoern A. Zeeb 
8122dd4f32aeSBjoern A. Zeeb 	vdev_param = WMI_VDEV_PARAM_NSS;
8123dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
8124dd4f32aeSBjoern A. Zeeb 					    vdev_param, nss);
8125dd4f32aeSBjoern A. Zeeb 	if (ret) {
8126dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to set nss param %d: %d\n",
8127dd4f32aeSBjoern A. Zeeb 			    nss, ret);
8128dd4f32aeSBjoern A. Zeeb 		return ret;
8129dd4f32aeSBjoern A. Zeeb 	}
8130dd4f32aeSBjoern A. Zeeb 
8131dd4f32aeSBjoern A. Zeeb 	vdev_param = WMI_VDEV_PARAM_LDPC;
8132dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
8133dd4f32aeSBjoern A. Zeeb 					    vdev_param, ldpc);
8134dd4f32aeSBjoern A. Zeeb 	if (ret) {
8135dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to set ldpc param %d: %d\n",
8136dd4f32aeSBjoern A. Zeeb 			    ldpc, ret);
8137dd4f32aeSBjoern A. Zeeb 		return ret;
8138dd4f32aeSBjoern A. Zeeb 	}
8139dd4f32aeSBjoern A. Zeeb 
8140dd4f32aeSBjoern A. Zeeb 	if (arvif->vif->bss_conf.he_support) {
8141dd4f32aeSBjoern A. Zeeb 		if (he_fixed_rate) {
8142dd4f32aeSBjoern A. Zeeb 			ret = ath11k_mac_set_fixed_rate_gi_ltf(arvif, he_gi,
8143dd4f32aeSBjoern A. Zeeb 							       he_ltf);
8144dd4f32aeSBjoern A. Zeeb 			if (ret) {
8145dd4f32aeSBjoern A. Zeeb 				ath11k_warn(ar->ab, "failed to set fixed rate gi ltf: %d\n",
8146dd4f32aeSBjoern A. Zeeb 					    ret);
8147dd4f32aeSBjoern A. Zeeb 				return ret;
8148dd4f32aeSBjoern A. Zeeb 			}
8149dd4f32aeSBjoern A. Zeeb 		} else {
8150dd4f32aeSBjoern A. Zeeb 			ret = ath11k_mac_set_auto_rate_gi_ltf(arvif, he_gi,
8151dd4f32aeSBjoern A. Zeeb 							      he_ltf);
8152dd4f32aeSBjoern A. Zeeb 			if (ret) {
8153dd4f32aeSBjoern A. Zeeb 				ath11k_warn(ar->ab, "failed to set auto rate gi ltf: %d\n",
8154dd4f32aeSBjoern A. Zeeb 					    ret);
8155dd4f32aeSBjoern A. Zeeb 				return ret;
8156dd4f32aeSBjoern A. Zeeb 			}
8157dd4f32aeSBjoern A. Zeeb 		}
8158dd4f32aeSBjoern A. Zeeb 	} else {
8159dd4f32aeSBjoern A. Zeeb 		vdev_param = WMI_VDEV_PARAM_SGI;
8160dd4f32aeSBjoern A. Zeeb 		ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
8161dd4f32aeSBjoern A. Zeeb 						    vdev_param, sgi);
8162dd4f32aeSBjoern A. Zeeb 		if (ret) {
8163dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "failed to set sgi param %d: %d\n",
8164dd4f32aeSBjoern A. Zeeb 				    sgi, ret);
8165dd4f32aeSBjoern A. Zeeb 			return ret;
8166dd4f32aeSBjoern A. Zeeb 		}
8167dd4f32aeSBjoern A. Zeeb 	}
8168dd4f32aeSBjoern A. Zeeb 
8169dd4f32aeSBjoern A. Zeeb 	return 0;
8170dd4f32aeSBjoern A. Zeeb }
8171dd4f32aeSBjoern A. Zeeb 
8172dd4f32aeSBjoern A. Zeeb static bool
ath11k_mac_vht_mcs_range_present(struct ath11k * ar,enum nl80211_band band,const struct cfg80211_bitrate_mask * mask)8173dd4f32aeSBjoern A. Zeeb ath11k_mac_vht_mcs_range_present(struct ath11k *ar,
8174dd4f32aeSBjoern A. Zeeb 				 enum nl80211_band band,
8175dd4f32aeSBjoern A. Zeeb 				 const struct cfg80211_bitrate_mask *mask)
8176dd4f32aeSBjoern A. Zeeb {
8177dd4f32aeSBjoern A. Zeeb 	int i;
8178dd4f32aeSBjoern A. Zeeb 	u16 vht_mcs;
8179dd4f32aeSBjoern A. Zeeb 
8180dd4f32aeSBjoern A. Zeeb 	for (i = 0; i < NL80211_VHT_NSS_MAX; i++) {
8181dd4f32aeSBjoern A. Zeeb 		vht_mcs = mask->control[band].vht_mcs[i];
8182dd4f32aeSBjoern A. Zeeb 
8183dd4f32aeSBjoern A. Zeeb 		switch (vht_mcs) {
8184dd4f32aeSBjoern A. Zeeb 		case 0:
8185dd4f32aeSBjoern A. Zeeb 		case BIT(8) - 1:
8186dd4f32aeSBjoern A. Zeeb 		case BIT(9) - 1:
8187dd4f32aeSBjoern A. Zeeb 		case BIT(10) - 1:
8188dd4f32aeSBjoern A. Zeeb 			break;
8189dd4f32aeSBjoern A. Zeeb 		default:
8190dd4f32aeSBjoern A. Zeeb 			return false;
8191dd4f32aeSBjoern A. Zeeb 		}
8192dd4f32aeSBjoern A. Zeeb 	}
8193dd4f32aeSBjoern A. Zeeb 
8194dd4f32aeSBjoern A. Zeeb 	return true;
8195dd4f32aeSBjoern A. Zeeb }
8196dd4f32aeSBjoern A. Zeeb 
8197dd4f32aeSBjoern A. Zeeb static bool
ath11k_mac_he_mcs_range_present(struct ath11k * ar,enum nl80211_band band,const struct cfg80211_bitrate_mask * mask)8198dd4f32aeSBjoern A. Zeeb ath11k_mac_he_mcs_range_present(struct ath11k *ar,
8199dd4f32aeSBjoern A. Zeeb 				enum nl80211_band band,
8200dd4f32aeSBjoern A. Zeeb 				const struct cfg80211_bitrate_mask *mask)
8201dd4f32aeSBjoern A. Zeeb {
8202dd4f32aeSBjoern A. Zeeb 	int i;
8203dd4f32aeSBjoern A. Zeeb 	u16 he_mcs;
8204dd4f32aeSBjoern A. Zeeb 
8205dd4f32aeSBjoern A. Zeeb 	for (i = 0; i < NL80211_HE_NSS_MAX; i++) {
8206dd4f32aeSBjoern A. Zeeb 		he_mcs = mask->control[band].he_mcs[i];
8207dd4f32aeSBjoern A. Zeeb 
8208dd4f32aeSBjoern A. Zeeb 		switch (he_mcs) {
8209dd4f32aeSBjoern A. Zeeb 		case 0:
8210dd4f32aeSBjoern A. Zeeb 		case BIT(8) - 1:
8211dd4f32aeSBjoern A. Zeeb 		case BIT(10) - 1:
8212dd4f32aeSBjoern A. Zeeb 		case BIT(12) - 1:
8213dd4f32aeSBjoern A. Zeeb 			break;
8214dd4f32aeSBjoern A. Zeeb 		default:
8215dd4f32aeSBjoern A. Zeeb 			return false;
8216dd4f32aeSBjoern A. Zeeb 		}
8217dd4f32aeSBjoern A. Zeeb 	}
8218dd4f32aeSBjoern A. Zeeb 
8219dd4f32aeSBjoern A. Zeeb 	return true;
8220dd4f32aeSBjoern A. Zeeb }
8221dd4f32aeSBjoern A. Zeeb 
ath11k_mac_set_bitrate_mask_iter(void * data,struct ieee80211_sta * sta)8222dd4f32aeSBjoern A. Zeeb static void ath11k_mac_set_bitrate_mask_iter(void *data,
8223dd4f32aeSBjoern A. Zeeb 					     struct ieee80211_sta *sta)
8224dd4f32aeSBjoern A. Zeeb {
8225dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif = data;
8226dd4f32aeSBjoern A. Zeeb 	struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
8227dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = arvif->ar;
8228dd4f32aeSBjoern A. Zeeb 
8229dd4f32aeSBjoern A. Zeeb 	spin_lock_bh(&ar->data_lock);
8230dd4f32aeSBjoern A. Zeeb 	arsta->changed |= IEEE80211_RC_SUPP_RATES_CHANGED;
8231dd4f32aeSBjoern A. Zeeb 	spin_unlock_bh(&ar->data_lock);
8232dd4f32aeSBjoern A. Zeeb 
8233dd4f32aeSBjoern A. Zeeb 	ieee80211_queue_work(ar->hw, &arsta->update_wk);
8234dd4f32aeSBjoern A. Zeeb }
8235dd4f32aeSBjoern A. Zeeb 
ath11k_mac_disable_peer_fixed_rate(void * data,struct ieee80211_sta * sta)8236dd4f32aeSBjoern A. Zeeb static void ath11k_mac_disable_peer_fixed_rate(void *data,
8237dd4f32aeSBjoern A. Zeeb 					       struct ieee80211_sta *sta)
8238dd4f32aeSBjoern A. Zeeb {
8239dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif = data;
8240dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = arvif->ar;
8241dd4f32aeSBjoern A. Zeeb 	int ret;
8242dd4f32aeSBjoern A. Zeeb 
8243dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_set_peer_param(ar, sta->addr,
8244dd4f32aeSBjoern A. Zeeb 					arvif->vdev_id,
8245dd4f32aeSBjoern A. Zeeb 					WMI_PEER_PARAM_FIXED_RATE,
8246dd4f32aeSBjoern A. Zeeb 					WMI_FIXED_RATE_NONE);
8247dd4f32aeSBjoern A. Zeeb 	if (ret)
8248dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab,
8249dd4f32aeSBjoern A. Zeeb 			    "failed to disable peer fixed rate for STA %pM ret %d\n",
8250dd4f32aeSBjoern A. Zeeb 			    sta->addr, ret);
8251dd4f32aeSBjoern A. Zeeb }
8252dd4f32aeSBjoern A. Zeeb 
8253dd4f32aeSBjoern A. Zeeb static bool
ath11k_mac_validate_vht_he_fixed_rate_settings(struct ath11k * ar,enum nl80211_band band,const struct cfg80211_bitrate_mask * mask)8254dd4f32aeSBjoern A. Zeeb ath11k_mac_validate_vht_he_fixed_rate_settings(struct ath11k *ar, enum nl80211_band band,
8255dd4f32aeSBjoern A. Zeeb 					       const struct cfg80211_bitrate_mask *mask)
8256dd4f32aeSBjoern A. Zeeb {
8257dd4f32aeSBjoern A. Zeeb 	bool he_fixed_rate = false, vht_fixed_rate = false;
8258*28348caeSBjoern A. Zeeb 	struct ath11k_peer *peer;
8259dd4f32aeSBjoern A. Zeeb 	const u16 *vht_mcs_mask, *he_mcs_mask;
8260*28348caeSBjoern A. Zeeb 	struct ieee80211_link_sta *deflink;
8261dd4f32aeSBjoern A. Zeeb 	u8 vht_nss, he_nss;
8262dd4f32aeSBjoern A. Zeeb 	bool ret = true;
8263dd4f32aeSBjoern A. Zeeb 
8264dd4f32aeSBjoern A. Zeeb 	vht_mcs_mask = mask->control[band].vht_mcs;
8265dd4f32aeSBjoern A. Zeeb 	he_mcs_mask = mask->control[band].he_mcs;
8266dd4f32aeSBjoern A. Zeeb 
8267dd4f32aeSBjoern A. Zeeb 	if (ath11k_mac_bitrate_mask_num_vht_rates(ar, band, mask) == 1)
8268dd4f32aeSBjoern A. Zeeb 		vht_fixed_rate = true;
8269dd4f32aeSBjoern A. Zeeb 
8270dd4f32aeSBjoern A. Zeeb 	if (ath11k_mac_bitrate_mask_num_he_rates(ar, band, mask) == 1)
8271dd4f32aeSBjoern A. Zeeb 		he_fixed_rate = true;
8272dd4f32aeSBjoern A. Zeeb 
8273dd4f32aeSBjoern A. Zeeb 	if (!vht_fixed_rate && !he_fixed_rate)
8274dd4f32aeSBjoern A. Zeeb 		return true;
8275dd4f32aeSBjoern A. Zeeb 
8276dd4f32aeSBjoern A. Zeeb 	vht_nss = ath11k_mac_max_vht_nss(vht_mcs_mask);
8277dd4f32aeSBjoern A. Zeeb 	he_nss =  ath11k_mac_max_he_nss(he_mcs_mask);
8278dd4f32aeSBjoern A. Zeeb 
8279dd4f32aeSBjoern A. Zeeb 	rcu_read_lock();
8280dd4f32aeSBjoern A. Zeeb 	spin_lock_bh(&ar->ab->base_lock);
8281*28348caeSBjoern A. Zeeb 	list_for_each_entry(peer, &ar->ab->peers, list) {
8282dd4f32aeSBjoern A. Zeeb 		if (peer->sta) {
8283*28348caeSBjoern A. Zeeb 			deflink = &peer->sta->deflink;
8284*28348caeSBjoern A. Zeeb 
8285*28348caeSBjoern A. Zeeb 			if (vht_fixed_rate && (!deflink->vht_cap.vht_supported ||
8286*28348caeSBjoern A. Zeeb 					       deflink->rx_nss < vht_nss)) {
8287dd4f32aeSBjoern A. Zeeb 				ret = false;
8288dd4f32aeSBjoern A. Zeeb 				goto out;
8289dd4f32aeSBjoern A. Zeeb 			}
8290*28348caeSBjoern A. Zeeb 
8291*28348caeSBjoern A. Zeeb 			if (he_fixed_rate && (!deflink->he_cap.has_he ||
8292*28348caeSBjoern A. Zeeb 					      deflink->rx_nss < he_nss)) {
8293dd4f32aeSBjoern A. Zeeb 				ret = false;
8294dd4f32aeSBjoern A. Zeeb 				goto out;
8295dd4f32aeSBjoern A. Zeeb 			}
8296dd4f32aeSBjoern A. Zeeb 		}
8297dd4f32aeSBjoern A. Zeeb 	}
8298dd4f32aeSBjoern A. Zeeb 
8299dd4f32aeSBjoern A. Zeeb out:
8300dd4f32aeSBjoern A. Zeeb 	spin_unlock_bh(&ar->ab->base_lock);
8301dd4f32aeSBjoern A. Zeeb 	rcu_read_unlock();
8302dd4f32aeSBjoern A. Zeeb 	return ret;
8303dd4f32aeSBjoern A. Zeeb }
8304dd4f32aeSBjoern A. Zeeb 
8305dd4f32aeSBjoern A. Zeeb static int
ath11k_mac_op_set_bitrate_mask(struct ieee80211_hw * hw,struct ieee80211_vif * vif,const struct cfg80211_bitrate_mask * mask)8306dd4f32aeSBjoern A. Zeeb ath11k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
8307dd4f32aeSBjoern A. Zeeb 			       struct ieee80211_vif *vif,
8308dd4f32aeSBjoern A. Zeeb 			       const struct cfg80211_bitrate_mask *mask)
8309dd4f32aeSBjoern A. Zeeb {
8310dd4f32aeSBjoern A. Zeeb 	struct ath11k_vif *arvif = (void *)vif->drv_priv;
8311dd4f32aeSBjoern A. Zeeb 	struct cfg80211_chan_def def;
8312*28348caeSBjoern A. Zeeb 	struct ath11k_pdev_cap *cap;
8313dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = arvif->ar;
8314dd4f32aeSBjoern A. Zeeb 	enum nl80211_band band;
8315dd4f32aeSBjoern A. Zeeb 	const u8 *ht_mcs_mask;
8316dd4f32aeSBjoern A. Zeeb 	const u16 *vht_mcs_mask;
8317dd4f32aeSBjoern A. Zeeb 	const u16 *he_mcs_mask;
8318dd4f32aeSBjoern A. Zeeb 	u8 he_ltf = 0;
8319dd4f32aeSBjoern A. Zeeb 	u8 he_gi = 0;
8320dd4f32aeSBjoern A. Zeeb 	u32 rate;
8321dd4f32aeSBjoern A. Zeeb 	u8 nss;
8322dd4f32aeSBjoern A. Zeeb 	u8 sgi;
8323dd4f32aeSBjoern A. Zeeb 	u8 ldpc;
8324dd4f32aeSBjoern A. Zeeb 	int single_nss;
8325dd4f32aeSBjoern A. Zeeb 	int ret;
8326dd4f32aeSBjoern A. Zeeb 	int num_rates;
8327dd4f32aeSBjoern A. Zeeb 	bool he_fixed_rate = false;
8328dd4f32aeSBjoern A. Zeeb 
8329dd4f32aeSBjoern A. Zeeb 	if (ath11k_mac_vif_chan(vif, &def))
8330dd4f32aeSBjoern A. Zeeb 		return -EPERM;
8331dd4f32aeSBjoern A. Zeeb 
8332dd4f32aeSBjoern A. Zeeb 	band = def.chan->band;
8333*28348caeSBjoern A. Zeeb 	cap = &ar->pdev->cap;
8334dd4f32aeSBjoern A. Zeeb 	ht_mcs_mask = mask->control[band].ht_mcs;
8335dd4f32aeSBjoern A. Zeeb 	vht_mcs_mask = mask->control[band].vht_mcs;
8336dd4f32aeSBjoern A. Zeeb 	he_mcs_mask = mask->control[band].he_mcs;
8337*28348caeSBjoern A. Zeeb 	ldpc = !!(cap->band[band].ht_cap_info & WMI_HT_CAP_TX_LDPC);
8338dd4f32aeSBjoern A. Zeeb 
8339dd4f32aeSBjoern A. Zeeb 	sgi = mask->control[band].gi;
8340dd4f32aeSBjoern A. Zeeb 	if (sgi == NL80211_TXRATE_FORCE_LGI)
8341dd4f32aeSBjoern A. Zeeb 		return -EINVAL;
8342dd4f32aeSBjoern A. Zeeb 
8343dd4f32aeSBjoern A. Zeeb 	he_gi = mask->control[band].he_gi;
8344dd4f32aeSBjoern A. Zeeb 	he_ltf = mask->control[band].he_ltf;
8345dd4f32aeSBjoern A. Zeeb 
8346dd4f32aeSBjoern A. Zeeb 	/* mac80211 doesn't support sending a fixed HT/VHT MCS alone, rather it
8347dd4f32aeSBjoern A. Zeeb 	 * requires passing at least one of used basic rates along with them.
8348dd4f32aeSBjoern A. Zeeb 	 * Fixed rate setting across different preambles(legacy, HT, VHT) is
8349dd4f32aeSBjoern A. Zeeb 	 * not supported by the FW. Hence use of FIXED_RATE vdev param is not
8350dd4f32aeSBjoern A. Zeeb 	 * suitable for setting single HT/VHT rates.
8351dd4f32aeSBjoern A. Zeeb 	 * But, there could be a single basic rate passed from userspace which
8352dd4f32aeSBjoern A. Zeeb 	 * can be done through the FIXED_RATE param.
8353dd4f32aeSBjoern A. Zeeb 	 */
8354dd4f32aeSBjoern A. Zeeb 	if (ath11k_mac_has_single_legacy_rate(ar, band, mask)) {
8355dd4f32aeSBjoern A. Zeeb 		ret = ath11k_mac_get_single_legacy_rate(ar, band, mask, &rate,
8356dd4f32aeSBjoern A. Zeeb 							&nss);
8357dd4f32aeSBjoern A. Zeeb 		if (ret) {
8358dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "failed to get single legacy rate for vdev %i: %d\n",
8359dd4f32aeSBjoern A. Zeeb 				    arvif->vdev_id, ret);
8360dd4f32aeSBjoern A. Zeeb 			return ret;
8361dd4f32aeSBjoern A. Zeeb 		}
8362dd4f32aeSBjoern A. Zeeb 		ieee80211_iterate_stations_atomic(ar->hw,
8363dd4f32aeSBjoern A. Zeeb 						  ath11k_mac_disable_peer_fixed_rate,
8364dd4f32aeSBjoern A. Zeeb 						  arvif);
8365dd4f32aeSBjoern A. Zeeb 	} else if (ath11k_mac_bitrate_mask_get_single_nss(ar, band, mask,
8366dd4f32aeSBjoern A. Zeeb 							  &single_nss)) {
8367dd4f32aeSBjoern A. Zeeb 		rate = WMI_FIXED_RATE_NONE;
8368dd4f32aeSBjoern A. Zeeb 		nss = single_nss;
8369dd4f32aeSBjoern A. Zeeb 		mutex_lock(&ar->conf_mutex);
8370dd4f32aeSBjoern A. Zeeb 		arvif->bitrate_mask = *mask;
8371dd4f32aeSBjoern A. Zeeb 		ieee80211_iterate_stations_atomic(ar->hw,
8372dd4f32aeSBjoern A. Zeeb 						  ath11k_mac_set_bitrate_mask_iter,
8373dd4f32aeSBjoern A. Zeeb 						  arvif);
8374dd4f32aeSBjoern A. Zeeb 		mutex_unlock(&ar->conf_mutex);
8375dd4f32aeSBjoern A. Zeeb 	} else {
8376dd4f32aeSBjoern A. Zeeb 		rate = WMI_FIXED_RATE_NONE;
8377dd4f32aeSBjoern A. Zeeb 
8378dd4f32aeSBjoern A. Zeeb 		if (!ath11k_mac_validate_vht_he_fixed_rate_settings(ar, band, mask))
8379dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab,
8380dd4f32aeSBjoern A. Zeeb 				    "could not update fixed rate settings to all peers due to mcs/nss incompatibility\n");
8381dd4f32aeSBjoern A. Zeeb 		nss = min_t(u32, ar->num_tx_chains,
8382dd4f32aeSBjoern A. Zeeb 			    max(max(ath11k_mac_max_ht_nss(ht_mcs_mask),
8383dd4f32aeSBjoern A. Zeeb 				    ath11k_mac_max_vht_nss(vht_mcs_mask)),
8384dd4f32aeSBjoern A. Zeeb 				ath11k_mac_max_he_nss(he_mcs_mask)));
8385dd4f32aeSBjoern A. Zeeb 
8386dd4f32aeSBjoern A. Zeeb 		/* If multiple rates across different preambles are given
8387dd4f32aeSBjoern A. Zeeb 		 * we can reconfigure this info with all peers using PEER_ASSOC
8388dd4f32aeSBjoern A. Zeeb 		 * command with the below exception cases.
8389dd4f32aeSBjoern A. Zeeb 		 * - Single VHT Rate : peer_assoc command accommodates only MCS
8390dd4f32aeSBjoern A. Zeeb 		 * range values i.e 0-7, 0-8, 0-9 for VHT. Though mac80211
8391dd4f32aeSBjoern A. Zeeb 		 * mandates passing basic rates along with HT/VHT rates, FW
8392dd4f32aeSBjoern A. Zeeb 		 * doesn't allow switching from VHT to Legacy. Hence instead of
8393dd4f32aeSBjoern A. Zeeb 		 * setting legacy and VHT rates using RATEMASK_CMD vdev cmd,
8394dd4f32aeSBjoern A. Zeeb 		 * we could set this VHT rate as peer fixed rate param, which
8395dd4f32aeSBjoern A. Zeeb 		 * will override FIXED rate and FW rate control algorithm.
8396dd4f32aeSBjoern A. Zeeb 		 * If single VHT rate is passed along with HT rates, we select
8397dd4f32aeSBjoern A. Zeeb 		 * the VHT rate as fixed rate for vht peers.
8398dd4f32aeSBjoern A. Zeeb 		 * - Multiple VHT Rates : When Multiple VHT rates are given,this
8399dd4f32aeSBjoern A. Zeeb 		 * can be set using RATEMASK CMD which uses FW rate-ctl alg.
8400dd4f32aeSBjoern A. Zeeb 		 * TODO: Setting multiple VHT MCS and replacing peer_assoc with
8401dd4f32aeSBjoern A. Zeeb 		 * RATEMASK_CMDID can cover all use cases of setting rates
8402dd4f32aeSBjoern A. Zeeb 		 * across multiple preambles and rates within same type.
8403dd4f32aeSBjoern A. Zeeb 		 * But requires more validation of the command at this point.
8404dd4f32aeSBjoern A. Zeeb 		 */
8405dd4f32aeSBjoern A. Zeeb 
8406dd4f32aeSBjoern A. Zeeb 		num_rates = ath11k_mac_bitrate_mask_num_vht_rates(ar, band,
8407dd4f32aeSBjoern A. Zeeb 								  mask);
8408dd4f32aeSBjoern A. Zeeb 
8409dd4f32aeSBjoern A. Zeeb 		if (!ath11k_mac_vht_mcs_range_present(ar, band, mask) &&
8410dd4f32aeSBjoern A. Zeeb 		    num_rates > 1) {
8411dd4f32aeSBjoern A. Zeeb 			/* TODO: Handle multiple VHT MCS values setting using
8412dd4f32aeSBjoern A. Zeeb 			 * RATEMASK CMD
8413dd4f32aeSBjoern A. Zeeb 			 */
8414dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab,
8415dd4f32aeSBjoern A. Zeeb 				    "setting %d mcs values in bitrate mask not supported\n",
8416dd4f32aeSBjoern A. Zeeb 				num_rates);
8417dd4f32aeSBjoern A. Zeeb 			return -EINVAL;
8418dd4f32aeSBjoern A. Zeeb 		}
8419dd4f32aeSBjoern A. Zeeb 
8420dd4f32aeSBjoern A. Zeeb 		num_rates = ath11k_mac_bitrate_mask_num_he_rates(ar, band,
8421dd4f32aeSBjoern A. Zeeb 								 mask);
8422dd4f32aeSBjoern A. Zeeb 		if (num_rates == 1)
8423dd4f32aeSBjoern A. Zeeb 			he_fixed_rate = true;
8424dd4f32aeSBjoern A. Zeeb 
8425dd4f32aeSBjoern A. Zeeb 		if (!ath11k_mac_he_mcs_range_present(ar, band, mask) &&
8426dd4f32aeSBjoern A. Zeeb 		    num_rates > 1) {
8427dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ar->ab,
8428dd4f32aeSBjoern A. Zeeb 				    "Setting more than one HE MCS Value in bitrate mask not supported\n");
8429dd4f32aeSBjoern A. Zeeb 			return -EINVAL;
8430dd4f32aeSBjoern A. Zeeb 		}
8431dd4f32aeSBjoern A. Zeeb 
8432dd4f32aeSBjoern A. Zeeb 		mutex_lock(&ar->conf_mutex);
8433dd4f32aeSBjoern A. Zeeb 		ieee80211_iterate_stations_atomic(ar->hw,
8434dd4f32aeSBjoern A. Zeeb 						  ath11k_mac_disable_peer_fixed_rate,
8435dd4f32aeSBjoern A. Zeeb 						  arvif);
8436dd4f32aeSBjoern A. Zeeb 
8437dd4f32aeSBjoern A. Zeeb 		arvif->bitrate_mask = *mask;
8438dd4f32aeSBjoern A. Zeeb 		ieee80211_iterate_stations_atomic(ar->hw,
8439dd4f32aeSBjoern A. Zeeb 						  ath11k_mac_set_bitrate_mask_iter,
8440dd4f32aeSBjoern A. Zeeb 						  arvif);
8441dd4f32aeSBjoern A. Zeeb 
8442dd4f32aeSBjoern A. Zeeb 		mutex_unlock(&ar->conf_mutex);
8443dd4f32aeSBjoern A. Zeeb 	}
8444dd4f32aeSBjoern A. Zeeb 
8445dd4f32aeSBjoern A. Zeeb 	mutex_lock(&ar->conf_mutex);
8446dd4f32aeSBjoern A. Zeeb 
8447dd4f32aeSBjoern A. Zeeb 	ret = ath11k_mac_set_rate_params(arvif, rate, nss, sgi, ldpc, he_gi,
8448dd4f32aeSBjoern A. Zeeb 					 he_ltf, he_fixed_rate);
8449dd4f32aeSBjoern A. Zeeb 	if (ret) {
8450dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to set rate params on vdev %i: %d\n",
8451dd4f32aeSBjoern A. Zeeb 			    arvif->vdev_id, ret);
8452dd4f32aeSBjoern A. Zeeb 	}
8453dd4f32aeSBjoern A. Zeeb 
8454dd4f32aeSBjoern A. Zeeb 	mutex_unlock(&ar->conf_mutex);
8455dd4f32aeSBjoern A. Zeeb 
8456dd4f32aeSBjoern A. Zeeb 	return ret;
8457dd4f32aeSBjoern A. Zeeb }
8458dd4f32aeSBjoern A. Zeeb 
8459dd4f32aeSBjoern A. Zeeb static void
ath11k_mac_op_reconfig_complete(struct ieee80211_hw * hw,enum ieee80211_reconfig_type reconfig_type)8460dd4f32aeSBjoern A. Zeeb ath11k_mac_op_reconfig_complete(struct ieee80211_hw *hw,
8461dd4f32aeSBjoern A. Zeeb 				enum ieee80211_reconfig_type reconfig_type)
8462dd4f32aeSBjoern A. Zeeb {
8463dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = hw->priv;
8464*28348caeSBjoern A. Zeeb 	struct ath11k_base *ab = ar->ab;
8465*28348caeSBjoern A. Zeeb 	int recovery_count;
8466*28348caeSBjoern A. Zeeb 	struct ath11k_vif *arvif;
8467dd4f32aeSBjoern A. Zeeb 
8468dd4f32aeSBjoern A. Zeeb 	if (reconfig_type != IEEE80211_RECONFIG_TYPE_RESTART)
8469dd4f32aeSBjoern A. Zeeb 		return;
8470dd4f32aeSBjoern A. Zeeb 
8471dd4f32aeSBjoern A. Zeeb 	mutex_lock(&ar->conf_mutex);
8472dd4f32aeSBjoern A. Zeeb 
8473dd4f32aeSBjoern A. Zeeb 	if (ar->state == ATH11K_STATE_RESTARTED) {
8474dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "pdev %d successfully recovered\n",
8475dd4f32aeSBjoern A. Zeeb 			    ar->pdev->pdev_id);
8476dd4f32aeSBjoern A. Zeeb 		ar->state = ATH11K_STATE_ON;
8477dd4f32aeSBjoern A. Zeeb 		ieee80211_wake_queues(ar->hw);
8478*28348caeSBjoern A. Zeeb 
8479*28348caeSBjoern A. Zeeb 		if (ar->ab->hw_params.current_cc_support &&
8480*28348caeSBjoern A. Zeeb 		    ar->alpha2[0] != 0 && ar->alpha2[1] != 0) {
8481*28348caeSBjoern A. Zeeb 			struct wmi_set_current_country_params set_current_param = {};
8482*28348caeSBjoern A. Zeeb 
8483*28348caeSBjoern A. Zeeb 			memcpy(&set_current_param.alpha2, ar->alpha2, 2);
8484*28348caeSBjoern A. Zeeb 			ath11k_wmi_send_set_current_country_cmd(ar, &set_current_param);
8485*28348caeSBjoern A. Zeeb 		}
8486*28348caeSBjoern A. Zeeb 
8487*28348caeSBjoern A. Zeeb 		if (ab->is_reset) {
8488*28348caeSBjoern A. Zeeb 			recovery_count = atomic_inc_return(&ab->recovery_count);
8489*28348caeSBjoern A. Zeeb 			ath11k_dbg(ab, ATH11K_DBG_BOOT,
8490*28348caeSBjoern A. Zeeb 				   "recovery count %d\n", recovery_count);
8491*28348caeSBjoern A. Zeeb 			/* When there are multiple radios in an SOC,
8492*28348caeSBjoern A. Zeeb 			 * the recovery has to be done for each radio
8493*28348caeSBjoern A. Zeeb 			 */
8494*28348caeSBjoern A. Zeeb 			if (recovery_count == ab->num_radios) {
8495*28348caeSBjoern A. Zeeb 				atomic_dec(&ab->reset_count);
8496*28348caeSBjoern A. Zeeb 				complete(&ab->reset_complete);
8497*28348caeSBjoern A. Zeeb 				ab->is_reset = false;
8498*28348caeSBjoern A. Zeeb 				atomic_set(&ab->fail_cont_count, 0);
8499*28348caeSBjoern A. Zeeb 				ath11k_dbg(ab, ATH11K_DBG_BOOT, "reset success\n");
8500*28348caeSBjoern A. Zeeb 			}
8501*28348caeSBjoern A. Zeeb 		}
8502*28348caeSBjoern A. Zeeb 		if (ar->ab->hw_params.support_fw_mac_sequence) {
8503*28348caeSBjoern A. Zeeb 			list_for_each_entry(arvif, &ar->arvifs, list) {
8504*28348caeSBjoern A. Zeeb 				if (arvif->is_up && arvif->vdev_type == WMI_VDEV_TYPE_STA)
8505*28348caeSBjoern A. Zeeb 					ieee80211_hw_restart_disconnect(arvif->vif);
8506*28348caeSBjoern A. Zeeb 			}
8507*28348caeSBjoern A. Zeeb 		}
8508dd4f32aeSBjoern A. Zeeb 	}
8509dd4f32aeSBjoern A. Zeeb 
8510dd4f32aeSBjoern A. Zeeb 	mutex_unlock(&ar->conf_mutex);
8511dd4f32aeSBjoern A. Zeeb }
8512dd4f32aeSBjoern A. Zeeb 
8513dd4f32aeSBjoern A. Zeeb static void
ath11k_mac_update_bss_chan_survey(struct ath11k * ar,struct ieee80211_channel * channel)8514dd4f32aeSBjoern A. Zeeb ath11k_mac_update_bss_chan_survey(struct ath11k *ar,
8515dd4f32aeSBjoern A. Zeeb 				  struct ieee80211_channel *channel)
8516dd4f32aeSBjoern A. Zeeb {
8517dd4f32aeSBjoern A. Zeeb 	int ret;
8518dd4f32aeSBjoern A. Zeeb 	enum wmi_bss_chan_info_req_type type = WMI_BSS_SURVEY_REQ_TYPE_READ;
8519dd4f32aeSBjoern A. Zeeb 
8520dd4f32aeSBjoern A. Zeeb 	lockdep_assert_held(&ar->conf_mutex);
8521dd4f32aeSBjoern A. Zeeb 
8522dd4f32aeSBjoern A. Zeeb 	if (!test_bit(WMI_TLV_SERVICE_BSS_CHANNEL_INFO_64, ar->ab->wmi_ab.svc_map) ||
8523dd4f32aeSBjoern A. Zeeb 	    ar->rx_channel != channel)
8524dd4f32aeSBjoern A. Zeeb 		return;
8525dd4f32aeSBjoern A. Zeeb 
8526dd4f32aeSBjoern A. Zeeb 	if (ar->scan.state != ATH11K_SCAN_IDLE) {
8527dd4f32aeSBjoern A. Zeeb 		ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
8528dd4f32aeSBjoern A. Zeeb 			   "ignoring bss chan info req while scanning..\n");
8529dd4f32aeSBjoern A. Zeeb 		return;
8530dd4f32aeSBjoern A. Zeeb 	}
8531dd4f32aeSBjoern A. Zeeb 
8532dd4f32aeSBjoern A. Zeeb 	reinit_completion(&ar->bss_survey_done);
8533dd4f32aeSBjoern A. Zeeb 
8534dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_pdev_bss_chan_info_request(ar, type);
8535dd4f32aeSBjoern A. Zeeb 	if (ret) {
8536dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to send pdev bss chan info request\n");
8537dd4f32aeSBjoern A. Zeeb 		return;
8538dd4f32aeSBjoern A. Zeeb 	}
8539dd4f32aeSBjoern A. Zeeb 
8540dd4f32aeSBjoern A. Zeeb 	ret = wait_for_completion_timeout(&ar->bss_survey_done, 3 * HZ);
8541dd4f32aeSBjoern A. Zeeb 	if (ret == 0)
8542dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "bss channel survey timed out\n");
8543dd4f32aeSBjoern A. Zeeb }
8544dd4f32aeSBjoern A. Zeeb 
ath11k_mac_op_get_survey(struct ieee80211_hw * hw,int idx,struct survey_info * survey)8545dd4f32aeSBjoern A. Zeeb static int ath11k_mac_op_get_survey(struct ieee80211_hw *hw, int idx,
8546dd4f32aeSBjoern A. Zeeb 				    struct survey_info *survey)
8547dd4f32aeSBjoern A. Zeeb {
8548dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = hw->priv;
8549dd4f32aeSBjoern A. Zeeb 	struct ieee80211_supported_band *sband;
8550dd4f32aeSBjoern A. Zeeb 	struct survey_info *ar_survey;
8551dd4f32aeSBjoern A. Zeeb 	int ret = 0;
8552dd4f32aeSBjoern A. Zeeb 
8553dd4f32aeSBjoern A. Zeeb 	if (idx >= ATH11K_NUM_CHANS)
8554dd4f32aeSBjoern A. Zeeb 		return -ENOENT;
8555dd4f32aeSBjoern A. Zeeb 
8556dd4f32aeSBjoern A. Zeeb 	ar_survey = &ar->survey[idx];
8557dd4f32aeSBjoern A. Zeeb 
8558dd4f32aeSBjoern A. Zeeb 	mutex_lock(&ar->conf_mutex);
8559dd4f32aeSBjoern A. Zeeb 
8560dd4f32aeSBjoern A. Zeeb 	sband = hw->wiphy->bands[NL80211_BAND_2GHZ];
8561dd4f32aeSBjoern A. Zeeb 	if (sband && idx >= sband->n_channels) {
8562dd4f32aeSBjoern A. Zeeb 		idx -= sband->n_channels;
8563dd4f32aeSBjoern A. Zeeb 		sband = NULL;
8564dd4f32aeSBjoern A. Zeeb 	}
8565dd4f32aeSBjoern A. Zeeb 
8566dd4f32aeSBjoern A. Zeeb 	if (!sband)
8567dd4f32aeSBjoern A. Zeeb 		sband = hw->wiphy->bands[NL80211_BAND_5GHZ];
8568dd4f32aeSBjoern A. Zeeb 	if (sband && idx >= sband->n_channels) {
8569dd4f32aeSBjoern A. Zeeb 		idx -= sband->n_channels;
8570dd4f32aeSBjoern A. Zeeb 		sband = NULL;
8571dd4f32aeSBjoern A. Zeeb 	}
8572dd4f32aeSBjoern A. Zeeb 
8573dd4f32aeSBjoern A. Zeeb 	if (!sband)
8574dd4f32aeSBjoern A. Zeeb 		sband = hw->wiphy->bands[NL80211_BAND_6GHZ];
8575dd4f32aeSBjoern A. Zeeb 	if (!sband || idx >= sband->n_channels) {
8576dd4f32aeSBjoern A. Zeeb 		ret = -ENOENT;
8577dd4f32aeSBjoern A. Zeeb 		goto exit;
8578dd4f32aeSBjoern A. Zeeb 	}
8579dd4f32aeSBjoern A. Zeeb 
8580dd4f32aeSBjoern A. Zeeb 	ath11k_mac_update_bss_chan_survey(ar, &sband->channels[idx]);
8581dd4f32aeSBjoern A. Zeeb 
8582dd4f32aeSBjoern A. Zeeb 	spin_lock_bh(&ar->data_lock);
8583dd4f32aeSBjoern A. Zeeb 	memcpy(survey, ar_survey, sizeof(*survey));
8584dd4f32aeSBjoern A. Zeeb 	spin_unlock_bh(&ar->data_lock);
8585dd4f32aeSBjoern A. Zeeb 
8586dd4f32aeSBjoern A. Zeeb 	survey->channel = &sband->channels[idx];
8587dd4f32aeSBjoern A. Zeeb 
8588dd4f32aeSBjoern A. Zeeb 	if (ar->rx_channel == survey->channel)
8589dd4f32aeSBjoern A. Zeeb 		survey->filled |= SURVEY_INFO_IN_USE;
8590dd4f32aeSBjoern A. Zeeb 
8591dd4f32aeSBjoern A. Zeeb exit:
8592dd4f32aeSBjoern A. Zeeb 	mutex_unlock(&ar->conf_mutex);
8593dd4f32aeSBjoern A. Zeeb 	return ret;
8594dd4f32aeSBjoern A. Zeeb }
8595dd4f32aeSBjoern A. Zeeb 
ath11k_mac_put_chain_rssi(struct station_info * sinfo,struct ath11k_sta * arsta,char * pre,bool clear)8596dd4f32aeSBjoern A. Zeeb static void ath11k_mac_put_chain_rssi(struct station_info *sinfo,
8597dd4f32aeSBjoern A. Zeeb 				      struct ath11k_sta *arsta,
8598dd4f32aeSBjoern A. Zeeb 				      char *pre,
8599dd4f32aeSBjoern A. Zeeb 				      bool clear)
8600dd4f32aeSBjoern A. Zeeb {
8601dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = arsta->arvif->ar;
8602dd4f32aeSBjoern A. Zeeb 	int i;
8603dd4f32aeSBjoern A. Zeeb 	s8 rssi;
8604dd4f32aeSBjoern A. Zeeb 
8605dd4f32aeSBjoern A. Zeeb 	for (i = 0; i < ARRAY_SIZE(sinfo->chain_signal); i++) {
8606dd4f32aeSBjoern A. Zeeb 		sinfo->chains &= ~BIT(i);
8607dd4f32aeSBjoern A. Zeeb 		rssi = arsta->chain_signal[i];
8608dd4f32aeSBjoern A. Zeeb 		if (clear)
8609dd4f32aeSBjoern A. Zeeb 			arsta->chain_signal[i] = ATH11K_INVALID_RSSI_FULL;
8610dd4f32aeSBjoern A. Zeeb 
8611dd4f32aeSBjoern A. Zeeb 		ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
8612*28348caeSBjoern A. Zeeb 			   "sta statistics %s rssi[%d] %d\n", pre, i, rssi);
8613dd4f32aeSBjoern A. Zeeb 
8614dd4f32aeSBjoern A. Zeeb 		if (rssi != ATH11K_DEFAULT_NOISE_FLOOR &&
8615dd4f32aeSBjoern A. Zeeb 		    rssi != ATH11K_INVALID_RSSI_FULL &&
8616dd4f32aeSBjoern A. Zeeb 		    rssi != ATH11K_INVALID_RSSI_EMPTY &&
8617dd4f32aeSBjoern A. Zeeb 		    rssi != 0) {
8618dd4f32aeSBjoern A. Zeeb 			sinfo->chain_signal[i] = rssi;
8619dd4f32aeSBjoern A. Zeeb 			sinfo->chains |= BIT(i);
8620dd4f32aeSBjoern A. Zeeb 			sinfo->filled |= BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL);
8621dd4f32aeSBjoern A. Zeeb 		}
8622dd4f32aeSBjoern A. Zeeb 	}
8623dd4f32aeSBjoern A. Zeeb }
8624dd4f32aeSBjoern A. Zeeb 
ath11k_mac_op_sta_statistics(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct station_info * sinfo)8625dd4f32aeSBjoern A. Zeeb static void ath11k_mac_op_sta_statistics(struct ieee80211_hw *hw,
8626dd4f32aeSBjoern A. Zeeb 					 struct ieee80211_vif *vif,
8627dd4f32aeSBjoern A. Zeeb 					 struct ieee80211_sta *sta,
8628dd4f32aeSBjoern A. Zeeb 					 struct station_info *sinfo)
8629dd4f32aeSBjoern A. Zeeb {
8630dd4f32aeSBjoern A. Zeeb 	struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
8631dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = arsta->arvif->ar;
8632dd4f32aeSBjoern A. Zeeb 	s8 signal;
8633dd4f32aeSBjoern A. Zeeb 	bool db2dbm = test_bit(WMI_TLV_SERVICE_HW_DB2DBM_CONVERSION_SUPPORT,
8634dd4f32aeSBjoern A. Zeeb 			       ar->ab->wmi_ab.svc_map);
8635dd4f32aeSBjoern A. Zeeb 
8636dd4f32aeSBjoern A. Zeeb 	sinfo->rx_duration = arsta->rx_duration;
8637dd4f32aeSBjoern A. Zeeb 	sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_DURATION);
8638dd4f32aeSBjoern A. Zeeb 
8639dd4f32aeSBjoern A. Zeeb 	sinfo->tx_duration = arsta->tx_duration;
8640dd4f32aeSBjoern A. Zeeb 	sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_DURATION);
8641dd4f32aeSBjoern A. Zeeb 
8642dd4f32aeSBjoern A. Zeeb 	if (arsta->txrate.legacy || arsta->txrate.nss) {
8643dd4f32aeSBjoern A. Zeeb 		if (arsta->txrate.legacy) {
8644dd4f32aeSBjoern A. Zeeb 			sinfo->txrate.legacy = arsta->txrate.legacy;
8645dd4f32aeSBjoern A. Zeeb 		} else {
8646dd4f32aeSBjoern A. Zeeb 			sinfo->txrate.mcs = arsta->txrate.mcs;
8647dd4f32aeSBjoern A. Zeeb 			sinfo->txrate.nss = arsta->txrate.nss;
8648dd4f32aeSBjoern A. Zeeb 			sinfo->txrate.bw = arsta->txrate.bw;
8649dd4f32aeSBjoern A. Zeeb 			sinfo->txrate.he_gi = arsta->txrate.he_gi;
8650dd4f32aeSBjoern A. Zeeb 			sinfo->txrate.he_dcm = arsta->txrate.he_dcm;
8651dd4f32aeSBjoern A. Zeeb 			sinfo->txrate.he_ru_alloc = arsta->txrate.he_ru_alloc;
8652dd4f32aeSBjoern A. Zeeb 		}
8653dd4f32aeSBjoern A. Zeeb 		sinfo->txrate.flags = arsta->txrate.flags;
8654dd4f32aeSBjoern A. Zeeb 		sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
8655dd4f32aeSBjoern A. Zeeb 	}
8656dd4f32aeSBjoern A. Zeeb 
8657dd4f32aeSBjoern A. Zeeb 	ath11k_mac_put_chain_rssi(sinfo, arsta, "ppdu", false);
8658dd4f32aeSBjoern A. Zeeb 
8659dd4f32aeSBjoern A. Zeeb 	if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL)) &&
8660dd4f32aeSBjoern A. Zeeb 	    arsta->arvif->vdev_type == WMI_VDEV_TYPE_STA &&
8661dd4f32aeSBjoern A. Zeeb 	    ar->ab->hw_params.supports_rssi_stats &&
8662dd4f32aeSBjoern A. Zeeb 	    !ath11k_debugfs_get_fw_stats(ar, ar->pdev->pdev_id, 0,
8663dd4f32aeSBjoern A. Zeeb 					 WMI_REQUEST_RSSI_PER_CHAIN_STAT)) {
8664dd4f32aeSBjoern A. Zeeb 		ath11k_mac_put_chain_rssi(sinfo, arsta, "fw stats", true);
8665dd4f32aeSBjoern A. Zeeb 	}
8666dd4f32aeSBjoern A. Zeeb 
8667dd4f32aeSBjoern A. Zeeb 	signal = arsta->rssi_comb;
8668dd4f32aeSBjoern A. Zeeb 	if (!signal &&
8669dd4f32aeSBjoern A. Zeeb 	    arsta->arvif->vdev_type == WMI_VDEV_TYPE_STA &&
8670dd4f32aeSBjoern A. Zeeb 	    ar->ab->hw_params.supports_rssi_stats &&
8671dd4f32aeSBjoern A. Zeeb 	    !(ath11k_debugfs_get_fw_stats(ar, ar->pdev->pdev_id, 0,
8672dd4f32aeSBjoern A. Zeeb 					WMI_REQUEST_VDEV_STAT)))
8673dd4f32aeSBjoern A. Zeeb 		signal = arsta->rssi_beacon;
8674dd4f32aeSBjoern A. Zeeb 
8675dd4f32aeSBjoern A. Zeeb 	ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
8676*28348caeSBjoern A. Zeeb 		   "sta statistics db2dbm %u rssi comb %d rssi beacon %d\n",
8677dd4f32aeSBjoern A. Zeeb 		   db2dbm, arsta->rssi_comb, arsta->rssi_beacon);
8678dd4f32aeSBjoern A. Zeeb 
8679dd4f32aeSBjoern A. Zeeb 	if (signal) {
8680dd4f32aeSBjoern A. Zeeb 		sinfo->signal = db2dbm ? signal : signal + ATH11K_DEFAULT_NOISE_FLOOR;
8681dd4f32aeSBjoern A. Zeeb 		sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL);
8682dd4f32aeSBjoern A. Zeeb 	}
8683*28348caeSBjoern A. Zeeb 
8684*28348caeSBjoern A. Zeeb 	sinfo->signal_avg = ewma_avg_rssi_read(&arsta->avg_rssi) +
8685*28348caeSBjoern A. Zeeb 		ATH11K_DEFAULT_NOISE_FLOOR;
8686*28348caeSBjoern A. Zeeb 	sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG);
8687*28348caeSBjoern A. Zeeb }
8688*28348caeSBjoern A. Zeeb 
8689*28348caeSBjoern A. Zeeb #if IS_ENABLED(CONFIG_IPV6)
ath11k_generate_ns_mc_addr(struct ath11k * ar,struct ath11k_arp_ns_offload * offload)8690*28348caeSBjoern A. Zeeb static void ath11k_generate_ns_mc_addr(struct ath11k *ar,
8691*28348caeSBjoern A. Zeeb 				       struct ath11k_arp_ns_offload *offload)
8692*28348caeSBjoern A. Zeeb {
8693*28348caeSBjoern A. Zeeb 	int i;
8694*28348caeSBjoern A. Zeeb 
8695*28348caeSBjoern A. Zeeb 	for (i = 0; i < offload->ipv6_count; i++) {
8696*28348caeSBjoern A. Zeeb 		offload->self_ipv6_addr[i][0] = 0xff;
8697*28348caeSBjoern A. Zeeb 		offload->self_ipv6_addr[i][1] = 0x02;
8698*28348caeSBjoern A. Zeeb 		offload->self_ipv6_addr[i][11] = 0x01;
8699*28348caeSBjoern A. Zeeb 		offload->self_ipv6_addr[i][12] = 0xff;
8700*28348caeSBjoern A. Zeeb 		offload->self_ipv6_addr[i][13] =
8701*28348caeSBjoern A. Zeeb 					offload->ipv6_addr[i][13];
8702*28348caeSBjoern A. Zeeb 		offload->self_ipv6_addr[i][14] =
8703*28348caeSBjoern A. Zeeb 					offload->ipv6_addr[i][14];
8704*28348caeSBjoern A. Zeeb 		offload->self_ipv6_addr[i][15] =
8705*28348caeSBjoern A. Zeeb 					offload->ipv6_addr[i][15];
8706*28348caeSBjoern A. Zeeb 		ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "NS solicited addr %pI6\n",
8707*28348caeSBjoern A. Zeeb 			   offload->self_ipv6_addr[i]);
8708*28348caeSBjoern A. Zeeb 	}
8709*28348caeSBjoern A. Zeeb }
8710*28348caeSBjoern A. Zeeb 
ath11k_mac_op_ipv6_changed(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct inet6_dev * idev)8711*28348caeSBjoern A. Zeeb static void ath11k_mac_op_ipv6_changed(struct ieee80211_hw *hw,
8712*28348caeSBjoern A. Zeeb 				       struct ieee80211_vif *vif,
8713*28348caeSBjoern A. Zeeb 				       struct inet6_dev *idev)
8714*28348caeSBjoern A. Zeeb {
8715*28348caeSBjoern A. Zeeb 	struct ath11k *ar = hw->priv;
8716*28348caeSBjoern A. Zeeb 	struct ath11k_arp_ns_offload *offload;
8717*28348caeSBjoern A. Zeeb 	struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
8718*28348caeSBjoern A. Zeeb 	struct inet6_ifaddr *ifa6;
8719*28348caeSBjoern A. Zeeb 	struct ifacaddr6 *ifaca6;
8720*28348caeSBjoern A. Zeeb 	struct list_head *p;
8721*28348caeSBjoern A. Zeeb 	u32 count, scope;
8722*28348caeSBjoern A. Zeeb 
8723*28348caeSBjoern A. Zeeb 	ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "op ipv6 changed\n");
8724*28348caeSBjoern A. Zeeb 
8725*28348caeSBjoern A. Zeeb 	offload = &arvif->arp_ns_offload;
8726*28348caeSBjoern A. Zeeb 	count = 0;
8727*28348caeSBjoern A. Zeeb 
8728*28348caeSBjoern A. Zeeb 	read_lock_bh(&idev->lock);
8729*28348caeSBjoern A. Zeeb 
8730*28348caeSBjoern A. Zeeb 	memset(offload->ipv6_addr, 0, sizeof(offload->ipv6_addr));
8731*28348caeSBjoern A. Zeeb 	memset(offload->self_ipv6_addr, 0, sizeof(offload->self_ipv6_addr));
8732*28348caeSBjoern A. Zeeb 	memcpy(offload->mac_addr, vif->addr, ETH_ALEN);
8733*28348caeSBjoern A. Zeeb 
8734*28348caeSBjoern A. Zeeb 	/* get unicast address */
8735*28348caeSBjoern A. Zeeb 	list_for_each(p, &idev->addr_list) {
8736*28348caeSBjoern A. Zeeb 		if (count >= ATH11K_IPV6_MAX_COUNT)
8737*28348caeSBjoern A. Zeeb 			goto generate;
8738*28348caeSBjoern A. Zeeb 
8739*28348caeSBjoern A. Zeeb 		ifa6 = list_entry(p, struct inet6_ifaddr, if_list);
8740*28348caeSBjoern A. Zeeb 		if (ifa6->flags & IFA_F_DADFAILED)
8741*28348caeSBjoern A. Zeeb 			continue;
8742*28348caeSBjoern A. Zeeb 		scope = ipv6_addr_src_scope(&ifa6->addr);
8743*28348caeSBjoern A. Zeeb 		if (scope == IPV6_ADDR_SCOPE_LINKLOCAL ||
8744*28348caeSBjoern A. Zeeb 		    scope == IPV6_ADDR_SCOPE_GLOBAL) {
8745*28348caeSBjoern A. Zeeb 			memcpy(offload->ipv6_addr[count], &ifa6->addr.s6_addr,
8746*28348caeSBjoern A. Zeeb 			       sizeof(ifa6->addr.s6_addr));
8747*28348caeSBjoern A. Zeeb 			offload->ipv6_type[count] = ATH11K_IPV6_UC_TYPE;
8748*28348caeSBjoern A. Zeeb 			ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "count %d ipv6 uc %pI6 scope %d\n",
8749*28348caeSBjoern A. Zeeb 				   count, offload->ipv6_addr[count],
8750*28348caeSBjoern A. Zeeb 				   scope);
8751*28348caeSBjoern A. Zeeb 			count++;
8752*28348caeSBjoern A. Zeeb 		} else {
8753*28348caeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "Unsupported ipv6 scope: %d\n", scope);
8754*28348caeSBjoern A. Zeeb 		}
8755*28348caeSBjoern A. Zeeb 	}
8756*28348caeSBjoern A. Zeeb 
8757*28348caeSBjoern A. Zeeb 	/* get anycast address */
8758*28348caeSBjoern A. Zeeb 	for (ifaca6 = idev->ac_list; ifaca6; ifaca6 = ifaca6->aca_next) {
8759*28348caeSBjoern A. Zeeb 		if (count >= ATH11K_IPV6_MAX_COUNT)
8760*28348caeSBjoern A. Zeeb 			goto generate;
8761*28348caeSBjoern A. Zeeb 
8762*28348caeSBjoern A. Zeeb 		scope = ipv6_addr_src_scope(&ifaca6->aca_addr);
8763*28348caeSBjoern A. Zeeb 		if (scope == IPV6_ADDR_SCOPE_LINKLOCAL ||
8764*28348caeSBjoern A. Zeeb 		    scope == IPV6_ADDR_SCOPE_GLOBAL) {
8765*28348caeSBjoern A. Zeeb 			memcpy(offload->ipv6_addr[count], &ifaca6->aca_addr,
8766*28348caeSBjoern A. Zeeb 			       sizeof(ifaca6->aca_addr));
8767*28348caeSBjoern A. Zeeb 			offload->ipv6_type[count] = ATH11K_IPV6_AC_TYPE;
8768*28348caeSBjoern A. Zeeb 			ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "count %d ipv6 ac %pI6 scope %d\n",
8769*28348caeSBjoern A. Zeeb 				   count, offload->ipv6_addr[count],
8770*28348caeSBjoern A. Zeeb 				   scope);
8771*28348caeSBjoern A. Zeeb 			count++;
8772*28348caeSBjoern A. Zeeb 		} else {
8773*28348caeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "Unsupported ipv scope: %d\n", scope);
8774*28348caeSBjoern A. Zeeb 		}
8775*28348caeSBjoern A. Zeeb 	}
8776*28348caeSBjoern A. Zeeb 
8777*28348caeSBjoern A. Zeeb generate:
8778*28348caeSBjoern A. Zeeb 	offload->ipv6_count = count;
8779*28348caeSBjoern A. Zeeb 	read_unlock_bh(&idev->lock);
8780*28348caeSBjoern A. Zeeb 
8781*28348caeSBjoern A. Zeeb 	/* generate ns multicast address */
8782*28348caeSBjoern A. Zeeb 	ath11k_generate_ns_mc_addr(ar, offload);
8783*28348caeSBjoern A. Zeeb }
8784*28348caeSBjoern A. Zeeb #endif
8785*28348caeSBjoern A. Zeeb 
ath11k_mac_op_set_rekey_data(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct cfg80211_gtk_rekey_data * data)8786*28348caeSBjoern A. Zeeb static void ath11k_mac_op_set_rekey_data(struct ieee80211_hw *hw,
8787*28348caeSBjoern A. Zeeb 					 struct ieee80211_vif *vif,
8788*28348caeSBjoern A. Zeeb 					 struct cfg80211_gtk_rekey_data *data)
8789*28348caeSBjoern A. Zeeb {
8790*28348caeSBjoern A. Zeeb 	struct ath11k *ar = hw->priv;
8791*28348caeSBjoern A. Zeeb 	struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
8792*28348caeSBjoern A. Zeeb 	struct ath11k_rekey_data *rekey_data = &arvif->rekey_data;
8793*28348caeSBjoern A. Zeeb 
8794*28348caeSBjoern A. Zeeb 	ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "set rekey data vdev %d\n",
8795*28348caeSBjoern A. Zeeb 		   arvif->vdev_id);
8796*28348caeSBjoern A. Zeeb 
8797*28348caeSBjoern A. Zeeb 	mutex_lock(&ar->conf_mutex);
8798*28348caeSBjoern A. Zeeb 
8799*28348caeSBjoern A. Zeeb 	memcpy(rekey_data->kck, data->kck, NL80211_KCK_LEN);
8800*28348caeSBjoern A. Zeeb 	memcpy(rekey_data->kek, data->kek, NL80211_KEK_LEN);
8801*28348caeSBjoern A. Zeeb 
8802*28348caeSBjoern A. Zeeb 	/* The supplicant works on big-endian, the firmware expects it on
8803*28348caeSBjoern A. Zeeb 	 * little endian.
8804*28348caeSBjoern A. Zeeb 	 */
8805*28348caeSBjoern A. Zeeb 	rekey_data->replay_ctr = get_unaligned_be64(data->replay_ctr);
8806*28348caeSBjoern A. Zeeb 
8807*28348caeSBjoern A. Zeeb 	arvif->rekey_data.enable_offload = true;
8808*28348caeSBjoern A. Zeeb 
8809*28348caeSBjoern A. Zeeb 	ath11k_dbg_dump(ar->ab, ATH11K_DBG_MAC, "kck", NULL,
8810*28348caeSBjoern A. Zeeb 			rekey_data->kck, NL80211_KCK_LEN);
8811*28348caeSBjoern A. Zeeb 	ath11k_dbg_dump(ar->ab, ATH11K_DBG_MAC, "kek", NULL,
8812*28348caeSBjoern A. Zeeb 			rekey_data->kck, NL80211_KEK_LEN);
8813*28348caeSBjoern A. Zeeb 	ath11k_dbg_dump(ar->ab, ATH11K_DBG_MAC, "replay ctr", NULL,
8814*28348caeSBjoern A. Zeeb 			&rekey_data->replay_ctr, sizeof(rekey_data->replay_ctr));
8815*28348caeSBjoern A. Zeeb 
8816*28348caeSBjoern A. Zeeb 	mutex_unlock(&ar->conf_mutex);
8817*28348caeSBjoern A. Zeeb }
8818*28348caeSBjoern A. Zeeb 
ath11k_mac_op_set_bios_sar_specs(struct ieee80211_hw * hw,const struct cfg80211_sar_specs * sar)8819*28348caeSBjoern A. Zeeb static int ath11k_mac_op_set_bios_sar_specs(struct ieee80211_hw *hw,
8820*28348caeSBjoern A. Zeeb 					    const struct cfg80211_sar_specs *sar)
8821*28348caeSBjoern A. Zeeb {
8822*28348caeSBjoern A. Zeeb 	struct ath11k *ar = hw->priv;
8823*28348caeSBjoern A. Zeeb 	const struct cfg80211_sar_sub_specs *sspec;
8824*28348caeSBjoern A. Zeeb 	int ret, index;
8825*28348caeSBjoern A. Zeeb 	u8 *sar_tbl;
8826*28348caeSBjoern A. Zeeb 	u32 i;
8827*28348caeSBjoern A. Zeeb 
8828*28348caeSBjoern A. Zeeb 	if (!sar || sar->type != NL80211_SAR_TYPE_POWER ||
8829*28348caeSBjoern A. Zeeb 	    sar->num_sub_specs == 0)
8830*28348caeSBjoern A. Zeeb 		return -EINVAL;
8831*28348caeSBjoern A. Zeeb 
8832*28348caeSBjoern A. Zeeb 	mutex_lock(&ar->conf_mutex);
8833*28348caeSBjoern A. Zeeb 
8834*28348caeSBjoern A. Zeeb 	if (!test_bit(WMI_TLV_SERVICE_BIOS_SAR_SUPPORT, ar->ab->wmi_ab.svc_map) ||
8835*28348caeSBjoern A. Zeeb 	    !ar->ab->hw_params.bios_sar_capa) {
8836*28348caeSBjoern A. Zeeb 		ret = -EOPNOTSUPP;
8837*28348caeSBjoern A. Zeeb 		goto exit;
8838*28348caeSBjoern A. Zeeb 	}
8839*28348caeSBjoern A. Zeeb 
8840*28348caeSBjoern A. Zeeb 	ret = ath11k_wmi_pdev_set_bios_geo_table_param(ar);
8841*28348caeSBjoern A. Zeeb 	if (ret) {
8842*28348caeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to set geo table: %d\n", ret);
8843*28348caeSBjoern A. Zeeb 		goto exit;
8844*28348caeSBjoern A. Zeeb 	}
8845*28348caeSBjoern A. Zeeb 
8846*28348caeSBjoern A. Zeeb 	sar_tbl = kzalloc(BIOS_SAR_TABLE_LEN, GFP_KERNEL);
8847*28348caeSBjoern A. Zeeb 	if (!sar_tbl) {
8848*28348caeSBjoern A. Zeeb 		ret = -ENOMEM;
8849*28348caeSBjoern A. Zeeb 		goto exit;
8850*28348caeSBjoern A. Zeeb 	}
8851*28348caeSBjoern A. Zeeb 
8852*28348caeSBjoern A. Zeeb 	sspec = sar->sub_specs;
8853*28348caeSBjoern A. Zeeb 	for (i = 0; i < sar->num_sub_specs; i++) {
8854*28348caeSBjoern A. Zeeb 		if (sspec->freq_range_index >= (BIOS_SAR_TABLE_LEN >> 1)) {
8855*28348caeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "Ignore bad frequency index %u, max allowed %u\n",
8856*28348caeSBjoern A. Zeeb 				    sspec->freq_range_index, BIOS_SAR_TABLE_LEN >> 1);
8857*28348caeSBjoern A. Zeeb 			continue;
8858*28348caeSBjoern A. Zeeb 		}
8859*28348caeSBjoern A. Zeeb 
8860*28348caeSBjoern A. Zeeb 		/* chain0 and chain1 share same power setting */
8861*28348caeSBjoern A. Zeeb 		sar_tbl[sspec->freq_range_index] = sspec->power;
8862*28348caeSBjoern A. Zeeb 		index = sspec->freq_range_index + (BIOS_SAR_TABLE_LEN >> 1);
8863*28348caeSBjoern A. Zeeb 		sar_tbl[index] = sspec->power;
8864*28348caeSBjoern A. Zeeb 		ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "sar tbl[%d] = %d\n",
8865*28348caeSBjoern A. Zeeb 			   sspec->freq_range_index, sar_tbl[sspec->freq_range_index]);
8866*28348caeSBjoern A. Zeeb 		sspec++;
8867*28348caeSBjoern A. Zeeb 	}
8868*28348caeSBjoern A. Zeeb 
8869*28348caeSBjoern A. Zeeb 	ret = ath11k_wmi_pdev_set_bios_sar_table_param(ar, sar_tbl);
8870*28348caeSBjoern A. Zeeb 	if (ret)
8871*28348caeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to set sar power: %d", ret);
8872*28348caeSBjoern A. Zeeb 
8873*28348caeSBjoern A. Zeeb 	kfree(sar_tbl);
8874*28348caeSBjoern A. Zeeb exit:
8875*28348caeSBjoern A. Zeeb 	mutex_unlock(&ar->conf_mutex);
8876*28348caeSBjoern A. Zeeb 
8877*28348caeSBjoern A. Zeeb 	return ret;
8878*28348caeSBjoern A. Zeeb }
8879*28348caeSBjoern A. Zeeb 
ath11k_mac_op_cancel_remain_on_channel(struct ieee80211_hw * hw,struct ieee80211_vif * vif)8880*28348caeSBjoern A. Zeeb static int ath11k_mac_op_cancel_remain_on_channel(struct ieee80211_hw *hw,
8881*28348caeSBjoern A. Zeeb 						  struct ieee80211_vif *vif)
8882*28348caeSBjoern A. Zeeb {
8883*28348caeSBjoern A. Zeeb 	struct ath11k *ar = hw->priv;
8884*28348caeSBjoern A. Zeeb 
8885*28348caeSBjoern A. Zeeb 	mutex_lock(&ar->conf_mutex);
8886*28348caeSBjoern A. Zeeb 
8887*28348caeSBjoern A. Zeeb 	spin_lock_bh(&ar->data_lock);
8888*28348caeSBjoern A. Zeeb 	ar->scan.roc_notify = false;
8889*28348caeSBjoern A. Zeeb 	spin_unlock_bh(&ar->data_lock);
8890*28348caeSBjoern A. Zeeb 
8891*28348caeSBjoern A. Zeeb 	ath11k_scan_abort(ar);
8892*28348caeSBjoern A. Zeeb 
8893*28348caeSBjoern A. Zeeb 	mutex_unlock(&ar->conf_mutex);
8894*28348caeSBjoern A. Zeeb 
8895*28348caeSBjoern A. Zeeb 	cancel_delayed_work_sync(&ar->scan.timeout);
8896*28348caeSBjoern A. Zeeb 
8897*28348caeSBjoern A. Zeeb 	return 0;
8898*28348caeSBjoern A. Zeeb }
8899*28348caeSBjoern A. Zeeb 
ath11k_mac_op_remain_on_channel(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_channel * chan,int duration,enum ieee80211_roc_type type)8900*28348caeSBjoern A. Zeeb static int ath11k_mac_op_remain_on_channel(struct ieee80211_hw *hw,
8901*28348caeSBjoern A. Zeeb 					   struct ieee80211_vif *vif,
8902*28348caeSBjoern A. Zeeb 					   struct ieee80211_channel *chan,
8903*28348caeSBjoern A. Zeeb 					   int duration,
8904*28348caeSBjoern A. Zeeb 					   enum ieee80211_roc_type type)
8905*28348caeSBjoern A. Zeeb {
8906*28348caeSBjoern A. Zeeb 	struct ath11k *ar = hw->priv;
8907*28348caeSBjoern A. Zeeb 	struct ath11k_vif *arvif = (void *)vif->drv_priv;
8908*28348caeSBjoern A. Zeeb 	struct scan_req_params arg;
8909*28348caeSBjoern A. Zeeb 	int ret;
8910*28348caeSBjoern A. Zeeb 	u32 scan_time_msec;
8911*28348caeSBjoern A. Zeeb 
8912*28348caeSBjoern A. Zeeb 	mutex_lock(&ar->conf_mutex);
8913*28348caeSBjoern A. Zeeb 
8914*28348caeSBjoern A. Zeeb 	spin_lock_bh(&ar->data_lock);
8915*28348caeSBjoern A. Zeeb 	switch (ar->scan.state) {
8916*28348caeSBjoern A. Zeeb 	case ATH11K_SCAN_IDLE:
8917*28348caeSBjoern A. Zeeb 		reinit_completion(&ar->scan.started);
8918*28348caeSBjoern A. Zeeb 		reinit_completion(&ar->scan.completed);
8919*28348caeSBjoern A. Zeeb 		reinit_completion(&ar->scan.on_channel);
8920*28348caeSBjoern A. Zeeb 		ar->scan.state = ATH11K_SCAN_STARTING;
8921*28348caeSBjoern A. Zeeb 		ar->scan.is_roc = true;
8922*28348caeSBjoern A. Zeeb 		ar->scan.vdev_id = arvif->vdev_id;
8923*28348caeSBjoern A. Zeeb 		ar->scan.roc_freq = chan->center_freq;
8924*28348caeSBjoern A. Zeeb 		ar->scan.roc_notify = true;
8925*28348caeSBjoern A. Zeeb 		ret = 0;
8926*28348caeSBjoern A. Zeeb 		break;
8927*28348caeSBjoern A. Zeeb 	case ATH11K_SCAN_STARTING:
8928*28348caeSBjoern A. Zeeb 	case ATH11K_SCAN_RUNNING:
8929*28348caeSBjoern A. Zeeb 	case ATH11K_SCAN_ABORTING:
8930*28348caeSBjoern A. Zeeb 		ret = -EBUSY;
8931*28348caeSBjoern A. Zeeb 		break;
8932*28348caeSBjoern A. Zeeb 	}
8933*28348caeSBjoern A. Zeeb 	spin_unlock_bh(&ar->data_lock);
8934*28348caeSBjoern A. Zeeb 
8935*28348caeSBjoern A. Zeeb 	if (ret)
8936*28348caeSBjoern A. Zeeb 		goto exit;
8937*28348caeSBjoern A. Zeeb 
8938*28348caeSBjoern A. Zeeb 	scan_time_msec = ar->hw->wiphy->max_remain_on_channel_duration * 2;
8939*28348caeSBjoern A. Zeeb 
8940*28348caeSBjoern A. Zeeb 	memset(&arg, 0, sizeof(arg));
8941*28348caeSBjoern A. Zeeb 	ath11k_wmi_start_scan_init(ar, &arg);
8942*28348caeSBjoern A. Zeeb 	arg.num_chan = 1;
8943*28348caeSBjoern A. Zeeb 	arg.chan_list = kcalloc(arg.num_chan, sizeof(*arg.chan_list),
8944*28348caeSBjoern A. Zeeb 				GFP_KERNEL);
8945*28348caeSBjoern A. Zeeb 	if (!arg.chan_list) {
8946*28348caeSBjoern A. Zeeb 		ret = -ENOMEM;
8947*28348caeSBjoern A. Zeeb 		goto exit;
8948*28348caeSBjoern A. Zeeb 	}
8949*28348caeSBjoern A. Zeeb 
8950*28348caeSBjoern A. Zeeb 	arg.vdev_id = arvif->vdev_id;
8951*28348caeSBjoern A. Zeeb 	arg.scan_id = ATH11K_SCAN_ID;
8952*28348caeSBjoern A. Zeeb 	arg.chan_list[0] = chan->center_freq;
8953*28348caeSBjoern A. Zeeb 	arg.dwell_time_active = scan_time_msec;
8954*28348caeSBjoern A. Zeeb 	arg.dwell_time_passive = scan_time_msec;
8955*28348caeSBjoern A. Zeeb 	arg.max_scan_time = scan_time_msec;
8956*28348caeSBjoern A. Zeeb 	arg.scan_flags |= WMI_SCAN_FLAG_PASSIVE;
8957*28348caeSBjoern A. Zeeb 	arg.scan_flags |= WMI_SCAN_FILTER_PROBE_REQ;
8958*28348caeSBjoern A. Zeeb 	arg.burst_duration = duration;
8959*28348caeSBjoern A. Zeeb 
8960*28348caeSBjoern A. Zeeb 	ret = ath11k_start_scan(ar, &arg);
8961*28348caeSBjoern A. Zeeb 	if (ret) {
8962*28348caeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to start roc scan: %d\n", ret);
8963*28348caeSBjoern A. Zeeb 
8964*28348caeSBjoern A. Zeeb 		spin_lock_bh(&ar->data_lock);
8965*28348caeSBjoern A. Zeeb 		ar->scan.state = ATH11K_SCAN_IDLE;
8966*28348caeSBjoern A. Zeeb 		spin_unlock_bh(&ar->data_lock);
8967*28348caeSBjoern A. Zeeb 		goto free_chan_list;
8968*28348caeSBjoern A. Zeeb 	}
8969*28348caeSBjoern A. Zeeb 
8970*28348caeSBjoern A. Zeeb 	ret = wait_for_completion_timeout(&ar->scan.on_channel, 3 * HZ);
8971*28348caeSBjoern A. Zeeb 	if (ret == 0) {
8972*28348caeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to switch to channel for roc scan\n");
8973*28348caeSBjoern A. Zeeb 		ret = ath11k_scan_stop(ar);
8974*28348caeSBjoern A. Zeeb 		if (ret)
8975*28348caeSBjoern A. Zeeb 			ath11k_warn(ar->ab, "failed to stop scan: %d\n", ret);
8976*28348caeSBjoern A. Zeeb 		ret = -ETIMEDOUT;
8977*28348caeSBjoern A. Zeeb 		goto free_chan_list;
8978*28348caeSBjoern A. Zeeb 	}
8979*28348caeSBjoern A. Zeeb 
8980*28348caeSBjoern A. Zeeb 	ieee80211_queue_delayed_work(ar->hw, &ar->scan.timeout,
8981*28348caeSBjoern A. Zeeb 				     msecs_to_jiffies(duration));
8982*28348caeSBjoern A. Zeeb 
8983*28348caeSBjoern A. Zeeb 	ret = 0;
8984*28348caeSBjoern A. Zeeb 
8985*28348caeSBjoern A. Zeeb free_chan_list:
8986*28348caeSBjoern A. Zeeb 	kfree(arg.chan_list);
8987*28348caeSBjoern A. Zeeb exit:
8988*28348caeSBjoern A. Zeeb 	mutex_unlock(&ar->conf_mutex);
8989*28348caeSBjoern A. Zeeb 	return ret;
8990*28348caeSBjoern A. Zeeb }
8991*28348caeSBjoern A. Zeeb 
ath11k_fw_stats_request(struct ath11k * ar,struct stats_request_params * req_param)8992*28348caeSBjoern A. Zeeb static int ath11k_fw_stats_request(struct ath11k *ar,
8993*28348caeSBjoern A. Zeeb 				   struct stats_request_params *req_param)
8994*28348caeSBjoern A. Zeeb {
8995*28348caeSBjoern A. Zeeb 	struct ath11k_base *ab = ar->ab;
8996*28348caeSBjoern A. Zeeb 	unsigned long time_left;
8997*28348caeSBjoern A. Zeeb 	int ret;
8998*28348caeSBjoern A. Zeeb 
8999*28348caeSBjoern A. Zeeb 	lockdep_assert_held(&ar->conf_mutex);
9000*28348caeSBjoern A. Zeeb 
9001*28348caeSBjoern A. Zeeb 	spin_lock_bh(&ar->data_lock);
9002*28348caeSBjoern A. Zeeb 	ar->fw_stats_done = false;
9003*28348caeSBjoern A. Zeeb 	ath11k_fw_stats_pdevs_free(&ar->fw_stats.pdevs);
9004*28348caeSBjoern A. Zeeb 	spin_unlock_bh(&ar->data_lock);
9005*28348caeSBjoern A. Zeeb 
9006*28348caeSBjoern A. Zeeb 	reinit_completion(&ar->fw_stats_complete);
9007*28348caeSBjoern A. Zeeb 
9008*28348caeSBjoern A. Zeeb 	ret = ath11k_wmi_send_stats_request_cmd(ar, req_param);
9009*28348caeSBjoern A. Zeeb 	if (ret) {
9010*28348caeSBjoern A. Zeeb 		ath11k_warn(ab, "could not request fw stats (%d)\n",
9011*28348caeSBjoern A. Zeeb 			    ret);
9012*28348caeSBjoern A. Zeeb 		return ret;
9013*28348caeSBjoern A. Zeeb 	}
9014*28348caeSBjoern A. Zeeb 
9015*28348caeSBjoern A. Zeeb 	time_left = wait_for_completion_timeout(&ar->fw_stats_complete,
9016*28348caeSBjoern A. Zeeb 						1 * HZ);
9017*28348caeSBjoern A. Zeeb 
9018*28348caeSBjoern A. Zeeb 	if (!time_left)
9019*28348caeSBjoern A. Zeeb 		return -ETIMEDOUT;
9020*28348caeSBjoern A. Zeeb 
9021*28348caeSBjoern A. Zeeb 	return 0;
9022*28348caeSBjoern A. Zeeb }
9023*28348caeSBjoern A. Zeeb 
ath11k_mac_op_get_txpower(struct ieee80211_hw * hw,struct ieee80211_vif * vif,int * dbm)9024*28348caeSBjoern A. Zeeb static int ath11k_mac_op_get_txpower(struct ieee80211_hw *hw,
9025*28348caeSBjoern A. Zeeb 				     struct ieee80211_vif *vif,
9026*28348caeSBjoern A. Zeeb 				     int *dbm)
9027*28348caeSBjoern A. Zeeb {
9028*28348caeSBjoern A. Zeeb 	struct ath11k *ar = hw->priv;
9029*28348caeSBjoern A. Zeeb 	struct ath11k_base *ab = ar->ab;
9030*28348caeSBjoern A. Zeeb 	struct stats_request_params req_param = {0};
9031*28348caeSBjoern A. Zeeb 	struct ath11k_fw_stats_pdev *pdev;
9032*28348caeSBjoern A. Zeeb 	int ret;
9033*28348caeSBjoern A. Zeeb 
9034*28348caeSBjoern A. Zeeb 	/* Final Tx power is minimum of Target Power, CTL power, Regulatory
9035*28348caeSBjoern A. Zeeb 	 * Power, PSD EIRP Power. We just know the Regulatory power from the
9036*28348caeSBjoern A. Zeeb 	 * regulatory rules obtained. FW knows all these power and sets the min
9037*28348caeSBjoern A. Zeeb 	 * of these. Hence, we request the FW pdev stats in which FW reports
9038*28348caeSBjoern A. Zeeb 	 * the minimum of all vdev's channel Tx power.
9039*28348caeSBjoern A. Zeeb 	 */
9040*28348caeSBjoern A. Zeeb 	mutex_lock(&ar->conf_mutex);
9041*28348caeSBjoern A. Zeeb 
9042*28348caeSBjoern A. Zeeb 	if (ar->state != ATH11K_STATE_ON)
9043*28348caeSBjoern A. Zeeb 		goto err_fallback;
9044*28348caeSBjoern A. Zeeb 
9045*28348caeSBjoern A. Zeeb 	req_param.pdev_id = ar->pdev->pdev_id;
9046*28348caeSBjoern A. Zeeb 	req_param.stats_id = WMI_REQUEST_PDEV_STAT;
9047*28348caeSBjoern A. Zeeb 
9048*28348caeSBjoern A. Zeeb 	ret = ath11k_fw_stats_request(ar, &req_param);
9049*28348caeSBjoern A. Zeeb 	if (ret) {
9050*28348caeSBjoern A. Zeeb 		ath11k_warn(ab, "failed to request fw pdev stats: %d\n", ret);
9051*28348caeSBjoern A. Zeeb 		goto err_fallback;
9052*28348caeSBjoern A. Zeeb 	}
9053*28348caeSBjoern A. Zeeb 
9054*28348caeSBjoern A. Zeeb 	spin_lock_bh(&ar->data_lock);
9055*28348caeSBjoern A. Zeeb 	pdev = list_first_entry_or_null(&ar->fw_stats.pdevs,
9056*28348caeSBjoern A. Zeeb 					struct ath11k_fw_stats_pdev, list);
9057*28348caeSBjoern A. Zeeb 	if (!pdev) {
9058*28348caeSBjoern A. Zeeb 		spin_unlock_bh(&ar->data_lock);
9059*28348caeSBjoern A. Zeeb 		goto err_fallback;
9060*28348caeSBjoern A. Zeeb 	}
9061*28348caeSBjoern A. Zeeb 
9062*28348caeSBjoern A. Zeeb 	/* tx power is set as 2 units per dBm in FW. */
9063*28348caeSBjoern A. Zeeb 	*dbm = pdev->chan_tx_power / 2;
9064*28348caeSBjoern A. Zeeb 
9065*28348caeSBjoern A. Zeeb 	spin_unlock_bh(&ar->data_lock);
9066*28348caeSBjoern A. Zeeb 	mutex_unlock(&ar->conf_mutex);
9067*28348caeSBjoern A. Zeeb 
9068*28348caeSBjoern A. Zeeb 	ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "txpower from firmware %d, reported %d dBm\n",
9069*28348caeSBjoern A. Zeeb 		   pdev->chan_tx_power, *dbm);
9070*28348caeSBjoern A. Zeeb 	return 0;
9071*28348caeSBjoern A. Zeeb 
9072*28348caeSBjoern A. Zeeb err_fallback:
9073*28348caeSBjoern A. Zeeb 	mutex_unlock(&ar->conf_mutex);
9074*28348caeSBjoern A. Zeeb 	/* We didn't get txpower from FW. Hence, relying on vif->bss_conf.txpower */
9075*28348caeSBjoern A. Zeeb 	*dbm = vif->bss_conf.txpower;
9076*28348caeSBjoern A. Zeeb 	ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "txpower from firmware NaN, reported %d dBm\n",
9077*28348caeSBjoern A. Zeeb 		   *dbm);
9078*28348caeSBjoern A. Zeeb 	return 0;
9079dd4f32aeSBjoern A. Zeeb }
9080dd4f32aeSBjoern A. Zeeb 
9081dd4f32aeSBjoern A. Zeeb static const struct ieee80211_ops ath11k_ops = {
9082dd4f32aeSBjoern A. Zeeb 	.tx				= ath11k_mac_op_tx,
9083*28348caeSBjoern A. Zeeb 	.wake_tx_queue			= ieee80211_handle_wake_tx_queue,
9084dd4f32aeSBjoern A. Zeeb 	.start                          = ath11k_mac_op_start,
9085dd4f32aeSBjoern A. Zeeb 	.stop                           = ath11k_mac_op_stop,
9086dd4f32aeSBjoern A. Zeeb 	.reconfig_complete              = ath11k_mac_op_reconfig_complete,
9087dd4f32aeSBjoern A. Zeeb 	.add_interface                  = ath11k_mac_op_add_interface,
9088dd4f32aeSBjoern A. Zeeb 	.remove_interface		= ath11k_mac_op_remove_interface,
9089dd4f32aeSBjoern A. Zeeb 	.update_vif_offload		= ath11k_mac_op_update_vif_offload,
9090dd4f32aeSBjoern A. Zeeb 	.config                         = ath11k_mac_op_config,
9091dd4f32aeSBjoern A. Zeeb 	.bss_info_changed               = ath11k_mac_op_bss_info_changed,
9092dd4f32aeSBjoern A. Zeeb 	.configure_filter		= ath11k_mac_op_configure_filter,
9093dd4f32aeSBjoern A. Zeeb 	.hw_scan                        = ath11k_mac_op_hw_scan,
9094dd4f32aeSBjoern A. Zeeb 	.cancel_hw_scan                 = ath11k_mac_op_cancel_hw_scan,
9095dd4f32aeSBjoern A. Zeeb 	.set_key                        = ath11k_mac_op_set_key,
9096*28348caeSBjoern A. Zeeb 	.set_rekey_data	                = ath11k_mac_op_set_rekey_data,
9097dd4f32aeSBjoern A. Zeeb 	.sta_state                      = ath11k_mac_op_sta_state,
9098dd4f32aeSBjoern A. Zeeb 	.sta_set_4addr                  = ath11k_mac_op_sta_set_4addr,
9099dd4f32aeSBjoern A. Zeeb 	.sta_set_txpwr			= ath11k_mac_op_sta_set_txpwr,
9100dd4f32aeSBjoern A. Zeeb 	.sta_rc_update			= ath11k_mac_op_sta_rc_update,
9101dd4f32aeSBjoern A. Zeeb 	.conf_tx                        = ath11k_mac_op_conf_tx,
9102dd4f32aeSBjoern A. Zeeb 	.set_antenna			= ath11k_mac_op_set_antenna,
9103dd4f32aeSBjoern A. Zeeb 	.get_antenna			= ath11k_mac_op_get_antenna,
9104dd4f32aeSBjoern A. Zeeb 	.ampdu_action			= ath11k_mac_op_ampdu_action,
9105dd4f32aeSBjoern A. Zeeb 	.add_chanctx			= ath11k_mac_op_add_chanctx,
9106dd4f32aeSBjoern A. Zeeb 	.remove_chanctx			= ath11k_mac_op_remove_chanctx,
9107dd4f32aeSBjoern A. Zeeb 	.change_chanctx			= ath11k_mac_op_change_chanctx,
9108dd4f32aeSBjoern A. Zeeb 	.assign_vif_chanctx		= ath11k_mac_op_assign_vif_chanctx,
9109dd4f32aeSBjoern A. Zeeb 	.unassign_vif_chanctx		= ath11k_mac_op_unassign_vif_chanctx,
9110dd4f32aeSBjoern A. Zeeb 	.switch_vif_chanctx		= ath11k_mac_op_switch_vif_chanctx,
9111dd4f32aeSBjoern A. Zeeb 	.set_rts_threshold		= ath11k_mac_op_set_rts_threshold,
9112dd4f32aeSBjoern A. Zeeb 	.set_frag_threshold		= ath11k_mac_op_set_frag_threshold,
9113dd4f32aeSBjoern A. Zeeb 	.set_bitrate_mask		= ath11k_mac_op_set_bitrate_mask,
9114dd4f32aeSBjoern A. Zeeb 	.get_survey			= ath11k_mac_op_get_survey,
9115dd4f32aeSBjoern A. Zeeb 	.flush				= ath11k_mac_op_flush,
9116dd4f32aeSBjoern A. Zeeb 	.sta_statistics			= ath11k_mac_op_sta_statistics,
9117dd4f32aeSBjoern A. Zeeb 	CFG80211_TESTMODE_CMD(ath11k_tm_cmd)
9118*28348caeSBjoern A. Zeeb 
9119*28348caeSBjoern A. Zeeb #ifdef CONFIG_PM
9120*28348caeSBjoern A. Zeeb 	.suspend			= ath11k_wow_op_suspend,
9121*28348caeSBjoern A. Zeeb 	.resume				= ath11k_wow_op_resume,
9122*28348caeSBjoern A. Zeeb 	.set_wakeup			= ath11k_wow_op_set_wakeup,
9123*28348caeSBjoern A. Zeeb #endif
9124*28348caeSBjoern A. Zeeb 
9125dd4f32aeSBjoern A. Zeeb #ifdef CONFIG_ATH11K_DEBUGFS
9126dd4f32aeSBjoern A. Zeeb 	.sta_add_debugfs		= ath11k_debugfs_sta_op_add,
9127dd4f32aeSBjoern A. Zeeb #endif
9128*28348caeSBjoern A. Zeeb 
9129*28348caeSBjoern A. Zeeb #if IS_ENABLED(CONFIG_IPV6)
9130*28348caeSBjoern A. Zeeb 	.ipv6_addr_change = ath11k_mac_op_ipv6_changed,
9131*28348caeSBjoern A. Zeeb #endif
9132*28348caeSBjoern A. Zeeb 	.get_txpower                    = ath11k_mac_op_get_txpower,
9133*28348caeSBjoern A. Zeeb 
9134*28348caeSBjoern A. Zeeb 	.set_sar_specs			= ath11k_mac_op_set_bios_sar_specs,
9135*28348caeSBjoern A. Zeeb 	.remain_on_channel		= ath11k_mac_op_remain_on_channel,
9136*28348caeSBjoern A. Zeeb 	.cancel_remain_on_channel	= ath11k_mac_op_cancel_remain_on_channel,
9137dd4f32aeSBjoern A. Zeeb };
9138dd4f32aeSBjoern A. Zeeb 
ath11k_mac_update_ch_list(struct ath11k * ar,struct ieee80211_supported_band * band,u32 freq_low,u32 freq_high)9139dd4f32aeSBjoern A. Zeeb static void ath11k_mac_update_ch_list(struct ath11k *ar,
9140dd4f32aeSBjoern A. Zeeb 				      struct ieee80211_supported_band *band,
9141dd4f32aeSBjoern A. Zeeb 				      u32 freq_low, u32 freq_high)
9142dd4f32aeSBjoern A. Zeeb {
9143dd4f32aeSBjoern A. Zeeb 	int i;
9144dd4f32aeSBjoern A. Zeeb 
9145dd4f32aeSBjoern A. Zeeb 	if (!(freq_low && freq_high))
9146dd4f32aeSBjoern A. Zeeb 		return;
9147dd4f32aeSBjoern A. Zeeb 
9148dd4f32aeSBjoern A. Zeeb 	for (i = 0; i < band->n_channels; i++) {
9149dd4f32aeSBjoern A. Zeeb 		if (band->channels[i].center_freq < freq_low ||
9150dd4f32aeSBjoern A. Zeeb 		    band->channels[i].center_freq > freq_high)
9151dd4f32aeSBjoern A. Zeeb 			band->channels[i].flags |= IEEE80211_CHAN_DISABLED;
9152dd4f32aeSBjoern A. Zeeb 	}
9153dd4f32aeSBjoern A. Zeeb }
9154dd4f32aeSBjoern A. Zeeb 
ath11k_get_phy_id(struct ath11k * ar,u32 band)9155dd4f32aeSBjoern A. Zeeb static u32 ath11k_get_phy_id(struct ath11k *ar, u32 band)
9156dd4f32aeSBjoern A. Zeeb {
9157dd4f32aeSBjoern A. Zeeb 	struct ath11k_pdev *pdev = ar->pdev;
9158dd4f32aeSBjoern A. Zeeb 	struct ath11k_pdev_cap *pdev_cap = &pdev->cap;
9159dd4f32aeSBjoern A. Zeeb 
9160dd4f32aeSBjoern A. Zeeb 	if (band == WMI_HOST_WLAN_2G_CAP)
9161dd4f32aeSBjoern A. Zeeb 		return pdev_cap->band[NL80211_BAND_2GHZ].phy_id;
9162dd4f32aeSBjoern A. Zeeb 
9163dd4f32aeSBjoern A. Zeeb 	if (band == WMI_HOST_WLAN_5G_CAP)
9164dd4f32aeSBjoern A. Zeeb 		return pdev_cap->band[NL80211_BAND_5GHZ].phy_id;
9165dd4f32aeSBjoern A. Zeeb 
9166dd4f32aeSBjoern A. Zeeb 	ath11k_warn(ar->ab, "unsupported phy cap:%d\n", band);
9167dd4f32aeSBjoern A. Zeeb 
9168dd4f32aeSBjoern A. Zeeb 	return 0;
9169dd4f32aeSBjoern A. Zeeb }
9170dd4f32aeSBjoern A. Zeeb 
ath11k_mac_setup_channels_rates(struct ath11k * ar,u32 supported_bands)9171dd4f32aeSBjoern A. Zeeb static int ath11k_mac_setup_channels_rates(struct ath11k *ar,
9172dd4f32aeSBjoern A. Zeeb 					   u32 supported_bands)
9173dd4f32aeSBjoern A. Zeeb {
9174dd4f32aeSBjoern A. Zeeb 	struct ieee80211_supported_band *band;
9175dd4f32aeSBjoern A. Zeeb 	struct ath11k_hal_reg_capabilities_ext *reg_cap, *temp_reg_cap;
9176dd4f32aeSBjoern A. Zeeb 	void *channels;
9177dd4f32aeSBjoern A. Zeeb 	u32 phy_id;
9178dd4f32aeSBjoern A. Zeeb 
9179dd4f32aeSBjoern A. Zeeb 	BUILD_BUG_ON((ARRAY_SIZE(ath11k_2ghz_channels) +
9180dd4f32aeSBjoern A. Zeeb 		      ARRAY_SIZE(ath11k_5ghz_channels) +
9181dd4f32aeSBjoern A. Zeeb 		      ARRAY_SIZE(ath11k_6ghz_channels)) !=
9182dd4f32aeSBjoern A. Zeeb 		     ATH11K_NUM_CHANS);
9183dd4f32aeSBjoern A. Zeeb 
9184dd4f32aeSBjoern A. Zeeb 	reg_cap = &ar->ab->hal_reg_cap[ar->pdev_idx];
9185dd4f32aeSBjoern A. Zeeb 	temp_reg_cap = reg_cap;
9186dd4f32aeSBjoern A. Zeeb 
9187dd4f32aeSBjoern A. Zeeb 	if (supported_bands & WMI_HOST_WLAN_2G_CAP) {
9188dd4f32aeSBjoern A. Zeeb 		channels = kmemdup(ath11k_2ghz_channels,
9189dd4f32aeSBjoern A. Zeeb 				   sizeof(ath11k_2ghz_channels),
9190dd4f32aeSBjoern A. Zeeb 				   GFP_KERNEL);
9191dd4f32aeSBjoern A. Zeeb 		if (!channels)
9192dd4f32aeSBjoern A. Zeeb 			return -ENOMEM;
9193dd4f32aeSBjoern A. Zeeb 
9194dd4f32aeSBjoern A. Zeeb 		band = &ar->mac.sbands[NL80211_BAND_2GHZ];
9195dd4f32aeSBjoern A. Zeeb 		band->band = NL80211_BAND_2GHZ;
9196dd4f32aeSBjoern A. Zeeb 		band->n_channels = ARRAY_SIZE(ath11k_2ghz_channels);
9197dd4f32aeSBjoern A. Zeeb 		band->channels = channels;
9198dd4f32aeSBjoern A. Zeeb 		band->n_bitrates = ath11k_g_rates_size;
9199dd4f32aeSBjoern A. Zeeb 		band->bitrates = ath11k_g_rates;
9200dd4f32aeSBjoern A. Zeeb 		ar->hw->wiphy->bands[NL80211_BAND_2GHZ] = band;
9201dd4f32aeSBjoern A. Zeeb 
9202dd4f32aeSBjoern A. Zeeb 		if (ar->ab->hw_params.single_pdev_only) {
9203dd4f32aeSBjoern A. Zeeb 			phy_id = ath11k_get_phy_id(ar, WMI_HOST_WLAN_2G_CAP);
9204dd4f32aeSBjoern A. Zeeb 			temp_reg_cap = &ar->ab->hal_reg_cap[phy_id];
9205dd4f32aeSBjoern A. Zeeb 		}
9206dd4f32aeSBjoern A. Zeeb 		ath11k_mac_update_ch_list(ar, band,
9207dd4f32aeSBjoern A. Zeeb 					  temp_reg_cap->low_2ghz_chan,
9208dd4f32aeSBjoern A. Zeeb 					  temp_reg_cap->high_2ghz_chan);
9209dd4f32aeSBjoern A. Zeeb 	}
9210dd4f32aeSBjoern A. Zeeb 
9211dd4f32aeSBjoern A. Zeeb 	if (supported_bands & WMI_HOST_WLAN_5G_CAP) {
9212*28348caeSBjoern A. Zeeb 		if (reg_cap->high_5ghz_chan >= ATH11K_MIN_6G_FREQ) {
9213dd4f32aeSBjoern A. Zeeb 			channels = kmemdup(ath11k_6ghz_channels,
9214dd4f32aeSBjoern A. Zeeb 					   sizeof(ath11k_6ghz_channels), GFP_KERNEL);
9215dd4f32aeSBjoern A. Zeeb 			if (!channels) {
9216dd4f32aeSBjoern A. Zeeb 				kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels);
9217dd4f32aeSBjoern A. Zeeb 				return -ENOMEM;
9218dd4f32aeSBjoern A. Zeeb 			}
9219dd4f32aeSBjoern A. Zeeb 
9220dd4f32aeSBjoern A. Zeeb 			ar->supports_6ghz = true;
9221dd4f32aeSBjoern A. Zeeb 			band = &ar->mac.sbands[NL80211_BAND_6GHZ];
9222dd4f32aeSBjoern A. Zeeb 			band->band = NL80211_BAND_6GHZ;
9223dd4f32aeSBjoern A. Zeeb 			band->n_channels = ARRAY_SIZE(ath11k_6ghz_channels);
9224dd4f32aeSBjoern A. Zeeb 			band->channels = channels;
9225dd4f32aeSBjoern A. Zeeb 			band->n_bitrates = ath11k_a_rates_size;
9226dd4f32aeSBjoern A. Zeeb 			band->bitrates = ath11k_a_rates;
9227dd4f32aeSBjoern A. Zeeb 			ar->hw->wiphy->bands[NL80211_BAND_6GHZ] = band;
9228dd4f32aeSBjoern A. Zeeb 
9229dd4f32aeSBjoern A. Zeeb 			if (ar->ab->hw_params.single_pdev_only) {
9230dd4f32aeSBjoern A. Zeeb 				phy_id = ath11k_get_phy_id(ar, WMI_HOST_WLAN_5G_CAP);
9231dd4f32aeSBjoern A. Zeeb 				temp_reg_cap = &ar->ab->hal_reg_cap[phy_id];
9232dd4f32aeSBjoern A. Zeeb 			}
9233dd4f32aeSBjoern A. Zeeb 
9234dd4f32aeSBjoern A. Zeeb 			ath11k_mac_update_ch_list(ar, band,
9235dd4f32aeSBjoern A. Zeeb 						  temp_reg_cap->low_5ghz_chan,
9236dd4f32aeSBjoern A. Zeeb 						  temp_reg_cap->high_5ghz_chan);
9237dd4f32aeSBjoern A. Zeeb 		}
9238dd4f32aeSBjoern A. Zeeb 
9239dd4f32aeSBjoern A. Zeeb 		if (reg_cap->low_5ghz_chan < ATH11K_MIN_6G_FREQ) {
9240dd4f32aeSBjoern A. Zeeb 			channels = kmemdup(ath11k_5ghz_channels,
9241dd4f32aeSBjoern A. Zeeb 					   sizeof(ath11k_5ghz_channels),
9242dd4f32aeSBjoern A. Zeeb 					   GFP_KERNEL);
9243dd4f32aeSBjoern A. Zeeb 			if (!channels) {
9244dd4f32aeSBjoern A. Zeeb 				kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels);
9245dd4f32aeSBjoern A. Zeeb 				kfree(ar->mac.sbands[NL80211_BAND_6GHZ].channels);
9246dd4f32aeSBjoern A. Zeeb 				return -ENOMEM;
9247dd4f32aeSBjoern A. Zeeb 			}
9248dd4f32aeSBjoern A. Zeeb 
9249dd4f32aeSBjoern A. Zeeb 			band = &ar->mac.sbands[NL80211_BAND_5GHZ];
9250dd4f32aeSBjoern A. Zeeb 			band->band = NL80211_BAND_5GHZ;
9251dd4f32aeSBjoern A. Zeeb 			band->n_channels = ARRAY_SIZE(ath11k_5ghz_channels);
9252dd4f32aeSBjoern A. Zeeb 			band->channels = channels;
9253dd4f32aeSBjoern A. Zeeb 			band->n_bitrates = ath11k_a_rates_size;
9254dd4f32aeSBjoern A. Zeeb 			band->bitrates = ath11k_a_rates;
9255dd4f32aeSBjoern A. Zeeb 			ar->hw->wiphy->bands[NL80211_BAND_5GHZ] = band;
9256dd4f32aeSBjoern A. Zeeb 
9257dd4f32aeSBjoern A. Zeeb 			if (ar->ab->hw_params.single_pdev_only) {
9258dd4f32aeSBjoern A. Zeeb 				phy_id = ath11k_get_phy_id(ar, WMI_HOST_WLAN_5G_CAP);
9259dd4f32aeSBjoern A. Zeeb 				temp_reg_cap = &ar->ab->hal_reg_cap[phy_id];
9260dd4f32aeSBjoern A. Zeeb 			}
9261dd4f32aeSBjoern A. Zeeb 
9262dd4f32aeSBjoern A. Zeeb 			ath11k_mac_update_ch_list(ar, band,
9263dd4f32aeSBjoern A. Zeeb 						  temp_reg_cap->low_5ghz_chan,
9264dd4f32aeSBjoern A. Zeeb 						  temp_reg_cap->high_5ghz_chan);
9265dd4f32aeSBjoern A. Zeeb 		}
9266dd4f32aeSBjoern A. Zeeb 	}
9267dd4f32aeSBjoern A. Zeeb 
9268dd4f32aeSBjoern A. Zeeb 	return 0;
9269dd4f32aeSBjoern A. Zeeb }
9270dd4f32aeSBjoern A. Zeeb 
ath11k_mac_setup_iface_combinations(struct ath11k * ar)9271dd4f32aeSBjoern A. Zeeb static int ath11k_mac_setup_iface_combinations(struct ath11k *ar)
9272dd4f32aeSBjoern A. Zeeb {
9273dd4f32aeSBjoern A. Zeeb 	struct ath11k_base *ab = ar->ab;
9274dd4f32aeSBjoern A. Zeeb 	struct ieee80211_iface_combination *combinations;
9275dd4f32aeSBjoern A. Zeeb 	struct ieee80211_iface_limit *limits;
9276dd4f32aeSBjoern A. Zeeb 	int n_limits;
9277dd4f32aeSBjoern A. Zeeb 
9278dd4f32aeSBjoern A. Zeeb 	combinations = kzalloc(sizeof(*combinations), GFP_KERNEL);
9279dd4f32aeSBjoern A. Zeeb 	if (!combinations)
9280dd4f32aeSBjoern A. Zeeb 		return -ENOMEM;
9281dd4f32aeSBjoern A. Zeeb 
9282dd4f32aeSBjoern A. Zeeb 	n_limits = 2;
9283dd4f32aeSBjoern A. Zeeb 
9284dd4f32aeSBjoern A. Zeeb 	limits = kcalloc(n_limits, sizeof(*limits), GFP_KERNEL);
9285dd4f32aeSBjoern A. Zeeb 	if (!limits) {
9286dd4f32aeSBjoern A. Zeeb 		kfree(combinations);
9287dd4f32aeSBjoern A. Zeeb 		return -ENOMEM;
9288dd4f32aeSBjoern A. Zeeb 	}
9289dd4f32aeSBjoern A. Zeeb 
9290dd4f32aeSBjoern A. Zeeb 	limits[0].max = 1;
9291dd4f32aeSBjoern A. Zeeb 	limits[0].types |= BIT(NL80211_IFTYPE_STATION);
9292dd4f32aeSBjoern A. Zeeb 
9293dd4f32aeSBjoern A. Zeeb 	limits[1].max = 16;
9294dd4f32aeSBjoern A. Zeeb 	limits[1].types |= BIT(NL80211_IFTYPE_AP);
9295dd4f32aeSBjoern A. Zeeb 
9296dd4f32aeSBjoern A. Zeeb 	if (IS_ENABLED(CONFIG_MAC80211_MESH) &&
9297dd4f32aeSBjoern A. Zeeb 	    ab->hw_params.interface_modes & BIT(NL80211_IFTYPE_MESH_POINT))
9298dd4f32aeSBjoern A. Zeeb 		limits[1].types |= BIT(NL80211_IFTYPE_MESH_POINT);
9299dd4f32aeSBjoern A. Zeeb 
9300dd4f32aeSBjoern A. Zeeb 	combinations[0].limits = limits;
9301dd4f32aeSBjoern A. Zeeb 	combinations[0].n_limits = n_limits;
9302dd4f32aeSBjoern A. Zeeb 	combinations[0].max_interfaces = 16;
9303dd4f32aeSBjoern A. Zeeb 	combinations[0].num_different_channels = 1;
9304dd4f32aeSBjoern A. Zeeb 	combinations[0].beacon_int_infra_match = true;
9305dd4f32aeSBjoern A. Zeeb 	combinations[0].beacon_int_min_gcd = 100;
9306dd4f32aeSBjoern A. Zeeb 	combinations[0].radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |
9307dd4f32aeSBjoern A. Zeeb 						BIT(NL80211_CHAN_WIDTH_20) |
9308dd4f32aeSBjoern A. Zeeb 						BIT(NL80211_CHAN_WIDTH_40) |
9309dd4f32aeSBjoern A. Zeeb 						BIT(NL80211_CHAN_WIDTH_80) |
9310dd4f32aeSBjoern A. Zeeb 						BIT(NL80211_CHAN_WIDTH_80P80) |
9311dd4f32aeSBjoern A. Zeeb 						BIT(NL80211_CHAN_WIDTH_160);
9312dd4f32aeSBjoern A. Zeeb 
9313dd4f32aeSBjoern A. Zeeb 	ar->hw->wiphy->iface_combinations = combinations;
9314dd4f32aeSBjoern A. Zeeb 	ar->hw->wiphy->n_iface_combinations = 1;
9315dd4f32aeSBjoern A. Zeeb 
9316dd4f32aeSBjoern A. Zeeb 	return 0;
9317dd4f32aeSBjoern A. Zeeb }
9318dd4f32aeSBjoern A. Zeeb 
9319dd4f32aeSBjoern A. Zeeb static const u8 ath11k_if_types_ext_capa[] = {
9320dd4f32aeSBjoern A. Zeeb 	[0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
9321*28348caeSBjoern A. Zeeb 	[2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT,
9322dd4f32aeSBjoern A. Zeeb 	[7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
9323dd4f32aeSBjoern A. Zeeb };
9324dd4f32aeSBjoern A. Zeeb 
9325dd4f32aeSBjoern A. Zeeb static const u8 ath11k_if_types_ext_capa_sta[] = {
9326dd4f32aeSBjoern A. Zeeb 	[0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
9327*28348caeSBjoern A. Zeeb 	[2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT,
9328dd4f32aeSBjoern A. Zeeb 	[7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
9329dd4f32aeSBjoern A. Zeeb 	[9] = WLAN_EXT_CAPA10_TWT_REQUESTER_SUPPORT,
9330dd4f32aeSBjoern A. Zeeb };
9331dd4f32aeSBjoern A. Zeeb 
9332dd4f32aeSBjoern A. Zeeb static const u8 ath11k_if_types_ext_capa_ap[] = {
9333dd4f32aeSBjoern A. Zeeb 	[0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
9334*28348caeSBjoern A. Zeeb 	[2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT,
9335dd4f32aeSBjoern A. Zeeb 	[7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
9336dd4f32aeSBjoern A. Zeeb 	[9] = WLAN_EXT_CAPA10_TWT_RESPONDER_SUPPORT,
9337*28348caeSBjoern A. Zeeb 	[10] = WLAN_EXT_CAPA11_EMA_SUPPORT,
9338dd4f32aeSBjoern A. Zeeb };
9339dd4f32aeSBjoern A. Zeeb 
9340dd4f32aeSBjoern A. Zeeb static const struct wiphy_iftype_ext_capab ath11k_iftypes_ext_capa[] = {
9341dd4f32aeSBjoern A. Zeeb 	{
9342dd4f32aeSBjoern A. Zeeb 		.extended_capabilities = ath11k_if_types_ext_capa,
9343dd4f32aeSBjoern A. Zeeb 		.extended_capabilities_mask = ath11k_if_types_ext_capa,
9344dd4f32aeSBjoern A. Zeeb 		.extended_capabilities_len = sizeof(ath11k_if_types_ext_capa),
9345dd4f32aeSBjoern A. Zeeb 	}, {
9346dd4f32aeSBjoern A. Zeeb 		.iftype = NL80211_IFTYPE_STATION,
9347dd4f32aeSBjoern A. Zeeb 		.extended_capabilities = ath11k_if_types_ext_capa_sta,
9348dd4f32aeSBjoern A. Zeeb 		.extended_capabilities_mask = ath11k_if_types_ext_capa_sta,
9349dd4f32aeSBjoern A. Zeeb 		.extended_capabilities_len =
9350dd4f32aeSBjoern A. Zeeb 				sizeof(ath11k_if_types_ext_capa_sta),
9351dd4f32aeSBjoern A. Zeeb 	}, {
9352dd4f32aeSBjoern A. Zeeb 		.iftype = NL80211_IFTYPE_AP,
9353dd4f32aeSBjoern A. Zeeb 		.extended_capabilities = ath11k_if_types_ext_capa_ap,
9354dd4f32aeSBjoern A. Zeeb 		.extended_capabilities_mask = ath11k_if_types_ext_capa_ap,
9355dd4f32aeSBjoern A. Zeeb 		.extended_capabilities_len =
9356dd4f32aeSBjoern A. Zeeb 				sizeof(ath11k_if_types_ext_capa_ap),
9357dd4f32aeSBjoern A. Zeeb 	},
9358dd4f32aeSBjoern A. Zeeb };
9359dd4f32aeSBjoern A. Zeeb 
__ath11k_mac_unregister(struct ath11k * ar)9360dd4f32aeSBjoern A. Zeeb static void __ath11k_mac_unregister(struct ath11k *ar)
9361dd4f32aeSBjoern A. Zeeb {
9362dd4f32aeSBjoern A. Zeeb 	cancel_work_sync(&ar->regd_update_work);
9363dd4f32aeSBjoern A. Zeeb 
9364dd4f32aeSBjoern A. Zeeb 	ieee80211_unregister_hw(ar->hw);
9365dd4f32aeSBjoern A. Zeeb 
9366dd4f32aeSBjoern A. Zeeb 	idr_for_each(&ar->txmgmt_idr, ath11k_mac_tx_mgmt_pending_free, ar);
9367dd4f32aeSBjoern A. Zeeb 	idr_destroy(&ar->txmgmt_idr);
9368dd4f32aeSBjoern A. Zeeb 
9369dd4f32aeSBjoern A. Zeeb 	kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels);
9370dd4f32aeSBjoern A. Zeeb 	kfree(ar->mac.sbands[NL80211_BAND_5GHZ].channels);
9371dd4f32aeSBjoern A. Zeeb 	kfree(ar->mac.sbands[NL80211_BAND_6GHZ].channels);
9372dd4f32aeSBjoern A. Zeeb 
9373dd4f32aeSBjoern A. Zeeb 	kfree(ar->hw->wiphy->iface_combinations[0].limits);
9374dd4f32aeSBjoern A. Zeeb 	kfree(ar->hw->wiphy->iface_combinations);
9375dd4f32aeSBjoern A. Zeeb 
9376dd4f32aeSBjoern A. Zeeb 	SET_IEEE80211_DEV(ar->hw, NULL);
9377dd4f32aeSBjoern A. Zeeb }
9378dd4f32aeSBjoern A. Zeeb 
ath11k_mac_unregister(struct ath11k_base * ab)9379dd4f32aeSBjoern A. Zeeb void ath11k_mac_unregister(struct ath11k_base *ab)
9380dd4f32aeSBjoern A. Zeeb {
9381dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar;
9382dd4f32aeSBjoern A. Zeeb 	struct ath11k_pdev *pdev;
9383dd4f32aeSBjoern A. Zeeb 	int i;
9384dd4f32aeSBjoern A. Zeeb 
9385dd4f32aeSBjoern A. Zeeb 	for (i = 0; i < ab->num_radios; i++) {
9386dd4f32aeSBjoern A. Zeeb 		pdev = &ab->pdevs[i];
9387dd4f32aeSBjoern A. Zeeb 		ar = pdev->ar;
9388dd4f32aeSBjoern A. Zeeb 		if (!ar)
9389dd4f32aeSBjoern A. Zeeb 			continue;
9390dd4f32aeSBjoern A. Zeeb 
9391dd4f32aeSBjoern A. Zeeb 		__ath11k_mac_unregister(ar);
9392dd4f32aeSBjoern A. Zeeb 	}
9393*28348caeSBjoern A. Zeeb 
9394*28348caeSBjoern A. Zeeb 	ath11k_peer_rhash_tbl_destroy(ab);
9395dd4f32aeSBjoern A. Zeeb }
9396dd4f32aeSBjoern A. Zeeb 
__ath11k_mac_register(struct ath11k * ar)9397dd4f32aeSBjoern A. Zeeb static int __ath11k_mac_register(struct ath11k *ar)
9398dd4f32aeSBjoern A. Zeeb {
9399dd4f32aeSBjoern A. Zeeb 	struct ath11k_base *ab = ar->ab;
9400dd4f32aeSBjoern A. Zeeb 	struct ath11k_pdev_cap *cap = &ar->pdev->cap;
9401dd4f32aeSBjoern A. Zeeb 	static const u32 cipher_suites[] = {
9402dd4f32aeSBjoern A. Zeeb 		WLAN_CIPHER_SUITE_TKIP,
9403dd4f32aeSBjoern A. Zeeb 		WLAN_CIPHER_SUITE_CCMP,
9404dd4f32aeSBjoern A. Zeeb 		WLAN_CIPHER_SUITE_AES_CMAC,
9405dd4f32aeSBjoern A. Zeeb 		WLAN_CIPHER_SUITE_BIP_CMAC_256,
9406dd4f32aeSBjoern A. Zeeb 		WLAN_CIPHER_SUITE_BIP_GMAC_128,
9407dd4f32aeSBjoern A. Zeeb 		WLAN_CIPHER_SUITE_BIP_GMAC_256,
9408dd4f32aeSBjoern A. Zeeb 		WLAN_CIPHER_SUITE_GCMP,
9409dd4f32aeSBjoern A. Zeeb 		WLAN_CIPHER_SUITE_GCMP_256,
9410dd4f32aeSBjoern A. Zeeb 		WLAN_CIPHER_SUITE_CCMP_256,
9411dd4f32aeSBjoern A. Zeeb 	};
9412dd4f32aeSBjoern A. Zeeb 	int ret;
9413dd4f32aeSBjoern A. Zeeb 	u32 ht_cap = 0;
9414dd4f32aeSBjoern A. Zeeb 
9415dd4f32aeSBjoern A. Zeeb 	ath11k_pdev_caps_update(ar);
9416dd4f32aeSBjoern A. Zeeb 
9417dd4f32aeSBjoern A. Zeeb 	SET_IEEE80211_PERM_ADDR(ar->hw, ar->mac_addr);
9418dd4f32aeSBjoern A. Zeeb 
9419dd4f32aeSBjoern A. Zeeb 	SET_IEEE80211_DEV(ar->hw, ab->dev);
9420dd4f32aeSBjoern A. Zeeb 
9421dd4f32aeSBjoern A. Zeeb 	ret = ath11k_mac_setup_channels_rates(ar,
9422dd4f32aeSBjoern A. Zeeb 					      cap->supported_bands);
9423dd4f32aeSBjoern A. Zeeb 	if (ret)
9424dd4f32aeSBjoern A. Zeeb 		goto err;
9425dd4f32aeSBjoern A. Zeeb 
9426dd4f32aeSBjoern A. Zeeb 	ath11k_mac_setup_ht_vht_cap(ar, cap, &ht_cap);
9427dd4f32aeSBjoern A. Zeeb 	ath11k_mac_setup_he_cap(ar, cap);
9428dd4f32aeSBjoern A. Zeeb 
9429dd4f32aeSBjoern A. Zeeb 	ret = ath11k_mac_setup_iface_combinations(ar);
9430dd4f32aeSBjoern A. Zeeb 	if (ret) {
9431dd4f32aeSBjoern A. Zeeb 		ath11k_err(ar->ab, "failed to setup interface combinations: %d\n", ret);
9432dd4f32aeSBjoern A. Zeeb 		goto err_free_channels;
9433dd4f32aeSBjoern A. Zeeb 	}
9434dd4f32aeSBjoern A. Zeeb 
9435dd4f32aeSBjoern A. Zeeb 	ar->hw->wiphy->available_antennas_rx = cap->rx_chain_mask;
9436dd4f32aeSBjoern A. Zeeb 	ar->hw->wiphy->available_antennas_tx = cap->tx_chain_mask;
9437dd4f32aeSBjoern A. Zeeb 
9438dd4f32aeSBjoern A. Zeeb 	ar->hw->wiphy->interface_modes = ab->hw_params.interface_modes;
9439dd4f32aeSBjoern A. Zeeb 
9440dd4f32aeSBjoern A. Zeeb 	if (ab->hw_params.single_pdev_only && ar->supports_6ghz)
9441dd4f32aeSBjoern A. Zeeb 		ieee80211_hw_set(ar->hw, SINGLE_SCAN_ON_ALL_BANDS);
9442dd4f32aeSBjoern A. Zeeb 
9443*28348caeSBjoern A. Zeeb 	if (ab->hw_params.supports_multi_bssid) {
9444*28348caeSBjoern A. Zeeb 		ieee80211_hw_set(ar->hw, SUPPORTS_MULTI_BSSID);
9445*28348caeSBjoern A. Zeeb 		ieee80211_hw_set(ar->hw, SUPPORTS_ONLY_HE_MULTI_BSSID);
9446*28348caeSBjoern A. Zeeb 	}
9447*28348caeSBjoern A. Zeeb 
9448dd4f32aeSBjoern A. Zeeb 	ieee80211_hw_set(ar->hw, SIGNAL_DBM);
9449dd4f32aeSBjoern A. Zeeb 	ieee80211_hw_set(ar->hw, SUPPORTS_PS);
9450dd4f32aeSBjoern A. Zeeb 	ieee80211_hw_set(ar->hw, SUPPORTS_DYNAMIC_PS);
9451dd4f32aeSBjoern A. Zeeb 	ieee80211_hw_set(ar->hw, MFP_CAPABLE);
9452dd4f32aeSBjoern A. Zeeb 	ieee80211_hw_set(ar->hw, REPORTS_TX_ACK_STATUS);
9453dd4f32aeSBjoern A. Zeeb 	ieee80211_hw_set(ar->hw, HAS_RATE_CONTROL);
9454dd4f32aeSBjoern A. Zeeb 	ieee80211_hw_set(ar->hw, AP_LINK_PS);
9455dd4f32aeSBjoern A. Zeeb 	ieee80211_hw_set(ar->hw, SPECTRUM_MGMT);
9456dd4f32aeSBjoern A. Zeeb 	ieee80211_hw_set(ar->hw, CONNECTION_MONITOR);
9457dd4f32aeSBjoern A. Zeeb 	ieee80211_hw_set(ar->hw, SUPPORTS_PER_STA_GTK);
9458dd4f32aeSBjoern A. Zeeb 	ieee80211_hw_set(ar->hw, WANT_MONITOR_VIF);
9459dd4f32aeSBjoern A. Zeeb 	ieee80211_hw_set(ar->hw, CHANCTX_STA_CSA);
9460dd4f32aeSBjoern A. Zeeb 	ieee80211_hw_set(ar->hw, QUEUE_CONTROL);
9461dd4f32aeSBjoern A. Zeeb 	ieee80211_hw_set(ar->hw, SUPPORTS_TX_FRAG);
9462dd4f32aeSBjoern A. Zeeb 	ieee80211_hw_set(ar->hw, REPORTS_LOW_ACK);
9463dd4f32aeSBjoern A. Zeeb 
9464dd4f32aeSBjoern A. Zeeb 	if (ath11k_frame_mode == ATH11K_HW_TXRX_ETHERNET) {
9465dd4f32aeSBjoern A. Zeeb 		ieee80211_hw_set(ar->hw, SUPPORTS_TX_ENCAP_OFFLOAD);
9466dd4f32aeSBjoern A. Zeeb 		ieee80211_hw_set(ar->hw, SUPPORTS_RX_DECAP_OFFLOAD);
9467dd4f32aeSBjoern A. Zeeb 	}
9468dd4f32aeSBjoern A. Zeeb 
9469dd4f32aeSBjoern A. Zeeb 	if (cap->nss_ratio_enabled)
9470dd4f32aeSBjoern A. Zeeb 		ieee80211_hw_set(ar->hw, SUPPORTS_VHT_EXT_NSS_BW);
9471dd4f32aeSBjoern A. Zeeb 
9472dd4f32aeSBjoern A. Zeeb 	if ((ht_cap & WMI_HT_CAP_ENABLED) || ar->supports_6ghz) {
9473dd4f32aeSBjoern A. Zeeb 		ieee80211_hw_set(ar->hw, AMPDU_AGGREGATION);
9474dd4f32aeSBjoern A. Zeeb 		ieee80211_hw_set(ar->hw, TX_AMPDU_SETUP_IN_HW);
9475dd4f32aeSBjoern A. Zeeb 		ieee80211_hw_set(ar->hw, SUPPORTS_REORDERING_BUFFER);
9476dd4f32aeSBjoern A. Zeeb 		ieee80211_hw_set(ar->hw, SUPPORTS_AMSDU_IN_AMPDU);
9477dd4f32aeSBjoern A. Zeeb 		ieee80211_hw_set(ar->hw, USES_RSS);
9478dd4f32aeSBjoern A. Zeeb 	}
9479dd4f32aeSBjoern A. Zeeb 
9480dd4f32aeSBjoern A. Zeeb 	ar->hw->wiphy->features |= NL80211_FEATURE_STATIC_SMPS;
9481dd4f32aeSBjoern A. Zeeb 	ar->hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
9482dd4f32aeSBjoern A. Zeeb 
9483dd4f32aeSBjoern A. Zeeb 	/* TODO: Check if HT capability advertised from firmware is different
9484dd4f32aeSBjoern A. Zeeb 	 * for each band for a dual band capable radio. It will be tricky to
9485dd4f32aeSBjoern A. Zeeb 	 * handle it when the ht capability different for each band.
9486dd4f32aeSBjoern A. Zeeb 	 */
9487dd4f32aeSBjoern A. Zeeb 	if (ht_cap & WMI_HT_CAP_DYNAMIC_SMPS ||
9488dd4f32aeSBjoern A. Zeeb 	    (ar->supports_6ghz && ab->hw_params.supports_dynamic_smps_6ghz))
9489dd4f32aeSBjoern A. Zeeb 		ar->hw->wiphy->features |= NL80211_FEATURE_DYNAMIC_SMPS;
9490dd4f32aeSBjoern A. Zeeb 
9491dd4f32aeSBjoern A. Zeeb 	ar->hw->wiphy->max_scan_ssids = WLAN_SCAN_PARAMS_MAX_SSID;
9492dd4f32aeSBjoern A. Zeeb 	ar->hw->wiphy->max_scan_ie_len = WLAN_SCAN_PARAMS_MAX_IE_LEN;
9493dd4f32aeSBjoern A. Zeeb 
9494dd4f32aeSBjoern A. Zeeb 	ar->hw->max_listen_interval = ATH11K_MAX_HW_LISTEN_INTERVAL;
9495dd4f32aeSBjoern A. Zeeb 
9496dd4f32aeSBjoern A. Zeeb 	ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
9497dd4f32aeSBjoern A. Zeeb 	ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
9498dd4f32aeSBjoern A. Zeeb 	ar->hw->wiphy->max_remain_on_channel_duration = 5000;
9499dd4f32aeSBjoern A. Zeeb 
9500dd4f32aeSBjoern A. Zeeb 	ar->hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
9501dd4f32aeSBjoern A. Zeeb 	ar->hw->wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE |
9502dd4f32aeSBjoern A. Zeeb 				   NL80211_FEATURE_AP_SCAN;
9503dd4f32aeSBjoern A. Zeeb 
9504dd4f32aeSBjoern A. Zeeb 	ar->max_num_stations = TARGET_NUM_STATIONS(ab);
9505dd4f32aeSBjoern A. Zeeb 	ar->max_num_peers = TARGET_NUM_PEERS_PDEV(ab);
9506dd4f32aeSBjoern A. Zeeb 
9507dd4f32aeSBjoern A. Zeeb 	ar->hw->wiphy->max_ap_assoc_sta = ar->max_num_stations;
9508dd4f32aeSBjoern A. Zeeb 
9509dd4f32aeSBjoern A. Zeeb 	if (test_bit(WMI_TLV_SERVICE_SPOOF_MAC_SUPPORT, ar->wmi->wmi_ab->svc_map)) {
9510dd4f32aeSBjoern A. Zeeb 		ar->hw->wiphy->features |=
9511dd4f32aeSBjoern A. Zeeb 			NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
9512dd4f32aeSBjoern A. Zeeb 	}
9513dd4f32aeSBjoern A. Zeeb 
9514*28348caeSBjoern A. Zeeb 	if (test_bit(WMI_TLV_SERVICE_NLO, ar->wmi->wmi_ab->svc_map)) {
9515*28348caeSBjoern A. Zeeb 		ar->hw->wiphy->max_sched_scan_ssids = WMI_PNO_MAX_SUPP_NETWORKS;
9516*28348caeSBjoern A. Zeeb 		ar->hw->wiphy->max_match_sets = WMI_PNO_MAX_SUPP_NETWORKS;
9517*28348caeSBjoern A. Zeeb 		ar->hw->wiphy->max_sched_scan_ie_len = WMI_PNO_MAX_IE_LENGTH;
9518*28348caeSBjoern A. Zeeb 		ar->hw->wiphy->max_sched_scan_plans = WMI_PNO_MAX_SCHED_SCAN_PLANS;
9519*28348caeSBjoern A. Zeeb 		ar->hw->wiphy->max_sched_scan_plan_interval =
9520*28348caeSBjoern A. Zeeb 			WMI_PNO_MAX_SCHED_SCAN_PLAN_INT;
9521*28348caeSBjoern A. Zeeb 		ar->hw->wiphy->max_sched_scan_plan_iterations =
9522*28348caeSBjoern A. Zeeb 			WMI_PNO_MAX_SCHED_SCAN_PLAN_ITRNS;
9523*28348caeSBjoern A. Zeeb 		ar->hw->wiphy->features |= NL80211_FEATURE_ND_RANDOM_MAC_ADDR;
9524*28348caeSBjoern A. Zeeb 	}
9525*28348caeSBjoern A. Zeeb 
9526*28348caeSBjoern A. Zeeb 	ret = ath11k_wow_init(ar);
9527*28348caeSBjoern A. Zeeb 	if (ret) {
9528*28348caeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to init wow: %d\n", ret);
9529*28348caeSBjoern A. Zeeb 		goto err_free_if_combs;
9530*28348caeSBjoern A. Zeeb 	}
9531*28348caeSBjoern A. Zeeb 
9532*28348caeSBjoern A. Zeeb 	if (test_bit(WMI_TLV_SERVICE_TX_DATA_MGMT_ACK_RSSI,
9533*28348caeSBjoern A. Zeeb 		     ar->ab->wmi_ab.svc_map))
9534*28348caeSBjoern A. Zeeb 		wiphy_ext_feature_set(ar->hw->wiphy,
9535*28348caeSBjoern A. Zeeb 				      NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT);
9536*28348caeSBjoern A. Zeeb 
9537dd4f32aeSBjoern A. Zeeb 	ar->hw->queues = ATH11K_HW_MAX_QUEUES;
9538dd4f32aeSBjoern A. Zeeb 	ar->hw->wiphy->tx_queue_len = ATH11K_QUEUE_LEN;
9539dd4f32aeSBjoern A. Zeeb 	ar->hw->offchannel_tx_hw_queue = ATH11K_HW_MAX_QUEUES - 1;
9540*28348caeSBjoern A. Zeeb 	ar->hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE;
9541dd4f32aeSBjoern A. Zeeb 
9542dd4f32aeSBjoern A. Zeeb 	ar->hw->vif_data_size = sizeof(struct ath11k_vif);
9543dd4f32aeSBjoern A. Zeeb 	ar->hw->sta_data_size = sizeof(struct ath11k_sta);
9544dd4f32aeSBjoern A. Zeeb 
9545dd4f32aeSBjoern A. Zeeb 	wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
9546dd4f32aeSBjoern A. Zeeb 	wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_STA_TX_PWR);
9547*28348caeSBjoern A. Zeeb 	if (test_bit(WMI_TLV_SERVICE_BSS_COLOR_OFFLOAD,
9548*28348caeSBjoern A. Zeeb 		     ar->ab->wmi_ab.svc_map)) {
9549dd4f32aeSBjoern A. Zeeb 		wiphy_ext_feature_set(ar->hw->wiphy,
9550dd4f32aeSBjoern A. Zeeb 				      NL80211_EXT_FEATURE_BSS_COLOR);
9551*28348caeSBjoern A. Zeeb 		ieee80211_hw_set(ar->hw, DETECTS_COLOR_COLLISION);
9552*28348caeSBjoern A. Zeeb 	}
9553dd4f32aeSBjoern A. Zeeb 
9554dd4f32aeSBjoern A. Zeeb 	ar->hw->wiphy->cipher_suites = cipher_suites;
9555dd4f32aeSBjoern A. Zeeb 	ar->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
9556dd4f32aeSBjoern A. Zeeb 
9557dd4f32aeSBjoern A. Zeeb 	ar->hw->wiphy->iftype_ext_capab = ath11k_iftypes_ext_capa;
9558dd4f32aeSBjoern A. Zeeb 	ar->hw->wiphy->num_iftype_ext_capab =
9559dd4f32aeSBjoern A. Zeeb 		ARRAY_SIZE(ath11k_iftypes_ext_capa);
9560dd4f32aeSBjoern A. Zeeb 
9561dd4f32aeSBjoern A. Zeeb 	if (ar->supports_6ghz) {
9562dd4f32aeSBjoern A. Zeeb 		wiphy_ext_feature_set(ar->hw->wiphy,
9563dd4f32aeSBjoern A. Zeeb 				      NL80211_EXT_FEATURE_FILS_DISCOVERY);
9564dd4f32aeSBjoern A. Zeeb 		wiphy_ext_feature_set(ar->hw->wiphy,
9565dd4f32aeSBjoern A. Zeeb 				      NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP);
9566dd4f32aeSBjoern A. Zeeb 	}
9567dd4f32aeSBjoern A. Zeeb 
9568*28348caeSBjoern A. Zeeb 	wiphy_ext_feature_set(ar->hw->wiphy,
9569*28348caeSBjoern A. Zeeb 			      NL80211_EXT_FEATURE_SET_SCAN_DWELL);
9570*28348caeSBjoern A. Zeeb 
9571*28348caeSBjoern A. Zeeb 	if (test_bit(WMI_TLV_SERVICE_RTT, ar->ab->wmi_ab.svc_map))
9572*28348caeSBjoern A. Zeeb 		wiphy_ext_feature_set(ar->hw->wiphy,
9573*28348caeSBjoern A. Zeeb 				      NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER);
9574*28348caeSBjoern A. Zeeb 
9575*28348caeSBjoern A. Zeeb 	ar->hw->wiphy->mbssid_max_interfaces = TARGET_NUM_VDEVS(ab);
9576*28348caeSBjoern A. Zeeb 	ar->hw->wiphy->ema_max_profile_periodicity = TARGET_EMA_MAX_PROFILE_PERIOD;
9577*28348caeSBjoern A. Zeeb 
9578dd4f32aeSBjoern A. Zeeb 	ath11k_reg_init(ar);
9579dd4f32aeSBjoern A. Zeeb 
9580dd4f32aeSBjoern A. Zeeb 	if (!test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags)) {
9581dd4f32aeSBjoern A. Zeeb 		ar->hw->netdev_features = NETIF_F_HW_CSUM;
9582dd4f32aeSBjoern A. Zeeb 		ieee80211_hw_set(ar->hw, SW_CRYPTO_CONTROL);
9583dd4f32aeSBjoern A. Zeeb 		ieee80211_hw_set(ar->hw, SUPPORT_FAST_XMIT);
9584dd4f32aeSBjoern A. Zeeb 	}
9585dd4f32aeSBjoern A. Zeeb 
9586*28348caeSBjoern A. Zeeb 	if (test_bit(WMI_TLV_SERVICE_BIOS_SAR_SUPPORT, ar->ab->wmi_ab.svc_map) &&
9587*28348caeSBjoern A. Zeeb 	    ab->hw_params.bios_sar_capa)
9588*28348caeSBjoern A. Zeeb 		ar->hw->wiphy->sar_capa = ab->hw_params.bios_sar_capa;
9589*28348caeSBjoern A. Zeeb 
9590dd4f32aeSBjoern A. Zeeb 	ret = ieee80211_register_hw(ar->hw);
9591dd4f32aeSBjoern A. Zeeb 	if (ret) {
9592dd4f32aeSBjoern A. Zeeb 		ath11k_err(ar->ab, "ieee80211 registration failed: %d\n", ret);
9593dd4f32aeSBjoern A. Zeeb 		goto err_free_if_combs;
9594dd4f32aeSBjoern A. Zeeb 	}
9595dd4f32aeSBjoern A. Zeeb 
9596dd4f32aeSBjoern A. Zeeb 	if (!ab->hw_params.supports_monitor)
9597dd4f32aeSBjoern A. Zeeb 		/* There's a race between calling ieee80211_register_hw()
9598dd4f32aeSBjoern A. Zeeb 		 * and here where the monitor mode is enabled for a little
9599dd4f32aeSBjoern A. Zeeb 		 * while. But that time is so short and in practise it make
9600dd4f32aeSBjoern A. Zeeb 		 * a difference in real life.
9601dd4f32aeSBjoern A. Zeeb 		 */
9602dd4f32aeSBjoern A. Zeeb 		ar->hw->wiphy->interface_modes &= ~BIT(NL80211_IFTYPE_MONITOR);
9603dd4f32aeSBjoern A. Zeeb 
9604dd4f32aeSBjoern A. Zeeb 	/* Apply the regd received during initialization */
9605dd4f32aeSBjoern A. Zeeb 	ret = ath11k_regd_update(ar);
9606dd4f32aeSBjoern A. Zeeb 	if (ret) {
9607dd4f32aeSBjoern A. Zeeb 		ath11k_err(ar->ab, "ath11k regd update failed: %d\n", ret);
9608dd4f32aeSBjoern A. Zeeb 		goto err_unregister_hw;
9609dd4f32aeSBjoern A. Zeeb 	}
9610dd4f32aeSBjoern A. Zeeb 
9611*28348caeSBjoern A. Zeeb 	if (ab->hw_params.current_cc_support && ab->new_alpha2[0]) {
9612*28348caeSBjoern A. Zeeb 		struct wmi_set_current_country_params set_current_param = {};
9613*28348caeSBjoern A. Zeeb 
9614*28348caeSBjoern A. Zeeb 		memcpy(&set_current_param.alpha2, ab->new_alpha2, 2);
9615*28348caeSBjoern A. Zeeb 		memcpy(&ar->alpha2, ab->new_alpha2, 2);
9616*28348caeSBjoern A. Zeeb 		ret = ath11k_wmi_send_set_current_country_cmd(ar, &set_current_param);
9617*28348caeSBjoern A. Zeeb 		if (ret)
9618*28348caeSBjoern A. Zeeb 			ath11k_warn(ar->ab,
9619*28348caeSBjoern A. Zeeb 				    "failed set cc code for mac register: %d\n", ret);
9620*28348caeSBjoern A. Zeeb 	}
9621*28348caeSBjoern A. Zeeb 
9622dd4f32aeSBjoern A. Zeeb 	ret = ath11k_debugfs_register(ar);
9623dd4f32aeSBjoern A. Zeeb 	if (ret) {
9624dd4f32aeSBjoern A. Zeeb 		ath11k_err(ar->ab, "debugfs registration failed: %d\n", ret);
9625dd4f32aeSBjoern A. Zeeb 		goto err_unregister_hw;
9626dd4f32aeSBjoern A. Zeeb 	}
9627dd4f32aeSBjoern A. Zeeb 
9628dd4f32aeSBjoern A. Zeeb 	return 0;
9629dd4f32aeSBjoern A. Zeeb 
9630dd4f32aeSBjoern A. Zeeb err_unregister_hw:
9631dd4f32aeSBjoern A. Zeeb 	ieee80211_unregister_hw(ar->hw);
9632dd4f32aeSBjoern A. Zeeb 
9633dd4f32aeSBjoern A. Zeeb err_free_if_combs:
9634dd4f32aeSBjoern A. Zeeb 	kfree(ar->hw->wiphy->iface_combinations[0].limits);
9635dd4f32aeSBjoern A. Zeeb 	kfree(ar->hw->wiphy->iface_combinations);
9636dd4f32aeSBjoern A. Zeeb 
9637dd4f32aeSBjoern A. Zeeb err_free_channels:
9638dd4f32aeSBjoern A. Zeeb 	kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels);
9639dd4f32aeSBjoern A. Zeeb 	kfree(ar->mac.sbands[NL80211_BAND_5GHZ].channels);
9640dd4f32aeSBjoern A. Zeeb 	kfree(ar->mac.sbands[NL80211_BAND_6GHZ].channels);
9641dd4f32aeSBjoern A. Zeeb 
9642dd4f32aeSBjoern A. Zeeb err:
9643dd4f32aeSBjoern A. Zeeb 	SET_IEEE80211_DEV(ar->hw, NULL);
9644dd4f32aeSBjoern A. Zeeb 	return ret;
9645dd4f32aeSBjoern A. Zeeb }
9646dd4f32aeSBjoern A. Zeeb 
ath11k_mac_register(struct ath11k_base * ab)9647dd4f32aeSBjoern A. Zeeb int ath11k_mac_register(struct ath11k_base *ab)
9648dd4f32aeSBjoern A. Zeeb {
9649dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar;
9650dd4f32aeSBjoern A. Zeeb 	struct ath11k_pdev *pdev;
9651dd4f32aeSBjoern A. Zeeb 	int i;
9652dd4f32aeSBjoern A. Zeeb 	int ret;
9653*28348caeSBjoern A. Zeeb 	u8 mac_addr[ETH_ALEN] = {0};
9654dd4f32aeSBjoern A. Zeeb 
9655dd4f32aeSBjoern A. Zeeb 	if (test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags))
9656dd4f32aeSBjoern A. Zeeb 		return 0;
9657dd4f32aeSBjoern A. Zeeb 
9658dd4f32aeSBjoern A. Zeeb 	/* Initialize channel counters frequency value in hertz */
9659dd4f32aeSBjoern A. Zeeb 	ab->cc_freq_hz = IPQ8074_CC_FREQ_HERTZ;
9660dd4f32aeSBjoern A. Zeeb 	ab->free_vdev_map = (1LL << (ab->num_radios * TARGET_NUM_VDEVS(ab))) - 1;
9661dd4f32aeSBjoern A. Zeeb 
9662*28348caeSBjoern A. Zeeb 	ret = ath11k_peer_rhash_tbl_init(ab);
9663*28348caeSBjoern A. Zeeb 	if (ret)
9664*28348caeSBjoern A. Zeeb 		return ret;
9665*28348caeSBjoern A. Zeeb 
9666*28348caeSBjoern A. Zeeb 	device_get_mac_address(ab->dev, mac_addr);
9667*28348caeSBjoern A. Zeeb 
9668dd4f32aeSBjoern A. Zeeb 	for (i = 0; i < ab->num_radios; i++) {
9669dd4f32aeSBjoern A. Zeeb 		pdev = &ab->pdevs[i];
9670dd4f32aeSBjoern A. Zeeb 		ar = pdev->ar;
9671dd4f32aeSBjoern A. Zeeb 		if (ab->pdevs_macaddr_valid) {
9672dd4f32aeSBjoern A. Zeeb 			ether_addr_copy(ar->mac_addr, pdev->mac_addr);
9673dd4f32aeSBjoern A. Zeeb 		} else {
9674*28348caeSBjoern A. Zeeb 			if (is_zero_ether_addr(mac_addr))
9675dd4f32aeSBjoern A. Zeeb 				ether_addr_copy(ar->mac_addr, ab->mac_addr);
9676*28348caeSBjoern A. Zeeb 			else
9677*28348caeSBjoern A. Zeeb 				ether_addr_copy(ar->mac_addr, mac_addr);
9678dd4f32aeSBjoern A. Zeeb 			ar->mac_addr[4] += i;
9679dd4f32aeSBjoern A. Zeeb 		}
9680dd4f32aeSBjoern A. Zeeb 
9681dd4f32aeSBjoern A. Zeeb 		idr_init(&ar->txmgmt_idr);
9682dd4f32aeSBjoern A. Zeeb 		spin_lock_init(&ar->txmgmt_idr_lock);
9683dd4f32aeSBjoern A. Zeeb 
9684dd4f32aeSBjoern A. Zeeb 		ret = __ath11k_mac_register(ar);
9685dd4f32aeSBjoern A. Zeeb 		if (ret)
9686dd4f32aeSBjoern A. Zeeb 			goto err_cleanup;
9687dd4f32aeSBjoern A. Zeeb 
9688dd4f32aeSBjoern A. Zeeb 		init_waitqueue_head(&ar->txmgmt_empty_waitq);
9689dd4f32aeSBjoern A. Zeeb 	}
9690dd4f32aeSBjoern A. Zeeb 
9691dd4f32aeSBjoern A. Zeeb 	return 0;
9692dd4f32aeSBjoern A. Zeeb 
9693dd4f32aeSBjoern A. Zeeb err_cleanup:
9694dd4f32aeSBjoern A. Zeeb 	for (i = i - 1; i >= 0; i--) {
9695dd4f32aeSBjoern A. Zeeb 		pdev = &ab->pdevs[i];
9696dd4f32aeSBjoern A. Zeeb 		ar = pdev->ar;
9697dd4f32aeSBjoern A. Zeeb 		__ath11k_mac_unregister(ar);
9698dd4f32aeSBjoern A. Zeeb 	}
9699dd4f32aeSBjoern A. Zeeb 
9700*28348caeSBjoern A. Zeeb 	ath11k_peer_rhash_tbl_destroy(ab);
9701*28348caeSBjoern A. Zeeb 
9702dd4f32aeSBjoern A. Zeeb 	return ret;
9703dd4f32aeSBjoern A. Zeeb }
9704dd4f32aeSBjoern A. Zeeb 
ath11k_mac_allocate(struct ath11k_base * ab)9705dd4f32aeSBjoern A. Zeeb int ath11k_mac_allocate(struct ath11k_base *ab)
9706dd4f32aeSBjoern A. Zeeb {
9707dd4f32aeSBjoern A. Zeeb 	struct ieee80211_hw *hw;
9708dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar;
9709dd4f32aeSBjoern A. Zeeb 	struct ath11k_pdev *pdev;
9710dd4f32aeSBjoern A. Zeeb 	int ret;
9711dd4f32aeSBjoern A. Zeeb 	int i;
9712dd4f32aeSBjoern A. Zeeb 
9713dd4f32aeSBjoern A. Zeeb 	if (test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags))
9714dd4f32aeSBjoern A. Zeeb 		return 0;
9715dd4f32aeSBjoern A. Zeeb 
9716dd4f32aeSBjoern A. Zeeb 	for (i = 0; i < ab->num_radios; i++) {
9717dd4f32aeSBjoern A. Zeeb 		pdev = &ab->pdevs[i];
9718dd4f32aeSBjoern A. Zeeb 		hw = ieee80211_alloc_hw(sizeof(struct ath11k), &ath11k_ops);
9719dd4f32aeSBjoern A. Zeeb 		if (!hw) {
9720dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ab, "failed to allocate mac80211 hw device\n");
9721dd4f32aeSBjoern A. Zeeb 			ret = -ENOMEM;
9722dd4f32aeSBjoern A. Zeeb 			goto err_free_mac;
9723dd4f32aeSBjoern A. Zeeb 		}
9724dd4f32aeSBjoern A. Zeeb 
9725dd4f32aeSBjoern A. Zeeb 		ar = hw->priv;
9726dd4f32aeSBjoern A. Zeeb 		ar->hw = hw;
9727dd4f32aeSBjoern A. Zeeb 		ar->ab = ab;
9728dd4f32aeSBjoern A. Zeeb 		ar->pdev = pdev;
9729dd4f32aeSBjoern A. Zeeb 		ar->pdev_idx = i;
9730dd4f32aeSBjoern A. Zeeb 		ar->lmac_id = ath11k_hw_get_mac_from_pdev_id(&ab->hw_params, i);
9731dd4f32aeSBjoern A. Zeeb 
9732dd4f32aeSBjoern A. Zeeb 		ar->wmi = &ab->wmi_ab.wmi[i];
9733dd4f32aeSBjoern A. Zeeb 		/* FIXME wmi[0] is already initialized during attach,
9734dd4f32aeSBjoern A. Zeeb 		 * Should we do this again?
9735dd4f32aeSBjoern A. Zeeb 		 */
9736dd4f32aeSBjoern A. Zeeb 		ath11k_wmi_pdev_attach(ab, i);
9737dd4f32aeSBjoern A. Zeeb 
9738dd4f32aeSBjoern A. Zeeb 		ar->cfg_tx_chainmask = pdev->cap.tx_chain_mask;
9739dd4f32aeSBjoern A. Zeeb 		ar->cfg_rx_chainmask = pdev->cap.rx_chain_mask;
9740dd4f32aeSBjoern A. Zeeb 		ar->num_tx_chains = get_num_chains(pdev->cap.tx_chain_mask);
9741dd4f32aeSBjoern A. Zeeb 		ar->num_rx_chains = get_num_chains(pdev->cap.rx_chain_mask);
9742dd4f32aeSBjoern A. Zeeb 
9743dd4f32aeSBjoern A. Zeeb 		pdev->ar = ar;
9744dd4f32aeSBjoern A. Zeeb 		spin_lock_init(&ar->data_lock);
9745dd4f32aeSBjoern A. Zeeb 		INIT_LIST_HEAD(&ar->arvifs);
9746dd4f32aeSBjoern A. Zeeb 		INIT_LIST_HEAD(&ar->ppdu_stats_info);
9747dd4f32aeSBjoern A. Zeeb 		mutex_init(&ar->conf_mutex);
9748dd4f32aeSBjoern A. Zeeb 		init_completion(&ar->vdev_setup_done);
9749dd4f32aeSBjoern A. Zeeb 		init_completion(&ar->vdev_delete_done);
9750dd4f32aeSBjoern A. Zeeb 		init_completion(&ar->peer_assoc_done);
9751dd4f32aeSBjoern A. Zeeb 		init_completion(&ar->peer_delete_done);
9752dd4f32aeSBjoern A. Zeeb 		init_completion(&ar->install_key_done);
9753dd4f32aeSBjoern A. Zeeb 		init_completion(&ar->bss_survey_done);
9754dd4f32aeSBjoern A. Zeeb 		init_completion(&ar->scan.started);
9755dd4f32aeSBjoern A. Zeeb 		init_completion(&ar->scan.completed);
9756*28348caeSBjoern A. Zeeb 		init_completion(&ar->scan.on_channel);
9757dd4f32aeSBjoern A. Zeeb 		init_completion(&ar->thermal.wmi_sync);
9758dd4f32aeSBjoern A. Zeeb 
9759dd4f32aeSBjoern A. Zeeb 		INIT_DELAYED_WORK(&ar->scan.timeout, ath11k_scan_timeout_work);
9760dd4f32aeSBjoern A. Zeeb 		INIT_WORK(&ar->regd_update_work, ath11k_regd_update_work);
9761dd4f32aeSBjoern A. Zeeb 
9762dd4f32aeSBjoern A. Zeeb 		INIT_WORK(&ar->wmi_mgmt_tx_work, ath11k_mgmt_over_wmi_tx_work);
9763dd4f32aeSBjoern A. Zeeb 		skb_queue_head_init(&ar->wmi_mgmt_tx_queue);
9764dd4f32aeSBjoern A. Zeeb 
9765dd4f32aeSBjoern A. Zeeb 		clear_bit(ATH11K_FLAG_MONITOR_STARTED, &ar->monitor_flags);
9766dd4f32aeSBjoern A. Zeeb 
9767dd4f32aeSBjoern A. Zeeb 		ar->monitor_vdev_id = -1;
9768dd4f32aeSBjoern A. Zeeb 		clear_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags);
9769dd4f32aeSBjoern A. Zeeb 		ar->vdev_id_11d_scan = ATH11K_11D_INVALID_VDEV_ID;
9770*28348caeSBjoern A. Zeeb 		init_completion(&ar->completed_11d_scan);
9771*28348caeSBjoern A. Zeeb 
9772*28348caeSBjoern A. Zeeb 		ath11k_fw_stats_init(ar);
9773dd4f32aeSBjoern A. Zeeb 	}
9774dd4f32aeSBjoern A. Zeeb 
9775dd4f32aeSBjoern A. Zeeb 	return 0;
9776dd4f32aeSBjoern A. Zeeb 
9777dd4f32aeSBjoern A. Zeeb err_free_mac:
9778dd4f32aeSBjoern A. Zeeb 	ath11k_mac_destroy(ab);
9779dd4f32aeSBjoern A. Zeeb 
9780dd4f32aeSBjoern A. Zeeb 	return ret;
9781dd4f32aeSBjoern A. Zeeb }
9782dd4f32aeSBjoern A. Zeeb 
ath11k_mac_destroy(struct ath11k_base * ab)9783dd4f32aeSBjoern A. Zeeb void ath11k_mac_destroy(struct ath11k_base *ab)
9784dd4f32aeSBjoern A. Zeeb {
9785dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar;
9786dd4f32aeSBjoern A. Zeeb 	struct ath11k_pdev *pdev;
9787dd4f32aeSBjoern A. Zeeb 	int i;
9788dd4f32aeSBjoern A. Zeeb 
9789dd4f32aeSBjoern A. Zeeb 	for (i = 0; i < ab->num_radios; i++) {
9790dd4f32aeSBjoern A. Zeeb 		pdev = &ab->pdevs[i];
9791dd4f32aeSBjoern A. Zeeb 		ar = pdev->ar;
9792dd4f32aeSBjoern A. Zeeb 		if (!ar)
9793dd4f32aeSBjoern A. Zeeb 			continue;
9794dd4f32aeSBjoern A. Zeeb 
9795*28348caeSBjoern A. Zeeb 		ath11k_fw_stats_free(&ar->fw_stats);
9796dd4f32aeSBjoern A. Zeeb 		ieee80211_free_hw(ar->hw);
9797dd4f32aeSBjoern A. Zeeb 		pdev->ar = NULL;
9798dd4f32aeSBjoern A. Zeeb 	}
9799dd4f32aeSBjoern A. Zeeb }
9800*28348caeSBjoern A. Zeeb 
ath11k_mac_vif_set_keepalive(struct ath11k_vif * arvif,enum wmi_sta_keepalive_method method,u32 interval)9801*28348caeSBjoern A. Zeeb int ath11k_mac_vif_set_keepalive(struct ath11k_vif *arvif,
9802*28348caeSBjoern A. Zeeb 				 enum wmi_sta_keepalive_method method,
9803*28348caeSBjoern A. Zeeb 				 u32 interval)
9804*28348caeSBjoern A. Zeeb {
9805*28348caeSBjoern A. Zeeb 	struct ath11k *ar = arvif->ar;
9806*28348caeSBjoern A. Zeeb 	struct wmi_sta_keepalive_arg arg = {};
9807*28348caeSBjoern A. Zeeb 	int ret;
9808*28348caeSBjoern A. Zeeb 
9809*28348caeSBjoern A. Zeeb 	lockdep_assert_held(&ar->conf_mutex);
9810*28348caeSBjoern A. Zeeb 
9811*28348caeSBjoern A. Zeeb 	if (arvif->vdev_type != WMI_VDEV_TYPE_STA)
9812*28348caeSBjoern A. Zeeb 		return 0;
9813*28348caeSBjoern A. Zeeb 
9814*28348caeSBjoern A. Zeeb 	if (!test_bit(WMI_TLV_SERVICE_STA_KEEP_ALIVE, ar->ab->wmi_ab.svc_map))
9815*28348caeSBjoern A. Zeeb 		return 0;
9816*28348caeSBjoern A. Zeeb 
9817*28348caeSBjoern A. Zeeb 	arg.vdev_id = arvif->vdev_id;
9818*28348caeSBjoern A. Zeeb 	arg.enabled = 1;
9819*28348caeSBjoern A. Zeeb 	arg.method = method;
9820*28348caeSBjoern A. Zeeb 	arg.interval = interval;
9821*28348caeSBjoern A. Zeeb 
9822*28348caeSBjoern A. Zeeb 	ret = ath11k_wmi_sta_keepalive(ar, &arg);
9823*28348caeSBjoern A. Zeeb 	if (ret) {
9824*28348caeSBjoern A. Zeeb 		ath11k_warn(ar->ab, "failed to set keepalive on vdev %i: %d\n",
9825*28348caeSBjoern A. Zeeb 			    arvif->vdev_id, ret);
9826*28348caeSBjoern A. Zeeb 		return ret;
9827*28348caeSBjoern A. Zeeb 	}
9828*28348caeSBjoern A. Zeeb 
9829*28348caeSBjoern A. Zeeb 	return 0;
9830*28348caeSBjoern A. Zeeb }
9831