xref: /openbmc/linux/drivers/net/wireless/ath/ath12k/mac.c (revision 603cf6c2)
1d8899132SKalle Valo // SPDX-License-Identifier: BSD-3-Clause-Clear
2d8899132SKalle Valo /*
3d8899132SKalle Valo  * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
4d8899132SKalle Valo  * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
5d8899132SKalle Valo  */
6d8899132SKalle Valo 
7d8899132SKalle Valo #include <net/mac80211.h>
8d8899132SKalle Valo #include <linux/etherdevice.h>
9d8899132SKalle Valo #include "mac.h"
10d8899132SKalle Valo #include "core.h"
11d8899132SKalle Valo #include "debug.h"
12d8899132SKalle Valo #include "wmi.h"
13d8899132SKalle Valo #include "hw.h"
14d8899132SKalle Valo #include "dp_tx.h"
15d8899132SKalle Valo #include "dp_rx.h"
16d8899132SKalle Valo #include "peer.h"
17d8899132SKalle Valo 
18d8899132SKalle Valo #define CHAN2G(_channel, _freq, _flags) { \
19d8899132SKalle Valo 	.band                   = NL80211_BAND_2GHZ, \
20d8899132SKalle Valo 	.hw_value               = (_channel), \
21d8899132SKalle Valo 	.center_freq            = (_freq), \
22d8899132SKalle Valo 	.flags                  = (_flags), \
23d8899132SKalle Valo 	.max_antenna_gain       = 0, \
24d8899132SKalle Valo 	.max_power              = 30, \
25d8899132SKalle Valo }
26d8899132SKalle Valo 
27d8899132SKalle Valo #define CHAN5G(_channel, _freq, _flags) { \
28d8899132SKalle Valo 	.band                   = NL80211_BAND_5GHZ, \
29d8899132SKalle Valo 	.hw_value               = (_channel), \
30d8899132SKalle Valo 	.center_freq            = (_freq), \
31d8899132SKalle Valo 	.flags                  = (_flags), \
32d8899132SKalle Valo 	.max_antenna_gain       = 0, \
33d8899132SKalle Valo 	.max_power              = 30, \
34d8899132SKalle Valo }
35d8899132SKalle Valo 
36d8899132SKalle Valo #define CHAN6G(_channel, _freq, _flags) { \
37d8899132SKalle Valo 	.band                   = NL80211_BAND_6GHZ, \
38d8899132SKalle Valo 	.hw_value               = (_channel), \
39d8899132SKalle Valo 	.center_freq            = (_freq), \
40d8899132SKalle Valo 	.flags                  = (_flags), \
41d8899132SKalle Valo 	.max_antenna_gain       = 0, \
42d8899132SKalle Valo 	.max_power              = 30, \
43d8899132SKalle Valo }
44d8899132SKalle Valo 
45d8899132SKalle Valo static const struct ieee80211_channel ath12k_2ghz_channels[] = {
46d8899132SKalle Valo 	CHAN2G(1, 2412, 0),
47d8899132SKalle Valo 	CHAN2G(2, 2417, 0),
48d8899132SKalle Valo 	CHAN2G(3, 2422, 0),
49d8899132SKalle Valo 	CHAN2G(4, 2427, 0),
50d8899132SKalle Valo 	CHAN2G(5, 2432, 0),
51d8899132SKalle Valo 	CHAN2G(6, 2437, 0),
52d8899132SKalle Valo 	CHAN2G(7, 2442, 0),
53d8899132SKalle Valo 	CHAN2G(8, 2447, 0),
54d8899132SKalle Valo 	CHAN2G(9, 2452, 0),
55d8899132SKalle Valo 	CHAN2G(10, 2457, 0),
56d8899132SKalle Valo 	CHAN2G(11, 2462, 0),
57d8899132SKalle Valo 	CHAN2G(12, 2467, 0),
58d8899132SKalle Valo 	CHAN2G(13, 2472, 0),
59d8899132SKalle Valo 	CHAN2G(14, 2484, 0),
60d8899132SKalle Valo };
61d8899132SKalle Valo 
62d8899132SKalle Valo static const struct ieee80211_channel ath12k_5ghz_channels[] = {
63d8899132SKalle Valo 	CHAN5G(36, 5180, 0),
64d8899132SKalle Valo 	CHAN5G(40, 5200, 0),
65d8899132SKalle Valo 	CHAN5G(44, 5220, 0),
66d8899132SKalle Valo 	CHAN5G(48, 5240, 0),
67d8899132SKalle Valo 	CHAN5G(52, 5260, 0),
68d8899132SKalle Valo 	CHAN5G(56, 5280, 0),
69d8899132SKalle Valo 	CHAN5G(60, 5300, 0),
70d8899132SKalle Valo 	CHAN5G(64, 5320, 0),
71d8899132SKalle Valo 	CHAN5G(100, 5500, 0),
72d8899132SKalle Valo 	CHAN5G(104, 5520, 0),
73d8899132SKalle Valo 	CHAN5G(108, 5540, 0),
74d8899132SKalle Valo 	CHAN5G(112, 5560, 0),
75d8899132SKalle Valo 	CHAN5G(116, 5580, 0),
76d8899132SKalle Valo 	CHAN5G(120, 5600, 0),
77d8899132SKalle Valo 	CHAN5G(124, 5620, 0),
78d8899132SKalle Valo 	CHAN5G(128, 5640, 0),
79d8899132SKalle Valo 	CHAN5G(132, 5660, 0),
80d8899132SKalle Valo 	CHAN5G(136, 5680, 0),
81d8899132SKalle Valo 	CHAN5G(140, 5700, 0),
82d8899132SKalle Valo 	CHAN5G(144, 5720, 0),
83d8899132SKalle Valo 	CHAN5G(149, 5745, 0),
84d8899132SKalle Valo 	CHAN5G(153, 5765, 0),
85d8899132SKalle Valo 	CHAN5G(157, 5785, 0),
86d8899132SKalle Valo 	CHAN5G(161, 5805, 0),
87d8899132SKalle Valo 	CHAN5G(165, 5825, 0),
88d8899132SKalle Valo 	CHAN5G(169, 5845, 0),
89d8899132SKalle Valo 	CHAN5G(173, 5865, 0),
90d8899132SKalle Valo };
91d8899132SKalle Valo 
92d8899132SKalle Valo static const struct ieee80211_channel ath12k_6ghz_channels[] = {
93d8899132SKalle Valo 	CHAN6G(1, 5955, 0),
94d8899132SKalle Valo 	CHAN6G(5, 5975, 0),
95d8899132SKalle Valo 	CHAN6G(9, 5995, 0),
96d8899132SKalle Valo 	CHAN6G(13, 6015, 0),
97d8899132SKalle Valo 	CHAN6G(17, 6035, 0),
98d8899132SKalle Valo 	CHAN6G(21, 6055, 0),
99d8899132SKalle Valo 	CHAN6G(25, 6075, 0),
100d8899132SKalle Valo 	CHAN6G(29, 6095, 0),
101d8899132SKalle Valo 	CHAN6G(33, 6115, 0),
102d8899132SKalle Valo 	CHAN6G(37, 6135, 0),
103d8899132SKalle Valo 	CHAN6G(41, 6155, 0),
104d8899132SKalle Valo 	CHAN6G(45, 6175, 0),
105d8899132SKalle Valo 	CHAN6G(49, 6195, 0),
106d8899132SKalle Valo 	CHAN6G(53, 6215, 0),
107d8899132SKalle Valo 	CHAN6G(57, 6235, 0),
108d8899132SKalle Valo 	CHAN6G(61, 6255, 0),
109d8899132SKalle Valo 	CHAN6G(65, 6275, 0),
110d8899132SKalle Valo 	CHAN6G(69, 6295, 0),
111d8899132SKalle Valo 	CHAN6G(73, 6315, 0),
112d8899132SKalle Valo 	CHAN6G(77, 6335, 0),
113d8899132SKalle Valo 	CHAN6G(81, 6355, 0),
114d8899132SKalle Valo 	CHAN6G(85, 6375, 0),
115d8899132SKalle Valo 	CHAN6G(89, 6395, 0),
116d8899132SKalle Valo 	CHAN6G(93, 6415, 0),
117d8899132SKalle Valo 	CHAN6G(97, 6435, 0),
118d8899132SKalle Valo 	CHAN6G(101, 6455, 0),
119d8899132SKalle Valo 	CHAN6G(105, 6475, 0),
120d8899132SKalle Valo 	CHAN6G(109, 6495, 0),
121d8899132SKalle Valo 	CHAN6G(113, 6515, 0),
122d8899132SKalle Valo 	CHAN6G(117, 6535, 0),
123d8899132SKalle Valo 	CHAN6G(121, 6555, 0),
124d8899132SKalle Valo 	CHAN6G(125, 6575, 0),
125d8899132SKalle Valo 	CHAN6G(129, 6595, 0),
126d8899132SKalle Valo 	CHAN6G(133, 6615, 0),
127d8899132SKalle Valo 	CHAN6G(137, 6635, 0),
128d8899132SKalle Valo 	CHAN6G(141, 6655, 0),
129d8899132SKalle Valo 	CHAN6G(145, 6675, 0),
130d8899132SKalle Valo 	CHAN6G(149, 6695, 0),
131d8899132SKalle Valo 	CHAN6G(153, 6715, 0),
132d8899132SKalle Valo 	CHAN6G(157, 6735, 0),
133d8899132SKalle Valo 	CHAN6G(161, 6755, 0),
134d8899132SKalle Valo 	CHAN6G(165, 6775, 0),
135d8899132SKalle Valo 	CHAN6G(169, 6795, 0),
136d8899132SKalle Valo 	CHAN6G(173, 6815, 0),
137d8899132SKalle Valo 	CHAN6G(177, 6835, 0),
138d8899132SKalle Valo 	CHAN6G(181, 6855, 0),
139d8899132SKalle Valo 	CHAN6G(185, 6875, 0),
140d8899132SKalle Valo 	CHAN6G(189, 6895, 0),
141d8899132SKalle Valo 	CHAN6G(193, 6915, 0),
142d8899132SKalle Valo 	CHAN6G(197, 6935, 0),
143d8899132SKalle Valo 	CHAN6G(201, 6955, 0),
144d8899132SKalle Valo 	CHAN6G(205, 6975, 0),
145d8899132SKalle Valo 	CHAN6G(209, 6995, 0),
146d8899132SKalle Valo 	CHAN6G(213, 7015, 0),
147d8899132SKalle Valo 	CHAN6G(217, 7035, 0),
148d8899132SKalle Valo 	CHAN6G(221, 7055, 0),
149d8899132SKalle Valo 	CHAN6G(225, 7075, 0),
150d8899132SKalle Valo 	CHAN6G(229, 7095, 0),
151d8899132SKalle Valo 	CHAN6G(233, 7115, 0),
152d8899132SKalle Valo };
153d8899132SKalle Valo 
154d8899132SKalle Valo static struct ieee80211_rate ath12k_legacy_rates[] = {
155d8899132SKalle Valo 	{ .bitrate = 10,
156d8899132SKalle Valo 	  .hw_value = ATH12K_HW_RATE_CCK_LP_1M },
157d8899132SKalle Valo 	{ .bitrate = 20,
158d8899132SKalle Valo 	  .hw_value = ATH12K_HW_RATE_CCK_LP_2M,
159d8899132SKalle Valo 	  .hw_value_short = ATH12K_HW_RATE_CCK_SP_2M,
160d8899132SKalle Valo 	  .flags = IEEE80211_RATE_SHORT_PREAMBLE },
161d8899132SKalle Valo 	{ .bitrate = 55,
162d8899132SKalle Valo 	  .hw_value = ATH12K_HW_RATE_CCK_LP_5_5M,
163d8899132SKalle Valo 	  .hw_value_short = ATH12K_HW_RATE_CCK_SP_5_5M,
164d8899132SKalle Valo 	  .flags = IEEE80211_RATE_SHORT_PREAMBLE },
165d8899132SKalle Valo 	{ .bitrate = 110,
166d8899132SKalle Valo 	  .hw_value = ATH12K_HW_RATE_CCK_LP_11M,
167d8899132SKalle Valo 	  .hw_value_short = ATH12K_HW_RATE_CCK_SP_11M,
168d8899132SKalle Valo 	  .flags = IEEE80211_RATE_SHORT_PREAMBLE },
169d8899132SKalle Valo 
170d8899132SKalle Valo 	{ .bitrate = 60, .hw_value = ATH12K_HW_RATE_OFDM_6M },
171d8899132SKalle Valo 	{ .bitrate = 90, .hw_value = ATH12K_HW_RATE_OFDM_9M },
172d8899132SKalle Valo 	{ .bitrate = 120, .hw_value = ATH12K_HW_RATE_OFDM_12M },
173d8899132SKalle Valo 	{ .bitrate = 180, .hw_value = ATH12K_HW_RATE_OFDM_18M },
174d8899132SKalle Valo 	{ .bitrate = 240, .hw_value = ATH12K_HW_RATE_OFDM_24M },
175d8899132SKalle Valo 	{ .bitrate = 360, .hw_value = ATH12K_HW_RATE_OFDM_36M },
176d8899132SKalle Valo 	{ .bitrate = 480, .hw_value = ATH12K_HW_RATE_OFDM_48M },
177d8899132SKalle Valo 	{ .bitrate = 540, .hw_value = ATH12K_HW_RATE_OFDM_54M },
178d8899132SKalle Valo };
179d8899132SKalle Valo 
180d8899132SKalle Valo static const int
181d8899132SKalle Valo ath12k_phymodes[NUM_NL80211_BANDS][ATH12K_CHAN_WIDTH_NUM] = {
182d8899132SKalle Valo 	[NL80211_BAND_2GHZ] = {
183d8899132SKalle Valo 			[NL80211_CHAN_WIDTH_5] = MODE_UNKNOWN,
184d8899132SKalle Valo 			[NL80211_CHAN_WIDTH_10] = MODE_UNKNOWN,
185d8899132SKalle Valo 			[NL80211_CHAN_WIDTH_20_NOHT] = MODE_11AX_HE20_2G,
186d8899132SKalle Valo 			[NL80211_CHAN_WIDTH_20] = MODE_11AX_HE20_2G,
187d8899132SKalle Valo 			[NL80211_CHAN_WIDTH_40] = MODE_11AX_HE40_2G,
188d8899132SKalle Valo 			[NL80211_CHAN_WIDTH_80] = MODE_11AX_HE80_2G,
189d8899132SKalle Valo 			[NL80211_CHAN_WIDTH_80P80] = MODE_UNKNOWN,
190d8899132SKalle Valo 			[NL80211_CHAN_WIDTH_160] = MODE_UNKNOWN,
191d8899132SKalle Valo 	},
192d8899132SKalle Valo 	[NL80211_BAND_5GHZ] = {
193d8899132SKalle Valo 			[NL80211_CHAN_WIDTH_5] = MODE_UNKNOWN,
194d8899132SKalle Valo 			[NL80211_CHAN_WIDTH_10] = MODE_UNKNOWN,
195d8899132SKalle Valo 			[NL80211_CHAN_WIDTH_20_NOHT] = MODE_11AX_HE20,
196d8899132SKalle Valo 			[NL80211_CHAN_WIDTH_20] = MODE_11AX_HE20,
197d8899132SKalle Valo 			[NL80211_CHAN_WIDTH_40] = MODE_11AX_HE40,
198d8899132SKalle Valo 			[NL80211_CHAN_WIDTH_80] = MODE_11AX_HE80,
199d8899132SKalle Valo 			[NL80211_CHAN_WIDTH_160] = MODE_11AX_HE160,
200d8899132SKalle Valo 			[NL80211_CHAN_WIDTH_80P80] = MODE_11AX_HE80_80,
201d8899132SKalle Valo 	},
202d8899132SKalle Valo 	[NL80211_BAND_6GHZ] = {
203d8899132SKalle Valo 			[NL80211_CHAN_WIDTH_5] = MODE_UNKNOWN,
204d8899132SKalle Valo 			[NL80211_CHAN_WIDTH_10] = MODE_UNKNOWN,
205d8899132SKalle Valo 			[NL80211_CHAN_WIDTH_20_NOHT] = MODE_11AX_HE20,
206d8899132SKalle Valo 			[NL80211_CHAN_WIDTH_20] = MODE_11AX_HE20,
207d8899132SKalle Valo 			[NL80211_CHAN_WIDTH_40] = MODE_11AX_HE40,
208d8899132SKalle Valo 			[NL80211_CHAN_WIDTH_80] = MODE_11AX_HE80,
209d8899132SKalle Valo 			[NL80211_CHAN_WIDTH_160] = MODE_11AX_HE160,
210d8899132SKalle Valo 			[NL80211_CHAN_WIDTH_80P80] = MODE_11AX_HE80_80,
211d8899132SKalle Valo 	},
212d8899132SKalle Valo 
213d8899132SKalle Valo };
214d8899132SKalle Valo 
215d8899132SKalle Valo const struct htt_rx_ring_tlv_filter ath12k_mac_mon_status_filter_default = {
216d8899132SKalle Valo 	.rx_filter = HTT_RX_FILTER_TLV_FLAGS_MPDU_START |
217d8899132SKalle Valo 		     HTT_RX_FILTER_TLV_FLAGS_PPDU_END |
218d8899132SKalle Valo 		     HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE,
219d8899132SKalle Valo 	.pkt_filter_flags0 = HTT_RX_FP_MGMT_FILTER_FLAGS0,
220d8899132SKalle Valo 	.pkt_filter_flags1 = HTT_RX_FP_MGMT_FILTER_FLAGS1,
221d8899132SKalle Valo 	.pkt_filter_flags2 = HTT_RX_FP_CTRL_FILTER_FLASG2,
222d8899132SKalle Valo 	.pkt_filter_flags3 = HTT_RX_FP_DATA_FILTER_FLASG3 |
223d8899132SKalle Valo 			     HTT_RX_FP_CTRL_FILTER_FLASG3
224d8899132SKalle Valo };
225d8899132SKalle Valo 
226d8899132SKalle Valo #define ATH12K_MAC_FIRST_OFDM_RATE_IDX 4
227d8899132SKalle Valo #define ath12k_g_rates ath12k_legacy_rates
228d8899132SKalle Valo #define ath12k_g_rates_size (ARRAY_SIZE(ath12k_legacy_rates))
229d8899132SKalle Valo #define ath12k_a_rates (ath12k_legacy_rates + 4)
230d8899132SKalle Valo #define ath12k_a_rates_size (ARRAY_SIZE(ath12k_legacy_rates) - 4)
231d8899132SKalle Valo 
232d8899132SKalle Valo #define ATH12K_MAC_SCAN_TIMEOUT_MSECS 200 /* in msecs */
233d8899132SKalle Valo 
234d8899132SKalle Valo static const u32 ath12k_smps_map[] = {
235d8899132SKalle Valo 	[WLAN_HT_CAP_SM_PS_STATIC] = WMI_PEER_SMPS_STATIC,
236d8899132SKalle Valo 	[WLAN_HT_CAP_SM_PS_DYNAMIC] = WMI_PEER_SMPS_DYNAMIC,
237d8899132SKalle Valo 	[WLAN_HT_CAP_SM_PS_INVALID] = WMI_PEER_SMPS_PS_NONE,
238d8899132SKalle Valo 	[WLAN_HT_CAP_SM_PS_DISABLED] = WMI_PEER_SMPS_PS_NONE,
239d8899132SKalle Valo };
240d8899132SKalle Valo 
241d8899132SKalle Valo static int ath12k_start_vdev_delay(struct ieee80211_hw *hw,
242d8899132SKalle Valo 				   struct ieee80211_vif *vif);
243d8899132SKalle Valo 
244d8899132SKalle Valo static const char *ath12k_mac_phymode_str(enum wmi_phy_mode mode)
245d8899132SKalle Valo {
246d8899132SKalle Valo 	switch (mode) {
247d8899132SKalle Valo 	case MODE_11A:
248d8899132SKalle Valo 		return "11a";
249d8899132SKalle Valo 	case MODE_11G:
250d8899132SKalle Valo 		return "11g";
251d8899132SKalle Valo 	case MODE_11B:
252d8899132SKalle Valo 		return "11b";
253d8899132SKalle Valo 	case MODE_11GONLY:
254d8899132SKalle Valo 		return "11gonly";
255d8899132SKalle Valo 	case MODE_11NA_HT20:
256d8899132SKalle Valo 		return "11na-ht20";
257d8899132SKalle Valo 	case MODE_11NG_HT20:
258d8899132SKalle Valo 		return "11ng-ht20";
259d8899132SKalle Valo 	case MODE_11NA_HT40:
260d8899132SKalle Valo 		return "11na-ht40";
261d8899132SKalle Valo 	case MODE_11NG_HT40:
262d8899132SKalle Valo 		return "11ng-ht40";
263d8899132SKalle Valo 	case MODE_11AC_VHT20:
264d8899132SKalle Valo 		return "11ac-vht20";
265d8899132SKalle Valo 	case MODE_11AC_VHT40:
266d8899132SKalle Valo 		return "11ac-vht40";
267d8899132SKalle Valo 	case MODE_11AC_VHT80:
268d8899132SKalle Valo 		return "11ac-vht80";
269d8899132SKalle Valo 	case MODE_11AC_VHT160:
270d8899132SKalle Valo 		return "11ac-vht160";
271d8899132SKalle Valo 	case MODE_11AC_VHT80_80:
272d8899132SKalle Valo 		return "11ac-vht80+80";
273d8899132SKalle Valo 	case MODE_11AC_VHT20_2G:
274d8899132SKalle Valo 		return "11ac-vht20-2g";
275d8899132SKalle Valo 	case MODE_11AC_VHT40_2G:
276d8899132SKalle Valo 		return "11ac-vht40-2g";
277d8899132SKalle Valo 	case MODE_11AC_VHT80_2G:
278d8899132SKalle Valo 		return "11ac-vht80-2g";
279d8899132SKalle Valo 	case MODE_11AX_HE20:
280d8899132SKalle Valo 		return "11ax-he20";
281d8899132SKalle Valo 	case MODE_11AX_HE40:
282d8899132SKalle Valo 		return "11ax-he40";
283d8899132SKalle Valo 	case MODE_11AX_HE80:
284d8899132SKalle Valo 		return "11ax-he80";
285d8899132SKalle Valo 	case MODE_11AX_HE80_80:
286d8899132SKalle Valo 		return "11ax-he80+80";
287d8899132SKalle Valo 	case MODE_11AX_HE160:
288d8899132SKalle Valo 		return "11ax-he160";
289d8899132SKalle Valo 	case MODE_11AX_HE20_2G:
290d8899132SKalle Valo 		return "11ax-he20-2g";
291d8899132SKalle Valo 	case MODE_11AX_HE40_2G:
292d8899132SKalle Valo 		return "11ax-he40-2g";
293d8899132SKalle Valo 	case MODE_11AX_HE80_2G:
294d8899132SKalle Valo 		return "11ax-he80-2g";
295d8899132SKalle Valo 	case MODE_UNKNOWN:
296d8899132SKalle Valo 		/* skip */
297d8899132SKalle Valo 		break;
298d8899132SKalle Valo 
299d8899132SKalle Valo 		/* no default handler to allow compiler to check that the
300d8899132SKalle Valo 		 * enum is fully handled
301d8899132SKalle Valo 		 */
302d8899132SKalle Valo 	}
303d8899132SKalle Valo 
304d8899132SKalle Valo 	return "<unknown>";
305d8899132SKalle Valo }
306d8899132SKalle Valo 
307d8899132SKalle Valo enum rate_info_bw
308d8899132SKalle Valo ath12k_mac_bw_to_mac80211_bw(enum ath12k_supported_bw bw)
309d8899132SKalle Valo {
310d8899132SKalle Valo 	u8 ret = RATE_INFO_BW_20;
311d8899132SKalle Valo 
312d8899132SKalle Valo 	switch (bw) {
313d8899132SKalle Valo 	case ATH12K_BW_20:
314d8899132SKalle Valo 		ret = RATE_INFO_BW_20;
315d8899132SKalle Valo 		break;
316d8899132SKalle Valo 	case ATH12K_BW_40:
317d8899132SKalle Valo 		ret = RATE_INFO_BW_40;
318d8899132SKalle Valo 		break;
319d8899132SKalle Valo 	case ATH12K_BW_80:
320d8899132SKalle Valo 		ret = RATE_INFO_BW_80;
321d8899132SKalle Valo 		break;
322d8899132SKalle Valo 	case ATH12K_BW_160:
323d8899132SKalle Valo 		ret = RATE_INFO_BW_160;
324d8899132SKalle Valo 		break;
325d8899132SKalle Valo 	}
326d8899132SKalle Valo 
327d8899132SKalle Valo 	return ret;
328d8899132SKalle Valo }
329d8899132SKalle Valo 
330d8899132SKalle Valo enum ath12k_supported_bw ath12k_mac_mac80211_bw_to_ath12k_bw(enum rate_info_bw bw)
331d8899132SKalle Valo {
332d8899132SKalle Valo 	switch (bw) {
333d8899132SKalle Valo 	case RATE_INFO_BW_20:
334d8899132SKalle Valo 		return ATH12K_BW_20;
335d8899132SKalle Valo 	case RATE_INFO_BW_40:
336d8899132SKalle Valo 		return ATH12K_BW_40;
337d8899132SKalle Valo 	case RATE_INFO_BW_80:
338d8899132SKalle Valo 		return ATH12K_BW_80;
339d8899132SKalle Valo 	case RATE_INFO_BW_160:
340d8899132SKalle Valo 		return ATH12K_BW_160;
341d8899132SKalle Valo 	default:
342d8899132SKalle Valo 		return ATH12K_BW_20;
343d8899132SKalle Valo 	}
344d8899132SKalle Valo }
345d8899132SKalle Valo 
346d8899132SKalle Valo int ath12k_mac_hw_ratecode_to_legacy_rate(u8 hw_rc, u8 preamble, u8 *rateidx,
347d8899132SKalle Valo 					  u16 *rate)
348d8899132SKalle Valo {
349d8899132SKalle Valo 	/* As default, it is OFDM rates */
350d8899132SKalle Valo 	int i = ATH12K_MAC_FIRST_OFDM_RATE_IDX;
351d8899132SKalle Valo 	int max_rates_idx = ath12k_g_rates_size;
352d8899132SKalle Valo 
353d8899132SKalle Valo 	if (preamble == WMI_RATE_PREAMBLE_CCK) {
354d8899132SKalle Valo 		hw_rc &= ~ATH12K_HW_RATECODE_CCK_SHORT_PREAM_MASK;
355d8899132SKalle Valo 		i = 0;
356d8899132SKalle Valo 		max_rates_idx = ATH12K_MAC_FIRST_OFDM_RATE_IDX;
357d8899132SKalle Valo 	}
358d8899132SKalle Valo 
359d8899132SKalle Valo 	while (i < max_rates_idx) {
360d8899132SKalle Valo 		if (hw_rc == ath12k_legacy_rates[i].hw_value) {
361d8899132SKalle Valo 			*rateidx = i;
362d8899132SKalle Valo 			*rate = ath12k_legacy_rates[i].bitrate;
363d8899132SKalle Valo 			return 0;
364d8899132SKalle Valo 		}
365d8899132SKalle Valo 		i++;
366d8899132SKalle Valo 	}
367d8899132SKalle Valo 
368d8899132SKalle Valo 	return -EINVAL;
369d8899132SKalle Valo }
370d8899132SKalle Valo 
371d8899132SKalle Valo u8 ath12k_mac_bitrate_to_idx(const struct ieee80211_supported_band *sband,
372d8899132SKalle Valo 			     u32 bitrate)
373d8899132SKalle Valo {
374d8899132SKalle Valo 	int i;
375d8899132SKalle Valo 
376d8899132SKalle Valo 	for (i = 0; i < sband->n_bitrates; i++)
377d8899132SKalle Valo 		if (sband->bitrates[i].bitrate == bitrate)
378d8899132SKalle Valo 			return i;
379d8899132SKalle Valo 
380d8899132SKalle Valo 	return 0;
381d8899132SKalle Valo }
382d8899132SKalle Valo 
383d8899132SKalle Valo static u32
384695df2f4SArnd Bergmann ath12k_mac_max_ht_nss(const u8 *ht_mcs_mask)
385d8899132SKalle Valo {
386d8899132SKalle Valo 	int nss;
387d8899132SKalle Valo 
388d8899132SKalle Valo 	for (nss = IEEE80211_HT_MCS_MASK_LEN - 1; nss >= 0; nss--)
389d8899132SKalle Valo 		if (ht_mcs_mask[nss])
390d8899132SKalle Valo 			return nss + 1;
391d8899132SKalle Valo 
392d8899132SKalle Valo 	return 1;
393d8899132SKalle Valo }
394d8899132SKalle Valo 
395d8899132SKalle Valo static u32
396695df2f4SArnd Bergmann ath12k_mac_max_vht_nss(const u16 *vht_mcs_mask)
397d8899132SKalle Valo {
398d8899132SKalle Valo 	int nss;
399d8899132SKalle Valo 
400d8899132SKalle Valo 	for (nss = NL80211_VHT_NSS_MAX - 1; nss >= 0; nss--)
401d8899132SKalle Valo 		if (vht_mcs_mask[nss])
402d8899132SKalle Valo 			return nss + 1;
403d8899132SKalle Valo 
404d8899132SKalle Valo 	return 1;
405d8899132SKalle Valo }
406d8899132SKalle Valo 
407d8899132SKalle Valo static u8 ath12k_parse_mpdudensity(u8 mpdudensity)
408d8899132SKalle Valo {
409d8899132SKalle Valo /*  From IEEE Std 802.11-2020 defined values for "Minimum MPDU Start Spacing":
410d8899132SKalle Valo  *   0 for no restriction
411d8899132SKalle Valo  *   1 for 1/4 us
412d8899132SKalle Valo  *   2 for 1/2 us
413d8899132SKalle Valo  *   3 for 1 us
414d8899132SKalle Valo  *   4 for 2 us
415d8899132SKalle Valo  *   5 for 4 us
416d8899132SKalle Valo  *   6 for 8 us
417d8899132SKalle Valo  *   7 for 16 us
418d8899132SKalle Valo  */
419d8899132SKalle Valo 	switch (mpdudensity) {
420d8899132SKalle Valo 	case 0:
421d8899132SKalle Valo 		return 0;
422d8899132SKalle Valo 	case 1:
423d8899132SKalle Valo 	case 2:
424d8899132SKalle Valo 	case 3:
425d8899132SKalle Valo 	/* Our lower layer calculations limit our precision to
426d8899132SKalle Valo 	 * 1 microsecond
427d8899132SKalle Valo 	 */
428d8899132SKalle Valo 		return 1;
429d8899132SKalle Valo 	case 4:
430d8899132SKalle Valo 		return 2;
431d8899132SKalle Valo 	case 5:
432d8899132SKalle Valo 		return 4;
433d8899132SKalle Valo 	case 6:
434d8899132SKalle Valo 		return 8;
435d8899132SKalle Valo 	case 7:
436d8899132SKalle Valo 		return 16;
437d8899132SKalle Valo 	default:
438d8899132SKalle Valo 		return 0;
439d8899132SKalle Valo 	}
440d8899132SKalle Valo }
441d8899132SKalle Valo 
442d8899132SKalle Valo static int ath12k_mac_vif_chan(struct ieee80211_vif *vif,
443d8899132SKalle Valo 			       struct cfg80211_chan_def *def)
444d8899132SKalle Valo {
445d8899132SKalle Valo 	struct ieee80211_chanctx_conf *conf;
446d8899132SKalle Valo 
447d8899132SKalle Valo 	rcu_read_lock();
448d8899132SKalle Valo 	conf = rcu_dereference(vif->bss_conf.chanctx_conf);
449d8899132SKalle Valo 	if (!conf) {
450d8899132SKalle Valo 		rcu_read_unlock();
451d8899132SKalle Valo 		return -ENOENT;
452d8899132SKalle Valo 	}
453d8899132SKalle Valo 
454d8899132SKalle Valo 	*def = conf->def;
455d8899132SKalle Valo 	rcu_read_unlock();
456d8899132SKalle Valo 
457d8899132SKalle Valo 	return 0;
458d8899132SKalle Valo }
459d8899132SKalle Valo 
460d8899132SKalle Valo static bool ath12k_mac_bitrate_is_cck(int bitrate)
461d8899132SKalle Valo {
462d8899132SKalle Valo 	switch (bitrate) {
463d8899132SKalle Valo 	case 10:
464d8899132SKalle Valo 	case 20:
465d8899132SKalle Valo 	case 55:
466d8899132SKalle Valo 	case 110:
467d8899132SKalle Valo 		return true;
468d8899132SKalle Valo 	}
469d8899132SKalle Valo 
470d8899132SKalle Valo 	return false;
471d8899132SKalle Valo }
472d8899132SKalle Valo 
473d8899132SKalle Valo u8 ath12k_mac_hw_rate_to_idx(const struct ieee80211_supported_band *sband,
474d8899132SKalle Valo 			     u8 hw_rate, bool cck)
475d8899132SKalle Valo {
476d8899132SKalle Valo 	const struct ieee80211_rate *rate;
477d8899132SKalle Valo 	int i;
478d8899132SKalle Valo 
479d8899132SKalle Valo 	for (i = 0; i < sband->n_bitrates; i++) {
480d8899132SKalle Valo 		rate = &sband->bitrates[i];
481d8899132SKalle Valo 
482d8899132SKalle Valo 		if (ath12k_mac_bitrate_is_cck(rate->bitrate) != cck)
483d8899132SKalle Valo 			continue;
484d8899132SKalle Valo 
485d8899132SKalle Valo 		if (rate->hw_value == hw_rate)
486d8899132SKalle Valo 			return i;
487d8899132SKalle Valo 		else if (rate->flags & IEEE80211_RATE_SHORT_PREAMBLE &&
488d8899132SKalle Valo 			 rate->hw_value_short == hw_rate)
489d8899132SKalle Valo 			return i;
490d8899132SKalle Valo 	}
491d8899132SKalle Valo 
492d8899132SKalle Valo 	return 0;
493d8899132SKalle Valo }
494d8899132SKalle Valo 
495d8899132SKalle Valo static u8 ath12k_mac_bitrate_to_rate(int bitrate)
496d8899132SKalle Valo {
497d8899132SKalle Valo 	return DIV_ROUND_UP(bitrate, 5) |
498d8899132SKalle Valo 	       (ath12k_mac_bitrate_is_cck(bitrate) ? BIT(7) : 0);
499d8899132SKalle Valo }
500d8899132SKalle Valo 
501d8899132SKalle Valo static void ath12k_get_arvif_iter(void *data, u8 *mac,
502d8899132SKalle Valo 				  struct ieee80211_vif *vif)
503d8899132SKalle Valo {
504d8899132SKalle Valo 	struct ath12k_vif_iter *arvif_iter = data;
505d8899132SKalle Valo 	struct ath12k_vif *arvif = (void *)vif->drv_priv;
506d8899132SKalle Valo 
507d8899132SKalle Valo 	if (arvif->vdev_id == arvif_iter->vdev_id)
508d8899132SKalle Valo 		arvif_iter->arvif = arvif;
509d8899132SKalle Valo }
510d8899132SKalle Valo 
511d8899132SKalle Valo struct ath12k_vif *ath12k_mac_get_arvif(struct ath12k *ar, u32 vdev_id)
512d8899132SKalle Valo {
513d8899132SKalle Valo 	struct ath12k_vif_iter arvif_iter = {};
514d8899132SKalle Valo 	u32 flags;
515d8899132SKalle Valo 
516d8899132SKalle Valo 	arvif_iter.vdev_id = vdev_id;
517d8899132SKalle Valo 
518d8899132SKalle Valo 	flags = IEEE80211_IFACE_ITER_RESUME_ALL;
519d8899132SKalle Valo 	ieee80211_iterate_active_interfaces_atomic(ar->hw,
520d8899132SKalle Valo 						   flags,
521d8899132SKalle Valo 						   ath12k_get_arvif_iter,
522d8899132SKalle Valo 						   &arvif_iter);
523d8899132SKalle Valo 	if (!arvif_iter.arvif) {
524d8899132SKalle Valo 		ath12k_warn(ar->ab, "No VIF found for vdev %d\n", vdev_id);
525d8899132SKalle Valo 		return NULL;
526d8899132SKalle Valo 	}
527d8899132SKalle Valo 
528d8899132SKalle Valo 	return arvif_iter.arvif;
529d8899132SKalle Valo }
530d8899132SKalle Valo 
531d8899132SKalle Valo struct ath12k_vif *ath12k_mac_get_arvif_by_vdev_id(struct ath12k_base *ab,
532d8899132SKalle Valo 						   u32 vdev_id)
533d8899132SKalle Valo {
534d8899132SKalle Valo 	int i;
535d8899132SKalle Valo 	struct ath12k_pdev *pdev;
536d8899132SKalle Valo 	struct ath12k_vif *arvif;
537d8899132SKalle Valo 
538d8899132SKalle Valo 	for (i = 0; i < ab->num_radios; i++) {
539d8899132SKalle Valo 		pdev = rcu_dereference(ab->pdevs_active[i]);
540d8899132SKalle Valo 		if (pdev && pdev->ar) {
541d8899132SKalle Valo 			arvif = ath12k_mac_get_arvif(pdev->ar, vdev_id);
542d8899132SKalle Valo 			if (arvif)
543d8899132SKalle Valo 				return arvif;
544d8899132SKalle Valo 		}
545d8899132SKalle Valo 	}
546d8899132SKalle Valo 
547d8899132SKalle Valo 	return NULL;
548d8899132SKalle Valo }
549d8899132SKalle Valo 
550d8899132SKalle Valo struct ath12k *ath12k_mac_get_ar_by_vdev_id(struct ath12k_base *ab, u32 vdev_id)
551d8899132SKalle Valo {
552d8899132SKalle Valo 	int i;
553d8899132SKalle Valo 	struct ath12k_pdev *pdev;
554d8899132SKalle Valo 
555d8899132SKalle Valo 	for (i = 0; i < ab->num_radios; i++) {
556d8899132SKalle Valo 		pdev = rcu_dereference(ab->pdevs_active[i]);
557d8899132SKalle Valo 		if (pdev && pdev->ar) {
558d8899132SKalle Valo 			if (pdev->ar->allocated_vdev_map & (1LL << vdev_id))
559d8899132SKalle Valo 				return pdev->ar;
560d8899132SKalle Valo 		}
561d8899132SKalle Valo 	}
562d8899132SKalle Valo 
563d8899132SKalle Valo 	return NULL;
564d8899132SKalle Valo }
565d8899132SKalle Valo 
566d8899132SKalle Valo struct ath12k *ath12k_mac_get_ar_by_pdev_id(struct ath12k_base *ab, u32 pdev_id)
567d8899132SKalle Valo {
568d8899132SKalle Valo 	int i;
569d8899132SKalle Valo 	struct ath12k_pdev *pdev;
570d8899132SKalle Valo 
571d8899132SKalle Valo 	if (ab->hw_params->single_pdev_only) {
572d8899132SKalle Valo 		pdev = rcu_dereference(ab->pdevs_active[0]);
573d8899132SKalle Valo 		return pdev ? pdev->ar : NULL;
574d8899132SKalle Valo 	}
575d8899132SKalle Valo 
576d8899132SKalle Valo 	if (WARN_ON(pdev_id > ab->num_radios))
577d8899132SKalle Valo 		return NULL;
578d8899132SKalle Valo 
579d8899132SKalle Valo 	for (i = 0; i < ab->num_radios; i++) {
580d8899132SKalle Valo 		pdev = rcu_dereference(ab->pdevs_active[i]);
581d8899132SKalle Valo 
582d8899132SKalle Valo 		if (pdev && pdev->pdev_id == pdev_id)
583d8899132SKalle Valo 			return (pdev->ar ? pdev->ar : NULL);
584d8899132SKalle Valo 	}
585d8899132SKalle Valo 
586d8899132SKalle Valo 	return NULL;
587d8899132SKalle Valo }
588d8899132SKalle Valo 
589d8899132SKalle Valo static void ath12k_pdev_caps_update(struct ath12k *ar)
590d8899132SKalle Valo {
591d8899132SKalle Valo 	struct ath12k_base *ab = ar->ab;
592d8899132SKalle Valo 
593d8899132SKalle Valo 	ar->max_tx_power = ab->target_caps.hw_max_tx_power;
594d8899132SKalle Valo 
595d8899132SKalle Valo 	/* FIXME: Set min_tx_power to ab->target_caps.hw_min_tx_power.
596d8899132SKalle Valo 	 * But since the received value in svcrdy is same as hw_max_tx_power,
597d8899132SKalle Valo 	 * we can set ar->min_tx_power to 0 currently until
598d8899132SKalle Valo 	 * this is fixed in firmware
599d8899132SKalle Valo 	 */
600d8899132SKalle Valo 	ar->min_tx_power = 0;
601d8899132SKalle Valo 
602d8899132SKalle Valo 	ar->txpower_limit_2g = ar->max_tx_power;
603d8899132SKalle Valo 	ar->txpower_limit_5g = ar->max_tx_power;
604d8899132SKalle Valo 	ar->txpower_scale = WMI_HOST_TP_SCALE_MAX;
605d8899132SKalle Valo }
606d8899132SKalle Valo 
607d8899132SKalle Valo static int ath12k_mac_txpower_recalc(struct ath12k *ar)
608d8899132SKalle Valo {
609d8899132SKalle Valo 	struct ath12k_pdev *pdev = ar->pdev;
610d8899132SKalle Valo 	struct ath12k_vif *arvif;
611d8899132SKalle Valo 	int ret, txpower = -1;
612d8899132SKalle Valo 	u32 param;
613d8899132SKalle Valo 
614d8899132SKalle Valo 	lockdep_assert_held(&ar->conf_mutex);
615d8899132SKalle Valo 
616d8899132SKalle Valo 	list_for_each_entry(arvif, &ar->arvifs, list) {
617d8899132SKalle Valo 		if (arvif->txpower <= 0)
618d8899132SKalle Valo 			continue;
619d8899132SKalle Valo 
620d8899132SKalle Valo 		if (txpower == -1)
621d8899132SKalle Valo 			txpower = arvif->txpower;
622d8899132SKalle Valo 		else
623d8899132SKalle Valo 			txpower = min(txpower, arvif->txpower);
624d8899132SKalle Valo 	}
625d8899132SKalle Valo 
626d8899132SKalle Valo 	if (txpower == -1)
627d8899132SKalle Valo 		return 0;
628d8899132SKalle Valo 
629d8899132SKalle Valo 	/* txpwr is set as 2 units per dBm in FW*/
630d8899132SKalle Valo 	txpower = min_t(u32, max_t(u32, ar->min_tx_power, txpower),
631d8899132SKalle Valo 			ar->max_tx_power) * 2;
632d8899132SKalle Valo 
633d8899132SKalle Valo 	ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "txpower to set in hw %d\n",
634d8899132SKalle Valo 		   txpower / 2);
635d8899132SKalle Valo 
636d8899132SKalle Valo 	if ((pdev->cap.supported_bands & WMI_HOST_WLAN_2G_CAP) &&
637d8899132SKalle Valo 	    ar->txpower_limit_2g != txpower) {
638d8899132SKalle Valo 		param = WMI_PDEV_PARAM_TXPOWER_LIMIT2G;
639d8899132SKalle Valo 		ret = ath12k_wmi_pdev_set_param(ar, param,
640d8899132SKalle Valo 						txpower, ar->pdev->pdev_id);
641d8899132SKalle Valo 		if (ret)
642d8899132SKalle Valo 			goto fail;
643d8899132SKalle Valo 		ar->txpower_limit_2g = txpower;
644d8899132SKalle Valo 	}
645d8899132SKalle Valo 
646d8899132SKalle Valo 	if ((pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP) &&
647d8899132SKalle Valo 	    ar->txpower_limit_5g != txpower) {
648d8899132SKalle Valo 		param = WMI_PDEV_PARAM_TXPOWER_LIMIT5G;
649d8899132SKalle Valo 		ret = ath12k_wmi_pdev_set_param(ar, param,
650d8899132SKalle Valo 						txpower, ar->pdev->pdev_id);
651d8899132SKalle Valo 		if (ret)
652d8899132SKalle Valo 			goto fail;
653d8899132SKalle Valo 		ar->txpower_limit_5g = txpower;
654d8899132SKalle Valo 	}
655d8899132SKalle Valo 
656d8899132SKalle Valo 	return 0;
657d8899132SKalle Valo 
658d8899132SKalle Valo fail:
659d8899132SKalle Valo 	ath12k_warn(ar->ab, "failed to recalc txpower limit %d using pdev param %d: %d\n",
660d8899132SKalle Valo 		    txpower / 2, param, ret);
661d8899132SKalle Valo 	return ret;
662d8899132SKalle Valo }
663d8899132SKalle Valo 
664d8899132SKalle Valo static int ath12k_recalc_rtscts_prot(struct ath12k_vif *arvif)
665d8899132SKalle Valo {
666d8899132SKalle Valo 	struct ath12k *ar = arvif->ar;
667d8899132SKalle Valo 	u32 vdev_param, rts_cts;
668d8899132SKalle Valo 	int ret;
669d8899132SKalle Valo 
670d8899132SKalle Valo 	lockdep_assert_held(&ar->conf_mutex);
671d8899132SKalle Valo 
672d8899132SKalle Valo 	vdev_param = WMI_VDEV_PARAM_ENABLE_RTSCTS;
673d8899132SKalle Valo 
674d8899132SKalle Valo 	/* Enable RTS/CTS protection for sw retries (when legacy stations
675d8899132SKalle Valo 	 * are in BSS) or by default only for second rate series.
676d8899132SKalle Valo 	 * TODO: Check if we need to enable CTS 2 Self in any case
677d8899132SKalle Valo 	 */
678d8899132SKalle Valo 	rts_cts = WMI_USE_RTS_CTS;
679d8899132SKalle Valo 
680d8899132SKalle Valo 	if (arvif->num_legacy_stations > 0)
681d8899132SKalle Valo 		rts_cts |= WMI_RTSCTS_ACROSS_SW_RETRIES << 4;
682d8899132SKalle Valo 	else
683d8899132SKalle Valo 		rts_cts |= WMI_RTSCTS_FOR_SECOND_RATESERIES << 4;
684d8899132SKalle Valo 
685d8899132SKalle Valo 	/* Need not send duplicate param value to firmware */
686d8899132SKalle Valo 	if (arvif->rtscts_prot_mode == rts_cts)
687d8899132SKalle Valo 		return 0;
688d8899132SKalle Valo 
689d8899132SKalle Valo 	arvif->rtscts_prot_mode = rts_cts;
690d8899132SKalle Valo 
691d8899132SKalle Valo 	ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev %d recalc rts/cts prot %d\n",
692d8899132SKalle Valo 		   arvif->vdev_id, rts_cts);
693d8899132SKalle Valo 
694d8899132SKalle Valo 	ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
695d8899132SKalle Valo 					    vdev_param, rts_cts);
696d8899132SKalle Valo 	if (ret)
697d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to recalculate rts/cts prot for vdev %d: %d\n",
698d8899132SKalle Valo 			    arvif->vdev_id, ret);
699d8899132SKalle Valo 
700d8899132SKalle Valo 	return ret;
701d8899132SKalle Valo }
702d8899132SKalle Valo 
703d8899132SKalle Valo static int ath12k_mac_set_kickout(struct ath12k_vif *arvif)
704d8899132SKalle Valo {
705d8899132SKalle Valo 	struct ath12k *ar = arvif->ar;
706d8899132SKalle Valo 	u32 param;
707d8899132SKalle Valo 	int ret;
708d8899132SKalle Valo 
709d8899132SKalle Valo 	ret = ath12k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_STA_KICKOUT_TH,
710d8899132SKalle Valo 					ATH12K_KICKOUT_THRESHOLD,
711d8899132SKalle Valo 					ar->pdev->pdev_id);
712d8899132SKalle Valo 	if (ret) {
713d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to set kickout threshold on vdev %i: %d\n",
714d8899132SKalle Valo 			    arvif->vdev_id, ret);
715d8899132SKalle Valo 		return ret;
716d8899132SKalle Valo 	}
717d8899132SKalle Valo 
718d8899132SKalle Valo 	param = WMI_VDEV_PARAM_AP_KEEPALIVE_MIN_IDLE_INACTIVE_TIME_SECS;
719d8899132SKalle Valo 	ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, param,
720d8899132SKalle Valo 					    ATH12K_KEEPALIVE_MIN_IDLE);
721d8899132SKalle Valo 	if (ret) {
722d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to set keepalive minimum idle time on vdev %i: %d\n",
723d8899132SKalle Valo 			    arvif->vdev_id, ret);
724d8899132SKalle Valo 		return ret;
725d8899132SKalle Valo 	}
726d8899132SKalle Valo 
727d8899132SKalle Valo 	param = WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_IDLE_INACTIVE_TIME_SECS;
728d8899132SKalle Valo 	ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, param,
729d8899132SKalle Valo 					    ATH12K_KEEPALIVE_MAX_IDLE);
730d8899132SKalle Valo 	if (ret) {
731d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to set keepalive maximum idle time on vdev %i: %d\n",
732d8899132SKalle Valo 			    arvif->vdev_id, ret);
733d8899132SKalle Valo 		return ret;
734d8899132SKalle Valo 	}
735d8899132SKalle Valo 
736d8899132SKalle Valo 	param = WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS;
737d8899132SKalle Valo 	ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, param,
738d8899132SKalle Valo 					    ATH12K_KEEPALIVE_MAX_UNRESPONSIVE);
739d8899132SKalle Valo 	if (ret) {
740d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to set keepalive maximum unresponsive time on vdev %i: %d\n",
741d8899132SKalle Valo 			    arvif->vdev_id, ret);
742d8899132SKalle Valo 		return ret;
743d8899132SKalle Valo 	}
744d8899132SKalle Valo 
745d8899132SKalle Valo 	return 0;
746d8899132SKalle Valo }
747d8899132SKalle Valo 
748d8899132SKalle Valo void ath12k_mac_peer_cleanup_all(struct ath12k *ar)
749d8899132SKalle Valo {
750d8899132SKalle Valo 	struct ath12k_peer *peer, *tmp;
751d8899132SKalle Valo 	struct ath12k_base *ab = ar->ab;
752d8899132SKalle Valo 
753d8899132SKalle Valo 	lockdep_assert_held(&ar->conf_mutex);
754d8899132SKalle Valo 
755d8899132SKalle Valo 	spin_lock_bh(&ab->base_lock);
756d8899132SKalle Valo 	list_for_each_entry_safe(peer, tmp, &ab->peers, list) {
757d8899132SKalle Valo 		ath12k_dp_rx_peer_tid_cleanup(ar, peer);
758d8899132SKalle Valo 		list_del(&peer->list);
759d8899132SKalle Valo 		kfree(peer);
760d8899132SKalle Valo 	}
761d8899132SKalle Valo 	spin_unlock_bh(&ab->base_lock);
762d8899132SKalle Valo 
763d8899132SKalle Valo 	ar->num_peers = 0;
764d8899132SKalle Valo 	ar->num_stations = 0;
765d8899132SKalle Valo }
766d8899132SKalle Valo 
767d8899132SKalle Valo static int ath12k_mac_vdev_setup_sync(struct ath12k *ar)
768d8899132SKalle Valo {
769d8899132SKalle Valo 	lockdep_assert_held(&ar->conf_mutex);
770d8899132SKalle Valo 
771d8899132SKalle Valo 	if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))
772d8899132SKalle Valo 		return -ESHUTDOWN;
773d8899132SKalle Valo 
7741fd2c3f9SAishwarya R 	ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "vdev setup timeout %d\n",
7751fd2c3f9SAishwarya R 		   ATH12K_VDEV_SETUP_TIMEOUT_HZ);
7761fd2c3f9SAishwarya R 
777d8899132SKalle Valo 	if (!wait_for_completion_timeout(&ar->vdev_setup_done,
778d8899132SKalle Valo 					 ATH12K_VDEV_SETUP_TIMEOUT_HZ))
779d8899132SKalle Valo 		return -ETIMEDOUT;
780d8899132SKalle Valo 
781d8899132SKalle Valo 	return ar->last_wmi_vdev_start_status ? -EINVAL : 0;
782d8899132SKalle Valo }
783d8899132SKalle Valo 
784d8899132SKalle Valo static int ath12k_monitor_vdev_up(struct ath12k *ar, int vdev_id)
785d8899132SKalle Valo {
786d8899132SKalle Valo 	int ret;
787d8899132SKalle Valo 
788d8899132SKalle Valo 	ret = ath12k_wmi_vdev_up(ar, vdev_id, 0, ar->mac_addr);
789d8899132SKalle Valo 	if (ret) {
790d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to put up monitor vdev %i: %d\n",
791d8899132SKalle Valo 			    vdev_id, ret);
792d8899132SKalle Valo 		return ret;
793d8899132SKalle Valo 	}
794d8899132SKalle Valo 
795d8899132SKalle Valo 	ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac monitor vdev %i started\n",
796d8899132SKalle Valo 		   vdev_id);
797d8899132SKalle Valo 	return 0;
798d8899132SKalle Valo }
799d8899132SKalle Valo 
800d8899132SKalle Valo static int ath12k_mac_monitor_vdev_start(struct ath12k *ar, int vdev_id,
801d8899132SKalle Valo 					 struct cfg80211_chan_def *chandef)
802d8899132SKalle Valo {
803d8899132SKalle Valo 	struct ieee80211_channel *channel;
804d8899132SKalle Valo 	struct wmi_vdev_start_req_arg arg = {};
805d8899132SKalle Valo 	int ret;
806d8899132SKalle Valo 
807d8899132SKalle Valo 	lockdep_assert_held(&ar->conf_mutex);
808d8899132SKalle Valo 
809d8899132SKalle Valo 	channel = chandef->chan;
810d8899132SKalle Valo 	arg.vdev_id = vdev_id;
811d8899132SKalle Valo 	arg.freq = channel->center_freq;
812d8899132SKalle Valo 	arg.band_center_freq1 = chandef->center_freq1;
813d8899132SKalle Valo 	arg.band_center_freq2 = chandef->center_freq2;
814d8899132SKalle Valo 	arg.mode = ath12k_phymodes[chandef->chan->band][chandef->width];
815d8899132SKalle Valo 	arg.chan_radar = !!(channel->flags & IEEE80211_CHAN_RADAR);
816d8899132SKalle Valo 
817d8899132SKalle Valo 	arg.min_power = 0;
818d8899132SKalle Valo 	arg.max_power = channel->max_power;
819d8899132SKalle Valo 	arg.max_reg_power = channel->max_reg_power;
820d8899132SKalle Valo 	arg.max_antenna_gain = channel->max_antenna_gain;
821d8899132SKalle Valo 
822d8899132SKalle Valo 	arg.pref_tx_streams = ar->num_tx_chains;
823d8899132SKalle Valo 	arg.pref_rx_streams = ar->num_rx_chains;
824d8899132SKalle Valo 
825d8899132SKalle Valo 	arg.passive |= !!(chandef->chan->flags & IEEE80211_CHAN_NO_IR);
826d8899132SKalle Valo 
827d8899132SKalle Valo 	reinit_completion(&ar->vdev_setup_done);
828d8899132SKalle Valo 	reinit_completion(&ar->vdev_delete_done);
829d8899132SKalle Valo 
830d8899132SKalle Valo 	ret = ath12k_wmi_vdev_start(ar, &arg, false);
831d8899132SKalle Valo 	if (ret) {
832d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to request monitor vdev %i start: %d\n",
833d8899132SKalle Valo 			    vdev_id, ret);
834d8899132SKalle Valo 		return ret;
835d8899132SKalle Valo 	}
836d8899132SKalle Valo 
837d8899132SKalle Valo 	ret = ath12k_mac_vdev_setup_sync(ar);
838d8899132SKalle Valo 	if (ret) {
839d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to synchronize setup for monitor vdev %i start: %d\n",
840d8899132SKalle Valo 			    vdev_id, ret);
841d8899132SKalle Valo 		return ret;
842d8899132SKalle Valo 	}
843d8899132SKalle Valo 
844d8899132SKalle Valo 	ret = ath12k_wmi_vdev_up(ar, vdev_id, 0, ar->mac_addr);
845d8899132SKalle Valo 	if (ret) {
846d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to put up monitor vdev %i: %d\n",
847d8899132SKalle Valo 			    vdev_id, ret);
848d8899132SKalle Valo 		goto vdev_stop;
849d8899132SKalle Valo 	}
850d8899132SKalle Valo 
851d8899132SKalle Valo 	ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac monitor vdev %i started\n",
852d8899132SKalle Valo 		   vdev_id);
853d8899132SKalle Valo 	return 0;
854d8899132SKalle Valo 
855d8899132SKalle Valo vdev_stop:
856d8899132SKalle Valo 	ret = ath12k_wmi_vdev_stop(ar, vdev_id);
857d8899132SKalle Valo 	if (ret)
858d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to stop monitor vdev %i after start failure: %d\n",
859d8899132SKalle Valo 			    vdev_id, ret);
860d8899132SKalle Valo 	return ret;
861d8899132SKalle Valo }
862d8899132SKalle Valo 
863d8899132SKalle Valo static int ath12k_mac_monitor_vdev_stop(struct ath12k *ar)
864d8899132SKalle Valo {
865d8899132SKalle Valo 	int ret;
866d8899132SKalle Valo 
867d8899132SKalle Valo 	lockdep_assert_held(&ar->conf_mutex);
868d8899132SKalle Valo 
869d8899132SKalle Valo 	reinit_completion(&ar->vdev_setup_done);
870d8899132SKalle Valo 
871d8899132SKalle Valo 	ret = ath12k_wmi_vdev_stop(ar, ar->monitor_vdev_id);
872d8899132SKalle Valo 	if (ret)
873d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to request monitor vdev %i stop: %d\n",
874d8899132SKalle Valo 			    ar->monitor_vdev_id, ret);
875d8899132SKalle Valo 
876d8899132SKalle Valo 	ret = ath12k_mac_vdev_setup_sync(ar);
877d8899132SKalle Valo 	if (ret)
878d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to synchronize monitor vdev %i stop: %d\n",
879d8899132SKalle Valo 			    ar->monitor_vdev_id, ret);
880d8899132SKalle Valo 
881d8899132SKalle Valo 	ret = ath12k_wmi_vdev_down(ar, ar->monitor_vdev_id);
882d8899132SKalle Valo 	if (ret)
883d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to put down monitor vdev %i: %d\n",
884d8899132SKalle Valo 			    ar->monitor_vdev_id, ret);
885d8899132SKalle Valo 
886d8899132SKalle Valo 	ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac monitor vdev %i stopped\n",
887d8899132SKalle Valo 		   ar->monitor_vdev_id);
888d8899132SKalle Valo 	return ret;
889d8899132SKalle Valo }
890d8899132SKalle Valo 
891d8899132SKalle Valo static int ath12k_mac_monitor_vdev_create(struct ath12k *ar)
892d8899132SKalle Valo {
893d8899132SKalle Valo 	struct ath12k_pdev *pdev = ar->pdev;
894d8899132SKalle Valo 	struct ath12k_wmi_vdev_create_arg arg = {};
895d8899132SKalle Valo 	int bit, ret;
896d8899132SKalle Valo 	u8 tmp_addr[6];
897d8899132SKalle Valo 	u16 nss;
898d8899132SKalle Valo 
899d8899132SKalle Valo 	lockdep_assert_held(&ar->conf_mutex);
900d8899132SKalle Valo 
901d8899132SKalle Valo 	if (ar->monitor_vdev_created)
902d8899132SKalle Valo 		return 0;
903d8899132SKalle Valo 
904d8899132SKalle Valo 	if (ar->ab->free_vdev_map == 0) {
905d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to find free vdev id for monitor vdev\n");
906d8899132SKalle Valo 		return -ENOMEM;
907d8899132SKalle Valo 	}
908d8899132SKalle Valo 
909d8899132SKalle Valo 	bit = __ffs64(ar->ab->free_vdev_map);
910d8899132SKalle Valo 
911d8899132SKalle Valo 	ar->monitor_vdev_id = bit;
912d8899132SKalle Valo 
913d8899132SKalle Valo 	arg.if_id = ar->monitor_vdev_id;
914d8899132SKalle Valo 	arg.type = WMI_VDEV_TYPE_MONITOR;
915d8899132SKalle Valo 	arg.subtype = WMI_VDEV_SUBTYPE_NONE;
916d8899132SKalle Valo 	arg.pdev_id = pdev->pdev_id;
917d8899132SKalle Valo 	arg.if_stats_id = ATH12K_INVAL_VDEV_STATS_ID;
918d8899132SKalle Valo 
919d8899132SKalle Valo 	if (pdev->cap.supported_bands & WMI_HOST_WLAN_2G_CAP) {
920d8899132SKalle Valo 		arg.chains[NL80211_BAND_2GHZ].tx = ar->num_tx_chains;
921d8899132SKalle Valo 		arg.chains[NL80211_BAND_2GHZ].rx = ar->num_rx_chains;
922d8899132SKalle Valo 	}
923d8899132SKalle Valo 
924d8899132SKalle Valo 	if (pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP) {
925d8899132SKalle Valo 		arg.chains[NL80211_BAND_5GHZ].tx = ar->num_tx_chains;
926d8899132SKalle Valo 		arg.chains[NL80211_BAND_5GHZ].rx = ar->num_rx_chains;
927d8899132SKalle Valo 	}
928d8899132SKalle Valo 
929d8899132SKalle Valo 	ret = ath12k_wmi_vdev_create(ar, tmp_addr, &arg);
930d8899132SKalle Valo 	if (ret) {
931d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to request monitor vdev %i creation: %d\n",
932d8899132SKalle Valo 			    ar->monitor_vdev_id, ret);
933d8899132SKalle Valo 		ar->monitor_vdev_id = -1;
934d8899132SKalle Valo 		return ret;
935d8899132SKalle Valo 	}
936d8899132SKalle Valo 
937d8899132SKalle Valo 	nss = hweight32(ar->cfg_tx_chainmask) ? : 1;
938d8899132SKalle Valo 	ret = ath12k_wmi_vdev_set_param_cmd(ar, ar->monitor_vdev_id,
939d8899132SKalle Valo 					    WMI_VDEV_PARAM_NSS, nss);
940d8899132SKalle Valo 	if (ret) {
941d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to set vdev %d chainmask 0x%x, nss %d :%d\n",
942d8899132SKalle Valo 			    ar->monitor_vdev_id, ar->cfg_tx_chainmask, nss, ret);
943d8899132SKalle Valo 		return ret;
944d8899132SKalle Valo 	}
945d8899132SKalle Valo 
946d8899132SKalle Valo 	ret = ath12k_mac_txpower_recalc(ar);
947d8899132SKalle Valo 	if (ret)
948d8899132SKalle Valo 		return ret;
949d8899132SKalle Valo 
950d8899132SKalle Valo 	ar->allocated_vdev_map |= 1LL << ar->monitor_vdev_id;
951d8899132SKalle Valo 	ar->ab->free_vdev_map &= ~(1LL << ar->monitor_vdev_id);
952d8899132SKalle Valo 	ar->num_created_vdevs++;
953d8899132SKalle Valo 	ar->monitor_vdev_created = true;
954d8899132SKalle Valo 	ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac monitor vdev %d created\n",
955d8899132SKalle Valo 		   ar->monitor_vdev_id);
956d8899132SKalle Valo 
957d8899132SKalle Valo 	return 0;
958d8899132SKalle Valo }
959d8899132SKalle Valo 
960d8899132SKalle Valo static int ath12k_mac_monitor_vdev_delete(struct ath12k *ar)
961d8899132SKalle Valo {
962d8899132SKalle Valo 	int ret;
963d8899132SKalle Valo 	unsigned long time_left;
964d8899132SKalle Valo 
965d8899132SKalle Valo 	lockdep_assert_held(&ar->conf_mutex);
966d8899132SKalle Valo 
967d8899132SKalle Valo 	if (!ar->monitor_vdev_created)
968d8899132SKalle Valo 		return 0;
969d8899132SKalle Valo 
970d8899132SKalle Valo 	reinit_completion(&ar->vdev_delete_done);
971d8899132SKalle Valo 
972d8899132SKalle Valo 	ret = ath12k_wmi_vdev_delete(ar, ar->monitor_vdev_id);
973d8899132SKalle Valo 	if (ret) {
974d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to request wmi monitor vdev %i removal: %d\n",
975d8899132SKalle Valo 			    ar->monitor_vdev_id, ret);
976d8899132SKalle Valo 		return ret;
977d8899132SKalle Valo 	}
978d8899132SKalle Valo 
979d8899132SKalle Valo 	time_left = wait_for_completion_timeout(&ar->vdev_delete_done,
980d8899132SKalle Valo 						ATH12K_VDEV_DELETE_TIMEOUT_HZ);
981d8899132SKalle Valo 	if (time_left == 0) {
982d8899132SKalle Valo 		ath12k_warn(ar->ab, "Timeout in receiving vdev delete response\n");
983d8899132SKalle Valo 	} else {
984d8899132SKalle Valo 		ar->allocated_vdev_map &= ~(1LL << ar->monitor_vdev_id);
985d8899132SKalle Valo 		ar->ab->free_vdev_map |= 1LL << (ar->monitor_vdev_id);
986d8899132SKalle Valo 		ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac monitor vdev %d deleted\n",
987d8899132SKalle Valo 			   ar->monitor_vdev_id);
988d8899132SKalle Valo 		ar->num_created_vdevs--;
989d8899132SKalle Valo 		ar->monitor_vdev_id = -1;
990d8899132SKalle Valo 		ar->monitor_vdev_created = false;
991d8899132SKalle Valo 	}
992d8899132SKalle Valo 
993d8899132SKalle Valo 	return ret;
994d8899132SKalle Valo }
995d8899132SKalle Valo 
996d8899132SKalle Valo static void
997d8899132SKalle Valo ath12k_mac_get_any_chandef_iter(struct ieee80211_hw *hw,
998d8899132SKalle Valo 				struct ieee80211_chanctx_conf *conf,
999d8899132SKalle Valo 				void *data)
1000d8899132SKalle Valo {
1001d8899132SKalle Valo 	struct cfg80211_chan_def **def = data;
1002d8899132SKalle Valo 
1003d8899132SKalle Valo 	*def = &conf->def;
1004d8899132SKalle Valo }
1005d8899132SKalle Valo 
1006d8899132SKalle Valo static int ath12k_mac_monitor_start(struct ath12k *ar)
1007d8899132SKalle Valo {
1008d8899132SKalle Valo 	struct cfg80211_chan_def *chandef = NULL;
1009d8899132SKalle Valo 	int ret;
1010d8899132SKalle Valo 
1011d8899132SKalle Valo 	lockdep_assert_held(&ar->conf_mutex);
1012d8899132SKalle Valo 
1013d8899132SKalle Valo 	if (ar->monitor_started)
1014d8899132SKalle Valo 		return 0;
1015d8899132SKalle Valo 
1016d8899132SKalle Valo 	ieee80211_iter_chan_contexts_atomic(ar->hw,
1017d8899132SKalle Valo 					    ath12k_mac_get_any_chandef_iter,
1018d8899132SKalle Valo 					    &chandef);
1019d8899132SKalle Valo 	if (!chandef)
1020d8899132SKalle Valo 		return 0;
1021d8899132SKalle Valo 
1022d8899132SKalle Valo 	ret = ath12k_mac_monitor_vdev_start(ar, ar->monitor_vdev_id, chandef);
1023d8899132SKalle Valo 	if (ret) {
1024d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to start monitor vdev: %d\n", ret);
1025d8899132SKalle Valo 		ath12k_mac_monitor_vdev_delete(ar);
1026d8899132SKalle Valo 		return ret;
1027d8899132SKalle Valo 	}
1028d8899132SKalle Valo 
1029d8899132SKalle Valo 	ar->monitor_started = true;
1030d8899132SKalle Valo 	ar->num_started_vdevs++;
1031d8899132SKalle Valo 	ret = ath12k_dp_tx_htt_monitor_mode_ring_config(ar, false);
1032d8899132SKalle Valo 	ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac monitor started ret %d\n", ret);
1033d8899132SKalle Valo 
1034d8899132SKalle Valo 	return ret;
1035d8899132SKalle Valo }
1036d8899132SKalle Valo 
1037d8899132SKalle Valo static int ath12k_mac_monitor_stop(struct ath12k *ar)
1038d8899132SKalle Valo {
1039d8899132SKalle Valo 	int ret;
1040d8899132SKalle Valo 
1041d8899132SKalle Valo 	lockdep_assert_held(&ar->conf_mutex);
1042d8899132SKalle Valo 
1043d8899132SKalle Valo 	if (!ar->monitor_started)
1044d8899132SKalle Valo 		return 0;
1045d8899132SKalle Valo 
1046d8899132SKalle Valo 	ret = ath12k_mac_monitor_vdev_stop(ar);
1047d8899132SKalle Valo 	if (ret) {
1048d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to stop monitor vdev: %d\n", ret);
1049d8899132SKalle Valo 		return ret;
1050d8899132SKalle Valo 	}
1051d8899132SKalle Valo 
1052d8899132SKalle Valo 	ar->monitor_started = false;
1053d8899132SKalle Valo 	ar->num_started_vdevs--;
1054d8899132SKalle Valo 	ret = ath12k_dp_tx_htt_monitor_mode_ring_config(ar, true);
1055d8899132SKalle Valo 	ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac monitor stopped ret %d\n", ret);
1056d8899132SKalle Valo 	return ret;
1057d8899132SKalle Valo }
1058d8899132SKalle Valo 
1059d8899132SKalle Valo static int ath12k_mac_op_config(struct ieee80211_hw *hw, u32 changed)
1060d8899132SKalle Valo {
1061d8899132SKalle Valo 	struct ath12k *ar = hw->priv;
1062d8899132SKalle Valo 	struct ieee80211_conf *conf = &hw->conf;
1063d1335f0dSThiraviyam Mariyappan 	int ret = 0;
1064d8899132SKalle Valo 
1065d8899132SKalle Valo 	mutex_lock(&ar->conf_mutex);
1066d8899132SKalle Valo 
1067d8899132SKalle Valo 	if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
1068d8899132SKalle Valo 		ar->monitor_conf_enabled = conf->flags & IEEE80211_CONF_MONITOR;
1069d8899132SKalle Valo 		if (ar->monitor_conf_enabled) {
1070d8899132SKalle Valo 			if (ar->monitor_vdev_created)
1071d8899132SKalle Valo 				goto exit;
1072d8899132SKalle Valo 			ret = ath12k_mac_monitor_vdev_create(ar);
1073d8899132SKalle Valo 			if (ret)
1074d8899132SKalle Valo 				goto exit;
1075d8899132SKalle Valo 			ret = ath12k_mac_monitor_start(ar);
1076d8899132SKalle Valo 			if (ret)
1077d8899132SKalle Valo 				goto err_mon_del;
1078d8899132SKalle Valo 		} else {
1079d8899132SKalle Valo 			if (!ar->monitor_vdev_created)
1080d8899132SKalle Valo 				goto exit;
1081d8899132SKalle Valo 			ret = ath12k_mac_monitor_stop(ar);
1082d8899132SKalle Valo 			if (ret)
1083d8899132SKalle Valo 				goto exit;
1084d8899132SKalle Valo 			ath12k_mac_monitor_vdev_delete(ar);
1085d8899132SKalle Valo 		}
1086d8899132SKalle Valo 	}
1087d8899132SKalle Valo 
1088d8899132SKalle Valo exit:
1089d8899132SKalle Valo 	mutex_unlock(&ar->conf_mutex);
1090d8899132SKalle Valo 	return ret;
1091d8899132SKalle Valo 
1092d8899132SKalle Valo err_mon_del:
1093d8899132SKalle Valo 	ath12k_mac_monitor_vdev_delete(ar);
1094d8899132SKalle Valo 	mutex_unlock(&ar->conf_mutex);
1095d1335f0dSThiraviyam Mariyappan 	return ret;
1096d8899132SKalle Valo }
1097d8899132SKalle Valo 
1098d8899132SKalle Valo static int ath12k_mac_setup_bcn_tmpl(struct ath12k_vif *arvif)
1099d8899132SKalle Valo {
1100d8899132SKalle Valo 	struct ath12k *ar = arvif->ar;
1101d8899132SKalle Valo 	struct ath12k_base *ab = ar->ab;
1102d8899132SKalle Valo 	struct ieee80211_hw *hw = ar->hw;
1103d8899132SKalle Valo 	struct ieee80211_vif *vif = arvif->vif;
1104d8899132SKalle Valo 	struct ieee80211_mutable_offsets offs = {};
1105d8899132SKalle Valo 	struct sk_buff *bcn;
1106d8899132SKalle Valo 	struct ieee80211_mgmt *mgmt;
1107d8899132SKalle Valo 	u8 *ies;
1108d8899132SKalle Valo 	int ret;
1109d8899132SKalle Valo 
1110d8899132SKalle Valo 	if (arvif->vdev_type != WMI_VDEV_TYPE_AP)
1111d8899132SKalle Valo 		return 0;
1112d8899132SKalle Valo 
1113d8899132SKalle Valo 	bcn = ieee80211_beacon_get_template(hw, vif, &offs, 0);
1114d8899132SKalle Valo 	if (!bcn) {
1115d8899132SKalle Valo 		ath12k_warn(ab, "failed to get beacon template from mac80211\n");
1116d8899132SKalle Valo 		return -EPERM;
1117d8899132SKalle Valo 	}
1118d8899132SKalle Valo 
1119d8899132SKalle Valo 	ies = bcn->data + ieee80211_get_hdrlen_from_skb(bcn);
1120d8899132SKalle Valo 	ies += sizeof(mgmt->u.beacon);
1121d8899132SKalle Valo 
1122d8899132SKalle Valo 	if (cfg80211_find_ie(WLAN_EID_RSN, ies, (skb_tail_pointer(bcn) - ies)))
1123d8899132SKalle Valo 		arvif->rsnie_present = true;
1124d8899132SKalle Valo 
1125d8899132SKalle Valo 	if (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1126d8899132SKalle Valo 				    WLAN_OUI_TYPE_MICROSOFT_WPA,
1127d8899132SKalle Valo 				    ies, (skb_tail_pointer(bcn) - ies)))
1128d8899132SKalle Valo 		arvif->wpaie_present = true;
1129d8899132SKalle Valo 
1130d8899132SKalle Valo 	ret = ath12k_wmi_bcn_tmpl(ar, arvif->vdev_id, &offs, bcn);
1131d8899132SKalle Valo 
1132d8899132SKalle Valo 	kfree_skb(bcn);
1133d8899132SKalle Valo 
1134d8899132SKalle Valo 	if (ret)
1135d8899132SKalle Valo 		ath12k_warn(ab, "failed to submit beacon template command: %d\n",
1136d8899132SKalle Valo 			    ret);
1137d8899132SKalle Valo 
1138d8899132SKalle Valo 	return ret;
1139d8899132SKalle Valo }
1140d8899132SKalle Valo 
1141d8899132SKalle Valo static void ath12k_control_beaconing(struct ath12k_vif *arvif,
1142d8899132SKalle Valo 				     struct ieee80211_bss_conf *info)
1143d8899132SKalle Valo {
1144d8899132SKalle Valo 	struct ath12k *ar = arvif->ar;
1145d8899132SKalle Valo 	int ret;
1146d8899132SKalle Valo 
1147d8899132SKalle Valo 	lockdep_assert_held(&arvif->ar->conf_mutex);
1148d8899132SKalle Valo 
1149d8899132SKalle Valo 	if (!info->enable_beacon) {
1150d8899132SKalle Valo 		ret = ath12k_wmi_vdev_down(ar, arvif->vdev_id);
1151d8899132SKalle Valo 		if (ret)
1152d8899132SKalle Valo 			ath12k_warn(ar->ab, "failed to down vdev_id %i: %d\n",
1153d8899132SKalle Valo 				    arvif->vdev_id, ret);
1154d8899132SKalle Valo 
1155d8899132SKalle Valo 		arvif->is_up = false;
1156d8899132SKalle Valo 		return;
1157d8899132SKalle Valo 	}
1158d8899132SKalle Valo 
1159d8899132SKalle Valo 	/* Install the beacon template to the FW */
1160d8899132SKalle Valo 	ret = ath12k_mac_setup_bcn_tmpl(arvif);
1161d8899132SKalle Valo 	if (ret) {
1162d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to update bcn tmpl during vdev up: %d\n",
1163d8899132SKalle Valo 			    ret);
1164d8899132SKalle Valo 		return;
1165d8899132SKalle Valo 	}
1166d8899132SKalle Valo 
1167d8899132SKalle Valo 	arvif->aid = 0;
1168d8899132SKalle Valo 
1169d8899132SKalle Valo 	ether_addr_copy(arvif->bssid, info->bssid);
1170d8899132SKalle Valo 
1171d8899132SKalle Valo 	ret = ath12k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid,
1172d8899132SKalle Valo 				 arvif->bssid);
1173d8899132SKalle Valo 	if (ret) {
1174d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to bring up vdev %d: %i\n",
1175d8899132SKalle Valo 			    arvif->vdev_id, ret);
1176d8899132SKalle Valo 		return;
1177d8899132SKalle Valo 	}
1178d8899132SKalle Valo 
1179d8899132SKalle Valo 	arvif->is_up = true;
1180d8899132SKalle Valo 
1181d8899132SKalle Valo 	ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev %d up\n", arvif->vdev_id);
1182d8899132SKalle Valo }
1183d8899132SKalle Valo 
1184d8899132SKalle Valo static void ath12k_peer_assoc_h_basic(struct ath12k *ar,
1185d8899132SKalle Valo 				      struct ieee80211_vif *vif,
1186d8899132SKalle Valo 				      struct ieee80211_sta *sta,
1187d8899132SKalle Valo 				      struct ath12k_wmi_peer_assoc_arg *arg)
1188d8899132SKalle Valo {
1189d8899132SKalle Valo 	struct ath12k_vif *arvif = (void *)vif->drv_priv;
1190d8899132SKalle Valo 	u32 aid;
1191d8899132SKalle Valo 
1192d8899132SKalle Valo 	lockdep_assert_held(&ar->conf_mutex);
1193d8899132SKalle Valo 
1194d8899132SKalle Valo 	if (vif->type == NL80211_IFTYPE_STATION)
1195d8899132SKalle Valo 		aid = vif->cfg.aid;
1196d8899132SKalle Valo 	else
1197d8899132SKalle Valo 		aid = sta->aid;
1198d8899132SKalle Valo 
1199d8899132SKalle Valo 	ether_addr_copy(arg->peer_mac, sta->addr);
1200d8899132SKalle Valo 	arg->vdev_id = arvif->vdev_id;
1201d8899132SKalle Valo 	arg->peer_associd = aid;
1202d8899132SKalle Valo 	arg->auth_flag = true;
1203d8899132SKalle Valo 	/* TODO: STA WAR in ath10k for listen interval required? */
1204d8899132SKalle Valo 	arg->peer_listen_intval = ar->hw->conf.listen_interval;
1205d8899132SKalle Valo 	arg->peer_nss = 1;
1206d8899132SKalle Valo 	arg->peer_caps = vif->bss_conf.assoc_capability;
1207d8899132SKalle Valo }
1208d8899132SKalle Valo 
1209d8899132SKalle Valo static void ath12k_peer_assoc_h_crypto(struct ath12k *ar,
1210d8899132SKalle Valo 				       struct ieee80211_vif *vif,
1211d8899132SKalle Valo 				       struct ieee80211_sta *sta,
1212d8899132SKalle Valo 				       struct ath12k_wmi_peer_assoc_arg *arg)
1213d8899132SKalle Valo {
1214d8899132SKalle Valo 	struct ieee80211_bss_conf *info = &vif->bss_conf;
1215d8899132SKalle Valo 	struct cfg80211_chan_def def;
1216d8899132SKalle Valo 	struct cfg80211_bss *bss;
1217d8899132SKalle Valo 	struct ath12k_vif *arvif = (struct ath12k_vif *)vif->drv_priv;
1218d8899132SKalle Valo 	const u8 *rsnie = NULL;
1219d8899132SKalle Valo 	const u8 *wpaie = NULL;
1220d8899132SKalle Valo 
1221d8899132SKalle Valo 	lockdep_assert_held(&ar->conf_mutex);
1222d8899132SKalle Valo 
1223d8899132SKalle Valo 	if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))
1224d8899132SKalle Valo 		return;
1225d8899132SKalle Valo 
1226d8899132SKalle Valo 	bss = cfg80211_get_bss(ar->hw->wiphy, def.chan, info->bssid, NULL, 0,
1227d8899132SKalle Valo 			       IEEE80211_BSS_TYPE_ANY, IEEE80211_PRIVACY_ANY);
1228d8899132SKalle Valo 
1229d8899132SKalle Valo 	if (arvif->rsnie_present || arvif->wpaie_present) {
1230d8899132SKalle Valo 		arg->need_ptk_4_way = true;
1231d8899132SKalle Valo 		if (arvif->wpaie_present)
1232d8899132SKalle Valo 			arg->need_gtk_2_way = true;
1233d8899132SKalle Valo 	} else if (bss) {
1234d8899132SKalle Valo 		const struct cfg80211_bss_ies *ies;
1235d8899132SKalle Valo 
1236d8899132SKalle Valo 		rcu_read_lock();
1237d8899132SKalle Valo 		rsnie = ieee80211_bss_get_ie(bss, WLAN_EID_RSN);
1238d8899132SKalle Valo 
1239d8899132SKalle Valo 		ies = rcu_dereference(bss->ies);
1240d8899132SKalle Valo 
1241d8899132SKalle Valo 		wpaie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1242d8899132SKalle Valo 						WLAN_OUI_TYPE_MICROSOFT_WPA,
1243d8899132SKalle Valo 						ies->data,
1244d8899132SKalle Valo 						ies->len);
1245d8899132SKalle Valo 		rcu_read_unlock();
1246d8899132SKalle Valo 		cfg80211_put_bss(ar->hw->wiphy, bss);
1247d8899132SKalle Valo 	}
1248d8899132SKalle Valo 
1249d8899132SKalle Valo 	/* FIXME: base on RSN IE/WPA IE is a correct idea? */
1250d8899132SKalle Valo 	if (rsnie || wpaie) {
1251d8899132SKalle Valo 		ath12k_dbg(ar->ab, ATH12K_DBG_WMI,
1252d8899132SKalle Valo 			   "%s: rsn ie found\n", __func__);
1253d8899132SKalle Valo 		arg->need_ptk_4_way = true;
1254d8899132SKalle Valo 	}
1255d8899132SKalle Valo 
1256d8899132SKalle Valo 	if (wpaie) {
1257d8899132SKalle Valo 		ath12k_dbg(ar->ab, ATH12K_DBG_WMI,
1258d8899132SKalle Valo 			   "%s: wpa ie found\n", __func__);
1259d8899132SKalle Valo 		arg->need_gtk_2_way = true;
1260d8899132SKalle Valo 	}
1261d8899132SKalle Valo 
1262d8899132SKalle Valo 	if (sta->mfp) {
1263d8899132SKalle Valo 		/* TODO: Need to check if FW supports PMF? */
1264d8899132SKalle Valo 		arg->is_pmf_enabled = true;
1265d8899132SKalle Valo 	}
1266d8899132SKalle Valo 
1267d8899132SKalle Valo 	/* TODO: safe_mode_enabled (bypass 4-way handshake) flag req? */
1268d8899132SKalle Valo }
1269d8899132SKalle Valo 
1270d8899132SKalle Valo static void ath12k_peer_assoc_h_rates(struct ath12k *ar,
1271d8899132SKalle Valo 				      struct ieee80211_vif *vif,
1272d8899132SKalle Valo 				      struct ieee80211_sta *sta,
1273d8899132SKalle Valo 				      struct ath12k_wmi_peer_assoc_arg *arg)
1274d8899132SKalle Valo {
1275d8899132SKalle Valo 	struct ath12k_vif *arvif = (void *)vif->drv_priv;
1276d8899132SKalle Valo 	struct wmi_rate_set_arg *rateset = &arg->peer_legacy_rates;
1277d8899132SKalle Valo 	struct cfg80211_chan_def def;
1278d8899132SKalle Valo 	const struct ieee80211_supported_band *sband;
1279d8899132SKalle Valo 	const struct ieee80211_rate *rates;
1280d8899132SKalle Valo 	enum nl80211_band band;
1281d8899132SKalle Valo 	u32 ratemask;
1282d8899132SKalle Valo 	u8 rate;
1283d8899132SKalle Valo 	int i;
1284d8899132SKalle Valo 
1285d8899132SKalle Valo 	lockdep_assert_held(&ar->conf_mutex);
1286d8899132SKalle Valo 
1287d8899132SKalle Valo 	if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))
1288d8899132SKalle Valo 		return;
1289d8899132SKalle Valo 
1290d8899132SKalle Valo 	band = def.chan->band;
1291d8899132SKalle Valo 	sband = ar->hw->wiphy->bands[band];
1292d8899132SKalle Valo 	ratemask = sta->deflink.supp_rates[band];
1293d8899132SKalle Valo 	ratemask &= arvif->bitrate_mask.control[band].legacy;
1294d8899132SKalle Valo 	rates = sband->bitrates;
1295d8899132SKalle Valo 
1296d8899132SKalle Valo 	rateset->num_rates = 0;
1297d8899132SKalle Valo 
1298d8899132SKalle Valo 	for (i = 0; i < 32; i++, ratemask >>= 1, rates++) {
1299d8899132SKalle Valo 		if (!(ratemask & 1))
1300d8899132SKalle Valo 			continue;
1301d8899132SKalle Valo 
1302d8899132SKalle Valo 		rate = ath12k_mac_bitrate_to_rate(rates->bitrate);
1303d8899132SKalle Valo 		rateset->rates[rateset->num_rates] = rate;
1304d8899132SKalle Valo 		rateset->num_rates++;
1305d8899132SKalle Valo 	}
1306d8899132SKalle Valo }
1307d8899132SKalle Valo 
1308d8899132SKalle Valo static bool
1309695df2f4SArnd Bergmann ath12k_peer_assoc_h_ht_masked(const u8 *ht_mcs_mask)
1310d8899132SKalle Valo {
1311d8899132SKalle Valo 	int nss;
1312d8899132SKalle Valo 
1313d8899132SKalle Valo 	for (nss = 0; nss < IEEE80211_HT_MCS_MASK_LEN; nss++)
1314d8899132SKalle Valo 		if (ht_mcs_mask[nss])
1315d8899132SKalle Valo 			return false;
1316d8899132SKalle Valo 
1317d8899132SKalle Valo 	return true;
1318d8899132SKalle Valo }
1319d8899132SKalle Valo 
1320d8899132SKalle Valo static bool
1321695df2f4SArnd Bergmann ath12k_peer_assoc_h_vht_masked(const u16 *vht_mcs_mask)
1322d8899132SKalle Valo {
1323d8899132SKalle Valo 	int nss;
1324d8899132SKalle Valo 
1325d8899132SKalle Valo 	for (nss = 0; nss < NL80211_VHT_NSS_MAX; nss++)
1326d8899132SKalle Valo 		if (vht_mcs_mask[nss])
1327d8899132SKalle Valo 			return false;
1328d8899132SKalle Valo 
1329d8899132SKalle Valo 	return true;
1330d8899132SKalle Valo }
1331d8899132SKalle Valo 
1332d8899132SKalle Valo static void ath12k_peer_assoc_h_ht(struct ath12k *ar,
1333d8899132SKalle Valo 				   struct ieee80211_vif *vif,
1334d8899132SKalle Valo 				   struct ieee80211_sta *sta,
1335d8899132SKalle Valo 				   struct ath12k_wmi_peer_assoc_arg *arg)
1336d8899132SKalle Valo {
1337d8899132SKalle Valo 	const struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap;
1338d8899132SKalle Valo 	struct ath12k_vif *arvif = (void *)vif->drv_priv;
1339d8899132SKalle Valo 	struct cfg80211_chan_def def;
1340d8899132SKalle Valo 	enum nl80211_band band;
1341d8899132SKalle Valo 	const u8 *ht_mcs_mask;
1342d8899132SKalle Valo 	int i, n;
1343d8899132SKalle Valo 	u8 max_nss;
1344d8899132SKalle Valo 	u32 stbc;
1345d8899132SKalle Valo 
1346d8899132SKalle Valo 	lockdep_assert_held(&ar->conf_mutex);
1347d8899132SKalle Valo 
1348d8899132SKalle Valo 	if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))
1349d8899132SKalle Valo 		return;
1350d8899132SKalle Valo 
1351d8899132SKalle Valo 	if (!ht_cap->ht_supported)
1352d8899132SKalle Valo 		return;
1353d8899132SKalle Valo 
1354d8899132SKalle Valo 	band = def.chan->band;
1355d8899132SKalle Valo 	ht_mcs_mask = arvif->bitrate_mask.control[band].ht_mcs;
1356d8899132SKalle Valo 
1357d8899132SKalle Valo 	if (ath12k_peer_assoc_h_ht_masked(ht_mcs_mask))
1358d8899132SKalle Valo 		return;
1359d8899132SKalle Valo 
1360d8899132SKalle Valo 	arg->ht_flag = true;
1361d8899132SKalle Valo 
1362d8899132SKalle Valo 	arg->peer_max_mpdu = (1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
1363d8899132SKalle Valo 				    ht_cap->ampdu_factor)) - 1;
1364d8899132SKalle Valo 
1365d8899132SKalle Valo 	arg->peer_mpdu_density =
1366d8899132SKalle Valo 		ath12k_parse_mpdudensity(ht_cap->ampdu_density);
1367d8899132SKalle Valo 
1368d8899132SKalle Valo 	arg->peer_ht_caps = ht_cap->cap;
1369d8899132SKalle Valo 	arg->peer_rate_caps |= WMI_HOST_RC_HT_FLAG;
1370d8899132SKalle Valo 
1371d8899132SKalle Valo 	if (ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING)
1372d8899132SKalle Valo 		arg->ldpc_flag = true;
1373d8899132SKalle Valo 
1374d8899132SKalle Valo 	if (sta->deflink.bandwidth >= IEEE80211_STA_RX_BW_40) {
1375d8899132SKalle Valo 		arg->bw_40 = true;
1376d8899132SKalle Valo 		arg->peer_rate_caps |= WMI_HOST_RC_CW40_FLAG;
1377d8899132SKalle Valo 	}
1378d8899132SKalle Valo 
1379d8899132SKalle Valo 	if (arvif->bitrate_mask.control[band].gi != NL80211_TXRATE_FORCE_LGI) {
1380d8899132SKalle Valo 		if (ht_cap->cap & (IEEE80211_HT_CAP_SGI_20 |
1381d8899132SKalle Valo 		    IEEE80211_HT_CAP_SGI_40))
1382d8899132SKalle Valo 			arg->peer_rate_caps |= WMI_HOST_RC_SGI_FLAG;
1383d8899132SKalle Valo 	}
1384d8899132SKalle Valo 
1385d8899132SKalle Valo 	if (ht_cap->cap & IEEE80211_HT_CAP_TX_STBC) {
1386d8899132SKalle Valo 		arg->peer_rate_caps |= WMI_HOST_RC_TX_STBC_FLAG;
1387d8899132SKalle Valo 		arg->stbc_flag = true;
1388d8899132SKalle Valo 	}
1389d8899132SKalle Valo 
1390d8899132SKalle Valo 	if (ht_cap->cap & IEEE80211_HT_CAP_RX_STBC) {
1391d8899132SKalle Valo 		stbc = ht_cap->cap & IEEE80211_HT_CAP_RX_STBC;
1392d8899132SKalle Valo 		stbc = stbc >> IEEE80211_HT_CAP_RX_STBC_SHIFT;
1393d8899132SKalle Valo 		stbc = stbc << WMI_HOST_RC_RX_STBC_FLAG_S;
1394d8899132SKalle Valo 		arg->peer_rate_caps |= stbc;
1395d8899132SKalle Valo 		arg->stbc_flag = true;
1396d8899132SKalle Valo 	}
1397d8899132SKalle Valo 
1398d8899132SKalle Valo 	if (ht_cap->mcs.rx_mask[1] && ht_cap->mcs.rx_mask[2])
1399d8899132SKalle Valo 		arg->peer_rate_caps |= WMI_HOST_RC_TS_FLAG;
1400d8899132SKalle Valo 	else if (ht_cap->mcs.rx_mask[1])
1401d8899132SKalle Valo 		arg->peer_rate_caps |= WMI_HOST_RC_DS_FLAG;
1402d8899132SKalle Valo 
1403d8899132SKalle Valo 	for (i = 0, n = 0, max_nss = 0; i < IEEE80211_HT_MCS_MASK_LEN * 8; i++)
1404d8899132SKalle Valo 		if ((ht_cap->mcs.rx_mask[i / 8] & BIT(i % 8)) &&
1405d8899132SKalle Valo 		    (ht_mcs_mask[i / 8] & BIT(i % 8))) {
1406d8899132SKalle Valo 			max_nss = (i / 8) + 1;
1407d8899132SKalle Valo 			arg->peer_ht_rates.rates[n++] = i;
1408d8899132SKalle Valo 		}
1409d8899132SKalle Valo 
1410d8899132SKalle Valo 	/* This is a workaround for HT-enabled STAs which break the spec
1411d8899132SKalle Valo 	 * and have no HT capabilities RX mask (no HT RX MCS map).
1412d8899132SKalle Valo 	 *
1413d8899132SKalle Valo 	 * As per spec, in section 20.3.5 Modulation and coding scheme (MCS),
1414d8899132SKalle Valo 	 * MCS 0 through 7 are mandatory in 20MHz with 800 ns GI at all STAs.
1415d8899132SKalle Valo 	 *
1416d8899132SKalle Valo 	 * Firmware asserts if such situation occurs.
1417d8899132SKalle Valo 	 */
1418d8899132SKalle Valo 	if (n == 0) {
1419d8899132SKalle Valo 		arg->peer_ht_rates.num_rates = 8;
1420d8899132SKalle Valo 		for (i = 0; i < arg->peer_ht_rates.num_rates; i++)
1421d8899132SKalle Valo 			arg->peer_ht_rates.rates[i] = i;
1422d8899132SKalle Valo 	} else {
1423d8899132SKalle Valo 		arg->peer_ht_rates.num_rates = n;
1424d8899132SKalle Valo 		arg->peer_nss = min(sta->deflink.rx_nss, max_nss);
1425d8899132SKalle Valo 	}
1426d8899132SKalle Valo 
1427d8899132SKalle Valo 	ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac ht peer %pM mcs cnt %d nss %d\n",
1428d8899132SKalle Valo 		   arg->peer_mac,
1429d8899132SKalle Valo 		   arg->peer_ht_rates.num_rates,
1430d8899132SKalle Valo 		   arg->peer_nss);
1431d8899132SKalle Valo }
1432d8899132SKalle Valo 
1433d8899132SKalle Valo static int ath12k_mac_get_max_vht_mcs_map(u16 mcs_map, int nss)
1434d8899132SKalle Valo {
1435d8899132SKalle Valo 	switch ((mcs_map >> (2 * nss)) & 0x3) {
1436d8899132SKalle Valo 	case IEEE80211_VHT_MCS_SUPPORT_0_7: return BIT(8) - 1;
1437d8899132SKalle Valo 	case IEEE80211_VHT_MCS_SUPPORT_0_8: return BIT(9) - 1;
1438d8899132SKalle Valo 	case IEEE80211_VHT_MCS_SUPPORT_0_9: return BIT(10) - 1;
1439d8899132SKalle Valo 	}
1440d8899132SKalle Valo 	return 0;
1441d8899132SKalle Valo }
1442d8899132SKalle Valo 
1443d8899132SKalle Valo static u16
1444d8899132SKalle Valo ath12k_peer_assoc_h_vht_limit(u16 tx_mcs_set,
1445d8899132SKalle Valo 			      const u16 vht_mcs_limit[NL80211_VHT_NSS_MAX])
1446d8899132SKalle Valo {
1447d8899132SKalle Valo 	int idx_limit;
1448d8899132SKalle Valo 	int nss;
1449d8899132SKalle Valo 	u16 mcs_map;
1450d8899132SKalle Valo 	u16 mcs;
1451d8899132SKalle Valo 
1452d8899132SKalle Valo 	for (nss = 0; nss < NL80211_VHT_NSS_MAX; nss++) {
1453d8899132SKalle Valo 		mcs_map = ath12k_mac_get_max_vht_mcs_map(tx_mcs_set, nss) &
1454d8899132SKalle Valo 			  vht_mcs_limit[nss];
1455d8899132SKalle Valo 
1456d8899132SKalle Valo 		if (mcs_map)
1457d8899132SKalle Valo 			idx_limit = fls(mcs_map) - 1;
1458d8899132SKalle Valo 		else
1459d8899132SKalle Valo 			idx_limit = -1;
1460d8899132SKalle Valo 
1461d8899132SKalle Valo 		switch (idx_limit) {
1462d8899132SKalle Valo 		case 0:
1463d8899132SKalle Valo 		case 1:
1464d8899132SKalle Valo 		case 2:
1465d8899132SKalle Valo 		case 3:
1466d8899132SKalle Valo 		case 4:
1467d8899132SKalle Valo 		case 5:
1468d8899132SKalle Valo 		case 6:
1469d8899132SKalle Valo 		case 7:
1470d8899132SKalle Valo 			mcs = IEEE80211_VHT_MCS_SUPPORT_0_7;
1471d8899132SKalle Valo 			break;
1472d8899132SKalle Valo 		case 8:
1473d8899132SKalle Valo 			mcs = IEEE80211_VHT_MCS_SUPPORT_0_8;
1474d8899132SKalle Valo 			break;
1475d8899132SKalle Valo 		case 9:
1476d8899132SKalle Valo 			mcs = IEEE80211_VHT_MCS_SUPPORT_0_9;
1477d8899132SKalle Valo 			break;
1478d8899132SKalle Valo 		default:
1479d8899132SKalle Valo 			WARN_ON(1);
1480d8899132SKalle Valo 			fallthrough;
1481d8899132SKalle Valo 		case -1:
1482d8899132SKalle Valo 			mcs = IEEE80211_VHT_MCS_NOT_SUPPORTED;
1483d8899132SKalle Valo 			break;
1484d8899132SKalle Valo 		}
1485d8899132SKalle Valo 
1486d8899132SKalle Valo 		tx_mcs_set &= ~(0x3 << (nss * 2));
1487d8899132SKalle Valo 		tx_mcs_set |= mcs << (nss * 2);
1488d8899132SKalle Valo 	}
1489d8899132SKalle Valo 
1490d8899132SKalle Valo 	return tx_mcs_set;
1491d8899132SKalle Valo }
1492d8899132SKalle Valo 
1493d8899132SKalle Valo static void ath12k_peer_assoc_h_vht(struct ath12k *ar,
1494d8899132SKalle Valo 				    struct ieee80211_vif *vif,
1495d8899132SKalle Valo 				    struct ieee80211_sta *sta,
1496d8899132SKalle Valo 				    struct ath12k_wmi_peer_assoc_arg *arg)
1497d8899132SKalle Valo {
1498d8899132SKalle Valo 	const struct ieee80211_sta_vht_cap *vht_cap = &sta->deflink.vht_cap;
1499d8899132SKalle Valo 	struct ath12k_vif *arvif = (void *)vif->drv_priv;
1500d8899132SKalle Valo 	struct cfg80211_chan_def def;
1501d8899132SKalle Valo 	enum nl80211_band band;
1502d8899132SKalle Valo 	const u16 *vht_mcs_mask;
1503d8899132SKalle Valo 	u16 tx_mcs_map;
1504d8899132SKalle Valo 	u8 ampdu_factor;
1505d8899132SKalle Valo 	u8 max_nss, vht_mcs;
1506d8899132SKalle Valo 	int i;
1507d8899132SKalle Valo 
1508d8899132SKalle Valo 	if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))
1509d8899132SKalle Valo 		return;
1510d8899132SKalle Valo 
1511d8899132SKalle Valo 	if (!vht_cap->vht_supported)
1512d8899132SKalle Valo 		return;
1513d8899132SKalle Valo 
1514d8899132SKalle Valo 	band = def.chan->band;
1515d8899132SKalle Valo 	vht_mcs_mask = arvif->bitrate_mask.control[band].vht_mcs;
1516d8899132SKalle Valo 
1517d8899132SKalle Valo 	if (ath12k_peer_assoc_h_vht_masked(vht_mcs_mask))
1518d8899132SKalle Valo 		return;
1519d8899132SKalle Valo 
1520d8899132SKalle Valo 	arg->vht_flag = true;
1521d8899132SKalle Valo 
1522d8899132SKalle Valo 	/* TODO: similar flags required? */
1523d8899132SKalle Valo 	arg->vht_capable = true;
1524d8899132SKalle Valo 
1525d8899132SKalle Valo 	if (def.chan->band == NL80211_BAND_2GHZ)
1526d8899132SKalle Valo 		arg->vht_ng_flag = true;
1527d8899132SKalle Valo 
1528d8899132SKalle Valo 	arg->peer_vht_caps = vht_cap->cap;
1529d8899132SKalle Valo 
1530d8899132SKalle Valo 	ampdu_factor = (vht_cap->cap &
1531d8899132SKalle Valo 			IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK) >>
1532d8899132SKalle Valo 		       IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;
1533d8899132SKalle Valo 
1534d8899132SKalle Valo 	/* Workaround: Some Netgear/Linksys 11ac APs set Rx A-MPDU factor to
1535d8899132SKalle Valo 	 * zero in VHT IE. Using it would result in degraded throughput.
1536d8899132SKalle Valo 	 * arg->peer_max_mpdu at this point contains HT max_mpdu so keep
1537d8899132SKalle Valo 	 * it if VHT max_mpdu is smaller.
1538d8899132SKalle Valo 	 */
1539d8899132SKalle Valo 	arg->peer_max_mpdu = max(arg->peer_max_mpdu,
1540d8899132SKalle Valo 				 (1U << (IEEE80211_HT_MAX_AMPDU_FACTOR +
1541d8899132SKalle Valo 					ampdu_factor)) - 1);
1542d8899132SKalle Valo 
1543d8899132SKalle Valo 	if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80)
1544d8899132SKalle Valo 		arg->bw_80 = true;
1545d8899132SKalle Valo 
1546d8899132SKalle Valo 	if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160)
1547d8899132SKalle Valo 		arg->bw_160 = true;
1548d8899132SKalle Valo 
1549d8899132SKalle Valo 	/* Calculate peer NSS capability from VHT capabilities if STA
1550d8899132SKalle Valo 	 * supports VHT.
1551d8899132SKalle Valo 	 */
1552d8899132SKalle Valo 	for (i = 0, max_nss = 0, vht_mcs = 0; i < NL80211_VHT_NSS_MAX; i++) {
1553d8899132SKalle Valo 		vht_mcs = __le16_to_cpu(vht_cap->vht_mcs.rx_mcs_map) >>
1554d8899132SKalle Valo 			  (2 * i) & 3;
1555d8899132SKalle Valo 
1556d8899132SKalle Valo 		if (vht_mcs != IEEE80211_VHT_MCS_NOT_SUPPORTED &&
1557d8899132SKalle Valo 		    vht_mcs_mask[i])
1558d8899132SKalle Valo 			max_nss = i + 1;
1559d8899132SKalle Valo 	}
1560d8899132SKalle Valo 	arg->peer_nss = min(sta->deflink.rx_nss, max_nss);
1561d8899132SKalle Valo 	arg->rx_max_rate = __le16_to_cpu(vht_cap->vht_mcs.rx_highest);
1562d8899132SKalle Valo 	arg->rx_mcs_set = __le16_to_cpu(vht_cap->vht_mcs.rx_mcs_map);
1563d8899132SKalle Valo 	arg->tx_max_rate = __le16_to_cpu(vht_cap->vht_mcs.tx_highest);
1564d8899132SKalle Valo 
1565d8899132SKalle Valo 	tx_mcs_map = __le16_to_cpu(vht_cap->vht_mcs.tx_mcs_map);
1566d8899132SKalle Valo 	arg->tx_mcs_set = ath12k_peer_assoc_h_vht_limit(tx_mcs_map, vht_mcs_mask);
1567d8899132SKalle Valo 
1568d8899132SKalle Valo 	/* In QCN9274 platform, VHT MCS rate 10 and 11 is enabled by default.
1569d8899132SKalle Valo 	 * VHT MCS rate 10 and 11 is not supported in 11ac standard.
1570d8899132SKalle Valo 	 * so explicitly disable the VHT MCS rate 10 and 11 in 11ac mode.
1571d8899132SKalle Valo 	 */
1572d8899132SKalle Valo 	arg->tx_mcs_set &= ~IEEE80211_VHT_MCS_SUPPORT_0_11_MASK;
1573d8899132SKalle Valo 	arg->tx_mcs_set |= IEEE80211_DISABLE_VHT_MCS_SUPPORT_0_11;
1574d8899132SKalle Valo 
1575d8899132SKalle Valo 	if ((arg->tx_mcs_set & IEEE80211_VHT_MCS_NOT_SUPPORTED) ==
1576d8899132SKalle Valo 			IEEE80211_VHT_MCS_NOT_SUPPORTED)
1577d8899132SKalle Valo 		arg->peer_vht_caps &= ~IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
1578d8899132SKalle Valo 
1579d8899132SKalle Valo 	/* TODO:  Check */
1580d8899132SKalle Valo 	arg->tx_max_mcs_nss = 0xFF;
1581d8899132SKalle Valo 
1582d8899132SKalle Valo 	ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vht peer %pM max_mpdu %d flags 0x%x\n",
1583d8899132SKalle Valo 		   sta->addr, arg->peer_max_mpdu, arg->peer_flags);
1584d8899132SKalle Valo 
1585d8899132SKalle Valo 	/* TODO: rxnss_override */
1586d8899132SKalle Valo }
1587d8899132SKalle Valo 
1588d8899132SKalle Valo static void ath12k_peer_assoc_h_he(struct ath12k *ar,
1589d8899132SKalle Valo 				   struct ieee80211_vif *vif,
1590d8899132SKalle Valo 				   struct ieee80211_sta *sta,
1591d8899132SKalle Valo 				   struct ath12k_wmi_peer_assoc_arg *arg)
1592d8899132SKalle Valo {
1593d8899132SKalle Valo 	const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap;
1594d8899132SKalle Valo 	int i;
1595d8899132SKalle Valo 	u8 ampdu_factor, rx_mcs_80, rx_mcs_160, max_nss;
1596d8899132SKalle Valo 	u16 mcs_160_map, mcs_80_map;
1597d8899132SKalle Valo 	bool support_160;
1598d8899132SKalle Valo 	u16 v;
1599d8899132SKalle Valo 
1600d8899132SKalle Valo 	if (!he_cap->has_he)
1601d8899132SKalle Valo 		return;
1602d8899132SKalle Valo 
1603d8899132SKalle Valo 	arg->he_flag = true;
1604d8899132SKalle Valo 
1605d8899132SKalle Valo 	support_160 = !!(he_cap->he_cap_elem.phy_cap_info[0] &
1606d8899132SKalle Valo 		  IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G);
1607d8899132SKalle Valo 
1608d8899132SKalle Valo 	/* Supported HE-MCS and NSS Set of peer he_cap is intersection with self he_cp */
1609d8899132SKalle Valo 	mcs_160_map = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160);
1610d8899132SKalle Valo 	mcs_80_map = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80);
1611d8899132SKalle Valo 
1612d8899132SKalle Valo 	if (support_160) {
1613d8899132SKalle Valo 		for (i = 7; i >= 0; i--) {
1614d8899132SKalle Valo 			u8 mcs_160 = (mcs_160_map >> (2 * i)) & 3;
1615d8899132SKalle Valo 
1616d8899132SKalle Valo 			if (mcs_160 != IEEE80211_HE_MCS_NOT_SUPPORTED) {
1617d8899132SKalle Valo 				rx_mcs_160 = i + 1;
1618d8899132SKalle Valo 				break;
1619d8899132SKalle Valo 			}
1620d8899132SKalle Valo 		}
1621d8899132SKalle Valo 	}
1622d8899132SKalle Valo 
1623d8899132SKalle Valo 	for (i = 7; i >= 0; i--) {
1624d8899132SKalle Valo 		u8 mcs_80 = (mcs_80_map >> (2 * i)) & 3;
1625d8899132SKalle Valo 
1626d8899132SKalle Valo 		if (mcs_80 != IEEE80211_HE_MCS_NOT_SUPPORTED) {
1627d8899132SKalle Valo 			rx_mcs_80 = i + 1;
1628d8899132SKalle Valo 			break;
1629d8899132SKalle Valo 		}
1630d8899132SKalle Valo 	}
1631d8899132SKalle Valo 
1632d8899132SKalle Valo 	if (support_160)
1633d8899132SKalle Valo 		max_nss = min(rx_mcs_80, rx_mcs_160);
1634d8899132SKalle Valo 	else
1635d8899132SKalle Valo 		max_nss = rx_mcs_80;
1636d8899132SKalle Valo 
1637d8899132SKalle Valo 	arg->peer_nss = min(sta->deflink.rx_nss, max_nss);
1638d8899132SKalle Valo 
1639d8899132SKalle Valo 	memcpy(&arg->peer_he_cap_macinfo, he_cap->he_cap_elem.mac_cap_info,
1640*603cf6c2SArnd Bergmann 	       sizeof(he_cap->he_cap_elem.mac_cap_info));
1641d8899132SKalle Valo 	memcpy(&arg->peer_he_cap_phyinfo, he_cap->he_cap_elem.phy_cap_info,
1642*603cf6c2SArnd Bergmann 	       sizeof(he_cap->he_cap_elem.phy_cap_info));
1643d8899132SKalle Valo 	arg->peer_he_ops = vif->bss_conf.he_oper.params;
1644d8899132SKalle Valo 
1645d8899132SKalle Valo 	/* the top most byte is used to indicate BSS color info */
1646d8899132SKalle Valo 	arg->peer_he_ops &= 0xffffff;
1647d8899132SKalle Valo 
1648d8899132SKalle Valo 	/* As per section 26.6.1 IEEE Std 802.11ax‐2022, if the Max AMPDU
1649d8899132SKalle Valo 	 * Exponent Extension in HE cap is zero, use the arg->peer_max_mpdu
1650d8899132SKalle Valo 	 * as calculated while parsing VHT caps(if VHT caps is present)
1651d8899132SKalle Valo 	 * or HT caps (if VHT caps is not present).
1652d8899132SKalle Valo 	 *
1653d8899132SKalle Valo 	 * For non-zero value of Max AMPDU Exponent Extension in HE MAC caps,
1654d8899132SKalle Valo 	 * if a HE STA sends VHT cap and HE cap IE in assoc request then, use
1655d8899132SKalle Valo 	 * MAX_AMPDU_LEN_FACTOR as 20 to calculate max_ampdu length.
1656d8899132SKalle Valo 	 * If a HE STA that does not send VHT cap, but HE and HT cap in assoc
1657d8899132SKalle Valo 	 * request, then use MAX_AMPDU_LEN_FACTOR as 16 to calculate max_ampdu
1658d8899132SKalle Valo 	 * length.
1659d8899132SKalle Valo 	 */
1660d8899132SKalle Valo 	ampdu_factor = (he_cap->he_cap_elem.mac_cap_info[3] &
1661d8899132SKalle Valo 			IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_MASK) >>
1662d8899132SKalle Valo 			IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_MASK;
1663d8899132SKalle Valo 
1664d8899132SKalle Valo 	if (ampdu_factor) {
1665d8899132SKalle Valo 		if (sta->deflink.vht_cap.vht_supported)
1666d8899132SKalle Valo 			arg->peer_max_mpdu = (1 << (IEEE80211_HE_VHT_MAX_AMPDU_FACTOR +
1667d8899132SKalle Valo 						    ampdu_factor)) - 1;
1668d8899132SKalle Valo 		else if (sta->deflink.ht_cap.ht_supported)
1669d8899132SKalle Valo 			arg->peer_max_mpdu = (1 << (IEEE80211_HE_HT_MAX_AMPDU_FACTOR +
1670d8899132SKalle Valo 						    ampdu_factor)) - 1;
1671d8899132SKalle Valo 	}
1672d8899132SKalle Valo 
1673d8899132SKalle Valo 	if (he_cap->he_cap_elem.phy_cap_info[6] &
1674d8899132SKalle Valo 	    IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) {
1675d8899132SKalle Valo 		int bit = 7;
1676d8899132SKalle Valo 		int nss, ru;
1677d8899132SKalle Valo 
1678d8899132SKalle Valo 		arg->peer_ppet.numss_m1 = he_cap->ppe_thres[0] &
1679d8899132SKalle Valo 					  IEEE80211_PPE_THRES_NSS_MASK;
1680d8899132SKalle Valo 		arg->peer_ppet.ru_bit_mask =
1681d8899132SKalle Valo 			(he_cap->ppe_thres[0] &
1682d8899132SKalle Valo 			 IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK) >>
1683d8899132SKalle Valo 			IEEE80211_PPE_THRES_RU_INDEX_BITMASK_POS;
1684d8899132SKalle Valo 
1685d8899132SKalle Valo 		for (nss = 0; nss <= arg->peer_ppet.numss_m1; nss++) {
1686d8899132SKalle Valo 			for (ru = 0; ru < 4; ru++) {
1687d8899132SKalle Valo 				u32 val = 0;
1688d8899132SKalle Valo 				int i;
1689d8899132SKalle Valo 
1690d8899132SKalle Valo 				if ((arg->peer_ppet.ru_bit_mask & BIT(ru)) == 0)
1691d8899132SKalle Valo 					continue;
1692d8899132SKalle Valo 				for (i = 0; i < 6; i++) {
1693d8899132SKalle Valo 					val >>= 1;
1694d8899132SKalle Valo 					val |= ((he_cap->ppe_thres[bit / 8] >>
1695d8899132SKalle Valo 						 (bit % 8)) & 0x1) << 5;
1696d8899132SKalle Valo 					bit++;
1697d8899132SKalle Valo 				}
1698d8899132SKalle Valo 				arg->peer_ppet.ppet16_ppet8_ru3_ru0[nss] |=
1699d8899132SKalle Valo 								val << (ru * 6);
1700d8899132SKalle Valo 			}
1701d8899132SKalle Valo 		}
1702d8899132SKalle Valo 	}
1703d8899132SKalle Valo 
1704d8899132SKalle Valo 	if (he_cap->he_cap_elem.mac_cap_info[0] & IEEE80211_HE_MAC_CAP0_TWT_RES)
1705d8899132SKalle Valo 		arg->twt_responder = true;
1706d8899132SKalle Valo 	if (he_cap->he_cap_elem.mac_cap_info[0] & IEEE80211_HE_MAC_CAP0_TWT_REQ)
1707d8899132SKalle Valo 		arg->twt_requester = true;
1708d8899132SKalle Valo 
1709d8899132SKalle Valo 	switch (sta->deflink.bandwidth) {
1710d8899132SKalle Valo 	case IEEE80211_STA_RX_BW_160:
1711d8899132SKalle Valo 		if (he_cap->he_cap_elem.phy_cap_info[0] &
1712d8899132SKalle Valo 		    IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G) {
1713d8899132SKalle Valo 			v = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80p80);
1714d8899132SKalle Valo 			arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80_80] = v;
1715d8899132SKalle Valo 
1716d8899132SKalle Valo 			v = le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_80p80);
1717d8899132SKalle Valo 			arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80_80] = v;
1718d8899132SKalle Valo 
1719d8899132SKalle Valo 			arg->peer_he_mcs_count++;
1720d8899132SKalle Valo 		}
1721d8899132SKalle Valo 		v = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160);
1722d8899132SKalle Valo 		arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_160] = v;
1723d8899132SKalle Valo 
1724d8899132SKalle Valo 		v = le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_160);
1725d8899132SKalle Valo 		arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_160] = v;
1726d8899132SKalle Valo 
1727d8899132SKalle Valo 		arg->peer_he_mcs_count++;
1728d8899132SKalle Valo 		fallthrough;
1729d8899132SKalle Valo 
1730d8899132SKalle Valo 	default:
1731d8899132SKalle Valo 		v = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80);
1732d8899132SKalle Valo 		arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80] = v;
1733d8899132SKalle Valo 
1734d8899132SKalle Valo 		v = le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_80);
1735d8899132SKalle Valo 		arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80] = v;
1736d8899132SKalle Valo 
1737d8899132SKalle Valo 		arg->peer_he_mcs_count++;
1738d8899132SKalle Valo 		break;
1739d8899132SKalle Valo 	}
1740d8899132SKalle Valo }
1741d8899132SKalle Valo 
1742d8899132SKalle Valo static void ath12k_peer_assoc_h_smps(struct ieee80211_sta *sta,
1743d8899132SKalle Valo 				     struct ath12k_wmi_peer_assoc_arg *arg)
1744d8899132SKalle Valo {
1745d8899132SKalle Valo 	const struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap;
1746d8899132SKalle Valo 	int smps;
1747d8899132SKalle Valo 
1748d8899132SKalle Valo 	if (!ht_cap->ht_supported)
1749d8899132SKalle Valo 		return;
1750d8899132SKalle Valo 
1751d8899132SKalle Valo 	smps = ht_cap->cap & IEEE80211_HT_CAP_SM_PS;
1752d8899132SKalle Valo 	smps >>= IEEE80211_HT_CAP_SM_PS_SHIFT;
1753d8899132SKalle Valo 
1754d8899132SKalle Valo 	switch (smps) {
1755d8899132SKalle Valo 	case WLAN_HT_CAP_SM_PS_STATIC:
1756d8899132SKalle Valo 		arg->static_mimops_flag = true;
1757d8899132SKalle Valo 		break;
1758d8899132SKalle Valo 	case WLAN_HT_CAP_SM_PS_DYNAMIC:
1759d8899132SKalle Valo 		arg->dynamic_mimops_flag = true;
1760d8899132SKalle Valo 		break;
1761d8899132SKalle Valo 	case WLAN_HT_CAP_SM_PS_DISABLED:
1762d8899132SKalle Valo 		arg->spatial_mux_flag = true;
1763d8899132SKalle Valo 		break;
1764d8899132SKalle Valo 	default:
1765d8899132SKalle Valo 		break;
1766d8899132SKalle Valo 	}
1767d8899132SKalle Valo }
1768d8899132SKalle Valo 
1769d8899132SKalle Valo static void ath12k_peer_assoc_h_qos(struct ath12k *ar,
1770d8899132SKalle Valo 				    struct ieee80211_vif *vif,
1771d8899132SKalle Valo 				    struct ieee80211_sta *sta,
1772d8899132SKalle Valo 				    struct ath12k_wmi_peer_assoc_arg *arg)
1773d8899132SKalle Valo {
1774d8899132SKalle Valo 	struct ath12k_vif *arvif = (void *)vif->drv_priv;
1775d8899132SKalle Valo 
1776d8899132SKalle Valo 	switch (arvif->vdev_type) {
1777d8899132SKalle Valo 	case WMI_VDEV_TYPE_AP:
1778d8899132SKalle Valo 		if (sta->wme) {
1779d8899132SKalle Valo 			/* TODO: Check WME vs QoS */
1780d8899132SKalle Valo 			arg->is_wme_set = true;
1781d8899132SKalle Valo 			arg->qos_flag = true;
1782d8899132SKalle Valo 		}
1783d8899132SKalle Valo 
1784d8899132SKalle Valo 		if (sta->wme && sta->uapsd_queues) {
1785d8899132SKalle Valo 			/* TODO: Check WME vs QoS */
1786d8899132SKalle Valo 			arg->is_wme_set = true;
1787d8899132SKalle Valo 			arg->apsd_flag = true;
1788d8899132SKalle Valo 			arg->peer_rate_caps |= WMI_HOST_RC_UAPSD_FLAG;
1789d8899132SKalle Valo 		}
1790d8899132SKalle Valo 		break;
1791d8899132SKalle Valo 	case WMI_VDEV_TYPE_STA:
1792d8899132SKalle Valo 		if (sta->wme) {
1793d8899132SKalle Valo 			arg->is_wme_set = true;
1794d8899132SKalle Valo 			arg->qos_flag = true;
1795d8899132SKalle Valo 		}
1796d8899132SKalle Valo 		break;
1797d8899132SKalle Valo 	default:
1798d8899132SKalle Valo 		break;
1799d8899132SKalle Valo 	}
1800d8899132SKalle Valo 
1801d8899132SKalle Valo 	ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac peer %pM qos %d\n",
1802d8899132SKalle Valo 		   sta->addr, arg->qos_flag);
1803d8899132SKalle Valo }
1804d8899132SKalle Valo 
1805d8899132SKalle Valo static int ath12k_peer_assoc_qos_ap(struct ath12k *ar,
1806d8899132SKalle Valo 				    struct ath12k_vif *arvif,
1807d8899132SKalle Valo 				    struct ieee80211_sta *sta)
1808d8899132SKalle Valo {
1809d8899132SKalle Valo 	struct ath12k_wmi_ap_ps_arg arg;
1810d8899132SKalle Valo 	u32 max_sp;
1811d8899132SKalle Valo 	u32 uapsd;
1812d8899132SKalle Valo 	int ret;
1813d8899132SKalle Valo 
1814d8899132SKalle Valo 	lockdep_assert_held(&ar->conf_mutex);
1815d8899132SKalle Valo 
1816d8899132SKalle Valo 	arg.vdev_id = arvif->vdev_id;
1817d8899132SKalle Valo 
1818d8899132SKalle Valo 	ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac uapsd_queues 0x%x max_sp %d\n",
1819d8899132SKalle Valo 		   sta->uapsd_queues, sta->max_sp);
1820d8899132SKalle Valo 
1821d8899132SKalle Valo 	uapsd = 0;
1822d8899132SKalle Valo 	if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO)
1823d8899132SKalle Valo 		uapsd |= WMI_AP_PS_UAPSD_AC3_DELIVERY_EN |
1824d8899132SKalle Valo 			 WMI_AP_PS_UAPSD_AC3_TRIGGER_EN;
1825d8899132SKalle Valo 	if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VI)
1826d8899132SKalle Valo 		uapsd |= WMI_AP_PS_UAPSD_AC2_DELIVERY_EN |
1827d8899132SKalle Valo 			 WMI_AP_PS_UAPSD_AC2_TRIGGER_EN;
1828d8899132SKalle Valo 	if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BK)
1829d8899132SKalle Valo 		uapsd |= WMI_AP_PS_UAPSD_AC1_DELIVERY_EN |
1830d8899132SKalle Valo 			 WMI_AP_PS_UAPSD_AC1_TRIGGER_EN;
1831d8899132SKalle Valo 	if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BE)
1832d8899132SKalle Valo 		uapsd |= WMI_AP_PS_UAPSD_AC0_DELIVERY_EN |
1833d8899132SKalle Valo 			 WMI_AP_PS_UAPSD_AC0_TRIGGER_EN;
1834d8899132SKalle Valo 
1835d8899132SKalle Valo 	max_sp = 0;
1836d8899132SKalle Valo 	if (sta->max_sp < MAX_WMI_AP_PS_PEER_PARAM_MAX_SP)
1837d8899132SKalle Valo 		max_sp = sta->max_sp;
1838d8899132SKalle Valo 
1839d8899132SKalle Valo 	arg.param = WMI_AP_PS_PEER_PARAM_UAPSD;
1840d8899132SKalle Valo 	arg.value = uapsd;
1841d8899132SKalle Valo 	ret = ath12k_wmi_send_set_ap_ps_param_cmd(ar, sta->addr, &arg);
1842d8899132SKalle Valo 	if (ret)
1843d8899132SKalle Valo 		goto err;
1844d8899132SKalle Valo 
1845d8899132SKalle Valo 	arg.param = WMI_AP_PS_PEER_PARAM_MAX_SP;
1846d8899132SKalle Valo 	arg.value = max_sp;
1847d8899132SKalle Valo 	ret = ath12k_wmi_send_set_ap_ps_param_cmd(ar, sta->addr, &arg);
1848d8899132SKalle Valo 	if (ret)
1849d8899132SKalle Valo 		goto err;
1850d8899132SKalle Valo 
1851d8899132SKalle Valo 	/* TODO: revisit during testing */
1852d8899132SKalle Valo 	arg.param = WMI_AP_PS_PEER_PARAM_SIFS_RESP_FRMTYPE;
1853d8899132SKalle Valo 	arg.value = DISABLE_SIFS_RESPONSE_TRIGGER;
1854d8899132SKalle Valo 	ret = ath12k_wmi_send_set_ap_ps_param_cmd(ar, sta->addr, &arg);
1855d8899132SKalle Valo 	if (ret)
1856d8899132SKalle Valo 		goto err;
1857d8899132SKalle Valo 
1858d8899132SKalle Valo 	arg.param = WMI_AP_PS_PEER_PARAM_SIFS_RESP_UAPSD;
1859d8899132SKalle Valo 	arg.value = DISABLE_SIFS_RESPONSE_TRIGGER;
1860d8899132SKalle Valo 	ret = ath12k_wmi_send_set_ap_ps_param_cmd(ar, sta->addr, &arg);
1861d8899132SKalle Valo 	if (ret)
1862d8899132SKalle Valo 		goto err;
1863d8899132SKalle Valo 
1864d8899132SKalle Valo 	return 0;
1865d8899132SKalle Valo 
1866d8899132SKalle Valo err:
1867d8899132SKalle Valo 	ath12k_warn(ar->ab, "failed to set ap ps peer param %d for vdev %i: %d\n",
1868d8899132SKalle Valo 		    arg.param, arvif->vdev_id, ret);
1869d8899132SKalle Valo 	return ret;
1870d8899132SKalle Valo }
1871d8899132SKalle Valo 
1872d8899132SKalle Valo static bool ath12k_mac_sta_has_ofdm_only(struct ieee80211_sta *sta)
1873d8899132SKalle Valo {
1874d8899132SKalle Valo 	return sta->deflink.supp_rates[NL80211_BAND_2GHZ] >>
1875d8899132SKalle Valo 	       ATH12K_MAC_FIRST_OFDM_RATE_IDX;
1876d8899132SKalle Valo }
1877d8899132SKalle Valo 
1878d8899132SKalle Valo static enum wmi_phy_mode ath12k_mac_get_phymode_vht(struct ath12k *ar,
1879d8899132SKalle Valo 						    struct ieee80211_sta *sta)
1880d8899132SKalle Valo {
1881d8899132SKalle Valo 	if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) {
1882d8899132SKalle Valo 		switch (sta->deflink.vht_cap.cap &
1883d8899132SKalle Valo 			IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) {
1884d8899132SKalle Valo 		case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ:
1885d8899132SKalle Valo 			return MODE_11AC_VHT160;
1886d8899132SKalle Valo 		case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ:
1887d8899132SKalle Valo 			return MODE_11AC_VHT80_80;
1888d8899132SKalle Valo 		default:
1889d8899132SKalle Valo 			/* not sure if this is a valid case? */
1890d8899132SKalle Valo 			return MODE_11AC_VHT160;
1891d8899132SKalle Valo 		}
1892d8899132SKalle Valo 	}
1893d8899132SKalle Valo 
1894d8899132SKalle Valo 	if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80)
1895d8899132SKalle Valo 		return MODE_11AC_VHT80;
1896d8899132SKalle Valo 
1897d8899132SKalle Valo 	if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
1898d8899132SKalle Valo 		return MODE_11AC_VHT40;
1899d8899132SKalle Valo 
1900d8899132SKalle Valo 	if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_20)
1901d8899132SKalle Valo 		return MODE_11AC_VHT20;
1902d8899132SKalle Valo 
1903d8899132SKalle Valo 	return MODE_UNKNOWN;
1904d8899132SKalle Valo }
1905d8899132SKalle Valo 
1906d8899132SKalle Valo static enum wmi_phy_mode ath12k_mac_get_phymode_he(struct ath12k *ar,
1907d8899132SKalle Valo 						   struct ieee80211_sta *sta)
1908d8899132SKalle Valo {
1909d8899132SKalle Valo 	if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) {
1910d8899132SKalle Valo 		if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[0] &
1911d8899132SKalle Valo 		     IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G)
1912d8899132SKalle Valo 			return MODE_11AX_HE160;
1913d8899132SKalle Valo 		else if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[0] &
1914d8899132SKalle Valo 		     IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)
1915d8899132SKalle Valo 			return MODE_11AX_HE80_80;
1916d8899132SKalle Valo 		/* not sure if this is a valid case? */
1917d8899132SKalle Valo 		return MODE_11AX_HE160;
1918d8899132SKalle Valo 	}
1919d8899132SKalle Valo 
1920d8899132SKalle Valo 	if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80)
1921d8899132SKalle Valo 		return MODE_11AX_HE80;
1922d8899132SKalle Valo 
1923d8899132SKalle Valo 	if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
1924d8899132SKalle Valo 		return MODE_11AX_HE40;
1925d8899132SKalle Valo 
1926d8899132SKalle Valo 	if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_20)
1927d8899132SKalle Valo 		return MODE_11AX_HE20;
1928d8899132SKalle Valo 
1929d8899132SKalle Valo 	return MODE_UNKNOWN;
1930d8899132SKalle Valo }
1931d8899132SKalle Valo 
1932d8899132SKalle Valo static void ath12k_peer_assoc_h_phymode(struct ath12k *ar,
1933d8899132SKalle Valo 					struct ieee80211_vif *vif,
1934d8899132SKalle Valo 					struct ieee80211_sta *sta,
1935d8899132SKalle Valo 					struct ath12k_wmi_peer_assoc_arg *arg)
1936d8899132SKalle Valo {
1937d8899132SKalle Valo 	struct ath12k_vif *arvif = (void *)vif->drv_priv;
1938d8899132SKalle Valo 	struct cfg80211_chan_def def;
1939d8899132SKalle Valo 	enum nl80211_band band;
1940d8899132SKalle Valo 	const u8 *ht_mcs_mask;
1941d8899132SKalle Valo 	const u16 *vht_mcs_mask;
1942d8899132SKalle Valo 	enum wmi_phy_mode phymode = MODE_UNKNOWN;
1943d8899132SKalle Valo 
1944d8899132SKalle Valo 	if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))
1945d8899132SKalle Valo 		return;
1946d8899132SKalle Valo 
1947d8899132SKalle Valo 	band = def.chan->band;
1948d8899132SKalle Valo 	ht_mcs_mask = arvif->bitrate_mask.control[band].ht_mcs;
1949d8899132SKalle Valo 	vht_mcs_mask = arvif->bitrate_mask.control[band].vht_mcs;
1950d8899132SKalle Valo 
1951d8899132SKalle Valo 	switch (band) {
1952d8899132SKalle Valo 	case NL80211_BAND_2GHZ:
1953d8899132SKalle Valo 		if (sta->deflink.he_cap.has_he) {
1954d8899132SKalle Valo 			if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80)
1955d8899132SKalle Valo 				phymode = MODE_11AX_HE80_2G;
1956d8899132SKalle Valo 			else if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
1957d8899132SKalle Valo 				phymode = MODE_11AX_HE40_2G;
1958d8899132SKalle Valo 			else
1959d8899132SKalle Valo 				phymode = MODE_11AX_HE20_2G;
1960d8899132SKalle Valo 		} else if (sta->deflink.vht_cap.vht_supported &&
1961d8899132SKalle Valo 		    !ath12k_peer_assoc_h_vht_masked(vht_mcs_mask)) {
1962d8899132SKalle Valo 			if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
1963d8899132SKalle Valo 				phymode = MODE_11AC_VHT40;
1964d8899132SKalle Valo 			else
1965d8899132SKalle Valo 				phymode = MODE_11AC_VHT20;
1966d8899132SKalle Valo 		} else if (sta->deflink.ht_cap.ht_supported &&
1967d8899132SKalle Valo 			   !ath12k_peer_assoc_h_ht_masked(ht_mcs_mask)) {
1968d8899132SKalle Valo 			if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
1969d8899132SKalle Valo 				phymode = MODE_11NG_HT40;
1970d8899132SKalle Valo 			else
1971d8899132SKalle Valo 				phymode = MODE_11NG_HT20;
1972d8899132SKalle Valo 		} else if (ath12k_mac_sta_has_ofdm_only(sta)) {
1973d8899132SKalle Valo 			phymode = MODE_11G;
1974d8899132SKalle Valo 		} else {
1975d8899132SKalle Valo 			phymode = MODE_11B;
1976d8899132SKalle Valo 		}
1977d8899132SKalle Valo 		break;
1978d8899132SKalle Valo 	case NL80211_BAND_5GHZ:
1979d8899132SKalle Valo 	case NL80211_BAND_6GHZ:
1980d8899132SKalle Valo 		/* Check HE first */
1981d8899132SKalle Valo 		if (sta->deflink.he_cap.has_he) {
1982d8899132SKalle Valo 			phymode = ath12k_mac_get_phymode_he(ar, sta);
1983d8899132SKalle Valo 		} else if (sta->deflink.vht_cap.vht_supported &&
1984d8899132SKalle Valo 		    !ath12k_peer_assoc_h_vht_masked(vht_mcs_mask)) {
1985d8899132SKalle Valo 			phymode = ath12k_mac_get_phymode_vht(ar, sta);
1986d8899132SKalle Valo 		} else if (sta->deflink.ht_cap.ht_supported &&
1987d8899132SKalle Valo 			   !ath12k_peer_assoc_h_ht_masked(ht_mcs_mask)) {
1988d8899132SKalle Valo 			if (sta->deflink.bandwidth >= IEEE80211_STA_RX_BW_40)
1989d8899132SKalle Valo 				phymode = MODE_11NA_HT40;
1990d8899132SKalle Valo 			else
1991d8899132SKalle Valo 				phymode = MODE_11NA_HT20;
1992d8899132SKalle Valo 		} else {
1993d8899132SKalle Valo 			phymode = MODE_11A;
1994d8899132SKalle Valo 		}
1995d8899132SKalle Valo 		break;
1996d8899132SKalle Valo 	default:
1997d8899132SKalle Valo 		break;
1998d8899132SKalle Valo 	}
1999d8899132SKalle Valo 
2000d8899132SKalle Valo 	ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac peer %pM phymode %s\n",
2001d8899132SKalle Valo 		   sta->addr, ath12k_mac_phymode_str(phymode));
2002d8899132SKalle Valo 
2003d8899132SKalle Valo 	arg->peer_phymode = phymode;
2004d8899132SKalle Valo 	WARN_ON(phymode == MODE_UNKNOWN);
2005d8899132SKalle Valo }
2006d8899132SKalle Valo 
2007d8899132SKalle Valo static void ath12k_peer_assoc_prepare(struct ath12k *ar,
2008d8899132SKalle Valo 				      struct ieee80211_vif *vif,
2009d8899132SKalle Valo 				      struct ieee80211_sta *sta,
2010d8899132SKalle Valo 				      struct ath12k_wmi_peer_assoc_arg *arg,
2011d8899132SKalle Valo 				      bool reassoc)
2012d8899132SKalle Valo {
2013d8899132SKalle Valo 	lockdep_assert_held(&ar->conf_mutex);
2014d8899132SKalle Valo 
2015d8899132SKalle Valo 	memset(arg, 0, sizeof(*arg));
2016d8899132SKalle Valo 
2017d8899132SKalle Valo 	reinit_completion(&ar->peer_assoc_done);
2018d8899132SKalle Valo 
2019d8899132SKalle Valo 	arg->peer_new_assoc = !reassoc;
2020d8899132SKalle Valo 	ath12k_peer_assoc_h_basic(ar, vif, sta, arg);
2021d8899132SKalle Valo 	ath12k_peer_assoc_h_crypto(ar, vif, sta, arg);
2022d8899132SKalle Valo 	ath12k_peer_assoc_h_rates(ar, vif, sta, arg);
2023d8899132SKalle Valo 	ath12k_peer_assoc_h_ht(ar, vif, sta, arg);
2024d8899132SKalle Valo 	ath12k_peer_assoc_h_vht(ar, vif, sta, arg);
2025d8899132SKalle Valo 	ath12k_peer_assoc_h_he(ar, vif, sta, arg);
2026d8899132SKalle Valo 	ath12k_peer_assoc_h_qos(ar, vif, sta, arg);
2027d8899132SKalle Valo 	ath12k_peer_assoc_h_phymode(ar, vif, sta, arg);
2028d8899132SKalle Valo 	ath12k_peer_assoc_h_smps(sta, arg);
2029d8899132SKalle Valo 
2030d8899132SKalle Valo 	/* TODO: amsdu_disable req? */
2031d8899132SKalle Valo }
2032d8899132SKalle Valo 
2033d8899132SKalle Valo static int ath12k_setup_peer_smps(struct ath12k *ar, struct ath12k_vif *arvif,
2034d8899132SKalle Valo 				  const u8 *addr,
2035d8899132SKalle Valo 				  const struct ieee80211_sta_ht_cap *ht_cap)
2036d8899132SKalle Valo {
2037d8899132SKalle Valo 	int smps;
2038d8899132SKalle Valo 
2039d8899132SKalle Valo 	if (!ht_cap->ht_supported)
2040d8899132SKalle Valo 		return 0;
2041d8899132SKalle Valo 
2042d8899132SKalle Valo 	smps = ht_cap->cap & IEEE80211_HT_CAP_SM_PS;
2043d8899132SKalle Valo 	smps >>= IEEE80211_HT_CAP_SM_PS_SHIFT;
2044d8899132SKalle Valo 
2045d8899132SKalle Valo 	if (smps >= ARRAY_SIZE(ath12k_smps_map))
2046d8899132SKalle Valo 		return -EINVAL;
2047d8899132SKalle Valo 
2048d8899132SKalle Valo 	return ath12k_wmi_set_peer_param(ar, addr, arvif->vdev_id,
2049d8899132SKalle Valo 					 WMI_PEER_MIMO_PS_STATE,
2050d8899132SKalle Valo 					 ath12k_smps_map[smps]);
2051d8899132SKalle Valo }
2052d8899132SKalle Valo 
2053d8899132SKalle Valo static void ath12k_bss_assoc(struct ieee80211_hw *hw,
2054d8899132SKalle Valo 			     struct ieee80211_vif *vif,
2055d8899132SKalle Valo 			     struct ieee80211_bss_conf *bss_conf)
2056d8899132SKalle Valo {
2057d8899132SKalle Valo 	struct ath12k *ar = hw->priv;
2058d8899132SKalle Valo 	struct ath12k_vif *arvif = (void *)vif->drv_priv;
2059d8899132SKalle Valo 	struct ath12k_wmi_peer_assoc_arg peer_arg;
2060d8899132SKalle Valo 	struct ieee80211_sta *ap_sta;
2061d8899132SKalle Valo 	struct ath12k_peer *peer;
2062d8899132SKalle Valo 	bool is_auth = false;
2063d8899132SKalle Valo 	int ret;
2064d8899132SKalle Valo 
2065d8899132SKalle Valo 	lockdep_assert_held(&ar->conf_mutex);
2066d8899132SKalle Valo 
2067d8899132SKalle Valo 	ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev %i assoc bssid %pM aid %d\n",
2068d8899132SKalle Valo 		   arvif->vdev_id, arvif->bssid, arvif->aid);
2069d8899132SKalle Valo 
2070d8899132SKalle Valo 	rcu_read_lock();
2071d8899132SKalle Valo 
2072d8899132SKalle Valo 	ap_sta = ieee80211_find_sta(vif, bss_conf->bssid);
2073d8899132SKalle Valo 	if (!ap_sta) {
2074d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to find station entry for bss %pM vdev %i\n",
2075d8899132SKalle Valo 			    bss_conf->bssid, arvif->vdev_id);
2076d8899132SKalle Valo 		rcu_read_unlock();
2077d8899132SKalle Valo 		return;
2078d8899132SKalle Valo 	}
2079d8899132SKalle Valo 
2080d8899132SKalle Valo 	ath12k_peer_assoc_prepare(ar, vif, ap_sta, &peer_arg, false);
2081d8899132SKalle Valo 
2082d8899132SKalle Valo 	rcu_read_unlock();
2083d8899132SKalle Valo 
2084d8899132SKalle Valo 	ret = ath12k_wmi_send_peer_assoc_cmd(ar, &peer_arg);
2085d8899132SKalle Valo 	if (ret) {
2086d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to run peer assoc for %pM vdev %i: %d\n",
2087d8899132SKalle Valo 			    bss_conf->bssid, arvif->vdev_id, ret);
2088d8899132SKalle Valo 		return;
2089d8899132SKalle Valo 	}
2090d8899132SKalle Valo 
2091d8899132SKalle Valo 	if (!wait_for_completion_timeout(&ar->peer_assoc_done, 1 * HZ)) {
2092d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to get peer assoc conf event for %pM vdev %i\n",
2093d8899132SKalle Valo 			    bss_conf->bssid, arvif->vdev_id);
2094d8899132SKalle Valo 		return;
2095d8899132SKalle Valo 	}
2096d8899132SKalle Valo 
2097d8899132SKalle Valo 	ret = ath12k_setup_peer_smps(ar, arvif, bss_conf->bssid,
2098d8899132SKalle Valo 				     &ap_sta->deflink.ht_cap);
2099d8899132SKalle Valo 	if (ret) {
2100d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to setup peer SMPS for vdev %d: %d\n",
2101d8899132SKalle Valo 			    arvif->vdev_id, ret);
2102d8899132SKalle Valo 		return;
2103d8899132SKalle Valo 	}
2104d8899132SKalle Valo 
2105d8899132SKalle Valo 	WARN_ON(arvif->is_up);
2106d8899132SKalle Valo 
2107d8899132SKalle Valo 	arvif->aid = vif->cfg.aid;
2108d8899132SKalle Valo 	ether_addr_copy(arvif->bssid, bss_conf->bssid);
2109d8899132SKalle Valo 
2110d8899132SKalle Valo 	ret = ath12k_wmi_vdev_up(ar, arvif->vdev_id, arvif->aid, arvif->bssid);
2111d8899132SKalle Valo 	if (ret) {
2112d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to set vdev %d up: %d\n",
2113d8899132SKalle Valo 			    arvif->vdev_id, ret);
2114d8899132SKalle Valo 		return;
2115d8899132SKalle Valo 	}
2116d8899132SKalle Valo 
2117d8899132SKalle Valo 	arvif->is_up = true;
2118d8899132SKalle Valo 
2119d8899132SKalle Valo 	ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
2120d8899132SKalle Valo 		   "mac vdev %d up (associated) bssid %pM aid %d\n",
2121d8899132SKalle Valo 		   arvif->vdev_id, bss_conf->bssid, vif->cfg.aid);
2122d8899132SKalle Valo 
2123d8899132SKalle Valo 	spin_lock_bh(&ar->ab->base_lock);
2124d8899132SKalle Valo 
2125d8899132SKalle Valo 	peer = ath12k_peer_find(ar->ab, arvif->vdev_id, arvif->bssid);
2126d8899132SKalle Valo 	if (peer && peer->is_authorized)
2127d8899132SKalle Valo 		is_auth = true;
2128d8899132SKalle Valo 
2129d8899132SKalle Valo 	spin_unlock_bh(&ar->ab->base_lock);
2130d8899132SKalle Valo 
2131d8899132SKalle Valo 	/* Authorize BSS Peer */
2132d8899132SKalle Valo 	if (is_auth) {
2133d8899132SKalle Valo 		ret = ath12k_wmi_set_peer_param(ar, arvif->bssid,
2134d8899132SKalle Valo 						arvif->vdev_id,
2135d8899132SKalle Valo 						WMI_PEER_AUTHORIZE,
2136d8899132SKalle Valo 						1);
2137d8899132SKalle Valo 		if (ret)
2138d8899132SKalle Valo 			ath12k_warn(ar->ab, "Unable to authorize BSS peer: %d\n", ret);
2139d8899132SKalle Valo 	}
2140d8899132SKalle Valo 
2141d8899132SKalle Valo 	ret = ath12k_wmi_send_obss_spr_cmd(ar, arvif->vdev_id,
2142d8899132SKalle Valo 					   &bss_conf->he_obss_pd);
2143d8899132SKalle Valo 	if (ret)
2144d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to set vdev %i OBSS PD parameters: %d\n",
2145d8899132SKalle Valo 			    arvif->vdev_id, ret);
2146d8899132SKalle Valo }
2147d8899132SKalle Valo 
2148d8899132SKalle Valo static void ath12k_bss_disassoc(struct ieee80211_hw *hw,
2149d8899132SKalle Valo 				struct ieee80211_vif *vif)
2150d8899132SKalle Valo {
2151d8899132SKalle Valo 	struct ath12k *ar = hw->priv;
2152d8899132SKalle Valo 	struct ath12k_vif *arvif = (void *)vif->drv_priv;
2153d8899132SKalle Valo 	int ret;
2154d8899132SKalle Valo 
2155d8899132SKalle Valo 	lockdep_assert_held(&ar->conf_mutex);
2156d8899132SKalle Valo 
2157d8899132SKalle Valo 	ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev %i disassoc bssid %pM\n",
2158d8899132SKalle Valo 		   arvif->vdev_id, arvif->bssid);
2159d8899132SKalle Valo 
2160d8899132SKalle Valo 	ret = ath12k_wmi_vdev_down(ar, arvif->vdev_id);
2161d8899132SKalle Valo 	if (ret)
2162d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to down vdev %i: %d\n",
2163d8899132SKalle Valo 			    arvif->vdev_id, ret);
2164d8899132SKalle Valo 
2165d8899132SKalle Valo 	arvif->is_up = false;
2166d8899132SKalle Valo 
2167d8899132SKalle Valo 	/* TODO: cancel connection_loss_work */
2168d8899132SKalle Valo }
2169d8899132SKalle Valo 
2170d8899132SKalle Valo static u32 ath12k_mac_get_rate_hw_value(int bitrate)
2171d8899132SKalle Valo {
2172d8899132SKalle Valo 	u32 preamble;
2173d8899132SKalle Valo 	u16 hw_value;
2174d8899132SKalle Valo 	int rate;
2175d8899132SKalle Valo 	size_t i;
2176d8899132SKalle Valo 
2177d8899132SKalle Valo 	if (ath12k_mac_bitrate_is_cck(bitrate))
2178d8899132SKalle Valo 		preamble = WMI_RATE_PREAMBLE_CCK;
2179d8899132SKalle Valo 	else
2180d8899132SKalle Valo 		preamble = WMI_RATE_PREAMBLE_OFDM;
2181d8899132SKalle Valo 
2182d8899132SKalle Valo 	for (i = 0; i < ARRAY_SIZE(ath12k_legacy_rates); i++) {
2183d8899132SKalle Valo 		if (ath12k_legacy_rates[i].bitrate != bitrate)
2184d8899132SKalle Valo 			continue;
2185d8899132SKalle Valo 
2186d8899132SKalle Valo 		hw_value = ath12k_legacy_rates[i].hw_value;
2187d8899132SKalle Valo 		rate = ATH12K_HW_RATE_CODE(hw_value, 0, preamble);
2188d8899132SKalle Valo 
2189d8899132SKalle Valo 		return rate;
2190d8899132SKalle Valo 	}
2191d8899132SKalle Valo 
2192d8899132SKalle Valo 	return -EINVAL;
2193d8899132SKalle Valo }
2194d8899132SKalle Valo 
2195d8899132SKalle Valo static void ath12k_recalculate_mgmt_rate(struct ath12k *ar,
2196d8899132SKalle Valo 					 struct ieee80211_vif *vif,
2197d8899132SKalle Valo 					 struct cfg80211_chan_def *def)
2198d8899132SKalle Valo {
2199d8899132SKalle Valo 	struct ath12k_vif *arvif = (void *)vif->drv_priv;
2200d8899132SKalle Valo 	const struct ieee80211_supported_band *sband;
2201d8899132SKalle Valo 	u8 basic_rate_idx;
2202d8899132SKalle Valo 	int hw_rate_code;
2203d8899132SKalle Valo 	u32 vdev_param;
2204d8899132SKalle Valo 	u16 bitrate;
2205d8899132SKalle Valo 	int ret;
2206d8899132SKalle Valo 
2207d8899132SKalle Valo 	lockdep_assert_held(&ar->conf_mutex);
2208d8899132SKalle Valo 
2209d8899132SKalle Valo 	sband = ar->hw->wiphy->bands[def->chan->band];
2210d8899132SKalle Valo 	basic_rate_idx = ffs(vif->bss_conf.basic_rates) - 1;
2211d8899132SKalle Valo 	bitrate = sband->bitrates[basic_rate_idx].bitrate;
2212d8899132SKalle Valo 
2213d8899132SKalle Valo 	hw_rate_code = ath12k_mac_get_rate_hw_value(bitrate);
2214d8899132SKalle Valo 	if (hw_rate_code < 0) {
2215d8899132SKalle Valo 		ath12k_warn(ar->ab, "bitrate not supported %d\n", bitrate);
2216d8899132SKalle Valo 		return;
2217d8899132SKalle Valo 	}
2218d8899132SKalle Valo 
2219d8899132SKalle Valo 	vdev_param = WMI_VDEV_PARAM_MGMT_RATE;
2220d8899132SKalle Valo 	ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, vdev_param,
2221d8899132SKalle Valo 					    hw_rate_code);
2222d8899132SKalle Valo 	if (ret)
2223d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to set mgmt tx rate %d\n", ret);
2224d8899132SKalle Valo 
2225d8899132SKalle Valo 	vdev_param = WMI_VDEV_PARAM_BEACON_RATE;
2226d8899132SKalle Valo 	ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, vdev_param,
2227d8899132SKalle Valo 					    hw_rate_code);
2228d8899132SKalle Valo 	if (ret)
2229d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to set beacon tx rate %d\n", ret);
2230d8899132SKalle Valo }
2231d8899132SKalle Valo 
2232d8899132SKalle Valo static int ath12k_mac_fils_discovery(struct ath12k_vif *arvif,
2233d8899132SKalle Valo 				     struct ieee80211_bss_conf *info)
2234d8899132SKalle Valo {
2235d8899132SKalle Valo 	struct ath12k *ar = arvif->ar;
2236d8899132SKalle Valo 	struct sk_buff *tmpl;
2237d8899132SKalle Valo 	int ret;
2238d8899132SKalle Valo 	u32 interval;
2239d8899132SKalle Valo 	bool unsol_bcast_probe_resp_enabled = false;
2240d8899132SKalle Valo 
2241d8899132SKalle Valo 	if (info->fils_discovery.max_interval) {
2242d8899132SKalle Valo 		interval = info->fils_discovery.max_interval;
2243d8899132SKalle Valo 
2244d8899132SKalle Valo 		tmpl = ieee80211_get_fils_discovery_tmpl(ar->hw, arvif->vif);
2245d8899132SKalle Valo 		if (tmpl)
2246d8899132SKalle Valo 			ret = ath12k_wmi_fils_discovery_tmpl(ar, arvif->vdev_id,
2247d8899132SKalle Valo 							     tmpl);
2248d8899132SKalle Valo 	} else if (info->unsol_bcast_probe_resp_interval) {
2249d8899132SKalle Valo 		unsol_bcast_probe_resp_enabled = 1;
2250d8899132SKalle Valo 		interval = info->unsol_bcast_probe_resp_interval;
2251d8899132SKalle Valo 
2252d8899132SKalle Valo 		tmpl = ieee80211_get_unsol_bcast_probe_resp_tmpl(ar->hw,
2253d8899132SKalle Valo 								 arvif->vif);
2254d8899132SKalle Valo 		if (tmpl)
2255d8899132SKalle Valo 			ret = ath12k_wmi_probe_resp_tmpl(ar, arvif->vdev_id,
2256d8899132SKalle Valo 							 tmpl);
2257d8899132SKalle Valo 	} else { /* Disable */
2258d8899132SKalle Valo 		return ath12k_wmi_fils_discovery(ar, arvif->vdev_id, 0, false);
2259d8899132SKalle Valo 	}
2260d8899132SKalle Valo 
2261d8899132SKalle Valo 	if (!tmpl) {
2262d8899132SKalle Valo 		ath12k_warn(ar->ab,
2263d8899132SKalle Valo 			    "mac vdev %i failed to retrieve %s template\n",
2264d8899132SKalle Valo 			    arvif->vdev_id, (unsol_bcast_probe_resp_enabled ?
2265d8899132SKalle Valo 			    "unsolicited broadcast probe response" :
2266d8899132SKalle Valo 			    "FILS discovery"));
2267d8899132SKalle Valo 		return -EPERM;
2268d8899132SKalle Valo 	}
2269d8899132SKalle Valo 	kfree_skb(tmpl);
2270d8899132SKalle Valo 
2271d8899132SKalle Valo 	if (!ret)
2272d8899132SKalle Valo 		ret = ath12k_wmi_fils_discovery(ar, arvif->vdev_id, interval,
2273d8899132SKalle Valo 						unsol_bcast_probe_resp_enabled);
2274d8899132SKalle Valo 
2275d8899132SKalle Valo 	return ret;
2276d8899132SKalle Valo }
2277d8899132SKalle Valo 
2278d8899132SKalle Valo static void ath12k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
2279d8899132SKalle Valo 					   struct ieee80211_vif *vif,
2280d8899132SKalle Valo 					   struct ieee80211_bss_conf *info,
2281d8899132SKalle Valo 					   u64 changed)
2282d8899132SKalle Valo {
2283d8899132SKalle Valo 	struct ath12k *ar = hw->priv;
2284d8899132SKalle Valo 	struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
2285d8899132SKalle Valo 	struct cfg80211_chan_def def;
2286d8899132SKalle Valo 	u32 param_id, param_value;
2287d8899132SKalle Valo 	enum nl80211_band band;
2288d8899132SKalle Valo 	u32 vdev_param;
2289d8899132SKalle Valo 	int mcast_rate;
2290d8899132SKalle Valo 	u32 preamble;
2291d8899132SKalle Valo 	u16 hw_value;
2292d8899132SKalle Valo 	u16 bitrate;
2293d8899132SKalle Valo 	int ret;
2294d8899132SKalle Valo 	u8 rateidx;
2295d8899132SKalle Valo 	u32 rate;
2296d8899132SKalle Valo 
2297d8899132SKalle Valo 	mutex_lock(&ar->conf_mutex);
2298d8899132SKalle Valo 
2299d8899132SKalle Valo 	if (changed & BSS_CHANGED_BEACON_INT) {
2300d8899132SKalle Valo 		arvif->beacon_interval = info->beacon_int;
2301d8899132SKalle Valo 
2302d8899132SKalle Valo 		param_id = WMI_VDEV_PARAM_BEACON_INTERVAL;
2303d8899132SKalle Valo 		ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
2304d8899132SKalle Valo 						    param_id,
2305d8899132SKalle Valo 						    arvif->beacon_interval);
2306d8899132SKalle Valo 		if (ret)
2307d8899132SKalle Valo 			ath12k_warn(ar->ab, "Failed to set beacon interval for VDEV: %d\n",
2308d8899132SKalle Valo 				    arvif->vdev_id);
2309d8899132SKalle Valo 		else
2310d8899132SKalle Valo 			ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
2311d8899132SKalle Valo 				   "Beacon interval: %d set for VDEV: %d\n",
2312d8899132SKalle Valo 				   arvif->beacon_interval, arvif->vdev_id);
2313d8899132SKalle Valo 	}
2314d8899132SKalle Valo 
2315d8899132SKalle Valo 	if (changed & BSS_CHANGED_BEACON) {
2316d8899132SKalle Valo 		param_id = WMI_PDEV_PARAM_BEACON_TX_MODE;
2317d8899132SKalle Valo 		param_value = WMI_BEACON_STAGGERED_MODE;
2318d8899132SKalle Valo 		ret = ath12k_wmi_pdev_set_param(ar, param_id,
2319d8899132SKalle Valo 						param_value, ar->pdev->pdev_id);
2320d8899132SKalle Valo 		if (ret)
2321d8899132SKalle Valo 			ath12k_warn(ar->ab, "Failed to set beacon mode for VDEV: %d\n",
2322d8899132SKalle Valo 				    arvif->vdev_id);
2323d8899132SKalle Valo 		else
2324d8899132SKalle Valo 			ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
2325d8899132SKalle Valo 				   "Set staggered beacon mode for VDEV: %d\n",
2326d8899132SKalle Valo 				   arvif->vdev_id);
2327d8899132SKalle Valo 
2328d8899132SKalle Valo 		ret = ath12k_mac_setup_bcn_tmpl(arvif);
2329d8899132SKalle Valo 		if (ret)
2330d8899132SKalle Valo 			ath12k_warn(ar->ab, "failed to update bcn template: %d\n",
2331d8899132SKalle Valo 				    ret);
2332d8899132SKalle Valo 	}
2333d8899132SKalle Valo 
2334d8899132SKalle Valo 	if (changed & (BSS_CHANGED_BEACON_INFO | BSS_CHANGED_BEACON)) {
2335d8899132SKalle Valo 		arvif->dtim_period = info->dtim_period;
2336d8899132SKalle Valo 
2337d8899132SKalle Valo 		param_id = WMI_VDEV_PARAM_DTIM_PERIOD;
2338d8899132SKalle Valo 		ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
2339d8899132SKalle Valo 						    param_id,
2340d8899132SKalle Valo 						    arvif->dtim_period);
2341d8899132SKalle Valo 
2342d8899132SKalle Valo 		if (ret)
2343d8899132SKalle Valo 			ath12k_warn(ar->ab, "Failed to set dtim period for VDEV %d: %i\n",
2344d8899132SKalle Valo 				    arvif->vdev_id, ret);
2345d8899132SKalle Valo 		else
2346d8899132SKalle Valo 			ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
2347d8899132SKalle Valo 				   "DTIM period: %d set for VDEV: %d\n",
2348d8899132SKalle Valo 				   arvif->dtim_period, arvif->vdev_id);
2349d8899132SKalle Valo 	}
2350d8899132SKalle Valo 
2351d8899132SKalle Valo 	if (changed & BSS_CHANGED_SSID &&
2352d8899132SKalle Valo 	    vif->type == NL80211_IFTYPE_AP) {
2353d8899132SKalle Valo 		arvif->u.ap.ssid_len = vif->cfg.ssid_len;
2354d8899132SKalle Valo 		if (vif->cfg.ssid_len)
2355d8899132SKalle Valo 			memcpy(arvif->u.ap.ssid, vif->cfg.ssid, vif->cfg.ssid_len);
2356d8899132SKalle Valo 		arvif->u.ap.hidden_ssid = info->hidden_ssid;
2357d8899132SKalle Valo 	}
2358d8899132SKalle Valo 
2359d8899132SKalle Valo 	if (changed & BSS_CHANGED_BSSID && !is_zero_ether_addr(info->bssid))
2360d8899132SKalle Valo 		ether_addr_copy(arvif->bssid, info->bssid);
2361d8899132SKalle Valo 
2362d8899132SKalle Valo 	if (changed & BSS_CHANGED_BEACON_ENABLED) {
2363d8899132SKalle Valo 		ath12k_control_beaconing(arvif, info);
2364d8899132SKalle Valo 
2365d8899132SKalle Valo 		if (arvif->is_up && vif->bss_conf.he_support &&
2366d8899132SKalle Valo 		    vif->bss_conf.he_oper.params) {
2367d8899132SKalle Valo 			/* TODO: Extend to support 1024 BA Bitmap size */
2368d8899132SKalle Valo 			ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
2369d8899132SKalle Valo 							    WMI_VDEV_PARAM_BA_MODE,
2370d8899132SKalle Valo 							    WMI_BA_MODE_BUFFER_SIZE_256);
2371d8899132SKalle Valo 			if (ret)
2372d8899132SKalle Valo 				ath12k_warn(ar->ab,
2373d8899132SKalle Valo 					    "failed to set BA BUFFER SIZE 256 for vdev: %d\n",
2374d8899132SKalle Valo 					    arvif->vdev_id);
2375d8899132SKalle Valo 
2376d8899132SKalle Valo 			param_id = WMI_VDEV_PARAM_HEOPS_0_31;
2377d8899132SKalle Valo 			param_value = vif->bss_conf.he_oper.params;
2378d8899132SKalle Valo 			ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
2379d8899132SKalle Valo 							    param_id, param_value);
2380d8899132SKalle Valo 			ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
2381d8899132SKalle Valo 				   "he oper param: %x set for VDEV: %d\n",
2382d8899132SKalle Valo 				   param_value, arvif->vdev_id);
2383d8899132SKalle Valo 
2384d8899132SKalle Valo 			if (ret)
2385d8899132SKalle Valo 				ath12k_warn(ar->ab, "Failed to set he oper params %x for VDEV %d: %i\n",
2386d8899132SKalle Valo 					    param_value, arvif->vdev_id, ret);
2387d8899132SKalle Valo 		}
2388d8899132SKalle Valo 	}
2389d8899132SKalle Valo 
2390d8899132SKalle Valo 	if (changed & BSS_CHANGED_ERP_CTS_PROT) {
2391d8899132SKalle Valo 		u32 cts_prot;
2392d8899132SKalle Valo 
2393d8899132SKalle Valo 		cts_prot = !!(info->use_cts_prot);
2394d8899132SKalle Valo 		param_id = WMI_VDEV_PARAM_PROTECTION_MODE;
2395d8899132SKalle Valo 
2396d8899132SKalle Valo 		if (arvif->is_started) {
2397d8899132SKalle Valo 			ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
2398d8899132SKalle Valo 							    param_id, cts_prot);
2399d8899132SKalle Valo 			if (ret)
2400d8899132SKalle Valo 				ath12k_warn(ar->ab, "Failed to set CTS prot for VDEV: %d\n",
2401d8899132SKalle Valo 					    arvif->vdev_id);
2402d8899132SKalle Valo 			else
2403d8899132SKalle Valo 				ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "Set CTS prot: %d for VDEV: %d\n",
2404d8899132SKalle Valo 					   cts_prot, arvif->vdev_id);
2405d8899132SKalle Valo 		} else {
2406d8899132SKalle Valo 			ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "defer protection mode setup, vdev is not ready yet\n");
2407d8899132SKalle Valo 		}
2408d8899132SKalle Valo 	}
2409d8899132SKalle Valo 
2410d8899132SKalle Valo 	if (changed & BSS_CHANGED_ERP_SLOT) {
2411d8899132SKalle Valo 		u32 slottime;
2412d8899132SKalle Valo 
2413d8899132SKalle Valo 		if (info->use_short_slot)
2414d8899132SKalle Valo 			slottime = WMI_VDEV_SLOT_TIME_SHORT; /* 9us */
2415d8899132SKalle Valo 
2416d8899132SKalle Valo 		else
2417d8899132SKalle Valo 			slottime = WMI_VDEV_SLOT_TIME_LONG; /* 20us */
2418d8899132SKalle Valo 
2419d8899132SKalle Valo 		param_id = WMI_VDEV_PARAM_SLOT_TIME;
2420d8899132SKalle Valo 		ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
2421d8899132SKalle Valo 						    param_id, slottime);
2422d8899132SKalle Valo 		if (ret)
2423d8899132SKalle Valo 			ath12k_warn(ar->ab, "Failed to set erp slot for VDEV: %d\n",
2424d8899132SKalle Valo 				    arvif->vdev_id);
2425d8899132SKalle Valo 		else
2426d8899132SKalle Valo 			ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
2427d8899132SKalle Valo 				   "Set slottime: %d for VDEV: %d\n",
2428d8899132SKalle Valo 				   slottime, arvif->vdev_id);
2429d8899132SKalle Valo 	}
2430d8899132SKalle Valo 
2431d8899132SKalle Valo 	if (changed & BSS_CHANGED_ERP_PREAMBLE) {
2432d8899132SKalle Valo 		u32 preamble;
2433d8899132SKalle Valo 
2434d8899132SKalle Valo 		if (info->use_short_preamble)
2435d8899132SKalle Valo 			preamble = WMI_VDEV_PREAMBLE_SHORT;
2436d8899132SKalle Valo 		else
2437d8899132SKalle Valo 			preamble = WMI_VDEV_PREAMBLE_LONG;
2438d8899132SKalle Valo 
2439d8899132SKalle Valo 		param_id = WMI_VDEV_PARAM_PREAMBLE;
2440d8899132SKalle Valo 		ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
2441d8899132SKalle Valo 						    param_id, preamble);
2442d8899132SKalle Valo 		if (ret)
2443d8899132SKalle Valo 			ath12k_warn(ar->ab, "Failed to set preamble for VDEV: %d\n",
2444d8899132SKalle Valo 				    arvif->vdev_id);
2445d8899132SKalle Valo 		else
2446d8899132SKalle Valo 			ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
2447d8899132SKalle Valo 				   "Set preamble: %d for VDEV: %d\n",
2448d8899132SKalle Valo 				   preamble, arvif->vdev_id);
2449d8899132SKalle Valo 	}
2450d8899132SKalle Valo 
2451d8899132SKalle Valo 	if (changed & BSS_CHANGED_ASSOC) {
2452d8899132SKalle Valo 		if (vif->cfg.assoc)
2453d8899132SKalle Valo 			ath12k_bss_assoc(hw, vif, info);
2454d8899132SKalle Valo 		else
2455d8899132SKalle Valo 			ath12k_bss_disassoc(hw, vif);
2456d8899132SKalle Valo 	}
2457d8899132SKalle Valo 
2458d8899132SKalle Valo 	if (changed & BSS_CHANGED_TXPOWER) {
2459d8899132SKalle Valo 		ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev_id %i txpower %d\n",
2460d8899132SKalle Valo 			   arvif->vdev_id, info->txpower);
2461d8899132SKalle Valo 
2462d8899132SKalle Valo 		arvif->txpower = info->txpower;
2463d8899132SKalle Valo 		ath12k_mac_txpower_recalc(ar);
2464d8899132SKalle Valo 	}
2465d8899132SKalle Valo 
2466d8899132SKalle Valo 	if (changed & BSS_CHANGED_MCAST_RATE &&
2467d8899132SKalle Valo 	    !ath12k_mac_vif_chan(arvif->vif, &def)) {
2468d8899132SKalle Valo 		band = def.chan->band;
2469d8899132SKalle Valo 		mcast_rate = vif->bss_conf.mcast_rate[band];
2470d8899132SKalle Valo 
2471d8899132SKalle Valo 		if (mcast_rate > 0)
2472d8899132SKalle Valo 			rateidx = mcast_rate - 1;
2473d8899132SKalle Valo 		else
2474d8899132SKalle Valo 			rateidx = ffs(vif->bss_conf.basic_rates) - 1;
2475d8899132SKalle Valo 
2476d8899132SKalle Valo 		if (ar->pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP)
2477d8899132SKalle Valo 			rateidx += ATH12K_MAC_FIRST_OFDM_RATE_IDX;
2478d8899132SKalle Valo 
2479d8899132SKalle Valo 		bitrate = ath12k_legacy_rates[rateidx].bitrate;
2480d8899132SKalle Valo 		hw_value = ath12k_legacy_rates[rateidx].hw_value;
2481d8899132SKalle Valo 
2482d8899132SKalle Valo 		if (ath12k_mac_bitrate_is_cck(bitrate))
2483d8899132SKalle Valo 			preamble = WMI_RATE_PREAMBLE_CCK;
2484d8899132SKalle Valo 		else
2485d8899132SKalle Valo 			preamble = WMI_RATE_PREAMBLE_OFDM;
2486d8899132SKalle Valo 
2487d8899132SKalle Valo 		rate = ATH12K_HW_RATE_CODE(hw_value, 0, preamble);
2488d8899132SKalle Valo 
2489d8899132SKalle Valo 		ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
2490d8899132SKalle Valo 			   "mac vdev %d mcast_rate %x\n",
2491d8899132SKalle Valo 			   arvif->vdev_id, rate);
2492d8899132SKalle Valo 
2493d8899132SKalle Valo 		vdev_param = WMI_VDEV_PARAM_MCAST_DATA_RATE;
2494d8899132SKalle Valo 		ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
2495d8899132SKalle Valo 						    vdev_param, rate);
2496d8899132SKalle Valo 		if (ret)
2497d8899132SKalle Valo 			ath12k_warn(ar->ab,
2498d8899132SKalle Valo 				    "failed to set mcast rate on vdev %i: %d\n",
2499d8899132SKalle Valo 				    arvif->vdev_id,  ret);
2500d8899132SKalle Valo 
2501d8899132SKalle Valo 		vdev_param = WMI_VDEV_PARAM_BCAST_DATA_RATE;
2502d8899132SKalle Valo 		ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
2503d8899132SKalle Valo 						    vdev_param, rate);
2504d8899132SKalle Valo 		if (ret)
2505d8899132SKalle Valo 			ath12k_warn(ar->ab,
2506d8899132SKalle Valo 				    "failed to set bcast rate on vdev %i: %d\n",
2507d8899132SKalle Valo 				    arvif->vdev_id,  ret);
2508d8899132SKalle Valo 	}
2509d8899132SKalle Valo 
2510d8899132SKalle Valo 	if (changed & BSS_CHANGED_BASIC_RATES &&
2511d8899132SKalle Valo 	    !ath12k_mac_vif_chan(arvif->vif, &def))
2512d8899132SKalle Valo 		ath12k_recalculate_mgmt_rate(ar, vif, &def);
2513d8899132SKalle Valo 
2514d8899132SKalle Valo 	if (changed & BSS_CHANGED_TWT) {
2515d8899132SKalle Valo 		if (info->twt_requester || info->twt_responder)
2516d8899132SKalle Valo 			ath12k_wmi_send_twt_enable_cmd(ar, ar->pdev->pdev_id);
2517d8899132SKalle Valo 		else
2518d8899132SKalle Valo 			ath12k_wmi_send_twt_disable_cmd(ar, ar->pdev->pdev_id);
2519d8899132SKalle Valo 	}
2520d8899132SKalle Valo 
2521d8899132SKalle Valo 	if (changed & BSS_CHANGED_HE_OBSS_PD)
2522d8899132SKalle Valo 		ath12k_wmi_send_obss_spr_cmd(ar, arvif->vdev_id,
2523d8899132SKalle Valo 					     &info->he_obss_pd);
2524d8899132SKalle Valo 
2525d8899132SKalle Valo 	if (changed & BSS_CHANGED_HE_BSS_COLOR) {
2526d8899132SKalle Valo 		if (vif->type == NL80211_IFTYPE_AP) {
2527d8899132SKalle Valo 			ret = ath12k_wmi_obss_color_cfg_cmd(ar,
2528d8899132SKalle Valo 							    arvif->vdev_id,
2529d8899132SKalle Valo 							    info->he_bss_color.color,
2530d8899132SKalle Valo 							    ATH12K_BSS_COLOR_AP_PERIODS,
2531d8899132SKalle Valo 							    info->he_bss_color.enabled);
2532d8899132SKalle Valo 			if (ret)
2533d8899132SKalle Valo 				ath12k_warn(ar->ab, "failed to set bss color collision on vdev %i: %d\n",
2534d8899132SKalle Valo 					    arvif->vdev_id,  ret);
2535d8899132SKalle Valo 		} else if (vif->type == NL80211_IFTYPE_STATION) {
2536d8899132SKalle Valo 			ret = ath12k_wmi_send_bss_color_change_enable_cmd(ar,
2537d8899132SKalle Valo 									  arvif->vdev_id,
2538d8899132SKalle Valo 									  1);
2539d8899132SKalle Valo 			if (ret)
2540d8899132SKalle Valo 				ath12k_warn(ar->ab, "failed to enable bss color change on vdev %i: %d\n",
2541d8899132SKalle Valo 					    arvif->vdev_id,  ret);
2542d8899132SKalle Valo 			ret = ath12k_wmi_obss_color_cfg_cmd(ar,
2543d8899132SKalle Valo 							    arvif->vdev_id,
2544d8899132SKalle Valo 							    0,
2545d8899132SKalle Valo 							    ATH12K_BSS_COLOR_STA_PERIODS,
2546d8899132SKalle Valo 							    1);
2547d8899132SKalle Valo 			if (ret)
2548d8899132SKalle Valo 				ath12k_warn(ar->ab, "failed to set bss color collision on vdev %i: %d\n",
2549d8899132SKalle Valo 					    arvif->vdev_id,  ret);
2550d8899132SKalle Valo 		}
2551d8899132SKalle Valo 	}
2552d8899132SKalle Valo 
2553d8899132SKalle Valo 	if (changed & BSS_CHANGED_FILS_DISCOVERY ||
2554d8899132SKalle Valo 	    changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP)
2555d8899132SKalle Valo 		ath12k_mac_fils_discovery(arvif, info);
2556d8899132SKalle Valo 
2557d8899132SKalle Valo 	mutex_unlock(&ar->conf_mutex);
2558d8899132SKalle Valo }
2559d8899132SKalle Valo 
2560d8899132SKalle Valo void __ath12k_mac_scan_finish(struct ath12k *ar)
2561d8899132SKalle Valo {
2562d8899132SKalle Valo 	lockdep_assert_held(&ar->data_lock);
2563d8899132SKalle Valo 
2564d8899132SKalle Valo 	switch (ar->scan.state) {
2565d8899132SKalle Valo 	case ATH12K_SCAN_IDLE:
2566d8899132SKalle Valo 		break;
2567d8899132SKalle Valo 	case ATH12K_SCAN_RUNNING:
2568d8899132SKalle Valo 	case ATH12K_SCAN_ABORTING:
2569d8899132SKalle Valo 		if (!ar->scan.is_roc) {
2570d8899132SKalle Valo 			struct cfg80211_scan_info info = {
2571d8899132SKalle Valo 				.aborted = (ar->scan.state ==
2572d8899132SKalle Valo 					    ATH12K_SCAN_ABORTING),
2573d8899132SKalle Valo 			};
2574d8899132SKalle Valo 
2575d8899132SKalle Valo 			ieee80211_scan_completed(ar->hw, &info);
2576d8899132SKalle Valo 		} else if (ar->scan.roc_notify) {
2577d8899132SKalle Valo 			ieee80211_remain_on_channel_expired(ar->hw);
2578d8899132SKalle Valo 		}
2579d8899132SKalle Valo 		fallthrough;
2580d8899132SKalle Valo 	case ATH12K_SCAN_STARTING:
2581d8899132SKalle Valo 		ar->scan.state = ATH12K_SCAN_IDLE;
2582d8899132SKalle Valo 		ar->scan_channel = NULL;
2583d8899132SKalle Valo 		ar->scan.roc_freq = 0;
2584d8899132SKalle Valo 		cancel_delayed_work(&ar->scan.timeout);
2585d8899132SKalle Valo 		complete(&ar->scan.completed);
2586d8899132SKalle Valo 		break;
2587d8899132SKalle Valo 	}
2588d8899132SKalle Valo }
2589d8899132SKalle Valo 
2590d8899132SKalle Valo void ath12k_mac_scan_finish(struct ath12k *ar)
2591d8899132SKalle Valo {
2592d8899132SKalle Valo 	spin_lock_bh(&ar->data_lock);
2593d8899132SKalle Valo 	__ath12k_mac_scan_finish(ar);
2594d8899132SKalle Valo 	spin_unlock_bh(&ar->data_lock);
2595d8899132SKalle Valo }
2596d8899132SKalle Valo 
2597d8899132SKalle Valo static int ath12k_scan_stop(struct ath12k *ar)
2598d8899132SKalle Valo {
2599d8899132SKalle Valo 	struct ath12k_wmi_scan_cancel_arg arg = {
2600d8899132SKalle Valo 		.req_type = WLAN_SCAN_CANCEL_SINGLE,
2601d8899132SKalle Valo 		.scan_id = ATH12K_SCAN_ID,
2602d8899132SKalle Valo 	};
2603d8899132SKalle Valo 	int ret;
2604d8899132SKalle Valo 
2605d8899132SKalle Valo 	lockdep_assert_held(&ar->conf_mutex);
2606d8899132SKalle Valo 
2607d8899132SKalle Valo 	/* TODO: Fill other STOP Params */
2608d8899132SKalle Valo 	arg.pdev_id = ar->pdev->pdev_id;
2609d8899132SKalle Valo 
2610d8899132SKalle Valo 	ret = ath12k_wmi_send_scan_stop_cmd(ar, &arg);
2611d8899132SKalle Valo 	if (ret) {
2612d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to stop wmi scan: %d\n", ret);
2613d8899132SKalle Valo 		goto out;
2614d8899132SKalle Valo 	}
2615d8899132SKalle Valo 
2616d8899132SKalle Valo 	ret = wait_for_completion_timeout(&ar->scan.completed, 3 * HZ);
2617d8899132SKalle Valo 	if (ret == 0) {
2618d8899132SKalle Valo 		ath12k_warn(ar->ab,
2619d8899132SKalle Valo 			    "failed to receive scan abort comple: timed out\n");
2620d8899132SKalle Valo 		ret = -ETIMEDOUT;
2621d8899132SKalle Valo 	} else if (ret > 0) {
2622d8899132SKalle Valo 		ret = 0;
2623d8899132SKalle Valo 	}
2624d8899132SKalle Valo 
2625d8899132SKalle Valo out:
2626d8899132SKalle Valo 	/* Scan state should be updated upon scan completion but in case
2627d8899132SKalle Valo 	 * firmware fails to deliver the event (for whatever reason) it is
2628d8899132SKalle Valo 	 * desired to clean up scan state anyway. Firmware may have just
2629d8899132SKalle Valo 	 * dropped the scan completion event delivery due to transport pipe
2630d8899132SKalle Valo 	 * being overflown with data and/or it can recover on its own before
2631d8899132SKalle Valo 	 * next scan request is submitted.
2632d8899132SKalle Valo 	 */
2633d8899132SKalle Valo 	spin_lock_bh(&ar->data_lock);
2634d8899132SKalle Valo 	if (ar->scan.state != ATH12K_SCAN_IDLE)
2635d8899132SKalle Valo 		__ath12k_mac_scan_finish(ar);
2636d8899132SKalle Valo 	spin_unlock_bh(&ar->data_lock);
2637d8899132SKalle Valo 
2638d8899132SKalle Valo 	return ret;
2639d8899132SKalle Valo }
2640d8899132SKalle Valo 
2641d8899132SKalle Valo static void ath12k_scan_abort(struct ath12k *ar)
2642d8899132SKalle Valo {
2643d8899132SKalle Valo 	int ret;
2644d8899132SKalle Valo 
2645d8899132SKalle Valo 	lockdep_assert_held(&ar->conf_mutex);
2646d8899132SKalle Valo 
2647d8899132SKalle Valo 	spin_lock_bh(&ar->data_lock);
2648d8899132SKalle Valo 
2649d8899132SKalle Valo 	switch (ar->scan.state) {
2650d8899132SKalle Valo 	case ATH12K_SCAN_IDLE:
2651d8899132SKalle Valo 		/* This can happen if timeout worker kicked in and called
2652d8899132SKalle Valo 		 * abortion while scan completion was being processed.
2653d8899132SKalle Valo 		 */
2654d8899132SKalle Valo 		break;
2655d8899132SKalle Valo 	case ATH12K_SCAN_STARTING:
2656d8899132SKalle Valo 	case ATH12K_SCAN_ABORTING:
2657d8899132SKalle Valo 		ath12k_warn(ar->ab, "refusing scan abortion due to invalid scan state: %d\n",
2658d8899132SKalle Valo 			    ar->scan.state);
2659d8899132SKalle Valo 		break;
2660d8899132SKalle Valo 	case ATH12K_SCAN_RUNNING:
2661d8899132SKalle Valo 		ar->scan.state = ATH12K_SCAN_ABORTING;
2662d8899132SKalle Valo 		spin_unlock_bh(&ar->data_lock);
2663d8899132SKalle Valo 
2664d8899132SKalle Valo 		ret = ath12k_scan_stop(ar);
2665d8899132SKalle Valo 		if (ret)
2666d8899132SKalle Valo 			ath12k_warn(ar->ab, "failed to abort scan: %d\n", ret);
2667d8899132SKalle Valo 
2668d8899132SKalle Valo 		spin_lock_bh(&ar->data_lock);
2669d8899132SKalle Valo 		break;
2670d8899132SKalle Valo 	}
2671d8899132SKalle Valo 
2672d8899132SKalle Valo 	spin_unlock_bh(&ar->data_lock);
2673d8899132SKalle Valo }
2674d8899132SKalle Valo 
2675d8899132SKalle Valo static void ath12k_scan_timeout_work(struct work_struct *work)
2676d8899132SKalle Valo {
2677d8899132SKalle Valo 	struct ath12k *ar = container_of(work, struct ath12k,
2678d8899132SKalle Valo 					 scan.timeout.work);
2679d8899132SKalle Valo 
2680d8899132SKalle Valo 	mutex_lock(&ar->conf_mutex);
2681d8899132SKalle Valo 	ath12k_scan_abort(ar);
2682d8899132SKalle Valo 	mutex_unlock(&ar->conf_mutex);
2683d8899132SKalle Valo }
2684d8899132SKalle Valo 
2685d8899132SKalle Valo static int ath12k_start_scan(struct ath12k *ar,
2686d8899132SKalle Valo 			     struct ath12k_wmi_scan_req_arg *arg)
2687d8899132SKalle Valo {
2688d8899132SKalle Valo 	int ret;
2689d8899132SKalle Valo 
2690d8899132SKalle Valo 	lockdep_assert_held(&ar->conf_mutex);
2691d8899132SKalle Valo 
2692d8899132SKalle Valo 	ret = ath12k_wmi_send_scan_start_cmd(ar, arg);
2693d8899132SKalle Valo 	if (ret)
2694d8899132SKalle Valo 		return ret;
2695d8899132SKalle Valo 
2696d8899132SKalle Valo 	ret = wait_for_completion_timeout(&ar->scan.started, 1 * HZ);
2697d8899132SKalle Valo 	if (ret == 0) {
2698d8899132SKalle Valo 		ret = ath12k_scan_stop(ar);
2699d8899132SKalle Valo 		if (ret)
2700d8899132SKalle Valo 			ath12k_warn(ar->ab, "failed to stop scan: %d\n", ret);
2701d8899132SKalle Valo 
2702d8899132SKalle Valo 		return -ETIMEDOUT;
2703d8899132SKalle Valo 	}
2704d8899132SKalle Valo 
2705d8899132SKalle Valo 	/* If we failed to start the scan, return error code at
2706d8899132SKalle Valo 	 * this point.  This is probably due to some issue in the
2707d8899132SKalle Valo 	 * firmware, but no need to wedge the driver due to that...
2708d8899132SKalle Valo 	 */
2709d8899132SKalle Valo 	spin_lock_bh(&ar->data_lock);
2710d8899132SKalle Valo 	if (ar->scan.state == ATH12K_SCAN_IDLE) {
2711d8899132SKalle Valo 		spin_unlock_bh(&ar->data_lock);
2712d8899132SKalle Valo 		return -EINVAL;
2713d8899132SKalle Valo 	}
2714d8899132SKalle Valo 	spin_unlock_bh(&ar->data_lock);
2715d8899132SKalle Valo 
2716d8899132SKalle Valo 	return 0;
2717d8899132SKalle Valo }
2718d8899132SKalle Valo 
2719d8899132SKalle Valo static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
2720d8899132SKalle Valo 				 struct ieee80211_vif *vif,
2721d8899132SKalle Valo 				 struct ieee80211_scan_request *hw_req)
2722d8899132SKalle Valo {
2723d8899132SKalle Valo 	struct ath12k *ar = hw->priv;
2724d8899132SKalle Valo 	struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
2725d8899132SKalle Valo 	struct cfg80211_scan_request *req = &hw_req->req;
2726d8899132SKalle Valo 	struct ath12k_wmi_scan_req_arg arg = {};
2727d8899132SKalle Valo 	int ret;
2728d8899132SKalle Valo 	int i;
2729d8899132SKalle Valo 
2730d8899132SKalle Valo 	mutex_lock(&ar->conf_mutex);
2731d8899132SKalle Valo 
2732d8899132SKalle Valo 	spin_lock_bh(&ar->data_lock);
2733d8899132SKalle Valo 	switch (ar->scan.state) {
2734d8899132SKalle Valo 	case ATH12K_SCAN_IDLE:
2735d8899132SKalle Valo 		reinit_completion(&ar->scan.started);
2736d8899132SKalle Valo 		reinit_completion(&ar->scan.completed);
2737d8899132SKalle Valo 		ar->scan.state = ATH12K_SCAN_STARTING;
2738d8899132SKalle Valo 		ar->scan.is_roc = false;
2739d8899132SKalle Valo 		ar->scan.vdev_id = arvif->vdev_id;
2740d8899132SKalle Valo 		ret = 0;
2741d8899132SKalle Valo 		break;
2742d8899132SKalle Valo 	case ATH12K_SCAN_STARTING:
2743d8899132SKalle Valo 	case ATH12K_SCAN_RUNNING:
2744d8899132SKalle Valo 	case ATH12K_SCAN_ABORTING:
2745d8899132SKalle Valo 		ret = -EBUSY;
2746d8899132SKalle Valo 		break;
2747d8899132SKalle Valo 	}
2748d8899132SKalle Valo 	spin_unlock_bh(&ar->data_lock);
2749d8899132SKalle Valo 
2750d8899132SKalle Valo 	if (ret)
2751d8899132SKalle Valo 		goto exit;
2752d8899132SKalle Valo 
2753d8899132SKalle Valo 	ath12k_wmi_start_scan_init(ar, &arg);
2754d8899132SKalle Valo 	arg.vdev_id = arvif->vdev_id;
2755d8899132SKalle Valo 	arg.scan_id = ATH12K_SCAN_ID;
2756d8899132SKalle Valo 
2757d8899132SKalle Valo 	if (req->ie_len) {
27588ad314daSWen Gong 		arg.extraie.ptr = kmemdup(req->ie, req->ie_len, GFP_KERNEL);
27598ad314daSWen Gong 		if (!arg.extraie.ptr) {
27608ad314daSWen Gong 			ret = -ENOMEM;
27618ad314daSWen Gong 			goto exit;
27628ad314daSWen Gong 		}
2763d8899132SKalle Valo 		arg.extraie.len = req->ie_len;
2764d8899132SKalle Valo 	}
2765d8899132SKalle Valo 
2766d8899132SKalle Valo 	if (req->n_ssids) {
2767d8899132SKalle Valo 		arg.num_ssids = req->n_ssids;
2768d8899132SKalle Valo 		for (i = 0; i < arg.num_ssids; i++)
2769d8899132SKalle Valo 			arg.ssid[i] = req->ssids[i];
2770d8899132SKalle Valo 	} else {
2771d8899132SKalle Valo 		arg.scan_flags |= WMI_SCAN_FLAG_PASSIVE;
2772d8899132SKalle Valo 	}
2773d8899132SKalle Valo 
2774d8899132SKalle Valo 	if (req->n_channels) {
2775d8899132SKalle Valo 		arg.num_chan = req->n_channels;
2776d8899132SKalle Valo 		for (i = 0; i < arg.num_chan; i++)
2777d8899132SKalle Valo 			arg.chan_list[i] = req->channels[i]->center_freq;
2778d8899132SKalle Valo 	}
2779d8899132SKalle Valo 
2780d8899132SKalle Valo 	ret = ath12k_start_scan(ar, &arg);
2781d8899132SKalle Valo 	if (ret) {
2782d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to start hw scan: %d\n", ret);
2783d8899132SKalle Valo 		spin_lock_bh(&ar->data_lock);
2784d8899132SKalle Valo 		ar->scan.state = ATH12K_SCAN_IDLE;
2785d8899132SKalle Valo 		spin_unlock_bh(&ar->data_lock);
2786d8899132SKalle Valo 	}
2787d8899132SKalle Valo 
2788d8899132SKalle Valo 	/* Add a margin to account for event/command processing */
2789d8899132SKalle Valo 	ieee80211_queue_delayed_work(ar->hw, &ar->scan.timeout,
2790d8899132SKalle Valo 				     msecs_to_jiffies(arg.max_scan_time +
2791d8899132SKalle Valo 						      ATH12K_MAC_SCAN_TIMEOUT_MSECS));
2792d8899132SKalle Valo 
2793d8899132SKalle Valo exit:
2794d8899132SKalle Valo 	if (req->ie_len)
2795d8899132SKalle Valo 		kfree(arg.extraie.ptr);
2796d8899132SKalle Valo 
2797d8899132SKalle Valo 	mutex_unlock(&ar->conf_mutex);
2798d8899132SKalle Valo 	return ret;
2799d8899132SKalle Valo }
2800d8899132SKalle Valo 
2801d8899132SKalle Valo static void ath12k_mac_op_cancel_hw_scan(struct ieee80211_hw *hw,
2802d8899132SKalle Valo 					 struct ieee80211_vif *vif)
2803d8899132SKalle Valo {
2804d8899132SKalle Valo 	struct ath12k *ar = hw->priv;
2805d8899132SKalle Valo 
2806d8899132SKalle Valo 	mutex_lock(&ar->conf_mutex);
2807d8899132SKalle Valo 	ath12k_scan_abort(ar);
2808d8899132SKalle Valo 	mutex_unlock(&ar->conf_mutex);
2809d8899132SKalle Valo 
2810d8899132SKalle Valo 	cancel_delayed_work_sync(&ar->scan.timeout);
2811d8899132SKalle Valo }
2812d8899132SKalle Valo 
2813d8899132SKalle Valo static int ath12k_install_key(struct ath12k_vif *arvif,
2814d8899132SKalle Valo 			      struct ieee80211_key_conf *key,
2815d8899132SKalle Valo 			      enum set_key_cmd cmd,
2816d8899132SKalle Valo 			      const u8 *macaddr, u32 flags)
2817d8899132SKalle Valo {
2818d8899132SKalle Valo 	int ret;
2819d8899132SKalle Valo 	struct ath12k *ar = arvif->ar;
2820d8899132SKalle Valo 	struct wmi_vdev_install_key_arg arg = {
2821d8899132SKalle Valo 		.vdev_id = arvif->vdev_id,
2822d8899132SKalle Valo 		.key_idx = key->keyidx,
2823d8899132SKalle Valo 		.key_len = key->keylen,
2824d8899132SKalle Valo 		.key_data = key->key,
2825d8899132SKalle Valo 		.key_flags = flags,
2826d8899132SKalle Valo 		.macaddr = macaddr,
2827d8899132SKalle Valo 	};
2828d8899132SKalle Valo 
2829d8899132SKalle Valo 	lockdep_assert_held(&arvif->ar->conf_mutex);
2830d8899132SKalle Valo 
2831d8899132SKalle Valo 	reinit_completion(&ar->install_key_done);
2832d8899132SKalle Valo 
2833d8899132SKalle Valo 	if (test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags))
2834d8899132SKalle Valo 		return 0;
2835d8899132SKalle Valo 
2836d8899132SKalle Valo 	if (cmd == DISABLE_KEY) {
2837d8899132SKalle Valo 		/* TODO: Check if FW expects  value other than NONE for del */
2838d8899132SKalle Valo 		/* arg.key_cipher = WMI_CIPHER_NONE; */
2839d8899132SKalle Valo 		arg.key_len = 0;
2840d8899132SKalle Valo 		arg.key_data = NULL;
2841d8899132SKalle Valo 		goto install;
2842d8899132SKalle Valo 	}
2843d8899132SKalle Valo 
2844d8899132SKalle Valo 	switch (key->cipher) {
2845d8899132SKalle Valo 	case WLAN_CIPHER_SUITE_CCMP:
2846d8899132SKalle Valo 		arg.key_cipher = WMI_CIPHER_AES_CCM;
2847d8899132SKalle Valo 		/* TODO: Re-check if flag is valid */
2848d8899132SKalle Valo 		key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV_MGMT;
2849d8899132SKalle Valo 		break;
2850d8899132SKalle Valo 	case WLAN_CIPHER_SUITE_TKIP:
2851d8899132SKalle Valo 		arg.key_cipher = WMI_CIPHER_TKIP;
2852d8899132SKalle Valo 		arg.key_txmic_len = 8;
2853d8899132SKalle Valo 		arg.key_rxmic_len = 8;
2854d8899132SKalle Valo 		break;
2855d8899132SKalle Valo 	case WLAN_CIPHER_SUITE_CCMP_256:
2856d8899132SKalle Valo 		arg.key_cipher = WMI_CIPHER_AES_CCM;
2857d8899132SKalle Valo 		break;
2858d8899132SKalle Valo 	case WLAN_CIPHER_SUITE_GCMP:
2859d8899132SKalle Valo 	case WLAN_CIPHER_SUITE_GCMP_256:
2860d8899132SKalle Valo 		arg.key_cipher = WMI_CIPHER_AES_GCM;
2861d8899132SKalle Valo 		break;
2862d8899132SKalle Valo 	default:
2863d8899132SKalle Valo 		ath12k_warn(ar->ab, "cipher %d is not supported\n", key->cipher);
2864d8899132SKalle Valo 		return -EOPNOTSUPP;
2865d8899132SKalle Valo 	}
2866d8899132SKalle Valo 
2867d8899132SKalle Valo 	if (test_bit(ATH12K_FLAG_RAW_MODE, &ar->ab->dev_flags))
2868d8899132SKalle Valo 		key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV |
2869d8899132SKalle Valo 			      IEEE80211_KEY_FLAG_RESERVE_TAILROOM;
2870d8899132SKalle Valo 
2871d8899132SKalle Valo install:
2872d8899132SKalle Valo 	ret = ath12k_wmi_vdev_install_key(arvif->ar, &arg);
2873d8899132SKalle Valo 
2874d8899132SKalle Valo 	if (ret)
2875d8899132SKalle Valo 		return ret;
2876d8899132SKalle Valo 
2877d8899132SKalle Valo 	if (!wait_for_completion_timeout(&ar->install_key_done, 1 * HZ))
2878d8899132SKalle Valo 		return -ETIMEDOUT;
2879d8899132SKalle Valo 
2880d8899132SKalle Valo 	if (ether_addr_equal(macaddr, arvif->vif->addr))
2881d8899132SKalle Valo 		arvif->key_cipher = key->cipher;
2882d8899132SKalle Valo 
2883d8899132SKalle Valo 	return ar->install_key_status ? -EINVAL : 0;
2884d8899132SKalle Valo }
2885d8899132SKalle Valo 
2886d8899132SKalle Valo static int ath12k_clear_peer_keys(struct ath12k_vif *arvif,
2887d8899132SKalle Valo 				  const u8 *addr)
2888d8899132SKalle Valo {
2889d8899132SKalle Valo 	struct ath12k *ar = arvif->ar;
2890d8899132SKalle Valo 	struct ath12k_base *ab = ar->ab;
2891d8899132SKalle Valo 	struct ath12k_peer *peer;
2892d8899132SKalle Valo 	int first_errno = 0;
2893d8899132SKalle Valo 	int ret;
2894d8899132SKalle Valo 	int i;
2895d8899132SKalle Valo 	u32 flags = 0;
2896d8899132SKalle Valo 
2897d8899132SKalle Valo 	lockdep_assert_held(&ar->conf_mutex);
2898d8899132SKalle Valo 
2899d8899132SKalle Valo 	spin_lock_bh(&ab->base_lock);
2900d8899132SKalle Valo 	peer = ath12k_peer_find(ab, arvif->vdev_id, addr);
2901d8899132SKalle Valo 	spin_unlock_bh(&ab->base_lock);
2902d8899132SKalle Valo 
2903d8899132SKalle Valo 	if (!peer)
2904d8899132SKalle Valo 		return -ENOENT;
2905d8899132SKalle Valo 
2906d8899132SKalle Valo 	for (i = 0; i < ARRAY_SIZE(peer->keys); i++) {
2907d8899132SKalle Valo 		if (!peer->keys[i])
2908d8899132SKalle Valo 			continue;
2909d8899132SKalle Valo 
2910d8899132SKalle Valo 		/* key flags are not required to delete the key */
2911d8899132SKalle Valo 		ret = ath12k_install_key(arvif, peer->keys[i],
2912d8899132SKalle Valo 					 DISABLE_KEY, addr, flags);
2913d8899132SKalle Valo 		if (ret < 0 && first_errno == 0)
2914d8899132SKalle Valo 			first_errno = ret;
2915d8899132SKalle Valo 
2916d8899132SKalle Valo 		if (ret < 0)
2917d8899132SKalle Valo 			ath12k_warn(ab, "failed to remove peer key %d: %d\n",
2918d8899132SKalle Valo 				    i, ret);
2919d8899132SKalle Valo 
2920d8899132SKalle Valo 		spin_lock_bh(&ab->base_lock);
2921d8899132SKalle Valo 		peer->keys[i] = NULL;
2922d8899132SKalle Valo 		spin_unlock_bh(&ab->base_lock);
2923d8899132SKalle Valo 	}
2924d8899132SKalle Valo 
2925d8899132SKalle Valo 	return first_errno;
2926d8899132SKalle Valo }
2927d8899132SKalle Valo 
2928d8899132SKalle Valo static int ath12k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
2929d8899132SKalle Valo 				 struct ieee80211_vif *vif, struct ieee80211_sta *sta,
2930d8899132SKalle Valo 				 struct ieee80211_key_conf *key)
2931d8899132SKalle Valo {
2932d8899132SKalle Valo 	struct ath12k *ar = hw->priv;
2933d8899132SKalle Valo 	struct ath12k_base *ab = ar->ab;
2934d8899132SKalle Valo 	struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
2935d8899132SKalle Valo 	struct ath12k_peer *peer;
2936d8899132SKalle Valo 	struct ath12k_sta *arsta;
2937d8899132SKalle Valo 	const u8 *peer_addr;
2938d8899132SKalle Valo 	int ret = 0;
2939d8899132SKalle Valo 	u32 flags = 0;
2940d8899132SKalle Valo 
2941d8899132SKalle Valo 	/* BIP needs to be done in software */
2942d8899132SKalle Valo 	if (key->cipher == WLAN_CIPHER_SUITE_AES_CMAC ||
2943d8899132SKalle Valo 	    key->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 ||
2944d8899132SKalle Valo 	    key->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256 ||
2945d8899132SKalle Valo 	    key->cipher == WLAN_CIPHER_SUITE_BIP_CMAC_256)
2946d8899132SKalle Valo 		return 1;
2947d8899132SKalle Valo 
2948d8899132SKalle Valo 	if (test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags))
2949d8899132SKalle Valo 		return 1;
2950d8899132SKalle Valo 
2951d8899132SKalle Valo 	if (key->keyidx > WMI_MAX_KEY_INDEX)
2952d8899132SKalle Valo 		return -ENOSPC;
2953d8899132SKalle Valo 
2954d8899132SKalle Valo 	mutex_lock(&ar->conf_mutex);
2955d8899132SKalle Valo 
2956d8899132SKalle Valo 	if (sta)
2957d8899132SKalle Valo 		peer_addr = sta->addr;
2958d8899132SKalle Valo 	else if (arvif->vdev_type == WMI_VDEV_TYPE_STA)
2959d8899132SKalle Valo 		peer_addr = vif->bss_conf.bssid;
2960d8899132SKalle Valo 	else
2961d8899132SKalle Valo 		peer_addr = vif->addr;
2962d8899132SKalle Valo 
2963d8899132SKalle Valo 	key->hw_key_idx = key->keyidx;
2964d8899132SKalle Valo 
2965d8899132SKalle Valo 	/* the peer should not disappear in mid-way (unless FW goes awry) since
2966d8899132SKalle Valo 	 * we already hold conf_mutex. we just make sure its there now.
2967d8899132SKalle Valo 	 */
2968d8899132SKalle Valo 	spin_lock_bh(&ab->base_lock);
2969d8899132SKalle Valo 	peer = ath12k_peer_find(ab, arvif->vdev_id, peer_addr);
2970d8899132SKalle Valo 	spin_unlock_bh(&ab->base_lock);
2971d8899132SKalle Valo 
2972d8899132SKalle Valo 	if (!peer) {
2973d8899132SKalle Valo 		if (cmd == SET_KEY) {
2974d8899132SKalle Valo 			ath12k_warn(ab, "cannot install key for non-existent peer %pM\n",
2975d8899132SKalle Valo 				    peer_addr);
2976d8899132SKalle Valo 			ret = -EOPNOTSUPP;
2977d8899132SKalle Valo 			goto exit;
2978d8899132SKalle Valo 		} else {
2979d8899132SKalle Valo 			/* if the peer doesn't exist there is no key to disable
2980d8899132SKalle Valo 			 * anymore
2981d8899132SKalle Valo 			 */
2982d8899132SKalle Valo 			goto exit;
2983d8899132SKalle Valo 		}
2984d8899132SKalle Valo 	}
2985d8899132SKalle Valo 
2986d8899132SKalle Valo 	if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
2987d8899132SKalle Valo 		flags |= WMI_KEY_PAIRWISE;
2988d8899132SKalle Valo 	else
2989d8899132SKalle Valo 		flags |= WMI_KEY_GROUP;
2990d8899132SKalle Valo 
2991d8899132SKalle Valo 	ret = ath12k_install_key(arvif, key, cmd, peer_addr, flags);
2992d8899132SKalle Valo 	if (ret) {
2993d8899132SKalle Valo 		ath12k_warn(ab, "ath12k_install_key failed (%d)\n", ret);
2994d8899132SKalle Valo 		goto exit;
2995d8899132SKalle Valo 	}
2996d8899132SKalle Valo 
2997d8899132SKalle Valo 	ret = ath12k_dp_rx_peer_pn_replay_config(arvif, peer_addr, cmd, key);
2998d8899132SKalle Valo 	if (ret) {
2999d8899132SKalle Valo 		ath12k_warn(ab, "failed to offload PN replay detection %d\n", ret);
3000d8899132SKalle Valo 		goto exit;
3001d8899132SKalle Valo 	}
3002d8899132SKalle Valo 
3003d8899132SKalle Valo 	spin_lock_bh(&ab->base_lock);
3004d8899132SKalle Valo 	peer = ath12k_peer_find(ab, arvif->vdev_id, peer_addr);
3005d8899132SKalle Valo 	if (peer && cmd == SET_KEY) {
3006d8899132SKalle Valo 		peer->keys[key->keyidx] = key;
3007d8899132SKalle Valo 		if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
3008d8899132SKalle Valo 			peer->ucast_keyidx = key->keyidx;
3009d8899132SKalle Valo 			peer->sec_type = ath12k_dp_tx_get_encrypt_type(key->cipher);
3010d8899132SKalle Valo 		} else {
3011d8899132SKalle Valo 			peer->mcast_keyidx = key->keyidx;
3012d8899132SKalle Valo 			peer->sec_type_grp = ath12k_dp_tx_get_encrypt_type(key->cipher);
3013d8899132SKalle Valo 		}
3014d8899132SKalle Valo 	} else if (peer && cmd == DISABLE_KEY) {
3015d8899132SKalle Valo 		peer->keys[key->keyidx] = NULL;
3016d8899132SKalle Valo 		if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
3017d8899132SKalle Valo 			peer->ucast_keyidx = 0;
3018d8899132SKalle Valo 		else
3019d8899132SKalle Valo 			peer->mcast_keyidx = 0;
3020d8899132SKalle Valo 	} else if (!peer)
3021d8899132SKalle Valo 		/* impossible unless FW goes crazy */
3022d8899132SKalle Valo 		ath12k_warn(ab, "peer %pM disappeared!\n", peer_addr);
3023d8899132SKalle Valo 
3024d8899132SKalle Valo 	if (sta) {
3025d8899132SKalle Valo 		arsta = (struct ath12k_sta *)sta->drv_priv;
3026d8899132SKalle Valo 
3027d8899132SKalle Valo 		switch (key->cipher) {
3028d8899132SKalle Valo 		case WLAN_CIPHER_SUITE_TKIP:
3029d8899132SKalle Valo 		case WLAN_CIPHER_SUITE_CCMP:
3030d8899132SKalle Valo 		case WLAN_CIPHER_SUITE_CCMP_256:
3031d8899132SKalle Valo 		case WLAN_CIPHER_SUITE_GCMP:
3032d8899132SKalle Valo 		case WLAN_CIPHER_SUITE_GCMP_256:
3033d8899132SKalle Valo 			if (cmd == SET_KEY)
3034d8899132SKalle Valo 				arsta->pn_type = HAL_PN_TYPE_WPA;
3035d8899132SKalle Valo 			else
3036d8899132SKalle Valo 				arsta->pn_type = HAL_PN_TYPE_NONE;
3037d8899132SKalle Valo 			break;
3038d8899132SKalle Valo 		default:
3039d8899132SKalle Valo 			arsta->pn_type = HAL_PN_TYPE_NONE;
3040d8899132SKalle Valo 			break;
3041d8899132SKalle Valo 		}
3042d8899132SKalle Valo 	}
3043d8899132SKalle Valo 
3044d8899132SKalle Valo 	spin_unlock_bh(&ab->base_lock);
3045d8899132SKalle Valo 
3046d8899132SKalle Valo exit:
3047d8899132SKalle Valo 	mutex_unlock(&ar->conf_mutex);
3048d8899132SKalle Valo 	return ret;
3049d8899132SKalle Valo }
3050d8899132SKalle Valo 
3051d8899132SKalle Valo static int
3052d8899132SKalle Valo ath12k_mac_bitrate_mask_num_vht_rates(struct ath12k *ar,
3053d8899132SKalle Valo 				      enum nl80211_band band,
3054d8899132SKalle Valo 				      const struct cfg80211_bitrate_mask *mask)
3055d8899132SKalle Valo {
3056d8899132SKalle Valo 	int num_rates = 0;
3057d8899132SKalle Valo 	int i;
3058d8899132SKalle Valo 
3059d8899132SKalle Valo 	for (i = 0; i < ARRAY_SIZE(mask->control[band].vht_mcs); i++)
3060d8899132SKalle Valo 		num_rates += hweight16(mask->control[band].vht_mcs[i]);
3061d8899132SKalle Valo 
3062d8899132SKalle Valo 	return num_rates;
3063d8899132SKalle Valo }
3064d8899132SKalle Valo 
3065d8899132SKalle Valo static int
3066d8899132SKalle Valo ath12k_mac_set_peer_vht_fixed_rate(struct ath12k_vif *arvif,
3067d8899132SKalle Valo 				   struct ieee80211_sta *sta,
3068d8899132SKalle Valo 				   const struct cfg80211_bitrate_mask *mask,
3069d8899132SKalle Valo 				   enum nl80211_band band)
3070d8899132SKalle Valo {
3071d8899132SKalle Valo 	struct ath12k *ar = arvif->ar;
3072d8899132SKalle Valo 	u8 vht_rate, nss;
3073d8899132SKalle Valo 	u32 rate_code;
3074d8899132SKalle Valo 	int ret, i;
3075d8899132SKalle Valo 
3076d8899132SKalle Valo 	lockdep_assert_held(&ar->conf_mutex);
3077d8899132SKalle Valo 
3078d8899132SKalle Valo 	nss = 0;
3079d8899132SKalle Valo 
3080d8899132SKalle Valo 	for (i = 0; i < ARRAY_SIZE(mask->control[band].vht_mcs); i++) {
3081d8899132SKalle Valo 		if (hweight16(mask->control[band].vht_mcs[i]) == 1) {
3082d8899132SKalle Valo 			nss = i + 1;
3083d8899132SKalle Valo 			vht_rate = ffs(mask->control[band].vht_mcs[i]) - 1;
3084d8899132SKalle Valo 		}
3085d8899132SKalle Valo 	}
3086d8899132SKalle Valo 
3087d8899132SKalle Valo 	if (!nss) {
3088d8899132SKalle Valo 		ath12k_warn(ar->ab, "No single VHT Fixed rate found to set for %pM",
3089d8899132SKalle Valo 			    sta->addr);
3090d8899132SKalle Valo 		return -EINVAL;
3091d8899132SKalle Valo 	}
3092d8899132SKalle Valo 
3093d8899132SKalle Valo 	ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
3094d8899132SKalle Valo 		   "Setting Fixed VHT Rate for peer %pM. Device will not switch to any other selected rates",
3095d8899132SKalle Valo 		   sta->addr);
3096d8899132SKalle Valo 
3097d8899132SKalle Valo 	rate_code = ATH12K_HW_RATE_CODE(vht_rate, nss - 1,
3098d8899132SKalle Valo 					WMI_RATE_PREAMBLE_VHT);
3099d8899132SKalle Valo 	ret = ath12k_wmi_set_peer_param(ar, sta->addr,
3100d8899132SKalle Valo 					arvif->vdev_id,
3101d8899132SKalle Valo 					WMI_PEER_PARAM_FIXED_RATE,
3102d8899132SKalle Valo 					rate_code);
3103d8899132SKalle Valo 	if (ret)
3104d8899132SKalle Valo 		ath12k_warn(ar->ab,
3105d8899132SKalle Valo 			    "failed to update STA %pM Fixed Rate %d: %d\n",
3106d8899132SKalle Valo 			     sta->addr, rate_code, ret);
3107d8899132SKalle Valo 
3108d8899132SKalle Valo 	return ret;
3109d8899132SKalle Valo }
3110d8899132SKalle Valo 
3111d8899132SKalle Valo static int ath12k_station_assoc(struct ath12k *ar,
3112d8899132SKalle Valo 				struct ieee80211_vif *vif,
3113d8899132SKalle Valo 				struct ieee80211_sta *sta,
3114d8899132SKalle Valo 				bool reassoc)
3115d8899132SKalle Valo {
3116d8899132SKalle Valo 	struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
3117d8899132SKalle Valo 	struct ath12k_wmi_peer_assoc_arg peer_arg;
3118d8899132SKalle Valo 	int ret;
3119d8899132SKalle Valo 	struct cfg80211_chan_def def;
3120d8899132SKalle Valo 	enum nl80211_band band;
3121d8899132SKalle Valo 	struct cfg80211_bitrate_mask *mask;
3122d8899132SKalle Valo 	u8 num_vht_rates;
3123d8899132SKalle Valo 
3124d8899132SKalle Valo 	lockdep_assert_held(&ar->conf_mutex);
3125d8899132SKalle Valo 
3126d8899132SKalle Valo 	if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))
3127d8899132SKalle Valo 		return -EPERM;
3128d8899132SKalle Valo 
3129d8899132SKalle Valo 	band = def.chan->band;
3130d8899132SKalle Valo 	mask = &arvif->bitrate_mask;
3131d8899132SKalle Valo 
3132d8899132SKalle Valo 	ath12k_peer_assoc_prepare(ar, vif, sta, &peer_arg, reassoc);
3133d8899132SKalle Valo 
3134d8899132SKalle Valo 	ret = ath12k_wmi_send_peer_assoc_cmd(ar, &peer_arg);
3135d8899132SKalle Valo 	if (ret) {
3136d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to run peer assoc for STA %pM vdev %i: %d\n",
3137d8899132SKalle Valo 			    sta->addr, arvif->vdev_id, ret);
3138d8899132SKalle Valo 		return ret;
3139d8899132SKalle Valo 	}
3140d8899132SKalle Valo 
3141d8899132SKalle Valo 	if (!wait_for_completion_timeout(&ar->peer_assoc_done, 1 * HZ)) {
3142d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to get peer assoc conf event for %pM vdev %i\n",
3143d8899132SKalle Valo 			    sta->addr, arvif->vdev_id);
3144d8899132SKalle Valo 		return -ETIMEDOUT;
3145d8899132SKalle Valo 	}
3146d8899132SKalle Valo 
3147d8899132SKalle Valo 	num_vht_rates = ath12k_mac_bitrate_mask_num_vht_rates(ar, band, mask);
3148d8899132SKalle Valo 
3149d8899132SKalle Valo 	/* If single VHT rate is configured (by set_bitrate_mask()),
3150d8899132SKalle Valo 	 * peer_assoc will disable VHT. This is now enabled by a peer specific
3151d8899132SKalle Valo 	 * fixed param.
3152d8899132SKalle Valo 	 * Note that all other rates and NSS will be disabled for this peer.
3153d8899132SKalle Valo 	 */
3154d8899132SKalle Valo 	if (sta->deflink.vht_cap.vht_supported && num_vht_rates == 1) {
3155d8899132SKalle Valo 		ret = ath12k_mac_set_peer_vht_fixed_rate(arvif, sta, mask,
3156d8899132SKalle Valo 							 band);
3157d8899132SKalle Valo 		if (ret)
3158d8899132SKalle Valo 			return ret;
3159d8899132SKalle Valo 	}
3160d8899132SKalle Valo 
3161d8899132SKalle Valo 	/* Re-assoc is run only to update supported rates for given station. It
3162d8899132SKalle Valo 	 * doesn't make much sense to reconfigure the peer completely.
3163d8899132SKalle Valo 	 */
3164d8899132SKalle Valo 	if (reassoc)
3165d8899132SKalle Valo 		return 0;
3166d8899132SKalle Valo 
3167d8899132SKalle Valo 	ret = ath12k_setup_peer_smps(ar, arvif, sta->addr,
3168d8899132SKalle Valo 				     &sta->deflink.ht_cap);
3169d8899132SKalle Valo 	if (ret) {
3170d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to setup peer SMPS for vdev %d: %d\n",
3171d8899132SKalle Valo 			    arvif->vdev_id, ret);
3172d8899132SKalle Valo 		return ret;
3173d8899132SKalle Valo 	}
3174d8899132SKalle Valo 
3175d8899132SKalle Valo 	if (!sta->wme) {
3176d8899132SKalle Valo 		arvif->num_legacy_stations++;
3177d8899132SKalle Valo 		ret = ath12k_recalc_rtscts_prot(arvif);
3178d8899132SKalle Valo 		if (ret)
3179d8899132SKalle Valo 			return ret;
3180d8899132SKalle Valo 	}
3181d8899132SKalle Valo 
3182d8899132SKalle Valo 	if (sta->wme && sta->uapsd_queues) {
3183d8899132SKalle Valo 		ret = ath12k_peer_assoc_qos_ap(ar, arvif, sta);
3184d8899132SKalle Valo 		if (ret) {
3185d8899132SKalle Valo 			ath12k_warn(ar->ab, "failed to set qos params for STA %pM for vdev %i: %d\n",
3186d8899132SKalle Valo 				    sta->addr, arvif->vdev_id, ret);
3187d8899132SKalle Valo 			return ret;
3188d8899132SKalle Valo 		}
3189d8899132SKalle Valo 	}
3190d8899132SKalle Valo 
3191d8899132SKalle Valo 	return 0;
3192d8899132SKalle Valo }
3193d8899132SKalle Valo 
3194d8899132SKalle Valo static int ath12k_station_disassoc(struct ath12k *ar,
3195d8899132SKalle Valo 				   struct ieee80211_vif *vif,
3196d8899132SKalle Valo 				   struct ieee80211_sta *sta)
3197d8899132SKalle Valo {
3198d8899132SKalle Valo 	struct ath12k_vif *arvif = (void *)vif->drv_priv;
3199d8899132SKalle Valo 	int ret;
3200d8899132SKalle Valo 
3201d8899132SKalle Valo 	lockdep_assert_held(&ar->conf_mutex);
3202d8899132SKalle Valo 
3203d8899132SKalle Valo 	if (!sta->wme) {
3204d8899132SKalle Valo 		arvif->num_legacy_stations--;
3205d8899132SKalle Valo 		ret = ath12k_recalc_rtscts_prot(arvif);
3206d8899132SKalle Valo 		if (ret)
3207d8899132SKalle Valo 			return ret;
3208d8899132SKalle Valo 	}
3209d8899132SKalle Valo 
3210d8899132SKalle Valo 	ret = ath12k_clear_peer_keys(arvif, sta->addr);
3211d8899132SKalle Valo 	if (ret) {
3212d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to clear all peer keys for vdev %i: %d\n",
3213d8899132SKalle Valo 			    arvif->vdev_id, ret);
3214d8899132SKalle Valo 		return ret;
3215d8899132SKalle Valo 	}
3216d8899132SKalle Valo 	return 0;
3217d8899132SKalle Valo }
3218d8899132SKalle Valo 
3219d8899132SKalle Valo static void ath12k_sta_rc_update_wk(struct work_struct *wk)
3220d8899132SKalle Valo {
3221d8899132SKalle Valo 	struct ath12k *ar;
3222d8899132SKalle Valo 	struct ath12k_vif *arvif;
3223d8899132SKalle Valo 	struct ath12k_sta *arsta;
3224d8899132SKalle Valo 	struct ieee80211_sta *sta;
3225d8899132SKalle Valo 	struct cfg80211_chan_def def;
3226d8899132SKalle Valo 	enum nl80211_band band;
3227d8899132SKalle Valo 	const u8 *ht_mcs_mask;
3228d8899132SKalle Valo 	const u16 *vht_mcs_mask;
3229cbc0008cSAditya Kumar Singh 	u32 changed, bw, nss, smps, bw_prev;
3230d8899132SKalle Valo 	int err, num_vht_rates;
3231d8899132SKalle Valo 	const struct cfg80211_bitrate_mask *mask;
3232d8899132SKalle Valo 	struct ath12k_wmi_peer_assoc_arg peer_arg;
3233cbc0008cSAditya Kumar Singh 	enum wmi_phy_mode peer_phymode;
3234d8899132SKalle Valo 
3235d8899132SKalle Valo 	arsta = container_of(wk, struct ath12k_sta, update_wk);
3236d8899132SKalle Valo 	sta = container_of((void *)arsta, struct ieee80211_sta, drv_priv);
3237d8899132SKalle Valo 	arvif = arsta->arvif;
3238d8899132SKalle Valo 	ar = arvif->ar;
3239d8899132SKalle Valo 
3240d8899132SKalle Valo 	if (WARN_ON(ath12k_mac_vif_chan(arvif->vif, &def)))
3241d8899132SKalle Valo 		return;
3242d8899132SKalle Valo 
3243d8899132SKalle Valo 	band = def.chan->band;
3244d8899132SKalle Valo 	ht_mcs_mask = arvif->bitrate_mask.control[band].ht_mcs;
3245d8899132SKalle Valo 	vht_mcs_mask = arvif->bitrate_mask.control[band].vht_mcs;
3246d8899132SKalle Valo 
3247d8899132SKalle Valo 	spin_lock_bh(&ar->data_lock);
3248d8899132SKalle Valo 
3249d8899132SKalle Valo 	changed = arsta->changed;
3250d8899132SKalle Valo 	arsta->changed = 0;
3251d8899132SKalle Valo 
3252d8899132SKalle Valo 	bw = arsta->bw;
3253cbc0008cSAditya Kumar Singh 	bw_prev = arsta->bw_prev;
3254d8899132SKalle Valo 	nss = arsta->nss;
3255d8899132SKalle Valo 	smps = arsta->smps;
3256d8899132SKalle Valo 
3257d8899132SKalle Valo 	spin_unlock_bh(&ar->data_lock);
3258d8899132SKalle Valo 
3259d8899132SKalle Valo 	mutex_lock(&ar->conf_mutex);
3260d8899132SKalle Valo 
3261d8899132SKalle Valo 	nss = max_t(u32, 1, nss);
3262d8899132SKalle Valo 	nss = min(nss, max(ath12k_mac_max_ht_nss(ht_mcs_mask),
3263d8899132SKalle Valo 			   ath12k_mac_max_vht_nss(vht_mcs_mask)));
3264d8899132SKalle Valo 
3265d8899132SKalle Valo 	if (changed & IEEE80211_RC_BW_CHANGED) {
3266cbc0008cSAditya Kumar Singh 		ath12k_peer_assoc_h_phymode(ar, arvif->vif, sta, &peer_arg);
3267cbc0008cSAditya Kumar Singh 		peer_phymode = peer_arg.peer_phymode;
3268cbc0008cSAditya Kumar Singh 
3269cbc0008cSAditya Kumar Singh 		if (bw > bw_prev) {
3270cbc0008cSAditya Kumar Singh 			/* Phymode shows maximum supported channel width, if we
3271cbc0008cSAditya Kumar Singh 			 * upgrade bandwidth then due to sanity check of firmware,
3272cbc0008cSAditya Kumar Singh 			 * we have to send WMI_PEER_PHYMODE followed by
3273cbc0008cSAditya Kumar Singh 			 * WMI_PEER_CHWIDTH
3274cbc0008cSAditya Kumar Singh 			 */
3275cbc0008cSAditya Kumar Singh 			ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac bandwidth upgrade for sta %pM new %d old %d\n",
3276cbc0008cSAditya Kumar Singh 				   sta->addr, bw, bw_prev);
3277cbc0008cSAditya Kumar Singh 			err = ath12k_wmi_set_peer_param(ar, sta->addr,
3278cbc0008cSAditya Kumar Singh 							arvif->vdev_id, WMI_PEER_PHYMODE,
3279cbc0008cSAditya Kumar Singh 							peer_phymode);
3280cbc0008cSAditya Kumar Singh 			if (err) {
3281cbc0008cSAditya Kumar Singh 				ath12k_warn(ar->ab, "failed to update STA %pM to peer phymode %d: %d\n",
3282cbc0008cSAditya Kumar Singh 					    sta->addr, peer_phymode, err);
3283cbc0008cSAditya Kumar Singh 				goto err_rc_bw_changed;
3284cbc0008cSAditya Kumar Singh 			}
3285cbc0008cSAditya Kumar Singh 			err = ath12k_wmi_set_peer_param(ar, sta->addr,
3286cbc0008cSAditya Kumar Singh 							arvif->vdev_id, WMI_PEER_CHWIDTH,
3287cbc0008cSAditya Kumar Singh 							bw);
3288d8899132SKalle Valo 			if (err)
3289cbc0008cSAditya Kumar Singh 				ath12k_warn(ar->ab, "failed to update STA %pM to peer bandwidth %d: %d\n",
3290d8899132SKalle Valo 					    sta->addr, bw, err);
3291cbc0008cSAditya Kumar Singh 		} else {
3292cbc0008cSAditya Kumar Singh 			/* When we downgrade bandwidth this will conflict with phymode
3293cbc0008cSAditya Kumar Singh 			 * and cause to trigger firmware crash. In this case we send
3294cbc0008cSAditya Kumar Singh 			 * WMI_PEER_CHWIDTH followed by WMI_PEER_PHYMODE
3295cbc0008cSAditya Kumar Singh 			 */
3296cbc0008cSAditya Kumar Singh 			ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac bandwidth downgrade for sta %pM new %d old %d\n",
3297cbc0008cSAditya Kumar Singh 				   sta->addr, bw, bw_prev);
3298cbc0008cSAditya Kumar Singh 			err = ath12k_wmi_set_peer_param(ar, sta->addr,
3299cbc0008cSAditya Kumar Singh 							arvif->vdev_id, WMI_PEER_CHWIDTH,
3300cbc0008cSAditya Kumar Singh 							bw);
3301cbc0008cSAditya Kumar Singh 			if (err) {
3302cbc0008cSAditya Kumar Singh 				ath12k_warn(ar->ab, "failed to update STA %pM peer to bandwidth %d: %d\n",
3303cbc0008cSAditya Kumar Singh 					    sta->addr, bw, err);
3304cbc0008cSAditya Kumar Singh 				goto err_rc_bw_changed;
3305cbc0008cSAditya Kumar Singh 			}
3306cbc0008cSAditya Kumar Singh 			err = ath12k_wmi_set_peer_param(ar, sta->addr,
3307cbc0008cSAditya Kumar Singh 							arvif->vdev_id, WMI_PEER_PHYMODE,
3308cbc0008cSAditya Kumar Singh 							peer_phymode);
3309cbc0008cSAditya Kumar Singh 			if (err)
3310cbc0008cSAditya Kumar Singh 				ath12k_warn(ar->ab, "failed to update STA %pM to peer phymode %d: %d\n",
3311cbc0008cSAditya Kumar Singh 					    sta->addr, peer_phymode, err);
3312cbc0008cSAditya Kumar Singh 		}
3313d8899132SKalle Valo 	}
3314d8899132SKalle Valo 
3315d8899132SKalle Valo 	if (changed & IEEE80211_RC_NSS_CHANGED) {
3316d8899132SKalle Valo 		ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac update sta %pM nss %d\n",
3317d8899132SKalle Valo 			   sta->addr, nss);
3318d8899132SKalle Valo 
3319d8899132SKalle Valo 		err = ath12k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,
3320d8899132SKalle Valo 						WMI_PEER_NSS, nss);
3321d8899132SKalle Valo 		if (err)
3322d8899132SKalle Valo 			ath12k_warn(ar->ab, "failed to update STA %pM nss %d: %d\n",
3323d8899132SKalle Valo 				    sta->addr, nss, err);
3324d8899132SKalle Valo 	}
3325d8899132SKalle Valo 
3326d8899132SKalle Valo 	if (changed & IEEE80211_RC_SMPS_CHANGED) {
3327d8899132SKalle Valo 		ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac update sta %pM smps %d\n",
3328d8899132SKalle Valo 			   sta->addr, smps);
3329d8899132SKalle Valo 
3330d8899132SKalle Valo 		err = ath12k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,
3331d8899132SKalle Valo 						WMI_PEER_MIMO_PS_STATE, smps);
3332d8899132SKalle Valo 		if (err)
3333d8899132SKalle Valo 			ath12k_warn(ar->ab, "failed to update STA %pM smps %d: %d\n",
3334d8899132SKalle Valo 				    sta->addr, smps, err);
3335d8899132SKalle Valo 	}
3336d8899132SKalle Valo 
3337d8899132SKalle Valo 	if (changed & IEEE80211_RC_SUPP_RATES_CHANGED) {
3338d8899132SKalle Valo 		mask = &arvif->bitrate_mask;
3339d8899132SKalle Valo 		num_vht_rates = ath12k_mac_bitrate_mask_num_vht_rates(ar, band,
3340d8899132SKalle Valo 								      mask);
3341d8899132SKalle Valo 
3342d8899132SKalle Valo 		/* Peer_assoc_prepare will reject vht rates in
3343d8899132SKalle Valo 		 * bitrate_mask if its not available in range format and
3344d8899132SKalle Valo 		 * sets vht tx_rateset as unsupported. So multiple VHT MCS
3345d8899132SKalle Valo 		 * setting(eg. MCS 4,5,6) per peer is not supported here.
3346d8899132SKalle Valo 		 * But, Single rate in VHT mask can be set as per-peer
3347d8899132SKalle Valo 		 * fixed rate. But even if any HT rates are configured in
3348d8899132SKalle Valo 		 * the bitrate mask, device will not switch to those rates
3349d8899132SKalle Valo 		 * when per-peer Fixed rate is set.
3350d8899132SKalle Valo 		 * TODO: Check RATEMASK_CMDID to support auto rates selection
3351d8899132SKalle Valo 		 * across HT/VHT and for multiple VHT MCS support.
3352d8899132SKalle Valo 		 */
3353d8899132SKalle Valo 		if (sta->deflink.vht_cap.vht_supported && num_vht_rates == 1) {
3354d8899132SKalle Valo 			ath12k_mac_set_peer_vht_fixed_rate(arvif, sta, mask,
3355d8899132SKalle Valo 							   band);
3356d8899132SKalle Valo 		} else {
3357d8899132SKalle Valo 			/* If the peer is non-VHT or no fixed VHT rate
3358d8899132SKalle Valo 			 * is provided in the new bitrate mask we set the
3359d8899132SKalle Valo 			 * other rates using peer_assoc command.
3360d8899132SKalle Valo 			 */
3361d8899132SKalle Valo 			ath12k_peer_assoc_prepare(ar, arvif->vif, sta,
3362d8899132SKalle Valo 						  &peer_arg, true);
3363d8899132SKalle Valo 
3364d8899132SKalle Valo 			err = ath12k_wmi_send_peer_assoc_cmd(ar, &peer_arg);
3365d8899132SKalle Valo 			if (err)
3366d8899132SKalle Valo 				ath12k_warn(ar->ab, "failed to run peer assoc for STA %pM vdev %i: %d\n",
3367d8899132SKalle Valo 					    sta->addr, arvif->vdev_id, err);
3368d8899132SKalle Valo 
3369d8899132SKalle Valo 			if (!wait_for_completion_timeout(&ar->peer_assoc_done, 1 * HZ))
3370d8899132SKalle Valo 				ath12k_warn(ar->ab, "failed to get peer assoc conf event for %pM vdev %i\n",
3371d8899132SKalle Valo 					    sta->addr, arvif->vdev_id);
3372d8899132SKalle Valo 		}
3373d8899132SKalle Valo 	}
3374cbc0008cSAditya Kumar Singh err_rc_bw_changed:
3375d8899132SKalle Valo 	mutex_unlock(&ar->conf_mutex);
3376d8899132SKalle Valo }
3377d8899132SKalle Valo 
3378d8899132SKalle Valo static int ath12k_mac_inc_num_stations(struct ath12k_vif *arvif,
3379d8899132SKalle Valo 				       struct ieee80211_sta *sta)
3380d8899132SKalle Valo {
3381d8899132SKalle Valo 	struct ath12k *ar = arvif->ar;
3382d8899132SKalle Valo 
3383d8899132SKalle Valo 	lockdep_assert_held(&ar->conf_mutex);
3384d8899132SKalle Valo 
3385d8899132SKalle Valo 	if (arvif->vdev_type == WMI_VDEV_TYPE_STA && !sta->tdls)
3386d8899132SKalle Valo 		return 0;
3387d8899132SKalle Valo 
3388d8899132SKalle Valo 	if (ar->num_stations >= ar->max_num_stations)
3389d8899132SKalle Valo 		return -ENOBUFS;
3390d8899132SKalle Valo 
3391d8899132SKalle Valo 	ar->num_stations++;
3392d8899132SKalle Valo 
3393d8899132SKalle Valo 	return 0;
3394d8899132SKalle Valo }
3395d8899132SKalle Valo 
3396d8899132SKalle Valo static void ath12k_mac_dec_num_stations(struct ath12k_vif *arvif,
3397d8899132SKalle Valo 					struct ieee80211_sta *sta)
3398d8899132SKalle Valo {
3399d8899132SKalle Valo 	struct ath12k *ar = arvif->ar;
3400d8899132SKalle Valo 
3401d8899132SKalle Valo 	lockdep_assert_held(&ar->conf_mutex);
3402d8899132SKalle Valo 
3403d8899132SKalle Valo 	if (arvif->vdev_type == WMI_VDEV_TYPE_STA && !sta->tdls)
3404d8899132SKalle Valo 		return;
3405d8899132SKalle Valo 
3406d8899132SKalle Valo 	ar->num_stations--;
3407d8899132SKalle Valo }
3408d8899132SKalle Valo 
3409d8899132SKalle Valo static int ath12k_mac_station_add(struct ath12k *ar,
3410d8899132SKalle Valo 				  struct ieee80211_vif *vif,
3411d8899132SKalle Valo 				  struct ieee80211_sta *sta)
3412d8899132SKalle Valo {
3413d8899132SKalle Valo 	struct ath12k_base *ab = ar->ab;
3414d8899132SKalle Valo 	struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
3415d8899132SKalle Valo 	struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv;
3416d8899132SKalle Valo 	struct ath12k_wmi_peer_create_arg peer_param;
3417d8899132SKalle Valo 	int ret;
3418d8899132SKalle Valo 
3419d8899132SKalle Valo 	lockdep_assert_held(&ar->conf_mutex);
3420d8899132SKalle Valo 
3421d8899132SKalle Valo 	ret = ath12k_mac_inc_num_stations(arvif, sta);
3422d8899132SKalle Valo 	if (ret) {
3423d8899132SKalle Valo 		ath12k_warn(ab, "refusing to associate station: too many connected already (%d)\n",
3424d8899132SKalle Valo 			    ar->max_num_stations);
3425d8899132SKalle Valo 		goto exit;
3426d8899132SKalle Valo 	}
3427d8899132SKalle Valo 
3428d8899132SKalle Valo 	arsta->rx_stats = kzalloc(sizeof(*arsta->rx_stats), GFP_KERNEL);
3429d8899132SKalle Valo 	if (!arsta->rx_stats) {
3430d8899132SKalle Valo 		ret = -ENOMEM;
3431d8899132SKalle Valo 		goto dec_num_station;
3432d8899132SKalle Valo 	}
3433d8899132SKalle Valo 
3434d8899132SKalle Valo 	peer_param.vdev_id = arvif->vdev_id;
3435d8899132SKalle Valo 	peer_param.peer_addr = sta->addr;
3436d8899132SKalle Valo 	peer_param.peer_type = WMI_PEER_TYPE_DEFAULT;
3437d8899132SKalle Valo 
3438d8899132SKalle Valo 	ret = ath12k_peer_create(ar, arvif, sta, &peer_param);
3439d8899132SKalle Valo 	if (ret) {
3440d8899132SKalle Valo 		ath12k_warn(ab, "Failed to add peer: %pM for VDEV: %d\n",
3441d8899132SKalle Valo 			    sta->addr, arvif->vdev_id);
3442d8899132SKalle Valo 		goto free_peer;
3443d8899132SKalle Valo 	}
3444d8899132SKalle Valo 
3445d8899132SKalle Valo 	ath12k_dbg(ab, ATH12K_DBG_MAC, "Added peer: %pM for VDEV: %d\n",
3446d8899132SKalle Valo 		   sta->addr, arvif->vdev_id);
3447d8899132SKalle Valo 
3448d8899132SKalle Valo 	if (ieee80211_vif_is_mesh(vif)) {
3449d8899132SKalle Valo 		ret = ath12k_wmi_set_peer_param(ar, sta->addr,
3450d8899132SKalle Valo 						arvif->vdev_id,
3451d8899132SKalle Valo 						WMI_PEER_USE_4ADDR, 1);
3452d8899132SKalle Valo 		if (ret) {
3453d8899132SKalle Valo 			ath12k_warn(ab, "failed to STA %pM 4addr capability: %d\n",
3454d8899132SKalle Valo 				    sta->addr, ret);
3455d8899132SKalle Valo 			goto free_peer;
3456d8899132SKalle Valo 		}
3457d8899132SKalle Valo 	}
3458d8899132SKalle Valo 
3459d8899132SKalle Valo 	ret = ath12k_dp_peer_setup(ar, arvif->vdev_id, sta->addr);
3460d8899132SKalle Valo 	if (ret) {
3461d8899132SKalle Valo 		ath12k_warn(ab, "failed to setup dp for peer %pM on vdev %i (%d)\n",
3462d8899132SKalle Valo 			    sta->addr, arvif->vdev_id, ret);
3463d8899132SKalle Valo 		goto free_peer;
3464d8899132SKalle Valo 	}
3465d8899132SKalle Valo 
3466d8899132SKalle Valo 	if (ab->hw_params->vdev_start_delay &&
3467d8899132SKalle Valo 	    !arvif->is_started &&
3468d8899132SKalle Valo 	    arvif->vdev_type != WMI_VDEV_TYPE_AP) {
3469d8899132SKalle Valo 		ret = ath12k_start_vdev_delay(ar->hw, vif);
3470d8899132SKalle Valo 		if (ret) {
3471d8899132SKalle Valo 			ath12k_warn(ab, "failed to delay vdev start: %d\n", ret);
3472d8899132SKalle Valo 			goto free_peer;
3473d8899132SKalle Valo 		}
3474d8899132SKalle Valo 	}
3475d8899132SKalle Valo 
3476d8899132SKalle Valo 	return 0;
3477d8899132SKalle Valo 
3478d8899132SKalle Valo free_peer:
3479d8899132SKalle Valo 	ath12k_peer_delete(ar, arvif->vdev_id, sta->addr);
3480d8899132SKalle Valo dec_num_station:
3481d8899132SKalle Valo 	ath12k_mac_dec_num_stations(arvif, sta);
3482d8899132SKalle Valo exit:
3483d8899132SKalle Valo 	return ret;
3484d8899132SKalle Valo }
3485d8899132SKalle Valo 
3486cbc0008cSAditya Kumar Singh static u32 ath12k_mac_ieee80211_sta_bw_to_wmi(struct ath12k *ar,
3487cbc0008cSAditya Kumar Singh 					      struct ieee80211_sta *sta)
3488cbc0008cSAditya Kumar Singh {
3489cbc0008cSAditya Kumar Singh 	u32 bw = WMI_PEER_CHWIDTH_20MHZ;
3490cbc0008cSAditya Kumar Singh 
3491cbc0008cSAditya Kumar Singh 	switch (sta->deflink.bandwidth) {
3492cbc0008cSAditya Kumar Singh 	case IEEE80211_STA_RX_BW_20:
3493cbc0008cSAditya Kumar Singh 		bw = WMI_PEER_CHWIDTH_20MHZ;
3494cbc0008cSAditya Kumar Singh 		break;
3495cbc0008cSAditya Kumar Singh 	case IEEE80211_STA_RX_BW_40:
3496cbc0008cSAditya Kumar Singh 		bw = WMI_PEER_CHWIDTH_40MHZ;
3497cbc0008cSAditya Kumar Singh 		break;
3498cbc0008cSAditya Kumar Singh 	case IEEE80211_STA_RX_BW_80:
3499cbc0008cSAditya Kumar Singh 		bw = WMI_PEER_CHWIDTH_80MHZ;
3500cbc0008cSAditya Kumar Singh 		break;
3501cbc0008cSAditya Kumar Singh 	case IEEE80211_STA_RX_BW_160:
3502cbc0008cSAditya Kumar Singh 		bw = WMI_PEER_CHWIDTH_160MHZ;
3503cbc0008cSAditya Kumar Singh 		break;
3504cbc0008cSAditya Kumar Singh 	default:
3505cbc0008cSAditya Kumar Singh 		ath12k_warn(ar->ab, "Invalid bandwidth %d in rc update for %pM\n",
3506cbc0008cSAditya Kumar Singh 			    sta->deflink.bandwidth, sta->addr);
3507cbc0008cSAditya Kumar Singh 		bw = WMI_PEER_CHWIDTH_20MHZ;
3508cbc0008cSAditya Kumar Singh 		break;
3509cbc0008cSAditya Kumar Singh 	}
3510cbc0008cSAditya Kumar Singh 
3511cbc0008cSAditya Kumar Singh 	return bw;
3512cbc0008cSAditya Kumar Singh }
3513cbc0008cSAditya Kumar Singh 
3514d8899132SKalle Valo static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
3515d8899132SKalle Valo 				   struct ieee80211_vif *vif,
3516d8899132SKalle Valo 				   struct ieee80211_sta *sta,
3517d8899132SKalle Valo 				   enum ieee80211_sta_state old_state,
3518d8899132SKalle Valo 				   enum ieee80211_sta_state new_state)
3519d8899132SKalle Valo {
3520d8899132SKalle Valo 	struct ath12k *ar = hw->priv;
3521d8899132SKalle Valo 	struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
3522d8899132SKalle Valo 	struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv;
3523d8899132SKalle Valo 	struct ath12k_peer *peer;
3524d8899132SKalle Valo 	int ret = 0;
3525d8899132SKalle Valo 
3526d8899132SKalle Valo 	/* cancel must be done outside the mutex to avoid deadlock */
3527d8899132SKalle Valo 	if ((old_state == IEEE80211_STA_NONE &&
3528d8899132SKalle Valo 	     new_state == IEEE80211_STA_NOTEXIST))
3529d8899132SKalle Valo 		cancel_work_sync(&arsta->update_wk);
3530d8899132SKalle Valo 
3531d8899132SKalle Valo 	mutex_lock(&ar->conf_mutex);
3532d8899132SKalle Valo 
3533d8899132SKalle Valo 	if (old_state == IEEE80211_STA_NOTEXIST &&
3534d8899132SKalle Valo 	    new_state == IEEE80211_STA_NONE) {
3535d8899132SKalle Valo 		memset(arsta, 0, sizeof(*arsta));
3536d8899132SKalle Valo 		arsta->arvif = arvif;
3537d8899132SKalle Valo 		INIT_WORK(&arsta->update_wk, ath12k_sta_rc_update_wk);
3538d8899132SKalle Valo 
3539d8899132SKalle Valo 		ret = ath12k_mac_station_add(ar, vif, sta);
3540d8899132SKalle Valo 		if (ret)
3541d8899132SKalle Valo 			ath12k_warn(ar->ab, "Failed to add station: %pM for VDEV: %d\n",
3542d8899132SKalle Valo 				    sta->addr, arvif->vdev_id);
3543d8899132SKalle Valo 	} else if ((old_state == IEEE80211_STA_NONE &&
3544d8899132SKalle Valo 		    new_state == IEEE80211_STA_NOTEXIST)) {
3545d8899132SKalle Valo 		ath12k_dp_peer_cleanup(ar, arvif->vdev_id, sta->addr);
3546d8899132SKalle Valo 
3547d8899132SKalle Valo 		ret = ath12k_peer_delete(ar, arvif->vdev_id, sta->addr);
3548d8899132SKalle Valo 		if (ret)
3549d8899132SKalle Valo 			ath12k_warn(ar->ab, "Failed to delete peer: %pM for VDEV: %d\n",
3550d8899132SKalle Valo 				    sta->addr, arvif->vdev_id);
3551d8899132SKalle Valo 		else
3552d8899132SKalle Valo 			ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "Removed peer: %pM for VDEV: %d\n",
3553d8899132SKalle Valo 				   sta->addr, arvif->vdev_id);
3554d8899132SKalle Valo 
3555d8899132SKalle Valo 		ath12k_mac_dec_num_stations(arvif, sta);
3556d8899132SKalle Valo 		spin_lock_bh(&ar->ab->base_lock);
3557d8899132SKalle Valo 		peer = ath12k_peer_find(ar->ab, arvif->vdev_id, sta->addr);
3558d8899132SKalle Valo 		if (peer && peer->sta == sta) {
3559d8899132SKalle Valo 			ath12k_warn(ar->ab, "Found peer entry %pM n vdev %i after it was supposedly removed\n",
3560d8899132SKalle Valo 				    vif->addr, arvif->vdev_id);
3561d8899132SKalle Valo 			peer->sta = NULL;
3562d8899132SKalle Valo 			list_del(&peer->list);
3563d8899132SKalle Valo 			kfree(peer);
3564d8899132SKalle Valo 			ar->num_peers--;
3565d8899132SKalle Valo 		}
3566d8899132SKalle Valo 		spin_unlock_bh(&ar->ab->base_lock);
3567d8899132SKalle Valo 
3568d8899132SKalle Valo 		kfree(arsta->rx_stats);
3569d8899132SKalle Valo 		arsta->rx_stats = NULL;
3570d8899132SKalle Valo 	} else if (old_state == IEEE80211_STA_AUTH &&
3571d8899132SKalle Valo 		   new_state == IEEE80211_STA_ASSOC &&
3572d8899132SKalle Valo 		   (vif->type == NL80211_IFTYPE_AP ||
3573d8899132SKalle Valo 		    vif->type == NL80211_IFTYPE_MESH_POINT ||
3574d8899132SKalle Valo 		    vif->type == NL80211_IFTYPE_ADHOC)) {
3575d8899132SKalle Valo 		ret = ath12k_station_assoc(ar, vif, sta, false);
3576d8899132SKalle Valo 		if (ret)
3577d8899132SKalle Valo 			ath12k_warn(ar->ab, "Failed to associate station: %pM\n",
3578d8899132SKalle Valo 				    sta->addr);
3579cbc0008cSAditya Kumar Singh 
3580cbc0008cSAditya Kumar Singh 		spin_lock_bh(&ar->data_lock);
3581cbc0008cSAditya Kumar Singh 
3582cbc0008cSAditya Kumar Singh 		arsta->bw = ath12k_mac_ieee80211_sta_bw_to_wmi(ar, sta);
3583cbc0008cSAditya Kumar Singh 		arsta->bw_prev = sta->deflink.bandwidth;
3584cbc0008cSAditya Kumar Singh 
3585cbc0008cSAditya Kumar Singh 		spin_unlock_bh(&ar->data_lock);
3586d8899132SKalle Valo 	} else if (old_state == IEEE80211_STA_ASSOC &&
3587d8899132SKalle Valo 		   new_state == IEEE80211_STA_AUTHORIZED) {
3588d8899132SKalle Valo 		spin_lock_bh(&ar->ab->base_lock);
3589d8899132SKalle Valo 
3590d8899132SKalle Valo 		peer = ath12k_peer_find(ar->ab, arvif->vdev_id, sta->addr);
3591d8899132SKalle Valo 		if (peer)
3592d8899132SKalle Valo 			peer->is_authorized = true;
3593d8899132SKalle Valo 
3594d8899132SKalle Valo 		spin_unlock_bh(&ar->ab->base_lock);
3595d8899132SKalle Valo 
3596d8899132SKalle Valo 		if (vif->type == NL80211_IFTYPE_STATION && arvif->is_up) {
3597d8899132SKalle Valo 			ret = ath12k_wmi_set_peer_param(ar, sta->addr,
3598d8899132SKalle Valo 							arvif->vdev_id,
3599d8899132SKalle Valo 							WMI_PEER_AUTHORIZE,
3600d8899132SKalle Valo 							1);
3601d8899132SKalle Valo 			if (ret)
3602d8899132SKalle Valo 				ath12k_warn(ar->ab, "Unable to authorize peer %pM vdev %d: %d\n",
3603d8899132SKalle Valo 					    sta->addr, arvif->vdev_id, ret);
3604d8899132SKalle Valo 		}
3605d8899132SKalle Valo 	} else if (old_state == IEEE80211_STA_AUTHORIZED &&
3606d8899132SKalle Valo 		   new_state == IEEE80211_STA_ASSOC) {
3607d8899132SKalle Valo 		spin_lock_bh(&ar->ab->base_lock);
3608d8899132SKalle Valo 
3609d8899132SKalle Valo 		peer = ath12k_peer_find(ar->ab, arvif->vdev_id, sta->addr);
3610d8899132SKalle Valo 		if (peer)
3611d8899132SKalle Valo 			peer->is_authorized = false;
3612d8899132SKalle Valo 
3613d8899132SKalle Valo 		spin_unlock_bh(&ar->ab->base_lock);
3614d8899132SKalle Valo 	} else if (old_state == IEEE80211_STA_ASSOC &&
3615d8899132SKalle Valo 		   new_state == IEEE80211_STA_AUTH &&
3616d8899132SKalle Valo 		   (vif->type == NL80211_IFTYPE_AP ||
3617d8899132SKalle Valo 		    vif->type == NL80211_IFTYPE_MESH_POINT ||
3618d8899132SKalle Valo 		    vif->type == NL80211_IFTYPE_ADHOC)) {
3619d8899132SKalle Valo 		ret = ath12k_station_disassoc(ar, vif, sta);
3620d8899132SKalle Valo 		if (ret)
3621d8899132SKalle Valo 			ath12k_warn(ar->ab, "Failed to disassociate station: %pM\n",
3622d8899132SKalle Valo 				    sta->addr);
3623d8899132SKalle Valo 	}
3624d8899132SKalle Valo 
3625d8899132SKalle Valo 	mutex_unlock(&ar->conf_mutex);
3626d8899132SKalle Valo 	return ret;
3627d8899132SKalle Valo }
3628d8899132SKalle Valo 
3629d8899132SKalle Valo static int ath12k_mac_op_sta_set_txpwr(struct ieee80211_hw *hw,
3630d8899132SKalle Valo 				       struct ieee80211_vif *vif,
3631d8899132SKalle Valo 				       struct ieee80211_sta *sta)
3632d8899132SKalle Valo {
3633d8899132SKalle Valo 	struct ath12k *ar = hw->priv;
3634d8899132SKalle Valo 	struct ath12k_vif *arvif = (void *)vif->drv_priv;
3635d8899132SKalle Valo 	int ret;
3636d8899132SKalle Valo 	s16 txpwr;
3637d8899132SKalle Valo 
3638d8899132SKalle Valo 	if (sta->deflink.txpwr.type == NL80211_TX_POWER_AUTOMATIC) {
3639d8899132SKalle Valo 		txpwr = 0;
3640d8899132SKalle Valo 	} else {
3641d8899132SKalle Valo 		txpwr = sta->deflink.txpwr.power;
3642d8899132SKalle Valo 		if (!txpwr)
3643d8899132SKalle Valo 			return -EINVAL;
3644d8899132SKalle Valo 	}
3645d8899132SKalle Valo 
3646d8899132SKalle Valo 	if (txpwr > ATH12K_TX_POWER_MAX_VAL || txpwr < ATH12K_TX_POWER_MIN_VAL)
3647d8899132SKalle Valo 		return -EINVAL;
3648d8899132SKalle Valo 
3649d8899132SKalle Valo 	mutex_lock(&ar->conf_mutex);
3650d8899132SKalle Valo 
3651d8899132SKalle Valo 	ret = ath12k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,
3652d8899132SKalle Valo 					WMI_PEER_USE_FIXED_PWR, txpwr);
3653d8899132SKalle Valo 	if (ret) {
3654d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to set tx power for station ret: %d\n",
3655d8899132SKalle Valo 			    ret);
3656d8899132SKalle Valo 		goto out;
3657d8899132SKalle Valo 	}
3658d8899132SKalle Valo 
3659d8899132SKalle Valo out:
3660d8899132SKalle Valo 	mutex_unlock(&ar->conf_mutex);
3661d8899132SKalle Valo 	return ret;
3662d8899132SKalle Valo }
3663d8899132SKalle Valo 
3664d8899132SKalle Valo static void ath12k_mac_op_sta_rc_update(struct ieee80211_hw *hw,
3665d8899132SKalle Valo 					struct ieee80211_vif *vif,
3666d8899132SKalle Valo 					struct ieee80211_sta *sta,
3667d8899132SKalle Valo 					u32 changed)
3668d8899132SKalle Valo {
3669d8899132SKalle Valo 	struct ath12k *ar = hw->priv;
3670d8899132SKalle Valo 	struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv;
3671d8899132SKalle Valo 	struct ath12k_vif *arvif = (void *)vif->drv_priv;
3672d8899132SKalle Valo 	struct ath12k_peer *peer;
3673d8899132SKalle Valo 	u32 bw, smps;
3674d8899132SKalle Valo 
3675d8899132SKalle Valo 	spin_lock_bh(&ar->ab->base_lock);
3676d8899132SKalle Valo 
3677d8899132SKalle Valo 	peer = ath12k_peer_find(ar->ab, arvif->vdev_id, sta->addr);
3678d8899132SKalle Valo 	if (!peer) {
3679d8899132SKalle Valo 		spin_unlock_bh(&ar->ab->base_lock);
3680d8899132SKalle Valo 		ath12k_warn(ar->ab, "mac sta rc update failed to find peer %pM on vdev %i\n",
3681d8899132SKalle Valo 			    sta->addr, arvif->vdev_id);
3682d8899132SKalle Valo 		return;
3683d8899132SKalle Valo 	}
3684d8899132SKalle Valo 
3685d8899132SKalle Valo 	spin_unlock_bh(&ar->ab->base_lock);
3686d8899132SKalle Valo 
3687d8899132SKalle Valo 	ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
3688d8899132SKalle Valo 		   "mac sta rc update for %pM changed %08x bw %d nss %d smps %d\n",
3689d8899132SKalle Valo 		   sta->addr, changed, sta->deflink.bandwidth, sta->deflink.rx_nss,
3690d8899132SKalle Valo 		   sta->deflink.smps_mode);
3691d8899132SKalle Valo 
3692d8899132SKalle Valo 	spin_lock_bh(&ar->data_lock);
3693d8899132SKalle Valo 
3694d8899132SKalle Valo 	if (changed & IEEE80211_RC_BW_CHANGED) {
3695cbc0008cSAditya Kumar Singh 		bw = ath12k_mac_ieee80211_sta_bw_to_wmi(ar, sta);
3696cbc0008cSAditya Kumar Singh 		arsta->bw_prev = arsta->bw;
3697d8899132SKalle Valo 		arsta->bw = bw;
3698d8899132SKalle Valo 	}
3699d8899132SKalle Valo 
3700d8899132SKalle Valo 	if (changed & IEEE80211_RC_NSS_CHANGED)
3701d8899132SKalle Valo 		arsta->nss = sta->deflink.rx_nss;
3702d8899132SKalle Valo 
3703d8899132SKalle Valo 	if (changed & IEEE80211_RC_SMPS_CHANGED) {
3704d8899132SKalle Valo 		smps = WMI_PEER_SMPS_PS_NONE;
3705d8899132SKalle Valo 
3706d8899132SKalle Valo 		switch (sta->deflink.smps_mode) {
3707d8899132SKalle Valo 		case IEEE80211_SMPS_AUTOMATIC:
3708d8899132SKalle Valo 		case IEEE80211_SMPS_OFF:
3709d8899132SKalle Valo 			smps = WMI_PEER_SMPS_PS_NONE;
3710d8899132SKalle Valo 			break;
3711d8899132SKalle Valo 		case IEEE80211_SMPS_STATIC:
3712d8899132SKalle Valo 			smps = WMI_PEER_SMPS_STATIC;
3713d8899132SKalle Valo 			break;
3714d8899132SKalle Valo 		case IEEE80211_SMPS_DYNAMIC:
3715d8899132SKalle Valo 			smps = WMI_PEER_SMPS_DYNAMIC;
3716d8899132SKalle Valo 			break;
3717d8899132SKalle Valo 		default:
3718d8899132SKalle Valo 			ath12k_warn(ar->ab, "Invalid smps %d in sta rc update for %pM\n",
3719d8899132SKalle Valo 				    sta->deflink.smps_mode, sta->addr);
3720d8899132SKalle Valo 			smps = WMI_PEER_SMPS_PS_NONE;
3721d8899132SKalle Valo 			break;
3722d8899132SKalle Valo 		}
3723d8899132SKalle Valo 
3724d8899132SKalle Valo 		arsta->smps = smps;
3725d8899132SKalle Valo 	}
3726d8899132SKalle Valo 
3727d8899132SKalle Valo 	arsta->changed |= changed;
3728d8899132SKalle Valo 
3729d8899132SKalle Valo 	spin_unlock_bh(&ar->data_lock);
3730d8899132SKalle Valo 
3731d8899132SKalle Valo 	ieee80211_queue_work(hw, &arsta->update_wk);
3732d8899132SKalle Valo }
3733d8899132SKalle Valo 
3734d8899132SKalle Valo static int ath12k_conf_tx_uapsd(struct ath12k *ar, struct ieee80211_vif *vif,
3735d8899132SKalle Valo 				u16 ac, bool enable)
3736d8899132SKalle Valo {
3737d8899132SKalle Valo 	struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
3738d8899132SKalle Valo 	u32 value;
3739d8899132SKalle Valo 	int ret;
3740d8899132SKalle Valo 
3741d8899132SKalle Valo 	if (arvif->vdev_type != WMI_VDEV_TYPE_STA)
3742d8899132SKalle Valo 		return 0;
3743d8899132SKalle Valo 
3744d8899132SKalle Valo 	switch (ac) {
3745d8899132SKalle Valo 	case IEEE80211_AC_VO:
3746d8899132SKalle Valo 		value = WMI_STA_PS_UAPSD_AC3_DELIVERY_EN |
3747d8899132SKalle Valo 			WMI_STA_PS_UAPSD_AC3_TRIGGER_EN;
3748d8899132SKalle Valo 		break;
3749d8899132SKalle Valo 	case IEEE80211_AC_VI:
3750d8899132SKalle Valo 		value = WMI_STA_PS_UAPSD_AC2_DELIVERY_EN |
3751d8899132SKalle Valo 			WMI_STA_PS_UAPSD_AC2_TRIGGER_EN;
3752d8899132SKalle Valo 		break;
3753d8899132SKalle Valo 	case IEEE80211_AC_BE:
3754d8899132SKalle Valo 		value = WMI_STA_PS_UAPSD_AC1_DELIVERY_EN |
3755d8899132SKalle Valo 			WMI_STA_PS_UAPSD_AC1_TRIGGER_EN;
3756d8899132SKalle Valo 		break;
3757d8899132SKalle Valo 	case IEEE80211_AC_BK:
3758d8899132SKalle Valo 		value = WMI_STA_PS_UAPSD_AC0_DELIVERY_EN |
3759d8899132SKalle Valo 			WMI_STA_PS_UAPSD_AC0_TRIGGER_EN;
3760d8899132SKalle Valo 		break;
3761d8899132SKalle Valo 	}
3762d8899132SKalle Valo 
3763d8899132SKalle Valo 	if (enable)
3764d8899132SKalle Valo 		arvif->u.sta.uapsd |= value;
3765d8899132SKalle Valo 	else
3766d8899132SKalle Valo 		arvif->u.sta.uapsd &= ~value;
3767d8899132SKalle Valo 
3768d8899132SKalle Valo 	ret = ath12k_wmi_set_sta_ps_param(ar, arvif->vdev_id,
3769d8899132SKalle Valo 					  WMI_STA_PS_PARAM_UAPSD,
3770d8899132SKalle Valo 					  arvif->u.sta.uapsd);
3771d8899132SKalle Valo 	if (ret) {
3772d8899132SKalle Valo 		ath12k_warn(ar->ab, "could not set uapsd params %d\n", ret);
3773d8899132SKalle Valo 		goto exit;
3774d8899132SKalle Valo 	}
3775d8899132SKalle Valo 
3776d8899132SKalle Valo 	if (arvif->u.sta.uapsd)
3777d8899132SKalle Valo 		value = WMI_STA_PS_RX_WAKE_POLICY_POLL_UAPSD;
3778d8899132SKalle Valo 	else
3779d8899132SKalle Valo 		value = WMI_STA_PS_RX_WAKE_POLICY_WAKE;
3780d8899132SKalle Valo 
3781d8899132SKalle Valo 	ret = ath12k_wmi_set_sta_ps_param(ar, arvif->vdev_id,
3782d8899132SKalle Valo 					  WMI_STA_PS_PARAM_RX_WAKE_POLICY,
3783d8899132SKalle Valo 					  value);
3784d8899132SKalle Valo 	if (ret)
3785d8899132SKalle Valo 		ath12k_warn(ar->ab, "could not set rx wake param %d\n", ret);
3786d8899132SKalle Valo 
3787d8899132SKalle Valo exit:
3788d8899132SKalle Valo 	return ret;
3789d8899132SKalle Valo }
3790d8899132SKalle Valo 
3791d8899132SKalle Valo static int ath12k_mac_op_conf_tx(struct ieee80211_hw *hw,
3792d8899132SKalle Valo 				 struct ieee80211_vif *vif,
3793d8899132SKalle Valo 				 unsigned int link_id, u16 ac,
3794d8899132SKalle Valo 				 const struct ieee80211_tx_queue_params *params)
3795d8899132SKalle Valo {
3796d8899132SKalle Valo 	struct ath12k *ar = hw->priv;
3797d8899132SKalle Valo 	struct ath12k_vif *arvif = (void *)vif->drv_priv;
3798d8899132SKalle Valo 	struct wmi_wmm_params_arg *p = NULL;
3799d8899132SKalle Valo 	int ret;
3800d8899132SKalle Valo 
3801d8899132SKalle Valo 	mutex_lock(&ar->conf_mutex);
3802d8899132SKalle Valo 
3803d8899132SKalle Valo 	switch (ac) {
3804d8899132SKalle Valo 	case IEEE80211_AC_VO:
3805d8899132SKalle Valo 		p = &arvif->wmm_params.ac_vo;
3806d8899132SKalle Valo 		break;
3807d8899132SKalle Valo 	case IEEE80211_AC_VI:
3808d8899132SKalle Valo 		p = &arvif->wmm_params.ac_vi;
3809d8899132SKalle Valo 		break;
3810d8899132SKalle Valo 	case IEEE80211_AC_BE:
3811d8899132SKalle Valo 		p = &arvif->wmm_params.ac_be;
3812d8899132SKalle Valo 		break;
3813d8899132SKalle Valo 	case IEEE80211_AC_BK:
3814d8899132SKalle Valo 		p = &arvif->wmm_params.ac_bk;
3815d8899132SKalle Valo 		break;
3816d8899132SKalle Valo 	}
3817d8899132SKalle Valo 
3818d8899132SKalle Valo 	if (WARN_ON(!p)) {
3819d8899132SKalle Valo 		ret = -EINVAL;
3820d8899132SKalle Valo 		goto exit;
3821d8899132SKalle Valo 	}
3822d8899132SKalle Valo 
3823d8899132SKalle Valo 	p->cwmin = params->cw_min;
3824d8899132SKalle Valo 	p->cwmax = params->cw_max;
3825d8899132SKalle Valo 	p->aifs = params->aifs;
3826d8899132SKalle Valo 	p->txop = params->txop;
3827d8899132SKalle Valo 
3828d8899132SKalle Valo 	ret = ath12k_wmi_send_wmm_update_cmd(ar, arvif->vdev_id,
3829d8899132SKalle Valo 					     &arvif->wmm_params);
3830d8899132SKalle Valo 	if (ret) {
3831d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to set wmm params: %d\n", ret);
3832d8899132SKalle Valo 		goto exit;
3833d8899132SKalle Valo 	}
3834d8899132SKalle Valo 
3835d8899132SKalle Valo 	ret = ath12k_conf_tx_uapsd(ar, vif, ac, params->uapsd);
3836d8899132SKalle Valo 
3837d8899132SKalle Valo 	if (ret)
3838d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to set sta uapsd: %d\n", ret);
3839d8899132SKalle Valo 
3840d8899132SKalle Valo exit:
3841d8899132SKalle Valo 	mutex_unlock(&ar->conf_mutex);
3842d8899132SKalle Valo 	return ret;
3843d8899132SKalle Valo }
3844d8899132SKalle Valo 
3845d8899132SKalle Valo static struct ieee80211_sta_ht_cap
3846d8899132SKalle Valo ath12k_create_ht_cap(struct ath12k *ar, u32 ar_ht_cap, u32 rate_cap_rx_chainmask)
3847d8899132SKalle Valo {
3848d8899132SKalle Valo 	int i;
3849d8899132SKalle Valo 	struct ieee80211_sta_ht_cap ht_cap = {0};
3850d8899132SKalle Valo 	u32 ar_vht_cap = ar->pdev->cap.vht_cap;
3851d8899132SKalle Valo 
3852d8899132SKalle Valo 	if (!(ar_ht_cap & WMI_HT_CAP_ENABLED))
3853d8899132SKalle Valo 		return ht_cap;
3854d8899132SKalle Valo 
3855d8899132SKalle Valo 	ht_cap.ht_supported = 1;
3856d8899132SKalle Valo 	ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
3857d8899132SKalle Valo 	ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE;
3858d8899132SKalle Valo 	ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
3859d8899132SKalle Valo 	ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40;
3860d8899132SKalle Valo 	ht_cap.cap |= WLAN_HT_CAP_SM_PS_STATIC << IEEE80211_HT_CAP_SM_PS_SHIFT;
3861d8899132SKalle Valo 
3862d8899132SKalle Valo 	if (ar_ht_cap & WMI_HT_CAP_HT20_SGI)
3863d8899132SKalle Valo 		ht_cap.cap |= IEEE80211_HT_CAP_SGI_20;
3864d8899132SKalle Valo 
3865d8899132SKalle Valo 	if (ar_ht_cap & WMI_HT_CAP_HT40_SGI)
3866d8899132SKalle Valo 		ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
3867d8899132SKalle Valo 
3868d8899132SKalle Valo 	if (ar_ht_cap & WMI_HT_CAP_DYNAMIC_SMPS) {
3869d8899132SKalle Valo 		u32 smps;
3870d8899132SKalle Valo 
3871d8899132SKalle Valo 		smps   = WLAN_HT_CAP_SM_PS_DYNAMIC;
3872d8899132SKalle Valo 		smps <<= IEEE80211_HT_CAP_SM_PS_SHIFT;
3873d8899132SKalle Valo 
3874d8899132SKalle Valo 		ht_cap.cap |= smps;
3875d8899132SKalle Valo 	}
3876d8899132SKalle Valo 
3877d8899132SKalle Valo 	if (ar_ht_cap & WMI_HT_CAP_TX_STBC)
3878d8899132SKalle Valo 		ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC;
3879d8899132SKalle Valo 
3880d8899132SKalle Valo 	if (ar_ht_cap & WMI_HT_CAP_RX_STBC) {
3881d8899132SKalle Valo 		u32 stbc;
3882d8899132SKalle Valo 
3883d8899132SKalle Valo 		stbc   = ar_ht_cap;
3884d8899132SKalle Valo 		stbc  &= WMI_HT_CAP_RX_STBC;
3885d8899132SKalle Valo 		stbc >>= WMI_HT_CAP_RX_STBC_MASK_SHIFT;
3886d8899132SKalle Valo 		stbc <<= IEEE80211_HT_CAP_RX_STBC_SHIFT;
3887d8899132SKalle Valo 		stbc  &= IEEE80211_HT_CAP_RX_STBC;
3888d8899132SKalle Valo 
3889d8899132SKalle Valo 		ht_cap.cap |= stbc;
3890d8899132SKalle Valo 	}
3891d8899132SKalle Valo 
3892d8899132SKalle Valo 	if (ar_ht_cap & WMI_HT_CAP_RX_LDPC)
3893d8899132SKalle Valo 		ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING;
3894d8899132SKalle Valo 
3895d8899132SKalle Valo 	if (ar_ht_cap & WMI_HT_CAP_L_SIG_TXOP_PROT)
3896d8899132SKalle Valo 		ht_cap.cap |= IEEE80211_HT_CAP_LSIG_TXOP_PROT;
3897d8899132SKalle Valo 
3898d8899132SKalle Valo 	if (ar_vht_cap & WMI_VHT_CAP_MAX_MPDU_LEN_MASK)
3899d8899132SKalle Valo 		ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU;
3900d8899132SKalle Valo 
3901d8899132SKalle Valo 	for (i = 0; i < ar->num_rx_chains; i++) {
3902d8899132SKalle Valo 		if (rate_cap_rx_chainmask & BIT(i))
3903d8899132SKalle Valo 			ht_cap.mcs.rx_mask[i] = 0xFF;
3904d8899132SKalle Valo 	}
3905d8899132SKalle Valo 
3906d8899132SKalle Valo 	ht_cap.mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
3907d8899132SKalle Valo 
3908d8899132SKalle Valo 	return ht_cap;
3909d8899132SKalle Valo }
3910d8899132SKalle Valo 
3911d8899132SKalle Valo static int ath12k_mac_set_txbf_conf(struct ath12k_vif *arvif)
3912d8899132SKalle Valo {
3913d8899132SKalle Valo 	u32 value = 0;
3914d8899132SKalle Valo 	struct ath12k *ar = arvif->ar;
3915d8899132SKalle Valo 	int nsts;
3916d8899132SKalle Valo 	int sound_dim;
3917d8899132SKalle Valo 	u32 vht_cap = ar->pdev->cap.vht_cap;
3918d8899132SKalle Valo 	u32 vdev_param = WMI_VDEV_PARAM_TXBF;
3919d8899132SKalle Valo 
3920d8899132SKalle Valo 	if (vht_cap & (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE)) {
3921d8899132SKalle Valo 		nsts = vht_cap & IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK;
3922d8899132SKalle Valo 		nsts >>= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT;
3923d8899132SKalle Valo 		value |= SM(nsts, WMI_TXBF_STS_CAP_OFFSET);
3924d8899132SKalle Valo 	}
3925d8899132SKalle Valo 
3926d8899132SKalle Valo 	if (vht_cap & (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)) {
3927d8899132SKalle Valo 		sound_dim = vht_cap &
3928d8899132SKalle Valo 			    IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK;
3929d8899132SKalle Valo 		sound_dim >>= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT;
3930d8899132SKalle Valo 		if (sound_dim > (ar->num_tx_chains - 1))
3931d8899132SKalle Valo 			sound_dim = ar->num_tx_chains - 1;
3932d8899132SKalle Valo 		value |= SM(sound_dim, WMI_BF_SOUND_DIM_OFFSET);
3933d8899132SKalle Valo 	}
3934d8899132SKalle Valo 
3935d8899132SKalle Valo 	if (!value)
3936d8899132SKalle Valo 		return 0;
3937d8899132SKalle Valo 
3938d8899132SKalle Valo 	if (vht_cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE) {
3939d8899132SKalle Valo 		value |= WMI_VDEV_PARAM_TXBF_SU_TX_BFER;
3940d8899132SKalle Valo 
3941d8899132SKalle Valo 		if ((vht_cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) &&
3942d8899132SKalle Valo 		    arvif->vdev_type == WMI_VDEV_TYPE_AP)
3943d8899132SKalle Valo 			value |= WMI_VDEV_PARAM_TXBF_MU_TX_BFER;
3944d8899132SKalle Valo 	}
3945d8899132SKalle Valo 
3946d8899132SKalle Valo 	if (vht_cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE) {
3947d8899132SKalle Valo 		value |= WMI_VDEV_PARAM_TXBF_SU_TX_BFEE;
3948d8899132SKalle Valo 
3949d8899132SKalle Valo 		if ((vht_cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE) &&
3950d8899132SKalle Valo 		    arvif->vdev_type == WMI_VDEV_TYPE_STA)
3951d8899132SKalle Valo 			value |= WMI_VDEV_PARAM_TXBF_MU_TX_BFEE;
3952d8899132SKalle Valo 	}
3953d8899132SKalle Valo 
3954d8899132SKalle Valo 	return ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
3955d8899132SKalle Valo 					     vdev_param, value);
3956d8899132SKalle Valo }
3957d8899132SKalle Valo 
3958d8899132SKalle Valo static void ath12k_set_vht_txbf_cap(struct ath12k *ar, u32 *vht_cap)
3959d8899132SKalle Valo {
3960d8899132SKalle Valo 	bool subfer, subfee;
3961d8899132SKalle Valo 	int sound_dim = 0;
3962d8899132SKalle Valo 
3963d8899132SKalle Valo 	subfer = !!(*vht_cap & (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE));
3964d8899132SKalle Valo 	subfee = !!(*vht_cap & (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE));
3965d8899132SKalle Valo 
3966d8899132SKalle Valo 	if (ar->num_tx_chains < 2) {
3967d8899132SKalle Valo 		*vht_cap &= ~(IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE);
3968d8899132SKalle Valo 		subfer = false;
3969d8899132SKalle Valo 	}
3970d8899132SKalle Valo 
3971d8899132SKalle Valo 	/* If SU Beaformer is not set, then disable MU Beamformer Capability */
3972d8899132SKalle Valo 	if (!subfer)
3973d8899132SKalle Valo 		*vht_cap &= ~(IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE);
3974d8899132SKalle Valo 
3975d8899132SKalle Valo 	/* If SU Beaformee is not set, then disable MU Beamformee Capability */
3976d8899132SKalle Valo 	if (!subfee)
3977d8899132SKalle Valo 		*vht_cap &= ~(IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE);
3978d8899132SKalle Valo 
3979d8899132SKalle Valo 	sound_dim = u32_get_bits(*vht_cap,
3980d8899132SKalle Valo 				 IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK);
3981d8899132SKalle Valo 	*vht_cap = u32_replace_bits(*vht_cap, 0,
3982d8899132SKalle Valo 				    IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK);
3983d8899132SKalle Valo 
3984d8899132SKalle Valo 	/* TODO: Need to check invalid STS and Sound_dim values set by FW? */
3985d8899132SKalle Valo 
3986d8899132SKalle Valo 	/* Enable Sounding Dimension Field only if SU BF is enabled */
3987d8899132SKalle Valo 	if (subfer) {
3988d8899132SKalle Valo 		if (sound_dim > (ar->num_tx_chains - 1))
3989d8899132SKalle Valo 			sound_dim = ar->num_tx_chains - 1;
3990d8899132SKalle Valo 
3991d8899132SKalle Valo 		*vht_cap = u32_replace_bits(*vht_cap, sound_dim,
3992d8899132SKalle Valo 					    IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK);
3993d8899132SKalle Valo 	}
3994d8899132SKalle Valo 
3995d8899132SKalle Valo 	/* Use the STS advertised by FW unless SU Beamformee is not supported*/
3996d8899132SKalle Valo 	if (!subfee)
3997d8899132SKalle Valo 		*vht_cap &= ~(IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK);
3998d8899132SKalle Valo }
3999d8899132SKalle Valo 
4000d8899132SKalle Valo static struct ieee80211_sta_vht_cap
4001d8899132SKalle Valo ath12k_create_vht_cap(struct ath12k *ar, u32 rate_cap_tx_chainmask,
4002d8899132SKalle Valo 		      u32 rate_cap_rx_chainmask)
4003d8899132SKalle Valo {
4004d8899132SKalle Valo 	struct ieee80211_sta_vht_cap vht_cap = {0};
4005d8899132SKalle Valo 	u16 txmcs_map, rxmcs_map;
4006d8899132SKalle Valo 	int i;
4007d8899132SKalle Valo 
4008d8899132SKalle Valo 	vht_cap.vht_supported = 1;
4009d8899132SKalle Valo 	vht_cap.cap = ar->pdev->cap.vht_cap;
4010d8899132SKalle Valo 
4011d8899132SKalle Valo 	ath12k_set_vht_txbf_cap(ar, &vht_cap.cap);
4012d8899132SKalle Valo 
4013d8899132SKalle Valo 	/* TODO: Enable back VHT160 mode once association issues are fixed */
4014d8899132SKalle Valo 	/* Disabling VHT160 and VHT80+80 modes */
4015d8899132SKalle Valo 	vht_cap.cap &= ~IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
4016d8899132SKalle Valo 	vht_cap.cap &= ~IEEE80211_VHT_CAP_SHORT_GI_160;
4017d8899132SKalle Valo 
4018d8899132SKalle Valo 	rxmcs_map = 0;
4019d8899132SKalle Valo 	txmcs_map = 0;
4020d8899132SKalle Valo 	for (i = 0; i < 8; i++) {
4021d8899132SKalle Valo 		if (i < ar->num_tx_chains && rate_cap_tx_chainmask & BIT(i))
4022d8899132SKalle Valo 			txmcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i * 2);
4023d8899132SKalle Valo 		else
4024d8899132SKalle Valo 			txmcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i * 2);
4025d8899132SKalle Valo 
4026d8899132SKalle Valo 		if (i < ar->num_rx_chains && rate_cap_rx_chainmask & BIT(i))
4027d8899132SKalle Valo 			rxmcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i * 2);
4028d8899132SKalle Valo 		else
4029d8899132SKalle Valo 			rxmcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i * 2);
4030d8899132SKalle Valo 	}
4031d8899132SKalle Valo 
4032d8899132SKalle Valo 	if (rate_cap_tx_chainmask <= 1)
4033d8899132SKalle Valo 		vht_cap.cap &= ~IEEE80211_VHT_CAP_TXSTBC;
4034d8899132SKalle Valo 
4035d8899132SKalle Valo 	vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(rxmcs_map);
4036d8899132SKalle Valo 	vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(txmcs_map);
4037d8899132SKalle Valo 
4038d8899132SKalle Valo 	return vht_cap;
4039d8899132SKalle Valo }
4040d8899132SKalle Valo 
4041d8899132SKalle Valo static void ath12k_mac_setup_ht_vht_cap(struct ath12k *ar,
4042d8899132SKalle Valo 					struct ath12k_pdev_cap *cap,
4043d8899132SKalle Valo 					u32 *ht_cap_info)
4044d8899132SKalle Valo {
4045d8899132SKalle Valo 	struct ieee80211_supported_band *band;
4046d8899132SKalle Valo 	u32 rate_cap_tx_chainmask;
4047d8899132SKalle Valo 	u32 rate_cap_rx_chainmask;
4048d8899132SKalle Valo 	u32 ht_cap;
4049d8899132SKalle Valo 
4050d8899132SKalle Valo 	rate_cap_tx_chainmask = ar->cfg_tx_chainmask >> cap->tx_chain_mask_shift;
4051d8899132SKalle Valo 	rate_cap_rx_chainmask = ar->cfg_rx_chainmask >> cap->rx_chain_mask_shift;
4052d8899132SKalle Valo 
4053d8899132SKalle Valo 	if (cap->supported_bands & WMI_HOST_WLAN_2G_CAP) {
4054d8899132SKalle Valo 		band = &ar->mac.sbands[NL80211_BAND_2GHZ];
4055d8899132SKalle Valo 		ht_cap = cap->band[NL80211_BAND_2GHZ].ht_cap_info;
4056d8899132SKalle Valo 		if (ht_cap_info)
4057d8899132SKalle Valo 			*ht_cap_info = ht_cap;
4058d8899132SKalle Valo 		band->ht_cap = ath12k_create_ht_cap(ar, ht_cap,
4059d8899132SKalle Valo 						    rate_cap_rx_chainmask);
4060d8899132SKalle Valo 	}
4061d8899132SKalle Valo 
4062d8899132SKalle Valo 	if (cap->supported_bands & WMI_HOST_WLAN_5G_CAP &&
4063d8899132SKalle Valo 	    (ar->ab->hw_params->single_pdev_only ||
4064d8899132SKalle Valo 	     !ar->supports_6ghz)) {
4065d8899132SKalle Valo 		band = &ar->mac.sbands[NL80211_BAND_5GHZ];
4066d8899132SKalle Valo 		ht_cap = cap->band[NL80211_BAND_5GHZ].ht_cap_info;
4067d8899132SKalle Valo 		if (ht_cap_info)
4068d8899132SKalle Valo 			*ht_cap_info = ht_cap;
4069d8899132SKalle Valo 		band->ht_cap = ath12k_create_ht_cap(ar, ht_cap,
4070d8899132SKalle Valo 						    rate_cap_rx_chainmask);
4071d8899132SKalle Valo 		band->vht_cap = ath12k_create_vht_cap(ar, rate_cap_tx_chainmask,
4072d8899132SKalle Valo 						      rate_cap_rx_chainmask);
4073d8899132SKalle Valo 	}
4074d8899132SKalle Valo }
4075d8899132SKalle Valo 
4076d8899132SKalle Valo static int ath12k_check_chain_mask(struct ath12k *ar, u32 ant, bool is_tx_ant)
4077d8899132SKalle Valo {
4078d8899132SKalle Valo 	/* TODO: Check the request chainmask against the supported
4079d8899132SKalle Valo 	 * chainmask table which is advertised in extented_service_ready event
4080d8899132SKalle Valo 	 */
4081d8899132SKalle Valo 
4082d8899132SKalle Valo 	return 0;
4083d8899132SKalle Valo }
4084d8899132SKalle Valo 
4085d8899132SKalle Valo static void ath12k_gen_ppe_thresh(struct ath12k_wmi_ppe_threshold_arg *fw_ppet,
4086d8899132SKalle Valo 				  u8 *he_ppet)
4087d8899132SKalle Valo {
4088d8899132SKalle Valo 	int nss, ru;
4089d8899132SKalle Valo 	u8 bit = 7;
4090d8899132SKalle Valo 
4091d8899132SKalle Valo 	he_ppet[0] = fw_ppet->numss_m1 & IEEE80211_PPE_THRES_NSS_MASK;
4092d8899132SKalle Valo 	he_ppet[0] |= (fw_ppet->ru_bit_mask <<
4093d8899132SKalle Valo 		       IEEE80211_PPE_THRES_RU_INDEX_BITMASK_POS) &
4094d8899132SKalle Valo 		      IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK;
4095d8899132SKalle Valo 	for (nss = 0; nss <= fw_ppet->numss_m1; nss++) {
4096d8899132SKalle Valo 		for (ru = 0; ru < 4; ru++) {
4097d8899132SKalle Valo 			u8 val;
4098d8899132SKalle Valo 			int i;
4099d8899132SKalle Valo 
4100d8899132SKalle Valo 			if ((fw_ppet->ru_bit_mask & BIT(ru)) == 0)
4101d8899132SKalle Valo 				continue;
4102d8899132SKalle Valo 			val = (fw_ppet->ppet16_ppet8_ru3_ru0[nss] >> (ru * 6)) &
4103d8899132SKalle Valo 			       0x3f;
4104d8899132SKalle Valo 			val = ((val >> 3) & 0x7) | ((val & 0x7) << 3);
4105d8899132SKalle Valo 			for (i = 5; i >= 0; i--) {
4106d8899132SKalle Valo 				he_ppet[bit / 8] |=
4107d8899132SKalle Valo 					((val >> i) & 0x1) << ((bit % 8));
4108d8899132SKalle Valo 				bit++;
4109d8899132SKalle Valo 			}
4110d8899132SKalle Valo 		}
4111d8899132SKalle Valo 	}
4112d8899132SKalle Valo }
4113d8899132SKalle Valo 
4114d8899132SKalle Valo static void
4115d8899132SKalle Valo ath12k_mac_filter_he_cap_mesh(struct ieee80211_he_cap_elem *he_cap_elem)
4116d8899132SKalle Valo {
4117d8899132SKalle Valo 	u8 m;
4118d8899132SKalle Valo 
4119d8899132SKalle Valo 	m = IEEE80211_HE_MAC_CAP0_TWT_RES |
4120d8899132SKalle Valo 	    IEEE80211_HE_MAC_CAP0_TWT_REQ;
4121d8899132SKalle Valo 	he_cap_elem->mac_cap_info[0] &= ~m;
4122d8899132SKalle Valo 
4123d8899132SKalle Valo 	m = IEEE80211_HE_MAC_CAP2_TRS |
4124d8899132SKalle Valo 	    IEEE80211_HE_MAC_CAP2_BCAST_TWT |
4125d8899132SKalle Valo 	    IEEE80211_HE_MAC_CAP2_MU_CASCADING;
4126d8899132SKalle Valo 	he_cap_elem->mac_cap_info[2] &= ~m;
4127d8899132SKalle Valo 
4128d8899132SKalle Valo 	m = IEEE80211_HE_MAC_CAP3_FLEX_TWT_SCHED |
4129d8899132SKalle Valo 	    IEEE80211_HE_MAC_CAP2_BCAST_TWT |
4130d8899132SKalle Valo 	    IEEE80211_HE_MAC_CAP2_MU_CASCADING;
4131d8899132SKalle Valo 	he_cap_elem->mac_cap_info[3] &= ~m;
4132d8899132SKalle Valo 
4133d8899132SKalle Valo 	m = IEEE80211_HE_MAC_CAP4_BSRP_BQRP_A_MPDU_AGG |
4134d8899132SKalle Valo 	    IEEE80211_HE_MAC_CAP4_BQR;
4135d8899132SKalle Valo 	he_cap_elem->mac_cap_info[4] &= ~m;
4136d8899132SKalle Valo 
4137d8899132SKalle Valo 	m = IEEE80211_HE_MAC_CAP5_SUBCHAN_SELECTIVE_TRANSMISSION |
4138d8899132SKalle Valo 	    IEEE80211_HE_MAC_CAP5_UL_2x996_TONE_RU |
4139d8899132SKalle Valo 	    IEEE80211_HE_MAC_CAP5_PUNCTURED_SOUNDING |
4140d8899132SKalle Valo 	    IEEE80211_HE_MAC_CAP5_HT_VHT_TRIG_FRAME_RX;
4141d8899132SKalle Valo 	he_cap_elem->mac_cap_info[5] &= ~m;
4142d8899132SKalle Valo 
4143d8899132SKalle Valo 	m = IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO |
4144d8899132SKalle Valo 	    IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO;
4145d8899132SKalle Valo 	he_cap_elem->phy_cap_info[2] &= ~m;
4146d8899132SKalle Valo 
4147d8899132SKalle Valo 	m = IEEE80211_HE_PHY_CAP3_RX_PARTIAL_BW_SU_IN_20MHZ_MU |
4148d8899132SKalle Valo 	    IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_MASK |
4149d8899132SKalle Valo 	    IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_MASK;
4150d8899132SKalle Valo 	he_cap_elem->phy_cap_info[3] &= ~m;
4151d8899132SKalle Valo 
4152d8899132SKalle Valo 	m = IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER;
4153d8899132SKalle Valo 	he_cap_elem->phy_cap_info[4] &= ~m;
4154d8899132SKalle Valo 
4155d8899132SKalle Valo 	m = IEEE80211_HE_PHY_CAP5_NG16_MU_FEEDBACK;
4156d8899132SKalle Valo 	he_cap_elem->phy_cap_info[5] &= ~m;
4157d8899132SKalle Valo 
4158d8899132SKalle Valo 	m = IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU |
4159d8899132SKalle Valo 	    IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMING_PARTIAL_BW_FB |
4160d8899132SKalle Valo 	    IEEE80211_HE_PHY_CAP6_TRIG_CQI_FB |
4161d8899132SKalle Valo 	    IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO;
4162d8899132SKalle Valo 	he_cap_elem->phy_cap_info[6] &= ~m;
4163d8899132SKalle Valo 
4164d8899132SKalle Valo 	m = IEEE80211_HE_PHY_CAP7_PSR_BASED_SR |
4165d8899132SKalle Valo 	    IEEE80211_HE_PHY_CAP7_POWER_BOOST_FACTOR_SUPP |
4166d8899132SKalle Valo 	    IEEE80211_HE_PHY_CAP7_STBC_TX_ABOVE_80MHZ |
4167d8899132SKalle Valo 	    IEEE80211_HE_PHY_CAP7_STBC_RX_ABOVE_80MHZ;
4168d8899132SKalle Valo 	he_cap_elem->phy_cap_info[7] &= ~m;
4169d8899132SKalle Valo 
4170d8899132SKalle Valo 	m = IEEE80211_HE_PHY_CAP8_HE_ER_SU_PPDU_4XLTF_AND_08_US_GI |
4171d8899132SKalle Valo 	    IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G |
4172d8899132SKalle Valo 	    IEEE80211_HE_PHY_CAP8_20MHZ_IN_160MHZ_HE_PPDU |
4173d8899132SKalle Valo 	    IEEE80211_HE_PHY_CAP8_80MHZ_IN_160MHZ_HE_PPDU;
4174d8899132SKalle Valo 	he_cap_elem->phy_cap_info[8] &= ~m;
4175d8899132SKalle Valo 
4176d8899132SKalle Valo 	m = IEEE80211_HE_PHY_CAP9_LONGER_THAN_16_SIGB_OFDM_SYM |
4177d8899132SKalle Valo 	    IEEE80211_HE_PHY_CAP9_NON_TRIGGERED_CQI_FEEDBACK |
4178d8899132SKalle Valo 	    IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU |
4179d8899132SKalle Valo 	    IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU |
4180d8899132SKalle Valo 	    IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB |
4181d8899132SKalle Valo 	    IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB;
4182d8899132SKalle Valo 	he_cap_elem->phy_cap_info[9] &= ~m;
4183d8899132SKalle Valo }
4184d8899132SKalle Valo 
4185d8899132SKalle Valo static __le16 ath12k_mac_setup_he_6ghz_cap(struct ath12k_pdev_cap *pcap,
4186d8899132SKalle Valo 					   struct ath12k_band_cap *bcap)
4187d8899132SKalle Valo {
4188d8899132SKalle Valo 	u8 val;
4189d8899132SKalle Valo 
4190d8899132SKalle Valo 	bcap->he_6ghz_capa = IEEE80211_HT_MPDU_DENSITY_NONE;
4191d8899132SKalle Valo 	if (bcap->ht_cap_info & WMI_HT_CAP_DYNAMIC_SMPS)
4192d8899132SKalle Valo 		bcap->he_6ghz_capa |=
4193d8899132SKalle Valo 			u32_encode_bits(WLAN_HT_CAP_SM_PS_DYNAMIC,
4194d8899132SKalle Valo 					IEEE80211_HE_6GHZ_CAP_SM_PS);
4195d8899132SKalle Valo 	else
4196d8899132SKalle Valo 		bcap->he_6ghz_capa |=
4197d8899132SKalle Valo 			u32_encode_bits(WLAN_HT_CAP_SM_PS_DISABLED,
4198d8899132SKalle Valo 					IEEE80211_HE_6GHZ_CAP_SM_PS);
4199d8899132SKalle Valo 	val = u32_get_bits(pcap->vht_cap,
4200d8899132SKalle Valo 			   IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK);
4201d8899132SKalle Valo 	bcap->he_6ghz_capa |=
4202d8899132SKalle Valo 		u32_encode_bits(val, IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP);
4203d8899132SKalle Valo 	val = u32_get_bits(pcap->vht_cap,
4204d8899132SKalle Valo 			   IEEE80211_VHT_CAP_MAX_MPDU_MASK);
4205d8899132SKalle Valo 	bcap->he_6ghz_capa |=
4206d8899132SKalle Valo 		u32_encode_bits(val, IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN);
4207d8899132SKalle Valo 	if (pcap->vht_cap & IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN)
4208d8899132SKalle Valo 		bcap->he_6ghz_capa |= IEEE80211_HE_6GHZ_CAP_RX_ANTPAT_CONS;
4209d8899132SKalle Valo 	if (pcap->vht_cap & IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN)
4210d8899132SKalle Valo 		bcap->he_6ghz_capa |= IEEE80211_HE_6GHZ_CAP_TX_ANTPAT_CONS;
4211d8899132SKalle Valo 
4212d8899132SKalle Valo 	return cpu_to_le16(bcap->he_6ghz_capa);
4213d8899132SKalle Valo }
4214d8899132SKalle Valo 
4215d8899132SKalle Valo static int ath12k_mac_copy_he_cap(struct ath12k *ar,
4216d8899132SKalle Valo 				  struct ath12k_pdev_cap *cap,
4217d8899132SKalle Valo 				  struct ieee80211_sband_iftype_data *data,
4218d8899132SKalle Valo 				  int band)
4219d8899132SKalle Valo {
4220d8899132SKalle Valo 	int i, idx = 0;
4221d8899132SKalle Valo 
4222d8899132SKalle Valo 	for (i = 0; i < NUM_NL80211_IFTYPES; i++) {
4223d8899132SKalle Valo 		struct ieee80211_sta_he_cap *he_cap = &data[idx].he_cap;
4224d8899132SKalle Valo 		struct ath12k_band_cap *band_cap = &cap->band[band];
4225d8899132SKalle Valo 		struct ieee80211_he_cap_elem *he_cap_elem =
4226d8899132SKalle Valo 				&he_cap->he_cap_elem;
4227d8899132SKalle Valo 
4228d8899132SKalle Valo 		switch (i) {
4229d8899132SKalle Valo 		case NL80211_IFTYPE_STATION:
4230d8899132SKalle Valo 		case NL80211_IFTYPE_AP:
4231d8899132SKalle Valo 		case NL80211_IFTYPE_MESH_POINT:
4232d8899132SKalle Valo 			break;
4233d8899132SKalle Valo 
4234d8899132SKalle Valo 		default:
4235d8899132SKalle Valo 			continue;
4236d8899132SKalle Valo 		}
4237d8899132SKalle Valo 
4238d8899132SKalle Valo 		data[idx].types_mask = BIT(i);
4239d8899132SKalle Valo 		he_cap->has_he = true;
4240d8899132SKalle Valo 		memcpy(he_cap_elem->mac_cap_info, band_cap->he_cap_info,
4241d8899132SKalle Valo 		       sizeof(he_cap_elem->mac_cap_info));
4242d8899132SKalle Valo 		memcpy(he_cap_elem->phy_cap_info, band_cap->he_cap_phy_info,
4243d8899132SKalle Valo 		       sizeof(he_cap_elem->phy_cap_info));
4244d8899132SKalle Valo 
4245d8899132SKalle Valo 		he_cap_elem->mac_cap_info[1] &=
4246d8899132SKalle Valo 			IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_MASK;
4247d8899132SKalle Valo 
4248d8899132SKalle Valo 		he_cap_elem->phy_cap_info[5] &=
4249d8899132SKalle Valo 			~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK;
4250d8899132SKalle Valo 		he_cap_elem->phy_cap_info[5] &=
4251d8899132SKalle Valo 			~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK;
4252d8899132SKalle Valo 		he_cap_elem->phy_cap_info[5] |= ar->num_tx_chains - 1;
4253d8899132SKalle Valo 
4254d8899132SKalle Valo 		switch (i) {
4255d8899132SKalle Valo 		case NL80211_IFTYPE_AP:
4256d8899132SKalle Valo 			he_cap_elem->phy_cap_info[3] &=
4257d8899132SKalle Valo 				~IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_MASK;
4258d8899132SKalle Valo 			he_cap_elem->phy_cap_info[9] |=
4259d8899132SKalle Valo 				IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU;
4260d8899132SKalle Valo 			break;
4261d8899132SKalle Valo 		case NL80211_IFTYPE_STATION:
4262d8899132SKalle Valo 			he_cap_elem->mac_cap_info[0] &=
4263d8899132SKalle Valo 				~IEEE80211_HE_MAC_CAP0_TWT_RES;
4264d8899132SKalle Valo 			he_cap_elem->mac_cap_info[0] |=
4265d8899132SKalle Valo 				IEEE80211_HE_MAC_CAP0_TWT_REQ;
4266d8899132SKalle Valo 			he_cap_elem->phy_cap_info[9] |=
4267d8899132SKalle Valo 				IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU;
4268d8899132SKalle Valo 			break;
4269d8899132SKalle Valo 		case NL80211_IFTYPE_MESH_POINT:
4270d8899132SKalle Valo 			ath12k_mac_filter_he_cap_mesh(he_cap_elem);
4271d8899132SKalle Valo 			break;
4272d8899132SKalle Valo 		}
4273d8899132SKalle Valo 
4274d8899132SKalle Valo 		he_cap->he_mcs_nss_supp.rx_mcs_80 =
4275d8899132SKalle Valo 			cpu_to_le16(band_cap->he_mcs & 0xffff);
4276d8899132SKalle Valo 		he_cap->he_mcs_nss_supp.tx_mcs_80 =
4277d8899132SKalle Valo 			cpu_to_le16(band_cap->he_mcs & 0xffff);
4278d8899132SKalle Valo 		he_cap->he_mcs_nss_supp.rx_mcs_160 =
4279d8899132SKalle Valo 			cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
4280d8899132SKalle Valo 		he_cap->he_mcs_nss_supp.tx_mcs_160 =
4281d8899132SKalle Valo 			cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
4282d8899132SKalle Valo 		he_cap->he_mcs_nss_supp.rx_mcs_80p80 =
4283d8899132SKalle Valo 			cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
4284d8899132SKalle Valo 		he_cap->he_mcs_nss_supp.tx_mcs_80p80 =
4285d8899132SKalle Valo 			cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
4286d8899132SKalle Valo 
4287d8899132SKalle Valo 		memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres));
4288d8899132SKalle Valo 		if (he_cap_elem->phy_cap_info[6] &
4289d8899132SKalle Valo 		    IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT)
4290d8899132SKalle Valo 			ath12k_gen_ppe_thresh(&band_cap->he_ppet,
4291d8899132SKalle Valo 					      he_cap->ppe_thres);
4292d8899132SKalle Valo 
4293d8899132SKalle Valo 		if (band == NL80211_BAND_6GHZ) {
4294d8899132SKalle Valo 			data[idx].he_6ghz_capa.capa =
4295d8899132SKalle Valo 				ath12k_mac_setup_he_6ghz_cap(cap, band_cap);
4296d8899132SKalle Valo 		}
4297d8899132SKalle Valo 		idx++;
4298d8899132SKalle Valo 	}
4299d8899132SKalle Valo 
4300d8899132SKalle Valo 	return idx;
4301d8899132SKalle Valo }
4302d8899132SKalle Valo 
4303d8899132SKalle Valo static void ath12k_mac_setup_he_cap(struct ath12k *ar,
4304d8899132SKalle Valo 				    struct ath12k_pdev_cap *cap)
4305d8899132SKalle Valo {
4306d8899132SKalle Valo 	struct ieee80211_supported_band *band;
4307d8899132SKalle Valo 	int count;
4308d8899132SKalle Valo 
4309d8899132SKalle Valo 	if (cap->supported_bands & WMI_HOST_WLAN_2G_CAP) {
4310d8899132SKalle Valo 		count = ath12k_mac_copy_he_cap(ar, cap,
4311d8899132SKalle Valo 					       ar->mac.iftype[NL80211_BAND_2GHZ],
4312d8899132SKalle Valo 					       NL80211_BAND_2GHZ);
4313d8899132SKalle Valo 		band = &ar->mac.sbands[NL80211_BAND_2GHZ];
4314d8899132SKalle Valo 		band->iftype_data = ar->mac.iftype[NL80211_BAND_2GHZ];
4315d8899132SKalle Valo 		band->n_iftype_data = count;
4316d8899132SKalle Valo 	}
4317d8899132SKalle Valo 
4318d8899132SKalle Valo 	if (cap->supported_bands & WMI_HOST_WLAN_5G_CAP) {
4319d8899132SKalle Valo 		count = ath12k_mac_copy_he_cap(ar, cap,
4320d8899132SKalle Valo 					       ar->mac.iftype[NL80211_BAND_5GHZ],
4321d8899132SKalle Valo 					       NL80211_BAND_5GHZ);
4322d8899132SKalle Valo 		band = &ar->mac.sbands[NL80211_BAND_5GHZ];
4323d8899132SKalle Valo 		band->iftype_data = ar->mac.iftype[NL80211_BAND_5GHZ];
4324d8899132SKalle Valo 		band->n_iftype_data = count;
4325d8899132SKalle Valo 	}
4326d8899132SKalle Valo 
4327d8899132SKalle Valo 	if (cap->supported_bands & WMI_HOST_WLAN_5G_CAP &&
4328d8899132SKalle Valo 	    ar->supports_6ghz) {
4329d8899132SKalle Valo 		count = ath12k_mac_copy_he_cap(ar, cap,
4330d8899132SKalle Valo 					       ar->mac.iftype[NL80211_BAND_6GHZ],
4331d8899132SKalle Valo 					       NL80211_BAND_6GHZ);
4332d8899132SKalle Valo 		band = &ar->mac.sbands[NL80211_BAND_6GHZ];
4333d8899132SKalle Valo 		band->iftype_data = ar->mac.iftype[NL80211_BAND_6GHZ];
4334d8899132SKalle Valo 		band->n_iftype_data = count;
4335d8899132SKalle Valo 	}
4336d8899132SKalle Valo }
4337d8899132SKalle Valo 
4338d8899132SKalle Valo static int __ath12k_set_antenna(struct ath12k *ar, u32 tx_ant, u32 rx_ant)
4339d8899132SKalle Valo {
4340d8899132SKalle Valo 	int ret;
4341d8899132SKalle Valo 
4342d8899132SKalle Valo 	lockdep_assert_held(&ar->conf_mutex);
4343d8899132SKalle Valo 
4344d8899132SKalle Valo 	if (ath12k_check_chain_mask(ar, tx_ant, true))
4345d8899132SKalle Valo 		return -EINVAL;
4346d8899132SKalle Valo 
4347d8899132SKalle Valo 	if (ath12k_check_chain_mask(ar, rx_ant, false))
4348d8899132SKalle Valo 		return -EINVAL;
4349d8899132SKalle Valo 
4350d8899132SKalle Valo 	ar->cfg_tx_chainmask = tx_ant;
4351d8899132SKalle Valo 	ar->cfg_rx_chainmask = rx_ant;
4352d8899132SKalle Valo 
4353d8899132SKalle Valo 	if (ar->state != ATH12K_STATE_ON &&
4354d8899132SKalle Valo 	    ar->state != ATH12K_STATE_RESTARTED)
4355d8899132SKalle Valo 		return 0;
4356d8899132SKalle Valo 
4357d8899132SKalle Valo 	ret = ath12k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_TX_CHAIN_MASK,
4358d8899132SKalle Valo 					tx_ant, ar->pdev->pdev_id);
4359d8899132SKalle Valo 	if (ret) {
4360d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to set tx-chainmask: %d, req 0x%x\n",
4361d8899132SKalle Valo 			    ret, tx_ant);
4362d8899132SKalle Valo 		return ret;
4363d8899132SKalle Valo 	}
4364d8899132SKalle Valo 
4365d8899132SKalle Valo 	ar->num_tx_chains = hweight32(tx_ant);
4366d8899132SKalle Valo 
4367d8899132SKalle Valo 	ret = ath12k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_RX_CHAIN_MASK,
4368d8899132SKalle Valo 					rx_ant, ar->pdev->pdev_id);
4369d8899132SKalle Valo 	if (ret) {
4370d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to set rx-chainmask: %d, req 0x%x\n",
4371d8899132SKalle Valo 			    ret, rx_ant);
4372d8899132SKalle Valo 		return ret;
4373d8899132SKalle Valo 	}
4374d8899132SKalle Valo 
4375d8899132SKalle Valo 	ar->num_rx_chains = hweight32(rx_ant);
4376d8899132SKalle Valo 
4377d8899132SKalle Valo 	/* Reload HT/VHT/HE capability */
4378d8899132SKalle Valo 	ath12k_mac_setup_ht_vht_cap(ar, &ar->pdev->cap, NULL);
4379d8899132SKalle Valo 	ath12k_mac_setup_he_cap(ar, &ar->pdev->cap);
4380d8899132SKalle Valo 
4381d8899132SKalle Valo 	return 0;
4382d8899132SKalle Valo }
4383d8899132SKalle Valo 
43845189a8dbSKarthik M static void ath12k_mgmt_over_wmi_tx_drop(struct ath12k *ar, struct sk_buff *skb)
43855189a8dbSKarthik M {
43865189a8dbSKarthik M 	int num_mgmt;
43875189a8dbSKarthik M 
43885189a8dbSKarthik M 	ieee80211_free_txskb(ar->hw, skb);
43895189a8dbSKarthik M 
43905189a8dbSKarthik M 	num_mgmt = atomic_dec_if_positive(&ar->num_pending_mgmt_tx);
43915189a8dbSKarthik M 
43925189a8dbSKarthik M 	if (num_mgmt < 0)
43935189a8dbSKarthik M 		WARN_ON_ONCE(1);
43945189a8dbSKarthik M 
43955189a8dbSKarthik M 	if (!num_mgmt)
43965189a8dbSKarthik M 		wake_up(&ar->txmgmt_empty_waitq);
43975189a8dbSKarthik M }
43985189a8dbSKarthik M 
4399d8899132SKalle Valo int ath12k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx)
4400d8899132SKalle Valo {
4401d8899132SKalle Valo 	struct sk_buff *msdu = skb;
4402d8899132SKalle Valo 	struct ieee80211_tx_info *info;
4403d8899132SKalle Valo 	struct ath12k *ar = ctx;
4404d8899132SKalle Valo 	struct ath12k_base *ab = ar->ab;
4405d8899132SKalle Valo 
4406d8899132SKalle Valo 	spin_lock_bh(&ar->txmgmt_idr_lock);
4407d8899132SKalle Valo 	idr_remove(&ar->txmgmt_idr, buf_id);
4408d8899132SKalle Valo 	spin_unlock_bh(&ar->txmgmt_idr_lock);
4409d8899132SKalle Valo 	dma_unmap_single(ab->dev, ATH12K_SKB_CB(msdu)->paddr, msdu->len,
4410d8899132SKalle Valo 			 DMA_TO_DEVICE);
4411d8899132SKalle Valo 
4412d8899132SKalle Valo 	info = IEEE80211_SKB_CB(msdu);
4413d8899132SKalle Valo 	memset(&info->status, 0, sizeof(info->status));
4414d8899132SKalle Valo 
44155189a8dbSKarthik M 	ath12k_mgmt_over_wmi_tx_drop(ar, skb);
4416d8899132SKalle Valo 
4417d8899132SKalle Valo 	return 0;
4418d8899132SKalle Valo }
4419d8899132SKalle Valo 
4420d8899132SKalle Valo static int ath12k_mac_vif_txmgmt_idr_remove(int buf_id, void *skb, void *ctx)
4421d8899132SKalle Valo {
4422d8899132SKalle Valo 	struct ieee80211_vif *vif = ctx;
4423d8899132SKalle Valo 	struct ath12k_skb_cb *skb_cb = ATH12K_SKB_CB(skb);
4424d8899132SKalle Valo 	struct sk_buff *msdu = skb;
4425d8899132SKalle Valo 	struct ath12k *ar = skb_cb->ar;
4426d8899132SKalle Valo 	struct ath12k_base *ab = ar->ab;
4427d8899132SKalle Valo 
4428d8899132SKalle Valo 	if (skb_cb->vif == vif) {
4429d8899132SKalle Valo 		spin_lock_bh(&ar->txmgmt_idr_lock);
4430d8899132SKalle Valo 		idr_remove(&ar->txmgmt_idr, buf_id);
4431d8899132SKalle Valo 		spin_unlock_bh(&ar->txmgmt_idr_lock);
4432d8899132SKalle Valo 		dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len,
4433d8899132SKalle Valo 				 DMA_TO_DEVICE);
4434d8899132SKalle Valo 	}
4435d8899132SKalle Valo 
4436d8899132SKalle Valo 	return 0;
4437d8899132SKalle Valo }
4438d8899132SKalle Valo 
4439d8899132SKalle Valo static int ath12k_mac_mgmt_tx_wmi(struct ath12k *ar, struct ath12k_vif *arvif,
4440d8899132SKalle Valo 				  struct sk_buff *skb)
4441d8899132SKalle Valo {
4442d8899132SKalle Valo 	struct ath12k_base *ab = ar->ab;
4443d8899132SKalle Valo 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
4444d8899132SKalle Valo 	struct ieee80211_tx_info *info;
4445d8899132SKalle Valo 	dma_addr_t paddr;
4446d8899132SKalle Valo 	int buf_id;
4447d8899132SKalle Valo 	int ret;
4448d8899132SKalle Valo 
4449054b5580SBalamurugan S 	ATH12K_SKB_CB(skb)->ar = ar;
4450d8899132SKalle Valo 	spin_lock_bh(&ar->txmgmt_idr_lock);
4451d8899132SKalle Valo 	buf_id = idr_alloc(&ar->txmgmt_idr, skb, 0,
4452d8899132SKalle Valo 			   ATH12K_TX_MGMT_NUM_PENDING_MAX, GFP_ATOMIC);
4453d8899132SKalle Valo 	spin_unlock_bh(&ar->txmgmt_idr_lock);
4454d8899132SKalle Valo 	if (buf_id < 0)
4455d8899132SKalle Valo 		return -ENOSPC;
4456d8899132SKalle Valo 
4457d8899132SKalle Valo 	info = IEEE80211_SKB_CB(skb);
4458d8899132SKalle Valo 	if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP)) {
4459d8899132SKalle Valo 		if ((ieee80211_is_action(hdr->frame_control) ||
4460d8899132SKalle Valo 		     ieee80211_is_deauth(hdr->frame_control) ||
4461d8899132SKalle Valo 		     ieee80211_is_disassoc(hdr->frame_control)) &&
4462d8899132SKalle Valo 		     ieee80211_has_protected(hdr->frame_control)) {
4463d8899132SKalle Valo 			skb_put(skb, IEEE80211_CCMP_MIC_LEN);
4464d8899132SKalle Valo 		}
4465d8899132SKalle Valo 	}
4466d8899132SKalle Valo 
4467d8899132SKalle Valo 	paddr = dma_map_single(ab->dev, skb->data, skb->len, DMA_TO_DEVICE);
4468d8899132SKalle Valo 	if (dma_mapping_error(ab->dev, paddr)) {
4469d8899132SKalle Valo 		ath12k_warn(ab, "failed to DMA map mgmt Tx buffer\n");
4470d8899132SKalle Valo 		ret = -EIO;
4471d8899132SKalle Valo 		goto err_free_idr;
4472d8899132SKalle Valo 	}
4473d8899132SKalle Valo 
4474d8899132SKalle Valo 	ATH12K_SKB_CB(skb)->paddr = paddr;
4475d8899132SKalle Valo 
4476d8899132SKalle Valo 	ret = ath12k_wmi_mgmt_send(ar, arvif->vdev_id, buf_id, skb);
4477d8899132SKalle Valo 	if (ret) {
4478d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to send mgmt frame: %d\n", ret);
4479d8899132SKalle Valo 		goto err_unmap_buf;
4480d8899132SKalle Valo 	}
4481d8899132SKalle Valo 
4482d8899132SKalle Valo 	return 0;
4483d8899132SKalle Valo 
4484d8899132SKalle Valo err_unmap_buf:
4485d8899132SKalle Valo 	dma_unmap_single(ab->dev, ATH12K_SKB_CB(skb)->paddr,
4486d8899132SKalle Valo 			 skb->len, DMA_TO_DEVICE);
4487d8899132SKalle Valo err_free_idr:
4488d8899132SKalle Valo 	spin_lock_bh(&ar->txmgmt_idr_lock);
4489d8899132SKalle Valo 	idr_remove(&ar->txmgmt_idr, buf_id);
4490d8899132SKalle Valo 	spin_unlock_bh(&ar->txmgmt_idr_lock);
4491d8899132SKalle Valo 
4492d8899132SKalle Valo 	return ret;
4493d8899132SKalle Valo }
4494d8899132SKalle Valo 
4495d8899132SKalle Valo static void ath12k_mgmt_over_wmi_tx_purge(struct ath12k *ar)
4496d8899132SKalle Valo {
4497d8899132SKalle Valo 	struct sk_buff *skb;
4498d8899132SKalle Valo 
4499d8899132SKalle Valo 	while ((skb = skb_dequeue(&ar->wmi_mgmt_tx_queue)) != NULL)
45005189a8dbSKarthik M 		ath12k_mgmt_over_wmi_tx_drop(ar, skb);
4501d8899132SKalle Valo }
4502d8899132SKalle Valo 
4503d8899132SKalle Valo static void ath12k_mgmt_over_wmi_tx_work(struct work_struct *work)
4504d8899132SKalle Valo {
4505d8899132SKalle Valo 	struct ath12k *ar = container_of(work, struct ath12k, wmi_mgmt_tx_work);
4506d8899132SKalle Valo 	struct ath12k_skb_cb *skb_cb;
4507d8899132SKalle Valo 	struct ath12k_vif *arvif;
4508d8899132SKalle Valo 	struct sk_buff *skb;
4509d8899132SKalle Valo 	int ret;
4510d8899132SKalle Valo 
4511d8899132SKalle Valo 	while ((skb = skb_dequeue(&ar->wmi_mgmt_tx_queue)) != NULL) {
4512d8899132SKalle Valo 		skb_cb = ATH12K_SKB_CB(skb);
4513d8899132SKalle Valo 		if (!skb_cb->vif) {
4514d8899132SKalle Valo 			ath12k_warn(ar->ab, "no vif found for mgmt frame\n");
45155189a8dbSKarthik M 			ath12k_mgmt_over_wmi_tx_drop(ar, skb);
4516d8899132SKalle Valo 			continue;
4517d8899132SKalle Valo 		}
4518d8899132SKalle Valo 
4519d8899132SKalle Valo 		arvif = ath12k_vif_to_arvif(skb_cb->vif);
4520d8899132SKalle Valo 		if (ar->allocated_vdev_map & (1LL << arvif->vdev_id) &&
4521d8899132SKalle Valo 		    arvif->is_started) {
4522d8899132SKalle Valo 			ret = ath12k_mac_mgmt_tx_wmi(ar, arvif, skb);
4523d8899132SKalle Valo 			if (ret) {
4524d8899132SKalle Valo 				ath12k_warn(ar->ab, "failed to tx mgmt frame, vdev_id %d :%d\n",
4525d8899132SKalle Valo 					    arvif->vdev_id, ret);
45265189a8dbSKarthik M 				ath12k_mgmt_over_wmi_tx_drop(ar, skb);
4527d8899132SKalle Valo 			}
4528d8899132SKalle Valo 		} else {
4529d8899132SKalle Valo 			ath12k_warn(ar->ab,
4530d8899132SKalle Valo 				    "dropping mgmt frame for vdev %d, is_started %d\n",
4531d8899132SKalle Valo 				    arvif->vdev_id,
4532d8899132SKalle Valo 				    arvif->is_started);
45335189a8dbSKarthik M 			ath12k_mgmt_over_wmi_tx_drop(ar, skb);
4534d8899132SKalle Valo 		}
4535d8899132SKalle Valo 	}
4536d8899132SKalle Valo }
4537d8899132SKalle Valo 
4538d8899132SKalle Valo static int ath12k_mac_mgmt_tx(struct ath12k *ar, struct sk_buff *skb,
4539d8899132SKalle Valo 			      bool is_prb_rsp)
4540d8899132SKalle Valo {
4541d8899132SKalle Valo 	struct sk_buff_head *q = &ar->wmi_mgmt_tx_queue;
4542d8899132SKalle Valo 
4543d8899132SKalle Valo 	if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))
4544d8899132SKalle Valo 		return -ESHUTDOWN;
4545d8899132SKalle Valo 
4546d8899132SKalle Valo 	/* Drop probe response packets when the pending management tx
4547d8899132SKalle Valo 	 * count has reached a certain threshold, so as to prioritize
4548d8899132SKalle Valo 	 * other mgmt packets like auth and assoc to be sent on time
4549d8899132SKalle Valo 	 * for establishing successful connections.
4550d8899132SKalle Valo 	 */
4551d8899132SKalle Valo 	if (is_prb_rsp &&
4552d8899132SKalle Valo 	    atomic_read(&ar->num_pending_mgmt_tx) > ATH12K_PRB_RSP_DROP_THRESHOLD) {
4553d8899132SKalle Valo 		ath12k_warn(ar->ab,
4554d8899132SKalle Valo 			    "dropping probe response as pending queue is almost full\n");
4555d8899132SKalle Valo 		return -ENOSPC;
4556d8899132SKalle Valo 	}
4557d8899132SKalle Valo 
4558e995f3f6SKarthik M 	if (skb_queue_len_lockless(q) >= ATH12K_TX_MGMT_NUM_PENDING_MAX) {
4559d8899132SKalle Valo 		ath12k_warn(ar->ab, "mgmt tx queue is full\n");
4560d8899132SKalle Valo 		return -ENOSPC;
4561d8899132SKalle Valo 	}
4562d8899132SKalle Valo 
4563d8899132SKalle Valo 	skb_queue_tail(q, skb);
45645189a8dbSKarthik M 	atomic_inc(&ar->num_pending_mgmt_tx);
4565d8899132SKalle Valo 	ieee80211_queue_work(ar->hw, &ar->wmi_mgmt_tx_work);
4566d8899132SKalle Valo 
4567d8899132SKalle Valo 	return 0;
4568d8899132SKalle Valo }
4569d8899132SKalle Valo 
4570d8899132SKalle Valo static void ath12k_mac_op_tx(struct ieee80211_hw *hw,
4571d8899132SKalle Valo 			     struct ieee80211_tx_control *control,
4572d8899132SKalle Valo 			     struct sk_buff *skb)
4573d8899132SKalle Valo {
4574d8899132SKalle Valo 	struct ath12k_skb_cb *skb_cb = ATH12K_SKB_CB(skb);
4575d8899132SKalle Valo 	struct ath12k *ar = hw->priv;
4576d8899132SKalle Valo 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
4577d8899132SKalle Valo 	struct ieee80211_vif *vif = info->control.vif;
4578d8899132SKalle Valo 	struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
4579d8899132SKalle Valo 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
4580d8899132SKalle Valo 	struct ieee80211_key_conf *key = info->control.hw_key;
4581d8899132SKalle Valo 	u32 info_flags = info->flags;
4582d8899132SKalle Valo 	bool is_prb_rsp;
4583d8899132SKalle Valo 	int ret;
4584d8899132SKalle Valo 
4585d8899132SKalle Valo 	memset(skb_cb, 0, sizeof(*skb_cb));
4586d8899132SKalle Valo 	skb_cb->vif = vif;
4587d8899132SKalle Valo 
4588d8899132SKalle Valo 	if (key) {
4589d8899132SKalle Valo 		skb_cb->cipher = key->cipher;
4590d8899132SKalle Valo 		skb_cb->flags |= ATH12K_SKB_CIPHER_SET;
4591d8899132SKalle Valo 	}
4592d8899132SKalle Valo 
4593d8899132SKalle Valo 	if (info_flags & IEEE80211_TX_CTL_HW_80211_ENCAP) {
4594d8899132SKalle Valo 		skb_cb->flags |= ATH12K_SKB_HW_80211_ENCAP;
4595d8899132SKalle Valo 	} else if (ieee80211_is_mgmt(hdr->frame_control)) {
4596d8899132SKalle Valo 		is_prb_rsp = ieee80211_is_probe_resp(hdr->frame_control);
4597d8899132SKalle Valo 		ret = ath12k_mac_mgmt_tx(ar, skb, is_prb_rsp);
4598d8899132SKalle Valo 		if (ret) {
4599d8899132SKalle Valo 			ath12k_warn(ar->ab, "failed to queue management frame %d\n",
4600d8899132SKalle Valo 				    ret);
4601d8899132SKalle Valo 			ieee80211_free_txskb(ar->hw, skb);
4602d8899132SKalle Valo 		}
4603d8899132SKalle Valo 		return;
4604d8899132SKalle Valo 	}
4605d8899132SKalle Valo 
4606d8899132SKalle Valo 	ret = ath12k_dp_tx(ar, arvif, skb);
4607d8899132SKalle Valo 	if (ret) {
4608d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to transmit frame %d\n", ret);
4609d8899132SKalle Valo 		ieee80211_free_txskb(ar->hw, skb);
4610d8899132SKalle Valo 	}
4611d8899132SKalle Valo }
4612d8899132SKalle Valo 
4613d8899132SKalle Valo void ath12k_mac_drain_tx(struct ath12k *ar)
4614d8899132SKalle Valo {
4615d8899132SKalle Valo 	/* make sure rcu-protected mac80211 tx path itself is drained */
4616d8899132SKalle Valo 	synchronize_net();
4617d8899132SKalle Valo 
4618d8899132SKalle Valo 	cancel_work_sync(&ar->wmi_mgmt_tx_work);
4619d8899132SKalle Valo 	ath12k_mgmt_over_wmi_tx_purge(ar);
4620d8899132SKalle Valo }
4621d8899132SKalle Valo 
4622d8899132SKalle Valo static int ath12k_mac_config_mon_status_default(struct ath12k *ar, bool enable)
4623d8899132SKalle Valo {
4624d8899132SKalle Valo 	return -ENOTSUPP;
4625d8899132SKalle Valo 	/* TODO: Need to support new monitor mode */
4626d8899132SKalle Valo }
4627d8899132SKalle Valo 
4628d8899132SKalle Valo static void ath12k_mac_wait_reconfigure(struct ath12k_base *ab)
4629d8899132SKalle Valo {
4630d8899132SKalle Valo 	int recovery_start_count;
4631d8899132SKalle Valo 
4632d8899132SKalle Valo 	if (!ab->is_reset)
4633d8899132SKalle Valo 		return;
4634d8899132SKalle Valo 
4635d8899132SKalle Valo 	recovery_start_count = atomic_inc_return(&ab->recovery_start_count);
4636d8899132SKalle Valo 
4637d8899132SKalle Valo 	ath12k_dbg(ab, ATH12K_DBG_MAC, "recovery start count %d\n", recovery_start_count);
4638d8899132SKalle Valo 
4639d8899132SKalle Valo 	if (recovery_start_count == ab->num_radios) {
4640d8899132SKalle Valo 		complete(&ab->recovery_start);
4641d8899132SKalle Valo 		ath12k_dbg(ab, ATH12K_DBG_MAC, "recovery started success\n");
4642d8899132SKalle Valo 	}
4643d8899132SKalle Valo 
4644d8899132SKalle Valo 	ath12k_dbg(ab, ATH12K_DBG_MAC, "waiting reconfigure...\n");
4645d8899132SKalle Valo 
4646d8899132SKalle Valo 	wait_for_completion_timeout(&ab->reconfigure_complete,
4647d8899132SKalle Valo 				    ATH12K_RECONFIGURE_TIMEOUT_HZ);
4648d8899132SKalle Valo }
4649d8899132SKalle Valo 
4650d8899132SKalle Valo static int ath12k_mac_op_start(struct ieee80211_hw *hw)
4651d8899132SKalle Valo {
4652d8899132SKalle Valo 	struct ath12k *ar = hw->priv;
4653d8899132SKalle Valo 	struct ath12k_base *ab = ar->ab;
4654d8899132SKalle Valo 	struct ath12k_pdev *pdev = ar->pdev;
4655d8899132SKalle Valo 	int ret;
4656d8899132SKalle Valo 
4657d8899132SKalle Valo 	ath12k_mac_drain_tx(ar);
4658d8899132SKalle Valo 	mutex_lock(&ar->conf_mutex);
4659d8899132SKalle Valo 
4660d8899132SKalle Valo 	switch (ar->state) {
4661d8899132SKalle Valo 	case ATH12K_STATE_OFF:
4662d8899132SKalle Valo 		ar->state = ATH12K_STATE_ON;
4663d8899132SKalle Valo 		break;
4664d8899132SKalle Valo 	case ATH12K_STATE_RESTARTING:
4665d8899132SKalle Valo 		ar->state = ATH12K_STATE_RESTARTED;
4666d8899132SKalle Valo 		ath12k_mac_wait_reconfigure(ab);
4667d8899132SKalle Valo 		break;
4668d8899132SKalle Valo 	case ATH12K_STATE_RESTARTED:
4669d8899132SKalle Valo 	case ATH12K_STATE_WEDGED:
4670d8899132SKalle Valo 	case ATH12K_STATE_ON:
4671d8899132SKalle Valo 		WARN_ON(1);
4672d8899132SKalle Valo 		ret = -EINVAL;
4673d8899132SKalle Valo 		goto err;
4674d8899132SKalle Valo 	}
4675d8899132SKalle Valo 
4676d8899132SKalle Valo 	ret = ath12k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_PMF_QOS,
4677d8899132SKalle Valo 					1, pdev->pdev_id);
4678d8899132SKalle Valo 
4679d8899132SKalle Valo 	if (ret) {
4680d8899132SKalle Valo 		ath12k_err(ar->ab, "failed to enable PMF QOS: (%d\n", ret);
4681d8899132SKalle Valo 		goto err;
4682d8899132SKalle Valo 	}
4683d8899132SKalle Valo 
4684d8899132SKalle Valo 	ret = ath12k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_DYNAMIC_BW, 1,
4685d8899132SKalle Valo 					pdev->pdev_id);
4686d8899132SKalle Valo 	if (ret) {
4687d8899132SKalle Valo 		ath12k_err(ar->ab, "failed to enable dynamic bw: %d\n", ret);
4688d8899132SKalle Valo 		goto err;
4689d8899132SKalle Valo 	}
4690d8899132SKalle Valo 
4691d8899132SKalle Valo 	ret = ath12k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_ARP_AC_OVERRIDE,
4692d8899132SKalle Valo 					0, pdev->pdev_id);
4693d8899132SKalle Valo 	if (ret) {
4694d8899132SKalle Valo 		ath12k_err(ab, "failed to set ac override for ARP: %d\n",
4695d8899132SKalle Valo 			   ret);
4696d8899132SKalle Valo 		goto err;
4697d8899132SKalle Valo 	}
4698d8899132SKalle Valo 
4699d8899132SKalle Valo 	ret = ath12k_wmi_send_dfs_phyerr_offload_enable_cmd(ar, pdev->pdev_id);
4700d8899132SKalle Valo 	if (ret) {
4701d8899132SKalle Valo 		ath12k_err(ab, "failed to offload radar detection: %d\n",
4702d8899132SKalle Valo 			   ret);
4703d8899132SKalle Valo 		goto err;
4704d8899132SKalle Valo 	}
4705d8899132SKalle Valo 
4706d8899132SKalle Valo 	ret = ath12k_dp_tx_htt_h2t_ppdu_stats_req(ar,
4707d8899132SKalle Valo 						  HTT_PPDU_STATS_TAG_DEFAULT);
4708d8899132SKalle Valo 	if (ret) {
4709d8899132SKalle Valo 		ath12k_err(ab, "failed to req ppdu stats: %d\n", ret);
4710d8899132SKalle Valo 		goto err;
4711d8899132SKalle Valo 	}
4712d8899132SKalle Valo 
4713d8899132SKalle Valo 	ret = ath12k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_MESH_MCAST_ENABLE,
4714d8899132SKalle Valo 					1, pdev->pdev_id);
4715d8899132SKalle Valo 
4716d8899132SKalle Valo 	if (ret) {
4717d8899132SKalle Valo 		ath12k_err(ar->ab, "failed to enable MESH MCAST ENABLE: (%d\n", ret);
4718d8899132SKalle Valo 		goto err;
4719d8899132SKalle Valo 	}
4720d8899132SKalle Valo 
4721d8899132SKalle Valo 	__ath12k_set_antenna(ar, ar->cfg_tx_chainmask, ar->cfg_rx_chainmask);
4722d8899132SKalle Valo 
4723d8899132SKalle Valo 	/* TODO: Do we need to enable ANI? */
4724d8899132SKalle Valo 
4725d8899132SKalle Valo 	ath12k_reg_update_chan_list(ar);
4726d8899132SKalle Valo 
4727d8899132SKalle Valo 	ar->num_started_vdevs = 0;
4728d8899132SKalle Valo 	ar->num_created_vdevs = 0;
4729d8899132SKalle Valo 	ar->num_peers = 0;
4730d8899132SKalle Valo 	ar->allocated_vdev_map = 0;
4731d8899132SKalle Valo 
4732d8899132SKalle Valo 	/* Configure monitor status ring with default rx_filter to get rx status
4733d8899132SKalle Valo 	 * such as rssi, rx_duration.
4734d8899132SKalle Valo 	 */
4735d8899132SKalle Valo 	ret = ath12k_mac_config_mon_status_default(ar, true);
4736d8899132SKalle Valo 	if (ret && (ret != -ENOTSUPP)) {
4737d8899132SKalle Valo 		ath12k_err(ab, "failed to configure monitor status ring with default rx_filter: (%d)\n",
4738d8899132SKalle Valo 			   ret);
4739d8899132SKalle Valo 		goto err;
4740d8899132SKalle Valo 	}
4741d8899132SKalle Valo 
4742d8899132SKalle Valo 	if (ret == -ENOTSUPP)
4743d8899132SKalle Valo 		ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
4744d8899132SKalle Valo 			   "monitor status config is not yet supported");
4745d8899132SKalle Valo 
4746d8899132SKalle Valo 	/* Configure the hash seed for hash based reo dest ring selection */
4747d8899132SKalle Valo 	ath12k_wmi_pdev_lro_cfg(ar, ar->pdev->pdev_id);
4748d8899132SKalle Valo 
4749d8899132SKalle Valo 	/* allow device to enter IMPS */
4750d8899132SKalle Valo 	if (ab->hw_params->idle_ps) {
4751d8899132SKalle Valo 		ret = ath12k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_IDLE_PS_CONFIG,
4752d8899132SKalle Valo 						1, pdev->pdev_id);
4753d8899132SKalle Valo 		if (ret) {
4754d8899132SKalle Valo 			ath12k_err(ab, "failed to enable idle ps: %d\n", ret);
4755d8899132SKalle Valo 			goto err;
4756d8899132SKalle Valo 		}
4757d8899132SKalle Valo 	}
4758d8899132SKalle Valo 
4759d8899132SKalle Valo 	mutex_unlock(&ar->conf_mutex);
4760d8899132SKalle Valo 
4761d8899132SKalle Valo 	rcu_assign_pointer(ab->pdevs_active[ar->pdev_idx],
4762d8899132SKalle Valo 			   &ab->pdevs[ar->pdev_idx]);
4763d8899132SKalle Valo 
4764d8899132SKalle Valo 	return 0;
4765d8899132SKalle Valo 
4766d8899132SKalle Valo err:
4767d8899132SKalle Valo 	ar->state = ATH12K_STATE_OFF;
4768d8899132SKalle Valo 	mutex_unlock(&ar->conf_mutex);
4769d8899132SKalle Valo 
4770d8899132SKalle Valo 	return ret;
4771d8899132SKalle Valo }
4772d8899132SKalle Valo 
4773d8899132SKalle Valo static void ath12k_mac_op_stop(struct ieee80211_hw *hw)
4774d8899132SKalle Valo {
4775d8899132SKalle Valo 	struct ath12k *ar = hw->priv;
4776d8899132SKalle Valo 	struct htt_ppdu_stats_info *ppdu_stats, *tmp;
4777d8899132SKalle Valo 	int ret;
4778d8899132SKalle Valo 
4779d8899132SKalle Valo 	ath12k_mac_drain_tx(ar);
4780d8899132SKalle Valo 
4781d8899132SKalle Valo 	mutex_lock(&ar->conf_mutex);
4782d8899132SKalle Valo 	ret = ath12k_mac_config_mon_status_default(ar, false);
4783d8899132SKalle Valo 	if (ret && (ret != -ENOTSUPP))
4784d8899132SKalle Valo 		ath12k_err(ar->ab, "failed to clear rx_filter for monitor status ring: (%d)\n",
4785d8899132SKalle Valo 			   ret);
4786d8899132SKalle Valo 
4787d8899132SKalle Valo 	clear_bit(ATH12K_CAC_RUNNING, &ar->dev_flags);
4788d8899132SKalle Valo 	ar->state = ATH12K_STATE_OFF;
4789d8899132SKalle Valo 	mutex_unlock(&ar->conf_mutex);
4790d8899132SKalle Valo 
4791d8899132SKalle Valo 	cancel_delayed_work_sync(&ar->scan.timeout);
4792d8899132SKalle Valo 	cancel_work_sync(&ar->regd_update_work);
4793d8899132SKalle Valo 
4794d8899132SKalle Valo 	spin_lock_bh(&ar->data_lock);
4795d8899132SKalle Valo 	list_for_each_entry_safe(ppdu_stats, tmp, &ar->ppdu_stats_info, list) {
4796d8899132SKalle Valo 		list_del(&ppdu_stats->list);
4797d8899132SKalle Valo 		kfree(ppdu_stats);
4798d8899132SKalle Valo 	}
4799d8899132SKalle Valo 	spin_unlock_bh(&ar->data_lock);
4800d8899132SKalle Valo 
4801d8899132SKalle Valo 	rcu_assign_pointer(ar->ab->pdevs_active[ar->pdev_idx], NULL);
4802d8899132SKalle Valo 
4803d8899132SKalle Valo 	synchronize_rcu();
4804d8899132SKalle Valo 
4805d8899132SKalle Valo 	atomic_set(&ar->num_pending_mgmt_tx, 0);
4806d8899132SKalle Valo }
4807d8899132SKalle Valo 
4808d8899132SKalle Valo static u8
4809d8899132SKalle Valo ath12k_mac_get_vdev_stats_id(struct ath12k_vif *arvif)
4810d8899132SKalle Valo {
4811d8899132SKalle Valo 	struct ath12k_base *ab = arvif->ar->ab;
4812d8899132SKalle Valo 	u8 vdev_stats_id = 0;
4813d8899132SKalle Valo 
4814d8899132SKalle Valo 	do {
4815d8899132SKalle Valo 		if (ab->free_vdev_stats_id_map & (1LL << vdev_stats_id)) {
4816d8899132SKalle Valo 			vdev_stats_id++;
4817d8899132SKalle Valo 			if (vdev_stats_id <= ATH12K_INVAL_VDEV_STATS_ID) {
4818d8899132SKalle Valo 				vdev_stats_id = ATH12K_INVAL_VDEV_STATS_ID;
4819d8899132SKalle Valo 				break;
4820d8899132SKalle Valo 			}
4821d8899132SKalle Valo 		} else {
4822d8899132SKalle Valo 			ab->free_vdev_stats_id_map |= (1LL << vdev_stats_id);
4823d8899132SKalle Valo 			break;
4824d8899132SKalle Valo 		}
4825d8899132SKalle Valo 	} while (vdev_stats_id);
4826d8899132SKalle Valo 
4827d8899132SKalle Valo 	arvif->vdev_stats_id = vdev_stats_id;
4828d8899132SKalle Valo 	return vdev_stats_id;
4829d8899132SKalle Valo }
4830d8899132SKalle Valo 
4831d8899132SKalle Valo static void ath12k_mac_setup_vdev_create_arg(struct ath12k_vif *arvif,
4832d8899132SKalle Valo 					     struct ath12k_wmi_vdev_create_arg *arg)
4833d8899132SKalle Valo {
4834d8899132SKalle Valo 	struct ath12k *ar = arvif->ar;
4835d8899132SKalle Valo 	struct ath12k_pdev *pdev = ar->pdev;
4836d8899132SKalle Valo 
4837d8899132SKalle Valo 	arg->if_id = arvif->vdev_id;
4838d8899132SKalle Valo 	arg->type = arvif->vdev_type;
4839d8899132SKalle Valo 	arg->subtype = arvif->vdev_subtype;
4840d8899132SKalle Valo 	arg->pdev_id = pdev->pdev_id;
4841d8899132SKalle Valo 
4842d8899132SKalle Valo 	if (pdev->cap.supported_bands & WMI_HOST_WLAN_2G_CAP) {
4843d8899132SKalle Valo 		arg->chains[NL80211_BAND_2GHZ].tx = ar->num_tx_chains;
4844d8899132SKalle Valo 		arg->chains[NL80211_BAND_2GHZ].rx = ar->num_rx_chains;
4845d8899132SKalle Valo 	}
4846d8899132SKalle Valo 	if (pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP) {
4847d8899132SKalle Valo 		arg->chains[NL80211_BAND_5GHZ].tx = ar->num_tx_chains;
4848d8899132SKalle Valo 		arg->chains[NL80211_BAND_5GHZ].rx = ar->num_rx_chains;
4849d8899132SKalle Valo 	}
4850d8899132SKalle Valo 	if (pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP &&
4851d8899132SKalle Valo 	    ar->supports_6ghz) {
4852d8899132SKalle Valo 		arg->chains[NL80211_BAND_6GHZ].tx = ar->num_tx_chains;
4853d8899132SKalle Valo 		arg->chains[NL80211_BAND_6GHZ].rx = ar->num_rx_chains;
4854d8899132SKalle Valo 	}
4855d8899132SKalle Valo 
4856d8899132SKalle Valo 	arg->if_stats_id = ath12k_mac_get_vdev_stats_id(arvif);
4857d8899132SKalle Valo }
4858d8899132SKalle Valo 
4859d8899132SKalle Valo static u32
4860d8899132SKalle Valo ath12k_mac_prepare_he_mode(struct ath12k_pdev *pdev, u32 viftype)
4861d8899132SKalle Valo {
4862d8899132SKalle Valo 	struct ath12k_pdev_cap *pdev_cap = &pdev->cap;
4863d8899132SKalle Valo 	struct ath12k_band_cap *cap_band = NULL;
4864d8899132SKalle Valo 	u32 *hecap_phy_ptr = NULL;
4865d8899132SKalle Valo 	u32 hemode;
4866d8899132SKalle Valo 
4867d8899132SKalle Valo 	if (pdev->cap.supported_bands & WMI_HOST_WLAN_2G_CAP)
4868d8899132SKalle Valo 		cap_band = &pdev_cap->band[NL80211_BAND_2GHZ];
4869d8899132SKalle Valo 	else
4870d8899132SKalle Valo 		cap_band = &pdev_cap->band[NL80211_BAND_5GHZ];
4871d8899132SKalle Valo 
4872d8899132SKalle Valo 	hecap_phy_ptr = &cap_band->he_cap_phy_info[0];
4873d8899132SKalle Valo 
4874d8899132SKalle Valo 	hemode = u32_encode_bits(HE_SU_BFEE_ENABLE, HE_MODE_SU_TX_BFEE) |
4875d8899132SKalle Valo 		 u32_encode_bits(HECAP_PHY_SUBFMR_GET(hecap_phy_ptr),
4876d8899132SKalle Valo 				 HE_MODE_SU_TX_BFER) |
4877d8899132SKalle Valo 		 u32_encode_bits(HECAP_PHY_ULMUMIMO_GET(hecap_phy_ptr),
4878d8899132SKalle Valo 				 HE_MODE_UL_MUMIMO);
4879d8899132SKalle Valo 
4880d8899132SKalle Valo 	/* TODO: WDS and other modes */
4881d8899132SKalle Valo 	if (viftype == NL80211_IFTYPE_AP) {
4882d8899132SKalle Valo 		hemode |= u32_encode_bits(HECAP_PHY_MUBFMR_GET(hecap_phy_ptr),
4883d8899132SKalle Valo 					  HE_MODE_MU_TX_BFER) |
4884d8899132SKalle Valo 			  u32_encode_bits(HE_DL_MUOFDMA_ENABLE, HE_MODE_DL_OFDMA) |
4885d8899132SKalle Valo 			  u32_encode_bits(HE_UL_MUOFDMA_ENABLE, HE_MODE_UL_OFDMA);
4886d8899132SKalle Valo 	} else {
4887d8899132SKalle Valo 		hemode |= u32_encode_bits(HE_MU_BFEE_ENABLE, HE_MODE_MU_TX_BFEE);
4888d8899132SKalle Valo 	}
4889d8899132SKalle Valo 
4890d8899132SKalle Valo 	return hemode;
4891d8899132SKalle Valo }
4892d8899132SKalle Valo 
4893d8899132SKalle Valo static int ath12k_set_he_mu_sounding_mode(struct ath12k *ar,
4894d8899132SKalle Valo 					  struct ath12k_vif *arvif)
4895d8899132SKalle Valo {
4896d8899132SKalle Valo 	u32 param_id, param_value;
4897d8899132SKalle Valo 	struct ath12k_base *ab = ar->ab;
4898d8899132SKalle Valo 	int ret;
4899d8899132SKalle Valo 
4900d8899132SKalle Valo 	param_id = WMI_VDEV_PARAM_SET_HEMU_MODE;
4901d8899132SKalle Valo 	param_value = ath12k_mac_prepare_he_mode(ar->pdev, arvif->vif->type);
4902d8899132SKalle Valo 	ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
4903d8899132SKalle Valo 					    param_id, param_value);
4904d8899132SKalle Valo 	if (ret) {
4905d8899132SKalle Valo 		ath12k_warn(ab, "failed to set vdev %d HE MU mode: %d param_value %x\n",
4906d8899132SKalle Valo 			    arvif->vdev_id, ret, param_value);
4907d8899132SKalle Valo 		return ret;
4908d8899132SKalle Valo 	}
4909d8899132SKalle Valo 	param_id = WMI_VDEV_PARAM_SET_HE_SOUNDING_MODE;
4910d8899132SKalle Valo 	param_value =
4911d8899132SKalle Valo 		u32_encode_bits(HE_VHT_SOUNDING_MODE_ENABLE, HE_VHT_SOUNDING_MODE) |
4912d8899132SKalle Valo 		u32_encode_bits(HE_TRIG_NONTRIG_SOUNDING_MODE_ENABLE,
4913d8899132SKalle Valo 				HE_TRIG_NONTRIG_SOUNDING_MODE);
4914d8899132SKalle Valo 	ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
4915d8899132SKalle Valo 					    param_id, param_value);
4916d8899132SKalle Valo 	if (ret) {
4917d8899132SKalle Valo 		ath12k_warn(ab, "failed to set vdev %d HE MU mode: %d\n",
4918d8899132SKalle Valo 			    arvif->vdev_id, ret);
4919d8899132SKalle Valo 		return ret;
4920d8899132SKalle Valo 	}
4921d8899132SKalle Valo 	return ret;
4922d8899132SKalle Valo }
4923d8899132SKalle Valo 
4924d8899132SKalle Valo static void ath12k_mac_op_update_vif_offload(struct ieee80211_hw *hw,
4925d8899132SKalle Valo 					     struct ieee80211_vif *vif)
4926d8899132SKalle Valo {
4927d8899132SKalle Valo 	struct ath12k *ar = hw->priv;
4928d8899132SKalle Valo 	struct ath12k_base *ab = ar->ab;
4929d8899132SKalle Valo 	struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
4930d8899132SKalle Valo 	u32 param_id, param_value;
4931d8899132SKalle Valo 	int ret;
4932d8899132SKalle Valo 
4933d8899132SKalle Valo 	param_id = WMI_VDEV_PARAM_TX_ENCAP_TYPE;
4934d8899132SKalle Valo 	if (vif->type != NL80211_IFTYPE_STATION &&
4935d8899132SKalle Valo 	    vif->type != NL80211_IFTYPE_AP)
4936d8899132SKalle Valo 		vif->offload_flags &= ~(IEEE80211_OFFLOAD_ENCAP_ENABLED |
4937d8899132SKalle Valo 					IEEE80211_OFFLOAD_DECAP_ENABLED);
4938d8899132SKalle Valo 
4939d8899132SKalle Valo 	if (vif->offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED)
4940d8899132SKalle Valo 		arvif->tx_encap_type = ATH12K_HW_TXRX_ETHERNET;
4941d8899132SKalle Valo 	else if (test_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags))
4942d8899132SKalle Valo 		arvif->tx_encap_type = ATH12K_HW_TXRX_RAW;
4943d8899132SKalle Valo 	else
4944d8899132SKalle Valo 		arvif->tx_encap_type = ATH12K_HW_TXRX_NATIVE_WIFI;
4945d8899132SKalle Valo 
4946d8899132SKalle Valo 	ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
4947d8899132SKalle Valo 					    param_id, arvif->tx_encap_type);
4948d8899132SKalle Valo 	if (ret) {
4949d8899132SKalle Valo 		ath12k_warn(ab, "failed to set vdev %d tx encap mode: %d\n",
4950d8899132SKalle Valo 			    arvif->vdev_id, ret);
4951d8899132SKalle Valo 		vif->offload_flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED;
4952d8899132SKalle Valo 	}
4953d8899132SKalle Valo 
4954d8899132SKalle Valo 	param_id = WMI_VDEV_PARAM_RX_DECAP_TYPE;
4955d8899132SKalle Valo 	if (vif->offload_flags & IEEE80211_OFFLOAD_DECAP_ENABLED)
4956d8899132SKalle Valo 		param_value = ATH12K_HW_TXRX_ETHERNET;
4957d8899132SKalle Valo 	else if (test_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags))
4958d8899132SKalle Valo 		param_value = ATH12K_HW_TXRX_RAW;
4959d8899132SKalle Valo 	else
4960d8899132SKalle Valo 		param_value = ATH12K_HW_TXRX_NATIVE_WIFI;
4961d8899132SKalle Valo 
4962d8899132SKalle Valo 	ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
4963d8899132SKalle Valo 					    param_id, param_value);
4964d8899132SKalle Valo 	if (ret) {
4965d8899132SKalle Valo 		ath12k_warn(ab, "failed to set vdev %d rx decap mode: %d\n",
4966d8899132SKalle Valo 			    arvif->vdev_id, ret);
4967d8899132SKalle Valo 		vif->offload_flags &= ~IEEE80211_OFFLOAD_DECAP_ENABLED;
4968d8899132SKalle Valo 	}
4969d8899132SKalle Valo }
4970d8899132SKalle Valo 
4971d8899132SKalle Valo static int ath12k_mac_op_add_interface(struct ieee80211_hw *hw,
4972d8899132SKalle Valo 				       struct ieee80211_vif *vif)
4973d8899132SKalle Valo {
4974d8899132SKalle Valo 	struct ath12k *ar = hw->priv;
4975d8899132SKalle Valo 	struct ath12k_base *ab = ar->ab;
4976d8899132SKalle Valo 	struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
4977d8899132SKalle Valo 	struct ath12k_wmi_vdev_create_arg vdev_arg = {0};
4978d8899132SKalle Valo 	struct ath12k_wmi_peer_create_arg peer_param;
4979d8899132SKalle Valo 	u32 param_id, param_value;
4980d8899132SKalle Valo 	u16 nss;
4981d8899132SKalle Valo 	int i;
4982d8899132SKalle Valo 	int ret;
4983d8899132SKalle Valo 	int bit;
4984d8899132SKalle Valo 
4985d8899132SKalle Valo 	vif->driver_flags |= IEEE80211_VIF_SUPPORTS_UAPSD;
4986d8899132SKalle Valo 
4987d8899132SKalle Valo 	mutex_lock(&ar->conf_mutex);
4988d8899132SKalle Valo 
4989d8899132SKalle Valo 	if (vif->type == NL80211_IFTYPE_AP &&
4990d8899132SKalle Valo 	    ar->num_peers > (ar->max_num_peers - 1)) {
4991d8899132SKalle Valo 		ath12k_warn(ab, "failed to create vdev due to insufficient peer entry resource in firmware\n");
4992d8899132SKalle Valo 		ret = -ENOBUFS;
4993d8899132SKalle Valo 		goto err;
4994d8899132SKalle Valo 	}
4995d8899132SKalle Valo 
4996d8899132SKalle Valo 	if (ar->num_created_vdevs > (TARGET_NUM_VDEVS - 1)) {
4997d8899132SKalle Valo 		ath12k_warn(ab, "failed to create vdev, reached max vdev limit %d\n",
4998d8899132SKalle Valo 			    TARGET_NUM_VDEVS);
4999d8899132SKalle Valo 		ret = -EBUSY;
5000d8899132SKalle Valo 		goto err;
5001d8899132SKalle Valo 	}
5002d8899132SKalle Valo 
5003d8899132SKalle Valo 	memset(arvif, 0, sizeof(*arvif));
5004d8899132SKalle Valo 
5005d8899132SKalle Valo 	arvif->ar = ar;
5006d8899132SKalle Valo 	arvif->vif = vif;
5007d8899132SKalle Valo 
5008d8899132SKalle Valo 	INIT_LIST_HEAD(&arvif->list);
5009d8899132SKalle Valo 
5010d8899132SKalle Valo 	/* Should we initialize any worker to handle connection loss indication
5011d8899132SKalle Valo 	 * from firmware in sta mode?
5012d8899132SKalle Valo 	 */
5013d8899132SKalle Valo 
5014d8899132SKalle Valo 	for (i = 0; i < ARRAY_SIZE(arvif->bitrate_mask.control); i++) {
5015d8899132SKalle Valo 		arvif->bitrate_mask.control[i].legacy = 0xffffffff;
5016d8899132SKalle Valo 		memset(arvif->bitrate_mask.control[i].ht_mcs, 0xff,
5017d8899132SKalle Valo 		       sizeof(arvif->bitrate_mask.control[i].ht_mcs));
5018d8899132SKalle Valo 		memset(arvif->bitrate_mask.control[i].vht_mcs, 0xff,
5019d8899132SKalle Valo 		       sizeof(arvif->bitrate_mask.control[i].vht_mcs));
5020d8899132SKalle Valo 	}
5021d8899132SKalle Valo 
5022d8899132SKalle Valo 	bit = __ffs64(ab->free_vdev_map);
5023d8899132SKalle Valo 
5024d8899132SKalle Valo 	arvif->vdev_id = bit;
5025d8899132SKalle Valo 	arvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE;
5026d8899132SKalle Valo 
5027d8899132SKalle Valo 	switch (vif->type) {
5028d8899132SKalle Valo 	case NL80211_IFTYPE_UNSPECIFIED:
5029d8899132SKalle Valo 	case NL80211_IFTYPE_STATION:
5030d8899132SKalle Valo 		arvif->vdev_type = WMI_VDEV_TYPE_STA;
5031d8899132SKalle Valo 		break;
5032d8899132SKalle Valo 	case NL80211_IFTYPE_MESH_POINT:
5033d8899132SKalle Valo 		arvif->vdev_subtype = WMI_VDEV_SUBTYPE_MESH_11S;
5034d8899132SKalle Valo 		fallthrough;
5035d8899132SKalle Valo 	case NL80211_IFTYPE_AP:
5036d8899132SKalle Valo 		arvif->vdev_type = WMI_VDEV_TYPE_AP;
5037d8899132SKalle Valo 		break;
5038d8899132SKalle Valo 	case NL80211_IFTYPE_MONITOR:
5039d8899132SKalle Valo 		arvif->vdev_type = WMI_VDEV_TYPE_MONITOR;
5040d8899132SKalle Valo 		ar->monitor_vdev_id = bit;
5041d8899132SKalle Valo 		break;
5042d8899132SKalle Valo 	default:
5043d8899132SKalle Valo 		WARN_ON(1);
5044d8899132SKalle Valo 		break;
5045d8899132SKalle Valo 	}
5046d8899132SKalle Valo 
5047d8899132SKalle Valo 	ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac add interface id %d type %d subtype %d map %llx\n",
5048d8899132SKalle Valo 		   arvif->vdev_id, arvif->vdev_type, arvif->vdev_subtype,
5049d8899132SKalle Valo 		   ab->free_vdev_map);
5050d8899132SKalle Valo 
5051d8899132SKalle Valo 	vif->cab_queue = arvif->vdev_id % (ATH12K_HW_MAX_QUEUES - 1);
5052d8899132SKalle Valo 	for (i = 0; i < ARRAY_SIZE(vif->hw_queue); i++)
5053d8899132SKalle Valo 		vif->hw_queue[i] = i % (ATH12K_HW_MAX_QUEUES - 1);
5054d8899132SKalle Valo 
5055d8899132SKalle Valo 	ath12k_mac_setup_vdev_create_arg(arvif, &vdev_arg);
5056d8899132SKalle Valo 
5057d8899132SKalle Valo 	ret = ath12k_wmi_vdev_create(ar, vif->addr, &vdev_arg);
5058d8899132SKalle Valo 	if (ret) {
5059d8899132SKalle Valo 		ath12k_warn(ab, "failed to create WMI vdev %d: %d\n",
5060d8899132SKalle Valo 			    arvif->vdev_id, ret);
5061d8899132SKalle Valo 		goto err;
5062d8899132SKalle Valo 	}
5063d8899132SKalle Valo 
5064d8899132SKalle Valo 	ar->num_created_vdevs++;
5065d8899132SKalle Valo 	ath12k_dbg(ab, ATH12K_DBG_MAC, "vdev %pM created, vdev_id %d\n",
5066d8899132SKalle Valo 		   vif->addr, arvif->vdev_id);
5067d8899132SKalle Valo 	ar->allocated_vdev_map |= 1LL << arvif->vdev_id;
5068d8899132SKalle Valo 	ab->free_vdev_map &= ~(1LL << arvif->vdev_id);
5069d8899132SKalle Valo 
5070d8899132SKalle Valo 	spin_lock_bh(&ar->data_lock);
5071d8899132SKalle Valo 	list_add(&arvif->list, &ar->arvifs);
5072d8899132SKalle Valo 	spin_unlock_bh(&ar->data_lock);
5073d8899132SKalle Valo 
5074d8899132SKalle Valo 	ath12k_mac_op_update_vif_offload(hw, vif);
5075d8899132SKalle Valo 
5076d8899132SKalle Valo 	nss = hweight32(ar->cfg_tx_chainmask) ? : 1;
5077d8899132SKalle Valo 	ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
5078d8899132SKalle Valo 					    WMI_VDEV_PARAM_NSS, nss);
5079d8899132SKalle Valo 	if (ret) {
5080d8899132SKalle Valo 		ath12k_warn(ab, "failed to set vdev %d chainmask 0x%x, nss %d :%d\n",
5081d8899132SKalle Valo 			    arvif->vdev_id, ar->cfg_tx_chainmask, nss, ret);
5082d8899132SKalle Valo 		goto err_vdev_del;
5083d8899132SKalle Valo 	}
5084d8899132SKalle Valo 
5085d8899132SKalle Valo 	switch (arvif->vdev_type) {
5086d8899132SKalle Valo 	case WMI_VDEV_TYPE_AP:
5087d8899132SKalle Valo 		peer_param.vdev_id = arvif->vdev_id;
5088d8899132SKalle Valo 		peer_param.peer_addr = vif->addr;
5089d8899132SKalle Valo 		peer_param.peer_type = WMI_PEER_TYPE_DEFAULT;
5090d8899132SKalle Valo 		ret = ath12k_peer_create(ar, arvif, NULL, &peer_param);
5091d8899132SKalle Valo 		if (ret) {
5092d8899132SKalle Valo 			ath12k_warn(ab, "failed to vdev %d create peer for AP: %d\n",
5093d8899132SKalle Valo 				    arvif->vdev_id, ret);
5094d8899132SKalle Valo 			goto err_vdev_del;
5095d8899132SKalle Valo 		}
5096d8899132SKalle Valo 
5097d8899132SKalle Valo 		ret = ath12k_mac_set_kickout(arvif);
5098d8899132SKalle Valo 		if (ret) {
5099d8899132SKalle Valo 			ath12k_warn(ar->ab, "failed to set vdev %i kickout parameters: %d\n",
5100d8899132SKalle Valo 				    arvif->vdev_id, ret);
5101d8899132SKalle Valo 			goto err_peer_del;
5102d8899132SKalle Valo 		}
5103d8899132SKalle Valo 		break;
5104d8899132SKalle Valo 	case WMI_VDEV_TYPE_STA:
5105d8899132SKalle Valo 		param_id = WMI_STA_PS_PARAM_RX_WAKE_POLICY;
5106d8899132SKalle Valo 		param_value = WMI_STA_PS_RX_WAKE_POLICY_WAKE;
5107d8899132SKalle Valo 		ret = ath12k_wmi_set_sta_ps_param(ar, arvif->vdev_id,
5108d8899132SKalle Valo 						  param_id, param_value);
5109d8899132SKalle Valo 		if (ret) {
5110d8899132SKalle Valo 			ath12k_warn(ar->ab, "failed to set vdev %d RX wake policy: %d\n",
5111d8899132SKalle Valo 				    arvif->vdev_id, ret);
5112d8899132SKalle Valo 			goto err_peer_del;
5113d8899132SKalle Valo 		}
5114d8899132SKalle Valo 
5115d8899132SKalle Valo 		param_id = WMI_STA_PS_PARAM_TX_WAKE_THRESHOLD;
5116d8899132SKalle Valo 		param_value = WMI_STA_PS_TX_WAKE_THRESHOLD_ALWAYS;
5117d8899132SKalle Valo 		ret = ath12k_wmi_set_sta_ps_param(ar, arvif->vdev_id,
5118d8899132SKalle Valo 						  param_id, param_value);
5119d8899132SKalle Valo 		if (ret) {
5120d8899132SKalle Valo 			ath12k_warn(ar->ab, "failed to set vdev %d TX wake threshold: %d\n",
5121d8899132SKalle Valo 				    arvif->vdev_id, ret);
5122d8899132SKalle Valo 			goto err_peer_del;
5123d8899132SKalle Valo 		}
5124d8899132SKalle Valo 
5125d8899132SKalle Valo 		param_id = WMI_STA_PS_PARAM_PSPOLL_COUNT;
5126d8899132SKalle Valo 		param_value = WMI_STA_PS_PSPOLL_COUNT_NO_MAX;
5127d8899132SKalle Valo 		ret = ath12k_wmi_set_sta_ps_param(ar, arvif->vdev_id,
5128d8899132SKalle Valo 						  param_id, param_value);
5129d8899132SKalle Valo 		if (ret) {
5130d8899132SKalle Valo 			ath12k_warn(ar->ab, "failed to set vdev %d pspoll count: %d\n",
5131d8899132SKalle Valo 				    arvif->vdev_id, ret);
5132d8899132SKalle Valo 			goto err_peer_del;
5133d8899132SKalle Valo 		}
5134d8899132SKalle Valo 
5135d8899132SKalle Valo 		ret = ath12k_wmi_pdev_set_ps_mode(ar, arvif->vdev_id, false);
5136d8899132SKalle Valo 		if (ret) {
5137d8899132SKalle Valo 			ath12k_warn(ar->ab, "failed to disable vdev %d ps mode: %d\n",
5138d8899132SKalle Valo 				    arvif->vdev_id, ret);
5139d8899132SKalle Valo 			goto err_peer_del;
5140d8899132SKalle Valo 		}
5141d8899132SKalle Valo 		break;
5142d8899132SKalle Valo 	default:
5143d8899132SKalle Valo 		break;
5144d8899132SKalle Valo 	}
5145d8899132SKalle Valo 
5146d8899132SKalle Valo 	arvif->txpower = vif->bss_conf.txpower;
5147d8899132SKalle Valo 	ret = ath12k_mac_txpower_recalc(ar);
5148d8899132SKalle Valo 	if (ret)
5149d8899132SKalle Valo 		goto err_peer_del;
5150d8899132SKalle Valo 
5151d8899132SKalle Valo 	param_id = WMI_VDEV_PARAM_RTS_THRESHOLD;
5152d8899132SKalle Valo 	param_value = ar->hw->wiphy->rts_threshold;
5153d8899132SKalle Valo 	ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
5154d8899132SKalle Valo 					    param_id, param_value);
5155d8899132SKalle Valo 	if (ret) {
5156d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to set rts threshold for vdev %d: %d\n",
5157d8899132SKalle Valo 			    arvif->vdev_id, ret);
5158d8899132SKalle Valo 	}
5159d8899132SKalle Valo 
5160d8899132SKalle Valo 	ath12k_dp_vdev_tx_attach(ar, arvif);
5161d8899132SKalle Valo 
5162d8899132SKalle Valo 	if (vif->type != NL80211_IFTYPE_MONITOR && ar->monitor_conf_enabled)
5163d8899132SKalle Valo 		ath12k_mac_monitor_vdev_create(ar);
5164d8899132SKalle Valo 
5165d8899132SKalle Valo 	mutex_unlock(&ar->conf_mutex);
5166d8899132SKalle Valo 
5167d8899132SKalle Valo 	return ret;
5168d8899132SKalle Valo 
5169d8899132SKalle Valo err_peer_del:
5170d8899132SKalle Valo 	if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
5171d8899132SKalle Valo 		reinit_completion(&ar->peer_delete_done);
5172d8899132SKalle Valo 
5173d8899132SKalle Valo 		ret = ath12k_wmi_send_peer_delete_cmd(ar, vif->addr,
5174d8899132SKalle Valo 						      arvif->vdev_id);
5175d8899132SKalle Valo 		if (ret) {
5176d8899132SKalle Valo 			ath12k_warn(ar->ab, "failed to delete peer vdev_id %d addr %pM\n",
5177d8899132SKalle Valo 				    arvif->vdev_id, vif->addr);
5178d8899132SKalle Valo 			goto err;
5179d8899132SKalle Valo 		}
5180d8899132SKalle Valo 
5181d8899132SKalle Valo 		ret = ath12k_wait_for_peer_delete_done(ar, arvif->vdev_id,
5182d8899132SKalle Valo 						       vif->addr);
5183d8899132SKalle Valo 		if (ret)
5184d8899132SKalle Valo 			goto err;
5185d8899132SKalle Valo 
5186d8899132SKalle Valo 		ar->num_peers--;
5187d8899132SKalle Valo 	}
5188d8899132SKalle Valo 
5189d8899132SKalle Valo err_vdev_del:
5190d8899132SKalle Valo 	ath12k_wmi_vdev_delete(ar, arvif->vdev_id);
5191d8899132SKalle Valo 	ar->num_created_vdevs--;
5192d8899132SKalle Valo 	ar->allocated_vdev_map &= ~(1LL << arvif->vdev_id);
5193d8899132SKalle Valo 	ab->free_vdev_map |= 1LL << arvif->vdev_id;
5194d8899132SKalle Valo 	ab->free_vdev_stats_id_map &= ~(1LL << arvif->vdev_stats_id);
5195d8899132SKalle Valo 	spin_lock_bh(&ar->data_lock);
5196d8899132SKalle Valo 	list_del(&arvif->list);
5197d8899132SKalle Valo 	spin_unlock_bh(&ar->data_lock);
5198d8899132SKalle Valo 
5199d8899132SKalle Valo err:
5200d8899132SKalle Valo 	mutex_unlock(&ar->conf_mutex);
5201d8899132SKalle Valo 
5202d8899132SKalle Valo 	return ret;
5203d8899132SKalle Valo }
5204d8899132SKalle Valo 
5205d8899132SKalle Valo static void ath12k_mac_vif_unref(struct ath12k_dp *dp, struct ieee80211_vif *vif)
5206d8899132SKalle Valo {
5207d8899132SKalle Valo 	struct ath12k_tx_desc_info *tx_desc_info, *tmp1;
5208d8899132SKalle Valo 	struct ath12k_skb_cb *skb_cb;
5209d8899132SKalle Valo 	struct sk_buff *skb;
5210d8899132SKalle Valo 	int i;
5211d8899132SKalle Valo 
5212d8899132SKalle Valo 	for (i = 0; i < ATH12K_HW_MAX_QUEUES; i++) {
5213d8899132SKalle Valo 		spin_lock_bh(&dp->tx_desc_lock[i]);
5214d8899132SKalle Valo 
5215d8899132SKalle Valo 		list_for_each_entry_safe(tx_desc_info, tmp1, &dp->tx_desc_used_list[i],
5216d8899132SKalle Valo 					 list) {
5217d8899132SKalle Valo 			skb = tx_desc_info->skb;
5218d8899132SKalle Valo 			if (!skb)
5219d8899132SKalle Valo 				continue;
5220d8899132SKalle Valo 
5221d8899132SKalle Valo 			skb_cb = ATH12K_SKB_CB(skb);
5222d8899132SKalle Valo 			if (skb_cb->vif == vif)
5223d8899132SKalle Valo 				skb_cb->vif = NULL;
5224d8899132SKalle Valo 		}
5225d8899132SKalle Valo 
5226d8899132SKalle Valo 		spin_unlock_bh(&dp->tx_desc_lock[i]);
5227d8899132SKalle Valo 	}
5228d8899132SKalle Valo }
5229d8899132SKalle Valo 
5230d8899132SKalle Valo static void ath12k_mac_op_remove_interface(struct ieee80211_hw *hw,
5231d8899132SKalle Valo 					   struct ieee80211_vif *vif)
5232d8899132SKalle Valo {
5233d8899132SKalle Valo 	struct ath12k *ar = hw->priv;
5234d8899132SKalle Valo 	struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
5235d8899132SKalle Valo 	struct ath12k_base *ab = ar->ab;
5236d8899132SKalle Valo 	unsigned long time_left;
5237d8899132SKalle Valo 	int ret;
5238d8899132SKalle Valo 
5239d8899132SKalle Valo 	mutex_lock(&ar->conf_mutex);
5240d8899132SKalle Valo 
5241d8899132SKalle Valo 	ath12k_dbg(ab, ATH12K_DBG_MAC, "mac remove interface (vdev %d)\n",
5242d8899132SKalle Valo 		   arvif->vdev_id);
5243d8899132SKalle Valo 
5244d8899132SKalle Valo 	if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
5245d8899132SKalle Valo 		ret = ath12k_peer_delete(ar, arvif->vdev_id, vif->addr);
5246d8899132SKalle Valo 		if (ret)
5247d8899132SKalle Valo 			ath12k_warn(ab, "failed to submit AP self-peer removal on vdev %d: %d\n",
5248d8899132SKalle Valo 				    arvif->vdev_id, ret);
5249d8899132SKalle Valo 	}
5250d8899132SKalle Valo 
5251d8899132SKalle Valo 	reinit_completion(&ar->vdev_delete_done);
5252d8899132SKalle Valo 
5253d8899132SKalle Valo 	ret = ath12k_wmi_vdev_delete(ar, arvif->vdev_id);
5254d8899132SKalle Valo 	if (ret) {
5255d8899132SKalle Valo 		ath12k_warn(ab, "failed to delete WMI vdev %d: %d\n",
5256d8899132SKalle Valo 			    arvif->vdev_id, ret);
5257d8899132SKalle Valo 		goto err_vdev_del;
5258d8899132SKalle Valo 	}
5259d8899132SKalle Valo 
5260d8899132SKalle Valo 	time_left = wait_for_completion_timeout(&ar->vdev_delete_done,
5261d8899132SKalle Valo 						ATH12K_VDEV_DELETE_TIMEOUT_HZ);
5262d8899132SKalle Valo 	if (time_left == 0) {
5263d8899132SKalle Valo 		ath12k_warn(ab, "Timeout in receiving vdev delete response\n");
5264d8899132SKalle Valo 		goto err_vdev_del;
5265d8899132SKalle Valo 	}
5266d8899132SKalle Valo 
5267d8899132SKalle Valo 	if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
5268d8899132SKalle Valo 		ar->monitor_vdev_id = -1;
5269d8899132SKalle Valo 		ar->monitor_vdev_created = false;
5270d8899132SKalle Valo 	} else if (ar->monitor_vdev_created && !ar->monitor_started) {
5271d8899132SKalle Valo 		ret = ath12k_mac_monitor_vdev_delete(ar);
5272d8899132SKalle Valo 	}
5273d8899132SKalle Valo 
5274d8899132SKalle Valo 	ab->free_vdev_map |= 1LL << (arvif->vdev_id);
5275d8899132SKalle Valo 	ar->allocated_vdev_map &= ~(1LL << arvif->vdev_id);
5276d8899132SKalle Valo 	ab->free_vdev_stats_id_map &= ~(1LL << arvif->vdev_stats_id);
5277d8899132SKalle Valo 	ar->num_created_vdevs--;
5278d8899132SKalle Valo 
5279d8899132SKalle Valo 	ath12k_dbg(ab, ATH12K_DBG_MAC, "vdev %pM deleted, vdev_id %d\n",
5280d8899132SKalle Valo 		   vif->addr, arvif->vdev_id);
5281d8899132SKalle Valo 
5282d8899132SKalle Valo err_vdev_del:
5283d8899132SKalle Valo 	spin_lock_bh(&ar->data_lock);
5284d8899132SKalle Valo 	list_del(&arvif->list);
5285d8899132SKalle Valo 	spin_unlock_bh(&ar->data_lock);
5286d8899132SKalle Valo 
5287d8899132SKalle Valo 	ath12k_peer_cleanup(ar, arvif->vdev_id);
5288d8899132SKalle Valo 
5289d8899132SKalle Valo 	idr_for_each(&ar->txmgmt_idr,
5290d8899132SKalle Valo 		     ath12k_mac_vif_txmgmt_idr_remove, vif);
5291d8899132SKalle Valo 
5292d8899132SKalle Valo 	ath12k_mac_vif_unref(&ab->dp, vif);
5293d8899132SKalle Valo 	ath12k_dp_tx_put_bank_profile(&ab->dp, arvif->bank_id);
5294d8899132SKalle Valo 
5295d8899132SKalle Valo 	/* Recalc txpower for remaining vdev */
5296d8899132SKalle Valo 	ath12k_mac_txpower_recalc(ar);
5297d8899132SKalle Valo 	clear_bit(ATH12K_FLAG_MONITOR_ENABLED, &ar->monitor_flags);
5298d8899132SKalle Valo 
5299d8899132SKalle Valo 	/* TODO: recal traffic pause state based on the available vdevs */
5300d8899132SKalle Valo 
5301d8899132SKalle Valo 	mutex_unlock(&ar->conf_mutex);
5302d8899132SKalle Valo }
5303d8899132SKalle Valo 
5304d8899132SKalle Valo /* FIXME: Has to be verified. */
5305d8899132SKalle Valo #define SUPPORTED_FILTERS			\
5306d8899132SKalle Valo 	(FIF_ALLMULTI |				\
5307d8899132SKalle Valo 	FIF_CONTROL |				\
5308d8899132SKalle Valo 	FIF_PSPOLL |				\
5309d8899132SKalle Valo 	FIF_OTHER_BSS |				\
5310d8899132SKalle Valo 	FIF_BCN_PRBRESP_PROMISC |		\
5311d8899132SKalle Valo 	FIF_PROBE_REQ |				\
5312d8899132SKalle Valo 	FIF_FCSFAIL)
5313d8899132SKalle Valo 
5314d8899132SKalle Valo static void ath12k_mac_op_configure_filter(struct ieee80211_hw *hw,
5315d8899132SKalle Valo 					   unsigned int changed_flags,
5316d8899132SKalle Valo 					   unsigned int *total_flags,
5317d8899132SKalle Valo 					   u64 multicast)
5318d8899132SKalle Valo {
5319d8899132SKalle Valo 	struct ath12k *ar = hw->priv;
5320d8899132SKalle Valo 	bool reset_flag;
5321d8899132SKalle Valo 	int ret;
5322d8899132SKalle Valo 
5323d8899132SKalle Valo 	mutex_lock(&ar->conf_mutex);
5324d8899132SKalle Valo 
5325d8899132SKalle Valo 	changed_flags &= SUPPORTED_FILTERS;
5326d8899132SKalle Valo 	*total_flags &= SUPPORTED_FILTERS;
5327d8899132SKalle Valo 	ar->filter_flags = *total_flags;
5328d8899132SKalle Valo 
5329d8899132SKalle Valo 	/* For monitor mode */
5330d8899132SKalle Valo 	reset_flag = !(ar->filter_flags & FIF_BCN_PRBRESP_PROMISC);
5331d8899132SKalle Valo 
5332d8899132SKalle Valo 	ret = ath12k_dp_tx_htt_monitor_mode_ring_config(ar, reset_flag);
5333d8899132SKalle Valo 	if (!ret) {
5334d8899132SKalle Valo 		if (!reset_flag)
5335d8899132SKalle Valo 			set_bit(ATH12K_FLAG_MONITOR_ENABLED, &ar->monitor_flags);
5336d8899132SKalle Valo 		else
5337d8899132SKalle Valo 			clear_bit(ATH12K_FLAG_MONITOR_ENABLED, &ar->monitor_flags);
5338d8899132SKalle Valo 	} else {
5339d8899132SKalle Valo 		ath12k_warn(ar->ab,
5340d8899132SKalle Valo 			    "fail to set monitor filter: %d\n", ret);
5341d8899132SKalle Valo 	}
5342d8899132SKalle Valo 	ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
5343d8899132SKalle Valo 		   "changed_flags:0x%x, total_flags:0x%x, reset_flag:%d\n",
5344d8899132SKalle Valo 		   changed_flags, *total_flags, reset_flag);
5345d8899132SKalle Valo 
5346d8899132SKalle Valo 	mutex_unlock(&ar->conf_mutex);
5347d8899132SKalle Valo }
5348d8899132SKalle Valo 
5349d8899132SKalle Valo static int ath12k_mac_op_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
5350d8899132SKalle Valo {
5351d8899132SKalle Valo 	struct ath12k *ar = hw->priv;
5352d8899132SKalle Valo 
5353d8899132SKalle Valo 	mutex_lock(&ar->conf_mutex);
5354d8899132SKalle Valo 
5355d8899132SKalle Valo 	*tx_ant = ar->cfg_tx_chainmask;
5356d8899132SKalle Valo 	*rx_ant = ar->cfg_rx_chainmask;
5357d8899132SKalle Valo 
5358d8899132SKalle Valo 	mutex_unlock(&ar->conf_mutex);
5359d8899132SKalle Valo 
5360d8899132SKalle Valo 	return 0;
5361d8899132SKalle Valo }
5362d8899132SKalle Valo 
5363d8899132SKalle Valo static int ath12k_mac_op_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
5364d8899132SKalle Valo {
5365d8899132SKalle Valo 	struct ath12k *ar = hw->priv;
5366d8899132SKalle Valo 	int ret;
5367d8899132SKalle Valo 
5368d8899132SKalle Valo 	mutex_lock(&ar->conf_mutex);
5369d8899132SKalle Valo 	ret = __ath12k_set_antenna(ar, tx_ant, rx_ant);
5370d8899132SKalle Valo 	mutex_unlock(&ar->conf_mutex);
5371d8899132SKalle Valo 
5372d8899132SKalle Valo 	return ret;
5373d8899132SKalle Valo }
5374d8899132SKalle Valo 
5375d8899132SKalle Valo static int ath12k_mac_op_ampdu_action(struct ieee80211_hw *hw,
5376d8899132SKalle Valo 				      struct ieee80211_vif *vif,
5377d8899132SKalle Valo 				      struct ieee80211_ampdu_params *params)
5378d8899132SKalle Valo {
5379d8899132SKalle Valo 	struct ath12k *ar = hw->priv;
5380d8899132SKalle Valo 	int ret = -EINVAL;
5381d8899132SKalle Valo 
5382d8899132SKalle Valo 	mutex_lock(&ar->conf_mutex);
5383d8899132SKalle Valo 
5384d8899132SKalle Valo 	switch (params->action) {
5385d8899132SKalle Valo 	case IEEE80211_AMPDU_RX_START:
5386d8899132SKalle Valo 		ret = ath12k_dp_rx_ampdu_start(ar, params);
5387d8899132SKalle Valo 		break;
5388d8899132SKalle Valo 	case IEEE80211_AMPDU_RX_STOP:
5389d8899132SKalle Valo 		ret = ath12k_dp_rx_ampdu_stop(ar, params);
5390d8899132SKalle Valo 		break;
5391d8899132SKalle Valo 	case IEEE80211_AMPDU_TX_START:
5392d8899132SKalle Valo 	case IEEE80211_AMPDU_TX_STOP_CONT:
5393d8899132SKalle Valo 	case IEEE80211_AMPDU_TX_STOP_FLUSH:
5394d8899132SKalle Valo 	case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
5395d8899132SKalle Valo 	case IEEE80211_AMPDU_TX_OPERATIONAL:
5396d8899132SKalle Valo 		/* Tx A-MPDU aggregation offloaded to hw/fw so deny mac80211
5397d8899132SKalle Valo 		 * Tx aggregation requests.
5398d8899132SKalle Valo 		 */
5399d8899132SKalle Valo 		ret = -EOPNOTSUPP;
5400d8899132SKalle Valo 		break;
5401d8899132SKalle Valo 	}
5402d8899132SKalle Valo 
5403d8899132SKalle Valo 	mutex_unlock(&ar->conf_mutex);
5404d8899132SKalle Valo 
5405d8899132SKalle Valo 	return ret;
5406d8899132SKalle Valo }
5407d8899132SKalle Valo 
5408d8899132SKalle Valo static int ath12k_mac_op_add_chanctx(struct ieee80211_hw *hw,
5409d8899132SKalle Valo 				     struct ieee80211_chanctx_conf *ctx)
5410d8899132SKalle Valo {
5411d8899132SKalle Valo 	struct ath12k *ar = hw->priv;
5412d8899132SKalle Valo 	struct ath12k_base *ab = ar->ab;
5413d8899132SKalle Valo 
5414d8899132SKalle Valo 	ath12k_dbg(ab, ATH12K_DBG_MAC,
5415d8899132SKalle Valo 		   "mac chanctx add freq %u width %d ptr %pK\n",
5416d8899132SKalle Valo 		   ctx->def.chan->center_freq, ctx->def.width, ctx);
5417d8899132SKalle Valo 
5418d8899132SKalle Valo 	mutex_lock(&ar->conf_mutex);
5419d8899132SKalle Valo 
5420d8899132SKalle Valo 	spin_lock_bh(&ar->data_lock);
5421d8899132SKalle Valo 	/* TODO: In case of multiple channel context, populate rx_channel from
5422d8899132SKalle Valo 	 * Rx PPDU desc information.
5423d8899132SKalle Valo 	 */
5424d8899132SKalle Valo 	ar->rx_channel = ctx->def.chan;
5425d8899132SKalle Valo 	spin_unlock_bh(&ar->data_lock);
5426d8899132SKalle Valo 
5427d8899132SKalle Valo 	mutex_unlock(&ar->conf_mutex);
5428d8899132SKalle Valo 
5429d8899132SKalle Valo 	return 0;
5430d8899132SKalle Valo }
5431d8899132SKalle Valo 
5432d8899132SKalle Valo static void ath12k_mac_op_remove_chanctx(struct ieee80211_hw *hw,
5433d8899132SKalle Valo 					 struct ieee80211_chanctx_conf *ctx)
5434d8899132SKalle Valo {
5435d8899132SKalle Valo 	struct ath12k *ar = hw->priv;
5436d8899132SKalle Valo 	struct ath12k_base *ab = ar->ab;
5437d8899132SKalle Valo 
5438d8899132SKalle Valo 	ath12k_dbg(ab, ATH12K_DBG_MAC,
5439d8899132SKalle Valo 		   "mac chanctx remove freq %u width %d ptr %pK\n",
5440d8899132SKalle Valo 		   ctx->def.chan->center_freq, ctx->def.width, ctx);
5441d8899132SKalle Valo 
5442d8899132SKalle Valo 	mutex_lock(&ar->conf_mutex);
5443d8899132SKalle Valo 
5444d8899132SKalle Valo 	spin_lock_bh(&ar->data_lock);
5445d8899132SKalle Valo 	/* TODO: In case of there is one more channel context left, populate
5446d8899132SKalle Valo 	 * rx_channel with the channel of that remaining channel context.
5447d8899132SKalle Valo 	 */
5448d8899132SKalle Valo 	ar->rx_channel = NULL;
5449d8899132SKalle Valo 	spin_unlock_bh(&ar->data_lock);
5450d8899132SKalle Valo 
5451d8899132SKalle Valo 	mutex_unlock(&ar->conf_mutex);
5452d8899132SKalle Valo }
5453d8899132SKalle Valo 
5454d8899132SKalle Valo static int
5455d8899132SKalle Valo ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif,
5456d8899132SKalle Valo 			      const struct cfg80211_chan_def *chandef,
5457d8899132SKalle Valo 			      bool restart)
5458d8899132SKalle Valo {
5459d8899132SKalle Valo 	struct ath12k *ar = arvif->ar;
5460d8899132SKalle Valo 	struct ath12k_base *ab = ar->ab;
5461d8899132SKalle Valo 	struct wmi_vdev_start_req_arg arg = {};
5462d8899132SKalle Valo 	int he_support = arvif->vif->bss_conf.he_support;
5463d8899132SKalle Valo 	int ret;
5464d8899132SKalle Valo 
5465d8899132SKalle Valo 	lockdep_assert_held(&ar->conf_mutex);
5466d8899132SKalle Valo 
5467d8899132SKalle Valo 	reinit_completion(&ar->vdev_setup_done);
5468d8899132SKalle Valo 
5469d8899132SKalle Valo 	arg.vdev_id = arvif->vdev_id;
5470d8899132SKalle Valo 	arg.dtim_period = arvif->dtim_period;
5471d8899132SKalle Valo 	arg.bcn_intval = arvif->beacon_interval;
5472d8899132SKalle Valo 
5473d8899132SKalle Valo 	arg.freq = chandef->chan->center_freq;
5474d8899132SKalle Valo 	arg.band_center_freq1 = chandef->center_freq1;
5475d8899132SKalle Valo 	arg.band_center_freq2 = chandef->center_freq2;
5476d8899132SKalle Valo 	arg.mode = ath12k_phymodes[chandef->chan->band][chandef->width];
5477d8899132SKalle Valo 
5478d8899132SKalle Valo 	arg.min_power = 0;
5479d8899132SKalle Valo 	arg.max_power = chandef->chan->max_power * 2;
5480d8899132SKalle Valo 	arg.max_reg_power = chandef->chan->max_reg_power * 2;
5481d8899132SKalle Valo 	arg.max_antenna_gain = chandef->chan->max_antenna_gain * 2;
5482d8899132SKalle Valo 
5483d8899132SKalle Valo 	arg.pref_tx_streams = ar->num_tx_chains;
5484d8899132SKalle Valo 	arg.pref_rx_streams = ar->num_rx_chains;
5485d8899132SKalle Valo 
5486d8899132SKalle Valo 	if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
5487d8899132SKalle Valo 		arg.ssid = arvif->u.ap.ssid;
5488d8899132SKalle Valo 		arg.ssid_len = arvif->u.ap.ssid_len;
5489d8899132SKalle Valo 		arg.hidden_ssid = arvif->u.ap.hidden_ssid;
5490d8899132SKalle Valo 
5491d8899132SKalle Valo 		/* For now allow DFS for AP mode */
5492d8899132SKalle Valo 		arg.chan_radar = !!(chandef->chan->flags & IEEE80211_CHAN_RADAR);
5493d8899132SKalle Valo 
5494d8899132SKalle Valo 		arg.passive = arg.chan_radar;
5495d8899132SKalle Valo 
5496d8899132SKalle Valo 		spin_lock_bh(&ab->base_lock);
5497d8899132SKalle Valo 		arg.regdomain = ar->ab->dfs_region;
5498d8899132SKalle Valo 		spin_unlock_bh(&ab->base_lock);
5499d8899132SKalle Valo 
5500d8899132SKalle Valo 		/* TODO: Notify if secondary 80Mhz also needs radar detection */
5501d8899132SKalle Valo 		if (he_support) {
5502d8899132SKalle Valo 			ret = ath12k_set_he_mu_sounding_mode(ar, arvif);
5503d8899132SKalle Valo 			if (ret) {
5504d8899132SKalle Valo 				ath12k_warn(ar->ab, "failed to set he mode vdev %i\n",
5505d8899132SKalle Valo 					    arg.vdev_id);
5506d8899132SKalle Valo 				return ret;
5507d8899132SKalle Valo 			}
5508d8899132SKalle Valo 		}
5509d8899132SKalle Valo 	}
5510d8899132SKalle Valo 
5511d8899132SKalle Valo 	arg.passive |= !!(chandef->chan->flags & IEEE80211_CHAN_NO_IR);
5512d8899132SKalle Valo 
5513d8899132SKalle Valo 	ath12k_dbg(ab, ATH12K_DBG_MAC,
5514d8899132SKalle Valo 		   "mac vdev %d start center_freq %d phymode %s\n",
5515d8899132SKalle Valo 		   arg.vdev_id, arg.freq,
5516d8899132SKalle Valo 		   ath12k_mac_phymode_str(arg.mode));
5517d8899132SKalle Valo 
5518d8899132SKalle Valo 	ret = ath12k_wmi_vdev_start(ar, &arg, restart);
5519d8899132SKalle Valo 	if (ret) {
5520d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to %s WMI vdev %i\n",
5521d8899132SKalle Valo 			    restart ? "restart" : "start", arg.vdev_id);
5522d8899132SKalle Valo 		return ret;
5523d8899132SKalle Valo 	}
5524d8899132SKalle Valo 
5525d8899132SKalle Valo 	ret = ath12k_mac_vdev_setup_sync(ar);
5526d8899132SKalle Valo 	if (ret) {
5527d8899132SKalle Valo 		ath12k_warn(ab, "failed to synchronize setup for vdev %i %s: %d\n",
5528d8899132SKalle Valo 			    arg.vdev_id, restart ? "restart" : "start", ret);
5529d8899132SKalle Valo 		return ret;
5530d8899132SKalle Valo 	}
5531d8899132SKalle Valo 
5532d8899132SKalle Valo 	ar->num_started_vdevs++;
5533d8899132SKalle Valo 	ath12k_dbg(ab, ATH12K_DBG_MAC,  "vdev %pM started, vdev_id %d\n",
5534d8899132SKalle Valo 		   arvif->vif->addr, arvif->vdev_id);
5535d8899132SKalle Valo 
5536d8899132SKalle Valo 	/* Enable CAC Flag in the driver by checking the channel DFS cac time,
5537d8899132SKalle Valo 	 * i.e dfs_cac_ms value which will be valid only for radar channels
5538d8899132SKalle Valo 	 * and state as NL80211_DFS_USABLE which indicates CAC needs to be
5539d8899132SKalle Valo 	 * done before channel usage. This flags is used to drop rx packets.
5540d8899132SKalle Valo 	 * during CAC.
5541d8899132SKalle Valo 	 */
5542d8899132SKalle Valo 	/* TODO: Set the flag for other interface types as required */
5543d8899132SKalle Valo 	if (arvif->vdev_type == WMI_VDEV_TYPE_AP &&
5544d8899132SKalle Valo 	    chandef->chan->dfs_cac_ms &&
5545d8899132SKalle Valo 	    chandef->chan->dfs_state == NL80211_DFS_USABLE) {
5546d8899132SKalle Valo 		set_bit(ATH12K_CAC_RUNNING, &ar->dev_flags);
5547d8899132SKalle Valo 		ath12k_dbg(ab, ATH12K_DBG_MAC,
5548d8899132SKalle Valo 			   "CAC Started in chan_freq %d for vdev %d\n",
5549d8899132SKalle Valo 			   arg.freq, arg.vdev_id);
5550d8899132SKalle Valo 	}
5551d8899132SKalle Valo 
5552d8899132SKalle Valo 	ret = ath12k_mac_set_txbf_conf(arvif);
5553d8899132SKalle Valo 	if (ret)
5554d8899132SKalle Valo 		ath12k_warn(ab, "failed to set txbf conf for vdev %d: %d\n",
5555d8899132SKalle Valo 			    arvif->vdev_id, ret);
5556d8899132SKalle Valo 
5557d8899132SKalle Valo 	return 0;
5558d8899132SKalle Valo }
5559d8899132SKalle Valo 
5560d8899132SKalle Valo static int ath12k_mac_vdev_stop(struct ath12k_vif *arvif)
5561d8899132SKalle Valo {
5562d8899132SKalle Valo 	struct ath12k *ar = arvif->ar;
5563d8899132SKalle Valo 	int ret;
5564d8899132SKalle Valo 
5565d8899132SKalle Valo 	lockdep_assert_held(&ar->conf_mutex);
5566d8899132SKalle Valo 
5567d8899132SKalle Valo 	reinit_completion(&ar->vdev_setup_done);
5568d8899132SKalle Valo 
5569d8899132SKalle Valo 	ret = ath12k_wmi_vdev_stop(ar, arvif->vdev_id);
5570d8899132SKalle Valo 	if (ret) {
5571d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to stop WMI vdev %i: %d\n",
5572d8899132SKalle Valo 			    arvif->vdev_id, ret);
5573d8899132SKalle Valo 		goto err;
5574d8899132SKalle Valo 	}
5575d8899132SKalle Valo 
5576d8899132SKalle Valo 	ret = ath12k_mac_vdev_setup_sync(ar);
5577d8899132SKalle Valo 	if (ret) {
5578d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to synchronize setup for vdev %i: %d\n",
5579d8899132SKalle Valo 			    arvif->vdev_id, ret);
5580d8899132SKalle Valo 		goto err;
5581d8899132SKalle Valo 	}
5582d8899132SKalle Valo 
5583d8899132SKalle Valo 	WARN_ON(ar->num_started_vdevs == 0);
5584d8899132SKalle Valo 
5585d8899132SKalle Valo 	ar->num_started_vdevs--;
5586d8899132SKalle Valo 	ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "vdev %pM stopped, vdev_id %d\n",
5587d8899132SKalle Valo 		   arvif->vif->addr, arvif->vdev_id);
5588d8899132SKalle Valo 
5589d8899132SKalle Valo 	if (test_bit(ATH12K_CAC_RUNNING, &ar->dev_flags)) {
5590d8899132SKalle Valo 		clear_bit(ATH12K_CAC_RUNNING, &ar->dev_flags);
5591d8899132SKalle Valo 		ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "CAC Stopped for vdev %d\n",
5592d8899132SKalle Valo 			   arvif->vdev_id);
5593d8899132SKalle Valo 	}
5594d8899132SKalle Valo 
5595d8899132SKalle Valo 	return 0;
5596d8899132SKalle Valo err:
5597d8899132SKalle Valo 	return ret;
5598d8899132SKalle Valo }
5599d8899132SKalle Valo 
5600d8899132SKalle Valo static int ath12k_mac_vdev_start(struct ath12k_vif *arvif,
5601d8899132SKalle Valo 				 const struct cfg80211_chan_def *chandef)
5602d8899132SKalle Valo {
5603d8899132SKalle Valo 	return ath12k_mac_vdev_start_restart(arvif, chandef, false);
5604d8899132SKalle Valo }
5605d8899132SKalle Valo 
5606d8899132SKalle Valo static int ath12k_mac_vdev_restart(struct ath12k_vif *arvif,
5607d8899132SKalle Valo 				   const struct cfg80211_chan_def *chandef)
5608d8899132SKalle Valo {
5609d8899132SKalle Valo 	return ath12k_mac_vdev_start_restart(arvif, chandef, true);
5610d8899132SKalle Valo }
5611d8899132SKalle Valo 
5612d8899132SKalle Valo struct ath12k_mac_change_chanctx_arg {
5613d8899132SKalle Valo 	struct ieee80211_chanctx_conf *ctx;
5614d8899132SKalle Valo 	struct ieee80211_vif_chanctx_switch *vifs;
5615d8899132SKalle Valo 	int n_vifs;
5616d8899132SKalle Valo 	int next_vif;
5617d8899132SKalle Valo };
5618d8899132SKalle Valo 
5619d8899132SKalle Valo static void
5620d8899132SKalle Valo ath12k_mac_change_chanctx_cnt_iter(void *data, u8 *mac,
5621d8899132SKalle Valo 				   struct ieee80211_vif *vif)
5622d8899132SKalle Valo {
5623d8899132SKalle Valo 	struct ath12k_mac_change_chanctx_arg *arg = data;
5624d8899132SKalle Valo 
5625d8899132SKalle Valo 	if (rcu_access_pointer(vif->bss_conf.chanctx_conf) != arg->ctx)
5626d8899132SKalle Valo 		return;
5627d8899132SKalle Valo 
5628d8899132SKalle Valo 	arg->n_vifs++;
5629d8899132SKalle Valo }
5630d8899132SKalle Valo 
5631d8899132SKalle Valo static void
5632d8899132SKalle Valo ath12k_mac_change_chanctx_fill_iter(void *data, u8 *mac,
5633d8899132SKalle Valo 				    struct ieee80211_vif *vif)
5634d8899132SKalle Valo {
5635d8899132SKalle Valo 	struct ath12k_mac_change_chanctx_arg *arg = data;
5636d8899132SKalle Valo 	struct ieee80211_chanctx_conf *ctx;
5637d8899132SKalle Valo 
5638d8899132SKalle Valo 	ctx = rcu_access_pointer(vif->bss_conf.chanctx_conf);
5639d8899132SKalle Valo 	if (ctx != arg->ctx)
5640d8899132SKalle Valo 		return;
5641d8899132SKalle Valo 
5642d8899132SKalle Valo 	if (WARN_ON(arg->next_vif == arg->n_vifs))
5643d8899132SKalle Valo 		return;
5644d8899132SKalle Valo 
5645d8899132SKalle Valo 	arg->vifs[arg->next_vif].vif = vif;
5646d8899132SKalle Valo 	arg->vifs[arg->next_vif].old_ctx = ctx;
5647d8899132SKalle Valo 	arg->vifs[arg->next_vif].new_ctx = ctx;
5648d8899132SKalle Valo 	arg->next_vif++;
5649d8899132SKalle Valo }
5650d8899132SKalle Valo 
5651d8899132SKalle Valo static void
5652d8899132SKalle Valo ath12k_mac_update_vif_chan(struct ath12k *ar,
5653d8899132SKalle Valo 			   struct ieee80211_vif_chanctx_switch *vifs,
5654d8899132SKalle Valo 			   int n_vifs)
5655d8899132SKalle Valo {
5656d8899132SKalle Valo 	struct ath12k_base *ab = ar->ab;
5657d8899132SKalle Valo 	struct ath12k_vif *arvif;
5658d8899132SKalle Valo 	int ret;
5659d8899132SKalle Valo 	int i;
5660d8899132SKalle Valo 	bool monitor_vif = false;
5661d8899132SKalle Valo 
5662d8899132SKalle Valo 	lockdep_assert_held(&ar->conf_mutex);
5663d8899132SKalle Valo 
5664d8899132SKalle Valo 	for (i = 0; i < n_vifs; i++) {
5665d8899132SKalle Valo 		arvif = (void *)vifs[i].vif->drv_priv;
5666d8899132SKalle Valo 
5667d8899132SKalle Valo 		if (vifs[i].vif->type == NL80211_IFTYPE_MONITOR)
5668d8899132SKalle Valo 			monitor_vif = true;
5669d8899132SKalle Valo 
5670d8899132SKalle Valo 		ath12k_dbg(ab, ATH12K_DBG_MAC,
5671d8899132SKalle Valo 			   "mac chanctx switch vdev_id %i freq %u->%u width %d->%d\n",
5672d8899132SKalle Valo 			   arvif->vdev_id,
5673d8899132SKalle Valo 			   vifs[i].old_ctx->def.chan->center_freq,
5674d8899132SKalle Valo 			   vifs[i].new_ctx->def.chan->center_freq,
5675d8899132SKalle Valo 			   vifs[i].old_ctx->def.width,
5676d8899132SKalle Valo 			   vifs[i].new_ctx->def.width);
5677d8899132SKalle Valo 
5678d8899132SKalle Valo 		if (WARN_ON(!arvif->is_started))
5679d8899132SKalle Valo 			continue;
5680d8899132SKalle Valo 
5681d8899132SKalle Valo 		if (WARN_ON(!arvif->is_up))
5682d8899132SKalle Valo 			continue;
5683d8899132SKalle Valo 
5684d8899132SKalle Valo 		ret = ath12k_wmi_vdev_down(ar, arvif->vdev_id);
5685d8899132SKalle Valo 		if (ret) {
5686d8899132SKalle Valo 			ath12k_warn(ab, "failed to down vdev %d: %d\n",
5687d8899132SKalle Valo 				    arvif->vdev_id, ret);
5688d8899132SKalle Valo 			continue;
5689d8899132SKalle Valo 		}
5690d8899132SKalle Valo 	}
5691d8899132SKalle Valo 
5692d8899132SKalle Valo 	/* All relevant vdevs are downed and associated channel resources
5693d8899132SKalle Valo 	 * should be available for the channel switch now.
5694d8899132SKalle Valo 	 */
5695d8899132SKalle Valo 
5696d8899132SKalle Valo 	/* TODO: Update ar->rx_channel */
5697d8899132SKalle Valo 
5698d8899132SKalle Valo 	for (i = 0; i < n_vifs; i++) {
5699d8899132SKalle Valo 		arvif = (void *)vifs[i].vif->drv_priv;
5700d8899132SKalle Valo 
5701d8899132SKalle Valo 		if (WARN_ON(!arvif->is_started))
5702d8899132SKalle Valo 			continue;
5703d8899132SKalle Valo 
5704d8899132SKalle Valo 		if (WARN_ON(!arvif->is_up))
5705d8899132SKalle Valo 			continue;
5706d8899132SKalle Valo 
5707d8899132SKalle Valo 		ret = ath12k_mac_vdev_restart(arvif, &vifs[i].new_ctx->def);
5708d8899132SKalle Valo 		if (ret) {
5709d8899132SKalle Valo 			ath12k_warn(ab, "failed to restart vdev %d: %d\n",
5710d8899132SKalle Valo 				    arvif->vdev_id, ret);
5711d8899132SKalle Valo 			continue;
5712d8899132SKalle Valo 		}
5713d8899132SKalle Valo 
5714d8899132SKalle Valo 		ret = ath12k_mac_setup_bcn_tmpl(arvif);
5715d8899132SKalle Valo 		if (ret)
5716d8899132SKalle Valo 			ath12k_warn(ab, "failed to update bcn tmpl during csa: %d\n",
5717d8899132SKalle Valo 				    ret);
5718d8899132SKalle Valo 
5719d8899132SKalle Valo 		ret = ath12k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid,
5720d8899132SKalle Valo 					 arvif->bssid);
5721d8899132SKalle Valo 		if (ret) {
5722d8899132SKalle Valo 			ath12k_warn(ab, "failed to bring vdev up %d: %d\n",
5723d8899132SKalle Valo 				    arvif->vdev_id, ret);
5724d8899132SKalle Valo 			continue;
5725d8899132SKalle Valo 		}
5726d8899132SKalle Valo 	}
5727d8899132SKalle Valo 
5728d8899132SKalle Valo 	/* Restart the internal monitor vdev on new channel */
5729d8899132SKalle Valo 	if (!monitor_vif && ar->monitor_vdev_created) {
5730d8899132SKalle Valo 		if (!ath12k_mac_monitor_stop(ar))
5731d8899132SKalle Valo 			ath12k_mac_monitor_start(ar);
5732d8899132SKalle Valo 	}
5733d8899132SKalle Valo }
5734d8899132SKalle Valo 
5735d8899132SKalle Valo static void
5736d8899132SKalle Valo ath12k_mac_update_active_vif_chan(struct ath12k *ar,
5737d8899132SKalle Valo 				  struct ieee80211_chanctx_conf *ctx)
5738d8899132SKalle Valo {
5739d8899132SKalle Valo 	struct ath12k_mac_change_chanctx_arg arg = { .ctx = ctx };
5740d8899132SKalle Valo 
5741d8899132SKalle Valo 	lockdep_assert_held(&ar->conf_mutex);
5742d8899132SKalle Valo 
5743d8899132SKalle Valo 	ieee80211_iterate_active_interfaces_atomic(ar->hw,
5744d8899132SKalle Valo 						   IEEE80211_IFACE_ITER_NORMAL,
5745d8899132SKalle Valo 						   ath12k_mac_change_chanctx_cnt_iter,
5746d8899132SKalle Valo 						   &arg);
5747d8899132SKalle Valo 	if (arg.n_vifs == 0)
5748d8899132SKalle Valo 		return;
5749d8899132SKalle Valo 
5750d8899132SKalle Valo 	arg.vifs = kcalloc(arg.n_vifs, sizeof(arg.vifs[0]), GFP_KERNEL);
5751d8899132SKalle Valo 	if (!arg.vifs)
5752d8899132SKalle Valo 		return;
5753d8899132SKalle Valo 
5754d8899132SKalle Valo 	ieee80211_iterate_active_interfaces_atomic(ar->hw,
5755d8899132SKalle Valo 						   IEEE80211_IFACE_ITER_NORMAL,
5756d8899132SKalle Valo 						   ath12k_mac_change_chanctx_fill_iter,
5757d8899132SKalle Valo 						   &arg);
5758d8899132SKalle Valo 
5759d8899132SKalle Valo 	ath12k_mac_update_vif_chan(ar, arg.vifs, arg.n_vifs);
5760d8899132SKalle Valo 
5761d8899132SKalle Valo 	kfree(arg.vifs);
5762d8899132SKalle Valo }
5763d8899132SKalle Valo 
5764d8899132SKalle Valo static void ath12k_mac_op_change_chanctx(struct ieee80211_hw *hw,
5765d8899132SKalle Valo 					 struct ieee80211_chanctx_conf *ctx,
5766d8899132SKalle Valo 					 u32 changed)
5767d8899132SKalle Valo {
5768d8899132SKalle Valo 	struct ath12k *ar = hw->priv;
5769d8899132SKalle Valo 	struct ath12k_base *ab = ar->ab;
5770d8899132SKalle Valo 
5771d8899132SKalle Valo 	mutex_lock(&ar->conf_mutex);
5772d8899132SKalle Valo 
5773d8899132SKalle Valo 	ath12k_dbg(ab, ATH12K_DBG_MAC,
5774d8899132SKalle Valo 		   "mac chanctx change freq %u width %d ptr %pK changed %x\n",
5775d8899132SKalle Valo 		   ctx->def.chan->center_freq, ctx->def.width, ctx, changed);
5776d8899132SKalle Valo 
5777d8899132SKalle Valo 	/* This shouldn't really happen because channel switching should use
5778d8899132SKalle Valo 	 * switch_vif_chanctx().
5779d8899132SKalle Valo 	 */
5780d8899132SKalle Valo 	if (WARN_ON(changed & IEEE80211_CHANCTX_CHANGE_CHANNEL))
5781d8899132SKalle Valo 		goto unlock;
5782d8899132SKalle Valo 
5783d8899132SKalle Valo 	if (changed & IEEE80211_CHANCTX_CHANGE_WIDTH)
5784d8899132SKalle Valo 		ath12k_mac_update_active_vif_chan(ar, ctx);
5785d8899132SKalle Valo 
5786d8899132SKalle Valo 	/* TODO: Recalc radar detection */
5787d8899132SKalle Valo 
5788d8899132SKalle Valo unlock:
5789d8899132SKalle Valo 	mutex_unlock(&ar->conf_mutex);
5790d8899132SKalle Valo }
5791d8899132SKalle Valo 
5792d8899132SKalle Valo static int ath12k_start_vdev_delay(struct ieee80211_hw *hw,
5793d8899132SKalle Valo 				   struct ieee80211_vif *vif)
5794d8899132SKalle Valo {
5795d8899132SKalle Valo 	struct ath12k *ar = hw->priv;
5796d8899132SKalle Valo 	struct ath12k_base *ab = ar->ab;
5797d8899132SKalle Valo 	struct ath12k_vif *arvif = (void *)vif->drv_priv;
5798d8899132SKalle Valo 	int ret;
5799d8899132SKalle Valo 
5800d8899132SKalle Valo 	if (WARN_ON(arvif->is_started))
5801d8899132SKalle Valo 		return -EBUSY;
5802d8899132SKalle Valo 
5803d8899132SKalle Valo 	ret = ath12k_mac_vdev_start(arvif, &arvif->chanctx.def);
5804d8899132SKalle Valo 	if (ret) {
5805d8899132SKalle Valo 		ath12k_warn(ab, "failed to start vdev %i addr %pM on freq %d: %d\n",
5806d8899132SKalle Valo 			    arvif->vdev_id, vif->addr,
5807d8899132SKalle Valo 			    arvif->chanctx.def.chan->center_freq, ret);
5808d8899132SKalle Valo 		return ret;
5809d8899132SKalle Valo 	}
5810d8899132SKalle Valo 
5811d8899132SKalle Valo 	if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
5812d8899132SKalle Valo 		ret = ath12k_monitor_vdev_up(ar, arvif->vdev_id);
5813d8899132SKalle Valo 		if (ret) {
5814d8899132SKalle Valo 			ath12k_warn(ab, "failed put monitor up: %d\n", ret);
5815d8899132SKalle Valo 			return ret;
5816d8899132SKalle Valo 		}
5817d8899132SKalle Valo 	}
5818d8899132SKalle Valo 
5819d8899132SKalle Valo 	arvif->is_started = true;
5820d8899132SKalle Valo 
5821d8899132SKalle Valo 	/* TODO: Setup ps and cts/rts protection */
5822d8899132SKalle Valo 	return 0;
5823d8899132SKalle Valo }
5824d8899132SKalle Valo 
5825d8899132SKalle Valo static int
5826d8899132SKalle Valo ath12k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
5827d8899132SKalle Valo 				 struct ieee80211_vif *vif,
5828d8899132SKalle Valo 				 struct ieee80211_bss_conf *link_conf,
5829d8899132SKalle Valo 				 struct ieee80211_chanctx_conf *ctx)
5830d8899132SKalle Valo {
5831d8899132SKalle Valo 	struct ath12k *ar = hw->priv;
5832d8899132SKalle Valo 	struct ath12k_base *ab = ar->ab;
5833d8899132SKalle Valo 	struct ath12k_vif *arvif = (void *)vif->drv_priv;
5834d8899132SKalle Valo 	int ret;
5835d8899132SKalle Valo 	struct ath12k_wmi_peer_create_arg param;
5836d8899132SKalle Valo 
5837d8899132SKalle Valo 	mutex_lock(&ar->conf_mutex);
5838d8899132SKalle Valo 
5839d8899132SKalle Valo 	ath12k_dbg(ab, ATH12K_DBG_MAC,
5840d8899132SKalle Valo 		   "mac chanctx assign ptr %pK vdev_id %i\n",
5841d8899132SKalle Valo 		   ctx, arvif->vdev_id);
5842d8899132SKalle Valo 
5843d8899132SKalle Valo 	/* for some targets bss peer must be created before vdev_start */
5844d8899132SKalle Valo 	if (ab->hw_params->vdev_start_delay &&
5845d8899132SKalle Valo 	    arvif->vdev_type != WMI_VDEV_TYPE_AP &&
5846d8899132SKalle Valo 	    arvif->vdev_type != WMI_VDEV_TYPE_MONITOR &&
5847d8899132SKalle Valo 	    !ath12k_peer_exist_by_vdev_id(ab, arvif->vdev_id)) {
5848d8899132SKalle Valo 		memcpy(&arvif->chanctx, ctx, sizeof(*ctx));
5849d8899132SKalle Valo 		ret = 0;
5850d8899132SKalle Valo 		goto out;
5851d8899132SKalle Valo 	}
5852d8899132SKalle Valo 
5853d8899132SKalle Valo 	if (WARN_ON(arvif->is_started)) {
5854d8899132SKalle Valo 		ret = -EBUSY;
5855d8899132SKalle Valo 		goto out;
5856d8899132SKalle Valo 	}
5857d8899132SKalle Valo 
5858d8899132SKalle Valo 	if (ab->hw_params->vdev_start_delay &&
5859d8899132SKalle Valo 	    (arvif->vdev_type == WMI_VDEV_TYPE_AP ||
5860d8899132SKalle Valo 	    arvif->vdev_type == WMI_VDEV_TYPE_MONITOR)) {
5861d8899132SKalle Valo 		param.vdev_id = arvif->vdev_id;
5862d8899132SKalle Valo 		param.peer_type = WMI_PEER_TYPE_DEFAULT;
5863d8899132SKalle Valo 		param.peer_addr = ar->mac_addr;
5864d8899132SKalle Valo 
5865d8899132SKalle Valo 		ret = ath12k_peer_create(ar, arvif, NULL, &param);
5866d8899132SKalle Valo 		if (ret) {
5867d8899132SKalle Valo 			ath12k_warn(ab, "failed to create peer after vdev start delay: %d",
5868d8899132SKalle Valo 				    ret);
5869d8899132SKalle Valo 			goto out;
5870d8899132SKalle Valo 		}
5871d8899132SKalle Valo 	}
5872d8899132SKalle Valo 
5873d8899132SKalle Valo 	if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
5874d8899132SKalle Valo 		ret = ath12k_mac_monitor_start(ar);
5875d8899132SKalle Valo 		if (ret)
5876d8899132SKalle Valo 			goto out;
5877d8899132SKalle Valo 		arvif->is_started = true;
5878d8899132SKalle Valo 		goto out;
5879d8899132SKalle Valo 	}
5880d8899132SKalle Valo 
5881d8899132SKalle Valo 	ret = ath12k_mac_vdev_start(arvif, &ctx->def);
5882d8899132SKalle Valo 	if (ret) {
5883d8899132SKalle Valo 		ath12k_warn(ab, "failed to start vdev %i addr %pM on freq %d: %d\n",
5884d8899132SKalle Valo 			    arvif->vdev_id, vif->addr,
5885d8899132SKalle Valo 			    ctx->def.chan->center_freq, ret);
5886d8899132SKalle Valo 		goto out;
5887d8899132SKalle Valo 	}
5888d8899132SKalle Valo 
5889d8899132SKalle Valo 	if (arvif->vdev_type != WMI_VDEV_TYPE_MONITOR && ar->monitor_vdev_created)
5890d8899132SKalle Valo 		ath12k_mac_monitor_start(ar);
5891d8899132SKalle Valo 
5892d8899132SKalle Valo 	arvif->is_started = true;
5893d8899132SKalle Valo 
5894d8899132SKalle Valo 	/* TODO: Setup ps and cts/rts protection */
5895d8899132SKalle Valo 
5896d8899132SKalle Valo out:
5897d8899132SKalle Valo 	mutex_unlock(&ar->conf_mutex);
5898d8899132SKalle Valo 
5899d8899132SKalle Valo 	return ret;
5900d8899132SKalle Valo }
5901d8899132SKalle Valo 
5902d8899132SKalle Valo static void
5903d8899132SKalle Valo ath12k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw,
5904d8899132SKalle Valo 				   struct ieee80211_vif *vif,
5905d8899132SKalle Valo 				   struct ieee80211_bss_conf *link_conf,
5906d8899132SKalle Valo 				   struct ieee80211_chanctx_conf *ctx)
5907d8899132SKalle Valo {
5908d8899132SKalle Valo 	struct ath12k *ar = hw->priv;
5909d8899132SKalle Valo 	struct ath12k_base *ab = ar->ab;
5910d8899132SKalle Valo 	struct ath12k_vif *arvif = (void *)vif->drv_priv;
5911d8899132SKalle Valo 	int ret;
5912d8899132SKalle Valo 
5913d8899132SKalle Valo 	mutex_lock(&ar->conf_mutex);
5914d8899132SKalle Valo 
5915d8899132SKalle Valo 	ath12k_dbg(ab, ATH12K_DBG_MAC,
5916d8899132SKalle Valo 		   "mac chanctx unassign ptr %pK vdev_id %i\n",
5917d8899132SKalle Valo 		   ctx, arvif->vdev_id);
5918d8899132SKalle Valo 
5919d8899132SKalle Valo 	WARN_ON(!arvif->is_started);
5920d8899132SKalle Valo 
5921d8899132SKalle Valo 	if (ab->hw_params->vdev_start_delay &&
5922d8899132SKalle Valo 	    arvif->vdev_type == WMI_VDEV_TYPE_MONITOR &&
5923d8899132SKalle Valo 	    ath12k_peer_find_by_addr(ab, ar->mac_addr))
5924d8899132SKalle Valo 		ath12k_peer_delete(ar, arvif->vdev_id, ar->mac_addr);
5925d8899132SKalle Valo 
5926d8899132SKalle Valo 	if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
5927d8899132SKalle Valo 		ret = ath12k_mac_monitor_stop(ar);
5928d8899132SKalle Valo 		if (ret) {
5929d8899132SKalle Valo 			mutex_unlock(&ar->conf_mutex);
5930d8899132SKalle Valo 			return;
5931d8899132SKalle Valo 		}
5932d8899132SKalle Valo 
5933d8899132SKalle Valo 		arvif->is_started = false;
5934d8899132SKalle Valo 	}
5935d8899132SKalle Valo 
5936d8899132SKalle Valo 	ret = ath12k_mac_vdev_stop(arvif);
5937d8899132SKalle Valo 	if (ret)
5938d8899132SKalle Valo 		ath12k_warn(ab, "failed to stop vdev %i: %d\n",
5939d8899132SKalle Valo 			    arvif->vdev_id, ret);
5940d8899132SKalle Valo 
5941d8899132SKalle Valo 	arvif->is_started = false;
5942d8899132SKalle Valo 
5943d8899132SKalle Valo 	if (ab->hw_params->vdev_start_delay &&
5944d8899132SKalle Valo 	    arvif->vdev_type == WMI_VDEV_TYPE_MONITOR)
5945d8899132SKalle Valo 		ath12k_wmi_vdev_down(ar, arvif->vdev_id);
5946d8899132SKalle Valo 
5947d8899132SKalle Valo 	if (arvif->vdev_type != WMI_VDEV_TYPE_MONITOR &&
5948d8899132SKalle Valo 	    ar->num_started_vdevs == 1 && ar->monitor_vdev_created)
5949d8899132SKalle Valo 		ath12k_mac_monitor_stop(ar);
5950d8899132SKalle Valo 
5951d8899132SKalle Valo 	mutex_unlock(&ar->conf_mutex);
5952d8899132SKalle Valo }
5953d8899132SKalle Valo 
5954d8899132SKalle Valo static int
5955d8899132SKalle Valo ath12k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw,
5956d8899132SKalle Valo 				 struct ieee80211_vif_chanctx_switch *vifs,
5957d8899132SKalle Valo 				 int n_vifs,
5958d8899132SKalle Valo 				 enum ieee80211_chanctx_switch_mode mode)
5959d8899132SKalle Valo {
5960d8899132SKalle Valo 	struct ath12k *ar = hw->priv;
5961d8899132SKalle Valo 
5962d8899132SKalle Valo 	mutex_lock(&ar->conf_mutex);
5963d8899132SKalle Valo 
5964d8899132SKalle Valo 	ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
5965d8899132SKalle Valo 		   "mac chanctx switch n_vifs %d mode %d\n",
5966d8899132SKalle Valo 		   n_vifs, mode);
5967d8899132SKalle Valo 	ath12k_mac_update_vif_chan(ar, vifs, n_vifs);
5968d8899132SKalle Valo 
5969d8899132SKalle Valo 	mutex_unlock(&ar->conf_mutex);
5970d8899132SKalle Valo 
5971d8899132SKalle Valo 	return 0;
5972d8899132SKalle Valo }
5973d8899132SKalle Valo 
5974d8899132SKalle Valo static int
5975d8899132SKalle Valo ath12k_set_vdev_param_to_all_vifs(struct ath12k *ar, int param, u32 value)
5976d8899132SKalle Valo {
5977d8899132SKalle Valo 	struct ath12k_vif *arvif;
5978d8899132SKalle Valo 	int ret = 0;
5979d8899132SKalle Valo 
5980d8899132SKalle Valo 	mutex_lock(&ar->conf_mutex);
5981d8899132SKalle Valo 	list_for_each_entry(arvif, &ar->arvifs, list) {
5982d8899132SKalle Valo 		ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "setting mac vdev %d param %d value %d\n",
5983d8899132SKalle Valo 			   param, arvif->vdev_id, value);
5984d8899132SKalle Valo 
5985d8899132SKalle Valo 		ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
5986d8899132SKalle Valo 						    param, value);
5987d8899132SKalle Valo 		if (ret) {
5988d8899132SKalle Valo 			ath12k_warn(ar->ab, "failed to set param %d for vdev %d: %d\n",
5989d8899132SKalle Valo 				    param, arvif->vdev_id, ret);
5990d8899132SKalle Valo 			break;
5991d8899132SKalle Valo 		}
5992d8899132SKalle Valo 	}
5993d8899132SKalle Valo 	mutex_unlock(&ar->conf_mutex);
5994d8899132SKalle Valo 	return ret;
5995d8899132SKalle Valo }
5996d8899132SKalle Valo 
5997d8899132SKalle Valo /* mac80211 stores device specific RTS/Fragmentation threshold value,
5998d8899132SKalle Valo  * this is set interface specific to firmware from ath12k driver
5999d8899132SKalle Valo  */
6000d8899132SKalle Valo static int ath12k_mac_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
6001d8899132SKalle Valo {
6002d8899132SKalle Valo 	struct ath12k *ar = hw->priv;
6003d8899132SKalle Valo 	int param_id = WMI_VDEV_PARAM_RTS_THRESHOLD;
6004d8899132SKalle Valo 
6005d8899132SKalle Valo 	return ath12k_set_vdev_param_to_all_vifs(ar, param_id, value);
6006d8899132SKalle Valo }
6007d8899132SKalle Valo 
6008d8899132SKalle Valo static int ath12k_mac_op_set_frag_threshold(struct ieee80211_hw *hw, u32 value)
6009d8899132SKalle Valo {
6010d8899132SKalle Valo 	/* Even though there's a WMI vdev param for fragmentation threshold no
6011d8899132SKalle Valo 	 * known firmware actually implements it. Moreover it is not possible to
6012d8899132SKalle Valo 	 * rely frame fragmentation to mac80211 because firmware clears the
6013d8899132SKalle Valo 	 * "more fragments" bit in frame control making it impossible for remote
6014d8899132SKalle Valo 	 * devices to reassemble frames.
6015d8899132SKalle Valo 	 *
6016d8899132SKalle Valo 	 * Hence implement a dummy callback just to say fragmentation isn't
6017d8899132SKalle Valo 	 * supported. This effectively prevents mac80211 from doing frame
6018d8899132SKalle Valo 	 * fragmentation in software.
6019d8899132SKalle Valo 	 */
6020d8899132SKalle Valo 	return -EOPNOTSUPP;
6021d8899132SKalle Valo }
6022d8899132SKalle Valo 
6023d8899132SKalle Valo static void ath12k_mac_op_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
6024d8899132SKalle Valo 				u32 queues, bool drop)
6025d8899132SKalle Valo {
6026d8899132SKalle Valo 	struct ath12k *ar = hw->priv;
6027d8899132SKalle Valo 	long time_left;
6028d8899132SKalle Valo 
6029d8899132SKalle Valo 	if (drop)
6030d8899132SKalle Valo 		return;
6031d8899132SKalle Valo 
6032d8899132SKalle Valo 	time_left = wait_event_timeout(ar->dp.tx_empty_waitq,
6033d8899132SKalle Valo 				       (atomic_read(&ar->dp.num_tx_pending) == 0),
6034d8899132SKalle Valo 				       ATH12K_FLUSH_TIMEOUT);
6035d8899132SKalle Valo 	if (time_left == 0)
6036d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to flush transmit queue %ld\n", time_left);
60375189a8dbSKarthik M 
60385189a8dbSKarthik M 	time_left = wait_event_timeout(ar->txmgmt_empty_waitq,
60395189a8dbSKarthik M 				       (atomic_read(&ar->num_pending_mgmt_tx) == 0),
60405189a8dbSKarthik M 				       ATH12K_FLUSH_TIMEOUT);
60415189a8dbSKarthik M 	if (time_left == 0)
60425189a8dbSKarthik M 		ath12k_warn(ar->ab, "failed to flush mgmt transmit queue %ld\n",
60435189a8dbSKarthik M 			    time_left);
6044d8899132SKalle Valo }
6045d8899132SKalle Valo 
6046d8899132SKalle Valo static int
6047d8899132SKalle Valo ath12k_mac_bitrate_mask_num_ht_rates(struct ath12k *ar,
6048d8899132SKalle Valo 				     enum nl80211_band band,
6049d8899132SKalle Valo 				     const struct cfg80211_bitrate_mask *mask)
6050d8899132SKalle Valo {
6051d8899132SKalle Valo 	int num_rates = 0;
6052d8899132SKalle Valo 	int i;
6053d8899132SKalle Valo 
6054d8899132SKalle Valo 	for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++)
6055d8899132SKalle Valo 		num_rates += hweight16(mask->control[band].ht_mcs[i]);
6056d8899132SKalle Valo 
6057d8899132SKalle Valo 	return num_rates;
6058d8899132SKalle Valo }
6059d8899132SKalle Valo 
6060d8899132SKalle Valo static bool
6061d8899132SKalle Valo ath12k_mac_has_single_legacy_rate(struct ath12k *ar,
6062d8899132SKalle Valo 				  enum nl80211_band band,
6063d8899132SKalle Valo 				  const struct cfg80211_bitrate_mask *mask)
6064d8899132SKalle Valo {
6065d8899132SKalle Valo 	int num_rates = 0;
6066d8899132SKalle Valo 
6067d8899132SKalle Valo 	num_rates = hweight32(mask->control[band].legacy);
6068d8899132SKalle Valo 
6069d8899132SKalle Valo 	if (ath12k_mac_bitrate_mask_num_ht_rates(ar, band, mask))
6070d8899132SKalle Valo 		return false;
6071d8899132SKalle Valo 
6072d8899132SKalle Valo 	if (ath12k_mac_bitrate_mask_num_vht_rates(ar, band, mask))
6073d8899132SKalle Valo 		return false;
6074d8899132SKalle Valo 
6075d8899132SKalle Valo 	return num_rates == 1;
6076d8899132SKalle Valo }
6077d8899132SKalle Valo 
6078d8899132SKalle Valo static bool
6079d8899132SKalle Valo ath12k_mac_bitrate_mask_get_single_nss(struct ath12k *ar,
6080d8899132SKalle Valo 				       enum nl80211_band band,
6081d8899132SKalle Valo 				       const struct cfg80211_bitrate_mask *mask,
6082d8899132SKalle Valo 				       int *nss)
6083d8899132SKalle Valo {
6084d8899132SKalle Valo 	struct ieee80211_supported_band *sband = &ar->mac.sbands[band];
6085d8899132SKalle Valo 	u16 vht_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map);
6086d8899132SKalle Valo 	u8 ht_nss_mask = 0;
6087d8899132SKalle Valo 	u8 vht_nss_mask = 0;
6088d8899132SKalle Valo 	int i;
6089d8899132SKalle Valo 
6090d8899132SKalle Valo 	/* No need to consider legacy here. Basic rates are always present
6091d8899132SKalle Valo 	 * in bitrate mask
6092d8899132SKalle Valo 	 */
6093d8899132SKalle Valo 
6094d8899132SKalle Valo 	for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++) {
6095d8899132SKalle Valo 		if (mask->control[band].ht_mcs[i] == 0)
6096d8899132SKalle Valo 			continue;
6097d8899132SKalle Valo 		else if (mask->control[band].ht_mcs[i] ==
6098d8899132SKalle Valo 			 sband->ht_cap.mcs.rx_mask[i])
6099d8899132SKalle Valo 			ht_nss_mask |= BIT(i);
6100d8899132SKalle Valo 		else
6101d8899132SKalle Valo 			return false;
6102d8899132SKalle Valo 	}
6103d8899132SKalle Valo 
6104d8899132SKalle Valo 	for (i = 0; i < ARRAY_SIZE(mask->control[band].vht_mcs); i++) {
6105d8899132SKalle Valo 		if (mask->control[band].vht_mcs[i] == 0)
6106d8899132SKalle Valo 			continue;
6107d8899132SKalle Valo 		else if (mask->control[band].vht_mcs[i] ==
6108d8899132SKalle Valo 			 ath12k_mac_get_max_vht_mcs_map(vht_mcs_map, i))
6109d8899132SKalle Valo 			vht_nss_mask |= BIT(i);
6110d8899132SKalle Valo 		else
6111d8899132SKalle Valo 			return false;
6112d8899132SKalle Valo 	}
6113d8899132SKalle Valo 
6114d8899132SKalle Valo 	if (ht_nss_mask != vht_nss_mask)
6115d8899132SKalle Valo 		return false;
6116d8899132SKalle Valo 
6117d8899132SKalle Valo 	if (ht_nss_mask == 0)
6118d8899132SKalle Valo 		return false;
6119d8899132SKalle Valo 
6120d8899132SKalle Valo 	if (BIT(fls(ht_nss_mask)) - 1 != ht_nss_mask)
6121d8899132SKalle Valo 		return false;
6122d8899132SKalle Valo 
6123d8899132SKalle Valo 	*nss = fls(ht_nss_mask);
6124d8899132SKalle Valo 
6125d8899132SKalle Valo 	return true;
6126d8899132SKalle Valo }
6127d8899132SKalle Valo 
6128d8899132SKalle Valo static int
6129d8899132SKalle Valo ath12k_mac_get_single_legacy_rate(struct ath12k *ar,
6130d8899132SKalle Valo 				  enum nl80211_band band,
6131d8899132SKalle Valo 				  const struct cfg80211_bitrate_mask *mask,
6132d8899132SKalle Valo 				  u32 *rate, u8 *nss)
6133d8899132SKalle Valo {
6134d8899132SKalle Valo 	int rate_idx;
6135d8899132SKalle Valo 	u16 bitrate;
6136d8899132SKalle Valo 	u8 preamble;
6137d8899132SKalle Valo 	u8 hw_rate;
6138d8899132SKalle Valo 
6139d8899132SKalle Valo 	if (hweight32(mask->control[band].legacy) != 1)
6140d8899132SKalle Valo 		return -EINVAL;
6141d8899132SKalle Valo 
6142d8899132SKalle Valo 	rate_idx = ffs(mask->control[band].legacy) - 1;
6143d8899132SKalle Valo 
6144d8899132SKalle Valo 	if (band == NL80211_BAND_5GHZ || band == NL80211_BAND_6GHZ)
6145d8899132SKalle Valo 		rate_idx += ATH12K_MAC_FIRST_OFDM_RATE_IDX;
6146d8899132SKalle Valo 
6147d8899132SKalle Valo 	hw_rate = ath12k_legacy_rates[rate_idx].hw_value;
6148d8899132SKalle Valo 	bitrate = ath12k_legacy_rates[rate_idx].bitrate;
6149d8899132SKalle Valo 
6150d8899132SKalle Valo 	if (ath12k_mac_bitrate_is_cck(bitrate))
6151d8899132SKalle Valo 		preamble = WMI_RATE_PREAMBLE_CCK;
6152d8899132SKalle Valo 	else
6153d8899132SKalle Valo 		preamble = WMI_RATE_PREAMBLE_OFDM;
6154d8899132SKalle Valo 
6155d8899132SKalle Valo 	*nss = 1;
6156d8899132SKalle Valo 	*rate = ATH12K_HW_RATE_CODE(hw_rate, 0, preamble);
6157d8899132SKalle Valo 
6158d8899132SKalle Valo 	return 0;
6159d8899132SKalle Valo }
6160d8899132SKalle Valo 
6161d8899132SKalle Valo static int ath12k_mac_set_fixed_rate_params(struct ath12k_vif *arvif,
6162d8899132SKalle Valo 					    u32 rate, u8 nss, u8 sgi, u8 ldpc)
6163d8899132SKalle Valo {
6164d8899132SKalle Valo 	struct ath12k *ar = arvif->ar;
6165d8899132SKalle Valo 	u32 vdev_param;
6166d8899132SKalle Valo 	int ret;
6167d8899132SKalle Valo 
6168d8899132SKalle Valo 	lockdep_assert_held(&ar->conf_mutex);
6169d8899132SKalle Valo 
6170d8899132SKalle Valo 	ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac set fixed rate params vdev %i rate 0x%02x nss %u sgi %u\n",
6171d8899132SKalle Valo 		   arvif->vdev_id, rate, nss, sgi);
6172d8899132SKalle Valo 
6173d8899132SKalle Valo 	vdev_param = WMI_VDEV_PARAM_FIXED_RATE;
6174d8899132SKalle Valo 	ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
6175d8899132SKalle Valo 					    vdev_param, rate);
6176d8899132SKalle Valo 	if (ret) {
6177d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to set fixed rate param 0x%02x: %d\n",
6178d8899132SKalle Valo 			    rate, ret);
6179d8899132SKalle Valo 		return ret;
6180d8899132SKalle Valo 	}
6181d8899132SKalle Valo 
6182d8899132SKalle Valo 	vdev_param = WMI_VDEV_PARAM_NSS;
6183d8899132SKalle Valo 	ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
6184d8899132SKalle Valo 					    vdev_param, nss);
6185d8899132SKalle Valo 	if (ret) {
6186d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to set nss param %d: %d\n",
6187d8899132SKalle Valo 			    nss, ret);
6188d8899132SKalle Valo 		return ret;
6189d8899132SKalle Valo 	}
6190d8899132SKalle Valo 
6191d8899132SKalle Valo 	vdev_param = WMI_VDEV_PARAM_SGI;
6192d8899132SKalle Valo 	ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
6193d8899132SKalle Valo 					    vdev_param, sgi);
6194d8899132SKalle Valo 	if (ret) {
6195d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to set sgi param %d: %d\n",
6196d8899132SKalle Valo 			    sgi, ret);
6197d8899132SKalle Valo 		return ret;
6198d8899132SKalle Valo 	}
6199d8899132SKalle Valo 
6200d8899132SKalle Valo 	vdev_param = WMI_VDEV_PARAM_LDPC;
6201d8899132SKalle Valo 	ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
6202d8899132SKalle Valo 					    vdev_param, ldpc);
6203d8899132SKalle Valo 	if (ret) {
6204d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to set ldpc param %d: %d\n",
6205d8899132SKalle Valo 			    ldpc, ret);
6206d8899132SKalle Valo 		return ret;
6207d8899132SKalle Valo 	}
6208d8899132SKalle Valo 
6209d8899132SKalle Valo 	return 0;
6210d8899132SKalle Valo }
6211d8899132SKalle Valo 
6212d8899132SKalle Valo static bool
6213d8899132SKalle Valo ath12k_mac_vht_mcs_range_present(struct ath12k *ar,
6214d8899132SKalle Valo 				 enum nl80211_band band,
6215d8899132SKalle Valo 				 const struct cfg80211_bitrate_mask *mask)
6216d8899132SKalle Valo {
6217d8899132SKalle Valo 	int i;
6218d8899132SKalle Valo 	u16 vht_mcs;
6219d8899132SKalle Valo 
6220d8899132SKalle Valo 	for (i = 0; i < NL80211_VHT_NSS_MAX; i++) {
6221d8899132SKalle Valo 		vht_mcs = mask->control[band].vht_mcs[i];
6222d8899132SKalle Valo 
6223d8899132SKalle Valo 		switch (vht_mcs) {
6224d8899132SKalle Valo 		case 0:
6225d8899132SKalle Valo 		case BIT(8) - 1:
6226d8899132SKalle Valo 		case BIT(9) - 1:
6227d8899132SKalle Valo 		case BIT(10) - 1:
6228d8899132SKalle Valo 			break;
6229d8899132SKalle Valo 		default:
6230d8899132SKalle Valo 			return false;
6231d8899132SKalle Valo 		}
6232d8899132SKalle Valo 	}
6233d8899132SKalle Valo 
6234d8899132SKalle Valo 	return true;
6235d8899132SKalle Valo }
6236d8899132SKalle Valo 
6237d8899132SKalle Valo static void ath12k_mac_set_bitrate_mask_iter(void *data,
6238d8899132SKalle Valo 					     struct ieee80211_sta *sta)
6239d8899132SKalle Valo {
6240d8899132SKalle Valo 	struct ath12k_vif *arvif = data;
6241d8899132SKalle Valo 	struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv;
6242d8899132SKalle Valo 	struct ath12k *ar = arvif->ar;
6243d8899132SKalle Valo 
6244d8899132SKalle Valo 	spin_lock_bh(&ar->data_lock);
6245d8899132SKalle Valo 	arsta->changed |= IEEE80211_RC_SUPP_RATES_CHANGED;
6246d8899132SKalle Valo 	spin_unlock_bh(&ar->data_lock);
6247d8899132SKalle Valo 
6248d8899132SKalle Valo 	ieee80211_queue_work(ar->hw, &arsta->update_wk);
6249d8899132SKalle Valo }
6250d8899132SKalle Valo 
6251d8899132SKalle Valo static void ath12k_mac_disable_peer_fixed_rate(void *data,
6252d8899132SKalle Valo 					       struct ieee80211_sta *sta)
6253d8899132SKalle Valo {
6254d8899132SKalle Valo 	struct ath12k_vif *arvif = data;
6255d8899132SKalle Valo 	struct ath12k *ar = arvif->ar;
6256d8899132SKalle Valo 	int ret;
6257d8899132SKalle Valo 
6258d8899132SKalle Valo 	ret = ath12k_wmi_set_peer_param(ar, sta->addr,
6259d8899132SKalle Valo 					arvif->vdev_id,
6260d8899132SKalle Valo 					WMI_PEER_PARAM_FIXED_RATE,
6261d8899132SKalle Valo 					WMI_FIXED_RATE_NONE);
6262d8899132SKalle Valo 	if (ret)
6263d8899132SKalle Valo 		ath12k_warn(ar->ab,
6264d8899132SKalle Valo 			    "failed to disable peer fixed rate for STA %pM ret %d\n",
6265d8899132SKalle Valo 			    sta->addr, ret);
6266d8899132SKalle Valo }
6267d8899132SKalle Valo 
6268d8899132SKalle Valo static int
6269d8899132SKalle Valo ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
6270d8899132SKalle Valo 			       struct ieee80211_vif *vif,
6271d8899132SKalle Valo 			       const struct cfg80211_bitrate_mask *mask)
6272d8899132SKalle Valo {
6273d8899132SKalle Valo 	struct ath12k_vif *arvif = (void *)vif->drv_priv;
6274d8899132SKalle Valo 	struct cfg80211_chan_def def;
6275d8899132SKalle Valo 	struct ath12k *ar = arvif->ar;
6276d8899132SKalle Valo 	enum nl80211_band band;
6277d8899132SKalle Valo 	const u8 *ht_mcs_mask;
6278d8899132SKalle Valo 	const u16 *vht_mcs_mask;
6279d8899132SKalle Valo 	u32 rate;
6280d8899132SKalle Valo 	u8 nss;
6281d8899132SKalle Valo 	u8 sgi;
6282d8899132SKalle Valo 	u8 ldpc;
6283d8899132SKalle Valo 	int single_nss;
6284d8899132SKalle Valo 	int ret;
6285d8899132SKalle Valo 	int num_rates;
6286d8899132SKalle Valo 
6287d8899132SKalle Valo 	if (ath12k_mac_vif_chan(vif, &def))
6288d8899132SKalle Valo 		return -EPERM;
6289d8899132SKalle Valo 
6290d8899132SKalle Valo 	band = def.chan->band;
6291d8899132SKalle Valo 	ht_mcs_mask = mask->control[band].ht_mcs;
6292d8899132SKalle Valo 	vht_mcs_mask = mask->control[band].vht_mcs;
6293d8899132SKalle Valo 	ldpc = !!(ar->ht_cap_info & WMI_HT_CAP_LDPC);
6294d8899132SKalle Valo 
6295d8899132SKalle Valo 	sgi = mask->control[band].gi;
6296d8899132SKalle Valo 	if (sgi == NL80211_TXRATE_FORCE_LGI)
6297d8899132SKalle Valo 		return -EINVAL;
6298d8899132SKalle Valo 
6299d8899132SKalle Valo 	/* mac80211 doesn't support sending a fixed HT/VHT MCS alone, rather it
6300d8899132SKalle Valo 	 * requires passing at least one of used basic rates along with them.
6301d8899132SKalle Valo 	 * Fixed rate setting across different preambles(legacy, HT, VHT) is
6302d8899132SKalle Valo 	 * not supported by the FW. Hence use of FIXED_RATE vdev param is not
6303d8899132SKalle Valo 	 * suitable for setting single HT/VHT rates.
6304d8899132SKalle Valo 	 * But, there could be a single basic rate passed from userspace which
6305d8899132SKalle Valo 	 * can be done through the FIXED_RATE param.
6306d8899132SKalle Valo 	 */
6307d8899132SKalle Valo 	if (ath12k_mac_has_single_legacy_rate(ar, band, mask)) {
6308d8899132SKalle Valo 		ret = ath12k_mac_get_single_legacy_rate(ar, band, mask, &rate,
6309d8899132SKalle Valo 							&nss);
6310d8899132SKalle Valo 		if (ret) {
6311d8899132SKalle Valo 			ath12k_warn(ar->ab, "failed to get single legacy rate for vdev %i: %d\n",
6312d8899132SKalle Valo 				    arvif->vdev_id, ret);
6313d8899132SKalle Valo 			return ret;
6314d8899132SKalle Valo 		}
6315d8899132SKalle Valo 		ieee80211_iterate_stations_atomic(ar->hw,
6316d8899132SKalle Valo 						  ath12k_mac_disable_peer_fixed_rate,
6317d8899132SKalle Valo 						  arvif);
6318d8899132SKalle Valo 	} else if (ath12k_mac_bitrate_mask_get_single_nss(ar, band, mask,
6319d8899132SKalle Valo 							  &single_nss)) {
6320d8899132SKalle Valo 		rate = WMI_FIXED_RATE_NONE;
6321d8899132SKalle Valo 		nss = single_nss;
6322d8899132SKalle Valo 	} else {
6323d8899132SKalle Valo 		rate = WMI_FIXED_RATE_NONE;
6324d8899132SKalle Valo 		nss = min_t(u32, ar->num_tx_chains,
6325d8899132SKalle Valo 			    max(ath12k_mac_max_ht_nss(ht_mcs_mask),
6326d8899132SKalle Valo 				ath12k_mac_max_vht_nss(vht_mcs_mask)));
6327d8899132SKalle Valo 
6328d8899132SKalle Valo 		/* If multiple rates across different preambles are given
6329d8899132SKalle Valo 		 * we can reconfigure this info with all peers using PEER_ASSOC
6330d8899132SKalle Valo 		 * command with the below exception cases.
6331d8899132SKalle Valo 		 * - Single VHT Rate : peer_assoc command accommodates only MCS
6332d8899132SKalle Valo 		 * range values i.e 0-7, 0-8, 0-9 for VHT. Though mac80211
6333d8899132SKalle Valo 		 * mandates passing basic rates along with HT/VHT rates, FW
6334d8899132SKalle Valo 		 * doesn't allow switching from VHT to Legacy. Hence instead of
6335d8899132SKalle Valo 		 * setting legacy and VHT rates using RATEMASK_CMD vdev cmd,
6336d8899132SKalle Valo 		 * we could set this VHT rate as peer fixed rate param, which
6337d8899132SKalle Valo 		 * will override FIXED rate and FW rate control algorithm.
6338d8899132SKalle Valo 		 * If single VHT rate is passed along with HT rates, we select
6339d8899132SKalle Valo 		 * the VHT rate as fixed rate for vht peers.
6340d8899132SKalle Valo 		 * - Multiple VHT Rates : When Multiple VHT rates are given,this
6341d8899132SKalle Valo 		 * can be set using RATEMASK CMD which uses FW rate-ctl alg.
6342d8899132SKalle Valo 		 * TODO: Setting multiple VHT MCS and replacing peer_assoc with
6343d8899132SKalle Valo 		 * RATEMASK_CMDID can cover all use cases of setting rates
6344d8899132SKalle Valo 		 * across multiple preambles and rates within same type.
6345d8899132SKalle Valo 		 * But requires more validation of the command at this point.
6346d8899132SKalle Valo 		 */
6347d8899132SKalle Valo 
6348d8899132SKalle Valo 		num_rates = ath12k_mac_bitrate_mask_num_vht_rates(ar, band,
6349d8899132SKalle Valo 								  mask);
6350d8899132SKalle Valo 
6351d8899132SKalle Valo 		if (!ath12k_mac_vht_mcs_range_present(ar, band, mask) &&
6352d8899132SKalle Valo 		    num_rates > 1) {
6353d8899132SKalle Valo 			/* TODO: Handle multiple VHT MCS values setting using
6354d8899132SKalle Valo 			 * RATEMASK CMD
6355d8899132SKalle Valo 			 */
6356d8899132SKalle Valo 			ath12k_warn(ar->ab,
6357d8899132SKalle Valo 				    "Setting more than one MCS Value in bitrate mask not supported\n");
6358d8899132SKalle Valo 			return -EINVAL;
6359d8899132SKalle Valo 		}
6360d8899132SKalle Valo 
6361d8899132SKalle Valo 		ieee80211_iterate_stations_atomic(ar->hw,
6362d8899132SKalle Valo 						  ath12k_mac_disable_peer_fixed_rate,
6363d8899132SKalle Valo 						  arvif);
6364d8899132SKalle Valo 
6365d8899132SKalle Valo 		mutex_lock(&ar->conf_mutex);
6366d8899132SKalle Valo 
6367d8899132SKalle Valo 		arvif->bitrate_mask = *mask;
6368d8899132SKalle Valo 		ieee80211_iterate_stations_atomic(ar->hw,
6369d8899132SKalle Valo 						  ath12k_mac_set_bitrate_mask_iter,
6370d8899132SKalle Valo 						  arvif);
6371d8899132SKalle Valo 
6372d8899132SKalle Valo 		mutex_unlock(&ar->conf_mutex);
6373d8899132SKalle Valo 	}
6374d8899132SKalle Valo 
6375d8899132SKalle Valo 	mutex_lock(&ar->conf_mutex);
6376d8899132SKalle Valo 
6377d8899132SKalle Valo 	ret = ath12k_mac_set_fixed_rate_params(arvif, rate, nss, sgi, ldpc);
6378d8899132SKalle Valo 	if (ret) {
6379d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to set fixed rate params on vdev %i: %d\n",
6380d8899132SKalle Valo 			    arvif->vdev_id, ret);
6381d8899132SKalle Valo 	}
6382d8899132SKalle Valo 
6383d8899132SKalle Valo 	mutex_unlock(&ar->conf_mutex);
6384d8899132SKalle Valo 
6385d8899132SKalle Valo 	return ret;
6386d8899132SKalle Valo }
6387d8899132SKalle Valo 
6388d8899132SKalle Valo static void
6389d8899132SKalle Valo ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw,
6390d8899132SKalle Valo 				enum ieee80211_reconfig_type reconfig_type)
6391d8899132SKalle Valo {
6392d8899132SKalle Valo 	struct ath12k *ar = hw->priv;
6393d8899132SKalle Valo 	struct ath12k_base *ab = ar->ab;
6394d8899132SKalle Valo 	int recovery_count;
6395d8899132SKalle Valo 
6396d8899132SKalle Valo 	if (reconfig_type != IEEE80211_RECONFIG_TYPE_RESTART)
6397d8899132SKalle Valo 		return;
6398d8899132SKalle Valo 
6399d8899132SKalle Valo 	mutex_lock(&ar->conf_mutex);
6400d8899132SKalle Valo 
6401d8899132SKalle Valo 	if (ar->state == ATH12K_STATE_RESTARTED) {
6402d8899132SKalle Valo 		ath12k_warn(ar->ab, "pdev %d successfully recovered\n",
6403d8899132SKalle Valo 			    ar->pdev->pdev_id);
6404d8899132SKalle Valo 		ar->state = ATH12K_STATE_ON;
6405d8899132SKalle Valo 		ieee80211_wake_queues(ar->hw);
6406d8899132SKalle Valo 
6407d8899132SKalle Valo 		if (ab->is_reset) {
6408d8899132SKalle Valo 			recovery_count = atomic_inc_return(&ab->recovery_count);
6409d8899132SKalle Valo 			ath12k_dbg(ab, ATH12K_DBG_BOOT, "recovery count %d\n",
6410d8899132SKalle Valo 				   recovery_count);
6411d8899132SKalle Valo 			/* When there are multiple radios in an SOC,
6412d8899132SKalle Valo 			 * the recovery has to be done for each radio
6413d8899132SKalle Valo 			 */
6414d8899132SKalle Valo 			if (recovery_count == ab->num_radios) {
6415d8899132SKalle Valo 				atomic_dec(&ab->reset_count);
6416d8899132SKalle Valo 				complete(&ab->reset_complete);
6417d8899132SKalle Valo 				ab->is_reset = false;
6418d8899132SKalle Valo 				atomic_set(&ab->fail_cont_count, 0);
6419d8899132SKalle Valo 				ath12k_dbg(ab, ATH12K_DBG_BOOT, "reset success\n");
6420d8899132SKalle Valo 			}
6421d8899132SKalle Valo 		}
6422d8899132SKalle Valo 	}
6423d8899132SKalle Valo 
6424d8899132SKalle Valo 	mutex_unlock(&ar->conf_mutex);
6425d8899132SKalle Valo }
6426d8899132SKalle Valo 
6427d8899132SKalle Valo static void
6428d8899132SKalle Valo ath12k_mac_update_bss_chan_survey(struct ath12k *ar,
6429d8899132SKalle Valo 				  struct ieee80211_channel *channel)
6430d8899132SKalle Valo {
6431d8899132SKalle Valo 	int ret;
6432d8899132SKalle Valo 	enum wmi_bss_chan_info_req_type type = WMI_BSS_SURVEY_REQ_TYPE_READ;
6433d8899132SKalle Valo 
6434d8899132SKalle Valo 	lockdep_assert_held(&ar->conf_mutex);
6435d8899132SKalle Valo 
6436d8899132SKalle Valo 	if (!test_bit(WMI_TLV_SERVICE_BSS_CHANNEL_INFO_64, ar->ab->wmi_ab.svc_map) ||
6437d8899132SKalle Valo 	    ar->rx_channel != channel)
6438d8899132SKalle Valo 		return;
6439d8899132SKalle Valo 
6440d8899132SKalle Valo 	if (ar->scan.state != ATH12K_SCAN_IDLE) {
6441d8899132SKalle Valo 		ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
6442d8899132SKalle Valo 			   "ignoring bss chan info req while scanning..\n");
6443d8899132SKalle Valo 		return;
6444d8899132SKalle Valo 	}
6445d8899132SKalle Valo 
6446d8899132SKalle Valo 	reinit_completion(&ar->bss_survey_done);
6447d8899132SKalle Valo 
6448d8899132SKalle Valo 	ret = ath12k_wmi_pdev_bss_chan_info_request(ar, type);
6449d8899132SKalle Valo 	if (ret) {
6450d8899132SKalle Valo 		ath12k_warn(ar->ab, "failed to send pdev bss chan info request\n");
6451d8899132SKalle Valo 		return;
6452d8899132SKalle Valo 	}
6453d8899132SKalle Valo 
6454d8899132SKalle Valo 	ret = wait_for_completion_timeout(&ar->bss_survey_done, 3 * HZ);
6455d8899132SKalle Valo 	if (ret == 0)
6456d8899132SKalle Valo 		ath12k_warn(ar->ab, "bss channel survey timed out\n");
6457d8899132SKalle Valo }
6458d8899132SKalle Valo 
6459d8899132SKalle Valo static int ath12k_mac_op_get_survey(struct ieee80211_hw *hw, int idx,
6460d8899132SKalle Valo 				    struct survey_info *survey)
6461d8899132SKalle Valo {
6462d8899132SKalle Valo 	struct ath12k *ar = hw->priv;
6463d8899132SKalle Valo 	struct ieee80211_supported_band *sband;
6464d8899132SKalle Valo 	struct survey_info *ar_survey;
6465d8899132SKalle Valo 	int ret = 0;
6466d8899132SKalle Valo 
6467d8899132SKalle Valo 	if (idx >= ATH12K_NUM_CHANS)
6468d8899132SKalle Valo 		return -ENOENT;
6469d8899132SKalle Valo 
6470d8899132SKalle Valo 	ar_survey = &ar->survey[idx];
6471d8899132SKalle Valo 
6472d8899132SKalle Valo 	mutex_lock(&ar->conf_mutex);
6473d8899132SKalle Valo 
6474d8899132SKalle Valo 	sband = hw->wiphy->bands[NL80211_BAND_2GHZ];
6475d8899132SKalle Valo 	if (sband && idx >= sband->n_channels) {
6476d8899132SKalle Valo 		idx -= sband->n_channels;
6477d8899132SKalle Valo 		sband = NULL;
6478d8899132SKalle Valo 	}
6479d8899132SKalle Valo 
6480d8899132SKalle Valo 	if (!sband)
6481d8899132SKalle Valo 		sband = hw->wiphy->bands[NL80211_BAND_5GHZ];
6482d8899132SKalle Valo 
6483d8899132SKalle Valo 	if (!sband || idx >= sband->n_channels) {
6484d8899132SKalle Valo 		ret = -ENOENT;
6485d8899132SKalle Valo 		goto exit;
6486d8899132SKalle Valo 	}
6487d8899132SKalle Valo 
6488d8899132SKalle Valo 	ath12k_mac_update_bss_chan_survey(ar, &sband->channels[idx]);
6489d8899132SKalle Valo 
6490d8899132SKalle Valo 	spin_lock_bh(&ar->data_lock);
6491d8899132SKalle Valo 	memcpy(survey, ar_survey, sizeof(*survey));
6492d8899132SKalle Valo 	spin_unlock_bh(&ar->data_lock);
6493d8899132SKalle Valo 
6494d8899132SKalle Valo 	survey->channel = &sband->channels[idx];
6495d8899132SKalle Valo 
6496d8899132SKalle Valo 	if (ar->rx_channel == survey->channel)
6497d8899132SKalle Valo 		survey->filled |= SURVEY_INFO_IN_USE;
6498d8899132SKalle Valo 
6499d8899132SKalle Valo exit:
6500d8899132SKalle Valo 	mutex_unlock(&ar->conf_mutex);
6501d8899132SKalle Valo 	return ret;
6502d8899132SKalle Valo }
6503d8899132SKalle Valo 
6504d8899132SKalle Valo static void ath12k_mac_op_sta_statistics(struct ieee80211_hw *hw,
6505d8899132SKalle Valo 					 struct ieee80211_vif *vif,
6506d8899132SKalle Valo 					 struct ieee80211_sta *sta,
6507d8899132SKalle Valo 					 struct station_info *sinfo)
6508d8899132SKalle Valo {
6509d8899132SKalle Valo 	struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv;
6510d8899132SKalle Valo 
6511d8899132SKalle Valo 	sinfo->rx_duration = arsta->rx_duration;
6512d8899132SKalle Valo 	sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_DURATION);
6513d8899132SKalle Valo 
6514d8899132SKalle Valo 	sinfo->tx_duration = arsta->tx_duration;
6515d8899132SKalle Valo 	sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_DURATION);
6516d8899132SKalle Valo 
6517d8899132SKalle Valo 	if (!arsta->txrate.legacy && !arsta->txrate.nss)
6518d8899132SKalle Valo 		return;
6519d8899132SKalle Valo 
6520d8899132SKalle Valo 	if (arsta->txrate.legacy) {
6521d8899132SKalle Valo 		sinfo->txrate.legacy = arsta->txrate.legacy;
6522d8899132SKalle Valo 	} else {
6523d8899132SKalle Valo 		sinfo->txrate.mcs = arsta->txrate.mcs;
6524d8899132SKalle Valo 		sinfo->txrate.nss = arsta->txrate.nss;
6525d8899132SKalle Valo 		sinfo->txrate.bw = arsta->txrate.bw;
6526d8899132SKalle Valo 		sinfo->txrate.he_gi = arsta->txrate.he_gi;
6527d8899132SKalle Valo 		sinfo->txrate.he_dcm = arsta->txrate.he_dcm;
6528d8899132SKalle Valo 		sinfo->txrate.he_ru_alloc = arsta->txrate.he_ru_alloc;
6529d8899132SKalle Valo 	}
6530d8899132SKalle Valo 	sinfo->txrate.flags = arsta->txrate.flags;
6531d8899132SKalle Valo 	sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
6532d8899132SKalle Valo 
6533d8899132SKalle Valo 	/* TODO: Use real NF instead of default one. */
6534d8899132SKalle Valo 	sinfo->signal = arsta->rssi_comb + ATH12K_DEFAULT_NOISE_FLOOR;
6535d8899132SKalle Valo 	sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL);
6536d8899132SKalle Valo }
6537d8899132SKalle Valo 
6538d8899132SKalle Valo static const struct ieee80211_ops ath12k_ops = {
6539d8899132SKalle Valo 	.tx				= ath12k_mac_op_tx,
6540d8899132SKalle Valo 	.wake_tx_queue			= ieee80211_handle_wake_tx_queue,
6541d8899132SKalle Valo 	.start                          = ath12k_mac_op_start,
6542d8899132SKalle Valo 	.stop                           = ath12k_mac_op_stop,
6543d8899132SKalle Valo 	.reconfig_complete              = ath12k_mac_op_reconfig_complete,
6544d8899132SKalle Valo 	.add_interface                  = ath12k_mac_op_add_interface,
6545d8899132SKalle Valo 	.remove_interface		= ath12k_mac_op_remove_interface,
6546d8899132SKalle Valo 	.update_vif_offload		= ath12k_mac_op_update_vif_offload,
6547d8899132SKalle Valo 	.config                         = ath12k_mac_op_config,
6548d8899132SKalle Valo 	.bss_info_changed               = ath12k_mac_op_bss_info_changed,
6549d8899132SKalle Valo 	.configure_filter		= ath12k_mac_op_configure_filter,
6550d8899132SKalle Valo 	.hw_scan                        = ath12k_mac_op_hw_scan,
6551d8899132SKalle Valo 	.cancel_hw_scan                 = ath12k_mac_op_cancel_hw_scan,
6552d8899132SKalle Valo 	.set_key                        = ath12k_mac_op_set_key,
6553d8899132SKalle Valo 	.sta_state                      = ath12k_mac_op_sta_state,
6554d8899132SKalle Valo 	.sta_set_txpwr			= ath12k_mac_op_sta_set_txpwr,
6555d8899132SKalle Valo 	.sta_rc_update			= ath12k_mac_op_sta_rc_update,
6556d8899132SKalle Valo 	.conf_tx                        = ath12k_mac_op_conf_tx,
6557d8899132SKalle Valo 	.set_antenna			= ath12k_mac_op_set_antenna,
6558d8899132SKalle Valo 	.get_antenna			= ath12k_mac_op_get_antenna,
6559d8899132SKalle Valo 	.ampdu_action			= ath12k_mac_op_ampdu_action,
6560d8899132SKalle Valo 	.add_chanctx			= ath12k_mac_op_add_chanctx,
6561d8899132SKalle Valo 	.remove_chanctx			= ath12k_mac_op_remove_chanctx,
6562d8899132SKalle Valo 	.change_chanctx			= ath12k_mac_op_change_chanctx,
6563d8899132SKalle Valo 	.assign_vif_chanctx		= ath12k_mac_op_assign_vif_chanctx,
6564d8899132SKalle Valo 	.unassign_vif_chanctx		= ath12k_mac_op_unassign_vif_chanctx,
6565d8899132SKalle Valo 	.switch_vif_chanctx		= ath12k_mac_op_switch_vif_chanctx,
6566d8899132SKalle Valo 	.set_rts_threshold		= ath12k_mac_op_set_rts_threshold,
6567d8899132SKalle Valo 	.set_frag_threshold		= ath12k_mac_op_set_frag_threshold,
6568d8899132SKalle Valo 	.set_bitrate_mask		= ath12k_mac_op_set_bitrate_mask,
6569d8899132SKalle Valo 	.get_survey			= ath12k_mac_op_get_survey,
6570d8899132SKalle Valo 	.flush				= ath12k_mac_op_flush,
6571d8899132SKalle Valo 	.sta_statistics			= ath12k_mac_op_sta_statistics,
6572d8899132SKalle Valo };
6573d8899132SKalle Valo 
6574d8899132SKalle Valo static void ath12k_mac_update_ch_list(struct ath12k *ar,
6575d8899132SKalle Valo 				      struct ieee80211_supported_band *band,
6576d8899132SKalle Valo 				      u32 freq_low, u32 freq_high)
6577d8899132SKalle Valo {
6578d8899132SKalle Valo 	int i;
6579d8899132SKalle Valo 
6580d8899132SKalle Valo 	if (!(freq_low && freq_high))
6581d8899132SKalle Valo 		return;
6582d8899132SKalle Valo 
6583d8899132SKalle Valo 	for (i = 0; i < band->n_channels; i++) {
6584d8899132SKalle Valo 		if (band->channels[i].center_freq < freq_low ||
6585d8899132SKalle Valo 		    band->channels[i].center_freq > freq_high)
6586d8899132SKalle Valo 			band->channels[i].flags |= IEEE80211_CHAN_DISABLED;
6587d8899132SKalle Valo 	}
6588d8899132SKalle Valo }
6589d8899132SKalle Valo 
6590d8899132SKalle Valo static u32 ath12k_get_phy_id(struct ath12k *ar, u32 band)
6591d8899132SKalle Valo {
6592d8899132SKalle Valo 	struct ath12k_pdev *pdev = ar->pdev;
6593d8899132SKalle Valo 	struct ath12k_pdev_cap *pdev_cap = &pdev->cap;
6594d8899132SKalle Valo 
6595d8899132SKalle Valo 	if (band == WMI_HOST_WLAN_2G_CAP)
6596d8899132SKalle Valo 		return pdev_cap->band[NL80211_BAND_2GHZ].phy_id;
6597d8899132SKalle Valo 
6598d8899132SKalle Valo 	if (band == WMI_HOST_WLAN_5G_CAP)
6599d8899132SKalle Valo 		return pdev_cap->band[NL80211_BAND_5GHZ].phy_id;
6600d8899132SKalle Valo 
6601d8899132SKalle Valo 	ath12k_warn(ar->ab, "unsupported phy cap:%d\n", band);
6602d8899132SKalle Valo 
6603d8899132SKalle Valo 	return 0;
6604d8899132SKalle Valo }
6605d8899132SKalle Valo 
6606d8899132SKalle Valo static int ath12k_mac_setup_channels_rates(struct ath12k *ar,
6607d8899132SKalle Valo 					   u32 supported_bands)
6608d8899132SKalle Valo {
6609d8899132SKalle Valo 	struct ieee80211_supported_band *band;
6610d8899132SKalle Valo 	struct ath12k_wmi_hal_reg_capabilities_ext_arg *reg_cap;
6611d8899132SKalle Valo 	void *channels;
6612d8899132SKalle Valo 	u32 phy_id;
6613d8899132SKalle Valo 
6614d8899132SKalle Valo 	BUILD_BUG_ON((ARRAY_SIZE(ath12k_2ghz_channels) +
6615d8899132SKalle Valo 		      ARRAY_SIZE(ath12k_5ghz_channels) +
6616d8899132SKalle Valo 		      ARRAY_SIZE(ath12k_6ghz_channels)) !=
6617d8899132SKalle Valo 		     ATH12K_NUM_CHANS);
6618d8899132SKalle Valo 
6619d8899132SKalle Valo 	reg_cap = &ar->ab->hal_reg_cap[ar->pdev_idx];
6620d8899132SKalle Valo 
6621d8899132SKalle Valo 	if (supported_bands & WMI_HOST_WLAN_2G_CAP) {
6622d8899132SKalle Valo 		channels = kmemdup(ath12k_2ghz_channels,
6623d8899132SKalle Valo 				   sizeof(ath12k_2ghz_channels),
6624d8899132SKalle Valo 				   GFP_KERNEL);
6625d8899132SKalle Valo 		if (!channels)
6626d8899132SKalle Valo 			return -ENOMEM;
6627d8899132SKalle Valo 
6628d8899132SKalle Valo 		band = &ar->mac.sbands[NL80211_BAND_2GHZ];
6629d8899132SKalle Valo 		band->band = NL80211_BAND_2GHZ;
6630d8899132SKalle Valo 		band->n_channels = ARRAY_SIZE(ath12k_2ghz_channels);
6631d8899132SKalle Valo 		band->channels = channels;
6632d8899132SKalle Valo 		band->n_bitrates = ath12k_g_rates_size;
6633d8899132SKalle Valo 		band->bitrates = ath12k_g_rates;
6634d8899132SKalle Valo 		ar->hw->wiphy->bands[NL80211_BAND_2GHZ] = band;
6635d8899132SKalle Valo 
6636d8899132SKalle Valo 		if (ar->ab->hw_params->single_pdev_only) {
6637d8899132SKalle Valo 			phy_id = ath12k_get_phy_id(ar, WMI_HOST_WLAN_2G_CAP);
6638d8899132SKalle Valo 			reg_cap = &ar->ab->hal_reg_cap[phy_id];
6639d8899132SKalle Valo 		}
6640d8899132SKalle Valo 		ath12k_mac_update_ch_list(ar, band,
6641d8899132SKalle Valo 					  reg_cap->low_2ghz_chan,
6642d8899132SKalle Valo 					  reg_cap->high_2ghz_chan);
6643d8899132SKalle Valo 	}
6644d8899132SKalle Valo 
6645d8899132SKalle Valo 	if (supported_bands & WMI_HOST_WLAN_5G_CAP) {
6646d8899132SKalle Valo 		if (reg_cap->high_5ghz_chan >= ATH12K_MAX_6G_FREQ) {
6647d8899132SKalle Valo 			channels = kmemdup(ath12k_6ghz_channels,
6648d8899132SKalle Valo 					   sizeof(ath12k_6ghz_channels), GFP_KERNEL);
6649d8899132SKalle Valo 			if (!channels) {
6650d8899132SKalle Valo 				kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels);
6651d8899132SKalle Valo 				return -ENOMEM;
6652d8899132SKalle Valo 			}
6653d8899132SKalle Valo 
6654d8899132SKalle Valo 			ar->supports_6ghz = true;
6655d8899132SKalle Valo 			band = &ar->mac.sbands[NL80211_BAND_6GHZ];
6656d8899132SKalle Valo 			band->band = NL80211_BAND_6GHZ;
6657d8899132SKalle Valo 			band->n_channels = ARRAY_SIZE(ath12k_6ghz_channels);
6658d8899132SKalle Valo 			band->channels = channels;
6659d8899132SKalle Valo 			band->n_bitrates = ath12k_a_rates_size;
6660d8899132SKalle Valo 			band->bitrates = ath12k_a_rates;
6661d8899132SKalle Valo 			ar->hw->wiphy->bands[NL80211_BAND_6GHZ] = band;
6662d8899132SKalle Valo 			ath12k_mac_update_ch_list(ar, band,
6663d8899132SKalle Valo 						  reg_cap->low_5ghz_chan,
6664d8899132SKalle Valo 						  reg_cap->high_5ghz_chan);
6665d8899132SKalle Valo 		}
6666d8899132SKalle Valo 
6667d8899132SKalle Valo 		if (reg_cap->low_5ghz_chan < ATH12K_MIN_6G_FREQ) {
6668d8899132SKalle Valo 			channels = kmemdup(ath12k_5ghz_channels,
6669d8899132SKalle Valo 					   sizeof(ath12k_5ghz_channels),
6670d8899132SKalle Valo 					   GFP_KERNEL);
6671d8899132SKalle Valo 			if (!channels) {
6672d8899132SKalle Valo 				kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels);
6673d8899132SKalle Valo 				kfree(ar->mac.sbands[NL80211_BAND_6GHZ].channels);
6674d8899132SKalle Valo 				return -ENOMEM;
6675d8899132SKalle Valo 			}
6676d8899132SKalle Valo 
6677d8899132SKalle Valo 			band = &ar->mac.sbands[NL80211_BAND_5GHZ];
6678d8899132SKalle Valo 			band->band = NL80211_BAND_5GHZ;
6679d8899132SKalle Valo 			band->n_channels = ARRAY_SIZE(ath12k_5ghz_channels);
6680d8899132SKalle Valo 			band->channels = channels;
6681d8899132SKalle Valo 			band->n_bitrates = ath12k_a_rates_size;
6682d8899132SKalle Valo 			band->bitrates = ath12k_a_rates;
6683d8899132SKalle Valo 			ar->hw->wiphy->bands[NL80211_BAND_5GHZ] = band;
6684d8899132SKalle Valo 
6685d8899132SKalle Valo 			if (ar->ab->hw_params->single_pdev_only) {
6686d8899132SKalle Valo 				phy_id = ath12k_get_phy_id(ar, WMI_HOST_WLAN_5G_CAP);
6687d8899132SKalle Valo 				reg_cap = &ar->ab->hal_reg_cap[phy_id];
6688d8899132SKalle Valo 			}
6689d8899132SKalle Valo 
6690d8899132SKalle Valo 			ath12k_mac_update_ch_list(ar, band,
6691d8899132SKalle Valo 						  reg_cap->low_5ghz_chan,
6692d8899132SKalle Valo 						  reg_cap->high_5ghz_chan);
6693d8899132SKalle Valo 		}
6694d8899132SKalle Valo 	}
6695d8899132SKalle Valo 
6696d8899132SKalle Valo 	return 0;
6697d8899132SKalle Valo }
6698d8899132SKalle Valo 
6699d8899132SKalle Valo static int ath12k_mac_setup_iface_combinations(struct ath12k *ar)
6700d8899132SKalle Valo {
6701d8899132SKalle Valo 	struct ath12k_base *ab = ar->ab;
6702d8899132SKalle Valo 	struct ieee80211_iface_combination *combinations;
6703d8899132SKalle Valo 	struct ieee80211_iface_limit *limits;
6704d8899132SKalle Valo 	int n_limits, max_interfaces;
6705d8899132SKalle Valo 	bool ap, mesh;
6706d8899132SKalle Valo 
6707d8899132SKalle Valo 	ap = ab->hw_params->interface_modes & BIT(NL80211_IFTYPE_AP);
6708d8899132SKalle Valo 
6709d8899132SKalle Valo 	mesh = IS_ENABLED(CONFIG_MAC80211_MESH) &&
6710d8899132SKalle Valo 		ab->hw_params->interface_modes & BIT(NL80211_IFTYPE_MESH_POINT);
6711d8899132SKalle Valo 
6712d8899132SKalle Valo 	combinations = kzalloc(sizeof(*combinations), GFP_KERNEL);
6713d8899132SKalle Valo 	if (!combinations)
6714d8899132SKalle Valo 		return -ENOMEM;
6715d8899132SKalle Valo 
6716d8899132SKalle Valo 	if (ap || mesh) {
6717d8899132SKalle Valo 		n_limits = 2;
6718d8899132SKalle Valo 		max_interfaces = 16;
6719d8899132SKalle Valo 	} else {
6720d8899132SKalle Valo 		n_limits = 1;
6721d8899132SKalle Valo 		max_interfaces = 1;
6722d8899132SKalle Valo 	}
6723d8899132SKalle Valo 
6724d8899132SKalle Valo 	limits = kcalloc(n_limits, sizeof(*limits), GFP_KERNEL);
6725d8899132SKalle Valo 	if (!limits) {
6726d8899132SKalle Valo 		kfree(combinations);
6727d8899132SKalle Valo 		return -ENOMEM;
6728d8899132SKalle Valo 	}
6729d8899132SKalle Valo 
6730d8899132SKalle Valo 	limits[0].max = 1;
6731d8899132SKalle Valo 	limits[0].types |= BIT(NL80211_IFTYPE_STATION);
6732d8899132SKalle Valo 
6733d8899132SKalle Valo 	if (ap) {
6734d8899132SKalle Valo 		limits[1].max = max_interfaces;
6735d8899132SKalle Valo 		limits[1].types |= BIT(NL80211_IFTYPE_AP);
6736d8899132SKalle Valo 	}
6737d8899132SKalle Valo 
6738d8899132SKalle Valo 	if (mesh)
6739d8899132SKalle Valo 		limits[1].types |= BIT(NL80211_IFTYPE_MESH_POINT);
6740d8899132SKalle Valo 
6741d8899132SKalle Valo 	combinations[0].limits = limits;
6742d8899132SKalle Valo 	combinations[0].n_limits = n_limits;
6743d8899132SKalle Valo 	combinations[0].max_interfaces = max_interfaces;
6744d8899132SKalle Valo 	combinations[0].num_different_channels = 1;
6745d8899132SKalle Valo 	combinations[0].beacon_int_infra_match = true;
6746d8899132SKalle Valo 	combinations[0].beacon_int_min_gcd = 100;
6747d8899132SKalle Valo 	combinations[0].radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |
6748d8899132SKalle Valo 						BIT(NL80211_CHAN_WIDTH_20) |
6749d8899132SKalle Valo 						BIT(NL80211_CHAN_WIDTH_40) |
6750d8899132SKalle Valo 						BIT(NL80211_CHAN_WIDTH_80);
6751d8899132SKalle Valo 
6752d8899132SKalle Valo 	ar->hw->wiphy->iface_combinations = combinations;
6753d8899132SKalle Valo 	ar->hw->wiphy->n_iface_combinations = 1;
6754d8899132SKalle Valo 
6755d8899132SKalle Valo 	return 0;
6756d8899132SKalle Valo }
6757d8899132SKalle Valo 
6758d8899132SKalle Valo static const u8 ath12k_if_types_ext_capa[] = {
6759d8899132SKalle Valo 	[0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
6760d8899132SKalle Valo 	[7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
6761d8899132SKalle Valo };
6762d8899132SKalle Valo 
6763d8899132SKalle Valo static const u8 ath12k_if_types_ext_capa_sta[] = {
6764d8899132SKalle Valo 	[0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
6765d8899132SKalle Valo 	[7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
6766d8899132SKalle Valo 	[9] = WLAN_EXT_CAPA10_TWT_REQUESTER_SUPPORT,
6767d8899132SKalle Valo };
6768d8899132SKalle Valo 
6769d8899132SKalle Valo static const u8 ath12k_if_types_ext_capa_ap[] = {
6770d8899132SKalle Valo 	[0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
6771d8899132SKalle Valo 	[7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
6772d8899132SKalle Valo 	[9] = WLAN_EXT_CAPA10_TWT_RESPONDER_SUPPORT,
6773d8899132SKalle Valo };
6774d8899132SKalle Valo 
6775d8899132SKalle Valo static const struct wiphy_iftype_ext_capab ath12k_iftypes_ext_capa[] = {
6776d8899132SKalle Valo 	{
6777d8899132SKalle Valo 		.extended_capabilities = ath12k_if_types_ext_capa,
6778d8899132SKalle Valo 		.extended_capabilities_mask = ath12k_if_types_ext_capa,
6779d8899132SKalle Valo 		.extended_capabilities_len = sizeof(ath12k_if_types_ext_capa),
6780d8899132SKalle Valo 	}, {
6781d8899132SKalle Valo 		.iftype = NL80211_IFTYPE_STATION,
6782d8899132SKalle Valo 		.extended_capabilities = ath12k_if_types_ext_capa_sta,
6783d8899132SKalle Valo 		.extended_capabilities_mask = ath12k_if_types_ext_capa_sta,
6784d8899132SKalle Valo 		.extended_capabilities_len =
6785d8899132SKalle Valo 				sizeof(ath12k_if_types_ext_capa_sta),
6786d8899132SKalle Valo 	}, {
6787d8899132SKalle Valo 		.iftype = NL80211_IFTYPE_AP,
6788d8899132SKalle Valo 		.extended_capabilities = ath12k_if_types_ext_capa_ap,
6789d8899132SKalle Valo 		.extended_capabilities_mask = ath12k_if_types_ext_capa_ap,
6790d8899132SKalle Valo 		.extended_capabilities_len =
6791d8899132SKalle Valo 				sizeof(ath12k_if_types_ext_capa_ap),
6792d8899132SKalle Valo 	},
6793d8899132SKalle Valo };
6794d8899132SKalle Valo 
6795d8899132SKalle Valo static void __ath12k_mac_unregister(struct ath12k *ar)
6796d8899132SKalle Valo {
6797d8899132SKalle Valo 	cancel_work_sync(&ar->regd_update_work);
6798d8899132SKalle Valo 
6799d8899132SKalle Valo 	ieee80211_unregister_hw(ar->hw);
6800d8899132SKalle Valo 
6801d8899132SKalle Valo 	idr_for_each(&ar->txmgmt_idr, ath12k_mac_tx_mgmt_pending_free, ar);
6802d8899132SKalle Valo 	idr_destroy(&ar->txmgmt_idr);
6803d8899132SKalle Valo 
6804d8899132SKalle Valo 	kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels);
6805d8899132SKalle Valo 	kfree(ar->mac.sbands[NL80211_BAND_5GHZ].channels);
6806d8899132SKalle Valo 	kfree(ar->mac.sbands[NL80211_BAND_6GHZ].channels);
6807d8899132SKalle Valo 
6808d8899132SKalle Valo 	kfree(ar->hw->wiphy->iface_combinations[0].limits);
6809d8899132SKalle Valo 	kfree(ar->hw->wiphy->iface_combinations);
6810d8899132SKalle Valo 
6811d8899132SKalle Valo 	SET_IEEE80211_DEV(ar->hw, NULL);
6812d8899132SKalle Valo }
6813d8899132SKalle Valo 
6814d8899132SKalle Valo void ath12k_mac_unregister(struct ath12k_base *ab)
6815d8899132SKalle Valo {
6816d8899132SKalle Valo 	struct ath12k *ar;
6817d8899132SKalle Valo 	struct ath12k_pdev *pdev;
6818d8899132SKalle Valo 	int i;
6819d8899132SKalle Valo 
6820d8899132SKalle Valo 	for (i = 0; i < ab->num_radios; i++) {
6821d8899132SKalle Valo 		pdev = &ab->pdevs[i];
6822d8899132SKalle Valo 		ar = pdev->ar;
6823d8899132SKalle Valo 		if (!ar)
6824d8899132SKalle Valo 			continue;
6825d8899132SKalle Valo 
6826d8899132SKalle Valo 		__ath12k_mac_unregister(ar);
6827d8899132SKalle Valo 	}
6828d8899132SKalle Valo }
6829d8899132SKalle Valo 
6830d8899132SKalle Valo static int __ath12k_mac_register(struct ath12k *ar)
6831d8899132SKalle Valo {
6832d8899132SKalle Valo 	struct ath12k_base *ab = ar->ab;
6833d8899132SKalle Valo 	struct ath12k_pdev_cap *cap = &ar->pdev->cap;
6834d8899132SKalle Valo 	static const u32 cipher_suites[] = {
6835d8899132SKalle Valo 		WLAN_CIPHER_SUITE_TKIP,
6836d8899132SKalle Valo 		WLAN_CIPHER_SUITE_CCMP,
6837d8899132SKalle Valo 		WLAN_CIPHER_SUITE_AES_CMAC,
6838d8899132SKalle Valo 		WLAN_CIPHER_SUITE_BIP_CMAC_256,
6839d8899132SKalle Valo 		WLAN_CIPHER_SUITE_BIP_GMAC_128,
6840d8899132SKalle Valo 		WLAN_CIPHER_SUITE_BIP_GMAC_256,
6841d8899132SKalle Valo 		WLAN_CIPHER_SUITE_GCMP,
6842d8899132SKalle Valo 		WLAN_CIPHER_SUITE_GCMP_256,
6843d8899132SKalle Valo 		WLAN_CIPHER_SUITE_CCMP_256,
6844d8899132SKalle Valo 	};
6845d8899132SKalle Valo 	int ret;
6846d8899132SKalle Valo 	u32 ht_cap = 0;
6847d8899132SKalle Valo 
6848d8899132SKalle Valo 	ath12k_pdev_caps_update(ar);
6849d8899132SKalle Valo 
6850d8899132SKalle Valo 	SET_IEEE80211_PERM_ADDR(ar->hw, ar->mac_addr);
6851d8899132SKalle Valo 
6852d8899132SKalle Valo 	SET_IEEE80211_DEV(ar->hw, ab->dev);
6853d8899132SKalle Valo 
6854d8899132SKalle Valo 	ret = ath12k_mac_setup_channels_rates(ar,
6855d8899132SKalle Valo 					      cap->supported_bands);
6856d8899132SKalle Valo 	if (ret)
6857d8899132SKalle Valo 		goto err;
6858d8899132SKalle Valo 
6859d8899132SKalle Valo 	ath12k_mac_setup_ht_vht_cap(ar, cap, &ht_cap);
6860d8899132SKalle Valo 	ath12k_mac_setup_he_cap(ar, cap);
6861d8899132SKalle Valo 
6862d8899132SKalle Valo 	ret = ath12k_mac_setup_iface_combinations(ar);
6863d8899132SKalle Valo 	if (ret) {
6864d8899132SKalle Valo 		ath12k_err(ar->ab, "failed to setup interface combinations: %d\n", ret);
6865d8899132SKalle Valo 		goto err_free_channels;
6866d8899132SKalle Valo 	}
6867d8899132SKalle Valo 
6868d8899132SKalle Valo 	ar->hw->wiphy->available_antennas_rx = cap->rx_chain_mask;
6869d8899132SKalle Valo 	ar->hw->wiphy->available_antennas_tx = cap->tx_chain_mask;
6870d8899132SKalle Valo 
6871d8899132SKalle Valo 	ar->hw->wiphy->interface_modes = ab->hw_params->interface_modes;
6872d8899132SKalle Valo 
6873d8899132SKalle Valo 	ieee80211_hw_set(ar->hw, SIGNAL_DBM);
6874d8899132SKalle Valo 	ieee80211_hw_set(ar->hw, SUPPORTS_PS);
6875d8899132SKalle Valo 	ieee80211_hw_set(ar->hw, SUPPORTS_DYNAMIC_PS);
6876d8899132SKalle Valo 	ieee80211_hw_set(ar->hw, MFP_CAPABLE);
6877d8899132SKalle Valo 	ieee80211_hw_set(ar->hw, REPORTS_TX_ACK_STATUS);
6878d8899132SKalle Valo 	ieee80211_hw_set(ar->hw, HAS_RATE_CONTROL);
6879d8899132SKalle Valo 	ieee80211_hw_set(ar->hw, AP_LINK_PS);
6880d8899132SKalle Valo 	ieee80211_hw_set(ar->hw, SPECTRUM_MGMT);
6881d8899132SKalle Valo 	ieee80211_hw_set(ar->hw, CONNECTION_MONITOR);
6882d8899132SKalle Valo 	ieee80211_hw_set(ar->hw, SUPPORTS_PER_STA_GTK);
6883d8899132SKalle Valo 	ieee80211_hw_set(ar->hw, CHANCTX_STA_CSA);
6884d8899132SKalle Valo 	ieee80211_hw_set(ar->hw, QUEUE_CONTROL);
6885d8899132SKalle Valo 	ieee80211_hw_set(ar->hw, SUPPORTS_TX_FRAG);
6886d8899132SKalle Valo 	ieee80211_hw_set(ar->hw, REPORTS_LOW_ACK);
6887d8899132SKalle Valo 
6888d8899132SKalle Valo 	if (ht_cap & WMI_HT_CAP_ENABLED) {
6889d8899132SKalle Valo 		ieee80211_hw_set(ar->hw, AMPDU_AGGREGATION);
6890d8899132SKalle Valo 		ieee80211_hw_set(ar->hw, TX_AMPDU_SETUP_IN_HW);
6891d8899132SKalle Valo 		ieee80211_hw_set(ar->hw, SUPPORTS_REORDERING_BUFFER);
6892d8899132SKalle Valo 		ieee80211_hw_set(ar->hw, SUPPORTS_AMSDU_IN_AMPDU);
6893d8899132SKalle Valo 		ieee80211_hw_set(ar->hw, USES_RSS);
6894d8899132SKalle Valo 	}
6895d8899132SKalle Valo 
6896d8899132SKalle Valo 	ar->hw->wiphy->features |= NL80211_FEATURE_STATIC_SMPS;
6897d8899132SKalle Valo 	ar->hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
6898d8899132SKalle Valo 
6899d8899132SKalle Valo 	/* TODO: Check if HT capability advertised from firmware is different
6900d8899132SKalle Valo 	 * for each band for a dual band capable radio. It will be tricky to
6901d8899132SKalle Valo 	 * handle it when the ht capability different for each band.
6902d8899132SKalle Valo 	 */
6903d8899132SKalle Valo 	if (ht_cap & WMI_HT_CAP_DYNAMIC_SMPS)
6904d8899132SKalle Valo 		ar->hw->wiphy->features |= NL80211_FEATURE_DYNAMIC_SMPS;
6905d8899132SKalle Valo 
6906d8899132SKalle Valo 	ar->hw->wiphy->max_scan_ssids = WLAN_SCAN_PARAMS_MAX_SSID;
6907d8899132SKalle Valo 	ar->hw->wiphy->max_scan_ie_len = WLAN_SCAN_PARAMS_MAX_IE_LEN;
6908d8899132SKalle Valo 
6909d8899132SKalle Valo 	ar->hw->max_listen_interval = ATH12K_MAX_HW_LISTEN_INTERVAL;
6910d8899132SKalle Valo 
6911d8899132SKalle Valo 	ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
6912d8899132SKalle Valo 	ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
6913d8899132SKalle Valo 	ar->hw->wiphy->max_remain_on_channel_duration = 5000;
6914d8899132SKalle Valo 
6915d8899132SKalle Valo 	ar->hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
6916d8899132SKalle Valo 	ar->hw->wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE |
6917d8899132SKalle Valo 				   NL80211_FEATURE_AP_SCAN;
6918d8899132SKalle Valo 
6919d8899132SKalle Valo 	ar->max_num_stations = TARGET_NUM_STATIONS;
6920d8899132SKalle Valo 	ar->max_num_peers = TARGET_NUM_PEERS_PDEV;
6921d8899132SKalle Valo 
6922d8899132SKalle Valo 	ar->hw->wiphy->max_ap_assoc_sta = ar->max_num_stations;
6923d8899132SKalle Valo 
6924d8899132SKalle Valo 	ar->hw->queues = ATH12K_HW_MAX_QUEUES;
6925d8899132SKalle Valo 	ar->hw->wiphy->tx_queue_len = ATH12K_QUEUE_LEN;
6926d8899132SKalle Valo 	ar->hw->offchannel_tx_hw_queue = ATH12K_HW_MAX_QUEUES - 1;
6927d8899132SKalle Valo 	ar->hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE;
6928d8899132SKalle Valo 
6929d8899132SKalle Valo 	ar->hw->vif_data_size = sizeof(struct ath12k_vif);
6930d8899132SKalle Valo 	ar->hw->sta_data_size = sizeof(struct ath12k_sta);
6931d8899132SKalle Valo 
6932d8899132SKalle Valo 	wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
6933d8899132SKalle Valo 	wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_STA_TX_PWR);
6934d8899132SKalle Valo 
6935d8899132SKalle Valo 	ar->hw->wiphy->cipher_suites = cipher_suites;
6936d8899132SKalle Valo 	ar->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
6937d8899132SKalle Valo 
6938d8899132SKalle Valo 	ar->hw->wiphy->iftype_ext_capab = ath12k_iftypes_ext_capa;
6939d8899132SKalle Valo 	ar->hw->wiphy->num_iftype_ext_capab =
6940d8899132SKalle Valo 		ARRAY_SIZE(ath12k_iftypes_ext_capa);
6941d8899132SKalle Valo 
6942d8899132SKalle Valo 	if (ar->supports_6ghz) {
6943d8899132SKalle Valo 		wiphy_ext_feature_set(ar->hw->wiphy,
6944d8899132SKalle Valo 				      NL80211_EXT_FEATURE_FILS_DISCOVERY);
6945d8899132SKalle Valo 		wiphy_ext_feature_set(ar->hw->wiphy,
6946d8899132SKalle Valo 				      NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP);
6947d8899132SKalle Valo 	}
6948d8899132SKalle Valo 
6949d8899132SKalle Valo 	ath12k_reg_init(ar);
6950d8899132SKalle Valo 
6951d8899132SKalle Valo 	if (!test_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags)) {
6952d8899132SKalle Valo 		ar->hw->netdev_features = NETIF_F_HW_CSUM;
6953d8899132SKalle Valo 		ieee80211_hw_set(ar->hw, SW_CRYPTO_CONTROL);
6954d8899132SKalle Valo 		ieee80211_hw_set(ar->hw, SUPPORT_FAST_XMIT);
6955d8899132SKalle Valo 	}
6956d8899132SKalle Valo 
6957d8899132SKalle Valo 	ret = ieee80211_register_hw(ar->hw);
6958d8899132SKalle Valo 	if (ret) {
6959d8899132SKalle Valo 		ath12k_err(ar->ab, "ieee80211 registration failed: %d\n", ret);
6960d8899132SKalle Valo 		goto err_free_if_combs;
6961d8899132SKalle Valo 	}
6962d8899132SKalle Valo 
6963d8899132SKalle Valo 	if (!ab->hw_params->supports_monitor)
6964d8899132SKalle Valo 		/* There's a race between calling ieee80211_register_hw()
6965d8899132SKalle Valo 		 * and here where the monitor mode is enabled for a little
6966d8899132SKalle Valo 		 * while. But that time is so short and in practise it make
6967d8899132SKalle Valo 		 * a difference in real life.
6968d8899132SKalle Valo 		 */
6969d8899132SKalle Valo 		ar->hw->wiphy->interface_modes &= ~BIT(NL80211_IFTYPE_MONITOR);
6970d8899132SKalle Valo 
6971d8899132SKalle Valo 	/* Apply the regd received during initialization */
6972d8899132SKalle Valo 	ret = ath12k_regd_update(ar, true);
6973d8899132SKalle Valo 	if (ret) {
6974d8899132SKalle Valo 		ath12k_err(ar->ab, "ath12k regd update failed: %d\n", ret);
6975d8899132SKalle Valo 		goto err_unregister_hw;
6976d8899132SKalle Valo 	}
6977d8899132SKalle Valo 
6978d8899132SKalle Valo 	return 0;
6979d8899132SKalle Valo 
6980d8899132SKalle Valo err_unregister_hw:
6981d8899132SKalle Valo 	ieee80211_unregister_hw(ar->hw);
6982d8899132SKalle Valo 
6983d8899132SKalle Valo err_free_if_combs:
6984d8899132SKalle Valo 	kfree(ar->hw->wiphy->iface_combinations[0].limits);
6985d8899132SKalle Valo 	kfree(ar->hw->wiphy->iface_combinations);
6986d8899132SKalle Valo 
6987d8899132SKalle Valo err_free_channels:
6988d8899132SKalle Valo 	kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels);
6989d8899132SKalle Valo 	kfree(ar->mac.sbands[NL80211_BAND_5GHZ].channels);
6990d8899132SKalle Valo 	kfree(ar->mac.sbands[NL80211_BAND_6GHZ].channels);
6991d8899132SKalle Valo 
6992d8899132SKalle Valo err:
6993d8899132SKalle Valo 	SET_IEEE80211_DEV(ar->hw, NULL);
6994d8899132SKalle Valo 	return ret;
6995d8899132SKalle Valo }
6996d8899132SKalle Valo 
6997d8899132SKalle Valo int ath12k_mac_register(struct ath12k_base *ab)
6998d8899132SKalle Valo {
6999d8899132SKalle Valo 	struct ath12k *ar;
7000d8899132SKalle Valo 	struct ath12k_pdev *pdev;
7001d8899132SKalle Valo 	int i;
7002d8899132SKalle Valo 	int ret;
7003d8899132SKalle Valo 
7004d8899132SKalle Valo 	if (test_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags))
7005d8899132SKalle Valo 		return 0;
7006d8899132SKalle Valo 
7007d8899132SKalle Valo 	for (i = 0; i < ab->num_radios; i++) {
7008d8899132SKalle Valo 		pdev = &ab->pdevs[i];
7009d8899132SKalle Valo 		ar = pdev->ar;
7010d8899132SKalle Valo 		if (ab->pdevs_macaddr_valid) {
7011d8899132SKalle Valo 			ether_addr_copy(ar->mac_addr, pdev->mac_addr);
7012d8899132SKalle Valo 		} else {
7013d8899132SKalle Valo 			ether_addr_copy(ar->mac_addr, ab->mac_addr);
7014d8899132SKalle Valo 			ar->mac_addr[4] += i;
7015d8899132SKalle Valo 		}
7016d8899132SKalle Valo 
7017d8899132SKalle Valo 		ret = __ath12k_mac_register(ar);
7018d8899132SKalle Valo 		if (ret)
7019d8899132SKalle Valo 			goto err_cleanup;
7020d8899132SKalle Valo 
70215189a8dbSKarthik M 		init_waitqueue_head(&ar->txmgmt_empty_waitq);
7022d8899132SKalle Valo 		idr_init(&ar->txmgmt_idr);
7023d8899132SKalle Valo 		spin_lock_init(&ar->txmgmt_idr_lock);
7024d8899132SKalle Valo 	}
7025d8899132SKalle Valo 
7026d8899132SKalle Valo 	/* Initialize channel counters frequency value in hertz */
7027d8899132SKalle Valo 	ab->cc_freq_hz = 320000;
7028d8899132SKalle Valo 	ab->free_vdev_map = (1LL << (ab->num_radios * TARGET_NUM_VDEVS)) - 1;
7029d8899132SKalle Valo 
7030d8899132SKalle Valo 	return 0;
7031d8899132SKalle Valo 
7032d8899132SKalle Valo err_cleanup:
7033d8899132SKalle Valo 	for (i = i - 1; i >= 0; i--) {
7034d8899132SKalle Valo 		pdev = &ab->pdevs[i];
7035d8899132SKalle Valo 		ar = pdev->ar;
7036d8899132SKalle Valo 		__ath12k_mac_unregister(ar);
7037d8899132SKalle Valo 	}
7038d8899132SKalle Valo 
7039d8899132SKalle Valo 	return ret;
7040d8899132SKalle Valo }
7041d8899132SKalle Valo 
7042d8899132SKalle Valo int ath12k_mac_allocate(struct ath12k_base *ab)
7043d8899132SKalle Valo {
7044d8899132SKalle Valo 	struct ieee80211_hw *hw;
7045d8899132SKalle Valo 	struct ath12k *ar;
7046d8899132SKalle Valo 	struct ath12k_pdev *pdev;
7047d8899132SKalle Valo 	int ret;
7048d8899132SKalle Valo 	int i;
7049d8899132SKalle Valo 
7050d8899132SKalle Valo 	if (test_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags))
7051d8899132SKalle Valo 		return 0;
7052d8899132SKalle Valo 
7053d8899132SKalle Valo 	for (i = 0; i < ab->num_radios; i++) {
7054d8899132SKalle Valo 		pdev = &ab->pdevs[i];
7055d8899132SKalle Valo 		hw = ieee80211_alloc_hw(sizeof(struct ath12k), &ath12k_ops);
7056d8899132SKalle Valo 		if (!hw) {
7057d8899132SKalle Valo 			ath12k_warn(ab, "failed to allocate mac80211 hw device\n");
7058d8899132SKalle Valo 			ret = -ENOMEM;
7059d8899132SKalle Valo 			goto err_free_mac;
7060d8899132SKalle Valo 		}
7061d8899132SKalle Valo 
7062d8899132SKalle Valo 		ar = hw->priv;
7063d8899132SKalle Valo 		ar->hw = hw;
7064d8899132SKalle Valo 		ar->ab = ab;
7065d8899132SKalle Valo 		ar->pdev = pdev;
7066d8899132SKalle Valo 		ar->pdev_idx = i;
7067d8899132SKalle Valo 		ar->lmac_id = ath12k_hw_get_mac_from_pdev_id(ab->hw_params, i);
7068d8899132SKalle Valo 
7069d8899132SKalle Valo 		ar->wmi = &ab->wmi_ab.wmi[i];
7070d8899132SKalle Valo 		/* FIXME: wmi[0] is already initialized during attach,
7071d8899132SKalle Valo 		 * Should we do this again?
7072d8899132SKalle Valo 		 */
7073d8899132SKalle Valo 		ath12k_wmi_pdev_attach(ab, i);
7074d8899132SKalle Valo 
7075d8899132SKalle Valo 		ar->cfg_tx_chainmask = pdev->cap.tx_chain_mask;
7076d8899132SKalle Valo 		ar->cfg_rx_chainmask = pdev->cap.rx_chain_mask;
7077d8899132SKalle Valo 		ar->num_tx_chains = hweight32(pdev->cap.tx_chain_mask);
7078d8899132SKalle Valo 		ar->num_rx_chains = hweight32(pdev->cap.rx_chain_mask);
7079d8899132SKalle Valo 
7080d8899132SKalle Valo 		pdev->ar = ar;
7081d8899132SKalle Valo 		spin_lock_init(&ar->data_lock);
7082d8899132SKalle Valo 		INIT_LIST_HEAD(&ar->arvifs);
7083d8899132SKalle Valo 		INIT_LIST_HEAD(&ar->ppdu_stats_info);
7084d8899132SKalle Valo 		mutex_init(&ar->conf_mutex);
7085d8899132SKalle Valo 		init_completion(&ar->vdev_setup_done);
7086d8899132SKalle Valo 		init_completion(&ar->vdev_delete_done);
7087d8899132SKalle Valo 		init_completion(&ar->peer_assoc_done);
7088d8899132SKalle Valo 		init_completion(&ar->peer_delete_done);
7089d8899132SKalle Valo 		init_completion(&ar->install_key_done);
7090d8899132SKalle Valo 		init_completion(&ar->bss_survey_done);
7091d8899132SKalle Valo 		init_completion(&ar->scan.started);
7092d8899132SKalle Valo 		init_completion(&ar->scan.completed);
7093d8899132SKalle Valo 
7094d8899132SKalle Valo 		INIT_DELAYED_WORK(&ar->scan.timeout, ath12k_scan_timeout_work);
7095d8899132SKalle Valo 		INIT_WORK(&ar->regd_update_work, ath12k_regd_update_work);
7096d8899132SKalle Valo 
7097d8899132SKalle Valo 		INIT_WORK(&ar->wmi_mgmt_tx_work, ath12k_mgmt_over_wmi_tx_work);
7098d8899132SKalle Valo 		skb_queue_head_init(&ar->wmi_mgmt_tx_queue);
7099d8899132SKalle Valo 		clear_bit(ATH12K_FLAG_MONITOR_ENABLED, &ar->monitor_flags);
7100d8899132SKalle Valo 	}
7101d8899132SKalle Valo 
7102d8899132SKalle Valo 	return 0;
7103d8899132SKalle Valo 
7104d8899132SKalle Valo err_free_mac:
7105d8899132SKalle Valo 	ath12k_mac_destroy(ab);
7106d8899132SKalle Valo 
7107d8899132SKalle Valo 	return ret;
7108d8899132SKalle Valo }
7109d8899132SKalle Valo 
7110d8899132SKalle Valo void ath12k_mac_destroy(struct ath12k_base *ab)
7111d8899132SKalle Valo {
7112d8899132SKalle Valo 	struct ath12k *ar;
7113d8899132SKalle Valo 	struct ath12k_pdev *pdev;
7114d8899132SKalle Valo 	int i;
7115d8899132SKalle Valo 
7116d8899132SKalle Valo 	for (i = 0; i < ab->num_radios; i++) {
7117d8899132SKalle Valo 		pdev = &ab->pdevs[i];
7118d8899132SKalle Valo 		ar = pdev->ar;
7119d8899132SKalle Valo 		if (!ar)
7120d8899132SKalle Valo 			continue;
7121d8899132SKalle Valo 
7122d8899132SKalle Valo 		ieee80211_free_hw(ar->hw);
7123d8899132SKalle Valo 		pdev->ar = NULL;
7124d8899132SKalle Valo 	}
7125d8899132SKalle Valo }
7126