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