1*5c1def83SBjoern A. Zeeb // SPDX-License-Identifier: BSD-3-Clause-Clear
2*5c1def83SBjoern A. Zeeb /*
3*5c1def83SBjoern A. Zeeb * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
4*5c1def83SBjoern A. Zeeb * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
5*5c1def83SBjoern A. Zeeb */
6*5c1def83SBjoern A. Zeeb
7*5c1def83SBjoern A. Zeeb #include <net/mac80211.h>
8*5c1def83SBjoern A. Zeeb #include <linux/etherdevice.h>
9*5c1def83SBjoern A. Zeeb #include "mac.h"
10*5c1def83SBjoern A. Zeeb #include "core.h"
11*5c1def83SBjoern A. Zeeb #include "debug.h"
12*5c1def83SBjoern A. Zeeb #include "wmi.h"
13*5c1def83SBjoern A. Zeeb #include "hw.h"
14*5c1def83SBjoern A. Zeeb #include "dp_tx.h"
15*5c1def83SBjoern A. Zeeb #include "dp_rx.h"
16*5c1def83SBjoern A. Zeeb #include "peer.h"
17*5c1def83SBjoern A. Zeeb
18*5c1def83SBjoern A. Zeeb #define CHAN2G(_channel, _freq, _flags) { \
19*5c1def83SBjoern A. Zeeb .band = NL80211_BAND_2GHZ, \
20*5c1def83SBjoern A. Zeeb .hw_value = (_channel), \
21*5c1def83SBjoern A. Zeeb .center_freq = (_freq), \
22*5c1def83SBjoern A. Zeeb .flags = (_flags), \
23*5c1def83SBjoern A. Zeeb .max_antenna_gain = 0, \
24*5c1def83SBjoern A. Zeeb .max_power = 30, \
25*5c1def83SBjoern A. Zeeb }
26*5c1def83SBjoern A. Zeeb
27*5c1def83SBjoern A. Zeeb #define CHAN5G(_channel, _freq, _flags) { \
28*5c1def83SBjoern A. Zeeb .band = NL80211_BAND_5GHZ, \
29*5c1def83SBjoern A. Zeeb .hw_value = (_channel), \
30*5c1def83SBjoern A. Zeeb .center_freq = (_freq), \
31*5c1def83SBjoern A. Zeeb .flags = (_flags), \
32*5c1def83SBjoern A. Zeeb .max_antenna_gain = 0, \
33*5c1def83SBjoern A. Zeeb .max_power = 30, \
34*5c1def83SBjoern A. Zeeb }
35*5c1def83SBjoern A. Zeeb
36*5c1def83SBjoern A. Zeeb #define CHAN6G(_channel, _freq, _flags) { \
37*5c1def83SBjoern A. Zeeb .band = NL80211_BAND_6GHZ, \
38*5c1def83SBjoern A. Zeeb .hw_value = (_channel), \
39*5c1def83SBjoern A. Zeeb .center_freq = (_freq), \
40*5c1def83SBjoern A. Zeeb .flags = (_flags), \
41*5c1def83SBjoern A. Zeeb .max_antenna_gain = 0, \
42*5c1def83SBjoern A. Zeeb .max_power = 30, \
43*5c1def83SBjoern A. Zeeb }
44*5c1def83SBjoern A. Zeeb
45*5c1def83SBjoern A. Zeeb static const struct ieee80211_channel ath12k_2ghz_channels[] = {
46*5c1def83SBjoern A. Zeeb CHAN2G(1, 2412, 0),
47*5c1def83SBjoern A. Zeeb CHAN2G(2, 2417, 0),
48*5c1def83SBjoern A. Zeeb CHAN2G(3, 2422, 0),
49*5c1def83SBjoern A. Zeeb CHAN2G(4, 2427, 0),
50*5c1def83SBjoern A. Zeeb CHAN2G(5, 2432, 0),
51*5c1def83SBjoern A. Zeeb CHAN2G(6, 2437, 0),
52*5c1def83SBjoern A. Zeeb CHAN2G(7, 2442, 0),
53*5c1def83SBjoern A. Zeeb CHAN2G(8, 2447, 0),
54*5c1def83SBjoern A. Zeeb CHAN2G(9, 2452, 0),
55*5c1def83SBjoern A. Zeeb CHAN2G(10, 2457, 0),
56*5c1def83SBjoern A. Zeeb CHAN2G(11, 2462, 0),
57*5c1def83SBjoern A. Zeeb CHAN2G(12, 2467, 0),
58*5c1def83SBjoern A. Zeeb CHAN2G(13, 2472, 0),
59*5c1def83SBjoern A. Zeeb CHAN2G(14, 2484, 0),
60*5c1def83SBjoern A. Zeeb };
61*5c1def83SBjoern A. Zeeb
62*5c1def83SBjoern A. Zeeb static const struct ieee80211_channel ath12k_5ghz_channels[] = {
63*5c1def83SBjoern A. Zeeb CHAN5G(36, 5180, 0),
64*5c1def83SBjoern A. Zeeb CHAN5G(40, 5200, 0),
65*5c1def83SBjoern A. Zeeb CHAN5G(44, 5220, 0),
66*5c1def83SBjoern A. Zeeb CHAN5G(48, 5240, 0),
67*5c1def83SBjoern A. Zeeb CHAN5G(52, 5260, 0),
68*5c1def83SBjoern A. Zeeb CHAN5G(56, 5280, 0),
69*5c1def83SBjoern A. Zeeb CHAN5G(60, 5300, 0),
70*5c1def83SBjoern A. Zeeb CHAN5G(64, 5320, 0),
71*5c1def83SBjoern A. Zeeb CHAN5G(100, 5500, 0),
72*5c1def83SBjoern A. Zeeb CHAN5G(104, 5520, 0),
73*5c1def83SBjoern A. Zeeb CHAN5G(108, 5540, 0),
74*5c1def83SBjoern A. Zeeb CHAN5G(112, 5560, 0),
75*5c1def83SBjoern A. Zeeb CHAN5G(116, 5580, 0),
76*5c1def83SBjoern A. Zeeb CHAN5G(120, 5600, 0),
77*5c1def83SBjoern A. Zeeb CHAN5G(124, 5620, 0),
78*5c1def83SBjoern A. Zeeb CHAN5G(128, 5640, 0),
79*5c1def83SBjoern A. Zeeb CHAN5G(132, 5660, 0),
80*5c1def83SBjoern A. Zeeb CHAN5G(136, 5680, 0),
81*5c1def83SBjoern A. Zeeb CHAN5G(140, 5700, 0),
82*5c1def83SBjoern A. Zeeb CHAN5G(144, 5720, 0),
83*5c1def83SBjoern A. Zeeb CHAN5G(149, 5745, 0),
84*5c1def83SBjoern A. Zeeb CHAN5G(153, 5765, 0),
85*5c1def83SBjoern A. Zeeb CHAN5G(157, 5785, 0),
86*5c1def83SBjoern A. Zeeb CHAN5G(161, 5805, 0),
87*5c1def83SBjoern A. Zeeb CHAN5G(165, 5825, 0),
88*5c1def83SBjoern A. Zeeb CHAN5G(169, 5845, 0),
89*5c1def83SBjoern A. Zeeb CHAN5G(173, 5865, 0),
90*5c1def83SBjoern A. Zeeb };
91*5c1def83SBjoern A. Zeeb
92*5c1def83SBjoern A. Zeeb static const struct ieee80211_channel ath12k_6ghz_channels[] = {
93*5c1def83SBjoern A. Zeeb CHAN6G(1, 5955, 0),
94*5c1def83SBjoern A. Zeeb CHAN6G(5, 5975, 0),
95*5c1def83SBjoern A. Zeeb CHAN6G(9, 5995, 0),
96*5c1def83SBjoern A. Zeeb CHAN6G(13, 6015, 0),
97*5c1def83SBjoern A. Zeeb CHAN6G(17, 6035, 0),
98*5c1def83SBjoern A. Zeeb CHAN6G(21, 6055, 0),
99*5c1def83SBjoern A. Zeeb CHAN6G(25, 6075, 0),
100*5c1def83SBjoern A. Zeeb CHAN6G(29, 6095, 0),
101*5c1def83SBjoern A. Zeeb CHAN6G(33, 6115, 0),
102*5c1def83SBjoern A. Zeeb CHAN6G(37, 6135, 0),
103*5c1def83SBjoern A. Zeeb CHAN6G(41, 6155, 0),
104*5c1def83SBjoern A. Zeeb CHAN6G(45, 6175, 0),
105*5c1def83SBjoern A. Zeeb CHAN6G(49, 6195, 0),
106*5c1def83SBjoern A. Zeeb CHAN6G(53, 6215, 0),
107*5c1def83SBjoern A. Zeeb CHAN6G(57, 6235, 0),
108*5c1def83SBjoern A. Zeeb CHAN6G(61, 6255, 0),
109*5c1def83SBjoern A. Zeeb CHAN6G(65, 6275, 0),
110*5c1def83SBjoern A. Zeeb CHAN6G(69, 6295, 0),
111*5c1def83SBjoern A. Zeeb CHAN6G(73, 6315, 0),
112*5c1def83SBjoern A. Zeeb CHAN6G(77, 6335, 0),
113*5c1def83SBjoern A. Zeeb CHAN6G(81, 6355, 0),
114*5c1def83SBjoern A. Zeeb CHAN6G(85, 6375, 0),
115*5c1def83SBjoern A. Zeeb CHAN6G(89, 6395, 0),
116*5c1def83SBjoern A. Zeeb CHAN6G(93, 6415, 0),
117*5c1def83SBjoern A. Zeeb CHAN6G(97, 6435, 0),
118*5c1def83SBjoern A. Zeeb CHAN6G(101, 6455, 0),
119*5c1def83SBjoern A. Zeeb CHAN6G(105, 6475, 0),
120*5c1def83SBjoern A. Zeeb CHAN6G(109, 6495, 0),
121*5c1def83SBjoern A. Zeeb CHAN6G(113, 6515, 0),
122*5c1def83SBjoern A. Zeeb CHAN6G(117, 6535, 0),
123*5c1def83SBjoern A. Zeeb CHAN6G(121, 6555, 0),
124*5c1def83SBjoern A. Zeeb CHAN6G(125, 6575, 0),
125*5c1def83SBjoern A. Zeeb CHAN6G(129, 6595, 0),
126*5c1def83SBjoern A. Zeeb CHAN6G(133, 6615, 0),
127*5c1def83SBjoern A. Zeeb CHAN6G(137, 6635, 0),
128*5c1def83SBjoern A. Zeeb CHAN6G(141, 6655, 0),
129*5c1def83SBjoern A. Zeeb CHAN6G(145, 6675, 0),
130*5c1def83SBjoern A. Zeeb CHAN6G(149, 6695, 0),
131*5c1def83SBjoern A. Zeeb CHAN6G(153, 6715, 0),
132*5c1def83SBjoern A. Zeeb CHAN6G(157, 6735, 0),
133*5c1def83SBjoern A. Zeeb CHAN6G(161, 6755, 0),
134*5c1def83SBjoern A. Zeeb CHAN6G(165, 6775, 0),
135*5c1def83SBjoern A. Zeeb CHAN6G(169, 6795, 0),
136*5c1def83SBjoern A. Zeeb CHAN6G(173, 6815, 0),
137*5c1def83SBjoern A. Zeeb CHAN6G(177, 6835, 0),
138*5c1def83SBjoern A. Zeeb CHAN6G(181, 6855, 0),
139*5c1def83SBjoern A. Zeeb CHAN6G(185, 6875, 0),
140*5c1def83SBjoern A. Zeeb CHAN6G(189, 6895, 0),
141*5c1def83SBjoern A. Zeeb CHAN6G(193, 6915, 0),
142*5c1def83SBjoern A. Zeeb CHAN6G(197, 6935, 0),
143*5c1def83SBjoern A. Zeeb CHAN6G(201, 6955, 0),
144*5c1def83SBjoern A. Zeeb CHAN6G(205, 6975, 0),
145*5c1def83SBjoern A. Zeeb CHAN6G(209, 6995, 0),
146*5c1def83SBjoern A. Zeeb CHAN6G(213, 7015, 0),
147*5c1def83SBjoern A. Zeeb CHAN6G(217, 7035, 0),
148*5c1def83SBjoern A. Zeeb CHAN6G(221, 7055, 0),
149*5c1def83SBjoern A. Zeeb CHAN6G(225, 7075, 0),
150*5c1def83SBjoern A. Zeeb CHAN6G(229, 7095, 0),
151*5c1def83SBjoern A. Zeeb CHAN6G(233, 7115, 0),
152*5c1def83SBjoern A. Zeeb };
153*5c1def83SBjoern A. Zeeb
154*5c1def83SBjoern A. Zeeb static struct ieee80211_rate ath12k_legacy_rates[] = {
155*5c1def83SBjoern A. Zeeb { .bitrate = 10,
156*5c1def83SBjoern A. Zeeb .hw_value = ATH12K_HW_RATE_CCK_LP_1M },
157*5c1def83SBjoern A. Zeeb { .bitrate = 20,
158*5c1def83SBjoern A. Zeeb .hw_value = ATH12K_HW_RATE_CCK_LP_2M,
159*5c1def83SBjoern A. Zeeb .hw_value_short = ATH12K_HW_RATE_CCK_SP_2M,
160*5c1def83SBjoern A. Zeeb .flags = IEEE80211_RATE_SHORT_PREAMBLE },
161*5c1def83SBjoern A. Zeeb { .bitrate = 55,
162*5c1def83SBjoern A. Zeeb .hw_value = ATH12K_HW_RATE_CCK_LP_5_5M,
163*5c1def83SBjoern A. Zeeb .hw_value_short = ATH12K_HW_RATE_CCK_SP_5_5M,
164*5c1def83SBjoern A. Zeeb .flags = IEEE80211_RATE_SHORT_PREAMBLE },
165*5c1def83SBjoern A. Zeeb { .bitrate = 110,
166*5c1def83SBjoern A. Zeeb .hw_value = ATH12K_HW_RATE_CCK_LP_11M,
167*5c1def83SBjoern A. Zeeb .hw_value_short = ATH12K_HW_RATE_CCK_SP_11M,
168*5c1def83SBjoern A. Zeeb .flags = IEEE80211_RATE_SHORT_PREAMBLE },
169*5c1def83SBjoern A. Zeeb
170*5c1def83SBjoern A. Zeeb { .bitrate = 60, .hw_value = ATH12K_HW_RATE_OFDM_6M },
171*5c1def83SBjoern A. Zeeb { .bitrate = 90, .hw_value = ATH12K_HW_RATE_OFDM_9M },
172*5c1def83SBjoern A. Zeeb { .bitrate = 120, .hw_value = ATH12K_HW_RATE_OFDM_12M },
173*5c1def83SBjoern A. Zeeb { .bitrate = 180, .hw_value = ATH12K_HW_RATE_OFDM_18M },
174*5c1def83SBjoern A. Zeeb { .bitrate = 240, .hw_value = ATH12K_HW_RATE_OFDM_24M },
175*5c1def83SBjoern A. Zeeb { .bitrate = 360, .hw_value = ATH12K_HW_RATE_OFDM_36M },
176*5c1def83SBjoern A. Zeeb { .bitrate = 480, .hw_value = ATH12K_HW_RATE_OFDM_48M },
177*5c1def83SBjoern A. Zeeb { .bitrate = 540, .hw_value = ATH12K_HW_RATE_OFDM_54M },
178*5c1def83SBjoern A. Zeeb };
179*5c1def83SBjoern A. Zeeb
180*5c1def83SBjoern A. Zeeb static const int
181*5c1def83SBjoern A. Zeeb ath12k_phymodes[NUM_NL80211_BANDS][ATH12K_CHAN_WIDTH_NUM] = {
182*5c1def83SBjoern A. Zeeb [NL80211_BAND_2GHZ] = {
183*5c1def83SBjoern A. Zeeb [NL80211_CHAN_WIDTH_5] = MODE_UNKNOWN,
184*5c1def83SBjoern A. Zeeb [NL80211_CHAN_WIDTH_10] = MODE_UNKNOWN,
185*5c1def83SBjoern A. Zeeb [NL80211_CHAN_WIDTH_20_NOHT] = MODE_11BE_EHT20_2G,
186*5c1def83SBjoern A. Zeeb [NL80211_CHAN_WIDTH_20] = MODE_11BE_EHT20_2G,
187*5c1def83SBjoern A. Zeeb [NL80211_CHAN_WIDTH_40] = MODE_11BE_EHT40_2G,
188*5c1def83SBjoern A. Zeeb [NL80211_CHAN_WIDTH_80] = MODE_UNKNOWN,
189*5c1def83SBjoern A. Zeeb [NL80211_CHAN_WIDTH_80P80] = MODE_UNKNOWN,
190*5c1def83SBjoern A. Zeeb [NL80211_CHAN_WIDTH_160] = MODE_UNKNOWN,
191*5c1def83SBjoern A. Zeeb [NL80211_CHAN_WIDTH_320] = MODE_UNKNOWN,
192*5c1def83SBjoern A. Zeeb },
193*5c1def83SBjoern A. Zeeb [NL80211_BAND_5GHZ] = {
194*5c1def83SBjoern A. Zeeb [NL80211_CHAN_WIDTH_5] = MODE_UNKNOWN,
195*5c1def83SBjoern A. Zeeb [NL80211_CHAN_WIDTH_10] = MODE_UNKNOWN,
196*5c1def83SBjoern A. Zeeb [NL80211_CHAN_WIDTH_20_NOHT] = MODE_11BE_EHT20,
197*5c1def83SBjoern A. Zeeb [NL80211_CHAN_WIDTH_20] = MODE_11BE_EHT20,
198*5c1def83SBjoern A. Zeeb [NL80211_CHAN_WIDTH_40] = MODE_11BE_EHT40,
199*5c1def83SBjoern A. Zeeb [NL80211_CHAN_WIDTH_80] = MODE_11BE_EHT80,
200*5c1def83SBjoern A. Zeeb [NL80211_CHAN_WIDTH_160] = MODE_11BE_EHT160,
201*5c1def83SBjoern A. Zeeb [NL80211_CHAN_WIDTH_80P80] = MODE_11BE_EHT80_80,
202*5c1def83SBjoern A. Zeeb [NL80211_CHAN_WIDTH_320] = MODE_11BE_EHT320,
203*5c1def83SBjoern A. Zeeb },
204*5c1def83SBjoern A. Zeeb [NL80211_BAND_6GHZ] = {
205*5c1def83SBjoern A. Zeeb [NL80211_CHAN_WIDTH_5] = MODE_UNKNOWN,
206*5c1def83SBjoern A. Zeeb [NL80211_CHAN_WIDTH_10] = MODE_UNKNOWN,
207*5c1def83SBjoern A. Zeeb [NL80211_CHAN_WIDTH_20_NOHT] = MODE_11BE_EHT20,
208*5c1def83SBjoern A. Zeeb [NL80211_CHAN_WIDTH_20] = MODE_11BE_EHT20,
209*5c1def83SBjoern A. Zeeb [NL80211_CHAN_WIDTH_40] = MODE_11BE_EHT40,
210*5c1def83SBjoern A. Zeeb [NL80211_CHAN_WIDTH_80] = MODE_11BE_EHT80,
211*5c1def83SBjoern A. Zeeb [NL80211_CHAN_WIDTH_160] = MODE_11BE_EHT160,
212*5c1def83SBjoern A. Zeeb [NL80211_CHAN_WIDTH_80P80] = MODE_11BE_EHT80_80,
213*5c1def83SBjoern A. Zeeb [NL80211_CHAN_WIDTH_320] = MODE_11BE_EHT320,
214*5c1def83SBjoern A. Zeeb },
215*5c1def83SBjoern A. Zeeb
216*5c1def83SBjoern A. Zeeb };
217*5c1def83SBjoern A. Zeeb
218*5c1def83SBjoern A. Zeeb const struct htt_rx_ring_tlv_filter ath12k_mac_mon_status_filter_default = {
219*5c1def83SBjoern A. Zeeb .rx_filter = HTT_RX_FILTER_TLV_FLAGS_MPDU_START |
220*5c1def83SBjoern A. Zeeb HTT_RX_FILTER_TLV_FLAGS_PPDU_END |
221*5c1def83SBjoern A. Zeeb HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE,
222*5c1def83SBjoern A. Zeeb .pkt_filter_flags0 = HTT_RX_FP_MGMT_FILTER_FLAGS0,
223*5c1def83SBjoern A. Zeeb .pkt_filter_flags1 = HTT_RX_FP_MGMT_FILTER_FLAGS1,
224*5c1def83SBjoern A. Zeeb .pkt_filter_flags2 = HTT_RX_FP_CTRL_FILTER_FLASG2,
225*5c1def83SBjoern A. Zeeb .pkt_filter_flags3 = HTT_RX_FP_DATA_FILTER_FLASG3 |
226*5c1def83SBjoern A. Zeeb HTT_RX_FP_CTRL_FILTER_FLASG3
227*5c1def83SBjoern A. Zeeb };
228*5c1def83SBjoern A. Zeeb
229*5c1def83SBjoern A. Zeeb #define ATH12K_MAC_FIRST_OFDM_RATE_IDX 4
230*5c1def83SBjoern A. Zeeb #define ath12k_g_rates ath12k_legacy_rates
231*5c1def83SBjoern A. Zeeb #define ath12k_g_rates_size (ARRAY_SIZE(ath12k_legacy_rates))
232*5c1def83SBjoern A. Zeeb #define ath12k_a_rates (ath12k_legacy_rates + 4)
233*5c1def83SBjoern A. Zeeb #define ath12k_a_rates_size (ARRAY_SIZE(ath12k_legacy_rates) - 4)
234*5c1def83SBjoern A. Zeeb
235*5c1def83SBjoern A. Zeeb #define ATH12K_MAC_SCAN_TIMEOUT_MSECS 200 /* in msecs */
236*5c1def83SBjoern A. Zeeb
237*5c1def83SBjoern A. Zeeb static const u32 ath12k_smps_map[] = {
238*5c1def83SBjoern A. Zeeb [WLAN_HT_CAP_SM_PS_STATIC] = WMI_PEER_SMPS_STATIC,
239*5c1def83SBjoern A. Zeeb [WLAN_HT_CAP_SM_PS_DYNAMIC] = WMI_PEER_SMPS_DYNAMIC,
240*5c1def83SBjoern A. Zeeb [WLAN_HT_CAP_SM_PS_INVALID] = WMI_PEER_SMPS_PS_NONE,
241*5c1def83SBjoern A. Zeeb [WLAN_HT_CAP_SM_PS_DISABLED] = WMI_PEER_SMPS_PS_NONE,
242*5c1def83SBjoern A. Zeeb };
243*5c1def83SBjoern A. Zeeb
244*5c1def83SBjoern A. Zeeb static int ath12k_start_vdev_delay(struct ieee80211_hw *hw,
245*5c1def83SBjoern A. Zeeb struct ieee80211_vif *vif);
246*5c1def83SBjoern A. Zeeb
ath12k_mac_phymode_str(enum wmi_phy_mode mode)247*5c1def83SBjoern A. Zeeb static const char *ath12k_mac_phymode_str(enum wmi_phy_mode mode)
248*5c1def83SBjoern A. Zeeb {
249*5c1def83SBjoern A. Zeeb switch (mode) {
250*5c1def83SBjoern A. Zeeb case MODE_11A:
251*5c1def83SBjoern A. Zeeb return "11a";
252*5c1def83SBjoern A. Zeeb case MODE_11G:
253*5c1def83SBjoern A. Zeeb return "11g";
254*5c1def83SBjoern A. Zeeb case MODE_11B:
255*5c1def83SBjoern A. Zeeb return "11b";
256*5c1def83SBjoern A. Zeeb case MODE_11GONLY:
257*5c1def83SBjoern A. Zeeb return "11gonly";
258*5c1def83SBjoern A. Zeeb case MODE_11NA_HT20:
259*5c1def83SBjoern A. Zeeb return "11na-ht20";
260*5c1def83SBjoern A. Zeeb case MODE_11NG_HT20:
261*5c1def83SBjoern A. Zeeb return "11ng-ht20";
262*5c1def83SBjoern A. Zeeb case MODE_11NA_HT40:
263*5c1def83SBjoern A. Zeeb return "11na-ht40";
264*5c1def83SBjoern A. Zeeb case MODE_11NG_HT40:
265*5c1def83SBjoern A. Zeeb return "11ng-ht40";
266*5c1def83SBjoern A. Zeeb case MODE_11AC_VHT20:
267*5c1def83SBjoern A. Zeeb return "11ac-vht20";
268*5c1def83SBjoern A. Zeeb case MODE_11AC_VHT40:
269*5c1def83SBjoern A. Zeeb return "11ac-vht40";
270*5c1def83SBjoern A. Zeeb case MODE_11AC_VHT80:
271*5c1def83SBjoern A. Zeeb return "11ac-vht80";
272*5c1def83SBjoern A. Zeeb case MODE_11AC_VHT160:
273*5c1def83SBjoern A. Zeeb return "11ac-vht160";
274*5c1def83SBjoern A. Zeeb case MODE_11AC_VHT80_80:
275*5c1def83SBjoern A. Zeeb return "11ac-vht80+80";
276*5c1def83SBjoern A. Zeeb case MODE_11AC_VHT20_2G:
277*5c1def83SBjoern A. Zeeb return "11ac-vht20-2g";
278*5c1def83SBjoern A. Zeeb case MODE_11AC_VHT40_2G:
279*5c1def83SBjoern A. Zeeb return "11ac-vht40-2g";
280*5c1def83SBjoern A. Zeeb case MODE_11AC_VHT80_2G:
281*5c1def83SBjoern A. Zeeb return "11ac-vht80-2g";
282*5c1def83SBjoern A. Zeeb case MODE_11AX_HE20:
283*5c1def83SBjoern A. Zeeb return "11ax-he20";
284*5c1def83SBjoern A. Zeeb case MODE_11AX_HE40:
285*5c1def83SBjoern A. Zeeb return "11ax-he40";
286*5c1def83SBjoern A. Zeeb case MODE_11AX_HE80:
287*5c1def83SBjoern A. Zeeb return "11ax-he80";
288*5c1def83SBjoern A. Zeeb case MODE_11AX_HE80_80:
289*5c1def83SBjoern A. Zeeb return "11ax-he80+80";
290*5c1def83SBjoern A. Zeeb case MODE_11AX_HE160:
291*5c1def83SBjoern A. Zeeb return "11ax-he160";
292*5c1def83SBjoern A. Zeeb case MODE_11AX_HE20_2G:
293*5c1def83SBjoern A. Zeeb return "11ax-he20-2g";
294*5c1def83SBjoern A. Zeeb case MODE_11AX_HE40_2G:
295*5c1def83SBjoern A. Zeeb return "11ax-he40-2g";
296*5c1def83SBjoern A. Zeeb case MODE_11AX_HE80_2G:
297*5c1def83SBjoern A. Zeeb return "11ax-he80-2g";
298*5c1def83SBjoern A. Zeeb case MODE_11BE_EHT20:
299*5c1def83SBjoern A. Zeeb return "11be-eht20";
300*5c1def83SBjoern A. Zeeb case MODE_11BE_EHT40:
301*5c1def83SBjoern A. Zeeb return "11be-eht40";
302*5c1def83SBjoern A. Zeeb case MODE_11BE_EHT80:
303*5c1def83SBjoern A. Zeeb return "11be-eht80";
304*5c1def83SBjoern A. Zeeb case MODE_11BE_EHT80_80:
305*5c1def83SBjoern A. Zeeb return "11be-eht80+80";
306*5c1def83SBjoern A. Zeeb case MODE_11BE_EHT160:
307*5c1def83SBjoern A. Zeeb return "11be-eht160";
308*5c1def83SBjoern A. Zeeb case MODE_11BE_EHT160_160:
309*5c1def83SBjoern A. Zeeb return "11be-eht160+160";
310*5c1def83SBjoern A. Zeeb case MODE_11BE_EHT320:
311*5c1def83SBjoern A. Zeeb return "11be-eht320";
312*5c1def83SBjoern A. Zeeb case MODE_11BE_EHT20_2G:
313*5c1def83SBjoern A. Zeeb return "11be-eht20-2g";
314*5c1def83SBjoern A. Zeeb case MODE_11BE_EHT40_2G:
315*5c1def83SBjoern A. Zeeb return "11be-eht40-2g";
316*5c1def83SBjoern A. Zeeb case MODE_UNKNOWN:
317*5c1def83SBjoern A. Zeeb /* skip */
318*5c1def83SBjoern A. Zeeb break;
319*5c1def83SBjoern A. Zeeb
320*5c1def83SBjoern A. Zeeb /* no default handler to allow compiler to check that the
321*5c1def83SBjoern A. Zeeb * enum is fully handled
322*5c1def83SBjoern A. Zeeb */
323*5c1def83SBjoern A. Zeeb }
324*5c1def83SBjoern A. Zeeb
325*5c1def83SBjoern A. Zeeb return "<unknown>";
326*5c1def83SBjoern A. Zeeb }
327*5c1def83SBjoern A. Zeeb
328*5c1def83SBjoern A. Zeeb enum rate_info_bw
ath12k_mac_bw_to_mac80211_bw(enum ath12k_supported_bw bw)329*5c1def83SBjoern A. Zeeb ath12k_mac_bw_to_mac80211_bw(enum ath12k_supported_bw bw)
330*5c1def83SBjoern A. Zeeb {
331*5c1def83SBjoern A. Zeeb u8 ret = RATE_INFO_BW_20;
332*5c1def83SBjoern A. Zeeb
333*5c1def83SBjoern A. Zeeb switch (bw) {
334*5c1def83SBjoern A. Zeeb case ATH12K_BW_20:
335*5c1def83SBjoern A. Zeeb ret = RATE_INFO_BW_20;
336*5c1def83SBjoern A. Zeeb break;
337*5c1def83SBjoern A. Zeeb case ATH12K_BW_40:
338*5c1def83SBjoern A. Zeeb ret = RATE_INFO_BW_40;
339*5c1def83SBjoern A. Zeeb break;
340*5c1def83SBjoern A. Zeeb case ATH12K_BW_80:
341*5c1def83SBjoern A. Zeeb ret = RATE_INFO_BW_80;
342*5c1def83SBjoern A. Zeeb break;
343*5c1def83SBjoern A. Zeeb case ATH12K_BW_160:
344*5c1def83SBjoern A. Zeeb ret = RATE_INFO_BW_160;
345*5c1def83SBjoern A. Zeeb break;
346*5c1def83SBjoern A. Zeeb }
347*5c1def83SBjoern A. Zeeb
348*5c1def83SBjoern A. Zeeb return ret;
349*5c1def83SBjoern A. Zeeb }
350*5c1def83SBjoern A. Zeeb
ath12k_mac_mac80211_bw_to_ath12k_bw(enum rate_info_bw bw)351*5c1def83SBjoern A. Zeeb enum ath12k_supported_bw ath12k_mac_mac80211_bw_to_ath12k_bw(enum rate_info_bw bw)
352*5c1def83SBjoern A. Zeeb {
353*5c1def83SBjoern A. Zeeb switch (bw) {
354*5c1def83SBjoern A. Zeeb case RATE_INFO_BW_20:
355*5c1def83SBjoern A. Zeeb return ATH12K_BW_20;
356*5c1def83SBjoern A. Zeeb case RATE_INFO_BW_40:
357*5c1def83SBjoern A. Zeeb return ATH12K_BW_40;
358*5c1def83SBjoern A. Zeeb case RATE_INFO_BW_80:
359*5c1def83SBjoern A. Zeeb return ATH12K_BW_80;
360*5c1def83SBjoern A. Zeeb case RATE_INFO_BW_160:
361*5c1def83SBjoern A. Zeeb return ATH12K_BW_160;
362*5c1def83SBjoern A. Zeeb default:
363*5c1def83SBjoern A. Zeeb return ATH12K_BW_20;
364*5c1def83SBjoern A. Zeeb }
365*5c1def83SBjoern A. Zeeb }
366*5c1def83SBjoern A. Zeeb
ath12k_mac_hw_ratecode_to_legacy_rate(u8 hw_rc,u8 preamble,u8 * rateidx,u16 * rate)367*5c1def83SBjoern A. Zeeb int ath12k_mac_hw_ratecode_to_legacy_rate(u8 hw_rc, u8 preamble, u8 *rateidx,
368*5c1def83SBjoern A. Zeeb u16 *rate)
369*5c1def83SBjoern A. Zeeb {
370*5c1def83SBjoern A. Zeeb /* As default, it is OFDM rates */
371*5c1def83SBjoern A. Zeeb int i = ATH12K_MAC_FIRST_OFDM_RATE_IDX;
372*5c1def83SBjoern A. Zeeb int max_rates_idx = ath12k_g_rates_size;
373*5c1def83SBjoern A. Zeeb
374*5c1def83SBjoern A. Zeeb if (preamble == WMI_RATE_PREAMBLE_CCK) {
375*5c1def83SBjoern A. Zeeb hw_rc &= ~ATH12K_HW_RATECODE_CCK_SHORT_PREAM_MASK;
376*5c1def83SBjoern A. Zeeb i = 0;
377*5c1def83SBjoern A. Zeeb max_rates_idx = ATH12K_MAC_FIRST_OFDM_RATE_IDX;
378*5c1def83SBjoern A. Zeeb }
379*5c1def83SBjoern A. Zeeb
380*5c1def83SBjoern A. Zeeb while (i < max_rates_idx) {
381*5c1def83SBjoern A. Zeeb if (hw_rc == ath12k_legacy_rates[i].hw_value) {
382*5c1def83SBjoern A. Zeeb *rateidx = i;
383*5c1def83SBjoern A. Zeeb *rate = ath12k_legacy_rates[i].bitrate;
384*5c1def83SBjoern A. Zeeb return 0;
385*5c1def83SBjoern A. Zeeb }
386*5c1def83SBjoern A. Zeeb i++;
387*5c1def83SBjoern A. Zeeb }
388*5c1def83SBjoern A. Zeeb
389*5c1def83SBjoern A. Zeeb return -EINVAL;
390*5c1def83SBjoern A. Zeeb }
391*5c1def83SBjoern A. Zeeb
ath12k_mac_bitrate_to_idx(const struct ieee80211_supported_band * sband,u32 bitrate)392*5c1def83SBjoern A. Zeeb u8 ath12k_mac_bitrate_to_idx(const struct ieee80211_supported_band *sband,
393*5c1def83SBjoern A. Zeeb u32 bitrate)
394*5c1def83SBjoern A. Zeeb {
395*5c1def83SBjoern A. Zeeb int i;
396*5c1def83SBjoern A. Zeeb
397*5c1def83SBjoern A. Zeeb for (i = 0; i < sband->n_bitrates; i++)
398*5c1def83SBjoern A. Zeeb if (sband->bitrates[i].bitrate == bitrate)
399*5c1def83SBjoern A. Zeeb return i;
400*5c1def83SBjoern A. Zeeb
401*5c1def83SBjoern A. Zeeb return 0;
402*5c1def83SBjoern A. Zeeb }
403*5c1def83SBjoern A. Zeeb
404*5c1def83SBjoern A. Zeeb static u32
ath12k_mac_max_ht_nss(const u8 * ht_mcs_mask)405*5c1def83SBjoern A. Zeeb ath12k_mac_max_ht_nss(const u8 *ht_mcs_mask)
406*5c1def83SBjoern A. Zeeb {
407*5c1def83SBjoern A. Zeeb int nss;
408*5c1def83SBjoern A. Zeeb
409*5c1def83SBjoern A. Zeeb for (nss = IEEE80211_HT_MCS_MASK_LEN - 1; nss >= 0; nss--)
410*5c1def83SBjoern A. Zeeb if (ht_mcs_mask[nss])
411*5c1def83SBjoern A. Zeeb return nss + 1;
412*5c1def83SBjoern A. Zeeb
413*5c1def83SBjoern A. Zeeb return 1;
414*5c1def83SBjoern A. Zeeb }
415*5c1def83SBjoern A. Zeeb
416*5c1def83SBjoern A. Zeeb static u32
ath12k_mac_max_vht_nss(const u16 * vht_mcs_mask)417*5c1def83SBjoern A. Zeeb ath12k_mac_max_vht_nss(const u16 *vht_mcs_mask)
418*5c1def83SBjoern A. Zeeb {
419*5c1def83SBjoern A. Zeeb int nss;
420*5c1def83SBjoern A. Zeeb
421*5c1def83SBjoern A. Zeeb for (nss = NL80211_VHT_NSS_MAX - 1; nss >= 0; nss--)
422*5c1def83SBjoern A. Zeeb if (vht_mcs_mask[nss])
423*5c1def83SBjoern A. Zeeb return nss + 1;
424*5c1def83SBjoern A. Zeeb
425*5c1def83SBjoern A. Zeeb return 1;
426*5c1def83SBjoern A. Zeeb }
427*5c1def83SBjoern A. Zeeb
ath12k_parse_mpdudensity(u8 mpdudensity)428*5c1def83SBjoern A. Zeeb static u8 ath12k_parse_mpdudensity(u8 mpdudensity)
429*5c1def83SBjoern A. Zeeb {
430*5c1def83SBjoern A. Zeeb /* From IEEE Std 802.11-2020 defined values for "Minimum MPDU Start Spacing":
431*5c1def83SBjoern A. Zeeb * 0 for no restriction
432*5c1def83SBjoern A. Zeeb * 1 for 1/4 us
433*5c1def83SBjoern A. Zeeb * 2 for 1/2 us
434*5c1def83SBjoern A. Zeeb * 3 for 1 us
435*5c1def83SBjoern A. Zeeb * 4 for 2 us
436*5c1def83SBjoern A. Zeeb * 5 for 4 us
437*5c1def83SBjoern A. Zeeb * 6 for 8 us
438*5c1def83SBjoern A. Zeeb * 7 for 16 us
439*5c1def83SBjoern A. Zeeb */
440*5c1def83SBjoern A. Zeeb switch (mpdudensity) {
441*5c1def83SBjoern A. Zeeb case 0:
442*5c1def83SBjoern A. Zeeb return 0;
443*5c1def83SBjoern A. Zeeb case 1:
444*5c1def83SBjoern A. Zeeb case 2:
445*5c1def83SBjoern A. Zeeb case 3:
446*5c1def83SBjoern A. Zeeb /* Our lower layer calculations limit our precision to
447*5c1def83SBjoern A. Zeeb * 1 microsecond
448*5c1def83SBjoern A. Zeeb */
449*5c1def83SBjoern A. Zeeb return 1;
450*5c1def83SBjoern A. Zeeb case 4:
451*5c1def83SBjoern A. Zeeb return 2;
452*5c1def83SBjoern A. Zeeb case 5:
453*5c1def83SBjoern A. Zeeb return 4;
454*5c1def83SBjoern A. Zeeb case 6:
455*5c1def83SBjoern A. Zeeb return 8;
456*5c1def83SBjoern A. Zeeb case 7:
457*5c1def83SBjoern A. Zeeb return 16;
458*5c1def83SBjoern A. Zeeb default:
459*5c1def83SBjoern A. Zeeb return 0;
460*5c1def83SBjoern A. Zeeb }
461*5c1def83SBjoern A. Zeeb }
462*5c1def83SBjoern A. Zeeb
ath12k_mac_vif_chan(struct ieee80211_vif * vif,struct cfg80211_chan_def * def)463*5c1def83SBjoern A. Zeeb static int ath12k_mac_vif_chan(struct ieee80211_vif *vif,
464*5c1def83SBjoern A. Zeeb struct cfg80211_chan_def *def)
465*5c1def83SBjoern A. Zeeb {
466*5c1def83SBjoern A. Zeeb struct ieee80211_chanctx_conf *conf;
467*5c1def83SBjoern A. Zeeb
468*5c1def83SBjoern A. Zeeb rcu_read_lock();
469*5c1def83SBjoern A. Zeeb conf = rcu_dereference(vif->bss_conf.chanctx_conf);
470*5c1def83SBjoern A. Zeeb if (!conf) {
471*5c1def83SBjoern A. Zeeb rcu_read_unlock();
472*5c1def83SBjoern A. Zeeb return -ENOENT;
473*5c1def83SBjoern A. Zeeb }
474*5c1def83SBjoern A. Zeeb
475*5c1def83SBjoern A. Zeeb *def = conf->def;
476*5c1def83SBjoern A. Zeeb rcu_read_unlock();
477*5c1def83SBjoern A. Zeeb
478*5c1def83SBjoern A. Zeeb return 0;
479*5c1def83SBjoern A. Zeeb }
480*5c1def83SBjoern A. Zeeb
ath12k_mac_bitrate_is_cck(int bitrate)481*5c1def83SBjoern A. Zeeb static bool ath12k_mac_bitrate_is_cck(int bitrate)
482*5c1def83SBjoern A. Zeeb {
483*5c1def83SBjoern A. Zeeb switch (bitrate) {
484*5c1def83SBjoern A. Zeeb case 10:
485*5c1def83SBjoern A. Zeeb case 20:
486*5c1def83SBjoern A. Zeeb case 55:
487*5c1def83SBjoern A. Zeeb case 110:
488*5c1def83SBjoern A. Zeeb return true;
489*5c1def83SBjoern A. Zeeb }
490*5c1def83SBjoern A. Zeeb
491*5c1def83SBjoern A. Zeeb return false;
492*5c1def83SBjoern A. Zeeb }
493*5c1def83SBjoern A. Zeeb
ath12k_mac_hw_rate_to_idx(const struct ieee80211_supported_band * sband,u8 hw_rate,bool cck)494*5c1def83SBjoern A. Zeeb u8 ath12k_mac_hw_rate_to_idx(const struct ieee80211_supported_band *sband,
495*5c1def83SBjoern A. Zeeb u8 hw_rate, bool cck)
496*5c1def83SBjoern A. Zeeb {
497*5c1def83SBjoern A. Zeeb const struct ieee80211_rate *rate;
498*5c1def83SBjoern A. Zeeb int i;
499*5c1def83SBjoern A. Zeeb
500*5c1def83SBjoern A. Zeeb for (i = 0; i < sband->n_bitrates; i++) {
501*5c1def83SBjoern A. Zeeb rate = &sband->bitrates[i];
502*5c1def83SBjoern A. Zeeb
503*5c1def83SBjoern A. Zeeb if (ath12k_mac_bitrate_is_cck(rate->bitrate) != cck)
504*5c1def83SBjoern A. Zeeb continue;
505*5c1def83SBjoern A. Zeeb
506*5c1def83SBjoern A. Zeeb if (rate->hw_value == hw_rate)
507*5c1def83SBjoern A. Zeeb return i;
508*5c1def83SBjoern A. Zeeb else if (rate->flags & IEEE80211_RATE_SHORT_PREAMBLE &&
509*5c1def83SBjoern A. Zeeb rate->hw_value_short == hw_rate)
510*5c1def83SBjoern A. Zeeb return i;
511*5c1def83SBjoern A. Zeeb }
512*5c1def83SBjoern A. Zeeb
513*5c1def83SBjoern A. Zeeb return 0;
514*5c1def83SBjoern A. Zeeb }
515*5c1def83SBjoern A. Zeeb
ath12k_mac_bitrate_to_rate(int bitrate)516*5c1def83SBjoern A. Zeeb static u8 ath12k_mac_bitrate_to_rate(int bitrate)
517*5c1def83SBjoern A. Zeeb {
518*5c1def83SBjoern A. Zeeb return DIV_ROUND_UP(bitrate, 5) |
519*5c1def83SBjoern A. Zeeb (ath12k_mac_bitrate_is_cck(bitrate) ? BIT(7) : 0);
520*5c1def83SBjoern A. Zeeb }
521*5c1def83SBjoern A. Zeeb
ath12k_get_arvif_iter(void * data,u8 * mac,struct ieee80211_vif * vif)522*5c1def83SBjoern A. Zeeb static void ath12k_get_arvif_iter(void *data, u8 *mac,
523*5c1def83SBjoern A. Zeeb struct ieee80211_vif *vif)
524*5c1def83SBjoern A. Zeeb {
525*5c1def83SBjoern A. Zeeb struct ath12k_vif_iter *arvif_iter = data;
526*5c1def83SBjoern A. Zeeb struct ath12k_vif *arvif = (void *)vif->drv_priv;
527*5c1def83SBjoern A. Zeeb
528*5c1def83SBjoern A. Zeeb if (arvif->vdev_id == arvif_iter->vdev_id)
529*5c1def83SBjoern A. Zeeb arvif_iter->arvif = arvif;
530*5c1def83SBjoern A. Zeeb }
531*5c1def83SBjoern A. Zeeb
ath12k_mac_get_arvif(struct ath12k * ar,u32 vdev_id)532*5c1def83SBjoern A. Zeeb struct ath12k_vif *ath12k_mac_get_arvif(struct ath12k *ar, u32 vdev_id)
533*5c1def83SBjoern A. Zeeb {
534*5c1def83SBjoern A. Zeeb struct ath12k_vif_iter arvif_iter = {};
535*5c1def83SBjoern A. Zeeb u32 flags;
536*5c1def83SBjoern A. Zeeb
537*5c1def83SBjoern A. Zeeb arvif_iter.vdev_id = vdev_id;
538*5c1def83SBjoern A. Zeeb
539*5c1def83SBjoern A. Zeeb flags = IEEE80211_IFACE_ITER_RESUME_ALL;
540*5c1def83SBjoern A. Zeeb ieee80211_iterate_active_interfaces_atomic(ar->hw,
541*5c1def83SBjoern A. Zeeb flags,
542*5c1def83SBjoern A. Zeeb ath12k_get_arvif_iter,
543*5c1def83SBjoern A. Zeeb &arvif_iter);
544*5c1def83SBjoern A. Zeeb if (!arvif_iter.arvif) {
545*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "No VIF found for vdev %d\n", vdev_id);
546*5c1def83SBjoern A. Zeeb return NULL;
547*5c1def83SBjoern A. Zeeb }
548*5c1def83SBjoern A. Zeeb
549*5c1def83SBjoern A. Zeeb return arvif_iter.arvif;
550*5c1def83SBjoern A. Zeeb }
551*5c1def83SBjoern A. Zeeb
ath12k_mac_get_arvif_by_vdev_id(struct ath12k_base * ab,u32 vdev_id)552*5c1def83SBjoern A. Zeeb struct ath12k_vif *ath12k_mac_get_arvif_by_vdev_id(struct ath12k_base *ab,
553*5c1def83SBjoern A. Zeeb u32 vdev_id)
554*5c1def83SBjoern A. Zeeb {
555*5c1def83SBjoern A. Zeeb int i;
556*5c1def83SBjoern A. Zeeb struct ath12k_pdev *pdev;
557*5c1def83SBjoern A. Zeeb struct ath12k_vif *arvif;
558*5c1def83SBjoern A. Zeeb
559*5c1def83SBjoern A. Zeeb for (i = 0; i < ab->num_radios; i++) {
560*5c1def83SBjoern A. Zeeb pdev = rcu_dereference(ab->pdevs_active[i]);
561*5c1def83SBjoern A. Zeeb if (pdev && pdev->ar) {
562*5c1def83SBjoern A. Zeeb arvif = ath12k_mac_get_arvif(pdev->ar, vdev_id);
563*5c1def83SBjoern A. Zeeb if (arvif)
564*5c1def83SBjoern A. Zeeb return arvif;
565*5c1def83SBjoern A. Zeeb }
566*5c1def83SBjoern A. Zeeb }
567*5c1def83SBjoern A. Zeeb
568*5c1def83SBjoern A. Zeeb return NULL;
569*5c1def83SBjoern A. Zeeb }
570*5c1def83SBjoern A. Zeeb
ath12k_mac_get_ar_by_vdev_id(struct ath12k_base * ab,u32 vdev_id)571*5c1def83SBjoern A. Zeeb struct ath12k *ath12k_mac_get_ar_by_vdev_id(struct ath12k_base *ab, u32 vdev_id)
572*5c1def83SBjoern A. Zeeb {
573*5c1def83SBjoern A. Zeeb int i;
574*5c1def83SBjoern A. Zeeb struct ath12k_pdev *pdev;
575*5c1def83SBjoern A. Zeeb
576*5c1def83SBjoern A. Zeeb for (i = 0; i < ab->num_radios; i++) {
577*5c1def83SBjoern A. Zeeb pdev = rcu_dereference(ab->pdevs_active[i]);
578*5c1def83SBjoern A. Zeeb if (pdev && pdev->ar) {
579*5c1def83SBjoern A. Zeeb if (pdev->ar->allocated_vdev_map & (1LL << vdev_id))
580*5c1def83SBjoern A. Zeeb return pdev->ar;
581*5c1def83SBjoern A. Zeeb }
582*5c1def83SBjoern A. Zeeb }
583*5c1def83SBjoern A. Zeeb
584*5c1def83SBjoern A. Zeeb return NULL;
585*5c1def83SBjoern A. Zeeb }
586*5c1def83SBjoern A. Zeeb
ath12k_mac_get_ar_by_pdev_id(struct ath12k_base * ab,u32 pdev_id)587*5c1def83SBjoern A. Zeeb struct ath12k *ath12k_mac_get_ar_by_pdev_id(struct ath12k_base *ab, u32 pdev_id)
588*5c1def83SBjoern A. Zeeb {
589*5c1def83SBjoern A. Zeeb int i;
590*5c1def83SBjoern A. Zeeb struct ath12k_pdev *pdev;
591*5c1def83SBjoern A. Zeeb
592*5c1def83SBjoern A. Zeeb if (ab->hw_params->single_pdev_only) {
593*5c1def83SBjoern A. Zeeb pdev = rcu_dereference(ab->pdevs_active[0]);
594*5c1def83SBjoern A. Zeeb return pdev ? pdev->ar : NULL;
595*5c1def83SBjoern A. Zeeb }
596*5c1def83SBjoern A. Zeeb
597*5c1def83SBjoern A. Zeeb if (WARN_ON(pdev_id > ab->num_radios))
598*5c1def83SBjoern A. Zeeb return NULL;
599*5c1def83SBjoern A. Zeeb
600*5c1def83SBjoern A. Zeeb for (i = 0; i < ab->num_radios; i++) {
601*5c1def83SBjoern A. Zeeb pdev = rcu_dereference(ab->pdevs_active[i]);
602*5c1def83SBjoern A. Zeeb
603*5c1def83SBjoern A. Zeeb if (pdev && pdev->pdev_id == pdev_id)
604*5c1def83SBjoern A. Zeeb return (pdev->ar ? pdev->ar : NULL);
605*5c1def83SBjoern A. Zeeb }
606*5c1def83SBjoern A. Zeeb
607*5c1def83SBjoern A. Zeeb return NULL;
608*5c1def83SBjoern A. Zeeb }
609*5c1def83SBjoern A. Zeeb
ath12k_pdev_caps_update(struct ath12k * ar)610*5c1def83SBjoern A. Zeeb static void ath12k_pdev_caps_update(struct ath12k *ar)
611*5c1def83SBjoern A. Zeeb {
612*5c1def83SBjoern A. Zeeb struct ath12k_base *ab = ar->ab;
613*5c1def83SBjoern A. Zeeb
614*5c1def83SBjoern A. Zeeb ar->max_tx_power = ab->target_caps.hw_max_tx_power;
615*5c1def83SBjoern A. Zeeb
616*5c1def83SBjoern A. Zeeb /* FIXME: Set min_tx_power to ab->target_caps.hw_min_tx_power.
617*5c1def83SBjoern A. Zeeb * But since the received value in svcrdy is same as hw_max_tx_power,
618*5c1def83SBjoern A. Zeeb * we can set ar->min_tx_power to 0 currently until
619*5c1def83SBjoern A. Zeeb * this is fixed in firmware
620*5c1def83SBjoern A. Zeeb */
621*5c1def83SBjoern A. Zeeb ar->min_tx_power = 0;
622*5c1def83SBjoern A. Zeeb
623*5c1def83SBjoern A. Zeeb ar->txpower_limit_2g = ar->max_tx_power;
624*5c1def83SBjoern A. Zeeb ar->txpower_limit_5g = ar->max_tx_power;
625*5c1def83SBjoern A. Zeeb ar->txpower_scale = WMI_HOST_TP_SCALE_MAX;
626*5c1def83SBjoern A. Zeeb }
627*5c1def83SBjoern A. Zeeb
ath12k_mac_txpower_recalc(struct ath12k * ar)628*5c1def83SBjoern A. Zeeb static int ath12k_mac_txpower_recalc(struct ath12k *ar)
629*5c1def83SBjoern A. Zeeb {
630*5c1def83SBjoern A. Zeeb struct ath12k_pdev *pdev = ar->pdev;
631*5c1def83SBjoern A. Zeeb struct ath12k_vif *arvif;
632*5c1def83SBjoern A. Zeeb int ret, txpower = -1;
633*5c1def83SBjoern A. Zeeb u32 param;
634*5c1def83SBjoern A. Zeeb
635*5c1def83SBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
636*5c1def83SBjoern A. Zeeb
637*5c1def83SBjoern A. Zeeb list_for_each_entry(arvif, &ar->arvifs, list) {
638*5c1def83SBjoern A. Zeeb if (arvif->txpower <= 0)
639*5c1def83SBjoern A. Zeeb continue;
640*5c1def83SBjoern A. Zeeb
641*5c1def83SBjoern A. Zeeb if (txpower == -1)
642*5c1def83SBjoern A. Zeeb txpower = arvif->txpower;
643*5c1def83SBjoern A. Zeeb else
644*5c1def83SBjoern A. Zeeb txpower = min(txpower, arvif->txpower);
645*5c1def83SBjoern A. Zeeb }
646*5c1def83SBjoern A. Zeeb
647*5c1def83SBjoern A. Zeeb if (txpower == -1)
648*5c1def83SBjoern A. Zeeb return 0;
649*5c1def83SBjoern A. Zeeb
650*5c1def83SBjoern A. Zeeb /* txpwr is set as 2 units per dBm in FW*/
651*5c1def83SBjoern A. Zeeb txpower = min_t(u32, max_t(u32, ar->min_tx_power, txpower),
652*5c1def83SBjoern A. Zeeb ar->max_tx_power) * 2;
653*5c1def83SBjoern A. Zeeb
654*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "txpower to set in hw %d\n",
655*5c1def83SBjoern A. Zeeb txpower / 2);
656*5c1def83SBjoern A. Zeeb
657*5c1def83SBjoern A. Zeeb if ((pdev->cap.supported_bands & WMI_HOST_WLAN_2G_CAP) &&
658*5c1def83SBjoern A. Zeeb ar->txpower_limit_2g != txpower) {
659*5c1def83SBjoern A. Zeeb param = WMI_PDEV_PARAM_TXPOWER_LIMIT2G;
660*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_pdev_set_param(ar, param,
661*5c1def83SBjoern A. Zeeb txpower, ar->pdev->pdev_id);
662*5c1def83SBjoern A. Zeeb if (ret)
663*5c1def83SBjoern A. Zeeb goto fail;
664*5c1def83SBjoern A. Zeeb ar->txpower_limit_2g = txpower;
665*5c1def83SBjoern A. Zeeb }
666*5c1def83SBjoern A. Zeeb
667*5c1def83SBjoern A. Zeeb if ((pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP) &&
668*5c1def83SBjoern A. Zeeb ar->txpower_limit_5g != txpower) {
669*5c1def83SBjoern A. Zeeb param = WMI_PDEV_PARAM_TXPOWER_LIMIT5G;
670*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_pdev_set_param(ar, param,
671*5c1def83SBjoern A. Zeeb txpower, ar->pdev->pdev_id);
672*5c1def83SBjoern A. Zeeb if (ret)
673*5c1def83SBjoern A. Zeeb goto fail;
674*5c1def83SBjoern A. Zeeb ar->txpower_limit_5g = txpower;
675*5c1def83SBjoern A. Zeeb }
676*5c1def83SBjoern A. Zeeb
677*5c1def83SBjoern A. Zeeb return 0;
678*5c1def83SBjoern A. Zeeb
679*5c1def83SBjoern A. Zeeb fail:
680*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to recalc txpower limit %d using pdev param %d: %d\n",
681*5c1def83SBjoern A. Zeeb txpower / 2, param, ret);
682*5c1def83SBjoern A. Zeeb return ret;
683*5c1def83SBjoern A. Zeeb }
684*5c1def83SBjoern A. Zeeb
ath12k_recalc_rtscts_prot(struct ath12k_vif * arvif)685*5c1def83SBjoern A. Zeeb static int ath12k_recalc_rtscts_prot(struct ath12k_vif *arvif)
686*5c1def83SBjoern A. Zeeb {
687*5c1def83SBjoern A. Zeeb struct ath12k *ar = arvif->ar;
688*5c1def83SBjoern A. Zeeb u32 vdev_param, rts_cts;
689*5c1def83SBjoern A. Zeeb int ret;
690*5c1def83SBjoern A. Zeeb
691*5c1def83SBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
692*5c1def83SBjoern A. Zeeb
693*5c1def83SBjoern A. Zeeb vdev_param = WMI_VDEV_PARAM_ENABLE_RTSCTS;
694*5c1def83SBjoern A. Zeeb
695*5c1def83SBjoern A. Zeeb /* Enable RTS/CTS protection for sw retries (when legacy stations
696*5c1def83SBjoern A. Zeeb * are in BSS) or by default only for second rate series.
697*5c1def83SBjoern A. Zeeb * TODO: Check if we need to enable CTS 2 Self in any case
698*5c1def83SBjoern A. Zeeb */
699*5c1def83SBjoern A. Zeeb rts_cts = WMI_USE_RTS_CTS;
700*5c1def83SBjoern A. Zeeb
701*5c1def83SBjoern A. Zeeb if (arvif->num_legacy_stations > 0)
702*5c1def83SBjoern A. Zeeb rts_cts |= WMI_RTSCTS_ACROSS_SW_RETRIES << 4;
703*5c1def83SBjoern A. Zeeb else
704*5c1def83SBjoern A. Zeeb rts_cts |= WMI_RTSCTS_FOR_SECOND_RATESERIES << 4;
705*5c1def83SBjoern A. Zeeb
706*5c1def83SBjoern A. Zeeb /* Need not send duplicate param value to firmware */
707*5c1def83SBjoern A. Zeeb if (arvif->rtscts_prot_mode == rts_cts)
708*5c1def83SBjoern A. Zeeb return 0;
709*5c1def83SBjoern A. Zeeb
710*5c1def83SBjoern A. Zeeb arvif->rtscts_prot_mode = rts_cts;
711*5c1def83SBjoern A. Zeeb
712*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev %d recalc rts/cts prot %d\n",
713*5c1def83SBjoern A. Zeeb arvif->vdev_id, rts_cts);
714*5c1def83SBjoern A. Zeeb
715*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
716*5c1def83SBjoern A. Zeeb vdev_param, rts_cts);
717*5c1def83SBjoern A. Zeeb if (ret)
718*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to recalculate rts/cts prot for vdev %d: %d\n",
719*5c1def83SBjoern A. Zeeb arvif->vdev_id, ret);
720*5c1def83SBjoern A. Zeeb
721*5c1def83SBjoern A. Zeeb return ret;
722*5c1def83SBjoern A. Zeeb }
723*5c1def83SBjoern A. Zeeb
ath12k_mac_set_kickout(struct ath12k_vif * arvif)724*5c1def83SBjoern A. Zeeb static int ath12k_mac_set_kickout(struct ath12k_vif *arvif)
725*5c1def83SBjoern A. Zeeb {
726*5c1def83SBjoern A. Zeeb struct ath12k *ar = arvif->ar;
727*5c1def83SBjoern A. Zeeb u32 param;
728*5c1def83SBjoern A. Zeeb int ret;
729*5c1def83SBjoern A. Zeeb
730*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_STA_KICKOUT_TH,
731*5c1def83SBjoern A. Zeeb ATH12K_KICKOUT_THRESHOLD,
732*5c1def83SBjoern A. Zeeb ar->pdev->pdev_id);
733*5c1def83SBjoern A. Zeeb if (ret) {
734*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to set kickout threshold on vdev %i: %d\n",
735*5c1def83SBjoern A. Zeeb arvif->vdev_id, ret);
736*5c1def83SBjoern A. Zeeb return ret;
737*5c1def83SBjoern A. Zeeb }
738*5c1def83SBjoern A. Zeeb
739*5c1def83SBjoern A. Zeeb param = WMI_VDEV_PARAM_AP_KEEPALIVE_MIN_IDLE_INACTIVE_TIME_SECS;
740*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, param,
741*5c1def83SBjoern A. Zeeb ATH12K_KEEPALIVE_MIN_IDLE);
742*5c1def83SBjoern A. Zeeb if (ret) {
743*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to set keepalive minimum idle time on vdev %i: %d\n",
744*5c1def83SBjoern A. Zeeb arvif->vdev_id, ret);
745*5c1def83SBjoern A. Zeeb return ret;
746*5c1def83SBjoern A. Zeeb }
747*5c1def83SBjoern A. Zeeb
748*5c1def83SBjoern A. Zeeb param = WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_IDLE_INACTIVE_TIME_SECS;
749*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, param,
750*5c1def83SBjoern A. Zeeb ATH12K_KEEPALIVE_MAX_IDLE);
751*5c1def83SBjoern A. Zeeb if (ret) {
752*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to set keepalive maximum idle time on vdev %i: %d\n",
753*5c1def83SBjoern A. Zeeb arvif->vdev_id, ret);
754*5c1def83SBjoern A. Zeeb return ret;
755*5c1def83SBjoern A. Zeeb }
756*5c1def83SBjoern A. Zeeb
757*5c1def83SBjoern A. Zeeb param = WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS;
758*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, param,
759*5c1def83SBjoern A. Zeeb ATH12K_KEEPALIVE_MAX_UNRESPONSIVE);
760*5c1def83SBjoern A. Zeeb if (ret) {
761*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to set keepalive maximum unresponsive time on vdev %i: %d\n",
762*5c1def83SBjoern A. Zeeb arvif->vdev_id, ret);
763*5c1def83SBjoern A. Zeeb return ret;
764*5c1def83SBjoern A. Zeeb }
765*5c1def83SBjoern A. Zeeb
766*5c1def83SBjoern A. Zeeb return 0;
767*5c1def83SBjoern A. Zeeb }
768*5c1def83SBjoern A. Zeeb
ath12k_mac_peer_cleanup_all(struct ath12k * ar)769*5c1def83SBjoern A. Zeeb void ath12k_mac_peer_cleanup_all(struct ath12k *ar)
770*5c1def83SBjoern A. Zeeb {
771*5c1def83SBjoern A. Zeeb struct ath12k_peer *peer, *tmp;
772*5c1def83SBjoern A. Zeeb struct ath12k_base *ab = ar->ab;
773*5c1def83SBjoern A. Zeeb
774*5c1def83SBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
775*5c1def83SBjoern A. Zeeb
776*5c1def83SBjoern A. Zeeb spin_lock_bh(&ab->base_lock);
777*5c1def83SBjoern A. Zeeb list_for_each_entry_safe(peer, tmp, &ab->peers, list) {
778*5c1def83SBjoern A. Zeeb ath12k_dp_rx_peer_tid_cleanup(ar, peer);
779*5c1def83SBjoern A. Zeeb list_del(&peer->list);
780*5c1def83SBjoern A. Zeeb kfree(peer);
781*5c1def83SBjoern A. Zeeb }
782*5c1def83SBjoern A. Zeeb spin_unlock_bh(&ab->base_lock);
783*5c1def83SBjoern A. Zeeb
784*5c1def83SBjoern A. Zeeb ar->num_peers = 0;
785*5c1def83SBjoern A. Zeeb ar->num_stations = 0;
786*5c1def83SBjoern A. Zeeb }
787*5c1def83SBjoern A. Zeeb
ath12k_mac_vdev_setup_sync(struct ath12k * ar)788*5c1def83SBjoern A. Zeeb static int ath12k_mac_vdev_setup_sync(struct ath12k *ar)
789*5c1def83SBjoern A. Zeeb {
790*5c1def83SBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
791*5c1def83SBjoern A. Zeeb
792*5c1def83SBjoern A. Zeeb if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))
793*5c1def83SBjoern A. Zeeb return -ESHUTDOWN;
794*5c1def83SBjoern A. Zeeb
795*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "vdev setup timeout %d\n",
796*5c1def83SBjoern A. Zeeb ATH12K_VDEV_SETUP_TIMEOUT_HZ);
797*5c1def83SBjoern A. Zeeb
798*5c1def83SBjoern A. Zeeb if (!wait_for_completion_timeout(&ar->vdev_setup_done,
799*5c1def83SBjoern A. Zeeb ATH12K_VDEV_SETUP_TIMEOUT_HZ))
800*5c1def83SBjoern A. Zeeb return -ETIMEDOUT;
801*5c1def83SBjoern A. Zeeb
802*5c1def83SBjoern A. Zeeb return ar->last_wmi_vdev_start_status ? -EINVAL : 0;
803*5c1def83SBjoern A. Zeeb }
804*5c1def83SBjoern A. Zeeb
ath12k_monitor_vdev_up(struct ath12k * ar,int vdev_id)805*5c1def83SBjoern A. Zeeb static int ath12k_monitor_vdev_up(struct ath12k *ar, int vdev_id)
806*5c1def83SBjoern A. Zeeb {
807*5c1def83SBjoern A. Zeeb int ret;
808*5c1def83SBjoern A. Zeeb
809*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_up(ar, vdev_id, 0, ar->mac_addr);
810*5c1def83SBjoern A. Zeeb if (ret) {
811*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to put up monitor vdev %i: %d\n",
812*5c1def83SBjoern A. Zeeb vdev_id, ret);
813*5c1def83SBjoern A. Zeeb return ret;
814*5c1def83SBjoern A. Zeeb }
815*5c1def83SBjoern A. Zeeb
816*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac monitor vdev %i started\n",
817*5c1def83SBjoern A. Zeeb vdev_id);
818*5c1def83SBjoern A. Zeeb return 0;
819*5c1def83SBjoern A. Zeeb }
820*5c1def83SBjoern A. Zeeb
ath12k_mac_monitor_vdev_start(struct ath12k * ar,int vdev_id,struct cfg80211_chan_def * chandef)821*5c1def83SBjoern A. Zeeb static int ath12k_mac_monitor_vdev_start(struct ath12k *ar, int vdev_id,
822*5c1def83SBjoern A. Zeeb struct cfg80211_chan_def *chandef)
823*5c1def83SBjoern A. Zeeb {
824*5c1def83SBjoern A. Zeeb struct ieee80211_channel *channel;
825*5c1def83SBjoern A. Zeeb struct wmi_vdev_start_req_arg arg = {};
826*5c1def83SBjoern A. Zeeb int ret;
827*5c1def83SBjoern A. Zeeb
828*5c1def83SBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
829*5c1def83SBjoern A. Zeeb
830*5c1def83SBjoern A. Zeeb channel = chandef->chan;
831*5c1def83SBjoern A. Zeeb arg.vdev_id = vdev_id;
832*5c1def83SBjoern A. Zeeb arg.freq = channel->center_freq;
833*5c1def83SBjoern A. Zeeb arg.band_center_freq1 = chandef->center_freq1;
834*5c1def83SBjoern A. Zeeb arg.band_center_freq2 = chandef->center_freq2;
835*5c1def83SBjoern A. Zeeb arg.mode = ath12k_phymodes[chandef->chan->band][chandef->width];
836*5c1def83SBjoern A. Zeeb arg.chan_radar = !!(channel->flags & IEEE80211_CHAN_RADAR);
837*5c1def83SBjoern A. Zeeb
838*5c1def83SBjoern A. Zeeb arg.min_power = 0;
839*5c1def83SBjoern A. Zeeb arg.max_power = channel->max_power;
840*5c1def83SBjoern A. Zeeb arg.max_reg_power = channel->max_reg_power;
841*5c1def83SBjoern A. Zeeb arg.max_antenna_gain = channel->max_antenna_gain;
842*5c1def83SBjoern A. Zeeb
843*5c1def83SBjoern A. Zeeb arg.pref_tx_streams = ar->num_tx_chains;
844*5c1def83SBjoern A. Zeeb arg.pref_rx_streams = ar->num_rx_chains;
845*5c1def83SBjoern A. Zeeb arg.punct_bitmap = 0xFFFFFFFF;
846*5c1def83SBjoern A. Zeeb
847*5c1def83SBjoern A. Zeeb arg.passive |= !!(chandef->chan->flags & IEEE80211_CHAN_NO_IR);
848*5c1def83SBjoern A. Zeeb
849*5c1def83SBjoern A. Zeeb reinit_completion(&ar->vdev_setup_done);
850*5c1def83SBjoern A. Zeeb reinit_completion(&ar->vdev_delete_done);
851*5c1def83SBjoern A. Zeeb
852*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_start(ar, &arg, false);
853*5c1def83SBjoern A. Zeeb if (ret) {
854*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to request monitor vdev %i start: %d\n",
855*5c1def83SBjoern A. Zeeb vdev_id, ret);
856*5c1def83SBjoern A. Zeeb return ret;
857*5c1def83SBjoern A. Zeeb }
858*5c1def83SBjoern A. Zeeb
859*5c1def83SBjoern A. Zeeb ret = ath12k_mac_vdev_setup_sync(ar);
860*5c1def83SBjoern A. Zeeb if (ret) {
861*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to synchronize setup for monitor vdev %i start: %d\n",
862*5c1def83SBjoern A. Zeeb vdev_id, ret);
863*5c1def83SBjoern A. Zeeb return ret;
864*5c1def83SBjoern A. Zeeb }
865*5c1def83SBjoern A. Zeeb
866*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_up(ar, vdev_id, 0, ar->mac_addr);
867*5c1def83SBjoern A. Zeeb if (ret) {
868*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to put up monitor vdev %i: %d\n",
869*5c1def83SBjoern A. Zeeb vdev_id, ret);
870*5c1def83SBjoern A. Zeeb goto vdev_stop;
871*5c1def83SBjoern A. Zeeb }
872*5c1def83SBjoern A. Zeeb
873*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac monitor vdev %i started\n",
874*5c1def83SBjoern A. Zeeb vdev_id);
875*5c1def83SBjoern A. Zeeb return 0;
876*5c1def83SBjoern A. Zeeb
877*5c1def83SBjoern A. Zeeb vdev_stop:
878*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_stop(ar, vdev_id);
879*5c1def83SBjoern A. Zeeb if (ret)
880*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to stop monitor vdev %i after start failure: %d\n",
881*5c1def83SBjoern A. Zeeb vdev_id, ret);
882*5c1def83SBjoern A. Zeeb return ret;
883*5c1def83SBjoern A. Zeeb }
884*5c1def83SBjoern A. Zeeb
ath12k_mac_monitor_vdev_stop(struct ath12k * ar)885*5c1def83SBjoern A. Zeeb static int ath12k_mac_monitor_vdev_stop(struct ath12k *ar)
886*5c1def83SBjoern A. Zeeb {
887*5c1def83SBjoern A. Zeeb int ret;
888*5c1def83SBjoern A. Zeeb
889*5c1def83SBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
890*5c1def83SBjoern A. Zeeb
891*5c1def83SBjoern A. Zeeb reinit_completion(&ar->vdev_setup_done);
892*5c1def83SBjoern A. Zeeb
893*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_stop(ar, ar->monitor_vdev_id);
894*5c1def83SBjoern A. Zeeb if (ret)
895*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to request monitor vdev %i stop: %d\n",
896*5c1def83SBjoern A. Zeeb ar->monitor_vdev_id, ret);
897*5c1def83SBjoern A. Zeeb
898*5c1def83SBjoern A. Zeeb ret = ath12k_mac_vdev_setup_sync(ar);
899*5c1def83SBjoern A. Zeeb if (ret)
900*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to synchronize monitor vdev %i stop: %d\n",
901*5c1def83SBjoern A. Zeeb ar->monitor_vdev_id, ret);
902*5c1def83SBjoern A. Zeeb
903*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_down(ar, ar->monitor_vdev_id);
904*5c1def83SBjoern A. Zeeb if (ret)
905*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to put down monitor vdev %i: %d\n",
906*5c1def83SBjoern A. Zeeb ar->monitor_vdev_id, ret);
907*5c1def83SBjoern A. Zeeb
908*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac monitor vdev %i stopped\n",
909*5c1def83SBjoern A. Zeeb ar->monitor_vdev_id);
910*5c1def83SBjoern A. Zeeb return ret;
911*5c1def83SBjoern A. Zeeb }
912*5c1def83SBjoern A. Zeeb
ath12k_mac_monitor_vdev_create(struct ath12k * ar)913*5c1def83SBjoern A. Zeeb static int ath12k_mac_monitor_vdev_create(struct ath12k *ar)
914*5c1def83SBjoern A. Zeeb {
915*5c1def83SBjoern A. Zeeb struct ath12k_pdev *pdev = ar->pdev;
916*5c1def83SBjoern A. Zeeb struct ath12k_wmi_vdev_create_arg arg = {};
917*5c1def83SBjoern A. Zeeb int bit, ret;
918*5c1def83SBjoern A. Zeeb u8 tmp_addr[6];
919*5c1def83SBjoern A. Zeeb u16 nss;
920*5c1def83SBjoern A. Zeeb
921*5c1def83SBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
922*5c1def83SBjoern A. Zeeb
923*5c1def83SBjoern A. Zeeb if (ar->monitor_vdev_created)
924*5c1def83SBjoern A. Zeeb return 0;
925*5c1def83SBjoern A. Zeeb
926*5c1def83SBjoern A. Zeeb if (ar->ab->free_vdev_map == 0) {
927*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to find free vdev id for monitor vdev\n");
928*5c1def83SBjoern A. Zeeb return -ENOMEM;
929*5c1def83SBjoern A. Zeeb }
930*5c1def83SBjoern A. Zeeb
931*5c1def83SBjoern A. Zeeb bit = __ffs64(ar->ab->free_vdev_map);
932*5c1def83SBjoern A. Zeeb
933*5c1def83SBjoern A. Zeeb ar->monitor_vdev_id = bit;
934*5c1def83SBjoern A. Zeeb
935*5c1def83SBjoern A. Zeeb arg.if_id = ar->monitor_vdev_id;
936*5c1def83SBjoern A. Zeeb arg.type = WMI_VDEV_TYPE_MONITOR;
937*5c1def83SBjoern A. Zeeb arg.subtype = WMI_VDEV_SUBTYPE_NONE;
938*5c1def83SBjoern A. Zeeb arg.pdev_id = pdev->pdev_id;
939*5c1def83SBjoern A. Zeeb arg.if_stats_id = ATH12K_INVAL_VDEV_STATS_ID;
940*5c1def83SBjoern A. Zeeb
941*5c1def83SBjoern A. Zeeb if (pdev->cap.supported_bands & WMI_HOST_WLAN_2G_CAP) {
942*5c1def83SBjoern A. Zeeb arg.chains[NL80211_BAND_2GHZ].tx = ar->num_tx_chains;
943*5c1def83SBjoern A. Zeeb arg.chains[NL80211_BAND_2GHZ].rx = ar->num_rx_chains;
944*5c1def83SBjoern A. Zeeb }
945*5c1def83SBjoern A. Zeeb
946*5c1def83SBjoern A. Zeeb if (pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP) {
947*5c1def83SBjoern A. Zeeb arg.chains[NL80211_BAND_5GHZ].tx = ar->num_tx_chains;
948*5c1def83SBjoern A. Zeeb arg.chains[NL80211_BAND_5GHZ].rx = ar->num_rx_chains;
949*5c1def83SBjoern A. Zeeb }
950*5c1def83SBjoern A. Zeeb
951*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_create(ar, tmp_addr, &arg);
952*5c1def83SBjoern A. Zeeb if (ret) {
953*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to request monitor vdev %i creation: %d\n",
954*5c1def83SBjoern A. Zeeb ar->monitor_vdev_id, ret);
955*5c1def83SBjoern A. Zeeb ar->monitor_vdev_id = -1;
956*5c1def83SBjoern A. Zeeb return ret;
957*5c1def83SBjoern A. Zeeb }
958*5c1def83SBjoern A. Zeeb
959*5c1def83SBjoern A. Zeeb nss = hweight32(ar->cfg_tx_chainmask) ? : 1;
960*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_set_param_cmd(ar, ar->monitor_vdev_id,
961*5c1def83SBjoern A. Zeeb WMI_VDEV_PARAM_NSS, nss);
962*5c1def83SBjoern A. Zeeb if (ret) {
963*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to set vdev %d chainmask 0x%x, nss %d :%d\n",
964*5c1def83SBjoern A. Zeeb ar->monitor_vdev_id, ar->cfg_tx_chainmask, nss, ret);
965*5c1def83SBjoern A. Zeeb return ret;
966*5c1def83SBjoern A. Zeeb }
967*5c1def83SBjoern A. Zeeb
968*5c1def83SBjoern A. Zeeb ret = ath12k_mac_txpower_recalc(ar);
969*5c1def83SBjoern A. Zeeb if (ret)
970*5c1def83SBjoern A. Zeeb return ret;
971*5c1def83SBjoern A. Zeeb
972*5c1def83SBjoern A. Zeeb ar->allocated_vdev_map |= 1LL << ar->monitor_vdev_id;
973*5c1def83SBjoern A. Zeeb ar->ab->free_vdev_map &= ~(1LL << ar->monitor_vdev_id);
974*5c1def83SBjoern A. Zeeb ar->num_created_vdevs++;
975*5c1def83SBjoern A. Zeeb ar->monitor_vdev_created = true;
976*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac monitor vdev %d created\n",
977*5c1def83SBjoern A. Zeeb ar->monitor_vdev_id);
978*5c1def83SBjoern A. Zeeb
979*5c1def83SBjoern A. Zeeb return 0;
980*5c1def83SBjoern A. Zeeb }
981*5c1def83SBjoern A. Zeeb
ath12k_mac_monitor_vdev_delete(struct ath12k * ar)982*5c1def83SBjoern A. Zeeb static int ath12k_mac_monitor_vdev_delete(struct ath12k *ar)
983*5c1def83SBjoern A. Zeeb {
984*5c1def83SBjoern A. Zeeb int ret;
985*5c1def83SBjoern A. Zeeb unsigned long time_left;
986*5c1def83SBjoern A. Zeeb
987*5c1def83SBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
988*5c1def83SBjoern A. Zeeb
989*5c1def83SBjoern A. Zeeb if (!ar->monitor_vdev_created)
990*5c1def83SBjoern A. Zeeb return 0;
991*5c1def83SBjoern A. Zeeb
992*5c1def83SBjoern A. Zeeb reinit_completion(&ar->vdev_delete_done);
993*5c1def83SBjoern A. Zeeb
994*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_delete(ar, ar->monitor_vdev_id);
995*5c1def83SBjoern A. Zeeb if (ret) {
996*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to request wmi monitor vdev %i removal: %d\n",
997*5c1def83SBjoern A. Zeeb ar->monitor_vdev_id, ret);
998*5c1def83SBjoern A. Zeeb return ret;
999*5c1def83SBjoern A. Zeeb }
1000*5c1def83SBjoern A. Zeeb
1001*5c1def83SBjoern A. Zeeb time_left = wait_for_completion_timeout(&ar->vdev_delete_done,
1002*5c1def83SBjoern A. Zeeb ATH12K_VDEV_DELETE_TIMEOUT_HZ);
1003*5c1def83SBjoern A. Zeeb if (time_left == 0) {
1004*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "Timeout in receiving vdev delete response\n");
1005*5c1def83SBjoern A. Zeeb } else {
1006*5c1def83SBjoern A. Zeeb ar->allocated_vdev_map &= ~(1LL << ar->monitor_vdev_id);
1007*5c1def83SBjoern A. Zeeb ar->ab->free_vdev_map |= 1LL << (ar->monitor_vdev_id);
1008*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac monitor vdev %d deleted\n",
1009*5c1def83SBjoern A. Zeeb ar->monitor_vdev_id);
1010*5c1def83SBjoern A. Zeeb ar->num_created_vdevs--;
1011*5c1def83SBjoern A. Zeeb ar->monitor_vdev_id = -1;
1012*5c1def83SBjoern A. Zeeb ar->monitor_vdev_created = false;
1013*5c1def83SBjoern A. Zeeb }
1014*5c1def83SBjoern A. Zeeb
1015*5c1def83SBjoern A. Zeeb return ret;
1016*5c1def83SBjoern A. Zeeb }
1017*5c1def83SBjoern A. Zeeb
1018*5c1def83SBjoern A. Zeeb static void
ath12k_mac_get_any_chandef_iter(struct ieee80211_hw * hw,struct ieee80211_chanctx_conf * conf,void * data)1019*5c1def83SBjoern A. Zeeb ath12k_mac_get_any_chandef_iter(struct ieee80211_hw *hw,
1020*5c1def83SBjoern A. Zeeb struct ieee80211_chanctx_conf *conf,
1021*5c1def83SBjoern A. Zeeb void *data)
1022*5c1def83SBjoern A. Zeeb {
1023*5c1def83SBjoern A. Zeeb struct cfg80211_chan_def **def = data;
1024*5c1def83SBjoern A. Zeeb
1025*5c1def83SBjoern A. Zeeb *def = &conf->def;
1026*5c1def83SBjoern A. Zeeb }
1027*5c1def83SBjoern A. Zeeb
ath12k_mac_monitor_start(struct ath12k * ar)1028*5c1def83SBjoern A. Zeeb static int ath12k_mac_monitor_start(struct ath12k *ar)
1029*5c1def83SBjoern A. Zeeb {
1030*5c1def83SBjoern A. Zeeb struct cfg80211_chan_def *chandef = NULL;
1031*5c1def83SBjoern A. Zeeb int ret;
1032*5c1def83SBjoern A. Zeeb
1033*5c1def83SBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
1034*5c1def83SBjoern A. Zeeb
1035*5c1def83SBjoern A. Zeeb if (ar->monitor_started)
1036*5c1def83SBjoern A. Zeeb return 0;
1037*5c1def83SBjoern A. Zeeb
1038*5c1def83SBjoern A. Zeeb ieee80211_iter_chan_contexts_atomic(ar->hw,
1039*5c1def83SBjoern A. Zeeb ath12k_mac_get_any_chandef_iter,
1040*5c1def83SBjoern A. Zeeb &chandef);
1041*5c1def83SBjoern A. Zeeb if (!chandef)
1042*5c1def83SBjoern A. Zeeb return 0;
1043*5c1def83SBjoern A. Zeeb
1044*5c1def83SBjoern A. Zeeb ret = ath12k_mac_monitor_vdev_start(ar, ar->monitor_vdev_id, chandef);
1045*5c1def83SBjoern A. Zeeb if (ret) {
1046*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to start monitor vdev: %d\n", ret);
1047*5c1def83SBjoern A. Zeeb ath12k_mac_monitor_vdev_delete(ar);
1048*5c1def83SBjoern A. Zeeb return ret;
1049*5c1def83SBjoern A. Zeeb }
1050*5c1def83SBjoern A. Zeeb
1051*5c1def83SBjoern A. Zeeb ar->monitor_started = true;
1052*5c1def83SBjoern A. Zeeb ar->num_started_vdevs++;
1053*5c1def83SBjoern A. Zeeb ret = ath12k_dp_tx_htt_monitor_mode_ring_config(ar, false);
1054*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac monitor started ret %d\n", ret);
1055*5c1def83SBjoern A. Zeeb
1056*5c1def83SBjoern A. Zeeb return ret;
1057*5c1def83SBjoern A. Zeeb }
1058*5c1def83SBjoern A. Zeeb
ath12k_mac_monitor_stop(struct ath12k * ar)1059*5c1def83SBjoern A. Zeeb static int ath12k_mac_monitor_stop(struct ath12k *ar)
1060*5c1def83SBjoern A. Zeeb {
1061*5c1def83SBjoern A. Zeeb int ret;
1062*5c1def83SBjoern A. Zeeb
1063*5c1def83SBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
1064*5c1def83SBjoern A. Zeeb
1065*5c1def83SBjoern A. Zeeb if (!ar->monitor_started)
1066*5c1def83SBjoern A. Zeeb return 0;
1067*5c1def83SBjoern A. Zeeb
1068*5c1def83SBjoern A. Zeeb ret = ath12k_mac_monitor_vdev_stop(ar);
1069*5c1def83SBjoern A. Zeeb if (ret) {
1070*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to stop monitor vdev: %d\n", ret);
1071*5c1def83SBjoern A. Zeeb return ret;
1072*5c1def83SBjoern A. Zeeb }
1073*5c1def83SBjoern A. Zeeb
1074*5c1def83SBjoern A. Zeeb ar->monitor_started = false;
1075*5c1def83SBjoern A. Zeeb ar->num_started_vdevs--;
1076*5c1def83SBjoern A. Zeeb ret = ath12k_dp_tx_htt_monitor_mode_ring_config(ar, true);
1077*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac monitor stopped ret %d\n", ret);
1078*5c1def83SBjoern A. Zeeb return ret;
1079*5c1def83SBjoern A. Zeeb }
1080*5c1def83SBjoern A. Zeeb
ath12k_mac_op_config(struct ieee80211_hw * hw,u32 changed)1081*5c1def83SBjoern A. Zeeb static int ath12k_mac_op_config(struct ieee80211_hw *hw, u32 changed)
1082*5c1def83SBjoern A. Zeeb {
1083*5c1def83SBjoern A. Zeeb struct ath12k *ar = hw->priv;
1084*5c1def83SBjoern A. Zeeb struct ieee80211_conf *conf = &hw->conf;
1085*5c1def83SBjoern A. Zeeb int ret = 0;
1086*5c1def83SBjoern A. Zeeb
1087*5c1def83SBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
1088*5c1def83SBjoern A. Zeeb
1089*5c1def83SBjoern A. Zeeb if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
1090*5c1def83SBjoern A. Zeeb ar->monitor_conf_enabled = conf->flags & IEEE80211_CONF_MONITOR;
1091*5c1def83SBjoern A. Zeeb if (ar->monitor_conf_enabled) {
1092*5c1def83SBjoern A. Zeeb if (ar->monitor_vdev_created)
1093*5c1def83SBjoern A. Zeeb goto exit;
1094*5c1def83SBjoern A. Zeeb ret = ath12k_mac_monitor_vdev_create(ar);
1095*5c1def83SBjoern A. Zeeb if (ret)
1096*5c1def83SBjoern A. Zeeb goto exit;
1097*5c1def83SBjoern A. Zeeb ret = ath12k_mac_monitor_start(ar);
1098*5c1def83SBjoern A. Zeeb if (ret)
1099*5c1def83SBjoern A. Zeeb goto err_mon_del;
1100*5c1def83SBjoern A. Zeeb } else {
1101*5c1def83SBjoern A. Zeeb if (!ar->monitor_vdev_created)
1102*5c1def83SBjoern A. Zeeb goto exit;
1103*5c1def83SBjoern A. Zeeb ret = ath12k_mac_monitor_stop(ar);
1104*5c1def83SBjoern A. Zeeb if (ret)
1105*5c1def83SBjoern A. Zeeb goto exit;
1106*5c1def83SBjoern A. Zeeb ath12k_mac_monitor_vdev_delete(ar);
1107*5c1def83SBjoern A. Zeeb }
1108*5c1def83SBjoern A. Zeeb }
1109*5c1def83SBjoern A. Zeeb
1110*5c1def83SBjoern A. Zeeb exit:
1111*5c1def83SBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
1112*5c1def83SBjoern A. Zeeb return ret;
1113*5c1def83SBjoern A. Zeeb
1114*5c1def83SBjoern A. Zeeb err_mon_del:
1115*5c1def83SBjoern A. Zeeb ath12k_mac_monitor_vdev_delete(ar);
1116*5c1def83SBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
1117*5c1def83SBjoern A. Zeeb return ret;
1118*5c1def83SBjoern A. Zeeb }
1119*5c1def83SBjoern A. Zeeb
ath12k_mac_setup_bcn_tmpl(struct ath12k_vif * arvif)1120*5c1def83SBjoern A. Zeeb static int ath12k_mac_setup_bcn_tmpl(struct ath12k_vif *arvif)
1121*5c1def83SBjoern A. Zeeb {
1122*5c1def83SBjoern A. Zeeb struct ath12k *ar = arvif->ar;
1123*5c1def83SBjoern A. Zeeb struct ath12k_base *ab = ar->ab;
1124*5c1def83SBjoern A. Zeeb struct ieee80211_hw *hw = ar->hw;
1125*5c1def83SBjoern A. Zeeb struct ieee80211_vif *vif = arvif->vif;
1126*5c1def83SBjoern A. Zeeb struct ieee80211_mutable_offsets offs = {};
1127*5c1def83SBjoern A. Zeeb struct sk_buff *bcn;
1128*5c1def83SBjoern A. Zeeb struct ieee80211_mgmt *mgmt;
1129*5c1def83SBjoern A. Zeeb u8 *ies;
1130*5c1def83SBjoern A. Zeeb int ret;
1131*5c1def83SBjoern A. Zeeb
1132*5c1def83SBjoern A. Zeeb if (arvif->vdev_type != WMI_VDEV_TYPE_AP)
1133*5c1def83SBjoern A. Zeeb return 0;
1134*5c1def83SBjoern A. Zeeb
1135*5c1def83SBjoern A. Zeeb bcn = ieee80211_beacon_get_template(hw, vif, &offs, 0);
1136*5c1def83SBjoern A. Zeeb if (!bcn) {
1137*5c1def83SBjoern A. Zeeb ath12k_warn(ab, "failed to get beacon template from mac80211\n");
1138*5c1def83SBjoern A. Zeeb return -EPERM;
1139*5c1def83SBjoern A. Zeeb }
1140*5c1def83SBjoern A. Zeeb
1141*5c1def83SBjoern A. Zeeb ies = bcn->data + ieee80211_get_hdrlen_from_skb(bcn);
1142*5c1def83SBjoern A. Zeeb ies += sizeof(mgmt->u.beacon);
1143*5c1def83SBjoern A. Zeeb
1144*5c1def83SBjoern A. Zeeb if (cfg80211_find_ie(WLAN_EID_RSN, ies, (skb_tail_pointer(bcn) - ies)))
1145*5c1def83SBjoern A. Zeeb arvif->rsnie_present = true;
1146*5c1def83SBjoern A. Zeeb
1147*5c1def83SBjoern A. Zeeb if (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1148*5c1def83SBjoern A. Zeeb WLAN_OUI_TYPE_MICROSOFT_WPA,
1149*5c1def83SBjoern A. Zeeb ies, (skb_tail_pointer(bcn) - ies)))
1150*5c1def83SBjoern A. Zeeb arvif->wpaie_present = true;
1151*5c1def83SBjoern A. Zeeb
1152*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_bcn_tmpl(ar, arvif->vdev_id, &offs, bcn);
1153*5c1def83SBjoern A. Zeeb
1154*5c1def83SBjoern A. Zeeb kfree_skb(bcn);
1155*5c1def83SBjoern A. Zeeb
1156*5c1def83SBjoern A. Zeeb if (ret)
1157*5c1def83SBjoern A. Zeeb ath12k_warn(ab, "failed to submit beacon template command: %d\n",
1158*5c1def83SBjoern A. Zeeb ret);
1159*5c1def83SBjoern A. Zeeb
1160*5c1def83SBjoern A. Zeeb return ret;
1161*5c1def83SBjoern A. Zeeb }
1162*5c1def83SBjoern A. Zeeb
ath12k_control_beaconing(struct ath12k_vif * arvif,struct ieee80211_bss_conf * info)1163*5c1def83SBjoern A. Zeeb static void ath12k_control_beaconing(struct ath12k_vif *arvif,
1164*5c1def83SBjoern A. Zeeb struct ieee80211_bss_conf *info)
1165*5c1def83SBjoern A. Zeeb {
1166*5c1def83SBjoern A. Zeeb struct ath12k *ar = arvif->ar;
1167*5c1def83SBjoern A. Zeeb int ret;
1168*5c1def83SBjoern A. Zeeb
1169*5c1def83SBjoern A. Zeeb lockdep_assert_held(&arvif->ar->conf_mutex);
1170*5c1def83SBjoern A. Zeeb
1171*5c1def83SBjoern A. Zeeb if (!info->enable_beacon) {
1172*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_down(ar, arvif->vdev_id);
1173*5c1def83SBjoern A. Zeeb if (ret)
1174*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to down vdev_id %i: %d\n",
1175*5c1def83SBjoern A. Zeeb arvif->vdev_id, ret);
1176*5c1def83SBjoern A. Zeeb
1177*5c1def83SBjoern A. Zeeb arvif->is_up = false;
1178*5c1def83SBjoern A. Zeeb return;
1179*5c1def83SBjoern A. Zeeb }
1180*5c1def83SBjoern A. Zeeb
1181*5c1def83SBjoern A. Zeeb /* Install the beacon template to the FW */
1182*5c1def83SBjoern A. Zeeb ret = ath12k_mac_setup_bcn_tmpl(arvif);
1183*5c1def83SBjoern A. Zeeb if (ret) {
1184*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to update bcn tmpl during vdev up: %d\n",
1185*5c1def83SBjoern A. Zeeb ret);
1186*5c1def83SBjoern A. Zeeb return;
1187*5c1def83SBjoern A. Zeeb }
1188*5c1def83SBjoern A. Zeeb
1189*5c1def83SBjoern A. Zeeb arvif->aid = 0;
1190*5c1def83SBjoern A. Zeeb
1191*5c1def83SBjoern A. Zeeb ether_addr_copy(arvif->bssid, info->bssid);
1192*5c1def83SBjoern A. Zeeb
1193*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid,
1194*5c1def83SBjoern A. Zeeb arvif->bssid);
1195*5c1def83SBjoern A. Zeeb if (ret) {
1196*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to bring up vdev %d: %i\n",
1197*5c1def83SBjoern A. Zeeb arvif->vdev_id, ret);
1198*5c1def83SBjoern A. Zeeb return;
1199*5c1def83SBjoern A. Zeeb }
1200*5c1def83SBjoern A. Zeeb
1201*5c1def83SBjoern A. Zeeb arvif->is_up = true;
1202*5c1def83SBjoern A. Zeeb
1203*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev %d up\n", arvif->vdev_id);
1204*5c1def83SBjoern A. Zeeb }
1205*5c1def83SBjoern A. Zeeb
ath12k_peer_assoc_h_basic(struct ath12k * ar,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct ath12k_wmi_peer_assoc_arg * arg)1206*5c1def83SBjoern A. Zeeb static void ath12k_peer_assoc_h_basic(struct ath12k *ar,
1207*5c1def83SBjoern A. Zeeb struct ieee80211_vif *vif,
1208*5c1def83SBjoern A. Zeeb struct ieee80211_sta *sta,
1209*5c1def83SBjoern A. Zeeb struct ath12k_wmi_peer_assoc_arg *arg)
1210*5c1def83SBjoern A. Zeeb {
1211*5c1def83SBjoern A. Zeeb struct ath12k_vif *arvif = (void *)vif->drv_priv;
1212*5c1def83SBjoern A. Zeeb u32 aid;
1213*5c1def83SBjoern A. Zeeb
1214*5c1def83SBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
1215*5c1def83SBjoern A. Zeeb
1216*5c1def83SBjoern A. Zeeb if (vif->type == NL80211_IFTYPE_STATION)
1217*5c1def83SBjoern A. Zeeb aid = vif->cfg.aid;
1218*5c1def83SBjoern A. Zeeb else
1219*5c1def83SBjoern A. Zeeb aid = sta->aid;
1220*5c1def83SBjoern A. Zeeb
1221*5c1def83SBjoern A. Zeeb ether_addr_copy(arg->peer_mac, sta->addr);
1222*5c1def83SBjoern A. Zeeb arg->vdev_id = arvif->vdev_id;
1223*5c1def83SBjoern A. Zeeb arg->peer_associd = aid;
1224*5c1def83SBjoern A. Zeeb arg->auth_flag = true;
1225*5c1def83SBjoern A. Zeeb /* TODO: STA WAR in ath10k for listen interval required? */
1226*5c1def83SBjoern A. Zeeb arg->peer_listen_intval = ar->hw->conf.listen_interval;
1227*5c1def83SBjoern A. Zeeb arg->peer_nss = 1;
1228*5c1def83SBjoern A. Zeeb arg->peer_caps = vif->bss_conf.assoc_capability;
1229*5c1def83SBjoern A. Zeeb }
1230*5c1def83SBjoern A. Zeeb
ath12k_peer_assoc_h_crypto(struct ath12k * ar,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct ath12k_wmi_peer_assoc_arg * arg)1231*5c1def83SBjoern A. Zeeb static void ath12k_peer_assoc_h_crypto(struct ath12k *ar,
1232*5c1def83SBjoern A. Zeeb struct ieee80211_vif *vif,
1233*5c1def83SBjoern A. Zeeb struct ieee80211_sta *sta,
1234*5c1def83SBjoern A. Zeeb struct ath12k_wmi_peer_assoc_arg *arg)
1235*5c1def83SBjoern A. Zeeb {
1236*5c1def83SBjoern A. Zeeb struct ieee80211_bss_conf *info = &vif->bss_conf;
1237*5c1def83SBjoern A. Zeeb struct cfg80211_chan_def def;
1238*5c1def83SBjoern A. Zeeb struct cfg80211_bss *bss;
1239*5c1def83SBjoern A. Zeeb struct ath12k_vif *arvif = (struct ath12k_vif *)vif->drv_priv;
1240*5c1def83SBjoern A. Zeeb const u8 *rsnie = NULL;
1241*5c1def83SBjoern A. Zeeb const u8 *wpaie = NULL;
1242*5c1def83SBjoern A. Zeeb
1243*5c1def83SBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
1244*5c1def83SBjoern A. Zeeb
1245*5c1def83SBjoern A. Zeeb if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))
1246*5c1def83SBjoern A. Zeeb return;
1247*5c1def83SBjoern A. Zeeb
1248*5c1def83SBjoern A. Zeeb bss = cfg80211_get_bss(ar->hw->wiphy, def.chan, info->bssid, NULL, 0,
1249*5c1def83SBjoern A. Zeeb IEEE80211_BSS_TYPE_ANY, IEEE80211_PRIVACY_ANY);
1250*5c1def83SBjoern A. Zeeb
1251*5c1def83SBjoern A. Zeeb if (arvif->rsnie_present || arvif->wpaie_present) {
1252*5c1def83SBjoern A. Zeeb arg->need_ptk_4_way = true;
1253*5c1def83SBjoern A. Zeeb if (arvif->wpaie_present)
1254*5c1def83SBjoern A. Zeeb arg->need_gtk_2_way = true;
1255*5c1def83SBjoern A. Zeeb } else if (bss) {
1256*5c1def83SBjoern A. Zeeb const struct cfg80211_bss_ies *ies;
1257*5c1def83SBjoern A. Zeeb
1258*5c1def83SBjoern A. Zeeb rcu_read_lock();
1259*5c1def83SBjoern A. Zeeb rsnie = ieee80211_bss_get_ie(bss, WLAN_EID_RSN);
1260*5c1def83SBjoern A. Zeeb
1261*5c1def83SBjoern A. Zeeb ies = rcu_dereference(bss->ies);
1262*5c1def83SBjoern A. Zeeb
1263*5c1def83SBjoern A. Zeeb wpaie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1264*5c1def83SBjoern A. Zeeb WLAN_OUI_TYPE_MICROSOFT_WPA,
1265*5c1def83SBjoern A. Zeeb ies->data,
1266*5c1def83SBjoern A. Zeeb ies->len);
1267*5c1def83SBjoern A. Zeeb rcu_read_unlock();
1268*5c1def83SBjoern A. Zeeb cfg80211_put_bss(ar->hw->wiphy, bss);
1269*5c1def83SBjoern A. Zeeb }
1270*5c1def83SBjoern A. Zeeb
1271*5c1def83SBjoern A. Zeeb /* FIXME: base on RSN IE/WPA IE is a correct idea? */
1272*5c1def83SBjoern A. Zeeb if (rsnie || wpaie) {
1273*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_WMI,
1274*5c1def83SBjoern A. Zeeb "%s: rsn ie found\n", __func__);
1275*5c1def83SBjoern A. Zeeb arg->need_ptk_4_way = true;
1276*5c1def83SBjoern A. Zeeb }
1277*5c1def83SBjoern A. Zeeb
1278*5c1def83SBjoern A. Zeeb if (wpaie) {
1279*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_WMI,
1280*5c1def83SBjoern A. Zeeb "%s: wpa ie found\n", __func__);
1281*5c1def83SBjoern A. Zeeb arg->need_gtk_2_way = true;
1282*5c1def83SBjoern A. Zeeb }
1283*5c1def83SBjoern A. Zeeb
1284*5c1def83SBjoern A. Zeeb if (sta->mfp) {
1285*5c1def83SBjoern A. Zeeb /* TODO: Need to check if FW supports PMF? */
1286*5c1def83SBjoern A. Zeeb arg->is_pmf_enabled = true;
1287*5c1def83SBjoern A. Zeeb }
1288*5c1def83SBjoern A. Zeeb
1289*5c1def83SBjoern A. Zeeb /* TODO: safe_mode_enabled (bypass 4-way handshake) flag req? */
1290*5c1def83SBjoern A. Zeeb }
1291*5c1def83SBjoern A. Zeeb
ath12k_peer_assoc_h_rates(struct ath12k * ar,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct ath12k_wmi_peer_assoc_arg * arg)1292*5c1def83SBjoern A. Zeeb static void ath12k_peer_assoc_h_rates(struct ath12k *ar,
1293*5c1def83SBjoern A. Zeeb struct ieee80211_vif *vif,
1294*5c1def83SBjoern A. Zeeb struct ieee80211_sta *sta,
1295*5c1def83SBjoern A. Zeeb struct ath12k_wmi_peer_assoc_arg *arg)
1296*5c1def83SBjoern A. Zeeb {
1297*5c1def83SBjoern A. Zeeb struct ath12k_vif *arvif = (void *)vif->drv_priv;
1298*5c1def83SBjoern A. Zeeb struct wmi_rate_set_arg *rateset = &arg->peer_legacy_rates;
1299*5c1def83SBjoern A. Zeeb struct cfg80211_chan_def def;
1300*5c1def83SBjoern A. Zeeb const struct ieee80211_supported_band *sband;
1301*5c1def83SBjoern A. Zeeb const struct ieee80211_rate *rates;
1302*5c1def83SBjoern A. Zeeb enum nl80211_band band;
1303*5c1def83SBjoern A. Zeeb u32 ratemask;
1304*5c1def83SBjoern A. Zeeb u8 rate;
1305*5c1def83SBjoern A. Zeeb int i;
1306*5c1def83SBjoern A. Zeeb
1307*5c1def83SBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
1308*5c1def83SBjoern A. Zeeb
1309*5c1def83SBjoern A. Zeeb if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))
1310*5c1def83SBjoern A. Zeeb return;
1311*5c1def83SBjoern A. Zeeb
1312*5c1def83SBjoern A. Zeeb band = def.chan->band;
1313*5c1def83SBjoern A. Zeeb sband = ar->hw->wiphy->bands[band];
1314*5c1def83SBjoern A. Zeeb ratemask = sta->deflink.supp_rates[band];
1315*5c1def83SBjoern A. Zeeb ratemask &= arvif->bitrate_mask.control[band].legacy;
1316*5c1def83SBjoern A. Zeeb rates = sband->bitrates;
1317*5c1def83SBjoern A. Zeeb
1318*5c1def83SBjoern A. Zeeb rateset->num_rates = 0;
1319*5c1def83SBjoern A. Zeeb
1320*5c1def83SBjoern A. Zeeb for (i = 0; i < 32; i++, ratemask >>= 1, rates++) {
1321*5c1def83SBjoern A. Zeeb if (!(ratemask & 1))
1322*5c1def83SBjoern A. Zeeb continue;
1323*5c1def83SBjoern A. Zeeb
1324*5c1def83SBjoern A. Zeeb rate = ath12k_mac_bitrate_to_rate(rates->bitrate);
1325*5c1def83SBjoern A. Zeeb rateset->rates[rateset->num_rates] = rate;
1326*5c1def83SBjoern A. Zeeb rateset->num_rates++;
1327*5c1def83SBjoern A. Zeeb }
1328*5c1def83SBjoern A. Zeeb }
1329*5c1def83SBjoern A. Zeeb
1330*5c1def83SBjoern A. Zeeb static bool
ath12k_peer_assoc_h_ht_masked(const u8 * ht_mcs_mask)1331*5c1def83SBjoern A. Zeeb ath12k_peer_assoc_h_ht_masked(const u8 *ht_mcs_mask)
1332*5c1def83SBjoern A. Zeeb {
1333*5c1def83SBjoern A. Zeeb int nss;
1334*5c1def83SBjoern A. Zeeb
1335*5c1def83SBjoern A. Zeeb for (nss = 0; nss < IEEE80211_HT_MCS_MASK_LEN; nss++)
1336*5c1def83SBjoern A. Zeeb if (ht_mcs_mask[nss])
1337*5c1def83SBjoern A. Zeeb return false;
1338*5c1def83SBjoern A. Zeeb
1339*5c1def83SBjoern A. Zeeb return true;
1340*5c1def83SBjoern A. Zeeb }
1341*5c1def83SBjoern A. Zeeb
1342*5c1def83SBjoern A. Zeeb static bool
ath12k_peer_assoc_h_vht_masked(const u16 * vht_mcs_mask)1343*5c1def83SBjoern A. Zeeb ath12k_peer_assoc_h_vht_masked(const u16 *vht_mcs_mask)
1344*5c1def83SBjoern A. Zeeb {
1345*5c1def83SBjoern A. Zeeb int nss;
1346*5c1def83SBjoern A. Zeeb
1347*5c1def83SBjoern A. Zeeb for (nss = 0; nss < NL80211_VHT_NSS_MAX; nss++)
1348*5c1def83SBjoern A. Zeeb if (vht_mcs_mask[nss])
1349*5c1def83SBjoern A. Zeeb return false;
1350*5c1def83SBjoern A. Zeeb
1351*5c1def83SBjoern A. Zeeb return true;
1352*5c1def83SBjoern A. Zeeb }
1353*5c1def83SBjoern A. Zeeb
ath12k_peer_assoc_h_ht(struct ath12k * ar,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct ath12k_wmi_peer_assoc_arg * arg)1354*5c1def83SBjoern A. Zeeb static void ath12k_peer_assoc_h_ht(struct ath12k *ar,
1355*5c1def83SBjoern A. Zeeb struct ieee80211_vif *vif,
1356*5c1def83SBjoern A. Zeeb struct ieee80211_sta *sta,
1357*5c1def83SBjoern A. Zeeb struct ath12k_wmi_peer_assoc_arg *arg)
1358*5c1def83SBjoern A. Zeeb {
1359*5c1def83SBjoern A. Zeeb const struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap;
1360*5c1def83SBjoern A. Zeeb struct ath12k_vif *arvif = (void *)vif->drv_priv;
1361*5c1def83SBjoern A. Zeeb struct cfg80211_chan_def def;
1362*5c1def83SBjoern A. Zeeb enum nl80211_band band;
1363*5c1def83SBjoern A. Zeeb const u8 *ht_mcs_mask;
1364*5c1def83SBjoern A. Zeeb int i, n;
1365*5c1def83SBjoern A. Zeeb u8 max_nss;
1366*5c1def83SBjoern A. Zeeb u32 stbc;
1367*5c1def83SBjoern A. Zeeb
1368*5c1def83SBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
1369*5c1def83SBjoern A. Zeeb
1370*5c1def83SBjoern A. Zeeb if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))
1371*5c1def83SBjoern A. Zeeb return;
1372*5c1def83SBjoern A. Zeeb
1373*5c1def83SBjoern A. Zeeb if (!ht_cap->ht_supported)
1374*5c1def83SBjoern A. Zeeb return;
1375*5c1def83SBjoern A. Zeeb
1376*5c1def83SBjoern A. Zeeb band = def.chan->band;
1377*5c1def83SBjoern A. Zeeb ht_mcs_mask = arvif->bitrate_mask.control[band].ht_mcs;
1378*5c1def83SBjoern A. Zeeb
1379*5c1def83SBjoern A. Zeeb if (ath12k_peer_assoc_h_ht_masked(ht_mcs_mask))
1380*5c1def83SBjoern A. Zeeb return;
1381*5c1def83SBjoern A. Zeeb
1382*5c1def83SBjoern A. Zeeb arg->ht_flag = true;
1383*5c1def83SBjoern A. Zeeb
1384*5c1def83SBjoern A. Zeeb arg->peer_max_mpdu = (1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
1385*5c1def83SBjoern A. Zeeb ht_cap->ampdu_factor)) - 1;
1386*5c1def83SBjoern A. Zeeb
1387*5c1def83SBjoern A. Zeeb arg->peer_mpdu_density =
1388*5c1def83SBjoern A. Zeeb ath12k_parse_mpdudensity(ht_cap->ampdu_density);
1389*5c1def83SBjoern A. Zeeb
1390*5c1def83SBjoern A. Zeeb arg->peer_ht_caps = ht_cap->cap;
1391*5c1def83SBjoern A. Zeeb arg->peer_rate_caps |= WMI_HOST_RC_HT_FLAG;
1392*5c1def83SBjoern A. Zeeb
1393*5c1def83SBjoern A. Zeeb if (ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING)
1394*5c1def83SBjoern A. Zeeb arg->ldpc_flag = true;
1395*5c1def83SBjoern A. Zeeb
1396*5c1def83SBjoern A. Zeeb if (sta->deflink.bandwidth >= IEEE80211_STA_RX_BW_40) {
1397*5c1def83SBjoern A. Zeeb arg->bw_40 = true;
1398*5c1def83SBjoern A. Zeeb arg->peer_rate_caps |= WMI_HOST_RC_CW40_FLAG;
1399*5c1def83SBjoern A. Zeeb }
1400*5c1def83SBjoern A. Zeeb
1401*5c1def83SBjoern A. Zeeb if (arvif->bitrate_mask.control[band].gi != NL80211_TXRATE_FORCE_LGI) {
1402*5c1def83SBjoern A. Zeeb if (ht_cap->cap & (IEEE80211_HT_CAP_SGI_20 |
1403*5c1def83SBjoern A. Zeeb IEEE80211_HT_CAP_SGI_40))
1404*5c1def83SBjoern A. Zeeb arg->peer_rate_caps |= WMI_HOST_RC_SGI_FLAG;
1405*5c1def83SBjoern A. Zeeb }
1406*5c1def83SBjoern A. Zeeb
1407*5c1def83SBjoern A. Zeeb if (ht_cap->cap & IEEE80211_HT_CAP_TX_STBC) {
1408*5c1def83SBjoern A. Zeeb arg->peer_rate_caps |= WMI_HOST_RC_TX_STBC_FLAG;
1409*5c1def83SBjoern A. Zeeb arg->stbc_flag = true;
1410*5c1def83SBjoern A. Zeeb }
1411*5c1def83SBjoern A. Zeeb
1412*5c1def83SBjoern A. Zeeb if (ht_cap->cap & IEEE80211_HT_CAP_RX_STBC) {
1413*5c1def83SBjoern A. Zeeb stbc = ht_cap->cap & IEEE80211_HT_CAP_RX_STBC;
1414*5c1def83SBjoern A. Zeeb stbc = stbc >> IEEE80211_HT_CAP_RX_STBC_SHIFT;
1415*5c1def83SBjoern A. Zeeb stbc = stbc << WMI_HOST_RC_RX_STBC_FLAG_S;
1416*5c1def83SBjoern A. Zeeb arg->peer_rate_caps |= stbc;
1417*5c1def83SBjoern A. Zeeb arg->stbc_flag = true;
1418*5c1def83SBjoern A. Zeeb }
1419*5c1def83SBjoern A. Zeeb
1420*5c1def83SBjoern A. Zeeb if (ht_cap->mcs.rx_mask[1] && ht_cap->mcs.rx_mask[2])
1421*5c1def83SBjoern A. Zeeb arg->peer_rate_caps |= WMI_HOST_RC_TS_FLAG;
1422*5c1def83SBjoern A. Zeeb else if (ht_cap->mcs.rx_mask[1])
1423*5c1def83SBjoern A. Zeeb arg->peer_rate_caps |= WMI_HOST_RC_DS_FLAG;
1424*5c1def83SBjoern A. Zeeb
1425*5c1def83SBjoern A. Zeeb for (i = 0, n = 0, max_nss = 0; i < IEEE80211_HT_MCS_MASK_LEN * 8; i++)
1426*5c1def83SBjoern A. Zeeb if ((ht_cap->mcs.rx_mask[i / 8] & BIT(i % 8)) &&
1427*5c1def83SBjoern A. Zeeb (ht_mcs_mask[i / 8] & BIT(i % 8))) {
1428*5c1def83SBjoern A. Zeeb max_nss = (i / 8) + 1;
1429*5c1def83SBjoern A. Zeeb arg->peer_ht_rates.rates[n++] = i;
1430*5c1def83SBjoern A. Zeeb }
1431*5c1def83SBjoern A. Zeeb
1432*5c1def83SBjoern A. Zeeb /* This is a workaround for HT-enabled STAs which break the spec
1433*5c1def83SBjoern A. Zeeb * and have no HT capabilities RX mask (no HT RX MCS map).
1434*5c1def83SBjoern A. Zeeb *
1435*5c1def83SBjoern A. Zeeb * As per spec, in section 20.3.5 Modulation and coding scheme (MCS),
1436*5c1def83SBjoern A. Zeeb * MCS 0 through 7 are mandatory in 20MHz with 800 ns GI at all STAs.
1437*5c1def83SBjoern A. Zeeb *
1438*5c1def83SBjoern A. Zeeb * Firmware asserts if such situation occurs.
1439*5c1def83SBjoern A. Zeeb */
1440*5c1def83SBjoern A. Zeeb if (n == 0) {
1441*5c1def83SBjoern A. Zeeb arg->peer_ht_rates.num_rates = 8;
1442*5c1def83SBjoern A. Zeeb for (i = 0; i < arg->peer_ht_rates.num_rates; i++)
1443*5c1def83SBjoern A. Zeeb arg->peer_ht_rates.rates[i] = i;
1444*5c1def83SBjoern A. Zeeb } else {
1445*5c1def83SBjoern A. Zeeb arg->peer_ht_rates.num_rates = n;
1446*5c1def83SBjoern A. Zeeb arg->peer_nss = min(sta->deflink.rx_nss, max_nss);
1447*5c1def83SBjoern A. Zeeb }
1448*5c1def83SBjoern A. Zeeb
1449*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac ht peer %pM mcs cnt %d nss %d\n",
1450*5c1def83SBjoern A. Zeeb arg->peer_mac,
1451*5c1def83SBjoern A. Zeeb arg->peer_ht_rates.num_rates,
1452*5c1def83SBjoern A. Zeeb arg->peer_nss);
1453*5c1def83SBjoern A. Zeeb }
1454*5c1def83SBjoern A. Zeeb
ath12k_mac_get_max_vht_mcs_map(u16 mcs_map,int nss)1455*5c1def83SBjoern A. Zeeb static int ath12k_mac_get_max_vht_mcs_map(u16 mcs_map, int nss)
1456*5c1def83SBjoern A. Zeeb {
1457*5c1def83SBjoern A. Zeeb switch ((mcs_map >> (2 * nss)) & 0x3) {
1458*5c1def83SBjoern A. Zeeb case IEEE80211_VHT_MCS_SUPPORT_0_7: return BIT(8) - 1;
1459*5c1def83SBjoern A. Zeeb case IEEE80211_VHT_MCS_SUPPORT_0_8: return BIT(9) - 1;
1460*5c1def83SBjoern A. Zeeb case IEEE80211_VHT_MCS_SUPPORT_0_9: return BIT(10) - 1;
1461*5c1def83SBjoern A. Zeeb }
1462*5c1def83SBjoern A. Zeeb return 0;
1463*5c1def83SBjoern A. Zeeb }
1464*5c1def83SBjoern A. Zeeb
1465*5c1def83SBjoern A. Zeeb static u16
ath12k_peer_assoc_h_vht_limit(u16 tx_mcs_set,const u16 vht_mcs_limit[NL80211_VHT_NSS_MAX])1466*5c1def83SBjoern A. Zeeb ath12k_peer_assoc_h_vht_limit(u16 tx_mcs_set,
1467*5c1def83SBjoern A. Zeeb const u16 vht_mcs_limit[NL80211_VHT_NSS_MAX])
1468*5c1def83SBjoern A. Zeeb {
1469*5c1def83SBjoern A. Zeeb int idx_limit;
1470*5c1def83SBjoern A. Zeeb int nss;
1471*5c1def83SBjoern A. Zeeb u16 mcs_map;
1472*5c1def83SBjoern A. Zeeb u16 mcs;
1473*5c1def83SBjoern A. Zeeb
1474*5c1def83SBjoern A. Zeeb for (nss = 0; nss < NL80211_VHT_NSS_MAX; nss++) {
1475*5c1def83SBjoern A. Zeeb mcs_map = ath12k_mac_get_max_vht_mcs_map(tx_mcs_set, nss) &
1476*5c1def83SBjoern A. Zeeb vht_mcs_limit[nss];
1477*5c1def83SBjoern A. Zeeb
1478*5c1def83SBjoern A. Zeeb if (mcs_map)
1479*5c1def83SBjoern A. Zeeb idx_limit = fls(mcs_map) - 1;
1480*5c1def83SBjoern A. Zeeb else
1481*5c1def83SBjoern A. Zeeb idx_limit = -1;
1482*5c1def83SBjoern A. Zeeb
1483*5c1def83SBjoern A. Zeeb switch (idx_limit) {
1484*5c1def83SBjoern A. Zeeb case 0:
1485*5c1def83SBjoern A. Zeeb case 1:
1486*5c1def83SBjoern A. Zeeb case 2:
1487*5c1def83SBjoern A. Zeeb case 3:
1488*5c1def83SBjoern A. Zeeb case 4:
1489*5c1def83SBjoern A. Zeeb case 5:
1490*5c1def83SBjoern A. Zeeb case 6:
1491*5c1def83SBjoern A. Zeeb case 7:
1492*5c1def83SBjoern A. Zeeb mcs = IEEE80211_VHT_MCS_SUPPORT_0_7;
1493*5c1def83SBjoern A. Zeeb break;
1494*5c1def83SBjoern A. Zeeb case 8:
1495*5c1def83SBjoern A. Zeeb mcs = IEEE80211_VHT_MCS_SUPPORT_0_8;
1496*5c1def83SBjoern A. Zeeb break;
1497*5c1def83SBjoern A. Zeeb case 9:
1498*5c1def83SBjoern A. Zeeb mcs = IEEE80211_VHT_MCS_SUPPORT_0_9;
1499*5c1def83SBjoern A. Zeeb break;
1500*5c1def83SBjoern A. Zeeb default:
1501*5c1def83SBjoern A. Zeeb WARN_ON(1);
1502*5c1def83SBjoern A. Zeeb fallthrough;
1503*5c1def83SBjoern A. Zeeb case -1:
1504*5c1def83SBjoern A. Zeeb mcs = IEEE80211_VHT_MCS_NOT_SUPPORTED;
1505*5c1def83SBjoern A. Zeeb break;
1506*5c1def83SBjoern A. Zeeb }
1507*5c1def83SBjoern A. Zeeb
1508*5c1def83SBjoern A. Zeeb tx_mcs_set &= ~(0x3 << (nss * 2));
1509*5c1def83SBjoern A. Zeeb tx_mcs_set |= mcs << (nss * 2);
1510*5c1def83SBjoern A. Zeeb }
1511*5c1def83SBjoern A. Zeeb
1512*5c1def83SBjoern A. Zeeb return tx_mcs_set;
1513*5c1def83SBjoern A. Zeeb }
1514*5c1def83SBjoern A. Zeeb
ath12k_peer_assoc_h_vht(struct ath12k * ar,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct ath12k_wmi_peer_assoc_arg * arg)1515*5c1def83SBjoern A. Zeeb static void ath12k_peer_assoc_h_vht(struct ath12k *ar,
1516*5c1def83SBjoern A. Zeeb struct ieee80211_vif *vif,
1517*5c1def83SBjoern A. Zeeb struct ieee80211_sta *sta,
1518*5c1def83SBjoern A. Zeeb struct ath12k_wmi_peer_assoc_arg *arg)
1519*5c1def83SBjoern A. Zeeb {
1520*5c1def83SBjoern A. Zeeb const struct ieee80211_sta_vht_cap *vht_cap = &sta->deflink.vht_cap;
1521*5c1def83SBjoern A. Zeeb struct ath12k_vif *arvif = (void *)vif->drv_priv;
1522*5c1def83SBjoern A. Zeeb struct cfg80211_chan_def def;
1523*5c1def83SBjoern A. Zeeb enum nl80211_band band;
1524*5c1def83SBjoern A. Zeeb const u16 *vht_mcs_mask;
1525*5c1def83SBjoern A. Zeeb u16 tx_mcs_map;
1526*5c1def83SBjoern A. Zeeb u8 ampdu_factor;
1527*5c1def83SBjoern A. Zeeb u8 max_nss, vht_mcs;
1528*5c1def83SBjoern A. Zeeb int i;
1529*5c1def83SBjoern A. Zeeb
1530*5c1def83SBjoern A. Zeeb if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))
1531*5c1def83SBjoern A. Zeeb return;
1532*5c1def83SBjoern A. Zeeb
1533*5c1def83SBjoern A. Zeeb if (!vht_cap->vht_supported)
1534*5c1def83SBjoern A. Zeeb return;
1535*5c1def83SBjoern A. Zeeb
1536*5c1def83SBjoern A. Zeeb band = def.chan->band;
1537*5c1def83SBjoern A. Zeeb vht_mcs_mask = arvif->bitrate_mask.control[band].vht_mcs;
1538*5c1def83SBjoern A. Zeeb
1539*5c1def83SBjoern A. Zeeb if (ath12k_peer_assoc_h_vht_masked(vht_mcs_mask))
1540*5c1def83SBjoern A. Zeeb return;
1541*5c1def83SBjoern A. Zeeb
1542*5c1def83SBjoern A. Zeeb arg->vht_flag = true;
1543*5c1def83SBjoern A. Zeeb
1544*5c1def83SBjoern A. Zeeb /* TODO: similar flags required? */
1545*5c1def83SBjoern A. Zeeb arg->vht_capable = true;
1546*5c1def83SBjoern A. Zeeb
1547*5c1def83SBjoern A. Zeeb if (def.chan->band == NL80211_BAND_2GHZ)
1548*5c1def83SBjoern A. Zeeb arg->vht_ng_flag = true;
1549*5c1def83SBjoern A. Zeeb
1550*5c1def83SBjoern A. Zeeb arg->peer_vht_caps = vht_cap->cap;
1551*5c1def83SBjoern A. Zeeb
1552*5c1def83SBjoern A. Zeeb ampdu_factor = (vht_cap->cap &
1553*5c1def83SBjoern A. Zeeb IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK) >>
1554*5c1def83SBjoern A. Zeeb IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;
1555*5c1def83SBjoern A. Zeeb
1556*5c1def83SBjoern A. Zeeb /* Workaround: Some Netgear/Linksys 11ac APs set Rx A-MPDU factor to
1557*5c1def83SBjoern A. Zeeb * zero in VHT IE. Using it would result in degraded throughput.
1558*5c1def83SBjoern A. Zeeb * arg->peer_max_mpdu at this point contains HT max_mpdu so keep
1559*5c1def83SBjoern A. Zeeb * it if VHT max_mpdu is smaller.
1560*5c1def83SBjoern A. Zeeb */
1561*5c1def83SBjoern A. Zeeb arg->peer_max_mpdu = max(arg->peer_max_mpdu,
1562*5c1def83SBjoern A. Zeeb (1U << (IEEE80211_HT_MAX_AMPDU_FACTOR +
1563*5c1def83SBjoern A. Zeeb ampdu_factor)) - 1);
1564*5c1def83SBjoern A. Zeeb
1565*5c1def83SBjoern A. Zeeb if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80)
1566*5c1def83SBjoern A. Zeeb arg->bw_80 = true;
1567*5c1def83SBjoern A. Zeeb
1568*5c1def83SBjoern A. Zeeb if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160)
1569*5c1def83SBjoern A. Zeeb arg->bw_160 = true;
1570*5c1def83SBjoern A. Zeeb
1571*5c1def83SBjoern A. Zeeb /* Calculate peer NSS capability from VHT capabilities if STA
1572*5c1def83SBjoern A. Zeeb * supports VHT.
1573*5c1def83SBjoern A. Zeeb */
1574*5c1def83SBjoern A. Zeeb for (i = 0, max_nss = 0, vht_mcs = 0; i < NL80211_VHT_NSS_MAX; i++) {
1575*5c1def83SBjoern A. Zeeb vht_mcs = __le16_to_cpu(vht_cap->vht_mcs.rx_mcs_map) >>
1576*5c1def83SBjoern A. Zeeb (2 * i) & 3;
1577*5c1def83SBjoern A. Zeeb
1578*5c1def83SBjoern A. Zeeb if (vht_mcs != IEEE80211_VHT_MCS_NOT_SUPPORTED &&
1579*5c1def83SBjoern A. Zeeb vht_mcs_mask[i])
1580*5c1def83SBjoern A. Zeeb max_nss = i + 1;
1581*5c1def83SBjoern A. Zeeb }
1582*5c1def83SBjoern A. Zeeb arg->peer_nss = min(sta->deflink.rx_nss, max_nss);
1583*5c1def83SBjoern A. Zeeb arg->rx_max_rate = __le16_to_cpu(vht_cap->vht_mcs.rx_highest);
1584*5c1def83SBjoern A. Zeeb arg->rx_mcs_set = __le16_to_cpu(vht_cap->vht_mcs.rx_mcs_map);
1585*5c1def83SBjoern A. Zeeb arg->tx_max_rate = __le16_to_cpu(vht_cap->vht_mcs.tx_highest);
1586*5c1def83SBjoern A. Zeeb
1587*5c1def83SBjoern A. Zeeb tx_mcs_map = __le16_to_cpu(vht_cap->vht_mcs.tx_mcs_map);
1588*5c1def83SBjoern A. Zeeb arg->tx_mcs_set = ath12k_peer_assoc_h_vht_limit(tx_mcs_map, vht_mcs_mask);
1589*5c1def83SBjoern A. Zeeb
1590*5c1def83SBjoern A. Zeeb /* In QCN9274 platform, VHT MCS rate 10 and 11 is enabled by default.
1591*5c1def83SBjoern A. Zeeb * VHT MCS rate 10 and 11 is not supported in 11ac standard.
1592*5c1def83SBjoern A. Zeeb * so explicitly disable the VHT MCS rate 10 and 11 in 11ac mode.
1593*5c1def83SBjoern A. Zeeb */
1594*5c1def83SBjoern A. Zeeb arg->tx_mcs_set &= ~IEEE80211_VHT_MCS_SUPPORT_0_11_MASK;
1595*5c1def83SBjoern A. Zeeb arg->tx_mcs_set |= IEEE80211_DISABLE_VHT_MCS_SUPPORT_0_11;
1596*5c1def83SBjoern A. Zeeb
1597*5c1def83SBjoern A. Zeeb if ((arg->tx_mcs_set & IEEE80211_VHT_MCS_NOT_SUPPORTED) ==
1598*5c1def83SBjoern A. Zeeb IEEE80211_VHT_MCS_NOT_SUPPORTED)
1599*5c1def83SBjoern A. Zeeb arg->peer_vht_caps &= ~IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
1600*5c1def83SBjoern A. Zeeb
1601*5c1def83SBjoern A. Zeeb /* TODO: Check */
1602*5c1def83SBjoern A. Zeeb arg->tx_max_mcs_nss = 0xFF;
1603*5c1def83SBjoern A. Zeeb
1604*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vht peer %pM max_mpdu %d flags 0x%x\n",
1605*5c1def83SBjoern A. Zeeb sta->addr, arg->peer_max_mpdu, arg->peer_flags);
1606*5c1def83SBjoern A. Zeeb
1607*5c1def83SBjoern A. Zeeb /* TODO: rxnss_override */
1608*5c1def83SBjoern A. Zeeb }
1609*5c1def83SBjoern A. Zeeb
ath12k_peer_assoc_h_he(struct ath12k * ar,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct ath12k_wmi_peer_assoc_arg * arg)1610*5c1def83SBjoern A. Zeeb static void ath12k_peer_assoc_h_he(struct ath12k *ar,
1611*5c1def83SBjoern A. Zeeb struct ieee80211_vif *vif,
1612*5c1def83SBjoern A. Zeeb struct ieee80211_sta *sta,
1613*5c1def83SBjoern A. Zeeb struct ath12k_wmi_peer_assoc_arg *arg)
1614*5c1def83SBjoern A. Zeeb {
1615*5c1def83SBjoern A. Zeeb const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap;
1616*5c1def83SBjoern A. Zeeb int i;
1617*5c1def83SBjoern A. Zeeb u8 ampdu_factor, rx_mcs_80, rx_mcs_160, max_nss;
1618*5c1def83SBjoern A. Zeeb u16 mcs_160_map, mcs_80_map;
1619*5c1def83SBjoern A. Zeeb bool support_160;
1620*5c1def83SBjoern A. Zeeb u16 v;
1621*5c1def83SBjoern A. Zeeb
1622*5c1def83SBjoern A. Zeeb if (!he_cap->has_he)
1623*5c1def83SBjoern A. Zeeb return;
1624*5c1def83SBjoern A. Zeeb
1625*5c1def83SBjoern A. Zeeb arg->he_flag = true;
1626*5c1def83SBjoern A. Zeeb
1627*5c1def83SBjoern A. Zeeb support_160 = !!(he_cap->he_cap_elem.phy_cap_info[0] &
1628*5c1def83SBjoern A. Zeeb IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G);
1629*5c1def83SBjoern A. Zeeb
1630*5c1def83SBjoern A. Zeeb /* Supported HE-MCS and NSS Set of peer he_cap is intersection with self he_cp */
1631*5c1def83SBjoern A. Zeeb mcs_160_map = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160);
1632*5c1def83SBjoern A. Zeeb mcs_80_map = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80);
1633*5c1def83SBjoern A. Zeeb
1634*5c1def83SBjoern A. Zeeb if (support_160) {
1635*5c1def83SBjoern A. Zeeb for (i = 7; i >= 0; i--) {
1636*5c1def83SBjoern A. Zeeb u8 mcs_160 = (mcs_160_map >> (2 * i)) & 3;
1637*5c1def83SBjoern A. Zeeb
1638*5c1def83SBjoern A. Zeeb if (mcs_160 != IEEE80211_HE_MCS_NOT_SUPPORTED) {
1639*5c1def83SBjoern A. Zeeb rx_mcs_160 = i + 1;
1640*5c1def83SBjoern A. Zeeb break;
1641*5c1def83SBjoern A. Zeeb }
1642*5c1def83SBjoern A. Zeeb }
1643*5c1def83SBjoern A. Zeeb }
1644*5c1def83SBjoern A. Zeeb
1645*5c1def83SBjoern A. Zeeb for (i = 7; i >= 0; i--) {
1646*5c1def83SBjoern A. Zeeb u8 mcs_80 = (mcs_80_map >> (2 * i)) & 3;
1647*5c1def83SBjoern A. Zeeb
1648*5c1def83SBjoern A. Zeeb if (mcs_80 != IEEE80211_HE_MCS_NOT_SUPPORTED) {
1649*5c1def83SBjoern A. Zeeb rx_mcs_80 = i + 1;
1650*5c1def83SBjoern A. Zeeb break;
1651*5c1def83SBjoern A. Zeeb }
1652*5c1def83SBjoern A. Zeeb }
1653*5c1def83SBjoern A. Zeeb
1654*5c1def83SBjoern A. Zeeb if (support_160)
1655*5c1def83SBjoern A. Zeeb max_nss = min(rx_mcs_80, rx_mcs_160);
1656*5c1def83SBjoern A. Zeeb else
1657*5c1def83SBjoern A. Zeeb max_nss = rx_mcs_80;
1658*5c1def83SBjoern A. Zeeb
1659*5c1def83SBjoern A. Zeeb arg->peer_nss = min(sta->deflink.rx_nss, max_nss);
1660*5c1def83SBjoern A. Zeeb
1661*5c1def83SBjoern A. Zeeb memcpy(&arg->peer_he_cap_macinfo, he_cap->he_cap_elem.mac_cap_info,
1662*5c1def83SBjoern A. Zeeb sizeof(he_cap->he_cap_elem.mac_cap_info));
1663*5c1def83SBjoern A. Zeeb memcpy(&arg->peer_he_cap_phyinfo, he_cap->he_cap_elem.phy_cap_info,
1664*5c1def83SBjoern A. Zeeb sizeof(he_cap->he_cap_elem.phy_cap_info));
1665*5c1def83SBjoern A. Zeeb arg->peer_he_ops = vif->bss_conf.he_oper.params;
1666*5c1def83SBjoern A. Zeeb
1667*5c1def83SBjoern A. Zeeb /* the top most byte is used to indicate BSS color info */
1668*5c1def83SBjoern A. Zeeb arg->peer_he_ops &= 0xffffff;
1669*5c1def83SBjoern A. Zeeb
1670*5c1def83SBjoern A. Zeeb /* As per section 26.6.1 IEEE Std 802.11ax‐2022, if the Max AMPDU
1671*5c1def83SBjoern A. Zeeb * Exponent Extension in HE cap is zero, use the arg->peer_max_mpdu
1672*5c1def83SBjoern A. Zeeb * as calculated while parsing VHT caps(if VHT caps is present)
1673*5c1def83SBjoern A. Zeeb * or HT caps (if VHT caps is not present).
1674*5c1def83SBjoern A. Zeeb *
1675*5c1def83SBjoern A. Zeeb * For non-zero value of Max AMPDU Exponent Extension in HE MAC caps,
1676*5c1def83SBjoern A. Zeeb * if a HE STA sends VHT cap and HE cap IE in assoc request then, use
1677*5c1def83SBjoern A. Zeeb * MAX_AMPDU_LEN_FACTOR as 20 to calculate max_ampdu length.
1678*5c1def83SBjoern A. Zeeb * If a HE STA that does not send VHT cap, but HE and HT cap in assoc
1679*5c1def83SBjoern A. Zeeb * request, then use MAX_AMPDU_LEN_FACTOR as 16 to calculate max_ampdu
1680*5c1def83SBjoern A. Zeeb * length.
1681*5c1def83SBjoern A. Zeeb */
1682*5c1def83SBjoern A. Zeeb ampdu_factor = (he_cap->he_cap_elem.mac_cap_info[3] &
1683*5c1def83SBjoern A. Zeeb IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_MASK) >>
1684*5c1def83SBjoern A. Zeeb IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_MASK;
1685*5c1def83SBjoern A. Zeeb
1686*5c1def83SBjoern A. Zeeb if (ampdu_factor) {
1687*5c1def83SBjoern A. Zeeb if (sta->deflink.vht_cap.vht_supported)
1688*5c1def83SBjoern A. Zeeb arg->peer_max_mpdu = (1 << (IEEE80211_HE_VHT_MAX_AMPDU_FACTOR +
1689*5c1def83SBjoern A. Zeeb ampdu_factor)) - 1;
1690*5c1def83SBjoern A. Zeeb else if (sta->deflink.ht_cap.ht_supported)
1691*5c1def83SBjoern A. Zeeb arg->peer_max_mpdu = (1 << (IEEE80211_HE_HT_MAX_AMPDU_FACTOR +
1692*5c1def83SBjoern A. Zeeb ampdu_factor)) - 1;
1693*5c1def83SBjoern A. Zeeb }
1694*5c1def83SBjoern A. Zeeb
1695*5c1def83SBjoern A. Zeeb if (he_cap->he_cap_elem.phy_cap_info[6] &
1696*5c1def83SBjoern A. Zeeb IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) {
1697*5c1def83SBjoern A. Zeeb int bit = 7;
1698*5c1def83SBjoern A. Zeeb int nss, ru;
1699*5c1def83SBjoern A. Zeeb
1700*5c1def83SBjoern A. Zeeb arg->peer_ppet.numss_m1 = he_cap->ppe_thres[0] &
1701*5c1def83SBjoern A. Zeeb IEEE80211_PPE_THRES_NSS_MASK;
1702*5c1def83SBjoern A. Zeeb arg->peer_ppet.ru_bit_mask =
1703*5c1def83SBjoern A. Zeeb (he_cap->ppe_thres[0] &
1704*5c1def83SBjoern A. Zeeb IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK) >>
1705*5c1def83SBjoern A. Zeeb IEEE80211_PPE_THRES_RU_INDEX_BITMASK_POS;
1706*5c1def83SBjoern A. Zeeb
1707*5c1def83SBjoern A. Zeeb for (nss = 0; nss <= arg->peer_ppet.numss_m1; nss++) {
1708*5c1def83SBjoern A. Zeeb for (ru = 0; ru < 4; ru++) {
1709*5c1def83SBjoern A. Zeeb u32 val = 0;
1710*5c1def83SBjoern A. Zeeb int i;
1711*5c1def83SBjoern A. Zeeb
1712*5c1def83SBjoern A. Zeeb if ((arg->peer_ppet.ru_bit_mask & BIT(ru)) == 0)
1713*5c1def83SBjoern A. Zeeb continue;
1714*5c1def83SBjoern A. Zeeb for (i = 0; i < 6; i++) {
1715*5c1def83SBjoern A. Zeeb val >>= 1;
1716*5c1def83SBjoern A. Zeeb val |= ((he_cap->ppe_thres[bit / 8] >>
1717*5c1def83SBjoern A. Zeeb (bit % 8)) & 0x1) << 5;
1718*5c1def83SBjoern A. Zeeb bit++;
1719*5c1def83SBjoern A. Zeeb }
1720*5c1def83SBjoern A. Zeeb arg->peer_ppet.ppet16_ppet8_ru3_ru0[nss] |=
1721*5c1def83SBjoern A. Zeeb val << (ru * 6);
1722*5c1def83SBjoern A. Zeeb }
1723*5c1def83SBjoern A. Zeeb }
1724*5c1def83SBjoern A. Zeeb }
1725*5c1def83SBjoern A. Zeeb
1726*5c1def83SBjoern A. Zeeb if (he_cap->he_cap_elem.mac_cap_info[0] & IEEE80211_HE_MAC_CAP0_TWT_RES)
1727*5c1def83SBjoern A. Zeeb arg->twt_responder = true;
1728*5c1def83SBjoern A. Zeeb if (he_cap->he_cap_elem.mac_cap_info[0] & IEEE80211_HE_MAC_CAP0_TWT_REQ)
1729*5c1def83SBjoern A. Zeeb arg->twt_requester = true;
1730*5c1def83SBjoern A. Zeeb
1731*5c1def83SBjoern A. Zeeb switch (sta->deflink.bandwidth) {
1732*5c1def83SBjoern A. Zeeb case IEEE80211_STA_RX_BW_160:
1733*5c1def83SBjoern A. Zeeb if (he_cap->he_cap_elem.phy_cap_info[0] &
1734*5c1def83SBjoern A. Zeeb IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G) {
1735*5c1def83SBjoern A. Zeeb v = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80p80);
1736*5c1def83SBjoern A. Zeeb arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80_80] = v;
1737*5c1def83SBjoern A. Zeeb
1738*5c1def83SBjoern A. Zeeb v = le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_80p80);
1739*5c1def83SBjoern A. Zeeb arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80_80] = v;
1740*5c1def83SBjoern A. Zeeb
1741*5c1def83SBjoern A. Zeeb arg->peer_he_mcs_count++;
1742*5c1def83SBjoern A. Zeeb }
1743*5c1def83SBjoern A. Zeeb v = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160);
1744*5c1def83SBjoern A. Zeeb arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_160] = v;
1745*5c1def83SBjoern A. Zeeb
1746*5c1def83SBjoern A. Zeeb v = le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_160);
1747*5c1def83SBjoern A. Zeeb arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_160] = v;
1748*5c1def83SBjoern A. Zeeb
1749*5c1def83SBjoern A. Zeeb arg->peer_he_mcs_count++;
1750*5c1def83SBjoern A. Zeeb fallthrough;
1751*5c1def83SBjoern A. Zeeb
1752*5c1def83SBjoern A. Zeeb default:
1753*5c1def83SBjoern A. Zeeb v = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80);
1754*5c1def83SBjoern A. Zeeb arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80] = v;
1755*5c1def83SBjoern A. Zeeb
1756*5c1def83SBjoern A. Zeeb v = le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_80);
1757*5c1def83SBjoern A. Zeeb arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80] = v;
1758*5c1def83SBjoern A. Zeeb
1759*5c1def83SBjoern A. Zeeb arg->peer_he_mcs_count++;
1760*5c1def83SBjoern A. Zeeb break;
1761*5c1def83SBjoern A. Zeeb }
1762*5c1def83SBjoern A. Zeeb }
1763*5c1def83SBjoern A. Zeeb
ath12k_peer_assoc_h_smps(struct ieee80211_sta * sta,struct ath12k_wmi_peer_assoc_arg * arg)1764*5c1def83SBjoern A. Zeeb static void ath12k_peer_assoc_h_smps(struct ieee80211_sta *sta,
1765*5c1def83SBjoern A. Zeeb struct ath12k_wmi_peer_assoc_arg *arg)
1766*5c1def83SBjoern A. Zeeb {
1767*5c1def83SBjoern A. Zeeb const struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap;
1768*5c1def83SBjoern A. Zeeb int smps;
1769*5c1def83SBjoern A. Zeeb
1770*5c1def83SBjoern A. Zeeb if (!ht_cap->ht_supported)
1771*5c1def83SBjoern A. Zeeb return;
1772*5c1def83SBjoern A. Zeeb
1773*5c1def83SBjoern A. Zeeb smps = ht_cap->cap & IEEE80211_HT_CAP_SM_PS;
1774*5c1def83SBjoern A. Zeeb smps >>= IEEE80211_HT_CAP_SM_PS_SHIFT;
1775*5c1def83SBjoern A. Zeeb
1776*5c1def83SBjoern A. Zeeb switch (smps) {
1777*5c1def83SBjoern A. Zeeb case WLAN_HT_CAP_SM_PS_STATIC:
1778*5c1def83SBjoern A. Zeeb arg->static_mimops_flag = true;
1779*5c1def83SBjoern A. Zeeb break;
1780*5c1def83SBjoern A. Zeeb case WLAN_HT_CAP_SM_PS_DYNAMIC:
1781*5c1def83SBjoern A. Zeeb arg->dynamic_mimops_flag = true;
1782*5c1def83SBjoern A. Zeeb break;
1783*5c1def83SBjoern A. Zeeb case WLAN_HT_CAP_SM_PS_DISABLED:
1784*5c1def83SBjoern A. Zeeb arg->spatial_mux_flag = true;
1785*5c1def83SBjoern A. Zeeb break;
1786*5c1def83SBjoern A. Zeeb default:
1787*5c1def83SBjoern A. Zeeb break;
1788*5c1def83SBjoern A. Zeeb }
1789*5c1def83SBjoern A. Zeeb }
1790*5c1def83SBjoern A. Zeeb
ath12k_peer_assoc_h_qos(struct ath12k * ar,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct ath12k_wmi_peer_assoc_arg * arg)1791*5c1def83SBjoern A. Zeeb static void ath12k_peer_assoc_h_qos(struct ath12k *ar,
1792*5c1def83SBjoern A. Zeeb struct ieee80211_vif *vif,
1793*5c1def83SBjoern A. Zeeb struct ieee80211_sta *sta,
1794*5c1def83SBjoern A. Zeeb struct ath12k_wmi_peer_assoc_arg *arg)
1795*5c1def83SBjoern A. Zeeb {
1796*5c1def83SBjoern A. Zeeb struct ath12k_vif *arvif = (void *)vif->drv_priv;
1797*5c1def83SBjoern A. Zeeb
1798*5c1def83SBjoern A. Zeeb switch (arvif->vdev_type) {
1799*5c1def83SBjoern A. Zeeb case WMI_VDEV_TYPE_AP:
1800*5c1def83SBjoern A. Zeeb if (sta->wme) {
1801*5c1def83SBjoern A. Zeeb /* TODO: Check WME vs QoS */
1802*5c1def83SBjoern A. Zeeb arg->is_wme_set = true;
1803*5c1def83SBjoern A. Zeeb arg->qos_flag = true;
1804*5c1def83SBjoern A. Zeeb }
1805*5c1def83SBjoern A. Zeeb
1806*5c1def83SBjoern A. Zeeb if (sta->wme && sta->uapsd_queues) {
1807*5c1def83SBjoern A. Zeeb /* TODO: Check WME vs QoS */
1808*5c1def83SBjoern A. Zeeb arg->is_wme_set = true;
1809*5c1def83SBjoern A. Zeeb arg->apsd_flag = true;
1810*5c1def83SBjoern A. Zeeb arg->peer_rate_caps |= WMI_HOST_RC_UAPSD_FLAG;
1811*5c1def83SBjoern A. Zeeb }
1812*5c1def83SBjoern A. Zeeb break;
1813*5c1def83SBjoern A. Zeeb case WMI_VDEV_TYPE_STA:
1814*5c1def83SBjoern A. Zeeb if (sta->wme) {
1815*5c1def83SBjoern A. Zeeb arg->is_wme_set = true;
1816*5c1def83SBjoern A. Zeeb arg->qos_flag = true;
1817*5c1def83SBjoern A. Zeeb }
1818*5c1def83SBjoern A. Zeeb break;
1819*5c1def83SBjoern A. Zeeb default:
1820*5c1def83SBjoern A. Zeeb break;
1821*5c1def83SBjoern A. Zeeb }
1822*5c1def83SBjoern A. Zeeb
1823*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac peer %pM qos %d\n",
1824*5c1def83SBjoern A. Zeeb sta->addr, arg->qos_flag);
1825*5c1def83SBjoern A. Zeeb }
1826*5c1def83SBjoern A. Zeeb
ath12k_peer_assoc_qos_ap(struct ath12k * ar,struct ath12k_vif * arvif,struct ieee80211_sta * sta)1827*5c1def83SBjoern A. Zeeb static int ath12k_peer_assoc_qos_ap(struct ath12k *ar,
1828*5c1def83SBjoern A. Zeeb struct ath12k_vif *arvif,
1829*5c1def83SBjoern A. Zeeb struct ieee80211_sta *sta)
1830*5c1def83SBjoern A. Zeeb {
1831*5c1def83SBjoern A. Zeeb struct ath12k_wmi_ap_ps_arg arg;
1832*5c1def83SBjoern A. Zeeb u32 max_sp;
1833*5c1def83SBjoern A. Zeeb u32 uapsd;
1834*5c1def83SBjoern A. Zeeb int ret;
1835*5c1def83SBjoern A. Zeeb
1836*5c1def83SBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
1837*5c1def83SBjoern A. Zeeb
1838*5c1def83SBjoern A. Zeeb arg.vdev_id = arvif->vdev_id;
1839*5c1def83SBjoern A. Zeeb
1840*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac uapsd_queues 0x%x max_sp %d\n",
1841*5c1def83SBjoern A. Zeeb sta->uapsd_queues, sta->max_sp);
1842*5c1def83SBjoern A. Zeeb
1843*5c1def83SBjoern A. Zeeb uapsd = 0;
1844*5c1def83SBjoern A. Zeeb if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO)
1845*5c1def83SBjoern A. Zeeb uapsd |= WMI_AP_PS_UAPSD_AC3_DELIVERY_EN |
1846*5c1def83SBjoern A. Zeeb WMI_AP_PS_UAPSD_AC3_TRIGGER_EN;
1847*5c1def83SBjoern A. Zeeb if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VI)
1848*5c1def83SBjoern A. Zeeb uapsd |= WMI_AP_PS_UAPSD_AC2_DELIVERY_EN |
1849*5c1def83SBjoern A. Zeeb WMI_AP_PS_UAPSD_AC2_TRIGGER_EN;
1850*5c1def83SBjoern A. Zeeb if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BK)
1851*5c1def83SBjoern A. Zeeb uapsd |= WMI_AP_PS_UAPSD_AC1_DELIVERY_EN |
1852*5c1def83SBjoern A. Zeeb WMI_AP_PS_UAPSD_AC1_TRIGGER_EN;
1853*5c1def83SBjoern A. Zeeb if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BE)
1854*5c1def83SBjoern A. Zeeb uapsd |= WMI_AP_PS_UAPSD_AC0_DELIVERY_EN |
1855*5c1def83SBjoern A. Zeeb WMI_AP_PS_UAPSD_AC0_TRIGGER_EN;
1856*5c1def83SBjoern A. Zeeb
1857*5c1def83SBjoern A. Zeeb max_sp = 0;
1858*5c1def83SBjoern A. Zeeb if (sta->max_sp < MAX_WMI_AP_PS_PEER_PARAM_MAX_SP)
1859*5c1def83SBjoern A. Zeeb max_sp = sta->max_sp;
1860*5c1def83SBjoern A. Zeeb
1861*5c1def83SBjoern A. Zeeb arg.param = WMI_AP_PS_PEER_PARAM_UAPSD;
1862*5c1def83SBjoern A. Zeeb arg.value = uapsd;
1863*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_send_set_ap_ps_param_cmd(ar, sta->addr, &arg);
1864*5c1def83SBjoern A. Zeeb if (ret)
1865*5c1def83SBjoern A. Zeeb goto err;
1866*5c1def83SBjoern A. Zeeb
1867*5c1def83SBjoern A. Zeeb arg.param = WMI_AP_PS_PEER_PARAM_MAX_SP;
1868*5c1def83SBjoern A. Zeeb arg.value = max_sp;
1869*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_send_set_ap_ps_param_cmd(ar, sta->addr, &arg);
1870*5c1def83SBjoern A. Zeeb if (ret)
1871*5c1def83SBjoern A. Zeeb goto err;
1872*5c1def83SBjoern A. Zeeb
1873*5c1def83SBjoern A. Zeeb /* TODO: revisit during testing */
1874*5c1def83SBjoern A. Zeeb arg.param = WMI_AP_PS_PEER_PARAM_SIFS_RESP_FRMTYPE;
1875*5c1def83SBjoern A. Zeeb arg.value = DISABLE_SIFS_RESPONSE_TRIGGER;
1876*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_send_set_ap_ps_param_cmd(ar, sta->addr, &arg);
1877*5c1def83SBjoern A. Zeeb if (ret)
1878*5c1def83SBjoern A. Zeeb goto err;
1879*5c1def83SBjoern A. Zeeb
1880*5c1def83SBjoern A. Zeeb arg.param = WMI_AP_PS_PEER_PARAM_SIFS_RESP_UAPSD;
1881*5c1def83SBjoern A. Zeeb arg.value = DISABLE_SIFS_RESPONSE_TRIGGER;
1882*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_send_set_ap_ps_param_cmd(ar, sta->addr, &arg);
1883*5c1def83SBjoern A. Zeeb if (ret)
1884*5c1def83SBjoern A. Zeeb goto err;
1885*5c1def83SBjoern A. Zeeb
1886*5c1def83SBjoern A. Zeeb return 0;
1887*5c1def83SBjoern A. Zeeb
1888*5c1def83SBjoern A. Zeeb err:
1889*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to set ap ps peer param %d for vdev %i: %d\n",
1890*5c1def83SBjoern A. Zeeb arg.param, arvif->vdev_id, ret);
1891*5c1def83SBjoern A. Zeeb return ret;
1892*5c1def83SBjoern A. Zeeb }
1893*5c1def83SBjoern A. Zeeb
ath12k_mac_sta_has_ofdm_only(struct ieee80211_sta * sta)1894*5c1def83SBjoern A. Zeeb static bool ath12k_mac_sta_has_ofdm_only(struct ieee80211_sta *sta)
1895*5c1def83SBjoern A. Zeeb {
1896*5c1def83SBjoern A. Zeeb return sta->deflink.supp_rates[NL80211_BAND_2GHZ] >>
1897*5c1def83SBjoern A. Zeeb ATH12K_MAC_FIRST_OFDM_RATE_IDX;
1898*5c1def83SBjoern A. Zeeb }
1899*5c1def83SBjoern A. Zeeb
ath12k_mac_get_phymode_vht(struct ath12k * ar,struct ieee80211_sta * sta)1900*5c1def83SBjoern A. Zeeb static enum wmi_phy_mode ath12k_mac_get_phymode_vht(struct ath12k *ar,
1901*5c1def83SBjoern A. Zeeb struct ieee80211_sta *sta)
1902*5c1def83SBjoern A. Zeeb {
1903*5c1def83SBjoern A. Zeeb if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) {
1904*5c1def83SBjoern A. Zeeb switch (sta->deflink.vht_cap.cap &
1905*5c1def83SBjoern A. Zeeb IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) {
1906*5c1def83SBjoern A. Zeeb case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ:
1907*5c1def83SBjoern A. Zeeb return MODE_11AC_VHT160;
1908*5c1def83SBjoern A. Zeeb case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ:
1909*5c1def83SBjoern A. Zeeb return MODE_11AC_VHT80_80;
1910*5c1def83SBjoern A. Zeeb default:
1911*5c1def83SBjoern A. Zeeb /* not sure if this is a valid case? */
1912*5c1def83SBjoern A. Zeeb return MODE_11AC_VHT160;
1913*5c1def83SBjoern A. Zeeb }
1914*5c1def83SBjoern A. Zeeb }
1915*5c1def83SBjoern A. Zeeb
1916*5c1def83SBjoern A. Zeeb if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80)
1917*5c1def83SBjoern A. Zeeb return MODE_11AC_VHT80;
1918*5c1def83SBjoern A. Zeeb
1919*5c1def83SBjoern A. Zeeb if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
1920*5c1def83SBjoern A. Zeeb return MODE_11AC_VHT40;
1921*5c1def83SBjoern A. Zeeb
1922*5c1def83SBjoern A. Zeeb if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_20)
1923*5c1def83SBjoern A. Zeeb return MODE_11AC_VHT20;
1924*5c1def83SBjoern A. Zeeb
1925*5c1def83SBjoern A. Zeeb return MODE_UNKNOWN;
1926*5c1def83SBjoern A. Zeeb }
1927*5c1def83SBjoern A. Zeeb
ath12k_mac_get_phymode_he(struct ath12k * ar,struct ieee80211_sta * sta)1928*5c1def83SBjoern A. Zeeb static enum wmi_phy_mode ath12k_mac_get_phymode_he(struct ath12k *ar,
1929*5c1def83SBjoern A. Zeeb struct ieee80211_sta *sta)
1930*5c1def83SBjoern A. Zeeb {
1931*5c1def83SBjoern A. Zeeb if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) {
1932*5c1def83SBjoern A. Zeeb if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[0] &
1933*5c1def83SBjoern A. Zeeb IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G)
1934*5c1def83SBjoern A. Zeeb return MODE_11AX_HE160;
1935*5c1def83SBjoern A. Zeeb else if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[0] &
1936*5c1def83SBjoern A. Zeeb IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)
1937*5c1def83SBjoern A. Zeeb return MODE_11AX_HE80_80;
1938*5c1def83SBjoern A. Zeeb /* not sure if this is a valid case? */
1939*5c1def83SBjoern A. Zeeb return MODE_11AX_HE160;
1940*5c1def83SBjoern A. Zeeb }
1941*5c1def83SBjoern A. Zeeb
1942*5c1def83SBjoern A. Zeeb if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80)
1943*5c1def83SBjoern A. Zeeb return MODE_11AX_HE80;
1944*5c1def83SBjoern A. Zeeb
1945*5c1def83SBjoern A. Zeeb if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
1946*5c1def83SBjoern A. Zeeb return MODE_11AX_HE40;
1947*5c1def83SBjoern A. Zeeb
1948*5c1def83SBjoern A. Zeeb if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_20)
1949*5c1def83SBjoern A. Zeeb return MODE_11AX_HE20;
1950*5c1def83SBjoern A. Zeeb
1951*5c1def83SBjoern A. Zeeb return MODE_UNKNOWN;
1952*5c1def83SBjoern A. Zeeb }
1953*5c1def83SBjoern A. Zeeb
ath12k_mac_get_phymode_eht(struct ath12k * ar,struct ieee80211_sta * sta)1954*5c1def83SBjoern A. Zeeb static enum wmi_phy_mode ath12k_mac_get_phymode_eht(struct ath12k *ar,
1955*5c1def83SBjoern A. Zeeb struct ieee80211_sta *sta)
1956*5c1def83SBjoern A. Zeeb {
1957*5c1def83SBjoern A. Zeeb if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_320)
1958*5c1def83SBjoern A. Zeeb if (sta->deflink.eht_cap.eht_cap_elem.phy_cap_info[0] &
1959*5c1def83SBjoern A. Zeeb IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ)
1960*5c1def83SBjoern A. Zeeb return MODE_11BE_EHT320;
1961*5c1def83SBjoern A. Zeeb
1962*5c1def83SBjoern A. Zeeb if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) {
1963*5c1def83SBjoern A. Zeeb if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[0] &
1964*5c1def83SBjoern A. Zeeb IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G)
1965*5c1def83SBjoern A. Zeeb return MODE_11BE_EHT160;
1966*5c1def83SBjoern A. Zeeb
1967*5c1def83SBjoern A. Zeeb if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[0] &
1968*5c1def83SBjoern A. Zeeb IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)
1969*5c1def83SBjoern A. Zeeb return MODE_11BE_EHT80_80;
1970*5c1def83SBjoern A. Zeeb
1971*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "invalid EHT PHY capability info for 160 Mhz: %d\n",
1972*5c1def83SBjoern A. Zeeb sta->deflink.he_cap.he_cap_elem.phy_cap_info[0]);
1973*5c1def83SBjoern A. Zeeb
1974*5c1def83SBjoern A. Zeeb return MODE_11BE_EHT160;
1975*5c1def83SBjoern A. Zeeb }
1976*5c1def83SBjoern A. Zeeb
1977*5c1def83SBjoern A. Zeeb if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80)
1978*5c1def83SBjoern A. Zeeb return MODE_11BE_EHT80;
1979*5c1def83SBjoern A. Zeeb
1980*5c1def83SBjoern A. Zeeb if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
1981*5c1def83SBjoern A. Zeeb return MODE_11BE_EHT40;
1982*5c1def83SBjoern A. Zeeb
1983*5c1def83SBjoern A. Zeeb if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_20)
1984*5c1def83SBjoern A. Zeeb return MODE_11BE_EHT20;
1985*5c1def83SBjoern A. Zeeb
1986*5c1def83SBjoern A. Zeeb return MODE_UNKNOWN;
1987*5c1def83SBjoern A. Zeeb }
1988*5c1def83SBjoern A. Zeeb
ath12k_peer_assoc_h_phymode(struct ath12k * ar,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct ath12k_wmi_peer_assoc_arg * arg)1989*5c1def83SBjoern A. Zeeb static void ath12k_peer_assoc_h_phymode(struct ath12k *ar,
1990*5c1def83SBjoern A. Zeeb struct ieee80211_vif *vif,
1991*5c1def83SBjoern A. Zeeb struct ieee80211_sta *sta,
1992*5c1def83SBjoern A. Zeeb struct ath12k_wmi_peer_assoc_arg *arg)
1993*5c1def83SBjoern A. Zeeb {
1994*5c1def83SBjoern A. Zeeb struct ath12k_vif *arvif = (void *)vif->drv_priv;
1995*5c1def83SBjoern A. Zeeb struct cfg80211_chan_def def;
1996*5c1def83SBjoern A. Zeeb enum nl80211_band band;
1997*5c1def83SBjoern A. Zeeb const u8 *ht_mcs_mask;
1998*5c1def83SBjoern A. Zeeb const u16 *vht_mcs_mask;
1999*5c1def83SBjoern A. Zeeb enum wmi_phy_mode phymode = MODE_UNKNOWN;
2000*5c1def83SBjoern A. Zeeb
2001*5c1def83SBjoern A. Zeeb if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))
2002*5c1def83SBjoern A. Zeeb return;
2003*5c1def83SBjoern A. Zeeb
2004*5c1def83SBjoern A. Zeeb band = def.chan->band;
2005*5c1def83SBjoern A. Zeeb ht_mcs_mask = arvif->bitrate_mask.control[band].ht_mcs;
2006*5c1def83SBjoern A. Zeeb vht_mcs_mask = arvif->bitrate_mask.control[band].vht_mcs;
2007*5c1def83SBjoern A. Zeeb
2008*5c1def83SBjoern A. Zeeb switch (band) {
2009*5c1def83SBjoern A. Zeeb case NL80211_BAND_2GHZ:
2010*5c1def83SBjoern A. Zeeb if (sta->deflink.eht_cap.has_eht) {
2011*5c1def83SBjoern A. Zeeb if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
2012*5c1def83SBjoern A. Zeeb phymode = MODE_11BE_EHT40_2G;
2013*5c1def83SBjoern A. Zeeb else
2014*5c1def83SBjoern A. Zeeb phymode = MODE_11BE_EHT20_2G;
2015*5c1def83SBjoern A. Zeeb } else if (sta->deflink.he_cap.has_he) {
2016*5c1def83SBjoern A. Zeeb if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80)
2017*5c1def83SBjoern A. Zeeb phymode = MODE_11AX_HE80_2G;
2018*5c1def83SBjoern A. Zeeb else if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
2019*5c1def83SBjoern A. Zeeb phymode = MODE_11AX_HE40_2G;
2020*5c1def83SBjoern A. Zeeb else
2021*5c1def83SBjoern A. Zeeb phymode = MODE_11AX_HE20_2G;
2022*5c1def83SBjoern A. Zeeb } else if (sta->deflink.vht_cap.vht_supported &&
2023*5c1def83SBjoern A. Zeeb !ath12k_peer_assoc_h_vht_masked(vht_mcs_mask)) {
2024*5c1def83SBjoern A. Zeeb if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
2025*5c1def83SBjoern A. Zeeb phymode = MODE_11AC_VHT40;
2026*5c1def83SBjoern A. Zeeb else
2027*5c1def83SBjoern A. Zeeb phymode = MODE_11AC_VHT20;
2028*5c1def83SBjoern A. Zeeb } else if (sta->deflink.ht_cap.ht_supported &&
2029*5c1def83SBjoern A. Zeeb !ath12k_peer_assoc_h_ht_masked(ht_mcs_mask)) {
2030*5c1def83SBjoern A. Zeeb if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
2031*5c1def83SBjoern A. Zeeb phymode = MODE_11NG_HT40;
2032*5c1def83SBjoern A. Zeeb else
2033*5c1def83SBjoern A. Zeeb phymode = MODE_11NG_HT20;
2034*5c1def83SBjoern A. Zeeb } else if (ath12k_mac_sta_has_ofdm_only(sta)) {
2035*5c1def83SBjoern A. Zeeb phymode = MODE_11G;
2036*5c1def83SBjoern A. Zeeb } else {
2037*5c1def83SBjoern A. Zeeb phymode = MODE_11B;
2038*5c1def83SBjoern A. Zeeb }
2039*5c1def83SBjoern A. Zeeb break;
2040*5c1def83SBjoern A. Zeeb case NL80211_BAND_5GHZ:
2041*5c1def83SBjoern A. Zeeb case NL80211_BAND_6GHZ:
2042*5c1def83SBjoern A. Zeeb /* Check EHT first */
2043*5c1def83SBjoern A. Zeeb if (sta->deflink.eht_cap.has_eht) {
2044*5c1def83SBjoern A. Zeeb phymode = ath12k_mac_get_phymode_eht(ar, sta);
2045*5c1def83SBjoern A. Zeeb } else if (sta->deflink.he_cap.has_he) {
2046*5c1def83SBjoern A. Zeeb phymode = ath12k_mac_get_phymode_he(ar, sta);
2047*5c1def83SBjoern A. Zeeb } else if (sta->deflink.vht_cap.vht_supported &&
2048*5c1def83SBjoern A. Zeeb !ath12k_peer_assoc_h_vht_masked(vht_mcs_mask)) {
2049*5c1def83SBjoern A. Zeeb phymode = ath12k_mac_get_phymode_vht(ar, sta);
2050*5c1def83SBjoern A. Zeeb } else if (sta->deflink.ht_cap.ht_supported &&
2051*5c1def83SBjoern A. Zeeb !ath12k_peer_assoc_h_ht_masked(ht_mcs_mask)) {
2052*5c1def83SBjoern A. Zeeb if (sta->deflink.bandwidth >= IEEE80211_STA_RX_BW_40)
2053*5c1def83SBjoern A. Zeeb phymode = MODE_11NA_HT40;
2054*5c1def83SBjoern A. Zeeb else
2055*5c1def83SBjoern A. Zeeb phymode = MODE_11NA_HT20;
2056*5c1def83SBjoern A. Zeeb } else {
2057*5c1def83SBjoern A. Zeeb phymode = MODE_11A;
2058*5c1def83SBjoern A. Zeeb }
2059*5c1def83SBjoern A. Zeeb break;
2060*5c1def83SBjoern A. Zeeb default:
2061*5c1def83SBjoern A. Zeeb break;
2062*5c1def83SBjoern A. Zeeb }
2063*5c1def83SBjoern A. Zeeb
2064*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac peer %pM phymode %s\n",
2065*5c1def83SBjoern A. Zeeb sta->addr, ath12k_mac_phymode_str(phymode));
2066*5c1def83SBjoern A. Zeeb
2067*5c1def83SBjoern A. Zeeb arg->peer_phymode = phymode;
2068*5c1def83SBjoern A. Zeeb WARN_ON(phymode == MODE_UNKNOWN);
2069*5c1def83SBjoern A. Zeeb }
2070*5c1def83SBjoern A. Zeeb
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)2071*5c1def83SBjoern A. Zeeb static void ath12k_mac_set_eht_mcs(u8 rx_tx_mcs7, u8 rx_tx_mcs9,
2072*5c1def83SBjoern A. Zeeb u8 rx_tx_mcs11, u8 rx_tx_mcs13,
2073*5c1def83SBjoern A. Zeeb u32 *rx_mcs, u32 *tx_mcs)
2074*5c1def83SBjoern A. Zeeb {
2075*5c1def83SBjoern A. Zeeb *rx_mcs = 0;
2076*5c1def83SBjoern A. Zeeb u32p_replace_bits(rx_mcs,
2077*5c1def83SBjoern A. Zeeb u8_get_bits(rx_tx_mcs7, IEEE80211_EHT_MCS_NSS_RX),
2078*5c1def83SBjoern A. Zeeb WMI_EHT_MCS_NSS_0_7);
2079*5c1def83SBjoern A. Zeeb u32p_replace_bits(rx_mcs,
2080*5c1def83SBjoern A. Zeeb u8_get_bits(rx_tx_mcs9, IEEE80211_EHT_MCS_NSS_RX),
2081*5c1def83SBjoern A. Zeeb WMI_EHT_MCS_NSS_8_9);
2082*5c1def83SBjoern A. Zeeb u32p_replace_bits(rx_mcs,
2083*5c1def83SBjoern A. Zeeb u8_get_bits(rx_tx_mcs11, IEEE80211_EHT_MCS_NSS_RX),
2084*5c1def83SBjoern A. Zeeb WMI_EHT_MCS_NSS_10_11);
2085*5c1def83SBjoern A. Zeeb u32p_replace_bits(rx_mcs,
2086*5c1def83SBjoern A. Zeeb u8_get_bits(rx_tx_mcs13, IEEE80211_EHT_MCS_NSS_RX),
2087*5c1def83SBjoern A. Zeeb WMI_EHT_MCS_NSS_12_13);
2088*5c1def83SBjoern A. Zeeb
2089*5c1def83SBjoern A. Zeeb *tx_mcs = 0;
2090*5c1def83SBjoern A. Zeeb u32p_replace_bits(tx_mcs,
2091*5c1def83SBjoern A. Zeeb u8_get_bits(rx_tx_mcs7, IEEE80211_EHT_MCS_NSS_TX),
2092*5c1def83SBjoern A. Zeeb WMI_EHT_MCS_NSS_0_7);
2093*5c1def83SBjoern A. Zeeb u32p_replace_bits(tx_mcs,
2094*5c1def83SBjoern A. Zeeb u8_get_bits(rx_tx_mcs9, IEEE80211_EHT_MCS_NSS_TX),
2095*5c1def83SBjoern A. Zeeb WMI_EHT_MCS_NSS_8_9);
2096*5c1def83SBjoern A. Zeeb u32p_replace_bits(tx_mcs,
2097*5c1def83SBjoern A. Zeeb u8_get_bits(rx_tx_mcs11, IEEE80211_EHT_MCS_NSS_TX),
2098*5c1def83SBjoern A. Zeeb WMI_EHT_MCS_NSS_10_11);
2099*5c1def83SBjoern A. Zeeb u32p_replace_bits(tx_mcs,
2100*5c1def83SBjoern A. Zeeb u8_get_bits(rx_tx_mcs13, IEEE80211_EHT_MCS_NSS_TX),
2101*5c1def83SBjoern A. Zeeb WMI_EHT_MCS_NSS_12_13);
2102*5c1def83SBjoern A. Zeeb }
2103*5c1def83SBjoern A. Zeeb
ath12k_mac_set_eht_ppe_threshold(const u8 * ppe_thres,struct ath12k_wmi_ppe_threshold_arg * ppet)2104*5c1def83SBjoern A. Zeeb static void ath12k_mac_set_eht_ppe_threshold(const u8 *ppe_thres,
2105*5c1def83SBjoern A. Zeeb struct ath12k_wmi_ppe_threshold_arg *ppet)
2106*5c1def83SBjoern A. Zeeb {
2107*5c1def83SBjoern A. Zeeb u32 bit_pos = IEEE80211_EHT_PPE_THRES_INFO_HEADER_SIZE, val;
2108*5c1def83SBjoern A. Zeeb u8 nss, ru, i;
2109*5c1def83SBjoern A. Zeeb u8 ppet_bit_len_per_ru = IEEE80211_EHT_PPE_THRES_INFO_PPET_SIZE * 2;
2110*5c1def83SBjoern A. Zeeb
2111*5c1def83SBjoern A. Zeeb ppet->numss_m1 = u8_get_bits(ppe_thres[0], IEEE80211_EHT_PPE_THRES_NSS_MASK);
2112*5c1def83SBjoern A. Zeeb ppet->ru_bit_mask = u16_get_bits(get_unaligned_le16(ppe_thres),
2113*5c1def83SBjoern A. Zeeb IEEE80211_EHT_PPE_THRES_RU_INDEX_BITMASK_MASK);
2114*5c1def83SBjoern A. Zeeb
2115*5c1def83SBjoern A. Zeeb for (nss = 0; nss <= ppet->numss_m1; nss++) {
2116*5c1def83SBjoern A. Zeeb for (ru = 0;
2117*5c1def83SBjoern A. Zeeb ru < hweight16(IEEE80211_EHT_PPE_THRES_RU_INDEX_BITMASK_MASK);
2118*5c1def83SBjoern A. Zeeb ru++) {
2119*5c1def83SBjoern A. Zeeb if ((ppet->ru_bit_mask & BIT(ru)) == 0)
2120*5c1def83SBjoern A. Zeeb continue;
2121*5c1def83SBjoern A. Zeeb
2122*5c1def83SBjoern A. Zeeb val = 0;
2123*5c1def83SBjoern A. Zeeb for (i = 0; i < ppet_bit_len_per_ru; i++) {
2124*5c1def83SBjoern A. Zeeb val |= (((ppe_thres[bit_pos / 8] >>
2125*5c1def83SBjoern A. Zeeb (bit_pos % 8)) & 0x1) << i);
2126*5c1def83SBjoern A. Zeeb bit_pos++;
2127*5c1def83SBjoern A. Zeeb }
2128*5c1def83SBjoern A. Zeeb ppet->ppet16_ppet8_ru3_ru0[nss] |=
2129*5c1def83SBjoern A. Zeeb (val << (ru * ppet_bit_len_per_ru));
2130*5c1def83SBjoern A. Zeeb }
2131*5c1def83SBjoern A. Zeeb }
2132*5c1def83SBjoern A. Zeeb }
2133*5c1def83SBjoern A. Zeeb
ath12k_peer_assoc_h_eht(struct ath12k * ar,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct ath12k_wmi_peer_assoc_arg * arg)2134*5c1def83SBjoern A. Zeeb static void ath12k_peer_assoc_h_eht(struct ath12k *ar,
2135*5c1def83SBjoern A. Zeeb struct ieee80211_vif *vif,
2136*5c1def83SBjoern A. Zeeb struct ieee80211_sta *sta,
2137*5c1def83SBjoern A. Zeeb struct ath12k_wmi_peer_assoc_arg *arg)
2138*5c1def83SBjoern A. Zeeb {
2139*5c1def83SBjoern A. Zeeb const struct ieee80211_sta_eht_cap *eht_cap = &sta->deflink.eht_cap;
2140*5c1def83SBjoern A. Zeeb const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap;
2141*5c1def83SBjoern A. Zeeb const struct ieee80211_eht_mcs_nss_supp_20mhz_only *bw_20;
2142*5c1def83SBjoern A. Zeeb const struct ieee80211_eht_mcs_nss_supp_bw *bw;
2143*5c1def83SBjoern A. Zeeb struct ath12k_vif *arvif = (struct ath12k_vif *)vif->drv_priv;
2144*5c1def83SBjoern A. Zeeb u32 *rx_mcs, *tx_mcs;
2145*5c1def83SBjoern A. Zeeb
2146*5c1def83SBjoern A. Zeeb if (!sta->deflink.he_cap.has_he || !eht_cap->has_eht)
2147*5c1def83SBjoern A. Zeeb return;
2148*5c1def83SBjoern A. Zeeb
2149*5c1def83SBjoern A. Zeeb arg->eht_flag = true;
2150*5c1def83SBjoern A. Zeeb
2151*5c1def83SBjoern A. Zeeb if ((eht_cap->eht_cap_elem.phy_cap_info[5] &
2152*5c1def83SBjoern A. Zeeb IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT) &&
2153*5c1def83SBjoern A. Zeeb eht_cap->eht_ppe_thres[0] != 0)
2154*5c1def83SBjoern A. Zeeb ath12k_mac_set_eht_ppe_threshold(eht_cap->eht_ppe_thres,
2155*5c1def83SBjoern A. Zeeb &arg->peer_eht_ppet);
2156*5c1def83SBjoern A. Zeeb
2157*5c1def83SBjoern A. Zeeb memcpy(arg->peer_eht_cap_mac, eht_cap->eht_cap_elem.mac_cap_info,
2158*5c1def83SBjoern A. Zeeb sizeof(eht_cap->eht_cap_elem.mac_cap_info));
2159*5c1def83SBjoern A. Zeeb memcpy(arg->peer_eht_cap_phy, eht_cap->eht_cap_elem.phy_cap_info,
2160*5c1def83SBjoern A. Zeeb sizeof(eht_cap->eht_cap_elem.phy_cap_info));
2161*5c1def83SBjoern A. Zeeb
2162*5c1def83SBjoern A. Zeeb rx_mcs = arg->peer_eht_rx_mcs_set;
2163*5c1def83SBjoern A. Zeeb tx_mcs = arg->peer_eht_tx_mcs_set;
2164*5c1def83SBjoern A. Zeeb
2165*5c1def83SBjoern A. Zeeb switch (sta->deflink.bandwidth) {
2166*5c1def83SBjoern A. Zeeb case IEEE80211_STA_RX_BW_320:
2167*5c1def83SBjoern A. Zeeb bw = &eht_cap->eht_mcs_nss_supp.bw._320;
2168*5c1def83SBjoern A. Zeeb ath12k_mac_set_eht_mcs(bw->rx_tx_mcs9_max_nss,
2169*5c1def83SBjoern A. Zeeb bw->rx_tx_mcs9_max_nss,
2170*5c1def83SBjoern A. Zeeb bw->rx_tx_mcs11_max_nss,
2171*5c1def83SBjoern A. Zeeb bw->rx_tx_mcs13_max_nss,
2172*5c1def83SBjoern A. Zeeb &rx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_320],
2173*5c1def83SBjoern A. Zeeb &tx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_320]);
2174*5c1def83SBjoern A. Zeeb arg->peer_eht_mcs_count++;
2175*5c1def83SBjoern A. Zeeb fallthrough;
2176*5c1def83SBjoern A. Zeeb case IEEE80211_STA_RX_BW_160:
2177*5c1def83SBjoern A. Zeeb bw = &eht_cap->eht_mcs_nss_supp.bw._160;
2178*5c1def83SBjoern A. Zeeb ath12k_mac_set_eht_mcs(bw->rx_tx_mcs9_max_nss,
2179*5c1def83SBjoern A. Zeeb bw->rx_tx_mcs9_max_nss,
2180*5c1def83SBjoern A. Zeeb bw->rx_tx_mcs11_max_nss,
2181*5c1def83SBjoern A. Zeeb bw->rx_tx_mcs13_max_nss,
2182*5c1def83SBjoern A. Zeeb &rx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_160],
2183*5c1def83SBjoern A. Zeeb &tx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_160]);
2184*5c1def83SBjoern A. Zeeb arg->peer_eht_mcs_count++;
2185*5c1def83SBjoern A. Zeeb fallthrough;
2186*5c1def83SBjoern A. Zeeb default:
2187*5c1def83SBjoern A. Zeeb if ((he_cap->he_cap_elem.phy_cap_info[0] &
2188*5c1def83SBjoern A. Zeeb (IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G |
2189*5c1def83SBjoern A. Zeeb IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |
2190*5c1def83SBjoern A. Zeeb IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G |
2191*5c1def83SBjoern A. Zeeb IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)) == 0) {
2192*5c1def83SBjoern A. Zeeb bw_20 = &eht_cap->eht_mcs_nss_supp.only_20mhz;
2193*5c1def83SBjoern A. Zeeb
2194*5c1def83SBjoern A. Zeeb ath12k_mac_set_eht_mcs(bw_20->rx_tx_mcs7_max_nss,
2195*5c1def83SBjoern A. Zeeb bw_20->rx_tx_mcs9_max_nss,
2196*5c1def83SBjoern A. Zeeb bw_20->rx_tx_mcs11_max_nss,
2197*5c1def83SBjoern A. Zeeb bw_20->rx_tx_mcs13_max_nss,
2198*5c1def83SBjoern A. Zeeb &rx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_80],
2199*5c1def83SBjoern A. Zeeb &tx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_80]);
2200*5c1def83SBjoern A. Zeeb } else {
2201*5c1def83SBjoern A. Zeeb bw = &eht_cap->eht_mcs_nss_supp.bw._80;
2202*5c1def83SBjoern A. Zeeb ath12k_mac_set_eht_mcs(bw->rx_tx_mcs9_max_nss,
2203*5c1def83SBjoern A. Zeeb bw->rx_tx_mcs9_max_nss,
2204*5c1def83SBjoern A. Zeeb bw->rx_tx_mcs11_max_nss,
2205*5c1def83SBjoern A. Zeeb bw->rx_tx_mcs13_max_nss,
2206*5c1def83SBjoern A. Zeeb &rx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_80],
2207*5c1def83SBjoern A. Zeeb &tx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_80]);
2208*5c1def83SBjoern A. Zeeb }
2209*5c1def83SBjoern A. Zeeb
2210*5c1def83SBjoern A. Zeeb arg->peer_eht_mcs_count++;
2211*5c1def83SBjoern A. Zeeb break;
2212*5c1def83SBjoern A. Zeeb }
2213*5c1def83SBjoern A. Zeeb
2214*5c1def83SBjoern A. Zeeb arg->punct_bitmap = ~arvif->punct_bitmap;
2215*5c1def83SBjoern A. Zeeb }
2216*5c1def83SBjoern A. Zeeb
ath12k_peer_assoc_prepare(struct ath12k * ar,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct ath12k_wmi_peer_assoc_arg * arg,bool reassoc)2217*5c1def83SBjoern A. Zeeb static void ath12k_peer_assoc_prepare(struct ath12k *ar,
2218*5c1def83SBjoern A. Zeeb struct ieee80211_vif *vif,
2219*5c1def83SBjoern A. Zeeb struct ieee80211_sta *sta,
2220*5c1def83SBjoern A. Zeeb struct ath12k_wmi_peer_assoc_arg *arg,
2221*5c1def83SBjoern A. Zeeb bool reassoc)
2222*5c1def83SBjoern A. Zeeb {
2223*5c1def83SBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
2224*5c1def83SBjoern A. Zeeb
2225*5c1def83SBjoern A. Zeeb memset(arg, 0, sizeof(*arg));
2226*5c1def83SBjoern A. Zeeb
2227*5c1def83SBjoern A. Zeeb reinit_completion(&ar->peer_assoc_done);
2228*5c1def83SBjoern A. Zeeb
2229*5c1def83SBjoern A. Zeeb arg->peer_new_assoc = !reassoc;
2230*5c1def83SBjoern A. Zeeb ath12k_peer_assoc_h_basic(ar, vif, sta, arg);
2231*5c1def83SBjoern A. Zeeb ath12k_peer_assoc_h_crypto(ar, vif, sta, arg);
2232*5c1def83SBjoern A. Zeeb ath12k_peer_assoc_h_rates(ar, vif, sta, arg);
2233*5c1def83SBjoern A. Zeeb ath12k_peer_assoc_h_ht(ar, vif, sta, arg);
2234*5c1def83SBjoern A. Zeeb ath12k_peer_assoc_h_vht(ar, vif, sta, arg);
2235*5c1def83SBjoern A. Zeeb ath12k_peer_assoc_h_he(ar, vif, sta, arg);
2236*5c1def83SBjoern A. Zeeb ath12k_peer_assoc_h_eht(ar, vif, sta, arg);
2237*5c1def83SBjoern A. Zeeb ath12k_peer_assoc_h_qos(ar, vif, sta, arg);
2238*5c1def83SBjoern A. Zeeb ath12k_peer_assoc_h_phymode(ar, vif, sta, arg);
2239*5c1def83SBjoern A. Zeeb ath12k_peer_assoc_h_smps(sta, arg);
2240*5c1def83SBjoern A. Zeeb
2241*5c1def83SBjoern A. Zeeb /* TODO: amsdu_disable req? */
2242*5c1def83SBjoern A. Zeeb }
2243*5c1def83SBjoern A. Zeeb
ath12k_setup_peer_smps(struct ath12k * ar,struct ath12k_vif * arvif,const u8 * addr,const struct ieee80211_sta_ht_cap * ht_cap)2244*5c1def83SBjoern A. Zeeb static int ath12k_setup_peer_smps(struct ath12k *ar, struct ath12k_vif *arvif,
2245*5c1def83SBjoern A. Zeeb const u8 *addr,
2246*5c1def83SBjoern A. Zeeb const struct ieee80211_sta_ht_cap *ht_cap)
2247*5c1def83SBjoern A. Zeeb {
2248*5c1def83SBjoern A. Zeeb int smps;
2249*5c1def83SBjoern A. Zeeb
2250*5c1def83SBjoern A. Zeeb if (!ht_cap->ht_supported)
2251*5c1def83SBjoern A. Zeeb return 0;
2252*5c1def83SBjoern A. Zeeb
2253*5c1def83SBjoern A. Zeeb smps = ht_cap->cap & IEEE80211_HT_CAP_SM_PS;
2254*5c1def83SBjoern A. Zeeb smps >>= IEEE80211_HT_CAP_SM_PS_SHIFT;
2255*5c1def83SBjoern A. Zeeb
2256*5c1def83SBjoern A. Zeeb if (smps >= ARRAY_SIZE(ath12k_smps_map))
2257*5c1def83SBjoern A. Zeeb return -EINVAL;
2258*5c1def83SBjoern A. Zeeb
2259*5c1def83SBjoern A. Zeeb return ath12k_wmi_set_peer_param(ar, addr, arvif->vdev_id,
2260*5c1def83SBjoern A. Zeeb WMI_PEER_MIMO_PS_STATE,
2261*5c1def83SBjoern A. Zeeb ath12k_smps_map[smps]);
2262*5c1def83SBjoern A. Zeeb }
2263*5c1def83SBjoern A. Zeeb
ath12k_bss_assoc(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_bss_conf * bss_conf)2264*5c1def83SBjoern A. Zeeb static void ath12k_bss_assoc(struct ieee80211_hw *hw,
2265*5c1def83SBjoern A. Zeeb struct ieee80211_vif *vif,
2266*5c1def83SBjoern A. Zeeb struct ieee80211_bss_conf *bss_conf)
2267*5c1def83SBjoern A. Zeeb {
2268*5c1def83SBjoern A. Zeeb struct ath12k *ar = hw->priv;
2269*5c1def83SBjoern A. Zeeb struct ath12k_vif *arvif = (void *)vif->drv_priv;
2270*5c1def83SBjoern A. Zeeb struct ath12k_wmi_peer_assoc_arg peer_arg;
2271*5c1def83SBjoern A. Zeeb struct ieee80211_sta *ap_sta;
2272*5c1def83SBjoern A. Zeeb struct ath12k_peer *peer;
2273*5c1def83SBjoern A. Zeeb bool is_auth = false;
2274*5c1def83SBjoern A. Zeeb int ret;
2275*5c1def83SBjoern A. Zeeb
2276*5c1def83SBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
2277*5c1def83SBjoern A. Zeeb
2278*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev %i assoc bssid %pM aid %d\n",
2279*5c1def83SBjoern A. Zeeb arvif->vdev_id, arvif->bssid, arvif->aid);
2280*5c1def83SBjoern A. Zeeb
2281*5c1def83SBjoern A. Zeeb rcu_read_lock();
2282*5c1def83SBjoern A. Zeeb
2283*5c1def83SBjoern A. Zeeb ap_sta = ieee80211_find_sta(vif, bss_conf->bssid);
2284*5c1def83SBjoern A. Zeeb if (!ap_sta) {
2285*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to find station entry for bss %pM vdev %i\n",
2286*5c1def83SBjoern A. Zeeb bss_conf->bssid, arvif->vdev_id);
2287*5c1def83SBjoern A. Zeeb rcu_read_unlock();
2288*5c1def83SBjoern A. Zeeb return;
2289*5c1def83SBjoern A. Zeeb }
2290*5c1def83SBjoern A. Zeeb
2291*5c1def83SBjoern A. Zeeb ath12k_peer_assoc_prepare(ar, vif, ap_sta, &peer_arg, false);
2292*5c1def83SBjoern A. Zeeb
2293*5c1def83SBjoern A. Zeeb rcu_read_unlock();
2294*5c1def83SBjoern A. Zeeb
2295*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_send_peer_assoc_cmd(ar, &peer_arg);
2296*5c1def83SBjoern A. Zeeb if (ret) {
2297*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to run peer assoc for %pM vdev %i: %d\n",
2298*5c1def83SBjoern A. Zeeb bss_conf->bssid, arvif->vdev_id, ret);
2299*5c1def83SBjoern A. Zeeb return;
2300*5c1def83SBjoern A. Zeeb }
2301*5c1def83SBjoern A. Zeeb
2302*5c1def83SBjoern A. Zeeb if (!wait_for_completion_timeout(&ar->peer_assoc_done, 1 * HZ)) {
2303*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to get peer assoc conf event for %pM vdev %i\n",
2304*5c1def83SBjoern A. Zeeb bss_conf->bssid, arvif->vdev_id);
2305*5c1def83SBjoern A. Zeeb return;
2306*5c1def83SBjoern A. Zeeb }
2307*5c1def83SBjoern A. Zeeb
2308*5c1def83SBjoern A. Zeeb ret = ath12k_setup_peer_smps(ar, arvif, bss_conf->bssid,
2309*5c1def83SBjoern A. Zeeb &ap_sta->deflink.ht_cap);
2310*5c1def83SBjoern A. Zeeb if (ret) {
2311*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to setup peer SMPS for vdev %d: %d\n",
2312*5c1def83SBjoern A. Zeeb arvif->vdev_id, ret);
2313*5c1def83SBjoern A. Zeeb return;
2314*5c1def83SBjoern A. Zeeb }
2315*5c1def83SBjoern A. Zeeb
2316*5c1def83SBjoern A. Zeeb WARN_ON(arvif->is_up);
2317*5c1def83SBjoern A. Zeeb
2318*5c1def83SBjoern A. Zeeb arvif->aid = vif->cfg.aid;
2319*5c1def83SBjoern A. Zeeb ether_addr_copy(arvif->bssid, bss_conf->bssid);
2320*5c1def83SBjoern A. Zeeb
2321*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_up(ar, arvif->vdev_id, arvif->aid, arvif->bssid);
2322*5c1def83SBjoern A. Zeeb if (ret) {
2323*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to set vdev %d up: %d\n",
2324*5c1def83SBjoern A. Zeeb arvif->vdev_id, ret);
2325*5c1def83SBjoern A. Zeeb return;
2326*5c1def83SBjoern A. Zeeb }
2327*5c1def83SBjoern A. Zeeb
2328*5c1def83SBjoern A. Zeeb arvif->is_up = true;
2329*5c1def83SBjoern A. Zeeb
2330*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
2331*5c1def83SBjoern A. Zeeb "mac vdev %d up (associated) bssid %pM aid %d\n",
2332*5c1def83SBjoern A. Zeeb arvif->vdev_id, bss_conf->bssid, vif->cfg.aid);
2333*5c1def83SBjoern A. Zeeb
2334*5c1def83SBjoern A. Zeeb spin_lock_bh(&ar->ab->base_lock);
2335*5c1def83SBjoern A. Zeeb
2336*5c1def83SBjoern A. Zeeb peer = ath12k_peer_find(ar->ab, arvif->vdev_id, arvif->bssid);
2337*5c1def83SBjoern A. Zeeb if (peer && peer->is_authorized)
2338*5c1def83SBjoern A. Zeeb is_auth = true;
2339*5c1def83SBjoern A. Zeeb
2340*5c1def83SBjoern A. Zeeb spin_unlock_bh(&ar->ab->base_lock);
2341*5c1def83SBjoern A. Zeeb
2342*5c1def83SBjoern A. Zeeb /* Authorize BSS Peer */
2343*5c1def83SBjoern A. Zeeb if (is_auth) {
2344*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_set_peer_param(ar, arvif->bssid,
2345*5c1def83SBjoern A. Zeeb arvif->vdev_id,
2346*5c1def83SBjoern A. Zeeb WMI_PEER_AUTHORIZE,
2347*5c1def83SBjoern A. Zeeb 1);
2348*5c1def83SBjoern A. Zeeb if (ret)
2349*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "Unable to authorize BSS peer: %d\n", ret);
2350*5c1def83SBjoern A. Zeeb }
2351*5c1def83SBjoern A. Zeeb
2352*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_send_obss_spr_cmd(ar, arvif->vdev_id,
2353*5c1def83SBjoern A. Zeeb &bss_conf->he_obss_pd);
2354*5c1def83SBjoern A. Zeeb if (ret)
2355*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to set vdev %i OBSS PD parameters: %d\n",
2356*5c1def83SBjoern A. Zeeb arvif->vdev_id, ret);
2357*5c1def83SBjoern A. Zeeb }
2358*5c1def83SBjoern A. Zeeb
ath12k_bss_disassoc(struct ieee80211_hw * hw,struct ieee80211_vif * vif)2359*5c1def83SBjoern A. Zeeb static void ath12k_bss_disassoc(struct ieee80211_hw *hw,
2360*5c1def83SBjoern A. Zeeb struct ieee80211_vif *vif)
2361*5c1def83SBjoern A. Zeeb {
2362*5c1def83SBjoern A. Zeeb struct ath12k *ar = hw->priv;
2363*5c1def83SBjoern A. Zeeb struct ath12k_vif *arvif = (void *)vif->drv_priv;
2364*5c1def83SBjoern A. Zeeb int ret;
2365*5c1def83SBjoern A. Zeeb
2366*5c1def83SBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
2367*5c1def83SBjoern A. Zeeb
2368*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev %i disassoc bssid %pM\n",
2369*5c1def83SBjoern A. Zeeb arvif->vdev_id, arvif->bssid);
2370*5c1def83SBjoern A. Zeeb
2371*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_down(ar, arvif->vdev_id);
2372*5c1def83SBjoern A. Zeeb if (ret)
2373*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to down vdev %i: %d\n",
2374*5c1def83SBjoern A. Zeeb arvif->vdev_id, ret);
2375*5c1def83SBjoern A. Zeeb
2376*5c1def83SBjoern A. Zeeb arvif->is_up = false;
2377*5c1def83SBjoern A. Zeeb
2378*5c1def83SBjoern A. Zeeb /* TODO: cancel connection_loss_work */
2379*5c1def83SBjoern A. Zeeb }
2380*5c1def83SBjoern A. Zeeb
ath12k_mac_get_rate_hw_value(int bitrate)2381*5c1def83SBjoern A. Zeeb static u32 ath12k_mac_get_rate_hw_value(int bitrate)
2382*5c1def83SBjoern A. Zeeb {
2383*5c1def83SBjoern A. Zeeb u32 preamble;
2384*5c1def83SBjoern A. Zeeb u16 hw_value;
2385*5c1def83SBjoern A. Zeeb int rate;
2386*5c1def83SBjoern A. Zeeb size_t i;
2387*5c1def83SBjoern A. Zeeb
2388*5c1def83SBjoern A. Zeeb if (ath12k_mac_bitrate_is_cck(bitrate))
2389*5c1def83SBjoern A. Zeeb preamble = WMI_RATE_PREAMBLE_CCK;
2390*5c1def83SBjoern A. Zeeb else
2391*5c1def83SBjoern A. Zeeb preamble = WMI_RATE_PREAMBLE_OFDM;
2392*5c1def83SBjoern A. Zeeb
2393*5c1def83SBjoern A. Zeeb for (i = 0; i < ARRAY_SIZE(ath12k_legacy_rates); i++) {
2394*5c1def83SBjoern A. Zeeb if (ath12k_legacy_rates[i].bitrate != bitrate)
2395*5c1def83SBjoern A. Zeeb continue;
2396*5c1def83SBjoern A. Zeeb
2397*5c1def83SBjoern A. Zeeb hw_value = ath12k_legacy_rates[i].hw_value;
2398*5c1def83SBjoern A. Zeeb rate = ATH12K_HW_RATE_CODE(hw_value, 0, preamble);
2399*5c1def83SBjoern A. Zeeb
2400*5c1def83SBjoern A. Zeeb return rate;
2401*5c1def83SBjoern A. Zeeb }
2402*5c1def83SBjoern A. Zeeb
2403*5c1def83SBjoern A. Zeeb return -EINVAL;
2404*5c1def83SBjoern A. Zeeb }
2405*5c1def83SBjoern A. Zeeb
ath12k_recalculate_mgmt_rate(struct ath12k * ar,struct ieee80211_vif * vif,struct cfg80211_chan_def * def)2406*5c1def83SBjoern A. Zeeb static void ath12k_recalculate_mgmt_rate(struct ath12k *ar,
2407*5c1def83SBjoern A. Zeeb struct ieee80211_vif *vif,
2408*5c1def83SBjoern A. Zeeb struct cfg80211_chan_def *def)
2409*5c1def83SBjoern A. Zeeb {
2410*5c1def83SBjoern A. Zeeb struct ath12k_vif *arvif = (void *)vif->drv_priv;
2411*5c1def83SBjoern A. Zeeb const struct ieee80211_supported_band *sband;
2412*5c1def83SBjoern A. Zeeb u8 basic_rate_idx;
2413*5c1def83SBjoern A. Zeeb int hw_rate_code;
2414*5c1def83SBjoern A. Zeeb u32 vdev_param;
2415*5c1def83SBjoern A. Zeeb u16 bitrate;
2416*5c1def83SBjoern A. Zeeb int ret;
2417*5c1def83SBjoern A. Zeeb
2418*5c1def83SBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
2419*5c1def83SBjoern A. Zeeb
2420*5c1def83SBjoern A. Zeeb sband = ar->hw->wiphy->bands[def->chan->band];
2421*5c1def83SBjoern A. Zeeb basic_rate_idx = ffs(vif->bss_conf.basic_rates) - 1;
2422*5c1def83SBjoern A. Zeeb bitrate = sband->bitrates[basic_rate_idx].bitrate;
2423*5c1def83SBjoern A. Zeeb
2424*5c1def83SBjoern A. Zeeb hw_rate_code = ath12k_mac_get_rate_hw_value(bitrate);
2425*5c1def83SBjoern A. Zeeb if (hw_rate_code < 0) {
2426*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "bitrate not supported %d\n", bitrate);
2427*5c1def83SBjoern A. Zeeb return;
2428*5c1def83SBjoern A. Zeeb }
2429*5c1def83SBjoern A. Zeeb
2430*5c1def83SBjoern A. Zeeb vdev_param = WMI_VDEV_PARAM_MGMT_RATE;
2431*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, vdev_param,
2432*5c1def83SBjoern A. Zeeb hw_rate_code);
2433*5c1def83SBjoern A. Zeeb if (ret)
2434*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to set mgmt tx rate %d\n", ret);
2435*5c1def83SBjoern A. Zeeb
2436*5c1def83SBjoern A. Zeeb vdev_param = WMI_VDEV_PARAM_BEACON_RATE;
2437*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, vdev_param,
2438*5c1def83SBjoern A. Zeeb hw_rate_code);
2439*5c1def83SBjoern A. Zeeb if (ret)
2440*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to set beacon tx rate %d\n", ret);
2441*5c1def83SBjoern A. Zeeb }
2442*5c1def83SBjoern A. Zeeb
ath12k_mac_fils_discovery(struct ath12k_vif * arvif,struct ieee80211_bss_conf * info)2443*5c1def83SBjoern A. Zeeb static int ath12k_mac_fils_discovery(struct ath12k_vif *arvif,
2444*5c1def83SBjoern A. Zeeb struct ieee80211_bss_conf *info)
2445*5c1def83SBjoern A. Zeeb {
2446*5c1def83SBjoern A. Zeeb struct ath12k *ar = arvif->ar;
2447*5c1def83SBjoern A. Zeeb struct sk_buff *tmpl;
2448*5c1def83SBjoern A. Zeeb int ret;
2449*5c1def83SBjoern A. Zeeb u32 interval;
2450*5c1def83SBjoern A. Zeeb bool unsol_bcast_probe_resp_enabled = false;
2451*5c1def83SBjoern A. Zeeb
2452*5c1def83SBjoern A. Zeeb if (info->fils_discovery.max_interval) {
2453*5c1def83SBjoern A. Zeeb interval = info->fils_discovery.max_interval;
2454*5c1def83SBjoern A. Zeeb
2455*5c1def83SBjoern A. Zeeb tmpl = ieee80211_get_fils_discovery_tmpl(ar->hw, arvif->vif);
2456*5c1def83SBjoern A. Zeeb if (tmpl)
2457*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_fils_discovery_tmpl(ar, arvif->vdev_id,
2458*5c1def83SBjoern A. Zeeb tmpl);
2459*5c1def83SBjoern A. Zeeb } else if (info->unsol_bcast_probe_resp_interval) {
2460*5c1def83SBjoern A. Zeeb unsol_bcast_probe_resp_enabled = 1;
2461*5c1def83SBjoern A. Zeeb interval = info->unsol_bcast_probe_resp_interval;
2462*5c1def83SBjoern A. Zeeb
2463*5c1def83SBjoern A. Zeeb tmpl = ieee80211_get_unsol_bcast_probe_resp_tmpl(ar->hw,
2464*5c1def83SBjoern A. Zeeb arvif->vif);
2465*5c1def83SBjoern A. Zeeb if (tmpl)
2466*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_probe_resp_tmpl(ar, arvif->vdev_id,
2467*5c1def83SBjoern A. Zeeb tmpl);
2468*5c1def83SBjoern A. Zeeb } else { /* Disable */
2469*5c1def83SBjoern A. Zeeb return ath12k_wmi_fils_discovery(ar, arvif->vdev_id, 0, false);
2470*5c1def83SBjoern A. Zeeb }
2471*5c1def83SBjoern A. Zeeb
2472*5c1def83SBjoern A. Zeeb if (!tmpl) {
2473*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab,
2474*5c1def83SBjoern A. Zeeb "mac vdev %i failed to retrieve %s template\n",
2475*5c1def83SBjoern A. Zeeb arvif->vdev_id, (unsol_bcast_probe_resp_enabled ?
2476*5c1def83SBjoern A. Zeeb "unsolicited broadcast probe response" :
2477*5c1def83SBjoern A. Zeeb "FILS discovery"));
2478*5c1def83SBjoern A. Zeeb return -EPERM;
2479*5c1def83SBjoern A. Zeeb }
2480*5c1def83SBjoern A. Zeeb kfree_skb(tmpl);
2481*5c1def83SBjoern A. Zeeb
2482*5c1def83SBjoern A. Zeeb if (!ret)
2483*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_fils_discovery(ar, arvif->vdev_id, interval,
2484*5c1def83SBjoern A. Zeeb unsol_bcast_probe_resp_enabled);
2485*5c1def83SBjoern A. Zeeb
2486*5c1def83SBjoern A. Zeeb return ret;
2487*5c1def83SBjoern A. Zeeb }
2488*5c1def83SBjoern A. Zeeb
ath12k_mac_op_bss_info_changed(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_bss_conf * info,u64 changed)2489*5c1def83SBjoern A. Zeeb static void ath12k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
2490*5c1def83SBjoern A. Zeeb struct ieee80211_vif *vif,
2491*5c1def83SBjoern A. Zeeb struct ieee80211_bss_conf *info,
2492*5c1def83SBjoern A. Zeeb u64 changed)
2493*5c1def83SBjoern A. Zeeb {
2494*5c1def83SBjoern A. Zeeb struct ath12k *ar = hw->priv;
2495*5c1def83SBjoern A. Zeeb struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
2496*5c1def83SBjoern A. Zeeb struct cfg80211_chan_def def;
2497*5c1def83SBjoern A. Zeeb u32 param_id, param_value;
2498*5c1def83SBjoern A. Zeeb enum nl80211_band band;
2499*5c1def83SBjoern A. Zeeb u32 vdev_param;
2500*5c1def83SBjoern A. Zeeb int mcast_rate;
2501*5c1def83SBjoern A. Zeeb u32 preamble;
2502*5c1def83SBjoern A. Zeeb u16 hw_value;
2503*5c1def83SBjoern A. Zeeb u16 bitrate;
2504*5c1def83SBjoern A. Zeeb int ret;
2505*5c1def83SBjoern A. Zeeb u8 rateidx;
2506*5c1def83SBjoern A. Zeeb u32 rate;
2507*5c1def83SBjoern A. Zeeb
2508*5c1def83SBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
2509*5c1def83SBjoern A. Zeeb
2510*5c1def83SBjoern A. Zeeb if (changed & BSS_CHANGED_BEACON_INT) {
2511*5c1def83SBjoern A. Zeeb arvif->beacon_interval = info->beacon_int;
2512*5c1def83SBjoern A. Zeeb
2513*5c1def83SBjoern A. Zeeb param_id = WMI_VDEV_PARAM_BEACON_INTERVAL;
2514*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
2515*5c1def83SBjoern A. Zeeb param_id,
2516*5c1def83SBjoern A. Zeeb arvif->beacon_interval);
2517*5c1def83SBjoern A. Zeeb if (ret)
2518*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "Failed to set beacon interval for VDEV: %d\n",
2519*5c1def83SBjoern A. Zeeb arvif->vdev_id);
2520*5c1def83SBjoern A. Zeeb else
2521*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
2522*5c1def83SBjoern A. Zeeb "Beacon interval: %d set for VDEV: %d\n",
2523*5c1def83SBjoern A. Zeeb arvif->beacon_interval, arvif->vdev_id);
2524*5c1def83SBjoern A. Zeeb }
2525*5c1def83SBjoern A. Zeeb
2526*5c1def83SBjoern A. Zeeb if (changed & BSS_CHANGED_BEACON) {
2527*5c1def83SBjoern A. Zeeb param_id = WMI_PDEV_PARAM_BEACON_TX_MODE;
2528*5c1def83SBjoern A. Zeeb param_value = WMI_BEACON_STAGGERED_MODE;
2529*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_pdev_set_param(ar, param_id,
2530*5c1def83SBjoern A. Zeeb param_value, ar->pdev->pdev_id);
2531*5c1def83SBjoern A. Zeeb if (ret)
2532*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "Failed to set beacon mode for VDEV: %d\n",
2533*5c1def83SBjoern A. Zeeb arvif->vdev_id);
2534*5c1def83SBjoern A. Zeeb else
2535*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
2536*5c1def83SBjoern A. Zeeb "Set staggered beacon mode for VDEV: %d\n",
2537*5c1def83SBjoern A. Zeeb arvif->vdev_id);
2538*5c1def83SBjoern A. Zeeb
2539*5c1def83SBjoern A. Zeeb ret = ath12k_mac_setup_bcn_tmpl(arvif);
2540*5c1def83SBjoern A. Zeeb if (ret)
2541*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to update bcn template: %d\n",
2542*5c1def83SBjoern A. Zeeb ret);
2543*5c1def83SBjoern A. Zeeb }
2544*5c1def83SBjoern A. Zeeb
2545*5c1def83SBjoern A. Zeeb if (changed & (BSS_CHANGED_BEACON_INFO | BSS_CHANGED_BEACON)) {
2546*5c1def83SBjoern A. Zeeb arvif->dtim_period = info->dtim_period;
2547*5c1def83SBjoern A. Zeeb
2548*5c1def83SBjoern A. Zeeb param_id = WMI_VDEV_PARAM_DTIM_PERIOD;
2549*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
2550*5c1def83SBjoern A. Zeeb param_id,
2551*5c1def83SBjoern A. Zeeb arvif->dtim_period);
2552*5c1def83SBjoern A. Zeeb
2553*5c1def83SBjoern A. Zeeb if (ret)
2554*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "Failed to set dtim period for VDEV %d: %i\n",
2555*5c1def83SBjoern A. Zeeb arvif->vdev_id, ret);
2556*5c1def83SBjoern A. Zeeb else
2557*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
2558*5c1def83SBjoern A. Zeeb "DTIM period: %d set for VDEV: %d\n",
2559*5c1def83SBjoern A. Zeeb arvif->dtim_period, arvif->vdev_id);
2560*5c1def83SBjoern A. Zeeb }
2561*5c1def83SBjoern A. Zeeb
2562*5c1def83SBjoern A. Zeeb if (changed & BSS_CHANGED_SSID &&
2563*5c1def83SBjoern A. Zeeb vif->type == NL80211_IFTYPE_AP) {
2564*5c1def83SBjoern A. Zeeb arvif->u.ap.ssid_len = vif->cfg.ssid_len;
2565*5c1def83SBjoern A. Zeeb if (vif->cfg.ssid_len)
2566*5c1def83SBjoern A. Zeeb memcpy(arvif->u.ap.ssid, vif->cfg.ssid, vif->cfg.ssid_len);
2567*5c1def83SBjoern A. Zeeb arvif->u.ap.hidden_ssid = info->hidden_ssid;
2568*5c1def83SBjoern A. Zeeb }
2569*5c1def83SBjoern A. Zeeb
2570*5c1def83SBjoern A. Zeeb if (changed & BSS_CHANGED_BSSID && !is_zero_ether_addr(info->bssid))
2571*5c1def83SBjoern A. Zeeb ether_addr_copy(arvif->bssid, info->bssid);
2572*5c1def83SBjoern A. Zeeb
2573*5c1def83SBjoern A. Zeeb if (changed & BSS_CHANGED_BEACON_ENABLED) {
2574*5c1def83SBjoern A. Zeeb ath12k_control_beaconing(arvif, info);
2575*5c1def83SBjoern A. Zeeb
2576*5c1def83SBjoern A. Zeeb if (arvif->is_up && vif->bss_conf.he_support &&
2577*5c1def83SBjoern A. Zeeb vif->bss_conf.he_oper.params) {
2578*5c1def83SBjoern A. Zeeb /* TODO: Extend to support 1024 BA Bitmap size */
2579*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
2580*5c1def83SBjoern A. Zeeb WMI_VDEV_PARAM_BA_MODE,
2581*5c1def83SBjoern A. Zeeb WMI_BA_MODE_BUFFER_SIZE_256);
2582*5c1def83SBjoern A. Zeeb if (ret)
2583*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab,
2584*5c1def83SBjoern A. Zeeb "failed to set BA BUFFER SIZE 256 for vdev: %d\n",
2585*5c1def83SBjoern A. Zeeb arvif->vdev_id);
2586*5c1def83SBjoern A. Zeeb
2587*5c1def83SBjoern A. Zeeb param_id = WMI_VDEV_PARAM_HEOPS_0_31;
2588*5c1def83SBjoern A. Zeeb param_value = vif->bss_conf.he_oper.params;
2589*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
2590*5c1def83SBjoern A. Zeeb param_id, param_value);
2591*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
2592*5c1def83SBjoern A. Zeeb "he oper param: %x set for VDEV: %d\n",
2593*5c1def83SBjoern A. Zeeb param_value, arvif->vdev_id);
2594*5c1def83SBjoern A. Zeeb
2595*5c1def83SBjoern A. Zeeb if (ret)
2596*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "Failed to set he oper params %x for VDEV %d: %i\n",
2597*5c1def83SBjoern A. Zeeb param_value, arvif->vdev_id, ret);
2598*5c1def83SBjoern A. Zeeb }
2599*5c1def83SBjoern A. Zeeb }
2600*5c1def83SBjoern A. Zeeb
2601*5c1def83SBjoern A. Zeeb if (changed & BSS_CHANGED_ERP_CTS_PROT) {
2602*5c1def83SBjoern A. Zeeb u32 cts_prot;
2603*5c1def83SBjoern A. Zeeb
2604*5c1def83SBjoern A. Zeeb cts_prot = !!(info->use_cts_prot);
2605*5c1def83SBjoern A. Zeeb param_id = WMI_VDEV_PARAM_PROTECTION_MODE;
2606*5c1def83SBjoern A. Zeeb
2607*5c1def83SBjoern A. Zeeb if (arvif->is_started) {
2608*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
2609*5c1def83SBjoern A. Zeeb param_id, cts_prot);
2610*5c1def83SBjoern A. Zeeb if (ret)
2611*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "Failed to set CTS prot for VDEV: %d\n",
2612*5c1def83SBjoern A. Zeeb arvif->vdev_id);
2613*5c1def83SBjoern A. Zeeb else
2614*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "Set CTS prot: %d for VDEV: %d\n",
2615*5c1def83SBjoern A. Zeeb cts_prot, arvif->vdev_id);
2616*5c1def83SBjoern A. Zeeb } else {
2617*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "defer protection mode setup, vdev is not ready yet\n");
2618*5c1def83SBjoern A. Zeeb }
2619*5c1def83SBjoern A. Zeeb }
2620*5c1def83SBjoern A. Zeeb
2621*5c1def83SBjoern A. Zeeb if (changed & BSS_CHANGED_ERP_SLOT) {
2622*5c1def83SBjoern A. Zeeb u32 slottime;
2623*5c1def83SBjoern A. Zeeb
2624*5c1def83SBjoern A. Zeeb if (info->use_short_slot)
2625*5c1def83SBjoern A. Zeeb slottime = WMI_VDEV_SLOT_TIME_SHORT; /* 9us */
2626*5c1def83SBjoern A. Zeeb
2627*5c1def83SBjoern A. Zeeb else
2628*5c1def83SBjoern A. Zeeb slottime = WMI_VDEV_SLOT_TIME_LONG; /* 20us */
2629*5c1def83SBjoern A. Zeeb
2630*5c1def83SBjoern A. Zeeb param_id = WMI_VDEV_PARAM_SLOT_TIME;
2631*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
2632*5c1def83SBjoern A. Zeeb param_id, slottime);
2633*5c1def83SBjoern A. Zeeb if (ret)
2634*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "Failed to set erp slot for VDEV: %d\n",
2635*5c1def83SBjoern A. Zeeb arvif->vdev_id);
2636*5c1def83SBjoern A. Zeeb else
2637*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
2638*5c1def83SBjoern A. Zeeb "Set slottime: %d for VDEV: %d\n",
2639*5c1def83SBjoern A. Zeeb slottime, arvif->vdev_id);
2640*5c1def83SBjoern A. Zeeb }
2641*5c1def83SBjoern A. Zeeb
2642*5c1def83SBjoern A. Zeeb if (changed & BSS_CHANGED_ERP_PREAMBLE) {
2643*5c1def83SBjoern A. Zeeb u32 preamble;
2644*5c1def83SBjoern A. Zeeb
2645*5c1def83SBjoern A. Zeeb if (info->use_short_preamble)
2646*5c1def83SBjoern A. Zeeb preamble = WMI_VDEV_PREAMBLE_SHORT;
2647*5c1def83SBjoern A. Zeeb else
2648*5c1def83SBjoern A. Zeeb preamble = WMI_VDEV_PREAMBLE_LONG;
2649*5c1def83SBjoern A. Zeeb
2650*5c1def83SBjoern A. Zeeb param_id = WMI_VDEV_PARAM_PREAMBLE;
2651*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
2652*5c1def83SBjoern A. Zeeb param_id, preamble);
2653*5c1def83SBjoern A. Zeeb if (ret)
2654*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "Failed to set preamble for VDEV: %d\n",
2655*5c1def83SBjoern A. Zeeb arvif->vdev_id);
2656*5c1def83SBjoern A. Zeeb else
2657*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
2658*5c1def83SBjoern A. Zeeb "Set preamble: %d for VDEV: %d\n",
2659*5c1def83SBjoern A. Zeeb preamble, arvif->vdev_id);
2660*5c1def83SBjoern A. Zeeb }
2661*5c1def83SBjoern A. Zeeb
2662*5c1def83SBjoern A. Zeeb if (changed & BSS_CHANGED_ASSOC) {
2663*5c1def83SBjoern A. Zeeb if (vif->cfg.assoc)
2664*5c1def83SBjoern A. Zeeb ath12k_bss_assoc(hw, vif, info);
2665*5c1def83SBjoern A. Zeeb else
2666*5c1def83SBjoern A. Zeeb ath12k_bss_disassoc(hw, vif);
2667*5c1def83SBjoern A. Zeeb }
2668*5c1def83SBjoern A. Zeeb
2669*5c1def83SBjoern A. Zeeb if (changed & BSS_CHANGED_TXPOWER) {
2670*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev_id %i txpower %d\n",
2671*5c1def83SBjoern A. Zeeb arvif->vdev_id, info->txpower);
2672*5c1def83SBjoern A. Zeeb
2673*5c1def83SBjoern A. Zeeb arvif->txpower = info->txpower;
2674*5c1def83SBjoern A. Zeeb ath12k_mac_txpower_recalc(ar);
2675*5c1def83SBjoern A. Zeeb }
2676*5c1def83SBjoern A. Zeeb
2677*5c1def83SBjoern A. Zeeb if (changed & BSS_CHANGED_MCAST_RATE &&
2678*5c1def83SBjoern A. Zeeb !ath12k_mac_vif_chan(arvif->vif, &def)) {
2679*5c1def83SBjoern A. Zeeb band = def.chan->band;
2680*5c1def83SBjoern A. Zeeb mcast_rate = vif->bss_conf.mcast_rate[band];
2681*5c1def83SBjoern A. Zeeb
2682*5c1def83SBjoern A. Zeeb if (mcast_rate > 0)
2683*5c1def83SBjoern A. Zeeb rateidx = mcast_rate - 1;
2684*5c1def83SBjoern A. Zeeb else
2685*5c1def83SBjoern A. Zeeb rateidx = ffs(vif->bss_conf.basic_rates) - 1;
2686*5c1def83SBjoern A. Zeeb
2687*5c1def83SBjoern A. Zeeb if (ar->pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP)
2688*5c1def83SBjoern A. Zeeb rateidx += ATH12K_MAC_FIRST_OFDM_RATE_IDX;
2689*5c1def83SBjoern A. Zeeb
2690*5c1def83SBjoern A. Zeeb bitrate = ath12k_legacy_rates[rateidx].bitrate;
2691*5c1def83SBjoern A. Zeeb hw_value = ath12k_legacy_rates[rateidx].hw_value;
2692*5c1def83SBjoern A. Zeeb
2693*5c1def83SBjoern A. Zeeb if (ath12k_mac_bitrate_is_cck(bitrate))
2694*5c1def83SBjoern A. Zeeb preamble = WMI_RATE_PREAMBLE_CCK;
2695*5c1def83SBjoern A. Zeeb else
2696*5c1def83SBjoern A. Zeeb preamble = WMI_RATE_PREAMBLE_OFDM;
2697*5c1def83SBjoern A. Zeeb
2698*5c1def83SBjoern A. Zeeb rate = ATH12K_HW_RATE_CODE(hw_value, 0, preamble);
2699*5c1def83SBjoern A. Zeeb
2700*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
2701*5c1def83SBjoern A. Zeeb "mac vdev %d mcast_rate %x\n",
2702*5c1def83SBjoern A. Zeeb arvif->vdev_id, rate);
2703*5c1def83SBjoern A. Zeeb
2704*5c1def83SBjoern A. Zeeb vdev_param = WMI_VDEV_PARAM_MCAST_DATA_RATE;
2705*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
2706*5c1def83SBjoern A. Zeeb vdev_param, rate);
2707*5c1def83SBjoern A. Zeeb if (ret)
2708*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab,
2709*5c1def83SBjoern A. Zeeb "failed to set mcast rate on vdev %i: %d\n",
2710*5c1def83SBjoern A. Zeeb arvif->vdev_id, ret);
2711*5c1def83SBjoern A. Zeeb
2712*5c1def83SBjoern A. Zeeb vdev_param = WMI_VDEV_PARAM_BCAST_DATA_RATE;
2713*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
2714*5c1def83SBjoern A. Zeeb vdev_param, rate);
2715*5c1def83SBjoern A. Zeeb if (ret)
2716*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab,
2717*5c1def83SBjoern A. Zeeb "failed to set bcast rate on vdev %i: %d\n",
2718*5c1def83SBjoern A. Zeeb arvif->vdev_id, ret);
2719*5c1def83SBjoern A. Zeeb }
2720*5c1def83SBjoern A. Zeeb
2721*5c1def83SBjoern A. Zeeb if (changed & BSS_CHANGED_BASIC_RATES &&
2722*5c1def83SBjoern A. Zeeb !ath12k_mac_vif_chan(arvif->vif, &def))
2723*5c1def83SBjoern A. Zeeb ath12k_recalculate_mgmt_rate(ar, vif, &def);
2724*5c1def83SBjoern A. Zeeb
2725*5c1def83SBjoern A. Zeeb if (changed & BSS_CHANGED_TWT) {
2726*5c1def83SBjoern A. Zeeb if (info->twt_requester || info->twt_responder)
2727*5c1def83SBjoern A. Zeeb ath12k_wmi_send_twt_enable_cmd(ar, ar->pdev->pdev_id);
2728*5c1def83SBjoern A. Zeeb else
2729*5c1def83SBjoern A. Zeeb ath12k_wmi_send_twt_disable_cmd(ar, ar->pdev->pdev_id);
2730*5c1def83SBjoern A. Zeeb }
2731*5c1def83SBjoern A. Zeeb
2732*5c1def83SBjoern A. Zeeb if (changed & BSS_CHANGED_HE_OBSS_PD)
2733*5c1def83SBjoern A. Zeeb ath12k_wmi_send_obss_spr_cmd(ar, arvif->vdev_id,
2734*5c1def83SBjoern A. Zeeb &info->he_obss_pd);
2735*5c1def83SBjoern A. Zeeb
2736*5c1def83SBjoern A. Zeeb if (changed & BSS_CHANGED_HE_BSS_COLOR) {
2737*5c1def83SBjoern A. Zeeb if (vif->type == NL80211_IFTYPE_AP) {
2738*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_obss_color_cfg_cmd(ar,
2739*5c1def83SBjoern A. Zeeb arvif->vdev_id,
2740*5c1def83SBjoern A. Zeeb info->he_bss_color.color,
2741*5c1def83SBjoern A. Zeeb ATH12K_BSS_COLOR_AP_PERIODS,
2742*5c1def83SBjoern A. Zeeb info->he_bss_color.enabled);
2743*5c1def83SBjoern A. Zeeb if (ret)
2744*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to set bss color collision on vdev %i: %d\n",
2745*5c1def83SBjoern A. Zeeb arvif->vdev_id, ret);
2746*5c1def83SBjoern A. Zeeb } else if (vif->type == NL80211_IFTYPE_STATION) {
2747*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_send_bss_color_change_enable_cmd(ar,
2748*5c1def83SBjoern A. Zeeb arvif->vdev_id,
2749*5c1def83SBjoern A. Zeeb 1);
2750*5c1def83SBjoern A. Zeeb if (ret)
2751*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to enable bss color change on vdev %i: %d\n",
2752*5c1def83SBjoern A. Zeeb arvif->vdev_id, ret);
2753*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_obss_color_cfg_cmd(ar,
2754*5c1def83SBjoern A. Zeeb arvif->vdev_id,
2755*5c1def83SBjoern A. Zeeb 0,
2756*5c1def83SBjoern A. Zeeb ATH12K_BSS_COLOR_STA_PERIODS,
2757*5c1def83SBjoern A. Zeeb 1);
2758*5c1def83SBjoern A. Zeeb if (ret)
2759*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to set bss color collision on vdev %i: %d\n",
2760*5c1def83SBjoern A. Zeeb arvif->vdev_id, ret);
2761*5c1def83SBjoern A. Zeeb }
2762*5c1def83SBjoern A. Zeeb }
2763*5c1def83SBjoern A. Zeeb
2764*5c1def83SBjoern A. Zeeb if (changed & BSS_CHANGED_FILS_DISCOVERY ||
2765*5c1def83SBjoern A. Zeeb changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP)
2766*5c1def83SBjoern A. Zeeb ath12k_mac_fils_discovery(arvif, info);
2767*5c1def83SBjoern A. Zeeb
2768*5c1def83SBjoern A. Zeeb if (changed & BSS_CHANGED_EHT_PUNCTURING)
2769*5c1def83SBjoern A. Zeeb arvif->punct_bitmap = info->eht_puncturing;
2770*5c1def83SBjoern A. Zeeb
2771*5c1def83SBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
2772*5c1def83SBjoern A. Zeeb }
2773*5c1def83SBjoern A. Zeeb
__ath12k_mac_scan_finish(struct ath12k * ar)2774*5c1def83SBjoern A. Zeeb void __ath12k_mac_scan_finish(struct ath12k *ar)
2775*5c1def83SBjoern A. Zeeb {
2776*5c1def83SBjoern A. Zeeb lockdep_assert_held(&ar->data_lock);
2777*5c1def83SBjoern A. Zeeb
2778*5c1def83SBjoern A. Zeeb switch (ar->scan.state) {
2779*5c1def83SBjoern A. Zeeb case ATH12K_SCAN_IDLE:
2780*5c1def83SBjoern A. Zeeb break;
2781*5c1def83SBjoern A. Zeeb case ATH12K_SCAN_RUNNING:
2782*5c1def83SBjoern A. Zeeb case ATH12K_SCAN_ABORTING:
2783*5c1def83SBjoern A. Zeeb if (!ar->scan.is_roc) {
2784*5c1def83SBjoern A. Zeeb struct cfg80211_scan_info info = {
2785*5c1def83SBjoern A. Zeeb .aborted = (ar->scan.state ==
2786*5c1def83SBjoern A. Zeeb ATH12K_SCAN_ABORTING),
2787*5c1def83SBjoern A. Zeeb };
2788*5c1def83SBjoern A. Zeeb
2789*5c1def83SBjoern A. Zeeb ieee80211_scan_completed(ar->hw, &info);
2790*5c1def83SBjoern A. Zeeb } else if (ar->scan.roc_notify) {
2791*5c1def83SBjoern A. Zeeb ieee80211_remain_on_channel_expired(ar->hw);
2792*5c1def83SBjoern A. Zeeb }
2793*5c1def83SBjoern A. Zeeb fallthrough;
2794*5c1def83SBjoern A. Zeeb case ATH12K_SCAN_STARTING:
2795*5c1def83SBjoern A. Zeeb ar->scan.state = ATH12K_SCAN_IDLE;
2796*5c1def83SBjoern A. Zeeb ar->scan_channel = NULL;
2797*5c1def83SBjoern A. Zeeb ar->scan.roc_freq = 0;
2798*5c1def83SBjoern A. Zeeb cancel_delayed_work(&ar->scan.timeout);
2799*5c1def83SBjoern A. Zeeb complete(&ar->scan.completed);
2800*5c1def83SBjoern A. Zeeb break;
2801*5c1def83SBjoern A. Zeeb }
2802*5c1def83SBjoern A. Zeeb }
2803*5c1def83SBjoern A. Zeeb
ath12k_mac_scan_finish(struct ath12k * ar)2804*5c1def83SBjoern A. Zeeb void ath12k_mac_scan_finish(struct ath12k *ar)
2805*5c1def83SBjoern A. Zeeb {
2806*5c1def83SBjoern A. Zeeb spin_lock_bh(&ar->data_lock);
2807*5c1def83SBjoern A. Zeeb __ath12k_mac_scan_finish(ar);
2808*5c1def83SBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
2809*5c1def83SBjoern A. Zeeb }
2810*5c1def83SBjoern A. Zeeb
ath12k_scan_stop(struct ath12k * ar)2811*5c1def83SBjoern A. Zeeb static int ath12k_scan_stop(struct ath12k *ar)
2812*5c1def83SBjoern A. Zeeb {
2813*5c1def83SBjoern A. Zeeb struct ath12k_wmi_scan_cancel_arg arg = {
2814*5c1def83SBjoern A. Zeeb .req_type = WLAN_SCAN_CANCEL_SINGLE,
2815*5c1def83SBjoern A. Zeeb .scan_id = ATH12K_SCAN_ID,
2816*5c1def83SBjoern A. Zeeb };
2817*5c1def83SBjoern A. Zeeb int ret;
2818*5c1def83SBjoern A. Zeeb
2819*5c1def83SBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
2820*5c1def83SBjoern A. Zeeb
2821*5c1def83SBjoern A. Zeeb /* TODO: Fill other STOP Params */
2822*5c1def83SBjoern A. Zeeb arg.pdev_id = ar->pdev->pdev_id;
2823*5c1def83SBjoern A. Zeeb
2824*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_send_scan_stop_cmd(ar, &arg);
2825*5c1def83SBjoern A. Zeeb if (ret) {
2826*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to stop wmi scan: %d\n", ret);
2827*5c1def83SBjoern A. Zeeb goto out;
2828*5c1def83SBjoern A. Zeeb }
2829*5c1def83SBjoern A. Zeeb
2830*5c1def83SBjoern A. Zeeb ret = wait_for_completion_timeout(&ar->scan.completed, 3 * HZ);
2831*5c1def83SBjoern A. Zeeb if (ret == 0) {
2832*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab,
2833*5c1def83SBjoern A. Zeeb "failed to receive scan abort comple: timed out\n");
2834*5c1def83SBjoern A. Zeeb ret = -ETIMEDOUT;
2835*5c1def83SBjoern A. Zeeb } else if (ret > 0) {
2836*5c1def83SBjoern A. Zeeb ret = 0;
2837*5c1def83SBjoern A. Zeeb }
2838*5c1def83SBjoern A. Zeeb
2839*5c1def83SBjoern A. Zeeb out:
2840*5c1def83SBjoern A. Zeeb /* Scan state should be updated upon scan completion but in case
2841*5c1def83SBjoern A. Zeeb * firmware fails to deliver the event (for whatever reason) it is
2842*5c1def83SBjoern A. Zeeb * desired to clean up scan state anyway. Firmware may have just
2843*5c1def83SBjoern A. Zeeb * dropped the scan completion event delivery due to transport pipe
2844*5c1def83SBjoern A. Zeeb * being overflown with data and/or it can recover on its own before
2845*5c1def83SBjoern A. Zeeb * next scan request is submitted.
2846*5c1def83SBjoern A. Zeeb */
2847*5c1def83SBjoern A. Zeeb spin_lock_bh(&ar->data_lock);
2848*5c1def83SBjoern A. Zeeb if (ar->scan.state != ATH12K_SCAN_IDLE)
2849*5c1def83SBjoern A. Zeeb __ath12k_mac_scan_finish(ar);
2850*5c1def83SBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
2851*5c1def83SBjoern A. Zeeb
2852*5c1def83SBjoern A. Zeeb return ret;
2853*5c1def83SBjoern A. Zeeb }
2854*5c1def83SBjoern A. Zeeb
ath12k_scan_abort(struct ath12k * ar)2855*5c1def83SBjoern A. Zeeb static void ath12k_scan_abort(struct ath12k *ar)
2856*5c1def83SBjoern A. Zeeb {
2857*5c1def83SBjoern A. Zeeb int ret;
2858*5c1def83SBjoern A. Zeeb
2859*5c1def83SBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
2860*5c1def83SBjoern A. Zeeb
2861*5c1def83SBjoern A. Zeeb spin_lock_bh(&ar->data_lock);
2862*5c1def83SBjoern A. Zeeb
2863*5c1def83SBjoern A. Zeeb switch (ar->scan.state) {
2864*5c1def83SBjoern A. Zeeb case ATH12K_SCAN_IDLE:
2865*5c1def83SBjoern A. Zeeb /* This can happen if timeout worker kicked in and called
2866*5c1def83SBjoern A. Zeeb * abortion while scan completion was being processed.
2867*5c1def83SBjoern A. Zeeb */
2868*5c1def83SBjoern A. Zeeb break;
2869*5c1def83SBjoern A. Zeeb case ATH12K_SCAN_STARTING:
2870*5c1def83SBjoern A. Zeeb case ATH12K_SCAN_ABORTING:
2871*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "refusing scan abortion due to invalid scan state: %d\n",
2872*5c1def83SBjoern A. Zeeb ar->scan.state);
2873*5c1def83SBjoern A. Zeeb break;
2874*5c1def83SBjoern A. Zeeb case ATH12K_SCAN_RUNNING:
2875*5c1def83SBjoern A. Zeeb ar->scan.state = ATH12K_SCAN_ABORTING;
2876*5c1def83SBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
2877*5c1def83SBjoern A. Zeeb
2878*5c1def83SBjoern A. Zeeb ret = ath12k_scan_stop(ar);
2879*5c1def83SBjoern A. Zeeb if (ret)
2880*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to abort scan: %d\n", ret);
2881*5c1def83SBjoern A. Zeeb
2882*5c1def83SBjoern A. Zeeb spin_lock_bh(&ar->data_lock);
2883*5c1def83SBjoern A. Zeeb break;
2884*5c1def83SBjoern A. Zeeb }
2885*5c1def83SBjoern A. Zeeb
2886*5c1def83SBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
2887*5c1def83SBjoern A. Zeeb }
2888*5c1def83SBjoern A. Zeeb
ath12k_scan_timeout_work(struct work_struct * work)2889*5c1def83SBjoern A. Zeeb static void ath12k_scan_timeout_work(struct work_struct *work)
2890*5c1def83SBjoern A. Zeeb {
2891*5c1def83SBjoern A. Zeeb struct ath12k *ar = container_of(work, struct ath12k,
2892*5c1def83SBjoern A. Zeeb scan.timeout.work);
2893*5c1def83SBjoern A. Zeeb
2894*5c1def83SBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
2895*5c1def83SBjoern A. Zeeb ath12k_scan_abort(ar);
2896*5c1def83SBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
2897*5c1def83SBjoern A. Zeeb }
2898*5c1def83SBjoern A. Zeeb
ath12k_start_scan(struct ath12k * ar,struct ath12k_wmi_scan_req_arg * arg)2899*5c1def83SBjoern A. Zeeb static int ath12k_start_scan(struct ath12k *ar,
2900*5c1def83SBjoern A. Zeeb struct ath12k_wmi_scan_req_arg *arg)
2901*5c1def83SBjoern A. Zeeb {
2902*5c1def83SBjoern A. Zeeb int ret;
2903*5c1def83SBjoern A. Zeeb
2904*5c1def83SBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
2905*5c1def83SBjoern A. Zeeb
2906*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_send_scan_start_cmd(ar, arg);
2907*5c1def83SBjoern A. Zeeb if (ret)
2908*5c1def83SBjoern A. Zeeb return ret;
2909*5c1def83SBjoern A. Zeeb
2910*5c1def83SBjoern A. Zeeb ret = wait_for_completion_timeout(&ar->scan.started, 1 * HZ);
2911*5c1def83SBjoern A. Zeeb if (ret == 0) {
2912*5c1def83SBjoern A. Zeeb ret = ath12k_scan_stop(ar);
2913*5c1def83SBjoern A. Zeeb if (ret)
2914*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to stop scan: %d\n", ret);
2915*5c1def83SBjoern A. Zeeb
2916*5c1def83SBjoern A. Zeeb return -ETIMEDOUT;
2917*5c1def83SBjoern A. Zeeb }
2918*5c1def83SBjoern A. Zeeb
2919*5c1def83SBjoern A. Zeeb /* If we failed to start the scan, return error code at
2920*5c1def83SBjoern A. Zeeb * this point. This is probably due to some issue in the
2921*5c1def83SBjoern A. Zeeb * firmware, but no need to wedge the driver due to that...
2922*5c1def83SBjoern A. Zeeb */
2923*5c1def83SBjoern A. Zeeb spin_lock_bh(&ar->data_lock);
2924*5c1def83SBjoern A. Zeeb if (ar->scan.state == ATH12K_SCAN_IDLE) {
2925*5c1def83SBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
2926*5c1def83SBjoern A. Zeeb return -EINVAL;
2927*5c1def83SBjoern A. Zeeb }
2928*5c1def83SBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
2929*5c1def83SBjoern A. Zeeb
2930*5c1def83SBjoern A. Zeeb return 0;
2931*5c1def83SBjoern A. Zeeb }
2932*5c1def83SBjoern A. Zeeb
ath12k_mac_op_hw_scan(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_scan_request * hw_req)2933*5c1def83SBjoern A. Zeeb static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
2934*5c1def83SBjoern A. Zeeb struct ieee80211_vif *vif,
2935*5c1def83SBjoern A. Zeeb struct ieee80211_scan_request *hw_req)
2936*5c1def83SBjoern A. Zeeb {
2937*5c1def83SBjoern A. Zeeb struct ath12k *ar = hw->priv;
2938*5c1def83SBjoern A. Zeeb struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
2939*5c1def83SBjoern A. Zeeb struct cfg80211_scan_request *req = &hw_req->req;
2940*5c1def83SBjoern A. Zeeb struct ath12k_wmi_scan_req_arg arg = {};
2941*5c1def83SBjoern A. Zeeb int ret;
2942*5c1def83SBjoern A. Zeeb int i;
2943*5c1def83SBjoern A. Zeeb
2944*5c1def83SBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
2945*5c1def83SBjoern A. Zeeb
2946*5c1def83SBjoern A. Zeeb spin_lock_bh(&ar->data_lock);
2947*5c1def83SBjoern A. Zeeb switch (ar->scan.state) {
2948*5c1def83SBjoern A. Zeeb case ATH12K_SCAN_IDLE:
2949*5c1def83SBjoern A. Zeeb reinit_completion(&ar->scan.started);
2950*5c1def83SBjoern A. Zeeb reinit_completion(&ar->scan.completed);
2951*5c1def83SBjoern A. Zeeb ar->scan.state = ATH12K_SCAN_STARTING;
2952*5c1def83SBjoern A. Zeeb ar->scan.is_roc = false;
2953*5c1def83SBjoern A. Zeeb ar->scan.vdev_id = arvif->vdev_id;
2954*5c1def83SBjoern A. Zeeb ret = 0;
2955*5c1def83SBjoern A. Zeeb break;
2956*5c1def83SBjoern A. Zeeb case ATH12K_SCAN_STARTING:
2957*5c1def83SBjoern A. Zeeb case ATH12K_SCAN_RUNNING:
2958*5c1def83SBjoern A. Zeeb case ATH12K_SCAN_ABORTING:
2959*5c1def83SBjoern A. Zeeb ret = -EBUSY;
2960*5c1def83SBjoern A. Zeeb break;
2961*5c1def83SBjoern A. Zeeb }
2962*5c1def83SBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
2963*5c1def83SBjoern A. Zeeb
2964*5c1def83SBjoern A. Zeeb if (ret)
2965*5c1def83SBjoern A. Zeeb goto exit;
2966*5c1def83SBjoern A. Zeeb
2967*5c1def83SBjoern A. Zeeb ath12k_wmi_start_scan_init(ar, &arg);
2968*5c1def83SBjoern A. Zeeb arg.vdev_id = arvif->vdev_id;
2969*5c1def83SBjoern A. Zeeb arg.scan_id = ATH12K_SCAN_ID;
2970*5c1def83SBjoern A. Zeeb
2971*5c1def83SBjoern A. Zeeb if (req->ie_len) {
2972*5c1def83SBjoern A. Zeeb arg.extraie.ptr = kmemdup(req->ie, req->ie_len, GFP_KERNEL);
2973*5c1def83SBjoern A. Zeeb if (!arg.extraie.ptr) {
2974*5c1def83SBjoern A. Zeeb ret = -ENOMEM;
2975*5c1def83SBjoern A. Zeeb goto exit;
2976*5c1def83SBjoern A. Zeeb }
2977*5c1def83SBjoern A. Zeeb arg.extraie.len = req->ie_len;
2978*5c1def83SBjoern A. Zeeb }
2979*5c1def83SBjoern A. Zeeb
2980*5c1def83SBjoern A. Zeeb if (req->n_ssids) {
2981*5c1def83SBjoern A. Zeeb arg.num_ssids = req->n_ssids;
2982*5c1def83SBjoern A. Zeeb for (i = 0; i < arg.num_ssids; i++)
2983*5c1def83SBjoern A. Zeeb arg.ssid[i] = req->ssids[i];
2984*5c1def83SBjoern A. Zeeb } else {
2985*5c1def83SBjoern A. Zeeb arg.scan_flags |= WMI_SCAN_FLAG_PASSIVE;
2986*5c1def83SBjoern A. Zeeb }
2987*5c1def83SBjoern A. Zeeb
2988*5c1def83SBjoern A. Zeeb if (req->n_channels) {
2989*5c1def83SBjoern A. Zeeb arg.num_chan = req->n_channels;
2990*5c1def83SBjoern A. Zeeb arg.chan_list = kcalloc(arg.num_chan, sizeof(*arg.chan_list),
2991*5c1def83SBjoern A. Zeeb GFP_KERNEL);
2992*5c1def83SBjoern A. Zeeb
2993*5c1def83SBjoern A. Zeeb if (!arg.chan_list) {
2994*5c1def83SBjoern A. Zeeb ret = -ENOMEM;
2995*5c1def83SBjoern A. Zeeb goto exit;
2996*5c1def83SBjoern A. Zeeb }
2997*5c1def83SBjoern A. Zeeb
2998*5c1def83SBjoern A. Zeeb for (i = 0; i < arg.num_chan; i++)
2999*5c1def83SBjoern A. Zeeb arg.chan_list[i] = req->channels[i]->center_freq;
3000*5c1def83SBjoern A. Zeeb }
3001*5c1def83SBjoern A. Zeeb
3002*5c1def83SBjoern A. Zeeb ret = ath12k_start_scan(ar, &arg);
3003*5c1def83SBjoern A. Zeeb if (ret) {
3004*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to start hw scan: %d\n", ret);
3005*5c1def83SBjoern A. Zeeb spin_lock_bh(&ar->data_lock);
3006*5c1def83SBjoern A. Zeeb ar->scan.state = ATH12K_SCAN_IDLE;
3007*5c1def83SBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
3008*5c1def83SBjoern A. Zeeb }
3009*5c1def83SBjoern A. Zeeb
3010*5c1def83SBjoern A. Zeeb /* Add a margin to account for event/command processing */
3011*5c1def83SBjoern A. Zeeb ieee80211_queue_delayed_work(ar->hw, &ar->scan.timeout,
3012*5c1def83SBjoern A. Zeeb msecs_to_jiffies(arg.max_scan_time +
3013*5c1def83SBjoern A. Zeeb ATH12K_MAC_SCAN_TIMEOUT_MSECS));
3014*5c1def83SBjoern A. Zeeb
3015*5c1def83SBjoern A. Zeeb exit:
3016*5c1def83SBjoern A. Zeeb kfree(arg.chan_list);
3017*5c1def83SBjoern A. Zeeb
3018*5c1def83SBjoern A. Zeeb if (req->ie_len)
3019*5c1def83SBjoern A. Zeeb kfree(arg.extraie.ptr);
3020*5c1def83SBjoern A. Zeeb
3021*5c1def83SBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
3022*5c1def83SBjoern A. Zeeb return ret;
3023*5c1def83SBjoern A. Zeeb }
3024*5c1def83SBjoern A. Zeeb
ath12k_mac_op_cancel_hw_scan(struct ieee80211_hw * hw,struct ieee80211_vif * vif)3025*5c1def83SBjoern A. Zeeb static void ath12k_mac_op_cancel_hw_scan(struct ieee80211_hw *hw,
3026*5c1def83SBjoern A. Zeeb struct ieee80211_vif *vif)
3027*5c1def83SBjoern A. Zeeb {
3028*5c1def83SBjoern A. Zeeb struct ath12k *ar = hw->priv;
3029*5c1def83SBjoern A. Zeeb
3030*5c1def83SBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
3031*5c1def83SBjoern A. Zeeb ath12k_scan_abort(ar);
3032*5c1def83SBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
3033*5c1def83SBjoern A. Zeeb
3034*5c1def83SBjoern A. Zeeb cancel_delayed_work_sync(&ar->scan.timeout);
3035*5c1def83SBjoern A. Zeeb }
3036*5c1def83SBjoern A. Zeeb
ath12k_install_key(struct ath12k_vif * arvif,struct ieee80211_key_conf * key,enum set_key_cmd cmd,const u8 * macaddr,u32 flags)3037*5c1def83SBjoern A. Zeeb static int ath12k_install_key(struct ath12k_vif *arvif,
3038*5c1def83SBjoern A. Zeeb struct ieee80211_key_conf *key,
3039*5c1def83SBjoern A. Zeeb enum set_key_cmd cmd,
3040*5c1def83SBjoern A. Zeeb const u8 *macaddr, u32 flags)
3041*5c1def83SBjoern A. Zeeb {
3042*5c1def83SBjoern A. Zeeb int ret;
3043*5c1def83SBjoern A. Zeeb struct ath12k *ar = arvif->ar;
3044*5c1def83SBjoern A. Zeeb struct wmi_vdev_install_key_arg arg = {
3045*5c1def83SBjoern A. Zeeb .vdev_id = arvif->vdev_id,
3046*5c1def83SBjoern A. Zeeb .key_idx = key->keyidx,
3047*5c1def83SBjoern A. Zeeb .key_len = key->keylen,
3048*5c1def83SBjoern A. Zeeb .key_data = key->key,
3049*5c1def83SBjoern A. Zeeb .key_flags = flags,
3050*5c1def83SBjoern A. Zeeb .macaddr = macaddr,
3051*5c1def83SBjoern A. Zeeb };
3052*5c1def83SBjoern A. Zeeb
3053*5c1def83SBjoern A. Zeeb lockdep_assert_held(&arvif->ar->conf_mutex);
3054*5c1def83SBjoern A. Zeeb
3055*5c1def83SBjoern A. Zeeb reinit_completion(&ar->install_key_done);
3056*5c1def83SBjoern A. Zeeb
3057*5c1def83SBjoern A. Zeeb if (test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags))
3058*5c1def83SBjoern A. Zeeb return 0;
3059*5c1def83SBjoern A. Zeeb
3060*5c1def83SBjoern A. Zeeb if (cmd == DISABLE_KEY) {
3061*5c1def83SBjoern A. Zeeb /* TODO: Check if FW expects value other than NONE for del */
3062*5c1def83SBjoern A. Zeeb /* arg.key_cipher = WMI_CIPHER_NONE; */
3063*5c1def83SBjoern A. Zeeb arg.key_len = 0;
3064*5c1def83SBjoern A. Zeeb arg.key_data = NULL;
3065*5c1def83SBjoern A. Zeeb goto install;
3066*5c1def83SBjoern A. Zeeb }
3067*5c1def83SBjoern A. Zeeb
3068*5c1def83SBjoern A. Zeeb switch (key->cipher) {
3069*5c1def83SBjoern A. Zeeb case WLAN_CIPHER_SUITE_CCMP:
3070*5c1def83SBjoern A. Zeeb arg.key_cipher = WMI_CIPHER_AES_CCM;
3071*5c1def83SBjoern A. Zeeb /* TODO: Re-check if flag is valid */
3072*5c1def83SBjoern A. Zeeb key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV_MGMT;
3073*5c1def83SBjoern A. Zeeb break;
3074*5c1def83SBjoern A. Zeeb case WLAN_CIPHER_SUITE_TKIP:
3075*5c1def83SBjoern A. Zeeb arg.key_cipher = WMI_CIPHER_TKIP;
3076*5c1def83SBjoern A. Zeeb arg.key_txmic_len = 8;
3077*5c1def83SBjoern A. Zeeb arg.key_rxmic_len = 8;
3078*5c1def83SBjoern A. Zeeb break;
3079*5c1def83SBjoern A. Zeeb case WLAN_CIPHER_SUITE_CCMP_256:
3080*5c1def83SBjoern A. Zeeb arg.key_cipher = WMI_CIPHER_AES_CCM;
3081*5c1def83SBjoern A. Zeeb break;
3082*5c1def83SBjoern A. Zeeb case WLAN_CIPHER_SUITE_GCMP:
3083*5c1def83SBjoern A. Zeeb case WLAN_CIPHER_SUITE_GCMP_256:
3084*5c1def83SBjoern A. Zeeb arg.key_cipher = WMI_CIPHER_AES_GCM;
3085*5c1def83SBjoern A. Zeeb break;
3086*5c1def83SBjoern A. Zeeb default:
3087*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "cipher %d is not supported\n", key->cipher);
3088*5c1def83SBjoern A. Zeeb return -EOPNOTSUPP;
3089*5c1def83SBjoern A. Zeeb }
3090*5c1def83SBjoern A. Zeeb
3091*5c1def83SBjoern A. Zeeb if (test_bit(ATH12K_FLAG_RAW_MODE, &ar->ab->dev_flags))
3092*5c1def83SBjoern A. Zeeb key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV |
3093*5c1def83SBjoern A. Zeeb IEEE80211_KEY_FLAG_RESERVE_TAILROOM;
3094*5c1def83SBjoern A. Zeeb
3095*5c1def83SBjoern A. Zeeb install:
3096*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_install_key(arvif->ar, &arg);
3097*5c1def83SBjoern A. Zeeb
3098*5c1def83SBjoern A. Zeeb if (ret)
3099*5c1def83SBjoern A. Zeeb return ret;
3100*5c1def83SBjoern A. Zeeb
3101*5c1def83SBjoern A. Zeeb if (!wait_for_completion_timeout(&ar->install_key_done, 1 * HZ))
3102*5c1def83SBjoern A. Zeeb return -ETIMEDOUT;
3103*5c1def83SBjoern A. Zeeb
3104*5c1def83SBjoern A. Zeeb if (ether_addr_equal(macaddr, arvif->vif->addr))
3105*5c1def83SBjoern A. Zeeb arvif->key_cipher = key->cipher;
3106*5c1def83SBjoern A. Zeeb
3107*5c1def83SBjoern A. Zeeb return ar->install_key_status ? -EINVAL : 0;
3108*5c1def83SBjoern A. Zeeb }
3109*5c1def83SBjoern A. Zeeb
ath12k_clear_peer_keys(struct ath12k_vif * arvif,const u8 * addr)3110*5c1def83SBjoern A. Zeeb static int ath12k_clear_peer_keys(struct ath12k_vif *arvif,
3111*5c1def83SBjoern A. Zeeb const u8 *addr)
3112*5c1def83SBjoern A. Zeeb {
3113*5c1def83SBjoern A. Zeeb struct ath12k *ar = arvif->ar;
3114*5c1def83SBjoern A. Zeeb struct ath12k_base *ab = ar->ab;
3115*5c1def83SBjoern A. Zeeb struct ath12k_peer *peer;
3116*5c1def83SBjoern A. Zeeb int first_errno = 0;
3117*5c1def83SBjoern A. Zeeb int ret;
3118*5c1def83SBjoern A. Zeeb int i;
3119*5c1def83SBjoern A. Zeeb u32 flags = 0;
3120*5c1def83SBjoern A. Zeeb
3121*5c1def83SBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
3122*5c1def83SBjoern A. Zeeb
3123*5c1def83SBjoern A. Zeeb spin_lock_bh(&ab->base_lock);
3124*5c1def83SBjoern A. Zeeb peer = ath12k_peer_find(ab, arvif->vdev_id, addr);
3125*5c1def83SBjoern A. Zeeb spin_unlock_bh(&ab->base_lock);
3126*5c1def83SBjoern A. Zeeb
3127*5c1def83SBjoern A. Zeeb if (!peer)
3128*5c1def83SBjoern A. Zeeb return -ENOENT;
3129*5c1def83SBjoern A. Zeeb
3130*5c1def83SBjoern A. Zeeb for (i = 0; i < ARRAY_SIZE(peer->keys); i++) {
3131*5c1def83SBjoern A. Zeeb if (!peer->keys[i])
3132*5c1def83SBjoern A. Zeeb continue;
3133*5c1def83SBjoern A. Zeeb
3134*5c1def83SBjoern A. Zeeb /* key flags are not required to delete the key */
3135*5c1def83SBjoern A. Zeeb ret = ath12k_install_key(arvif, peer->keys[i],
3136*5c1def83SBjoern A. Zeeb DISABLE_KEY, addr, flags);
3137*5c1def83SBjoern A. Zeeb if (ret < 0 && first_errno == 0)
3138*5c1def83SBjoern A. Zeeb first_errno = ret;
3139*5c1def83SBjoern A. Zeeb
3140*5c1def83SBjoern A. Zeeb if (ret < 0)
3141*5c1def83SBjoern A. Zeeb ath12k_warn(ab, "failed to remove peer key %d: %d\n",
3142*5c1def83SBjoern A. Zeeb i, ret);
3143*5c1def83SBjoern A. Zeeb
3144*5c1def83SBjoern A. Zeeb spin_lock_bh(&ab->base_lock);
3145*5c1def83SBjoern A. Zeeb peer->keys[i] = NULL;
3146*5c1def83SBjoern A. Zeeb spin_unlock_bh(&ab->base_lock);
3147*5c1def83SBjoern A. Zeeb }
3148*5c1def83SBjoern A. Zeeb
3149*5c1def83SBjoern A. Zeeb return first_errno;
3150*5c1def83SBjoern A. Zeeb }
3151*5c1def83SBjoern A. Zeeb
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)3152*5c1def83SBjoern A. Zeeb static int ath12k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
3153*5c1def83SBjoern A. Zeeb struct ieee80211_vif *vif, struct ieee80211_sta *sta,
3154*5c1def83SBjoern A. Zeeb struct ieee80211_key_conf *key)
3155*5c1def83SBjoern A. Zeeb {
3156*5c1def83SBjoern A. Zeeb struct ath12k *ar = hw->priv;
3157*5c1def83SBjoern A. Zeeb struct ath12k_base *ab = ar->ab;
3158*5c1def83SBjoern A. Zeeb struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
3159*5c1def83SBjoern A. Zeeb struct ath12k_peer *peer;
3160*5c1def83SBjoern A. Zeeb struct ath12k_sta *arsta;
3161*5c1def83SBjoern A. Zeeb const u8 *peer_addr;
3162*5c1def83SBjoern A. Zeeb int ret = 0;
3163*5c1def83SBjoern A. Zeeb u32 flags = 0;
3164*5c1def83SBjoern A. Zeeb
3165*5c1def83SBjoern A. Zeeb /* BIP needs to be done in software */
3166*5c1def83SBjoern A. Zeeb if (key->cipher == WLAN_CIPHER_SUITE_AES_CMAC ||
3167*5c1def83SBjoern A. Zeeb key->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 ||
3168*5c1def83SBjoern A. Zeeb key->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256 ||
3169*5c1def83SBjoern A. Zeeb key->cipher == WLAN_CIPHER_SUITE_BIP_CMAC_256)
3170*5c1def83SBjoern A. Zeeb return 1;
3171*5c1def83SBjoern A. Zeeb
3172*5c1def83SBjoern A. Zeeb if (test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags))
3173*5c1def83SBjoern A. Zeeb return 1;
3174*5c1def83SBjoern A. Zeeb
3175*5c1def83SBjoern A. Zeeb if (key->keyidx > WMI_MAX_KEY_INDEX)
3176*5c1def83SBjoern A. Zeeb return -ENOSPC;
3177*5c1def83SBjoern A. Zeeb
3178*5c1def83SBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
3179*5c1def83SBjoern A. Zeeb
3180*5c1def83SBjoern A. Zeeb if (sta)
3181*5c1def83SBjoern A. Zeeb peer_addr = sta->addr;
3182*5c1def83SBjoern A. Zeeb else if (arvif->vdev_type == WMI_VDEV_TYPE_STA)
3183*5c1def83SBjoern A. Zeeb peer_addr = vif->bss_conf.bssid;
3184*5c1def83SBjoern A. Zeeb else
3185*5c1def83SBjoern A. Zeeb peer_addr = vif->addr;
3186*5c1def83SBjoern A. Zeeb
3187*5c1def83SBjoern A. Zeeb key->hw_key_idx = key->keyidx;
3188*5c1def83SBjoern A. Zeeb
3189*5c1def83SBjoern A. Zeeb /* the peer should not disappear in mid-way (unless FW goes awry) since
3190*5c1def83SBjoern A. Zeeb * we already hold conf_mutex. we just make sure its there now.
3191*5c1def83SBjoern A. Zeeb */
3192*5c1def83SBjoern A. Zeeb spin_lock_bh(&ab->base_lock);
3193*5c1def83SBjoern A. Zeeb peer = ath12k_peer_find(ab, arvif->vdev_id, peer_addr);
3194*5c1def83SBjoern A. Zeeb spin_unlock_bh(&ab->base_lock);
3195*5c1def83SBjoern A. Zeeb
3196*5c1def83SBjoern A. Zeeb if (!peer) {
3197*5c1def83SBjoern A. Zeeb if (cmd == SET_KEY) {
3198*5c1def83SBjoern A. Zeeb ath12k_warn(ab, "cannot install key for non-existent peer %pM\n",
3199*5c1def83SBjoern A. Zeeb peer_addr);
3200*5c1def83SBjoern A. Zeeb ret = -EOPNOTSUPP;
3201*5c1def83SBjoern A. Zeeb goto exit;
3202*5c1def83SBjoern A. Zeeb } else {
3203*5c1def83SBjoern A. Zeeb /* if the peer doesn't exist there is no key to disable
3204*5c1def83SBjoern A. Zeeb * anymore
3205*5c1def83SBjoern A. Zeeb */
3206*5c1def83SBjoern A. Zeeb goto exit;
3207*5c1def83SBjoern A. Zeeb }
3208*5c1def83SBjoern A. Zeeb }
3209*5c1def83SBjoern A. Zeeb
3210*5c1def83SBjoern A. Zeeb if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
3211*5c1def83SBjoern A. Zeeb flags |= WMI_KEY_PAIRWISE;
3212*5c1def83SBjoern A. Zeeb else
3213*5c1def83SBjoern A. Zeeb flags |= WMI_KEY_GROUP;
3214*5c1def83SBjoern A. Zeeb
3215*5c1def83SBjoern A. Zeeb ret = ath12k_install_key(arvif, key, cmd, peer_addr, flags);
3216*5c1def83SBjoern A. Zeeb if (ret) {
3217*5c1def83SBjoern A. Zeeb ath12k_warn(ab, "ath12k_install_key failed (%d)\n", ret);
3218*5c1def83SBjoern A. Zeeb goto exit;
3219*5c1def83SBjoern A. Zeeb }
3220*5c1def83SBjoern A. Zeeb
3221*5c1def83SBjoern A. Zeeb ret = ath12k_dp_rx_peer_pn_replay_config(arvif, peer_addr, cmd, key);
3222*5c1def83SBjoern A. Zeeb if (ret) {
3223*5c1def83SBjoern A. Zeeb ath12k_warn(ab, "failed to offload PN replay detection %d\n", ret);
3224*5c1def83SBjoern A. Zeeb goto exit;
3225*5c1def83SBjoern A. Zeeb }
3226*5c1def83SBjoern A. Zeeb
3227*5c1def83SBjoern A. Zeeb spin_lock_bh(&ab->base_lock);
3228*5c1def83SBjoern A. Zeeb peer = ath12k_peer_find(ab, arvif->vdev_id, peer_addr);
3229*5c1def83SBjoern A. Zeeb if (peer && cmd == SET_KEY) {
3230*5c1def83SBjoern A. Zeeb peer->keys[key->keyidx] = key;
3231*5c1def83SBjoern A. Zeeb if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
3232*5c1def83SBjoern A. Zeeb peer->ucast_keyidx = key->keyidx;
3233*5c1def83SBjoern A. Zeeb peer->sec_type = ath12k_dp_tx_get_encrypt_type(key->cipher);
3234*5c1def83SBjoern A. Zeeb } else {
3235*5c1def83SBjoern A. Zeeb peer->mcast_keyidx = key->keyidx;
3236*5c1def83SBjoern A. Zeeb peer->sec_type_grp = ath12k_dp_tx_get_encrypt_type(key->cipher);
3237*5c1def83SBjoern A. Zeeb }
3238*5c1def83SBjoern A. Zeeb } else if (peer && cmd == DISABLE_KEY) {
3239*5c1def83SBjoern A. Zeeb peer->keys[key->keyidx] = NULL;
3240*5c1def83SBjoern A. Zeeb if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
3241*5c1def83SBjoern A. Zeeb peer->ucast_keyidx = 0;
3242*5c1def83SBjoern A. Zeeb else
3243*5c1def83SBjoern A. Zeeb peer->mcast_keyidx = 0;
3244*5c1def83SBjoern A. Zeeb } else if (!peer)
3245*5c1def83SBjoern A. Zeeb /* impossible unless FW goes crazy */
3246*5c1def83SBjoern A. Zeeb ath12k_warn(ab, "peer %pM disappeared!\n", peer_addr);
3247*5c1def83SBjoern A. Zeeb
3248*5c1def83SBjoern A. Zeeb if (sta) {
3249*5c1def83SBjoern A. Zeeb arsta = (struct ath12k_sta *)sta->drv_priv;
3250*5c1def83SBjoern A. Zeeb
3251*5c1def83SBjoern A. Zeeb switch (key->cipher) {
3252*5c1def83SBjoern A. Zeeb case WLAN_CIPHER_SUITE_TKIP:
3253*5c1def83SBjoern A. Zeeb case WLAN_CIPHER_SUITE_CCMP:
3254*5c1def83SBjoern A. Zeeb case WLAN_CIPHER_SUITE_CCMP_256:
3255*5c1def83SBjoern A. Zeeb case WLAN_CIPHER_SUITE_GCMP:
3256*5c1def83SBjoern A. Zeeb case WLAN_CIPHER_SUITE_GCMP_256:
3257*5c1def83SBjoern A. Zeeb if (cmd == SET_KEY)
3258*5c1def83SBjoern A. Zeeb arsta->pn_type = HAL_PN_TYPE_WPA;
3259*5c1def83SBjoern A. Zeeb else
3260*5c1def83SBjoern A. Zeeb arsta->pn_type = HAL_PN_TYPE_NONE;
3261*5c1def83SBjoern A. Zeeb break;
3262*5c1def83SBjoern A. Zeeb default:
3263*5c1def83SBjoern A. Zeeb arsta->pn_type = HAL_PN_TYPE_NONE;
3264*5c1def83SBjoern A. Zeeb break;
3265*5c1def83SBjoern A. Zeeb }
3266*5c1def83SBjoern A. Zeeb }
3267*5c1def83SBjoern A. Zeeb
3268*5c1def83SBjoern A. Zeeb spin_unlock_bh(&ab->base_lock);
3269*5c1def83SBjoern A. Zeeb
3270*5c1def83SBjoern A. Zeeb exit:
3271*5c1def83SBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
3272*5c1def83SBjoern A. Zeeb return ret;
3273*5c1def83SBjoern A. Zeeb }
3274*5c1def83SBjoern A. Zeeb
3275*5c1def83SBjoern A. Zeeb static int
ath12k_mac_bitrate_mask_num_vht_rates(struct ath12k * ar,enum nl80211_band band,const struct cfg80211_bitrate_mask * mask)3276*5c1def83SBjoern A. Zeeb ath12k_mac_bitrate_mask_num_vht_rates(struct ath12k *ar,
3277*5c1def83SBjoern A. Zeeb enum nl80211_band band,
3278*5c1def83SBjoern A. Zeeb const struct cfg80211_bitrate_mask *mask)
3279*5c1def83SBjoern A. Zeeb {
3280*5c1def83SBjoern A. Zeeb int num_rates = 0;
3281*5c1def83SBjoern A. Zeeb int i;
3282*5c1def83SBjoern A. Zeeb
3283*5c1def83SBjoern A. Zeeb for (i = 0; i < ARRAY_SIZE(mask->control[band].vht_mcs); i++)
3284*5c1def83SBjoern A. Zeeb num_rates += hweight16(mask->control[band].vht_mcs[i]);
3285*5c1def83SBjoern A. Zeeb
3286*5c1def83SBjoern A. Zeeb return num_rates;
3287*5c1def83SBjoern A. Zeeb }
3288*5c1def83SBjoern A. Zeeb
3289*5c1def83SBjoern A. Zeeb 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)3290*5c1def83SBjoern A. Zeeb ath12k_mac_set_peer_vht_fixed_rate(struct ath12k_vif *arvif,
3291*5c1def83SBjoern A. Zeeb struct ieee80211_sta *sta,
3292*5c1def83SBjoern A. Zeeb const struct cfg80211_bitrate_mask *mask,
3293*5c1def83SBjoern A. Zeeb enum nl80211_band band)
3294*5c1def83SBjoern A. Zeeb {
3295*5c1def83SBjoern A. Zeeb struct ath12k *ar = arvif->ar;
3296*5c1def83SBjoern A. Zeeb u8 vht_rate, nss;
3297*5c1def83SBjoern A. Zeeb u32 rate_code;
3298*5c1def83SBjoern A. Zeeb int ret, i;
3299*5c1def83SBjoern A. Zeeb
3300*5c1def83SBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
3301*5c1def83SBjoern A. Zeeb
3302*5c1def83SBjoern A. Zeeb nss = 0;
3303*5c1def83SBjoern A. Zeeb
3304*5c1def83SBjoern A. Zeeb for (i = 0; i < ARRAY_SIZE(mask->control[band].vht_mcs); i++) {
3305*5c1def83SBjoern A. Zeeb if (hweight16(mask->control[band].vht_mcs[i]) == 1) {
3306*5c1def83SBjoern A. Zeeb nss = i + 1;
3307*5c1def83SBjoern A. Zeeb vht_rate = ffs(mask->control[band].vht_mcs[i]) - 1;
3308*5c1def83SBjoern A. Zeeb }
3309*5c1def83SBjoern A. Zeeb }
3310*5c1def83SBjoern A. Zeeb
3311*5c1def83SBjoern A. Zeeb if (!nss) {
3312*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "No single VHT Fixed rate found to set for %pM",
3313*5c1def83SBjoern A. Zeeb sta->addr);
3314*5c1def83SBjoern A. Zeeb return -EINVAL;
3315*5c1def83SBjoern A. Zeeb }
3316*5c1def83SBjoern A. Zeeb
3317*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
3318*5c1def83SBjoern A. Zeeb "Setting Fixed VHT Rate for peer %pM. Device will not switch to any other selected rates",
3319*5c1def83SBjoern A. Zeeb sta->addr);
3320*5c1def83SBjoern A. Zeeb
3321*5c1def83SBjoern A. Zeeb rate_code = ATH12K_HW_RATE_CODE(vht_rate, nss - 1,
3322*5c1def83SBjoern A. Zeeb WMI_RATE_PREAMBLE_VHT);
3323*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_set_peer_param(ar, sta->addr,
3324*5c1def83SBjoern A. Zeeb arvif->vdev_id,
3325*5c1def83SBjoern A. Zeeb WMI_PEER_PARAM_FIXED_RATE,
3326*5c1def83SBjoern A. Zeeb rate_code);
3327*5c1def83SBjoern A. Zeeb if (ret)
3328*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab,
3329*5c1def83SBjoern A. Zeeb "failed to update STA %pM Fixed Rate %d: %d\n",
3330*5c1def83SBjoern A. Zeeb sta->addr, rate_code, ret);
3331*5c1def83SBjoern A. Zeeb
3332*5c1def83SBjoern A. Zeeb return ret;
3333*5c1def83SBjoern A. Zeeb }
3334*5c1def83SBjoern A. Zeeb
ath12k_station_assoc(struct ath12k * ar,struct ieee80211_vif * vif,struct ieee80211_sta * sta,bool reassoc)3335*5c1def83SBjoern A. Zeeb static int ath12k_station_assoc(struct ath12k *ar,
3336*5c1def83SBjoern A. Zeeb struct ieee80211_vif *vif,
3337*5c1def83SBjoern A. Zeeb struct ieee80211_sta *sta,
3338*5c1def83SBjoern A. Zeeb bool reassoc)
3339*5c1def83SBjoern A. Zeeb {
3340*5c1def83SBjoern A. Zeeb struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
3341*5c1def83SBjoern A. Zeeb struct ath12k_wmi_peer_assoc_arg peer_arg;
3342*5c1def83SBjoern A. Zeeb int ret;
3343*5c1def83SBjoern A. Zeeb struct cfg80211_chan_def def;
3344*5c1def83SBjoern A. Zeeb enum nl80211_band band;
3345*5c1def83SBjoern A. Zeeb struct cfg80211_bitrate_mask *mask;
3346*5c1def83SBjoern A. Zeeb u8 num_vht_rates;
3347*5c1def83SBjoern A. Zeeb
3348*5c1def83SBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
3349*5c1def83SBjoern A. Zeeb
3350*5c1def83SBjoern A. Zeeb if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))
3351*5c1def83SBjoern A. Zeeb return -EPERM;
3352*5c1def83SBjoern A. Zeeb
3353*5c1def83SBjoern A. Zeeb band = def.chan->band;
3354*5c1def83SBjoern A. Zeeb mask = &arvif->bitrate_mask;
3355*5c1def83SBjoern A. Zeeb
3356*5c1def83SBjoern A. Zeeb ath12k_peer_assoc_prepare(ar, vif, sta, &peer_arg, reassoc);
3357*5c1def83SBjoern A. Zeeb
3358*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_send_peer_assoc_cmd(ar, &peer_arg);
3359*5c1def83SBjoern A. Zeeb if (ret) {
3360*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to run peer assoc for STA %pM vdev %i: %d\n",
3361*5c1def83SBjoern A. Zeeb sta->addr, arvif->vdev_id, ret);
3362*5c1def83SBjoern A. Zeeb return ret;
3363*5c1def83SBjoern A. Zeeb }
3364*5c1def83SBjoern A. Zeeb
3365*5c1def83SBjoern A. Zeeb if (!wait_for_completion_timeout(&ar->peer_assoc_done, 1 * HZ)) {
3366*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to get peer assoc conf event for %pM vdev %i\n",
3367*5c1def83SBjoern A. Zeeb sta->addr, arvif->vdev_id);
3368*5c1def83SBjoern A. Zeeb return -ETIMEDOUT;
3369*5c1def83SBjoern A. Zeeb }
3370*5c1def83SBjoern A. Zeeb
3371*5c1def83SBjoern A. Zeeb num_vht_rates = ath12k_mac_bitrate_mask_num_vht_rates(ar, band, mask);
3372*5c1def83SBjoern A. Zeeb
3373*5c1def83SBjoern A. Zeeb /* If single VHT rate is configured (by set_bitrate_mask()),
3374*5c1def83SBjoern A. Zeeb * peer_assoc will disable VHT. This is now enabled by a peer specific
3375*5c1def83SBjoern A. Zeeb * fixed param.
3376*5c1def83SBjoern A. Zeeb * Note that all other rates and NSS will be disabled for this peer.
3377*5c1def83SBjoern A. Zeeb */
3378*5c1def83SBjoern A. Zeeb if (sta->deflink.vht_cap.vht_supported && num_vht_rates == 1) {
3379*5c1def83SBjoern A. Zeeb ret = ath12k_mac_set_peer_vht_fixed_rate(arvif, sta, mask,
3380*5c1def83SBjoern A. Zeeb band);
3381*5c1def83SBjoern A. Zeeb if (ret)
3382*5c1def83SBjoern A. Zeeb return ret;
3383*5c1def83SBjoern A. Zeeb }
3384*5c1def83SBjoern A. Zeeb
3385*5c1def83SBjoern A. Zeeb /* Re-assoc is run only to update supported rates for given station. It
3386*5c1def83SBjoern A. Zeeb * doesn't make much sense to reconfigure the peer completely.
3387*5c1def83SBjoern A. Zeeb */
3388*5c1def83SBjoern A. Zeeb if (reassoc)
3389*5c1def83SBjoern A. Zeeb return 0;
3390*5c1def83SBjoern A. Zeeb
3391*5c1def83SBjoern A. Zeeb ret = ath12k_setup_peer_smps(ar, arvif, sta->addr,
3392*5c1def83SBjoern A. Zeeb &sta->deflink.ht_cap);
3393*5c1def83SBjoern A. Zeeb if (ret) {
3394*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to setup peer SMPS for vdev %d: %d\n",
3395*5c1def83SBjoern A. Zeeb arvif->vdev_id, ret);
3396*5c1def83SBjoern A. Zeeb return ret;
3397*5c1def83SBjoern A. Zeeb }
3398*5c1def83SBjoern A. Zeeb
3399*5c1def83SBjoern A. Zeeb if (!sta->wme) {
3400*5c1def83SBjoern A. Zeeb arvif->num_legacy_stations++;
3401*5c1def83SBjoern A. Zeeb ret = ath12k_recalc_rtscts_prot(arvif);
3402*5c1def83SBjoern A. Zeeb if (ret)
3403*5c1def83SBjoern A. Zeeb return ret;
3404*5c1def83SBjoern A. Zeeb }
3405*5c1def83SBjoern A. Zeeb
3406*5c1def83SBjoern A. Zeeb if (sta->wme && sta->uapsd_queues) {
3407*5c1def83SBjoern A. Zeeb ret = ath12k_peer_assoc_qos_ap(ar, arvif, sta);
3408*5c1def83SBjoern A. Zeeb if (ret) {
3409*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to set qos params for STA %pM for vdev %i: %d\n",
3410*5c1def83SBjoern A. Zeeb sta->addr, arvif->vdev_id, ret);
3411*5c1def83SBjoern A. Zeeb return ret;
3412*5c1def83SBjoern A. Zeeb }
3413*5c1def83SBjoern A. Zeeb }
3414*5c1def83SBjoern A. Zeeb
3415*5c1def83SBjoern A. Zeeb return 0;
3416*5c1def83SBjoern A. Zeeb }
3417*5c1def83SBjoern A. Zeeb
ath12k_station_disassoc(struct ath12k * ar,struct ieee80211_vif * vif,struct ieee80211_sta * sta)3418*5c1def83SBjoern A. Zeeb static int ath12k_station_disassoc(struct ath12k *ar,
3419*5c1def83SBjoern A. Zeeb struct ieee80211_vif *vif,
3420*5c1def83SBjoern A. Zeeb struct ieee80211_sta *sta)
3421*5c1def83SBjoern A. Zeeb {
3422*5c1def83SBjoern A. Zeeb struct ath12k_vif *arvif = (void *)vif->drv_priv;
3423*5c1def83SBjoern A. Zeeb int ret;
3424*5c1def83SBjoern A. Zeeb
3425*5c1def83SBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
3426*5c1def83SBjoern A. Zeeb
3427*5c1def83SBjoern A. Zeeb if (!sta->wme) {
3428*5c1def83SBjoern A. Zeeb arvif->num_legacy_stations--;
3429*5c1def83SBjoern A. Zeeb ret = ath12k_recalc_rtscts_prot(arvif);
3430*5c1def83SBjoern A. Zeeb if (ret)
3431*5c1def83SBjoern A. Zeeb return ret;
3432*5c1def83SBjoern A. Zeeb }
3433*5c1def83SBjoern A. Zeeb
3434*5c1def83SBjoern A. Zeeb ret = ath12k_clear_peer_keys(arvif, sta->addr);
3435*5c1def83SBjoern A. Zeeb if (ret) {
3436*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to clear all peer keys for vdev %i: %d\n",
3437*5c1def83SBjoern A. Zeeb arvif->vdev_id, ret);
3438*5c1def83SBjoern A. Zeeb return ret;
3439*5c1def83SBjoern A. Zeeb }
3440*5c1def83SBjoern A. Zeeb return 0;
3441*5c1def83SBjoern A. Zeeb }
3442*5c1def83SBjoern A. Zeeb
ath12k_sta_rc_update_wk(struct work_struct * wk)3443*5c1def83SBjoern A. Zeeb static void ath12k_sta_rc_update_wk(struct work_struct *wk)
3444*5c1def83SBjoern A. Zeeb {
3445*5c1def83SBjoern A. Zeeb struct ath12k *ar;
3446*5c1def83SBjoern A. Zeeb struct ath12k_vif *arvif;
3447*5c1def83SBjoern A. Zeeb struct ath12k_sta *arsta;
3448*5c1def83SBjoern A. Zeeb struct ieee80211_sta *sta;
3449*5c1def83SBjoern A. Zeeb struct cfg80211_chan_def def;
3450*5c1def83SBjoern A. Zeeb enum nl80211_band band;
3451*5c1def83SBjoern A. Zeeb const u8 *ht_mcs_mask;
3452*5c1def83SBjoern A. Zeeb const u16 *vht_mcs_mask;
3453*5c1def83SBjoern A. Zeeb u32 changed, bw, nss, smps, bw_prev;
3454*5c1def83SBjoern A. Zeeb int err, num_vht_rates;
3455*5c1def83SBjoern A. Zeeb const struct cfg80211_bitrate_mask *mask;
3456*5c1def83SBjoern A. Zeeb struct ath12k_wmi_peer_assoc_arg peer_arg;
3457*5c1def83SBjoern A. Zeeb enum wmi_phy_mode peer_phymode;
3458*5c1def83SBjoern A. Zeeb
3459*5c1def83SBjoern A. Zeeb arsta = container_of(wk, struct ath12k_sta, update_wk);
3460*5c1def83SBjoern A. Zeeb sta = container_of((void *)arsta, struct ieee80211_sta, drv_priv);
3461*5c1def83SBjoern A. Zeeb arvif = arsta->arvif;
3462*5c1def83SBjoern A. Zeeb ar = arvif->ar;
3463*5c1def83SBjoern A. Zeeb
3464*5c1def83SBjoern A. Zeeb if (WARN_ON(ath12k_mac_vif_chan(arvif->vif, &def)))
3465*5c1def83SBjoern A. Zeeb return;
3466*5c1def83SBjoern A. Zeeb
3467*5c1def83SBjoern A. Zeeb band = def.chan->band;
3468*5c1def83SBjoern A. Zeeb ht_mcs_mask = arvif->bitrate_mask.control[band].ht_mcs;
3469*5c1def83SBjoern A. Zeeb vht_mcs_mask = arvif->bitrate_mask.control[band].vht_mcs;
3470*5c1def83SBjoern A. Zeeb
3471*5c1def83SBjoern A. Zeeb spin_lock_bh(&ar->data_lock);
3472*5c1def83SBjoern A. Zeeb
3473*5c1def83SBjoern A. Zeeb changed = arsta->changed;
3474*5c1def83SBjoern A. Zeeb arsta->changed = 0;
3475*5c1def83SBjoern A. Zeeb
3476*5c1def83SBjoern A. Zeeb bw = arsta->bw;
3477*5c1def83SBjoern A. Zeeb bw_prev = arsta->bw_prev;
3478*5c1def83SBjoern A. Zeeb nss = arsta->nss;
3479*5c1def83SBjoern A. Zeeb smps = arsta->smps;
3480*5c1def83SBjoern A. Zeeb
3481*5c1def83SBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
3482*5c1def83SBjoern A. Zeeb
3483*5c1def83SBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
3484*5c1def83SBjoern A. Zeeb
3485*5c1def83SBjoern A. Zeeb nss = max_t(u32, 1, nss);
3486*5c1def83SBjoern A. Zeeb nss = min(nss, max(ath12k_mac_max_ht_nss(ht_mcs_mask),
3487*5c1def83SBjoern A. Zeeb ath12k_mac_max_vht_nss(vht_mcs_mask)));
3488*5c1def83SBjoern A. Zeeb
3489*5c1def83SBjoern A. Zeeb if (changed & IEEE80211_RC_BW_CHANGED) {
3490*5c1def83SBjoern A. Zeeb ath12k_peer_assoc_h_phymode(ar, arvif->vif, sta, &peer_arg);
3491*5c1def83SBjoern A. Zeeb peer_phymode = peer_arg.peer_phymode;
3492*5c1def83SBjoern A. Zeeb
3493*5c1def83SBjoern A. Zeeb if (bw > bw_prev) {
3494*5c1def83SBjoern A. Zeeb /* Phymode shows maximum supported channel width, if we
3495*5c1def83SBjoern A. Zeeb * upgrade bandwidth then due to sanity check of firmware,
3496*5c1def83SBjoern A. Zeeb * we have to send WMI_PEER_PHYMODE followed by
3497*5c1def83SBjoern A. Zeeb * WMI_PEER_CHWIDTH
3498*5c1def83SBjoern A. Zeeb */
3499*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac bandwidth upgrade for sta %pM new %d old %d\n",
3500*5c1def83SBjoern A. Zeeb sta->addr, bw, bw_prev);
3501*5c1def83SBjoern A. Zeeb err = ath12k_wmi_set_peer_param(ar, sta->addr,
3502*5c1def83SBjoern A. Zeeb arvif->vdev_id, WMI_PEER_PHYMODE,
3503*5c1def83SBjoern A. Zeeb peer_phymode);
3504*5c1def83SBjoern A. Zeeb if (err) {
3505*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to update STA %pM to peer phymode %d: %d\n",
3506*5c1def83SBjoern A. Zeeb sta->addr, peer_phymode, err);
3507*5c1def83SBjoern A. Zeeb goto err_rc_bw_changed;
3508*5c1def83SBjoern A. Zeeb }
3509*5c1def83SBjoern A. Zeeb err = ath12k_wmi_set_peer_param(ar, sta->addr,
3510*5c1def83SBjoern A. Zeeb arvif->vdev_id, WMI_PEER_CHWIDTH,
3511*5c1def83SBjoern A. Zeeb bw);
3512*5c1def83SBjoern A. Zeeb if (err)
3513*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to update STA %pM to peer bandwidth %d: %d\n",
3514*5c1def83SBjoern A. Zeeb sta->addr, bw, err);
3515*5c1def83SBjoern A. Zeeb } else {
3516*5c1def83SBjoern A. Zeeb /* When we downgrade bandwidth this will conflict with phymode
3517*5c1def83SBjoern A. Zeeb * and cause to trigger firmware crash. In this case we send
3518*5c1def83SBjoern A. Zeeb * WMI_PEER_CHWIDTH followed by WMI_PEER_PHYMODE
3519*5c1def83SBjoern A. Zeeb */
3520*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac bandwidth downgrade for sta %pM new %d old %d\n",
3521*5c1def83SBjoern A. Zeeb sta->addr, bw, bw_prev);
3522*5c1def83SBjoern A. Zeeb err = ath12k_wmi_set_peer_param(ar, sta->addr,
3523*5c1def83SBjoern A. Zeeb arvif->vdev_id, WMI_PEER_CHWIDTH,
3524*5c1def83SBjoern A. Zeeb bw);
3525*5c1def83SBjoern A. Zeeb if (err) {
3526*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to update STA %pM peer to bandwidth %d: %d\n",
3527*5c1def83SBjoern A. Zeeb sta->addr, bw, err);
3528*5c1def83SBjoern A. Zeeb goto err_rc_bw_changed;
3529*5c1def83SBjoern A. Zeeb }
3530*5c1def83SBjoern A. Zeeb err = ath12k_wmi_set_peer_param(ar, sta->addr,
3531*5c1def83SBjoern A. Zeeb arvif->vdev_id, WMI_PEER_PHYMODE,
3532*5c1def83SBjoern A. Zeeb peer_phymode);
3533*5c1def83SBjoern A. Zeeb if (err)
3534*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to update STA %pM to peer phymode %d: %d\n",
3535*5c1def83SBjoern A. Zeeb sta->addr, peer_phymode, err);
3536*5c1def83SBjoern A. Zeeb }
3537*5c1def83SBjoern A. Zeeb }
3538*5c1def83SBjoern A. Zeeb
3539*5c1def83SBjoern A. Zeeb if (changed & IEEE80211_RC_NSS_CHANGED) {
3540*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac update sta %pM nss %d\n",
3541*5c1def83SBjoern A. Zeeb sta->addr, nss);
3542*5c1def83SBjoern A. Zeeb
3543*5c1def83SBjoern A. Zeeb err = ath12k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,
3544*5c1def83SBjoern A. Zeeb WMI_PEER_NSS, nss);
3545*5c1def83SBjoern A. Zeeb if (err)
3546*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to update STA %pM nss %d: %d\n",
3547*5c1def83SBjoern A. Zeeb sta->addr, nss, err);
3548*5c1def83SBjoern A. Zeeb }
3549*5c1def83SBjoern A. Zeeb
3550*5c1def83SBjoern A. Zeeb if (changed & IEEE80211_RC_SMPS_CHANGED) {
3551*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac update sta %pM smps %d\n",
3552*5c1def83SBjoern A. Zeeb sta->addr, smps);
3553*5c1def83SBjoern A. Zeeb
3554*5c1def83SBjoern A. Zeeb err = ath12k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,
3555*5c1def83SBjoern A. Zeeb WMI_PEER_MIMO_PS_STATE, smps);
3556*5c1def83SBjoern A. Zeeb if (err)
3557*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to update STA %pM smps %d: %d\n",
3558*5c1def83SBjoern A. Zeeb sta->addr, smps, err);
3559*5c1def83SBjoern A. Zeeb }
3560*5c1def83SBjoern A. Zeeb
3561*5c1def83SBjoern A. Zeeb if (changed & IEEE80211_RC_SUPP_RATES_CHANGED) {
3562*5c1def83SBjoern A. Zeeb mask = &arvif->bitrate_mask;
3563*5c1def83SBjoern A. Zeeb num_vht_rates = ath12k_mac_bitrate_mask_num_vht_rates(ar, band,
3564*5c1def83SBjoern A. Zeeb mask);
3565*5c1def83SBjoern A. Zeeb
3566*5c1def83SBjoern A. Zeeb /* Peer_assoc_prepare will reject vht rates in
3567*5c1def83SBjoern A. Zeeb * bitrate_mask if its not available in range format and
3568*5c1def83SBjoern A. Zeeb * sets vht tx_rateset as unsupported. So multiple VHT MCS
3569*5c1def83SBjoern A. Zeeb * setting(eg. MCS 4,5,6) per peer is not supported here.
3570*5c1def83SBjoern A. Zeeb * But, Single rate in VHT mask can be set as per-peer
3571*5c1def83SBjoern A. Zeeb * fixed rate. But even if any HT rates are configured in
3572*5c1def83SBjoern A. Zeeb * the bitrate mask, device will not switch to those rates
3573*5c1def83SBjoern A. Zeeb * when per-peer Fixed rate is set.
3574*5c1def83SBjoern A. Zeeb * TODO: Check RATEMASK_CMDID to support auto rates selection
3575*5c1def83SBjoern A. Zeeb * across HT/VHT and for multiple VHT MCS support.
3576*5c1def83SBjoern A. Zeeb */
3577*5c1def83SBjoern A. Zeeb if (sta->deflink.vht_cap.vht_supported && num_vht_rates == 1) {
3578*5c1def83SBjoern A. Zeeb ath12k_mac_set_peer_vht_fixed_rate(arvif, sta, mask,
3579*5c1def83SBjoern A. Zeeb band);
3580*5c1def83SBjoern A. Zeeb } else {
3581*5c1def83SBjoern A. Zeeb /* If the peer is non-VHT or no fixed VHT rate
3582*5c1def83SBjoern A. Zeeb * is provided in the new bitrate mask we set the
3583*5c1def83SBjoern A. Zeeb * other rates using peer_assoc command.
3584*5c1def83SBjoern A. Zeeb */
3585*5c1def83SBjoern A. Zeeb ath12k_peer_assoc_prepare(ar, arvif->vif, sta,
3586*5c1def83SBjoern A. Zeeb &peer_arg, true);
3587*5c1def83SBjoern A. Zeeb
3588*5c1def83SBjoern A. Zeeb err = ath12k_wmi_send_peer_assoc_cmd(ar, &peer_arg);
3589*5c1def83SBjoern A. Zeeb if (err)
3590*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to run peer assoc for STA %pM vdev %i: %d\n",
3591*5c1def83SBjoern A. Zeeb sta->addr, arvif->vdev_id, err);
3592*5c1def83SBjoern A. Zeeb
3593*5c1def83SBjoern A. Zeeb if (!wait_for_completion_timeout(&ar->peer_assoc_done, 1 * HZ))
3594*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to get peer assoc conf event for %pM vdev %i\n",
3595*5c1def83SBjoern A. Zeeb sta->addr, arvif->vdev_id);
3596*5c1def83SBjoern A. Zeeb }
3597*5c1def83SBjoern A. Zeeb }
3598*5c1def83SBjoern A. Zeeb err_rc_bw_changed:
3599*5c1def83SBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
3600*5c1def83SBjoern A. Zeeb }
3601*5c1def83SBjoern A. Zeeb
ath12k_mac_inc_num_stations(struct ath12k_vif * arvif,struct ieee80211_sta * sta)3602*5c1def83SBjoern A. Zeeb static int ath12k_mac_inc_num_stations(struct ath12k_vif *arvif,
3603*5c1def83SBjoern A. Zeeb struct ieee80211_sta *sta)
3604*5c1def83SBjoern A. Zeeb {
3605*5c1def83SBjoern A. Zeeb struct ath12k *ar = arvif->ar;
3606*5c1def83SBjoern A. Zeeb
3607*5c1def83SBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
3608*5c1def83SBjoern A. Zeeb
3609*5c1def83SBjoern A. Zeeb if (arvif->vdev_type == WMI_VDEV_TYPE_STA && !sta->tdls)
3610*5c1def83SBjoern A. Zeeb return 0;
3611*5c1def83SBjoern A. Zeeb
3612*5c1def83SBjoern A. Zeeb if (ar->num_stations >= ar->max_num_stations)
3613*5c1def83SBjoern A. Zeeb return -ENOBUFS;
3614*5c1def83SBjoern A. Zeeb
3615*5c1def83SBjoern A. Zeeb ar->num_stations++;
3616*5c1def83SBjoern A. Zeeb
3617*5c1def83SBjoern A. Zeeb return 0;
3618*5c1def83SBjoern A. Zeeb }
3619*5c1def83SBjoern A. Zeeb
ath12k_mac_dec_num_stations(struct ath12k_vif * arvif,struct ieee80211_sta * sta)3620*5c1def83SBjoern A. Zeeb static void ath12k_mac_dec_num_stations(struct ath12k_vif *arvif,
3621*5c1def83SBjoern A. Zeeb struct ieee80211_sta *sta)
3622*5c1def83SBjoern A. Zeeb {
3623*5c1def83SBjoern A. Zeeb struct ath12k *ar = arvif->ar;
3624*5c1def83SBjoern A. Zeeb
3625*5c1def83SBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
3626*5c1def83SBjoern A. Zeeb
3627*5c1def83SBjoern A. Zeeb if (arvif->vdev_type == WMI_VDEV_TYPE_STA && !sta->tdls)
3628*5c1def83SBjoern A. Zeeb return;
3629*5c1def83SBjoern A. Zeeb
3630*5c1def83SBjoern A. Zeeb ar->num_stations--;
3631*5c1def83SBjoern A. Zeeb }
3632*5c1def83SBjoern A. Zeeb
ath12k_mac_station_add(struct ath12k * ar,struct ieee80211_vif * vif,struct ieee80211_sta * sta)3633*5c1def83SBjoern A. Zeeb static int ath12k_mac_station_add(struct ath12k *ar,
3634*5c1def83SBjoern A. Zeeb struct ieee80211_vif *vif,
3635*5c1def83SBjoern A. Zeeb struct ieee80211_sta *sta)
3636*5c1def83SBjoern A. Zeeb {
3637*5c1def83SBjoern A. Zeeb struct ath12k_base *ab = ar->ab;
3638*5c1def83SBjoern A. Zeeb struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
3639*5c1def83SBjoern A. Zeeb struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv;
3640*5c1def83SBjoern A. Zeeb struct ath12k_wmi_peer_create_arg peer_param;
3641*5c1def83SBjoern A. Zeeb int ret;
3642*5c1def83SBjoern A. Zeeb
3643*5c1def83SBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
3644*5c1def83SBjoern A. Zeeb
3645*5c1def83SBjoern A. Zeeb ret = ath12k_mac_inc_num_stations(arvif, sta);
3646*5c1def83SBjoern A. Zeeb if (ret) {
3647*5c1def83SBjoern A. Zeeb ath12k_warn(ab, "refusing to associate station: too many connected already (%d)\n",
3648*5c1def83SBjoern A. Zeeb ar->max_num_stations);
3649*5c1def83SBjoern A. Zeeb goto exit;
3650*5c1def83SBjoern A. Zeeb }
3651*5c1def83SBjoern A. Zeeb
3652*5c1def83SBjoern A. Zeeb arsta->rx_stats = kzalloc(sizeof(*arsta->rx_stats), GFP_KERNEL);
3653*5c1def83SBjoern A. Zeeb if (!arsta->rx_stats) {
3654*5c1def83SBjoern A. Zeeb ret = -ENOMEM;
3655*5c1def83SBjoern A. Zeeb goto dec_num_station;
3656*5c1def83SBjoern A. Zeeb }
3657*5c1def83SBjoern A. Zeeb
3658*5c1def83SBjoern A. Zeeb peer_param.vdev_id = arvif->vdev_id;
3659*5c1def83SBjoern A. Zeeb peer_param.peer_addr = sta->addr;
3660*5c1def83SBjoern A. Zeeb peer_param.peer_type = WMI_PEER_TYPE_DEFAULT;
3661*5c1def83SBjoern A. Zeeb
3662*5c1def83SBjoern A. Zeeb ret = ath12k_peer_create(ar, arvif, sta, &peer_param);
3663*5c1def83SBjoern A. Zeeb if (ret) {
3664*5c1def83SBjoern A. Zeeb ath12k_warn(ab, "Failed to add peer: %pM for VDEV: %d\n",
3665*5c1def83SBjoern A. Zeeb sta->addr, arvif->vdev_id);
3666*5c1def83SBjoern A. Zeeb goto free_peer;
3667*5c1def83SBjoern A. Zeeb }
3668*5c1def83SBjoern A. Zeeb
3669*5c1def83SBjoern A. Zeeb ath12k_dbg(ab, ATH12K_DBG_MAC, "Added peer: %pM for VDEV: %d\n",
3670*5c1def83SBjoern A. Zeeb sta->addr, arvif->vdev_id);
3671*5c1def83SBjoern A. Zeeb
3672*5c1def83SBjoern A. Zeeb if (ieee80211_vif_is_mesh(vif)) {
3673*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_set_peer_param(ar, sta->addr,
3674*5c1def83SBjoern A. Zeeb arvif->vdev_id,
3675*5c1def83SBjoern A. Zeeb WMI_PEER_USE_4ADDR, 1);
3676*5c1def83SBjoern A. Zeeb if (ret) {
3677*5c1def83SBjoern A. Zeeb ath12k_warn(ab, "failed to STA %pM 4addr capability: %d\n",
3678*5c1def83SBjoern A. Zeeb sta->addr, ret);
3679*5c1def83SBjoern A. Zeeb goto free_peer;
3680*5c1def83SBjoern A. Zeeb }
3681*5c1def83SBjoern A. Zeeb }
3682*5c1def83SBjoern A. Zeeb
3683*5c1def83SBjoern A. Zeeb ret = ath12k_dp_peer_setup(ar, arvif->vdev_id, sta->addr);
3684*5c1def83SBjoern A. Zeeb if (ret) {
3685*5c1def83SBjoern A. Zeeb ath12k_warn(ab, "failed to setup dp for peer %pM on vdev %i (%d)\n",
3686*5c1def83SBjoern A. Zeeb sta->addr, arvif->vdev_id, ret);
3687*5c1def83SBjoern A. Zeeb goto free_peer;
3688*5c1def83SBjoern A. Zeeb }
3689*5c1def83SBjoern A. Zeeb
3690*5c1def83SBjoern A. Zeeb if (ab->hw_params->vdev_start_delay &&
3691*5c1def83SBjoern A. Zeeb !arvif->is_started &&
3692*5c1def83SBjoern A. Zeeb arvif->vdev_type != WMI_VDEV_TYPE_AP) {
3693*5c1def83SBjoern A. Zeeb ret = ath12k_start_vdev_delay(ar->hw, vif);
3694*5c1def83SBjoern A. Zeeb if (ret) {
3695*5c1def83SBjoern A. Zeeb ath12k_warn(ab, "failed to delay vdev start: %d\n", ret);
3696*5c1def83SBjoern A. Zeeb goto free_peer;
3697*5c1def83SBjoern A. Zeeb }
3698*5c1def83SBjoern A. Zeeb }
3699*5c1def83SBjoern A. Zeeb
3700*5c1def83SBjoern A. Zeeb return 0;
3701*5c1def83SBjoern A. Zeeb
3702*5c1def83SBjoern A. Zeeb free_peer:
3703*5c1def83SBjoern A. Zeeb ath12k_peer_delete(ar, arvif->vdev_id, sta->addr);
3704*5c1def83SBjoern A. Zeeb dec_num_station:
3705*5c1def83SBjoern A. Zeeb ath12k_mac_dec_num_stations(arvif, sta);
3706*5c1def83SBjoern A. Zeeb exit:
3707*5c1def83SBjoern A. Zeeb return ret;
3708*5c1def83SBjoern A. Zeeb }
3709*5c1def83SBjoern A. Zeeb
ath12k_mac_ieee80211_sta_bw_to_wmi(struct ath12k * ar,struct ieee80211_sta * sta)3710*5c1def83SBjoern A. Zeeb static u32 ath12k_mac_ieee80211_sta_bw_to_wmi(struct ath12k *ar,
3711*5c1def83SBjoern A. Zeeb struct ieee80211_sta *sta)
3712*5c1def83SBjoern A. Zeeb {
3713*5c1def83SBjoern A. Zeeb u32 bw = WMI_PEER_CHWIDTH_20MHZ;
3714*5c1def83SBjoern A. Zeeb
3715*5c1def83SBjoern A. Zeeb switch (sta->deflink.bandwidth) {
3716*5c1def83SBjoern A. Zeeb case IEEE80211_STA_RX_BW_20:
3717*5c1def83SBjoern A. Zeeb bw = WMI_PEER_CHWIDTH_20MHZ;
3718*5c1def83SBjoern A. Zeeb break;
3719*5c1def83SBjoern A. Zeeb case IEEE80211_STA_RX_BW_40:
3720*5c1def83SBjoern A. Zeeb bw = WMI_PEER_CHWIDTH_40MHZ;
3721*5c1def83SBjoern A. Zeeb break;
3722*5c1def83SBjoern A. Zeeb case IEEE80211_STA_RX_BW_80:
3723*5c1def83SBjoern A. Zeeb bw = WMI_PEER_CHWIDTH_80MHZ;
3724*5c1def83SBjoern A. Zeeb break;
3725*5c1def83SBjoern A. Zeeb case IEEE80211_STA_RX_BW_160:
3726*5c1def83SBjoern A. Zeeb bw = WMI_PEER_CHWIDTH_160MHZ;
3727*5c1def83SBjoern A. Zeeb break;
3728*5c1def83SBjoern A. Zeeb default:
3729*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "Invalid bandwidth %d in rc update for %pM\n",
3730*5c1def83SBjoern A. Zeeb sta->deflink.bandwidth, sta->addr);
3731*5c1def83SBjoern A. Zeeb bw = WMI_PEER_CHWIDTH_20MHZ;
3732*5c1def83SBjoern A. Zeeb break;
3733*5c1def83SBjoern A. Zeeb }
3734*5c1def83SBjoern A. Zeeb
3735*5c1def83SBjoern A. Zeeb return bw;
3736*5c1def83SBjoern A. Zeeb }
3737*5c1def83SBjoern A. Zeeb
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)3738*5c1def83SBjoern A. Zeeb static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
3739*5c1def83SBjoern A. Zeeb struct ieee80211_vif *vif,
3740*5c1def83SBjoern A. Zeeb struct ieee80211_sta *sta,
3741*5c1def83SBjoern A. Zeeb enum ieee80211_sta_state old_state,
3742*5c1def83SBjoern A. Zeeb enum ieee80211_sta_state new_state)
3743*5c1def83SBjoern A. Zeeb {
3744*5c1def83SBjoern A. Zeeb struct ath12k *ar = hw->priv;
3745*5c1def83SBjoern A. Zeeb struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
3746*5c1def83SBjoern A. Zeeb struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv;
3747*5c1def83SBjoern A. Zeeb struct ath12k_peer *peer;
3748*5c1def83SBjoern A. Zeeb int ret = 0;
3749*5c1def83SBjoern A. Zeeb
3750*5c1def83SBjoern A. Zeeb /* cancel must be done outside the mutex to avoid deadlock */
3751*5c1def83SBjoern A. Zeeb if ((old_state == IEEE80211_STA_NONE &&
3752*5c1def83SBjoern A. Zeeb new_state == IEEE80211_STA_NOTEXIST))
3753*5c1def83SBjoern A. Zeeb cancel_work_sync(&arsta->update_wk);
3754*5c1def83SBjoern A. Zeeb
3755*5c1def83SBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
3756*5c1def83SBjoern A. Zeeb
3757*5c1def83SBjoern A. Zeeb if (old_state == IEEE80211_STA_NOTEXIST &&
3758*5c1def83SBjoern A. Zeeb new_state == IEEE80211_STA_NONE) {
3759*5c1def83SBjoern A. Zeeb memset(arsta, 0, sizeof(*arsta));
3760*5c1def83SBjoern A. Zeeb arsta->arvif = arvif;
3761*5c1def83SBjoern A. Zeeb INIT_WORK(&arsta->update_wk, ath12k_sta_rc_update_wk);
3762*5c1def83SBjoern A. Zeeb
3763*5c1def83SBjoern A. Zeeb ret = ath12k_mac_station_add(ar, vif, sta);
3764*5c1def83SBjoern A. Zeeb if (ret)
3765*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "Failed to add station: %pM for VDEV: %d\n",
3766*5c1def83SBjoern A. Zeeb sta->addr, arvif->vdev_id);
3767*5c1def83SBjoern A. Zeeb } else if ((old_state == IEEE80211_STA_NONE &&
3768*5c1def83SBjoern A. Zeeb new_state == IEEE80211_STA_NOTEXIST)) {
3769*5c1def83SBjoern A. Zeeb ath12k_dp_peer_cleanup(ar, arvif->vdev_id, sta->addr);
3770*5c1def83SBjoern A. Zeeb
3771*5c1def83SBjoern A. Zeeb ret = ath12k_peer_delete(ar, arvif->vdev_id, sta->addr);
3772*5c1def83SBjoern A. Zeeb if (ret)
3773*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "Failed to delete peer: %pM for VDEV: %d\n",
3774*5c1def83SBjoern A. Zeeb sta->addr, arvif->vdev_id);
3775*5c1def83SBjoern A. Zeeb else
3776*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "Removed peer: %pM for VDEV: %d\n",
3777*5c1def83SBjoern A. Zeeb sta->addr, arvif->vdev_id);
3778*5c1def83SBjoern A. Zeeb
3779*5c1def83SBjoern A. Zeeb ath12k_mac_dec_num_stations(arvif, sta);
3780*5c1def83SBjoern A. Zeeb spin_lock_bh(&ar->ab->base_lock);
3781*5c1def83SBjoern A. Zeeb peer = ath12k_peer_find(ar->ab, arvif->vdev_id, sta->addr);
3782*5c1def83SBjoern A. Zeeb if (peer && peer->sta == sta) {
3783*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "Found peer entry %pM n vdev %i after it was supposedly removed\n",
3784*5c1def83SBjoern A. Zeeb vif->addr, arvif->vdev_id);
3785*5c1def83SBjoern A. Zeeb peer->sta = NULL;
3786*5c1def83SBjoern A. Zeeb list_del(&peer->list);
3787*5c1def83SBjoern A. Zeeb kfree(peer);
3788*5c1def83SBjoern A. Zeeb ar->num_peers--;
3789*5c1def83SBjoern A. Zeeb }
3790*5c1def83SBjoern A. Zeeb spin_unlock_bh(&ar->ab->base_lock);
3791*5c1def83SBjoern A. Zeeb
3792*5c1def83SBjoern A. Zeeb kfree(arsta->rx_stats);
3793*5c1def83SBjoern A. Zeeb arsta->rx_stats = NULL;
3794*5c1def83SBjoern A. Zeeb } else if (old_state == IEEE80211_STA_AUTH &&
3795*5c1def83SBjoern A. Zeeb new_state == IEEE80211_STA_ASSOC &&
3796*5c1def83SBjoern A. Zeeb (vif->type == NL80211_IFTYPE_AP ||
3797*5c1def83SBjoern A. Zeeb vif->type == NL80211_IFTYPE_MESH_POINT ||
3798*5c1def83SBjoern A. Zeeb vif->type == NL80211_IFTYPE_ADHOC)) {
3799*5c1def83SBjoern A. Zeeb ret = ath12k_station_assoc(ar, vif, sta, false);
3800*5c1def83SBjoern A. Zeeb if (ret)
3801*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "Failed to associate station: %pM\n",
3802*5c1def83SBjoern A. Zeeb sta->addr);
3803*5c1def83SBjoern A. Zeeb
3804*5c1def83SBjoern A. Zeeb spin_lock_bh(&ar->data_lock);
3805*5c1def83SBjoern A. Zeeb
3806*5c1def83SBjoern A. Zeeb arsta->bw = ath12k_mac_ieee80211_sta_bw_to_wmi(ar, sta);
3807*5c1def83SBjoern A. Zeeb arsta->bw_prev = sta->deflink.bandwidth;
3808*5c1def83SBjoern A. Zeeb
3809*5c1def83SBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
3810*5c1def83SBjoern A. Zeeb } else if (old_state == IEEE80211_STA_ASSOC &&
3811*5c1def83SBjoern A. Zeeb new_state == IEEE80211_STA_AUTHORIZED) {
3812*5c1def83SBjoern A. Zeeb spin_lock_bh(&ar->ab->base_lock);
3813*5c1def83SBjoern A. Zeeb
3814*5c1def83SBjoern A. Zeeb peer = ath12k_peer_find(ar->ab, arvif->vdev_id, sta->addr);
3815*5c1def83SBjoern A. Zeeb if (peer)
3816*5c1def83SBjoern A. Zeeb peer->is_authorized = true;
3817*5c1def83SBjoern A. Zeeb
3818*5c1def83SBjoern A. Zeeb spin_unlock_bh(&ar->ab->base_lock);
3819*5c1def83SBjoern A. Zeeb
3820*5c1def83SBjoern A. Zeeb if (vif->type == NL80211_IFTYPE_STATION && arvif->is_up) {
3821*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_set_peer_param(ar, sta->addr,
3822*5c1def83SBjoern A. Zeeb arvif->vdev_id,
3823*5c1def83SBjoern A. Zeeb WMI_PEER_AUTHORIZE,
3824*5c1def83SBjoern A. Zeeb 1);
3825*5c1def83SBjoern A. Zeeb if (ret)
3826*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "Unable to authorize peer %pM vdev %d: %d\n",
3827*5c1def83SBjoern A. Zeeb sta->addr, arvif->vdev_id, ret);
3828*5c1def83SBjoern A. Zeeb }
3829*5c1def83SBjoern A. Zeeb } else if (old_state == IEEE80211_STA_AUTHORIZED &&
3830*5c1def83SBjoern A. Zeeb new_state == IEEE80211_STA_ASSOC) {
3831*5c1def83SBjoern A. Zeeb spin_lock_bh(&ar->ab->base_lock);
3832*5c1def83SBjoern A. Zeeb
3833*5c1def83SBjoern A. Zeeb peer = ath12k_peer_find(ar->ab, arvif->vdev_id, sta->addr);
3834*5c1def83SBjoern A. Zeeb if (peer)
3835*5c1def83SBjoern A. Zeeb peer->is_authorized = false;
3836*5c1def83SBjoern A. Zeeb
3837*5c1def83SBjoern A. Zeeb spin_unlock_bh(&ar->ab->base_lock);
3838*5c1def83SBjoern A. Zeeb } else if (old_state == IEEE80211_STA_ASSOC &&
3839*5c1def83SBjoern A. Zeeb new_state == IEEE80211_STA_AUTH &&
3840*5c1def83SBjoern A. Zeeb (vif->type == NL80211_IFTYPE_AP ||
3841*5c1def83SBjoern A. Zeeb vif->type == NL80211_IFTYPE_MESH_POINT ||
3842*5c1def83SBjoern A. Zeeb vif->type == NL80211_IFTYPE_ADHOC)) {
3843*5c1def83SBjoern A. Zeeb ret = ath12k_station_disassoc(ar, vif, sta);
3844*5c1def83SBjoern A. Zeeb if (ret)
3845*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "Failed to disassociate station: %pM\n",
3846*5c1def83SBjoern A. Zeeb sta->addr);
3847*5c1def83SBjoern A. Zeeb }
3848*5c1def83SBjoern A. Zeeb
3849*5c1def83SBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
3850*5c1def83SBjoern A. Zeeb return ret;
3851*5c1def83SBjoern A. Zeeb }
3852*5c1def83SBjoern A. Zeeb
ath12k_mac_op_sta_set_txpwr(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_sta * sta)3853*5c1def83SBjoern A. Zeeb static int ath12k_mac_op_sta_set_txpwr(struct ieee80211_hw *hw,
3854*5c1def83SBjoern A. Zeeb struct ieee80211_vif *vif,
3855*5c1def83SBjoern A. Zeeb struct ieee80211_sta *sta)
3856*5c1def83SBjoern A. Zeeb {
3857*5c1def83SBjoern A. Zeeb struct ath12k *ar = hw->priv;
3858*5c1def83SBjoern A. Zeeb struct ath12k_vif *arvif = (void *)vif->drv_priv;
3859*5c1def83SBjoern A. Zeeb int ret;
3860*5c1def83SBjoern A. Zeeb s16 txpwr;
3861*5c1def83SBjoern A. Zeeb
3862*5c1def83SBjoern A. Zeeb if (sta->deflink.txpwr.type == NL80211_TX_POWER_AUTOMATIC) {
3863*5c1def83SBjoern A. Zeeb txpwr = 0;
3864*5c1def83SBjoern A. Zeeb } else {
3865*5c1def83SBjoern A. Zeeb txpwr = sta->deflink.txpwr.power;
3866*5c1def83SBjoern A. Zeeb if (!txpwr)
3867*5c1def83SBjoern A. Zeeb return -EINVAL;
3868*5c1def83SBjoern A. Zeeb }
3869*5c1def83SBjoern A. Zeeb
3870*5c1def83SBjoern A. Zeeb if (txpwr > ATH12K_TX_POWER_MAX_VAL || txpwr < ATH12K_TX_POWER_MIN_VAL)
3871*5c1def83SBjoern A. Zeeb return -EINVAL;
3872*5c1def83SBjoern A. Zeeb
3873*5c1def83SBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
3874*5c1def83SBjoern A. Zeeb
3875*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,
3876*5c1def83SBjoern A. Zeeb WMI_PEER_USE_FIXED_PWR, txpwr);
3877*5c1def83SBjoern A. Zeeb if (ret) {
3878*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to set tx power for station ret: %d\n",
3879*5c1def83SBjoern A. Zeeb ret);
3880*5c1def83SBjoern A. Zeeb goto out;
3881*5c1def83SBjoern A. Zeeb }
3882*5c1def83SBjoern A. Zeeb
3883*5c1def83SBjoern A. Zeeb out:
3884*5c1def83SBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
3885*5c1def83SBjoern A. Zeeb return ret;
3886*5c1def83SBjoern A. Zeeb }
3887*5c1def83SBjoern A. Zeeb
ath12k_mac_op_sta_rc_update(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_sta * sta,u32 changed)3888*5c1def83SBjoern A. Zeeb static void ath12k_mac_op_sta_rc_update(struct ieee80211_hw *hw,
3889*5c1def83SBjoern A. Zeeb struct ieee80211_vif *vif,
3890*5c1def83SBjoern A. Zeeb struct ieee80211_sta *sta,
3891*5c1def83SBjoern A. Zeeb u32 changed)
3892*5c1def83SBjoern A. Zeeb {
3893*5c1def83SBjoern A. Zeeb struct ath12k *ar = hw->priv;
3894*5c1def83SBjoern A. Zeeb struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv;
3895*5c1def83SBjoern A. Zeeb struct ath12k_vif *arvif = (void *)vif->drv_priv;
3896*5c1def83SBjoern A. Zeeb struct ath12k_peer *peer;
3897*5c1def83SBjoern A. Zeeb u32 bw, smps;
3898*5c1def83SBjoern A. Zeeb
3899*5c1def83SBjoern A. Zeeb spin_lock_bh(&ar->ab->base_lock);
3900*5c1def83SBjoern A. Zeeb
3901*5c1def83SBjoern A. Zeeb peer = ath12k_peer_find(ar->ab, arvif->vdev_id, sta->addr);
3902*5c1def83SBjoern A. Zeeb if (!peer) {
3903*5c1def83SBjoern A. Zeeb spin_unlock_bh(&ar->ab->base_lock);
3904*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "mac sta rc update failed to find peer %pM on vdev %i\n",
3905*5c1def83SBjoern A. Zeeb sta->addr, arvif->vdev_id);
3906*5c1def83SBjoern A. Zeeb return;
3907*5c1def83SBjoern A. Zeeb }
3908*5c1def83SBjoern A. Zeeb
3909*5c1def83SBjoern A. Zeeb spin_unlock_bh(&ar->ab->base_lock);
3910*5c1def83SBjoern A. Zeeb
3911*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
3912*5c1def83SBjoern A. Zeeb "mac sta rc update for %pM changed %08x bw %d nss %d smps %d\n",
3913*5c1def83SBjoern A. Zeeb sta->addr, changed, sta->deflink.bandwidth, sta->deflink.rx_nss,
3914*5c1def83SBjoern A. Zeeb sta->deflink.smps_mode);
3915*5c1def83SBjoern A. Zeeb
3916*5c1def83SBjoern A. Zeeb spin_lock_bh(&ar->data_lock);
3917*5c1def83SBjoern A. Zeeb
3918*5c1def83SBjoern A. Zeeb if (changed & IEEE80211_RC_BW_CHANGED) {
3919*5c1def83SBjoern A. Zeeb bw = ath12k_mac_ieee80211_sta_bw_to_wmi(ar, sta);
3920*5c1def83SBjoern A. Zeeb arsta->bw_prev = arsta->bw;
3921*5c1def83SBjoern A. Zeeb arsta->bw = bw;
3922*5c1def83SBjoern A. Zeeb }
3923*5c1def83SBjoern A. Zeeb
3924*5c1def83SBjoern A. Zeeb if (changed & IEEE80211_RC_NSS_CHANGED)
3925*5c1def83SBjoern A. Zeeb arsta->nss = sta->deflink.rx_nss;
3926*5c1def83SBjoern A. Zeeb
3927*5c1def83SBjoern A. Zeeb if (changed & IEEE80211_RC_SMPS_CHANGED) {
3928*5c1def83SBjoern A. Zeeb smps = WMI_PEER_SMPS_PS_NONE;
3929*5c1def83SBjoern A. Zeeb
3930*5c1def83SBjoern A. Zeeb switch (sta->deflink.smps_mode) {
3931*5c1def83SBjoern A. Zeeb case IEEE80211_SMPS_AUTOMATIC:
3932*5c1def83SBjoern A. Zeeb case IEEE80211_SMPS_OFF:
3933*5c1def83SBjoern A. Zeeb smps = WMI_PEER_SMPS_PS_NONE;
3934*5c1def83SBjoern A. Zeeb break;
3935*5c1def83SBjoern A. Zeeb case IEEE80211_SMPS_STATIC:
3936*5c1def83SBjoern A. Zeeb smps = WMI_PEER_SMPS_STATIC;
3937*5c1def83SBjoern A. Zeeb break;
3938*5c1def83SBjoern A. Zeeb case IEEE80211_SMPS_DYNAMIC:
3939*5c1def83SBjoern A. Zeeb smps = WMI_PEER_SMPS_DYNAMIC;
3940*5c1def83SBjoern A. Zeeb break;
3941*5c1def83SBjoern A. Zeeb default:
3942*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "Invalid smps %d in sta rc update for %pM\n",
3943*5c1def83SBjoern A. Zeeb sta->deflink.smps_mode, sta->addr);
3944*5c1def83SBjoern A. Zeeb smps = WMI_PEER_SMPS_PS_NONE;
3945*5c1def83SBjoern A. Zeeb break;
3946*5c1def83SBjoern A. Zeeb }
3947*5c1def83SBjoern A. Zeeb
3948*5c1def83SBjoern A. Zeeb arsta->smps = smps;
3949*5c1def83SBjoern A. Zeeb }
3950*5c1def83SBjoern A. Zeeb
3951*5c1def83SBjoern A. Zeeb arsta->changed |= changed;
3952*5c1def83SBjoern A. Zeeb
3953*5c1def83SBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
3954*5c1def83SBjoern A. Zeeb
3955*5c1def83SBjoern A. Zeeb ieee80211_queue_work(hw, &arsta->update_wk);
3956*5c1def83SBjoern A. Zeeb }
3957*5c1def83SBjoern A. Zeeb
ath12k_conf_tx_uapsd(struct ath12k * ar,struct ieee80211_vif * vif,u16 ac,bool enable)3958*5c1def83SBjoern A. Zeeb static int ath12k_conf_tx_uapsd(struct ath12k *ar, struct ieee80211_vif *vif,
3959*5c1def83SBjoern A. Zeeb u16 ac, bool enable)
3960*5c1def83SBjoern A. Zeeb {
3961*5c1def83SBjoern A. Zeeb struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
3962*5c1def83SBjoern A. Zeeb u32 value;
3963*5c1def83SBjoern A. Zeeb int ret;
3964*5c1def83SBjoern A. Zeeb
3965*5c1def83SBjoern A. Zeeb if (arvif->vdev_type != WMI_VDEV_TYPE_STA)
3966*5c1def83SBjoern A. Zeeb return 0;
3967*5c1def83SBjoern A. Zeeb
3968*5c1def83SBjoern A. Zeeb switch (ac) {
3969*5c1def83SBjoern A. Zeeb case IEEE80211_AC_VO:
3970*5c1def83SBjoern A. Zeeb value = WMI_STA_PS_UAPSD_AC3_DELIVERY_EN |
3971*5c1def83SBjoern A. Zeeb WMI_STA_PS_UAPSD_AC3_TRIGGER_EN;
3972*5c1def83SBjoern A. Zeeb break;
3973*5c1def83SBjoern A. Zeeb case IEEE80211_AC_VI:
3974*5c1def83SBjoern A. Zeeb value = WMI_STA_PS_UAPSD_AC2_DELIVERY_EN |
3975*5c1def83SBjoern A. Zeeb WMI_STA_PS_UAPSD_AC2_TRIGGER_EN;
3976*5c1def83SBjoern A. Zeeb break;
3977*5c1def83SBjoern A. Zeeb case IEEE80211_AC_BE:
3978*5c1def83SBjoern A. Zeeb value = WMI_STA_PS_UAPSD_AC1_DELIVERY_EN |
3979*5c1def83SBjoern A. Zeeb WMI_STA_PS_UAPSD_AC1_TRIGGER_EN;
3980*5c1def83SBjoern A. Zeeb break;
3981*5c1def83SBjoern A. Zeeb case IEEE80211_AC_BK:
3982*5c1def83SBjoern A. Zeeb value = WMI_STA_PS_UAPSD_AC0_DELIVERY_EN |
3983*5c1def83SBjoern A. Zeeb WMI_STA_PS_UAPSD_AC0_TRIGGER_EN;
3984*5c1def83SBjoern A. Zeeb break;
3985*5c1def83SBjoern A. Zeeb }
3986*5c1def83SBjoern A. Zeeb
3987*5c1def83SBjoern A. Zeeb if (enable)
3988*5c1def83SBjoern A. Zeeb arvif->u.sta.uapsd |= value;
3989*5c1def83SBjoern A. Zeeb else
3990*5c1def83SBjoern A. Zeeb arvif->u.sta.uapsd &= ~value;
3991*5c1def83SBjoern A. Zeeb
3992*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_set_sta_ps_param(ar, arvif->vdev_id,
3993*5c1def83SBjoern A. Zeeb WMI_STA_PS_PARAM_UAPSD,
3994*5c1def83SBjoern A. Zeeb arvif->u.sta.uapsd);
3995*5c1def83SBjoern A. Zeeb if (ret) {
3996*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "could not set uapsd params %d\n", ret);
3997*5c1def83SBjoern A. Zeeb goto exit;
3998*5c1def83SBjoern A. Zeeb }
3999*5c1def83SBjoern A. Zeeb
4000*5c1def83SBjoern A. Zeeb if (arvif->u.sta.uapsd)
4001*5c1def83SBjoern A. Zeeb value = WMI_STA_PS_RX_WAKE_POLICY_POLL_UAPSD;
4002*5c1def83SBjoern A. Zeeb else
4003*5c1def83SBjoern A. Zeeb value = WMI_STA_PS_RX_WAKE_POLICY_WAKE;
4004*5c1def83SBjoern A. Zeeb
4005*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_set_sta_ps_param(ar, arvif->vdev_id,
4006*5c1def83SBjoern A. Zeeb WMI_STA_PS_PARAM_RX_WAKE_POLICY,
4007*5c1def83SBjoern A. Zeeb value);
4008*5c1def83SBjoern A. Zeeb if (ret)
4009*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "could not set rx wake param %d\n", ret);
4010*5c1def83SBjoern A. Zeeb
4011*5c1def83SBjoern A. Zeeb exit:
4012*5c1def83SBjoern A. Zeeb return ret;
4013*5c1def83SBjoern A. Zeeb }
4014*5c1def83SBjoern A. Zeeb
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)4015*5c1def83SBjoern A. Zeeb static int ath12k_mac_op_conf_tx(struct ieee80211_hw *hw,
4016*5c1def83SBjoern A. Zeeb struct ieee80211_vif *vif,
4017*5c1def83SBjoern A. Zeeb unsigned int link_id, u16 ac,
4018*5c1def83SBjoern A. Zeeb const struct ieee80211_tx_queue_params *params)
4019*5c1def83SBjoern A. Zeeb {
4020*5c1def83SBjoern A. Zeeb struct ath12k *ar = hw->priv;
4021*5c1def83SBjoern A. Zeeb struct ath12k_vif *arvif = (void *)vif->drv_priv;
4022*5c1def83SBjoern A. Zeeb struct wmi_wmm_params_arg *p = NULL;
4023*5c1def83SBjoern A. Zeeb int ret;
4024*5c1def83SBjoern A. Zeeb
4025*5c1def83SBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
4026*5c1def83SBjoern A. Zeeb
4027*5c1def83SBjoern A. Zeeb switch (ac) {
4028*5c1def83SBjoern A. Zeeb case IEEE80211_AC_VO:
4029*5c1def83SBjoern A. Zeeb p = &arvif->wmm_params.ac_vo;
4030*5c1def83SBjoern A. Zeeb break;
4031*5c1def83SBjoern A. Zeeb case IEEE80211_AC_VI:
4032*5c1def83SBjoern A. Zeeb p = &arvif->wmm_params.ac_vi;
4033*5c1def83SBjoern A. Zeeb break;
4034*5c1def83SBjoern A. Zeeb case IEEE80211_AC_BE:
4035*5c1def83SBjoern A. Zeeb p = &arvif->wmm_params.ac_be;
4036*5c1def83SBjoern A. Zeeb break;
4037*5c1def83SBjoern A. Zeeb case IEEE80211_AC_BK:
4038*5c1def83SBjoern A. Zeeb p = &arvif->wmm_params.ac_bk;
4039*5c1def83SBjoern A. Zeeb break;
4040*5c1def83SBjoern A. Zeeb }
4041*5c1def83SBjoern A. Zeeb
4042*5c1def83SBjoern A. Zeeb if (WARN_ON(!p)) {
4043*5c1def83SBjoern A. Zeeb ret = -EINVAL;
4044*5c1def83SBjoern A. Zeeb goto exit;
4045*5c1def83SBjoern A. Zeeb }
4046*5c1def83SBjoern A. Zeeb
4047*5c1def83SBjoern A. Zeeb p->cwmin = params->cw_min;
4048*5c1def83SBjoern A. Zeeb p->cwmax = params->cw_max;
4049*5c1def83SBjoern A. Zeeb p->aifs = params->aifs;
4050*5c1def83SBjoern A. Zeeb p->txop = params->txop;
4051*5c1def83SBjoern A. Zeeb
4052*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_send_wmm_update_cmd(ar, arvif->vdev_id,
4053*5c1def83SBjoern A. Zeeb &arvif->wmm_params);
4054*5c1def83SBjoern A. Zeeb if (ret) {
4055*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to set wmm params: %d\n", ret);
4056*5c1def83SBjoern A. Zeeb goto exit;
4057*5c1def83SBjoern A. Zeeb }
4058*5c1def83SBjoern A. Zeeb
4059*5c1def83SBjoern A. Zeeb ret = ath12k_conf_tx_uapsd(ar, vif, ac, params->uapsd);
4060*5c1def83SBjoern A. Zeeb
4061*5c1def83SBjoern A. Zeeb if (ret)
4062*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to set sta uapsd: %d\n", ret);
4063*5c1def83SBjoern A. Zeeb
4064*5c1def83SBjoern A. Zeeb exit:
4065*5c1def83SBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
4066*5c1def83SBjoern A. Zeeb return ret;
4067*5c1def83SBjoern A. Zeeb }
4068*5c1def83SBjoern A. Zeeb
4069*5c1def83SBjoern A. Zeeb static struct ieee80211_sta_ht_cap
ath12k_create_ht_cap(struct ath12k * ar,u32 ar_ht_cap,u32 rate_cap_rx_chainmask)4070*5c1def83SBjoern A. Zeeb ath12k_create_ht_cap(struct ath12k *ar, u32 ar_ht_cap, u32 rate_cap_rx_chainmask)
4071*5c1def83SBjoern A. Zeeb {
4072*5c1def83SBjoern A. Zeeb int i;
4073*5c1def83SBjoern A. Zeeb struct ieee80211_sta_ht_cap ht_cap = {0};
4074*5c1def83SBjoern A. Zeeb u32 ar_vht_cap = ar->pdev->cap.vht_cap;
4075*5c1def83SBjoern A. Zeeb
4076*5c1def83SBjoern A. Zeeb if (!(ar_ht_cap & WMI_HT_CAP_ENABLED))
4077*5c1def83SBjoern A. Zeeb return ht_cap;
4078*5c1def83SBjoern A. Zeeb
4079*5c1def83SBjoern A. Zeeb ht_cap.ht_supported = 1;
4080*5c1def83SBjoern A. Zeeb ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
4081*5c1def83SBjoern A. Zeeb ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE;
4082*5c1def83SBjoern A. Zeeb ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
4083*5c1def83SBjoern A. Zeeb ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40;
4084*5c1def83SBjoern A. Zeeb ht_cap.cap |= WLAN_HT_CAP_SM_PS_STATIC << IEEE80211_HT_CAP_SM_PS_SHIFT;
4085*5c1def83SBjoern A. Zeeb
4086*5c1def83SBjoern A. Zeeb if (ar_ht_cap & WMI_HT_CAP_HT20_SGI)
4087*5c1def83SBjoern A. Zeeb ht_cap.cap |= IEEE80211_HT_CAP_SGI_20;
4088*5c1def83SBjoern A. Zeeb
4089*5c1def83SBjoern A. Zeeb if (ar_ht_cap & WMI_HT_CAP_HT40_SGI)
4090*5c1def83SBjoern A. Zeeb ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
4091*5c1def83SBjoern A. Zeeb
4092*5c1def83SBjoern A. Zeeb if (ar_ht_cap & WMI_HT_CAP_DYNAMIC_SMPS) {
4093*5c1def83SBjoern A. Zeeb u32 smps;
4094*5c1def83SBjoern A. Zeeb
4095*5c1def83SBjoern A. Zeeb smps = WLAN_HT_CAP_SM_PS_DYNAMIC;
4096*5c1def83SBjoern A. Zeeb smps <<= IEEE80211_HT_CAP_SM_PS_SHIFT;
4097*5c1def83SBjoern A. Zeeb
4098*5c1def83SBjoern A. Zeeb ht_cap.cap |= smps;
4099*5c1def83SBjoern A. Zeeb }
4100*5c1def83SBjoern A. Zeeb
4101*5c1def83SBjoern A. Zeeb if (ar_ht_cap & WMI_HT_CAP_TX_STBC)
4102*5c1def83SBjoern A. Zeeb ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC;
4103*5c1def83SBjoern A. Zeeb
4104*5c1def83SBjoern A. Zeeb if (ar_ht_cap & WMI_HT_CAP_RX_STBC) {
4105*5c1def83SBjoern A. Zeeb u32 stbc;
4106*5c1def83SBjoern A. Zeeb
4107*5c1def83SBjoern A. Zeeb stbc = ar_ht_cap;
4108*5c1def83SBjoern A. Zeeb stbc &= WMI_HT_CAP_RX_STBC;
4109*5c1def83SBjoern A. Zeeb stbc >>= WMI_HT_CAP_RX_STBC_MASK_SHIFT;
4110*5c1def83SBjoern A. Zeeb stbc <<= IEEE80211_HT_CAP_RX_STBC_SHIFT;
4111*5c1def83SBjoern A. Zeeb stbc &= IEEE80211_HT_CAP_RX_STBC;
4112*5c1def83SBjoern A. Zeeb
4113*5c1def83SBjoern A. Zeeb ht_cap.cap |= stbc;
4114*5c1def83SBjoern A. Zeeb }
4115*5c1def83SBjoern A. Zeeb
4116*5c1def83SBjoern A. Zeeb if (ar_ht_cap & WMI_HT_CAP_RX_LDPC)
4117*5c1def83SBjoern A. Zeeb ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING;
4118*5c1def83SBjoern A. Zeeb
4119*5c1def83SBjoern A. Zeeb if (ar_ht_cap & WMI_HT_CAP_L_SIG_TXOP_PROT)
4120*5c1def83SBjoern A. Zeeb ht_cap.cap |= IEEE80211_HT_CAP_LSIG_TXOP_PROT;
4121*5c1def83SBjoern A. Zeeb
4122*5c1def83SBjoern A. Zeeb if (ar_vht_cap & WMI_VHT_CAP_MAX_MPDU_LEN_MASK)
4123*5c1def83SBjoern A. Zeeb ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU;
4124*5c1def83SBjoern A. Zeeb
4125*5c1def83SBjoern A. Zeeb for (i = 0; i < ar->num_rx_chains; i++) {
4126*5c1def83SBjoern A. Zeeb if (rate_cap_rx_chainmask & BIT(i))
4127*5c1def83SBjoern A. Zeeb ht_cap.mcs.rx_mask[i] = 0xFF;
4128*5c1def83SBjoern A. Zeeb }
4129*5c1def83SBjoern A. Zeeb
4130*5c1def83SBjoern A. Zeeb ht_cap.mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
4131*5c1def83SBjoern A. Zeeb
4132*5c1def83SBjoern A. Zeeb return ht_cap;
4133*5c1def83SBjoern A. Zeeb }
4134*5c1def83SBjoern A. Zeeb
ath12k_mac_set_txbf_conf(struct ath12k_vif * arvif)4135*5c1def83SBjoern A. Zeeb static int ath12k_mac_set_txbf_conf(struct ath12k_vif *arvif)
4136*5c1def83SBjoern A. Zeeb {
4137*5c1def83SBjoern A. Zeeb u32 value = 0;
4138*5c1def83SBjoern A. Zeeb struct ath12k *ar = arvif->ar;
4139*5c1def83SBjoern A. Zeeb int nsts;
4140*5c1def83SBjoern A. Zeeb int sound_dim;
4141*5c1def83SBjoern A. Zeeb u32 vht_cap = ar->pdev->cap.vht_cap;
4142*5c1def83SBjoern A. Zeeb u32 vdev_param = WMI_VDEV_PARAM_TXBF;
4143*5c1def83SBjoern A. Zeeb
4144*5c1def83SBjoern A. Zeeb if (vht_cap & (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE)) {
4145*5c1def83SBjoern A. Zeeb nsts = vht_cap & IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK;
4146*5c1def83SBjoern A. Zeeb nsts >>= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT;
4147*5c1def83SBjoern A. Zeeb value |= SM(nsts, WMI_TXBF_STS_CAP_OFFSET);
4148*5c1def83SBjoern A. Zeeb }
4149*5c1def83SBjoern A. Zeeb
4150*5c1def83SBjoern A. Zeeb if (vht_cap & (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)) {
4151*5c1def83SBjoern A. Zeeb sound_dim = vht_cap &
4152*5c1def83SBjoern A. Zeeb IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK;
4153*5c1def83SBjoern A. Zeeb sound_dim >>= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT;
4154*5c1def83SBjoern A. Zeeb if (sound_dim > (ar->num_tx_chains - 1))
4155*5c1def83SBjoern A. Zeeb sound_dim = ar->num_tx_chains - 1;
4156*5c1def83SBjoern A. Zeeb value |= SM(sound_dim, WMI_BF_SOUND_DIM_OFFSET);
4157*5c1def83SBjoern A. Zeeb }
4158*5c1def83SBjoern A. Zeeb
4159*5c1def83SBjoern A. Zeeb if (!value)
4160*5c1def83SBjoern A. Zeeb return 0;
4161*5c1def83SBjoern A. Zeeb
4162*5c1def83SBjoern A. Zeeb if (vht_cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE) {
4163*5c1def83SBjoern A. Zeeb value |= WMI_VDEV_PARAM_TXBF_SU_TX_BFER;
4164*5c1def83SBjoern A. Zeeb
4165*5c1def83SBjoern A. Zeeb if ((vht_cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) &&
4166*5c1def83SBjoern A. Zeeb arvif->vdev_type == WMI_VDEV_TYPE_AP)
4167*5c1def83SBjoern A. Zeeb value |= WMI_VDEV_PARAM_TXBF_MU_TX_BFER;
4168*5c1def83SBjoern A. Zeeb }
4169*5c1def83SBjoern A. Zeeb
4170*5c1def83SBjoern A. Zeeb if (vht_cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE) {
4171*5c1def83SBjoern A. Zeeb value |= WMI_VDEV_PARAM_TXBF_SU_TX_BFEE;
4172*5c1def83SBjoern A. Zeeb
4173*5c1def83SBjoern A. Zeeb if ((vht_cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE) &&
4174*5c1def83SBjoern A. Zeeb arvif->vdev_type == WMI_VDEV_TYPE_STA)
4175*5c1def83SBjoern A. Zeeb value |= WMI_VDEV_PARAM_TXBF_MU_TX_BFEE;
4176*5c1def83SBjoern A. Zeeb }
4177*5c1def83SBjoern A. Zeeb
4178*5c1def83SBjoern A. Zeeb return ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
4179*5c1def83SBjoern A. Zeeb vdev_param, value);
4180*5c1def83SBjoern A. Zeeb }
4181*5c1def83SBjoern A. Zeeb
ath12k_set_vht_txbf_cap(struct ath12k * ar,u32 * vht_cap)4182*5c1def83SBjoern A. Zeeb static void ath12k_set_vht_txbf_cap(struct ath12k *ar, u32 *vht_cap)
4183*5c1def83SBjoern A. Zeeb {
4184*5c1def83SBjoern A. Zeeb bool subfer, subfee;
4185*5c1def83SBjoern A. Zeeb int sound_dim = 0;
4186*5c1def83SBjoern A. Zeeb
4187*5c1def83SBjoern A. Zeeb subfer = !!(*vht_cap & (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE));
4188*5c1def83SBjoern A. Zeeb subfee = !!(*vht_cap & (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE));
4189*5c1def83SBjoern A. Zeeb
4190*5c1def83SBjoern A. Zeeb if (ar->num_tx_chains < 2) {
4191*5c1def83SBjoern A. Zeeb *vht_cap &= ~(IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE);
4192*5c1def83SBjoern A. Zeeb subfer = false;
4193*5c1def83SBjoern A. Zeeb }
4194*5c1def83SBjoern A. Zeeb
4195*5c1def83SBjoern A. Zeeb /* If SU Beaformer is not set, then disable MU Beamformer Capability */
4196*5c1def83SBjoern A. Zeeb if (!subfer)
4197*5c1def83SBjoern A. Zeeb *vht_cap &= ~(IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE);
4198*5c1def83SBjoern A. Zeeb
4199*5c1def83SBjoern A. Zeeb /* If SU Beaformee is not set, then disable MU Beamformee Capability */
4200*5c1def83SBjoern A. Zeeb if (!subfee)
4201*5c1def83SBjoern A. Zeeb *vht_cap &= ~(IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE);
4202*5c1def83SBjoern A. Zeeb
4203*5c1def83SBjoern A. Zeeb sound_dim = u32_get_bits(*vht_cap,
4204*5c1def83SBjoern A. Zeeb IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK);
4205*5c1def83SBjoern A. Zeeb *vht_cap = u32_replace_bits(*vht_cap, 0,
4206*5c1def83SBjoern A. Zeeb IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK);
4207*5c1def83SBjoern A. Zeeb
4208*5c1def83SBjoern A. Zeeb /* TODO: Need to check invalid STS and Sound_dim values set by FW? */
4209*5c1def83SBjoern A. Zeeb
4210*5c1def83SBjoern A. Zeeb /* Enable Sounding Dimension Field only if SU BF is enabled */
4211*5c1def83SBjoern A. Zeeb if (subfer) {
4212*5c1def83SBjoern A. Zeeb if (sound_dim > (ar->num_tx_chains - 1))
4213*5c1def83SBjoern A. Zeeb sound_dim = ar->num_tx_chains - 1;
4214*5c1def83SBjoern A. Zeeb
4215*5c1def83SBjoern A. Zeeb *vht_cap = u32_replace_bits(*vht_cap, sound_dim,
4216*5c1def83SBjoern A. Zeeb IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK);
4217*5c1def83SBjoern A. Zeeb }
4218*5c1def83SBjoern A. Zeeb
4219*5c1def83SBjoern A. Zeeb /* Use the STS advertised by FW unless SU Beamformee is not supported*/
4220*5c1def83SBjoern A. Zeeb if (!subfee)
4221*5c1def83SBjoern A. Zeeb *vht_cap &= ~(IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK);
4222*5c1def83SBjoern A. Zeeb }
4223*5c1def83SBjoern A. Zeeb
4224*5c1def83SBjoern A. Zeeb static struct ieee80211_sta_vht_cap
ath12k_create_vht_cap(struct ath12k * ar,u32 rate_cap_tx_chainmask,u32 rate_cap_rx_chainmask)4225*5c1def83SBjoern A. Zeeb ath12k_create_vht_cap(struct ath12k *ar, u32 rate_cap_tx_chainmask,
4226*5c1def83SBjoern A. Zeeb u32 rate_cap_rx_chainmask)
4227*5c1def83SBjoern A. Zeeb {
4228*5c1def83SBjoern A. Zeeb struct ieee80211_sta_vht_cap vht_cap = {0};
4229*5c1def83SBjoern A. Zeeb u16 txmcs_map, rxmcs_map;
4230*5c1def83SBjoern A. Zeeb int i;
4231*5c1def83SBjoern A. Zeeb
4232*5c1def83SBjoern A. Zeeb vht_cap.vht_supported = 1;
4233*5c1def83SBjoern A. Zeeb vht_cap.cap = ar->pdev->cap.vht_cap;
4234*5c1def83SBjoern A. Zeeb
4235*5c1def83SBjoern A. Zeeb ath12k_set_vht_txbf_cap(ar, &vht_cap.cap);
4236*5c1def83SBjoern A. Zeeb
4237*5c1def83SBjoern A. Zeeb /* TODO: Enable back VHT160 mode once association issues are fixed */
4238*5c1def83SBjoern A. Zeeb /* Disabling VHT160 and VHT80+80 modes */
4239*5c1def83SBjoern A. Zeeb vht_cap.cap &= ~IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
4240*5c1def83SBjoern A. Zeeb vht_cap.cap &= ~IEEE80211_VHT_CAP_SHORT_GI_160;
4241*5c1def83SBjoern A. Zeeb
4242*5c1def83SBjoern A. Zeeb rxmcs_map = 0;
4243*5c1def83SBjoern A. Zeeb txmcs_map = 0;
4244*5c1def83SBjoern A. Zeeb for (i = 0; i < 8; i++) {
4245*5c1def83SBjoern A. Zeeb if (i < ar->num_tx_chains && rate_cap_tx_chainmask & BIT(i))
4246*5c1def83SBjoern A. Zeeb txmcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i * 2);
4247*5c1def83SBjoern A. Zeeb else
4248*5c1def83SBjoern A. Zeeb txmcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i * 2);
4249*5c1def83SBjoern A. Zeeb
4250*5c1def83SBjoern A. Zeeb if (i < ar->num_rx_chains && rate_cap_rx_chainmask & BIT(i))
4251*5c1def83SBjoern A. Zeeb rxmcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i * 2);
4252*5c1def83SBjoern A. Zeeb else
4253*5c1def83SBjoern A. Zeeb rxmcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i * 2);
4254*5c1def83SBjoern A. Zeeb }
4255*5c1def83SBjoern A. Zeeb
4256*5c1def83SBjoern A. Zeeb if (rate_cap_tx_chainmask <= 1)
4257*5c1def83SBjoern A. Zeeb vht_cap.cap &= ~IEEE80211_VHT_CAP_TXSTBC;
4258*5c1def83SBjoern A. Zeeb
4259*5c1def83SBjoern A. Zeeb vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(rxmcs_map);
4260*5c1def83SBjoern A. Zeeb vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(txmcs_map);
4261*5c1def83SBjoern A. Zeeb
4262*5c1def83SBjoern A. Zeeb return vht_cap;
4263*5c1def83SBjoern A. Zeeb }
4264*5c1def83SBjoern A. Zeeb
ath12k_mac_setup_ht_vht_cap(struct ath12k * ar,struct ath12k_pdev_cap * cap,u32 * ht_cap_info)4265*5c1def83SBjoern A. Zeeb static void ath12k_mac_setup_ht_vht_cap(struct ath12k *ar,
4266*5c1def83SBjoern A. Zeeb struct ath12k_pdev_cap *cap,
4267*5c1def83SBjoern A. Zeeb u32 *ht_cap_info)
4268*5c1def83SBjoern A. Zeeb {
4269*5c1def83SBjoern A. Zeeb struct ieee80211_supported_band *band;
4270*5c1def83SBjoern A. Zeeb u32 rate_cap_tx_chainmask;
4271*5c1def83SBjoern A. Zeeb u32 rate_cap_rx_chainmask;
4272*5c1def83SBjoern A. Zeeb u32 ht_cap;
4273*5c1def83SBjoern A. Zeeb
4274*5c1def83SBjoern A. Zeeb rate_cap_tx_chainmask = ar->cfg_tx_chainmask >> cap->tx_chain_mask_shift;
4275*5c1def83SBjoern A. Zeeb rate_cap_rx_chainmask = ar->cfg_rx_chainmask >> cap->rx_chain_mask_shift;
4276*5c1def83SBjoern A. Zeeb
4277*5c1def83SBjoern A. Zeeb if (cap->supported_bands & WMI_HOST_WLAN_2G_CAP) {
4278*5c1def83SBjoern A. Zeeb band = &ar->mac.sbands[NL80211_BAND_2GHZ];
4279*5c1def83SBjoern A. Zeeb ht_cap = cap->band[NL80211_BAND_2GHZ].ht_cap_info;
4280*5c1def83SBjoern A. Zeeb if (ht_cap_info)
4281*5c1def83SBjoern A. Zeeb *ht_cap_info = ht_cap;
4282*5c1def83SBjoern A. Zeeb band->ht_cap = ath12k_create_ht_cap(ar, ht_cap,
4283*5c1def83SBjoern A. Zeeb rate_cap_rx_chainmask);
4284*5c1def83SBjoern A. Zeeb }
4285*5c1def83SBjoern A. Zeeb
4286*5c1def83SBjoern A. Zeeb if (cap->supported_bands & WMI_HOST_WLAN_5G_CAP &&
4287*5c1def83SBjoern A. Zeeb (ar->ab->hw_params->single_pdev_only ||
4288*5c1def83SBjoern A. Zeeb !ar->supports_6ghz)) {
4289*5c1def83SBjoern A. Zeeb band = &ar->mac.sbands[NL80211_BAND_5GHZ];
4290*5c1def83SBjoern A. Zeeb ht_cap = cap->band[NL80211_BAND_5GHZ].ht_cap_info;
4291*5c1def83SBjoern A. Zeeb if (ht_cap_info)
4292*5c1def83SBjoern A. Zeeb *ht_cap_info = ht_cap;
4293*5c1def83SBjoern A. Zeeb band->ht_cap = ath12k_create_ht_cap(ar, ht_cap,
4294*5c1def83SBjoern A. Zeeb rate_cap_rx_chainmask);
4295*5c1def83SBjoern A. Zeeb band->vht_cap = ath12k_create_vht_cap(ar, rate_cap_tx_chainmask,
4296*5c1def83SBjoern A. Zeeb rate_cap_rx_chainmask);
4297*5c1def83SBjoern A. Zeeb }
4298*5c1def83SBjoern A. Zeeb }
4299*5c1def83SBjoern A. Zeeb
ath12k_check_chain_mask(struct ath12k * ar,u32 ant,bool is_tx_ant)4300*5c1def83SBjoern A. Zeeb static int ath12k_check_chain_mask(struct ath12k *ar, u32 ant, bool is_tx_ant)
4301*5c1def83SBjoern A. Zeeb {
4302*5c1def83SBjoern A. Zeeb /* TODO: Check the request chainmask against the supported
4303*5c1def83SBjoern A. Zeeb * chainmask table which is advertised in extented_service_ready event
4304*5c1def83SBjoern A. Zeeb */
4305*5c1def83SBjoern A. Zeeb
4306*5c1def83SBjoern A. Zeeb return 0;
4307*5c1def83SBjoern A. Zeeb }
4308*5c1def83SBjoern A. Zeeb
ath12k_gen_ppe_thresh(struct ath12k_wmi_ppe_threshold_arg * fw_ppet,u8 * he_ppet)4309*5c1def83SBjoern A. Zeeb static void ath12k_gen_ppe_thresh(struct ath12k_wmi_ppe_threshold_arg *fw_ppet,
4310*5c1def83SBjoern A. Zeeb u8 *he_ppet)
4311*5c1def83SBjoern A. Zeeb {
4312*5c1def83SBjoern A. Zeeb int nss, ru;
4313*5c1def83SBjoern A. Zeeb u8 bit = 7;
4314*5c1def83SBjoern A. Zeeb
4315*5c1def83SBjoern A. Zeeb he_ppet[0] = fw_ppet->numss_m1 & IEEE80211_PPE_THRES_NSS_MASK;
4316*5c1def83SBjoern A. Zeeb he_ppet[0] |= (fw_ppet->ru_bit_mask <<
4317*5c1def83SBjoern A. Zeeb IEEE80211_PPE_THRES_RU_INDEX_BITMASK_POS) &
4318*5c1def83SBjoern A. Zeeb IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK;
4319*5c1def83SBjoern A. Zeeb for (nss = 0; nss <= fw_ppet->numss_m1; nss++) {
4320*5c1def83SBjoern A. Zeeb for (ru = 0; ru < 4; ru++) {
4321*5c1def83SBjoern A. Zeeb u8 val;
4322*5c1def83SBjoern A. Zeeb int i;
4323*5c1def83SBjoern A. Zeeb
4324*5c1def83SBjoern A. Zeeb if ((fw_ppet->ru_bit_mask & BIT(ru)) == 0)
4325*5c1def83SBjoern A. Zeeb continue;
4326*5c1def83SBjoern A. Zeeb val = (fw_ppet->ppet16_ppet8_ru3_ru0[nss] >> (ru * 6)) &
4327*5c1def83SBjoern A. Zeeb 0x3f;
4328*5c1def83SBjoern A. Zeeb val = ((val >> 3) & 0x7) | ((val & 0x7) << 3);
4329*5c1def83SBjoern A. Zeeb for (i = 5; i >= 0; i--) {
4330*5c1def83SBjoern A. Zeeb he_ppet[bit / 8] |=
4331*5c1def83SBjoern A. Zeeb ((val >> i) & 0x1) << ((bit % 8));
4332*5c1def83SBjoern A. Zeeb bit++;
4333*5c1def83SBjoern A. Zeeb }
4334*5c1def83SBjoern A. Zeeb }
4335*5c1def83SBjoern A. Zeeb }
4336*5c1def83SBjoern A. Zeeb }
4337*5c1def83SBjoern A. Zeeb
4338*5c1def83SBjoern A. Zeeb static void
ath12k_mac_filter_he_cap_mesh(struct ieee80211_he_cap_elem * he_cap_elem)4339*5c1def83SBjoern A. Zeeb ath12k_mac_filter_he_cap_mesh(struct ieee80211_he_cap_elem *he_cap_elem)
4340*5c1def83SBjoern A. Zeeb {
4341*5c1def83SBjoern A. Zeeb u8 m;
4342*5c1def83SBjoern A. Zeeb
4343*5c1def83SBjoern A. Zeeb m = IEEE80211_HE_MAC_CAP0_TWT_RES |
4344*5c1def83SBjoern A. Zeeb IEEE80211_HE_MAC_CAP0_TWT_REQ;
4345*5c1def83SBjoern A. Zeeb he_cap_elem->mac_cap_info[0] &= ~m;
4346*5c1def83SBjoern A. Zeeb
4347*5c1def83SBjoern A. Zeeb m = IEEE80211_HE_MAC_CAP2_TRS |
4348*5c1def83SBjoern A. Zeeb IEEE80211_HE_MAC_CAP2_BCAST_TWT |
4349*5c1def83SBjoern A. Zeeb IEEE80211_HE_MAC_CAP2_MU_CASCADING;
4350*5c1def83SBjoern A. Zeeb he_cap_elem->mac_cap_info[2] &= ~m;
4351*5c1def83SBjoern A. Zeeb
4352*5c1def83SBjoern A. Zeeb m = IEEE80211_HE_MAC_CAP3_FLEX_TWT_SCHED |
4353*5c1def83SBjoern A. Zeeb IEEE80211_HE_MAC_CAP2_BCAST_TWT |
4354*5c1def83SBjoern A. Zeeb IEEE80211_HE_MAC_CAP2_MU_CASCADING;
4355*5c1def83SBjoern A. Zeeb he_cap_elem->mac_cap_info[3] &= ~m;
4356*5c1def83SBjoern A. Zeeb
4357*5c1def83SBjoern A. Zeeb m = IEEE80211_HE_MAC_CAP4_BSRP_BQRP_A_MPDU_AGG |
4358*5c1def83SBjoern A. Zeeb IEEE80211_HE_MAC_CAP4_BQR;
4359*5c1def83SBjoern A. Zeeb he_cap_elem->mac_cap_info[4] &= ~m;
4360*5c1def83SBjoern A. Zeeb
4361*5c1def83SBjoern A. Zeeb m = IEEE80211_HE_MAC_CAP5_SUBCHAN_SELECTIVE_TRANSMISSION |
4362*5c1def83SBjoern A. Zeeb IEEE80211_HE_MAC_CAP5_UL_2x996_TONE_RU |
4363*5c1def83SBjoern A. Zeeb IEEE80211_HE_MAC_CAP5_PUNCTURED_SOUNDING |
4364*5c1def83SBjoern A. Zeeb IEEE80211_HE_MAC_CAP5_HT_VHT_TRIG_FRAME_RX;
4365*5c1def83SBjoern A. Zeeb he_cap_elem->mac_cap_info[5] &= ~m;
4366*5c1def83SBjoern A. Zeeb
4367*5c1def83SBjoern A. Zeeb m = IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO |
4368*5c1def83SBjoern A. Zeeb IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO;
4369*5c1def83SBjoern A. Zeeb he_cap_elem->phy_cap_info[2] &= ~m;
4370*5c1def83SBjoern A. Zeeb
4371*5c1def83SBjoern A. Zeeb m = IEEE80211_HE_PHY_CAP3_RX_PARTIAL_BW_SU_IN_20MHZ_MU |
4372*5c1def83SBjoern A. Zeeb IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_MASK |
4373*5c1def83SBjoern A. Zeeb IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_MASK;
4374*5c1def83SBjoern A. Zeeb he_cap_elem->phy_cap_info[3] &= ~m;
4375*5c1def83SBjoern A. Zeeb
4376*5c1def83SBjoern A. Zeeb m = IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER;
4377*5c1def83SBjoern A. Zeeb he_cap_elem->phy_cap_info[4] &= ~m;
4378*5c1def83SBjoern A. Zeeb
4379*5c1def83SBjoern A. Zeeb m = IEEE80211_HE_PHY_CAP5_NG16_MU_FEEDBACK;
4380*5c1def83SBjoern A. Zeeb he_cap_elem->phy_cap_info[5] &= ~m;
4381*5c1def83SBjoern A. Zeeb
4382*5c1def83SBjoern A. Zeeb m = IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU |
4383*5c1def83SBjoern A. Zeeb IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMING_PARTIAL_BW_FB |
4384*5c1def83SBjoern A. Zeeb IEEE80211_HE_PHY_CAP6_TRIG_CQI_FB |
4385*5c1def83SBjoern A. Zeeb IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO;
4386*5c1def83SBjoern A. Zeeb he_cap_elem->phy_cap_info[6] &= ~m;
4387*5c1def83SBjoern A. Zeeb
4388*5c1def83SBjoern A. Zeeb m = IEEE80211_HE_PHY_CAP7_PSR_BASED_SR |
4389*5c1def83SBjoern A. Zeeb IEEE80211_HE_PHY_CAP7_POWER_BOOST_FACTOR_SUPP |
4390*5c1def83SBjoern A. Zeeb IEEE80211_HE_PHY_CAP7_STBC_TX_ABOVE_80MHZ |
4391*5c1def83SBjoern A. Zeeb IEEE80211_HE_PHY_CAP7_STBC_RX_ABOVE_80MHZ;
4392*5c1def83SBjoern A. Zeeb he_cap_elem->phy_cap_info[7] &= ~m;
4393*5c1def83SBjoern A. Zeeb
4394*5c1def83SBjoern A. Zeeb m = IEEE80211_HE_PHY_CAP8_HE_ER_SU_PPDU_4XLTF_AND_08_US_GI |
4395*5c1def83SBjoern A. Zeeb IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G |
4396*5c1def83SBjoern A. Zeeb IEEE80211_HE_PHY_CAP8_20MHZ_IN_160MHZ_HE_PPDU |
4397*5c1def83SBjoern A. Zeeb IEEE80211_HE_PHY_CAP8_80MHZ_IN_160MHZ_HE_PPDU;
4398*5c1def83SBjoern A. Zeeb he_cap_elem->phy_cap_info[8] &= ~m;
4399*5c1def83SBjoern A. Zeeb
4400*5c1def83SBjoern A. Zeeb m = IEEE80211_HE_PHY_CAP9_LONGER_THAN_16_SIGB_OFDM_SYM |
4401*5c1def83SBjoern A. Zeeb IEEE80211_HE_PHY_CAP9_NON_TRIGGERED_CQI_FEEDBACK |
4402*5c1def83SBjoern A. Zeeb IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU |
4403*5c1def83SBjoern A. Zeeb IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU |
4404*5c1def83SBjoern A. Zeeb IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB |
4405*5c1def83SBjoern A. Zeeb IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB;
4406*5c1def83SBjoern A. Zeeb he_cap_elem->phy_cap_info[9] &= ~m;
4407*5c1def83SBjoern A. Zeeb }
4408*5c1def83SBjoern A. Zeeb
ath12k_mac_setup_he_6ghz_cap(struct ath12k_pdev_cap * pcap,struct ath12k_band_cap * bcap)4409*5c1def83SBjoern A. Zeeb static __le16 ath12k_mac_setup_he_6ghz_cap(struct ath12k_pdev_cap *pcap,
4410*5c1def83SBjoern A. Zeeb struct ath12k_band_cap *bcap)
4411*5c1def83SBjoern A. Zeeb {
4412*5c1def83SBjoern A. Zeeb u8 val;
4413*5c1def83SBjoern A. Zeeb
4414*5c1def83SBjoern A. Zeeb bcap->he_6ghz_capa = IEEE80211_HT_MPDU_DENSITY_NONE;
4415*5c1def83SBjoern A. Zeeb if (bcap->ht_cap_info & WMI_HT_CAP_DYNAMIC_SMPS)
4416*5c1def83SBjoern A. Zeeb bcap->he_6ghz_capa |=
4417*5c1def83SBjoern A. Zeeb u32_encode_bits(WLAN_HT_CAP_SM_PS_DYNAMIC,
4418*5c1def83SBjoern A. Zeeb IEEE80211_HE_6GHZ_CAP_SM_PS);
4419*5c1def83SBjoern A. Zeeb else
4420*5c1def83SBjoern A. Zeeb bcap->he_6ghz_capa |=
4421*5c1def83SBjoern A. Zeeb u32_encode_bits(WLAN_HT_CAP_SM_PS_DISABLED,
4422*5c1def83SBjoern A. Zeeb IEEE80211_HE_6GHZ_CAP_SM_PS);
4423*5c1def83SBjoern A. Zeeb val = u32_get_bits(pcap->vht_cap,
4424*5c1def83SBjoern A. Zeeb IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK);
4425*5c1def83SBjoern A. Zeeb bcap->he_6ghz_capa |=
4426*5c1def83SBjoern A. Zeeb u32_encode_bits(val, IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP);
4427*5c1def83SBjoern A. Zeeb val = u32_get_bits(pcap->vht_cap,
4428*5c1def83SBjoern A. Zeeb IEEE80211_VHT_CAP_MAX_MPDU_MASK);
4429*5c1def83SBjoern A. Zeeb bcap->he_6ghz_capa |=
4430*5c1def83SBjoern A. Zeeb u32_encode_bits(val, IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN);
4431*5c1def83SBjoern A. Zeeb if (pcap->vht_cap & IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN)
4432*5c1def83SBjoern A. Zeeb bcap->he_6ghz_capa |= IEEE80211_HE_6GHZ_CAP_RX_ANTPAT_CONS;
4433*5c1def83SBjoern A. Zeeb if (pcap->vht_cap & IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN)
4434*5c1def83SBjoern A. Zeeb bcap->he_6ghz_capa |= IEEE80211_HE_6GHZ_CAP_TX_ANTPAT_CONS;
4435*5c1def83SBjoern A. Zeeb
4436*5c1def83SBjoern A. Zeeb return cpu_to_le16(bcap->he_6ghz_capa);
4437*5c1def83SBjoern A. Zeeb }
4438*5c1def83SBjoern A. Zeeb
ath12k_mac_copy_he_cap(struct ath12k_band_cap * band_cap,int iftype,u8 num_tx_chains,struct ieee80211_sta_he_cap * he_cap)4439*5c1def83SBjoern A. Zeeb static void ath12k_mac_copy_he_cap(struct ath12k_band_cap *band_cap,
4440*5c1def83SBjoern A. Zeeb int iftype, u8 num_tx_chains,
4441*5c1def83SBjoern A. Zeeb struct ieee80211_sta_he_cap *he_cap)
4442*5c1def83SBjoern A. Zeeb {
4443*5c1def83SBjoern A. Zeeb struct ieee80211_he_cap_elem *he_cap_elem = &he_cap->he_cap_elem;
4444*5c1def83SBjoern A. Zeeb struct ieee80211_he_mcs_nss_supp *mcs_nss = &he_cap->he_mcs_nss_supp;
4445*5c1def83SBjoern A. Zeeb
4446*5c1def83SBjoern A. Zeeb he_cap->has_he = true;
4447*5c1def83SBjoern A. Zeeb memcpy(he_cap_elem->mac_cap_info, band_cap->he_cap_info,
4448*5c1def83SBjoern A. Zeeb sizeof(he_cap_elem->mac_cap_info));
4449*5c1def83SBjoern A. Zeeb memcpy(he_cap_elem->phy_cap_info, band_cap->he_cap_phy_info,
4450*5c1def83SBjoern A. Zeeb sizeof(he_cap_elem->phy_cap_info));
4451*5c1def83SBjoern A. Zeeb
4452*5c1def83SBjoern A. Zeeb he_cap_elem->mac_cap_info[1] &=
4453*5c1def83SBjoern A. Zeeb IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_MASK;
4454*5c1def83SBjoern A. Zeeb
4455*5c1def83SBjoern A. Zeeb he_cap_elem->phy_cap_info[5] &=
4456*5c1def83SBjoern A. Zeeb ~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK;
4457*5c1def83SBjoern A. Zeeb he_cap_elem->phy_cap_info[5] &=
4458*5c1def83SBjoern A. Zeeb ~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK;
4459*5c1def83SBjoern A. Zeeb he_cap_elem->phy_cap_info[5] |= num_tx_chains - 1;
4460*5c1def83SBjoern A. Zeeb
4461*5c1def83SBjoern A. Zeeb switch (iftype) {
4462*5c1def83SBjoern A. Zeeb case NL80211_IFTYPE_AP:
4463*5c1def83SBjoern A. Zeeb he_cap_elem->phy_cap_info[3] &=
4464*5c1def83SBjoern A. Zeeb ~IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_MASK;
4465*5c1def83SBjoern A. Zeeb he_cap_elem->phy_cap_info[9] |=
4466*5c1def83SBjoern A. Zeeb IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU;
4467*5c1def83SBjoern A. Zeeb break;
4468*5c1def83SBjoern A. Zeeb case NL80211_IFTYPE_STATION:
4469*5c1def83SBjoern A. Zeeb he_cap_elem->mac_cap_info[0] &= ~IEEE80211_HE_MAC_CAP0_TWT_RES;
4470*5c1def83SBjoern A. Zeeb he_cap_elem->mac_cap_info[0] |= IEEE80211_HE_MAC_CAP0_TWT_REQ;
4471*5c1def83SBjoern A. Zeeb he_cap_elem->phy_cap_info[9] |=
4472*5c1def83SBjoern A. Zeeb IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU;
4473*5c1def83SBjoern A. Zeeb break;
4474*5c1def83SBjoern A. Zeeb case NL80211_IFTYPE_MESH_POINT:
4475*5c1def83SBjoern A. Zeeb ath12k_mac_filter_he_cap_mesh(he_cap_elem);
4476*5c1def83SBjoern A. Zeeb break;
4477*5c1def83SBjoern A. Zeeb }
4478*5c1def83SBjoern A. Zeeb
4479*5c1def83SBjoern A. Zeeb mcs_nss->rx_mcs_80 = cpu_to_le16(band_cap->he_mcs & 0xffff);
4480*5c1def83SBjoern A. Zeeb mcs_nss->tx_mcs_80 = cpu_to_le16(band_cap->he_mcs & 0xffff);
4481*5c1def83SBjoern A. Zeeb mcs_nss->rx_mcs_160 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
4482*5c1def83SBjoern A. Zeeb mcs_nss->tx_mcs_160 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
4483*5c1def83SBjoern A. Zeeb mcs_nss->rx_mcs_80p80 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
4484*5c1def83SBjoern A. Zeeb mcs_nss->tx_mcs_80p80 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
4485*5c1def83SBjoern A. Zeeb
4486*5c1def83SBjoern A. Zeeb memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres));
4487*5c1def83SBjoern A. Zeeb if (he_cap_elem->phy_cap_info[6] &
4488*5c1def83SBjoern A. Zeeb IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT)
4489*5c1def83SBjoern A. Zeeb ath12k_gen_ppe_thresh(&band_cap->he_ppet, he_cap->ppe_thres);
4490*5c1def83SBjoern A. Zeeb }
4491*5c1def83SBjoern A. Zeeb
4492*5c1def83SBjoern A. Zeeb 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)4493*5c1def83SBjoern A. Zeeb ath12k_mac_copy_eht_mcs_nss(struct ath12k_band_cap *band_cap,
4494*5c1def83SBjoern A. Zeeb struct ieee80211_eht_mcs_nss_supp *mcs_nss,
4495*5c1def83SBjoern A. Zeeb const struct ieee80211_he_cap_elem *he_cap,
4496*5c1def83SBjoern A. Zeeb const struct ieee80211_eht_cap_elem_fixed *eht_cap)
4497*5c1def83SBjoern A. Zeeb {
4498*5c1def83SBjoern A. Zeeb if ((he_cap->phy_cap_info[0] &
4499*5c1def83SBjoern A. Zeeb (IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G |
4500*5c1def83SBjoern A. Zeeb IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |
4501*5c1def83SBjoern A. Zeeb IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G |
4502*5c1def83SBjoern A. Zeeb IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)) == 0)
4503*5c1def83SBjoern A. Zeeb memcpy(&mcs_nss->only_20mhz, &band_cap->eht_mcs_20_only,
4504*5c1def83SBjoern A. Zeeb sizeof(struct ieee80211_eht_mcs_nss_supp_20mhz_only));
4505*5c1def83SBjoern A. Zeeb
4506*5c1def83SBjoern A. Zeeb if (he_cap->phy_cap_info[0] &
4507*5c1def83SBjoern A. Zeeb (IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G |
4508*5c1def83SBjoern A. Zeeb IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G))
4509*5c1def83SBjoern A. Zeeb memcpy(&mcs_nss->bw._80, &band_cap->eht_mcs_80,
4510*5c1def83SBjoern A. Zeeb sizeof(struct ieee80211_eht_mcs_nss_supp_bw));
4511*5c1def83SBjoern A. Zeeb
4512*5c1def83SBjoern A. Zeeb if (he_cap->phy_cap_info[0] &
4513*5c1def83SBjoern A. Zeeb IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G)
4514*5c1def83SBjoern A. Zeeb memcpy(&mcs_nss->bw._160, &band_cap->eht_mcs_160,
4515*5c1def83SBjoern A. Zeeb sizeof(struct ieee80211_eht_mcs_nss_supp_bw));
4516*5c1def83SBjoern A. Zeeb
4517*5c1def83SBjoern A. Zeeb if (eht_cap->phy_cap_info[0] & IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ)
4518*5c1def83SBjoern A. Zeeb memcpy(&mcs_nss->bw._320, &band_cap->eht_mcs_320,
4519*5c1def83SBjoern A. Zeeb sizeof(struct ieee80211_eht_mcs_nss_supp_bw));
4520*5c1def83SBjoern A. Zeeb }
4521*5c1def83SBjoern A. Zeeb
ath12k_mac_copy_eht_ppe_thresh(struct ath12k_wmi_ppe_threshold_arg * fw_ppet,struct ieee80211_sta_eht_cap * cap)4522*5c1def83SBjoern A. Zeeb static void ath12k_mac_copy_eht_ppe_thresh(struct ath12k_wmi_ppe_threshold_arg *fw_ppet,
4523*5c1def83SBjoern A. Zeeb struct ieee80211_sta_eht_cap *cap)
4524*5c1def83SBjoern A. Zeeb {
4525*5c1def83SBjoern A. Zeeb u16 bit = IEEE80211_EHT_PPE_THRES_INFO_HEADER_SIZE;
4526*5c1def83SBjoern A. Zeeb u8 i, nss, ru, ppet_bit_len_per_ru = IEEE80211_EHT_PPE_THRES_INFO_PPET_SIZE * 2;
4527*5c1def83SBjoern A. Zeeb
4528*5c1def83SBjoern A. Zeeb u8p_replace_bits(&cap->eht_ppe_thres[0], fw_ppet->numss_m1,
4529*5c1def83SBjoern A. Zeeb IEEE80211_EHT_PPE_THRES_NSS_MASK);
4530*5c1def83SBjoern A. Zeeb
4531*5c1def83SBjoern A. Zeeb u16p_replace_bits((u16 *)&cap->eht_ppe_thres[0], fw_ppet->ru_bit_mask,
4532*5c1def83SBjoern A. Zeeb IEEE80211_EHT_PPE_THRES_RU_INDEX_BITMASK_MASK);
4533*5c1def83SBjoern A. Zeeb
4534*5c1def83SBjoern A. Zeeb for (nss = 0; nss <= fw_ppet->numss_m1; nss++) {
4535*5c1def83SBjoern A. Zeeb for (ru = 0;
4536*5c1def83SBjoern A. Zeeb ru < hweight16(IEEE80211_EHT_PPE_THRES_RU_INDEX_BITMASK_MASK);
4537*5c1def83SBjoern A. Zeeb ru++) {
4538*5c1def83SBjoern A. Zeeb u32 val = 0;
4539*5c1def83SBjoern A. Zeeb
4540*5c1def83SBjoern A. Zeeb if ((fw_ppet->ru_bit_mask & BIT(ru)) == 0)
4541*5c1def83SBjoern A. Zeeb continue;
4542*5c1def83SBjoern A. Zeeb
4543*5c1def83SBjoern A. Zeeb u32p_replace_bits(&val, fw_ppet->ppet16_ppet8_ru3_ru0[nss] >>
4544*5c1def83SBjoern A. Zeeb (ru * ppet_bit_len_per_ru),
4545*5c1def83SBjoern A. Zeeb GENMASK(ppet_bit_len_per_ru - 1, 0));
4546*5c1def83SBjoern A. Zeeb
4547*5c1def83SBjoern A. Zeeb for (i = 0; i < ppet_bit_len_per_ru; i++) {
4548*5c1def83SBjoern A. Zeeb cap->eht_ppe_thres[bit / 8] |=
4549*5c1def83SBjoern A. Zeeb (((val >> i) & 0x1) << ((bit % 8)));
4550*5c1def83SBjoern A. Zeeb bit++;
4551*5c1def83SBjoern A. Zeeb }
4552*5c1def83SBjoern A. Zeeb }
4553*5c1def83SBjoern A. Zeeb }
4554*5c1def83SBjoern A. Zeeb }
4555*5c1def83SBjoern A. Zeeb
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)4556*5c1def83SBjoern A. Zeeb static void ath12k_mac_copy_eht_cap(struct ath12k_band_cap *band_cap,
4557*5c1def83SBjoern A. Zeeb struct ieee80211_he_cap_elem *he_cap_elem,
4558*5c1def83SBjoern A. Zeeb int iftype,
4559*5c1def83SBjoern A. Zeeb struct ieee80211_sta_eht_cap *eht_cap)
4560*5c1def83SBjoern A. Zeeb {
4561*5c1def83SBjoern A. Zeeb struct ieee80211_eht_cap_elem_fixed *eht_cap_elem = &eht_cap->eht_cap_elem;
4562*5c1def83SBjoern A. Zeeb
4563*5c1def83SBjoern A. Zeeb memset(eht_cap, 0, sizeof(struct ieee80211_sta_eht_cap));
4564*5c1def83SBjoern A. Zeeb eht_cap->has_eht = true;
4565*5c1def83SBjoern A. Zeeb memcpy(eht_cap_elem->mac_cap_info, band_cap->eht_cap_mac_info,
4566*5c1def83SBjoern A. Zeeb sizeof(eht_cap_elem->mac_cap_info));
4567*5c1def83SBjoern A. Zeeb memcpy(eht_cap_elem->phy_cap_info, band_cap->eht_cap_phy_info,
4568*5c1def83SBjoern A. Zeeb sizeof(eht_cap_elem->phy_cap_info));
4569*5c1def83SBjoern A. Zeeb
4570*5c1def83SBjoern A. Zeeb switch (iftype) {
4571*5c1def83SBjoern A. Zeeb case NL80211_IFTYPE_AP:
4572*5c1def83SBjoern A. Zeeb eht_cap_elem->phy_cap_info[0] &=
4573*5c1def83SBjoern A. Zeeb ~IEEE80211_EHT_PHY_CAP0_242_TONE_RU_GT20MHZ;
4574*5c1def83SBjoern A. Zeeb eht_cap_elem->phy_cap_info[4] &=
4575*5c1def83SBjoern A. Zeeb ~IEEE80211_EHT_PHY_CAP4_PART_BW_DL_MU_MIMO;
4576*5c1def83SBjoern A. Zeeb eht_cap_elem->phy_cap_info[5] &=
4577*5c1def83SBjoern A. Zeeb ~IEEE80211_EHT_PHY_CAP5_TX_LESS_242_TONE_RU_SUPP;
4578*5c1def83SBjoern A. Zeeb break;
4579*5c1def83SBjoern A. Zeeb case NL80211_IFTYPE_STATION:
4580*5c1def83SBjoern A. Zeeb eht_cap_elem->phy_cap_info[7] &=
4581*5c1def83SBjoern A. Zeeb ~(IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_80MHZ |
4582*5c1def83SBjoern A. Zeeb IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_160MHZ |
4583*5c1def83SBjoern A. Zeeb IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_320MHZ);
4584*5c1def83SBjoern A. Zeeb eht_cap_elem->phy_cap_info[7] &=
4585*5c1def83SBjoern A. Zeeb ~(IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_80MHZ |
4586*5c1def83SBjoern A. Zeeb IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_160MHZ |
4587*5c1def83SBjoern A. Zeeb IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_320MHZ);
4588*5c1def83SBjoern A. Zeeb break;
4589*5c1def83SBjoern A. Zeeb default:
4590*5c1def83SBjoern A. Zeeb break;
4591*5c1def83SBjoern A. Zeeb }
4592*5c1def83SBjoern A. Zeeb
4593*5c1def83SBjoern A. Zeeb ath12k_mac_copy_eht_mcs_nss(band_cap, &eht_cap->eht_mcs_nss_supp,
4594*5c1def83SBjoern A. Zeeb he_cap_elem, eht_cap_elem);
4595*5c1def83SBjoern A. Zeeb
4596*5c1def83SBjoern A. Zeeb if (eht_cap_elem->phy_cap_info[5] &
4597*5c1def83SBjoern A. Zeeb IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT)
4598*5c1def83SBjoern A. Zeeb ath12k_mac_copy_eht_ppe_thresh(&band_cap->eht_ppet, eht_cap);
4599*5c1def83SBjoern A. Zeeb }
4600*5c1def83SBjoern A. Zeeb
ath12k_mac_copy_sband_iftype_data(struct ath12k * ar,struct ath12k_pdev_cap * cap,struct ieee80211_sband_iftype_data * data,int band)4601*5c1def83SBjoern A. Zeeb static int ath12k_mac_copy_sband_iftype_data(struct ath12k *ar,
4602*5c1def83SBjoern A. Zeeb struct ath12k_pdev_cap *cap,
4603*5c1def83SBjoern A. Zeeb struct ieee80211_sband_iftype_data *data,
4604*5c1def83SBjoern A. Zeeb int band)
4605*5c1def83SBjoern A. Zeeb {
4606*5c1def83SBjoern A. Zeeb struct ath12k_band_cap *band_cap = &cap->band[band];
4607*5c1def83SBjoern A. Zeeb int i, idx = 0;
4608*5c1def83SBjoern A. Zeeb
4609*5c1def83SBjoern A. Zeeb for (i = 0; i < NUM_NL80211_IFTYPES; i++) {
4610*5c1def83SBjoern A. Zeeb struct ieee80211_sta_he_cap *he_cap = &data[idx].he_cap;
4611*5c1def83SBjoern A. Zeeb
4612*5c1def83SBjoern A. Zeeb switch (i) {
4613*5c1def83SBjoern A. Zeeb case NL80211_IFTYPE_STATION:
4614*5c1def83SBjoern A. Zeeb case NL80211_IFTYPE_AP:
4615*5c1def83SBjoern A. Zeeb case NL80211_IFTYPE_MESH_POINT:
4616*5c1def83SBjoern A. Zeeb break;
4617*5c1def83SBjoern A. Zeeb
4618*5c1def83SBjoern A. Zeeb default:
4619*5c1def83SBjoern A. Zeeb continue;
4620*5c1def83SBjoern A. Zeeb }
4621*5c1def83SBjoern A. Zeeb
4622*5c1def83SBjoern A. Zeeb data[idx].types_mask = BIT(i);
4623*5c1def83SBjoern A. Zeeb
4624*5c1def83SBjoern A. Zeeb ath12k_mac_copy_he_cap(band_cap, i, ar->num_tx_chains, he_cap);
4625*5c1def83SBjoern A. Zeeb if (band == NL80211_BAND_6GHZ) {
4626*5c1def83SBjoern A. Zeeb data[idx].he_6ghz_capa.capa =
4627*5c1def83SBjoern A. Zeeb ath12k_mac_setup_he_6ghz_cap(cap, band_cap);
4628*5c1def83SBjoern A. Zeeb }
4629*5c1def83SBjoern A. Zeeb ath12k_mac_copy_eht_cap(band_cap, &he_cap->he_cap_elem, i,
4630*5c1def83SBjoern A. Zeeb &data[idx].eht_cap);
4631*5c1def83SBjoern A. Zeeb idx++;
4632*5c1def83SBjoern A. Zeeb }
4633*5c1def83SBjoern A. Zeeb
4634*5c1def83SBjoern A. Zeeb return idx;
4635*5c1def83SBjoern A. Zeeb }
4636*5c1def83SBjoern A. Zeeb
ath12k_mac_setup_sband_iftype_data(struct ath12k * ar,struct ath12k_pdev_cap * cap)4637*5c1def83SBjoern A. Zeeb static void ath12k_mac_setup_sband_iftype_data(struct ath12k *ar,
4638*5c1def83SBjoern A. Zeeb struct ath12k_pdev_cap *cap)
4639*5c1def83SBjoern A. Zeeb {
4640*5c1def83SBjoern A. Zeeb struct ieee80211_supported_band *sband;
4641*5c1def83SBjoern A. Zeeb enum nl80211_band band;
4642*5c1def83SBjoern A. Zeeb int count;
4643*5c1def83SBjoern A. Zeeb
4644*5c1def83SBjoern A. Zeeb if (cap->supported_bands & WMI_HOST_WLAN_2G_CAP) {
4645*5c1def83SBjoern A. Zeeb band = NL80211_BAND_2GHZ;
4646*5c1def83SBjoern A. Zeeb count = ath12k_mac_copy_sband_iftype_data(ar, cap,
4647*5c1def83SBjoern A. Zeeb ar->mac.iftype[band],
4648*5c1def83SBjoern A. Zeeb band);
4649*5c1def83SBjoern A. Zeeb sband = &ar->mac.sbands[band];
4650*5c1def83SBjoern A. Zeeb sband->iftype_data = ar->mac.iftype[band];
4651*5c1def83SBjoern A. Zeeb sband->n_iftype_data = count;
4652*5c1def83SBjoern A. Zeeb }
4653*5c1def83SBjoern A. Zeeb
4654*5c1def83SBjoern A. Zeeb if (cap->supported_bands & WMI_HOST_WLAN_5G_CAP) {
4655*5c1def83SBjoern A. Zeeb band = NL80211_BAND_5GHZ;
4656*5c1def83SBjoern A. Zeeb count = ath12k_mac_copy_sband_iftype_data(ar, cap,
4657*5c1def83SBjoern A. Zeeb ar->mac.iftype[band],
4658*5c1def83SBjoern A. Zeeb band);
4659*5c1def83SBjoern A. Zeeb sband = &ar->mac.sbands[band];
4660*5c1def83SBjoern A. Zeeb sband->iftype_data = ar->mac.iftype[band];
4661*5c1def83SBjoern A. Zeeb sband->n_iftype_data = count;
4662*5c1def83SBjoern A. Zeeb }
4663*5c1def83SBjoern A. Zeeb
4664*5c1def83SBjoern A. Zeeb if (cap->supported_bands & WMI_HOST_WLAN_5G_CAP &&
4665*5c1def83SBjoern A. Zeeb ar->supports_6ghz) {
4666*5c1def83SBjoern A. Zeeb band = NL80211_BAND_6GHZ;
4667*5c1def83SBjoern A. Zeeb count = ath12k_mac_copy_sband_iftype_data(ar, cap,
4668*5c1def83SBjoern A. Zeeb ar->mac.iftype[band],
4669*5c1def83SBjoern A. Zeeb band);
4670*5c1def83SBjoern A. Zeeb sband = &ar->mac.sbands[band];
4671*5c1def83SBjoern A. Zeeb sband->iftype_data = ar->mac.iftype[band];
4672*5c1def83SBjoern A. Zeeb sband->n_iftype_data = count;
4673*5c1def83SBjoern A. Zeeb }
4674*5c1def83SBjoern A. Zeeb }
4675*5c1def83SBjoern A. Zeeb
__ath12k_set_antenna(struct ath12k * ar,u32 tx_ant,u32 rx_ant)4676*5c1def83SBjoern A. Zeeb static int __ath12k_set_antenna(struct ath12k *ar, u32 tx_ant, u32 rx_ant)
4677*5c1def83SBjoern A. Zeeb {
4678*5c1def83SBjoern A. Zeeb int ret;
4679*5c1def83SBjoern A. Zeeb
4680*5c1def83SBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
4681*5c1def83SBjoern A. Zeeb
4682*5c1def83SBjoern A. Zeeb if (ath12k_check_chain_mask(ar, tx_ant, true))
4683*5c1def83SBjoern A. Zeeb return -EINVAL;
4684*5c1def83SBjoern A. Zeeb
4685*5c1def83SBjoern A. Zeeb if (ath12k_check_chain_mask(ar, rx_ant, false))
4686*5c1def83SBjoern A. Zeeb return -EINVAL;
4687*5c1def83SBjoern A. Zeeb
4688*5c1def83SBjoern A. Zeeb ar->cfg_tx_chainmask = tx_ant;
4689*5c1def83SBjoern A. Zeeb ar->cfg_rx_chainmask = rx_ant;
4690*5c1def83SBjoern A. Zeeb
4691*5c1def83SBjoern A. Zeeb if (ar->state != ATH12K_STATE_ON &&
4692*5c1def83SBjoern A. Zeeb ar->state != ATH12K_STATE_RESTARTED)
4693*5c1def83SBjoern A. Zeeb return 0;
4694*5c1def83SBjoern A. Zeeb
4695*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_TX_CHAIN_MASK,
4696*5c1def83SBjoern A. Zeeb tx_ant, ar->pdev->pdev_id);
4697*5c1def83SBjoern A. Zeeb if (ret) {
4698*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to set tx-chainmask: %d, req 0x%x\n",
4699*5c1def83SBjoern A. Zeeb ret, tx_ant);
4700*5c1def83SBjoern A. Zeeb return ret;
4701*5c1def83SBjoern A. Zeeb }
4702*5c1def83SBjoern A. Zeeb
4703*5c1def83SBjoern A. Zeeb ar->num_tx_chains = hweight32(tx_ant);
4704*5c1def83SBjoern A. Zeeb
4705*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_RX_CHAIN_MASK,
4706*5c1def83SBjoern A. Zeeb rx_ant, ar->pdev->pdev_id);
4707*5c1def83SBjoern A. Zeeb if (ret) {
4708*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to set rx-chainmask: %d, req 0x%x\n",
4709*5c1def83SBjoern A. Zeeb ret, rx_ant);
4710*5c1def83SBjoern A. Zeeb return ret;
4711*5c1def83SBjoern A. Zeeb }
4712*5c1def83SBjoern A. Zeeb
4713*5c1def83SBjoern A. Zeeb ar->num_rx_chains = hweight32(rx_ant);
4714*5c1def83SBjoern A. Zeeb
4715*5c1def83SBjoern A. Zeeb /* Reload HT/VHT/HE capability */
4716*5c1def83SBjoern A. Zeeb ath12k_mac_setup_ht_vht_cap(ar, &ar->pdev->cap, NULL);
4717*5c1def83SBjoern A. Zeeb ath12k_mac_setup_sband_iftype_data(ar, &ar->pdev->cap);
4718*5c1def83SBjoern A. Zeeb
4719*5c1def83SBjoern A. Zeeb return 0;
4720*5c1def83SBjoern A. Zeeb }
4721*5c1def83SBjoern A. Zeeb
ath12k_mgmt_over_wmi_tx_drop(struct ath12k * ar,struct sk_buff * skb)4722*5c1def83SBjoern A. Zeeb static void ath12k_mgmt_over_wmi_tx_drop(struct ath12k *ar, struct sk_buff *skb)
4723*5c1def83SBjoern A. Zeeb {
4724*5c1def83SBjoern A. Zeeb int num_mgmt;
4725*5c1def83SBjoern A. Zeeb
4726*5c1def83SBjoern A. Zeeb ieee80211_free_txskb(ar->hw, skb);
4727*5c1def83SBjoern A. Zeeb
4728*5c1def83SBjoern A. Zeeb num_mgmt = atomic_dec_if_positive(&ar->num_pending_mgmt_tx);
4729*5c1def83SBjoern A. Zeeb
4730*5c1def83SBjoern A. Zeeb if (num_mgmt < 0)
4731*5c1def83SBjoern A. Zeeb WARN_ON_ONCE(1);
4732*5c1def83SBjoern A. Zeeb
4733*5c1def83SBjoern A. Zeeb if (!num_mgmt)
4734*5c1def83SBjoern A. Zeeb wake_up(&ar->txmgmt_empty_waitq);
4735*5c1def83SBjoern A. Zeeb }
4736*5c1def83SBjoern A. Zeeb
ath12k_mac_tx_mgmt_pending_free(int buf_id,void * skb,void * ctx)4737*5c1def83SBjoern A. Zeeb int ath12k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx)
4738*5c1def83SBjoern A. Zeeb {
4739*5c1def83SBjoern A. Zeeb struct sk_buff *msdu = skb;
4740*5c1def83SBjoern A. Zeeb struct ieee80211_tx_info *info;
4741*5c1def83SBjoern A. Zeeb struct ath12k *ar = ctx;
4742*5c1def83SBjoern A. Zeeb struct ath12k_base *ab = ar->ab;
4743*5c1def83SBjoern A. Zeeb
4744*5c1def83SBjoern A. Zeeb spin_lock_bh(&ar->txmgmt_idr_lock);
4745*5c1def83SBjoern A. Zeeb idr_remove(&ar->txmgmt_idr, buf_id);
4746*5c1def83SBjoern A. Zeeb spin_unlock_bh(&ar->txmgmt_idr_lock);
4747*5c1def83SBjoern A. Zeeb dma_unmap_single(ab->dev, ATH12K_SKB_CB(msdu)->paddr, msdu->len,
4748*5c1def83SBjoern A. Zeeb DMA_TO_DEVICE);
4749*5c1def83SBjoern A. Zeeb
4750*5c1def83SBjoern A. Zeeb info = IEEE80211_SKB_CB(msdu);
4751*5c1def83SBjoern A. Zeeb memset(&info->status, 0, sizeof(info->status));
4752*5c1def83SBjoern A. Zeeb
4753*5c1def83SBjoern A. Zeeb ath12k_mgmt_over_wmi_tx_drop(ar, skb);
4754*5c1def83SBjoern A. Zeeb
4755*5c1def83SBjoern A. Zeeb return 0;
4756*5c1def83SBjoern A. Zeeb }
4757*5c1def83SBjoern A. Zeeb
ath12k_mac_vif_txmgmt_idr_remove(int buf_id,void * skb,void * ctx)4758*5c1def83SBjoern A. Zeeb static int ath12k_mac_vif_txmgmt_idr_remove(int buf_id, void *skb, void *ctx)
4759*5c1def83SBjoern A. Zeeb {
4760*5c1def83SBjoern A. Zeeb struct ieee80211_vif *vif = ctx;
4761*5c1def83SBjoern A. Zeeb struct ath12k_skb_cb *skb_cb = ATH12K_SKB_CB(skb);
4762*5c1def83SBjoern A. Zeeb struct sk_buff *msdu = skb;
4763*5c1def83SBjoern A. Zeeb struct ath12k *ar = skb_cb->ar;
4764*5c1def83SBjoern A. Zeeb struct ath12k_base *ab = ar->ab;
4765*5c1def83SBjoern A. Zeeb
4766*5c1def83SBjoern A. Zeeb if (skb_cb->vif == vif) {
4767*5c1def83SBjoern A. Zeeb spin_lock_bh(&ar->txmgmt_idr_lock);
4768*5c1def83SBjoern A. Zeeb idr_remove(&ar->txmgmt_idr, buf_id);
4769*5c1def83SBjoern A. Zeeb spin_unlock_bh(&ar->txmgmt_idr_lock);
4770*5c1def83SBjoern A. Zeeb dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len,
4771*5c1def83SBjoern A. Zeeb DMA_TO_DEVICE);
4772*5c1def83SBjoern A. Zeeb }
4773*5c1def83SBjoern A. Zeeb
4774*5c1def83SBjoern A. Zeeb return 0;
4775*5c1def83SBjoern A. Zeeb }
4776*5c1def83SBjoern A. Zeeb
ath12k_mac_mgmt_tx_wmi(struct ath12k * ar,struct ath12k_vif * arvif,struct sk_buff * skb)4777*5c1def83SBjoern A. Zeeb static int ath12k_mac_mgmt_tx_wmi(struct ath12k *ar, struct ath12k_vif *arvif,
4778*5c1def83SBjoern A. Zeeb struct sk_buff *skb)
4779*5c1def83SBjoern A. Zeeb {
4780*5c1def83SBjoern A. Zeeb struct ath12k_base *ab = ar->ab;
4781*5c1def83SBjoern A. Zeeb struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
4782*5c1def83SBjoern A. Zeeb struct ieee80211_tx_info *info;
4783*5c1def83SBjoern A. Zeeb dma_addr_t paddr;
4784*5c1def83SBjoern A. Zeeb int buf_id;
4785*5c1def83SBjoern A. Zeeb int ret;
4786*5c1def83SBjoern A. Zeeb
4787*5c1def83SBjoern A. Zeeb ATH12K_SKB_CB(skb)->ar = ar;
4788*5c1def83SBjoern A. Zeeb spin_lock_bh(&ar->txmgmt_idr_lock);
4789*5c1def83SBjoern A. Zeeb buf_id = idr_alloc(&ar->txmgmt_idr, skb, 0,
4790*5c1def83SBjoern A. Zeeb ATH12K_TX_MGMT_NUM_PENDING_MAX, GFP_ATOMIC);
4791*5c1def83SBjoern A. Zeeb spin_unlock_bh(&ar->txmgmt_idr_lock);
4792*5c1def83SBjoern A. Zeeb if (buf_id < 0)
4793*5c1def83SBjoern A. Zeeb return -ENOSPC;
4794*5c1def83SBjoern A. Zeeb
4795*5c1def83SBjoern A. Zeeb info = IEEE80211_SKB_CB(skb);
4796*5c1def83SBjoern A. Zeeb if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP)) {
4797*5c1def83SBjoern A. Zeeb if ((ieee80211_is_action(hdr->frame_control) ||
4798*5c1def83SBjoern A. Zeeb ieee80211_is_deauth(hdr->frame_control) ||
4799*5c1def83SBjoern A. Zeeb ieee80211_is_disassoc(hdr->frame_control)) &&
4800*5c1def83SBjoern A. Zeeb ieee80211_has_protected(hdr->frame_control)) {
4801*5c1def83SBjoern A. Zeeb skb_put(skb, IEEE80211_CCMP_MIC_LEN);
4802*5c1def83SBjoern A. Zeeb }
4803*5c1def83SBjoern A. Zeeb }
4804*5c1def83SBjoern A. Zeeb
4805*5c1def83SBjoern A. Zeeb paddr = dma_map_single(ab->dev, skb->data, skb->len, DMA_TO_DEVICE);
4806*5c1def83SBjoern A. Zeeb if (dma_mapping_error(ab->dev, paddr)) {
4807*5c1def83SBjoern A. Zeeb ath12k_warn(ab, "failed to DMA map mgmt Tx buffer\n");
4808*5c1def83SBjoern A. Zeeb ret = -EIO;
4809*5c1def83SBjoern A. Zeeb goto err_free_idr;
4810*5c1def83SBjoern A. Zeeb }
4811*5c1def83SBjoern A. Zeeb
4812*5c1def83SBjoern A. Zeeb ATH12K_SKB_CB(skb)->paddr = paddr;
4813*5c1def83SBjoern A. Zeeb
4814*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_mgmt_send(ar, arvif->vdev_id, buf_id, skb);
4815*5c1def83SBjoern A. Zeeb if (ret) {
4816*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to send mgmt frame: %d\n", ret);
4817*5c1def83SBjoern A. Zeeb goto err_unmap_buf;
4818*5c1def83SBjoern A. Zeeb }
4819*5c1def83SBjoern A. Zeeb
4820*5c1def83SBjoern A. Zeeb return 0;
4821*5c1def83SBjoern A. Zeeb
4822*5c1def83SBjoern A. Zeeb err_unmap_buf:
4823*5c1def83SBjoern A. Zeeb dma_unmap_single(ab->dev, ATH12K_SKB_CB(skb)->paddr,
4824*5c1def83SBjoern A. Zeeb skb->len, DMA_TO_DEVICE);
4825*5c1def83SBjoern A. Zeeb err_free_idr:
4826*5c1def83SBjoern A. Zeeb spin_lock_bh(&ar->txmgmt_idr_lock);
4827*5c1def83SBjoern A. Zeeb idr_remove(&ar->txmgmt_idr, buf_id);
4828*5c1def83SBjoern A. Zeeb spin_unlock_bh(&ar->txmgmt_idr_lock);
4829*5c1def83SBjoern A. Zeeb
4830*5c1def83SBjoern A. Zeeb return ret;
4831*5c1def83SBjoern A. Zeeb }
4832*5c1def83SBjoern A. Zeeb
ath12k_mgmt_over_wmi_tx_purge(struct ath12k * ar)4833*5c1def83SBjoern A. Zeeb static void ath12k_mgmt_over_wmi_tx_purge(struct ath12k *ar)
4834*5c1def83SBjoern A. Zeeb {
4835*5c1def83SBjoern A. Zeeb struct sk_buff *skb;
4836*5c1def83SBjoern A. Zeeb
4837*5c1def83SBjoern A. Zeeb while ((skb = skb_dequeue(&ar->wmi_mgmt_tx_queue)) != NULL)
4838*5c1def83SBjoern A. Zeeb ath12k_mgmt_over_wmi_tx_drop(ar, skb);
4839*5c1def83SBjoern A. Zeeb }
4840*5c1def83SBjoern A. Zeeb
ath12k_mgmt_over_wmi_tx_work(struct work_struct * work)4841*5c1def83SBjoern A. Zeeb static void ath12k_mgmt_over_wmi_tx_work(struct work_struct *work)
4842*5c1def83SBjoern A. Zeeb {
4843*5c1def83SBjoern A. Zeeb struct ath12k *ar = container_of(work, struct ath12k, wmi_mgmt_tx_work);
4844*5c1def83SBjoern A. Zeeb struct ath12k_skb_cb *skb_cb;
4845*5c1def83SBjoern A. Zeeb struct ath12k_vif *arvif;
4846*5c1def83SBjoern A. Zeeb struct sk_buff *skb;
4847*5c1def83SBjoern A. Zeeb int ret;
4848*5c1def83SBjoern A. Zeeb
4849*5c1def83SBjoern A. Zeeb while ((skb = skb_dequeue(&ar->wmi_mgmt_tx_queue)) != NULL) {
4850*5c1def83SBjoern A. Zeeb skb_cb = ATH12K_SKB_CB(skb);
4851*5c1def83SBjoern A. Zeeb if (!skb_cb->vif) {
4852*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "no vif found for mgmt frame\n");
4853*5c1def83SBjoern A. Zeeb ath12k_mgmt_over_wmi_tx_drop(ar, skb);
4854*5c1def83SBjoern A. Zeeb continue;
4855*5c1def83SBjoern A. Zeeb }
4856*5c1def83SBjoern A. Zeeb
4857*5c1def83SBjoern A. Zeeb arvif = ath12k_vif_to_arvif(skb_cb->vif);
4858*5c1def83SBjoern A. Zeeb if (ar->allocated_vdev_map & (1LL << arvif->vdev_id) &&
4859*5c1def83SBjoern A. Zeeb arvif->is_started) {
4860*5c1def83SBjoern A. Zeeb ret = ath12k_mac_mgmt_tx_wmi(ar, arvif, skb);
4861*5c1def83SBjoern A. Zeeb if (ret) {
4862*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to tx mgmt frame, vdev_id %d :%d\n",
4863*5c1def83SBjoern A. Zeeb arvif->vdev_id, ret);
4864*5c1def83SBjoern A. Zeeb ath12k_mgmt_over_wmi_tx_drop(ar, skb);
4865*5c1def83SBjoern A. Zeeb }
4866*5c1def83SBjoern A. Zeeb } else {
4867*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab,
4868*5c1def83SBjoern A. Zeeb "dropping mgmt frame for vdev %d, is_started %d\n",
4869*5c1def83SBjoern A. Zeeb arvif->vdev_id,
4870*5c1def83SBjoern A. Zeeb arvif->is_started);
4871*5c1def83SBjoern A. Zeeb ath12k_mgmt_over_wmi_tx_drop(ar, skb);
4872*5c1def83SBjoern A. Zeeb }
4873*5c1def83SBjoern A. Zeeb }
4874*5c1def83SBjoern A. Zeeb }
4875*5c1def83SBjoern A. Zeeb
ath12k_mac_mgmt_tx(struct ath12k * ar,struct sk_buff * skb,bool is_prb_rsp)4876*5c1def83SBjoern A. Zeeb static int ath12k_mac_mgmt_tx(struct ath12k *ar, struct sk_buff *skb,
4877*5c1def83SBjoern A. Zeeb bool is_prb_rsp)
4878*5c1def83SBjoern A. Zeeb {
4879*5c1def83SBjoern A. Zeeb struct sk_buff_head *q = &ar->wmi_mgmt_tx_queue;
4880*5c1def83SBjoern A. Zeeb
4881*5c1def83SBjoern A. Zeeb if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))
4882*5c1def83SBjoern A. Zeeb return -ESHUTDOWN;
4883*5c1def83SBjoern A. Zeeb
4884*5c1def83SBjoern A. Zeeb /* Drop probe response packets when the pending management tx
4885*5c1def83SBjoern A. Zeeb * count has reached a certain threshold, so as to prioritize
4886*5c1def83SBjoern A. Zeeb * other mgmt packets like auth and assoc to be sent on time
4887*5c1def83SBjoern A. Zeeb * for establishing successful connections.
4888*5c1def83SBjoern A. Zeeb */
4889*5c1def83SBjoern A. Zeeb if (is_prb_rsp &&
4890*5c1def83SBjoern A. Zeeb atomic_read(&ar->num_pending_mgmt_tx) > ATH12K_PRB_RSP_DROP_THRESHOLD) {
4891*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab,
4892*5c1def83SBjoern A. Zeeb "dropping probe response as pending queue is almost full\n");
4893*5c1def83SBjoern A. Zeeb return -ENOSPC;
4894*5c1def83SBjoern A. Zeeb }
4895*5c1def83SBjoern A. Zeeb
4896*5c1def83SBjoern A. Zeeb if (skb_queue_len_lockless(q) >= ATH12K_TX_MGMT_NUM_PENDING_MAX) {
4897*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "mgmt tx queue is full\n");
4898*5c1def83SBjoern A. Zeeb return -ENOSPC;
4899*5c1def83SBjoern A. Zeeb }
4900*5c1def83SBjoern A. Zeeb
4901*5c1def83SBjoern A. Zeeb skb_queue_tail(q, skb);
4902*5c1def83SBjoern A. Zeeb atomic_inc(&ar->num_pending_mgmt_tx);
4903*5c1def83SBjoern A. Zeeb ieee80211_queue_work(ar->hw, &ar->wmi_mgmt_tx_work);
4904*5c1def83SBjoern A. Zeeb
4905*5c1def83SBjoern A. Zeeb return 0;
4906*5c1def83SBjoern A. Zeeb }
4907*5c1def83SBjoern A. Zeeb
ath12k_mac_op_tx(struct ieee80211_hw * hw,struct ieee80211_tx_control * control,struct sk_buff * skb)4908*5c1def83SBjoern A. Zeeb static void ath12k_mac_op_tx(struct ieee80211_hw *hw,
4909*5c1def83SBjoern A. Zeeb struct ieee80211_tx_control *control,
4910*5c1def83SBjoern A. Zeeb struct sk_buff *skb)
4911*5c1def83SBjoern A. Zeeb {
4912*5c1def83SBjoern A. Zeeb struct ath12k_skb_cb *skb_cb = ATH12K_SKB_CB(skb);
4913*5c1def83SBjoern A. Zeeb struct ath12k *ar = hw->priv;
4914*5c1def83SBjoern A. Zeeb struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
4915*5c1def83SBjoern A. Zeeb struct ieee80211_vif *vif = info->control.vif;
4916*5c1def83SBjoern A. Zeeb struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
4917*5c1def83SBjoern A. Zeeb struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
4918*5c1def83SBjoern A. Zeeb struct ieee80211_key_conf *key = info->control.hw_key;
4919*5c1def83SBjoern A. Zeeb u32 info_flags = info->flags;
4920*5c1def83SBjoern A. Zeeb bool is_prb_rsp;
4921*5c1def83SBjoern A. Zeeb int ret;
4922*5c1def83SBjoern A. Zeeb
4923*5c1def83SBjoern A. Zeeb memset(skb_cb, 0, sizeof(*skb_cb));
4924*5c1def83SBjoern A. Zeeb skb_cb->vif = vif;
4925*5c1def83SBjoern A. Zeeb
4926*5c1def83SBjoern A. Zeeb if (key) {
4927*5c1def83SBjoern A. Zeeb skb_cb->cipher = key->cipher;
4928*5c1def83SBjoern A. Zeeb skb_cb->flags |= ATH12K_SKB_CIPHER_SET;
4929*5c1def83SBjoern A. Zeeb }
4930*5c1def83SBjoern A. Zeeb
4931*5c1def83SBjoern A. Zeeb if (info_flags & IEEE80211_TX_CTL_HW_80211_ENCAP) {
4932*5c1def83SBjoern A. Zeeb skb_cb->flags |= ATH12K_SKB_HW_80211_ENCAP;
4933*5c1def83SBjoern A. Zeeb } else if (ieee80211_is_mgmt(hdr->frame_control)) {
4934*5c1def83SBjoern A. Zeeb is_prb_rsp = ieee80211_is_probe_resp(hdr->frame_control);
4935*5c1def83SBjoern A. Zeeb ret = ath12k_mac_mgmt_tx(ar, skb, is_prb_rsp);
4936*5c1def83SBjoern A. Zeeb if (ret) {
4937*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to queue management frame %d\n",
4938*5c1def83SBjoern A. Zeeb ret);
4939*5c1def83SBjoern A. Zeeb ieee80211_free_txskb(ar->hw, skb);
4940*5c1def83SBjoern A. Zeeb }
4941*5c1def83SBjoern A. Zeeb return;
4942*5c1def83SBjoern A. Zeeb }
4943*5c1def83SBjoern A. Zeeb
4944*5c1def83SBjoern A. Zeeb ret = ath12k_dp_tx(ar, arvif, skb);
4945*5c1def83SBjoern A. Zeeb if (ret) {
4946*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to transmit frame %d\n", ret);
4947*5c1def83SBjoern A. Zeeb ieee80211_free_txskb(ar->hw, skb);
4948*5c1def83SBjoern A. Zeeb }
4949*5c1def83SBjoern A. Zeeb }
4950*5c1def83SBjoern A. Zeeb
ath12k_mac_drain_tx(struct ath12k * ar)4951*5c1def83SBjoern A. Zeeb void ath12k_mac_drain_tx(struct ath12k *ar)
4952*5c1def83SBjoern A. Zeeb {
4953*5c1def83SBjoern A. Zeeb /* make sure rcu-protected mac80211 tx path itself is drained */
4954*5c1def83SBjoern A. Zeeb synchronize_net();
4955*5c1def83SBjoern A. Zeeb
4956*5c1def83SBjoern A. Zeeb cancel_work_sync(&ar->wmi_mgmt_tx_work);
4957*5c1def83SBjoern A. Zeeb ath12k_mgmt_over_wmi_tx_purge(ar);
4958*5c1def83SBjoern A. Zeeb }
4959*5c1def83SBjoern A. Zeeb
ath12k_mac_config_mon_status_default(struct ath12k * ar,bool enable)4960*5c1def83SBjoern A. Zeeb static int ath12k_mac_config_mon_status_default(struct ath12k *ar, bool enable)
4961*5c1def83SBjoern A. Zeeb {
4962*5c1def83SBjoern A. Zeeb return -ENOTSUPP;
4963*5c1def83SBjoern A. Zeeb /* TODO: Need to support new monitor mode */
4964*5c1def83SBjoern A. Zeeb }
4965*5c1def83SBjoern A. Zeeb
ath12k_mac_wait_reconfigure(struct ath12k_base * ab)4966*5c1def83SBjoern A. Zeeb static void ath12k_mac_wait_reconfigure(struct ath12k_base *ab)
4967*5c1def83SBjoern A. Zeeb {
4968*5c1def83SBjoern A. Zeeb int recovery_start_count;
4969*5c1def83SBjoern A. Zeeb
4970*5c1def83SBjoern A. Zeeb if (!ab->is_reset)
4971*5c1def83SBjoern A. Zeeb return;
4972*5c1def83SBjoern A. Zeeb
4973*5c1def83SBjoern A. Zeeb recovery_start_count = atomic_inc_return(&ab->recovery_start_count);
4974*5c1def83SBjoern A. Zeeb
4975*5c1def83SBjoern A. Zeeb ath12k_dbg(ab, ATH12K_DBG_MAC, "recovery start count %d\n", recovery_start_count);
4976*5c1def83SBjoern A. Zeeb
4977*5c1def83SBjoern A. Zeeb if (recovery_start_count == ab->num_radios) {
4978*5c1def83SBjoern A. Zeeb complete(&ab->recovery_start);
4979*5c1def83SBjoern A. Zeeb ath12k_dbg(ab, ATH12K_DBG_MAC, "recovery started success\n");
4980*5c1def83SBjoern A. Zeeb }
4981*5c1def83SBjoern A. Zeeb
4982*5c1def83SBjoern A. Zeeb ath12k_dbg(ab, ATH12K_DBG_MAC, "waiting reconfigure...\n");
4983*5c1def83SBjoern A. Zeeb
4984*5c1def83SBjoern A. Zeeb wait_for_completion_timeout(&ab->reconfigure_complete,
4985*5c1def83SBjoern A. Zeeb ATH12K_RECONFIGURE_TIMEOUT_HZ);
4986*5c1def83SBjoern A. Zeeb }
4987*5c1def83SBjoern A. Zeeb
ath12k_mac_op_start(struct ieee80211_hw * hw)4988*5c1def83SBjoern A. Zeeb static int ath12k_mac_op_start(struct ieee80211_hw *hw)
4989*5c1def83SBjoern A. Zeeb {
4990*5c1def83SBjoern A. Zeeb struct ath12k *ar = hw->priv;
4991*5c1def83SBjoern A. Zeeb struct ath12k_base *ab = ar->ab;
4992*5c1def83SBjoern A. Zeeb struct ath12k_pdev *pdev = ar->pdev;
4993*5c1def83SBjoern A. Zeeb int ret;
4994*5c1def83SBjoern A. Zeeb
4995*5c1def83SBjoern A. Zeeb ath12k_mac_drain_tx(ar);
4996*5c1def83SBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
4997*5c1def83SBjoern A. Zeeb
4998*5c1def83SBjoern A. Zeeb switch (ar->state) {
4999*5c1def83SBjoern A. Zeeb case ATH12K_STATE_OFF:
5000*5c1def83SBjoern A. Zeeb ar->state = ATH12K_STATE_ON;
5001*5c1def83SBjoern A. Zeeb break;
5002*5c1def83SBjoern A. Zeeb case ATH12K_STATE_RESTARTING:
5003*5c1def83SBjoern A. Zeeb ar->state = ATH12K_STATE_RESTARTED;
5004*5c1def83SBjoern A. Zeeb ath12k_mac_wait_reconfigure(ab);
5005*5c1def83SBjoern A. Zeeb break;
5006*5c1def83SBjoern A. Zeeb case ATH12K_STATE_RESTARTED:
5007*5c1def83SBjoern A. Zeeb case ATH12K_STATE_WEDGED:
5008*5c1def83SBjoern A. Zeeb case ATH12K_STATE_ON:
5009*5c1def83SBjoern A. Zeeb WARN_ON(1);
5010*5c1def83SBjoern A. Zeeb ret = -EINVAL;
5011*5c1def83SBjoern A. Zeeb goto err;
5012*5c1def83SBjoern A. Zeeb }
5013*5c1def83SBjoern A. Zeeb
5014*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_PMF_QOS,
5015*5c1def83SBjoern A. Zeeb 1, pdev->pdev_id);
5016*5c1def83SBjoern A. Zeeb
5017*5c1def83SBjoern A. Zeeb if (ret) {
5018*5c1def83SBjoern A. Zeeb ath12k_err(ar->ab, "failed to enable PMF QOS: (%d\n", ret);
5019*5c1def83SBjoern A. Zeeb goto err;
5020*5c1def83SBjoern A. Zeeb }
5021*5c1def83SBjoern A. Zeeb
5022*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_DYNAMIC_BW, 1,
5023*5c1def83SBjoern A. Zeeb pdev->pdev_id);
5024*5c1def83SBjoern A. Zeeb if (ret) {
5025*5c1def83SBjoern A. Zeeb ath12k_err(ar->ab, "failed to enable dynamic bw: %d\n", ret);
5026*5c1def83SBjoern A. Zeeb goto err;
5027*5c1def83SBjoern A. Zeeb }
5028*5c1def83SBjoern A. Zeeb
5029*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_ARP_AC_OVERRIDE,
5030*5c1def83SBjoern A. Zeeb 0, pdev->pdev_id);
5031*5c1def83SBjoern A. Zeeb if (ret) {
5032*5c1def83SBjoern A. Zeeb ath12k_err(ab, "failed to set ac override for ARP: %d\n",
5033*5c1def83SBjoern A. Zeeb ret);
5034*5c1def83SBjoern A. Zeeb goto err;
5035*5c1def83SBjoern A. Zeeb }
5036*5c1def83SBjoern A. Zeeb
5037*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_send_dfs_phyerr_offload_enable_cmd(ar, pdev->pdev_id);
5038*5c1def83SBjoern A. Zeeb if (ret) {
5039*5c1def83SBjoern A. Zeeb ath12k_err(ab, "failed to offload radar detection: %d\n",
5040*5c1def83SBjoern A. Zeeb ret);
5041*5c1def83SBjoern A. Zeeb goto err;
5042*5c1def83SBjoern A. Zeeb }
5043*5c1def83SBjoern A. Zeeb
5044*5c1def83SBjoern A. Zeeb ret = ath12k_dp_tx_htt_h2t_ppdu_stats_req(ar,
5045*5c1def83SBjoern A. Zeeb HTT_PPDU_STATS_TAG_DEFAULT);
5046*5c1def83SBjoern A. Zeeb if (ret) {
5047*5c1def83SBjoern A. Zeeb ath12k_err(ab, "failed to req ppdu stats: %d\n", ret);
5048*5c1def83SBjoern A. Zeeb goto err;
5049*5c1def83SBjoern A. Zeeb }
5050*5c1def83SBjoern A. Zeeb
5051*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_MESH_MCAST_ENABLE,
5052*5c1def83SBjoern A. Zeeb 1, pdev->pdev_id);
5053*5c1def83SBjoern A. Zeeb
5054*5c1def83SBjoern A. Zeeb if (ret) {
5055*5c1def83SBjoern A. Zeeb ath12k_err(ar->ab, "failed to enable MESH MCAST ENABLE: (%d\n", ret);
5056*5c1def83SBjoern A. Zeeb goto err;
5057*5c1def83SBjoern A. Zeeb }
5058*5c1def83SBjoern A. Zeeb
5059*5c1def83SBjoern A. Zeeb __ath12k_set_antenna(ar, ar->cfg_tx_chainmask, ar->cfg_rx_chainmask);
5060*5c1def83SBjoern A. Zeeb
5061*5c1def83SBjoern A. Zeeb /* TODO: Do we need to enable ANI? */
5062*5c1def83SBjoern A. Zeeb
5063*5c1def83SBjoern A. Zeeb ath12k_reg_update_chan_list(ar);
5064*5c1def83SBjoern A. Zeeb
5065*5c1def83SBjoern A. Zeeb ar->num_started_vdevs = 0;
5066*5c1def83SBjoern A. Zeeb ar->num_created_vdevs = 0;
5067*5c1def83SBjoern A. Zeeb ar->num_peers = 0;
5068*5c1def83SBjoern A. Zeeb ar->allocated_vdev_map = 0;
5069*5c1def83SBjoern A. Zeeb
5070*5c1def83SBjoern A. Zeeb /* Configure monitor status ring with default rx_filter to get rx status
5071*5c1def83SBjoern A. Zeeb * such as rssi, rx_duration.
5072*5c1def83SBjoern A. Zeeb */
5073*5c1def83SBjoern A. Zeeb ret = ath12k_mac_config_mon_status_default(ar, true);
5074*5c1def83SBjoern A. Zeeb if (ret && (ret != -ENOTSUPP)) {
5075*5c1def83SBjoern A. Zeeb ath12k_err(ab, "failed to configure monitor status ring with default rx_filter: (%d)\n",
5076*5c1def83SBjoern A. Zeeb ret);
5077*5c1def83SBjoern A. Zeeb goto err;
5078*5c1def83SBjoern A. Zeeb }
5079*5c1def83SBjoern A. Zeeb
5080*5c1def83SBjoern A. Zeeb if (ret == -ENOTSUPP)
5081*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
5082*5c1def83SBjoern A. Zeeb "monitor status config is not yet supported");
5083*5c1def83SBjoern A. Zeeb
5084*5c1def83SBjoern A. Zeeb /* Configure the hash seed for hash based reo dest ring selection */
5085*5c1def83SBjoern A. Zeeb ath12k_wmi_pdev_lro_cfg(ar, ar->pdev->pdev_id);
5086*5c1def83SBjoern A. Zeeb
5087*5c1def83SBjoern A. Zeeb /* allow device to enter IMPS */
5088*5c1def83SBjoern A. Zeeb if (ab->hw_params->idle_ps) {
5089*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_IDLE_PS_CONFIG,
5090*5c1def83SBjoern A. Zeeb 1, pdev->pdev_id);
5091*5c1def83SBjoern A. Zeeb if (ret) {
5092*5c1def83SBjoern A. Zeeb ath12k_err(ab, "failed to enable idle ps: %d\n", ret);
5093*5c1def83SBjoern A. Zeeb goto err;
5094*5c1def83SBjoern A. Zeeb }
5095*5c1def83SBjoern A. Zeeb }
5096*5c1def83SBjoern A. Zeeb
5097*5c1def83SBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
5098*5c1def83SBjoern A. Zeeb
5099*5c1def83SBjoern A. Zeeb rcu_assign_pointer(ab->pdevs_active[ar->pdev_idx],
5100*5c1def83SBjoern A. Zeeb &ab->pdevs[ar->pdev_idx]);
5101*5c1def83SBjoern A. Zeeb
5102*5c1def83SBjoern A. Zeeb return 0;
5103*5c1def83SBjoern A. Zeeb
5104*5c1def83SBjoern A. Zeeb err:
5105*5c1def83SBjoern A. Zeeb ar->state = ATH12K_STATE_OFF;
5106*5c1def83SBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
5107*5c1def83SBjoern A. Zeeb
5108*5c1def83SBjoern A. Zeeb return ret;
5109*5c1def83SBjoern A. Zeeb }
5110*5c1def83SBjoern A. Zeeb
ath12k_mac_op_stop(struct ieee80211_hw * hw)5111*5c1def83SBjoern A. Zeeb static void ath12k_mac_op_stop(struct ieee80211_hw *hw)
5112*5c1def83SBjoern A. Zeeb {
5113*5c1def83SBjoern A. Zeeb struct ath12k *ar = hw->priv;
5114*5c1def83SBjoern A. Zeeb struct htt_ppdu_stats_info *ppdu_stats, *tmp;
5115*5c1def83SBjoern A. Zeeb int ret;
5116*5c1def83SBjoern A. Zeeb
5117*5c1def83SBjoern A. Zeeb ath12k_mac_drain_tx(ar);
5118*5c1def83SBjoern A. Zeeb
5119*5c1def83SBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
5120*5c1def83SBjoern A. Zeeb ret = ath12k_mac_config_mon_status_default(ar, false);
5121*5c1def83SBjoern A. Zeeb if (ret && (ret != -ENOTSUPP))
5122*5c1def83SBjoern A. Zeeb ath12k_err(ar->ab, "failed to clear rx_filter for monitor status ring: (%d)\n",
5123*5c1def83SBjoern A. Zeeb ret);
5124*5c1def83SBjoern A. Zeeb
5125*5c1def83SBjoern A. Zeeb clear_bit(ATH12K_CAC_RUNNING, &ar->dev_flags);
5126*5c1def83SBjoern A. Zeeb ar->state = ATH12K_STATE_OFF;
5127*5c1def83SBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
5128*5c1def83SBjoern A. Zeeb
5129*5c1def83SBjoern A. Zeeb cancel_delayed_work_sync(&ar->scan.timeout);
5130*5c1def83SBjoern A. Zeeb cancel_work_sync(&ar->regd_update_work);
5131*5c1def83SBjoern A. Zeeb
5132*5c1def83SBjoern A. Zeeb spin_lock_bh(&ar->data_lock);
5133*5c1def83SBjoern A. Zeeb list_for_each_entry_safe(ppdu_stats, tmp, &ar->ppdu_stats_info, list) {
5134*5c1def83SBjoern A. Zeeb list_del(&ppdu_stats->list);
5135*5c1def83SBjoern A. Zeeb kfree(ppdu_stats);
5136*5c1def83SBjoern A. Zeeb }
5137*5c1def83SBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
5138*5c1def83SBjoern A. Zeeb
5139*5c1def83SBjoern A. Zeeb rcu_assign_pointer(ar->ab->pdevs_active[ar->pdev_idx], NULL);
5140*5c1def83SBjoern A. Zeeb
5141*5c1def83SBjoern A. Zeeb synchronize_rcu();
5142*5c1def83SBjoern A. Zeeb
5143*5c1def83SBjoern A. Zeeb atomic_set(&ar->num_pending_mgmt_tx, 0);
5144*5c1def83SBjoern A. Zeeb }
5145*5c1def83SBjoern A. Zeeb
5146*5c1def83SBjoern A. Zeeb static u8
ath12k_mac_get_vdev_stats_id(struct ath12k_vif * arvif)5147*5c1def83SBjoern A. Zeeb ath12k_mac_get_vdev_stats_id(struct ath12k_vif *arvif)
5148*5c1def83SBjoern A. Zeeb {
5149*5c1def83SBjoern A. Zeeb struct ath12k_base *ab = arvif->ar->ab;
5150*5c1def83SBjoern A. Zeeb u8 vdev_stats_id = 0;
5151*5c1def83SBjoern A. Zeeb
5152*5c1def83SBjoern A. Zeeb do {
5153*5c1def83SBjoern A. Zeeb if (ab->free_vdev_stats_id_map & (1LL << vdev_stats_id)) {
5154*5c1def83SBjoern A. Zeeb vdev_stats_id++;
5155*5c1def83SBjoern A. Zeeb if (vdev_stats_id <= ATH12K_INVAL_VDEV_STATS_ID) {
5156*5c1def83SBjoern A. Zeeb vdev_stats_id = ATH12K_INVAL_VDEV_STATS_ID;
5157*5c1def83SBjoern A. Zeeb break;
5158*5c1def83SBjoern A. Zeeb }
5159*5c1def83SBjoern A. Zeeb } else {
5160*5c1def83SBjoern A. Zeeb ab->free_vdev_stats_id_map |= (1LL << vdev_stats_id);
5161*5c1def83SBjoern A. Zeeb break;
5162*5c1def83SBjoern A. Zeeb }
5163*5c1def83SBjoern A. Zeeb } while (vdev_stats_id);
5164*5c1def83SBjoern A. Zeeb
5165*5c1def83SBjoern A. Zeeb arvif->vdev_stats_id = vdev_stats_id;
5166*5c1def83SBjoern A. Zeeb return vdev_stats_id;
5167*5c1def83SBjoern A. Zeeb }
5168*5c1def83SBjoern A. Zeeb
ath12k_mac_setup_vdev_create_arg(struct ath12k_vif * arvif,struct ath12k_wmi_vdev_create_arg * arg)5169*5c1def83SBjoern A. Zeeb static void ath12k_mac_setup_vdev_create_arg(struct ath12k_vif *arvif,
5170*5c1def83SBjoern A. Zeeb struct ath12k_wmi_vdev_create_arg *arg)
5171*5c1def83SBjoern A. Zeeb {
5172*5c1def83SBjoern A. Zeeb struct ath12k *ar = arvif->ar;
5173*5c1def83SBjoern A. Zeeb struct ath12k_pdev *pdev = ar->pdev;
5174*5c1def83SBjoern A. Zeeb
5175*5c1def83SBjoern A. Zeeb arg->if_id = arvif->vdev_id;
5176*5c1def83SBjoern A. Zeeb arg->type = arvif->vdev_type;
5177*5c1def83SBjoern A. Zeeb arg->subtype = arvif->vdev_subtype;
5178*5c1def83SBjoern A. Zeeb arg->pdev_id = pdev->pdev_id;
5179*5c1def83SBjoern A. Zeeb
5180*5c1def83SBjoern A. Zeeb if (pdev->cap.supported_bands & WMI_HOST_WLAN_2G_CAP) {
5181*5c1def83SBjoern A. Zeeb arg->chains[NL80211_BAND_2GHZ].tx = ar->num_tx_chains;
5182*5c1def83SBjoern A. Zeeb arg->chains[NL80211_BAND_2GHZ].rx = ar->num_rx_chains;
5183*5c1def83SBjoern A. Zeeb }
5184*5c1def83SBjoern A. Zeeb if (pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP) {
5185*5c1def83SBjoern A. Zeeb arg->chains[NL80211_BAND_5GHZ].tx = ar->num_tx_chains;
5186*5c1def83SBjoern A. Zeeb arg->chains[NL80211_BAND_5GHZ].rx = ar->num_rx_chains;
5187*5c1def83SBjoern A. Zeeb }
5188*5c1def83SBjoern A. Zeeb if (pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP &&
5189*5c1def83SBjoern A. Zeeb ar->supports_6ghz) {
5190*5c1def83SBjoern A. Zeeb arg->chains[NL80211_BAND_6GHZ].tx = ar->num_tx_chains;
5191*5c1def83SBjoern A. Zeeb arg->chains[NL80211_BAND_6GHZ].rx = ar->num_rx_chains;
5192*5c1def83SBjoern A. Zeeb }
5193*5c1def83SBjoern A. Zeeb
5194*5c1def83SBjoern A. Zeeb arg->if_stats_id = ath12k_mac_get_vdev_stats_id(arvif);
5195*5c1def83SBjoern A. Zeeb }
5196*5c1def83SBjoern A. Zeeb
5197*5c1def83SBjoern A. Zeeb static u32
ath12k_mac_prepare_he_mode(struct ath12k_pdev * pdev,u32 viftype)5198*5c1def83SBjoern A. Zeeb ath12k_mac_prepare_he_mode(struct ath12k_pdev *pdev, u32 viftype)
5199*5c1def83SBjoern A. Zeeb {
5200*5c1def83SBjoern A. Zeeb struct ath12k_pdev_cap *pdev_cap = &pdev->cap;
5201*5c1def83SBjoern A. Zeeb struct ath12k_band_cap *cap_band = NULL;
5202*5c1def83SBjoern A. Zeeb u32 *hecap_phy_ptr = NULL;
5203*5c1def83SBjoern A. Zeeb u32 hemode;
5204*5c1def83SBjoern A. Zeeb
5205*5c1def83SBjoern A. Zeeb if (pdev->cap.supported_bands & WMI_HOST_WLAN_2G_CAP)
5206*5c1def83SBjoern A. Zeeb cap_band = &pdev_cap->band[NL80211_BAND_2GHZ];
5207*5c1def83SBjoern A. Zeeb else
5208*5c1def83SBjoern A. Zeeb cap_band = &pdev_cap->band[NL80211_BAND_5GHZ];
5209*5c1def83SBjoern A. Zeeb
5210*5c1def83SBjoern A. Zeeb hecap_phy_ptr = &cap_band->he_cap_phy_info[0];
5211*5c1def83SBjoern A. Zeeb
5212*5c1def83SBjoern A. Zeeb hemode = u32_encode_bits(HE_SU_BFEE_ENABLE, HE_MODE_SU_TX_BFEE) |
5213*5c1def83SBjoern A. Zeeb u32_encode_bits(HECAP_PHY_SUBFMR_GET(hecap_phy_ptr),
5214*5c1def83SBjoern A. Zeeb HE_MODE_SU_TX_BFER) |
5215*5c1def83SBjoern A. Zeeb u32_encode_bits(HECAP_PHY_ULMUMIMO_GET(hecap_phy_ptr),
5216*5c1def83SBjoern A. Zeeb HE_MODE_UL_MUMIMO);
5217*5c1def83SBjoern A. Zeeb
5218*5c1def83SBjoern A. Zeeb /* TODO: WDS and other modes */
5219*5c1def83SBjoern A. Zeeb if (viftype == NL80211_IFTYPE_AP) {
5220*5c1def83SBjoern A. Zeeb hemode |= u32_encode_bits(HECAP_PHY_MUBFMR_GET(hecap_phy_ptr),
5221*5c1def83SBjoern A. Zeeb HE_MODE_MU_TX_BFER) |
5222*5c1def83SBjoern A. Zeeb u32_encode_bits(HE_DL_MUOFDMA_ENABLE, HE_MODE_DL_OFDMA) |
5223*5c1def83SBjoern A. Zeeb u32_encode_bits(HE_UL_MUOFDMA_ENABLE, HE_MODE_UL_OFDMA);
5224*5c1def83SBjoern A. Zeeb } else {
5225*5c1def83SBjoern A. Zeeb hemode |= u32_encode_bits(HE_MU_BFEE_ENABLE, HE_MODE_MU_TX_BFEE);
5226*5c1def83SBjoern A. Zeeb }
5227*5c1def83SBjoern A. Zeeb
5228*5c1def83SBjoern A. Zeeb return hemode;
5229*5c1def83SBjoern A. Zeeb }
5230*5c1def83SBjoern A. Zeeb
ath12k_set_he_mu_sounding_mode(struct ath12k * ar,struct ath12k_vif * arvif)5231*5c1def83SBjoern A. Zeeb static int ath12k_set_he_mu_sounding_mode(struct ath12k *ar,
5232*5c1def83SBjoern A. Zeeb struct ath12k_vif *arvif)
5233*5c1def83SBjoern A. Zeeb {
5234*5c1def83SBjoern A. Zeeb u32 param_id, param_value;
5235*5c1def83SBjoern A. Zeeb struct ath12k_base *ab = ar->ab;
5236*5c1def83SBjoern A. Zeeb int ret;
5237*5c1def83SBjoern A. Zeeb
5238*5c1def83SBjoern A. Zeeb param_id = WMI_VDEV_PARAM_SET_HEMU_MODE;
5239*5c1def83SBjoern A. Zeeb param_value = ath12k_mac_prepare_he_mode(ar->pdev, arvif->vif->type);
5240*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
5241*5c1def83SBjoern A. Zeeb param_id, param_value);
5242*5c1def83SBjoern A. Zeeb if (ret) {
5243*5c1def83SBjoern A. Zeeb ath12k_warn(ab, "failed to set vdev %d HE MU mode: %d param_value %x\n",
5244*5c1def83SBjoern A. Zeeb arvif->vdev_id, ret, param_value);
5245*5c1def83SBjoern A. Zeeb return ret;
5246*5c1def83SBjoern A. Zeeb }
5247*5c1def83SBjoern A. Zeeb param_id = WMI_VDEV_PARAM_SET_HE_SOUNDING_MODE;
5248*5c1def83SBjoern A. Zeeb param_value =
5249*5c1def83SBjoern A. Zeeb u32_encode_bits(HE_VHT_SOUNDING_MODE_ENABLE, HE_VHT_SOUNDING_MODE) |
5250*5c1def83SBjoern A. Zeeb u32_encode_bits(HE_TRIG_NONTRIG_SOUNDING_MODE_ENABLE,
5251*5c1def83SBjoern A. Zeeb HE_TRIG_NONTRIG_SOUNDING_MODE);
5252*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
5253*5c1def83SBjoern A. Zeeb param_id, param_value);
5254*5c1def83SBjoern A. Zeeb if (ret) {
5255*5c1def83SBjoern A. Zeeb ath12k_warn(ab, "failed to set vdev %d HE MU mode: %d\n",
5256*5c1def83SBjoern A. Zeeb arvif->vdev_id, ret);
5257*5c1def83SBjoern A. Zeeb return ret;
5258*5c1def83SBjoern A. Zeeb }
5259*5c1def83SBjoern A. Zeeb return ret;
5260*5c1def83SBjoern A. Zeeb }
5261*5c1def83SBjoern A. Zeeb
ath12k_mac_op_update_vif_offload(struct ieee80211_hw * hw,struct ieee80211_vif * vif)5262*5c1def83SBjoern A. Zeeb static void ath12k_mac_op_update_vif_offload(struct ieee80211_hw *hw,
5263*5c1def83SBjoern A. Zeeb struct ieee80211_vif *vif)
5264*5c1def83SBjoern A. Zeeb {
5265*5c1def83SBjoern A. Zeeb struct ath12k *ar = hw->priv;
5266*5c1def83SBjoern A. Zeeb struct ath12k_base *ab = ar->ab;
5267*5c1def83SBjoern A. Zeeb struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
5268*5c1def83SBjoern A. Zeeb u32 param_id, param_value;
5269*5c1def83SBjoern A. Zeeb int ret;
5270*5c1def83SBjoern A. Zeeb
5271*5c1def83SBjoern A. Zeeb param_id = WMI_VDEV_PARAM_TX_ENCAP_TYPE;
5272*5c1def83SBjoern A. Zeeb if (vif->type != NL80211_IFTYPE_STATION &&
5273*5c1def83SBjoern A. Zeeb vif->type != NL80211_IFTYPE_AP)
5274*5c1def83SBjoern A. Zeeb vif->offload_flags &= ~(IEEE80211_OFFLOAD_ENCAP_ENABLED |
5275*5c1def83SBjoern A. Zeeb IEEE80211_OFFLOAD_DECAP_ENABLED);
5276*5c1def83SBjoern A. Zeeb
5277*5c1def83SBjoern A. Zeeb if (vif->offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED)
5278*5c1def83SBjoern A. Zeeb arvif->tx_encap_type = ATH12K_HW_TXRX_ETHERNET;
5279*5c1def83SBjoern A. Zeeb else if (test_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags))
5280*5c1def83SBjoern A. Zeeb arvif->tx_encap_type = ATH12K_HW_TXRX_RAW;
5281*5c1def83SBjoern A. Zeeb else
5282*5c1def83SBjoern A. Zeeb arvif->tx_encap_type = ATH12K_HW_TXRX_NATIVE_WIFI;
5283*5c1def83SBjoern A. Zeeb
5284*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
5285*5c1def83SBjoern A. Zeeb param_id, arvif->tx_encap_type);
5286*5c1def83SBjoern A. Zeeb if (ret) {
5287*5c1def83SBjoern A. Zeeb ath12k_warn(ab, "failed to set vdev %d tx encap mode: %d\n",
5288*5c1def83SBjoern A. Zeeb arvif->vdev_id, ret);
5289*5c1def83SBjoern A. Zeeb vif->offload_flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED;
5290*5c1def83SBjoern A. Zeeb }
5291*5c1def83SBjoern A. Zeeb
5292*5c1def83SBjoern A. Zeeb param_id = WMI_VDEV_PARAM_RX_DECAP_TYPE;
5293*5c1def83SBjoern A. Zeeb if (vif->offload_flags & IEEE80211_OFFLOAD_DECAP_ENABLED)
5294*5c1def83SBjoern A. Zeeb param_value = ATH12K_HW_TXRX_ETHERNET;
5295*5c1def83SBjoern A. Zeeb else if (test_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags))
5296*5c1def83SBjoern A. Zeeb param_value = ATH12K_HW_TXRX_RAW;
5297*5c1def83SBjoern A. Zeeb else
5298*5c1def83SBjoern A. Zeeb param_value = ATH12K_HW_TXRX_NATIVE_WIFI;
5299*5c1def83SBjoern A. Zeeb
5300*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
5301*5c1def83SBjoern A. Zeeb param_id, param_value);
5302*5c1def83SBjoern A. Zeeb if (ret) {
5303*5c1def83SBjoern A. Zeeb ath12k_warn(ab, "failed to set vdev %d rx decap mode: %d\n",
5304*5c1def83SBjoern A. Zeeb arvif->vdev_id, ret);
5305*5c1def83SBjoern A. Zeeb vif->offload_flags &= ~IEEE80211_OFFLOAD_DECAP_ENABLED;
5306*5c1def83SBjoern A. Zeeb }
5307*5c1def83SBjoern A. Zeeb }
5308*5c1def83SBjoern A. Zeeb
ath12k_mac_op_add_interface(struct ieee80211_hw * hw,struct ieee80211_vif * vif)5309*5c1def83SBjoern A. Zeeb static int ath12k_mac_op_add_interface(struct ieee80211_hw *hw,
5310*5c1def83SBjoern A. Zeeb struct ieee80211_vif *vif)
5311*5c1def83SBjoern A. Zeeb {
5312*5c1def83SBjoern A. Zeeb struct ath12k *ar = hw->priv;
5313*5c1def83SBjoern A. Zeeb struct ath12k_base *ab = ar->ab;
5314*5c1def83SBjoern A. Zeeb struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
5315*5c1def83SBjoern A. Zeeb struct ath12k_wmi_vdev_create_arg vdev_arg = {0};
5316*5c1def83SBjoern A. Zeeb struct ath12k_wmi_peer_create_arg peer_param;
5317*5c1def83SBjoern A. Zeeb u32 param_id, param_value;
5318*5c1def83SBjoern A. Zeeb u16 nss;
5319*5c1def83SBjoern A. Zeeb int i;
5320*5c1def83SBjoern A. Zeeb int ret;
5321*5c1def83SBjoern A. Zeeb int bit;
5322*5c1def83SBjoern A. Zeeb
5323*5c1def83SBjoern A. Zeeb vif->driver_flags |= IEEE80211_VIF_SUPPORTS_UAPSD;
5324*5c1def83SBjoern A. Zeeb
5325*5c1def83SBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
5326*5c1def83SBjoern A. Zeeb
5327*5c1def83SBjoern A. Zeeb if (vif->type == NL80211_IFTYPE_AP &&
5328*5c1def83SBjoern A. Zeeb ar->num_peers > (ar->max_num_peers - 1)) {
5329*5c1def83SBjoern A. Zeeb ath12k_warn(ab, "failed to create vdev due to insufficient peer entry resource in firmware\n");
5330*5c1def83SBjoern A. Zeeb ret = -ENOBUFS;
5331*5c1def83SBjoern A. Zeeb goto err;
5332*5c1def83SBjoern A. Zeeb }
5333*5c1def83SBjoern A. Zeeb
5334*5c1def83SBjoern A. Zeeb if (ar->num_created_vdevs > (TARGET_NUM_VDEVS - 1)) {
5335*5c1def83SBjoern A. Zeeb ath12k_warn(ab, "failed to create vdev, reached max vdev limit %d\n",
5336*5c1def83SBjoern A. Zeeb TARGET_NUM_VDEVS);
5337*5c1def83SBjoern A. Zeeb ret = -EBUSY;
5338*5c1def83SBjoern A. Zeeb goto err;
5339*5c1def83SBjoern A. Zeeb }
5340*5c1def83SBjoern A. Zeeb
5341*5c1def83SBjoern A. Zeeb memset(arvif, 0, sizeof(*arvif));
5342*5c1def83SBjoern A. Zeeb
5343*5c1def83SBjoern A. Zeeb arvif->ar = ar;
5344*5c1def83SBjoern A. Zeeb arvif->vif = vif;
5345*5c1def83SBjoern A. Zeeb
5346*5c1def83SBjoern A. Zeeb INIT_LIST_HEAD(&arvif->list);
5347*5c1def83SBjoern A. Zeeb
5348*5c1def83SBjoern A. Zeeb /* Should we initialize any worker to handle connection loss indication
5349*5c1def83SBjoern A. Zeeb * from firmware in sta mode?
5350*5c1def83SBjoern A. Zeeb */
5351*5c1def83SBjoern A. Zeeb
5352*5c1def83SBjoern A. Zeeb for (i = 0; i < ARRAY_SIZE(arvif->bitrate_mask.control); i++) {
5353*5c1def83SBjoern A. Zeeb arvif->bitrate_mask.control[i].legacy = 0xffffffff;
5354*5c1def83SBjoern A. Zeeb memset(arvif->bitrate_mask.control[i].ht_mcs, 0xff,
5355*5c1def83SBjoern A. Zeeb sizeof(arvif->bitrate_mask.control[i].ht_mcs));
5356*5c1def83SBjoern A. Zeeb memset(arvif->bitrate_mask.control[i].vht_mcs, 0xff,
5357*5c1def83SBjoern A. Zeeb sizeof(arvif->bitrate_mask.control[i].vht_mcs));
5358*5c1def83SBjoern A. Zeeb }
5359*5c1def83SBjoern A. Zeeb
5360*5c1def83SBjoern A. Zeeb bit = __ffs64(ab->free_vdev_map);
5361*5c1def83SBjoern A. Zeeb
5362*5c1def83SBjoern A. Zeeb arvif->vdev_id = bit;
5363*5c1def83SBjoern A. Zeeb arvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE;
5364*5c1def83SBjoern A. Zeeb
5365*5c1def83SBjoern A. Zeeb switch (vif->type) {
5366*5c1def83SBjoern A. Zeeb case NL80211_IFTYPE_UNSPECIFIED:
5367*5c1def83SBjoern A. Zeeb case NL80211_IFTYPE_STATION:
5368*5c1def83SBjoern A. Zeeb arvif->vdev_type = WMI_VDEV_TYPE_STA;
5369*5c1def83SBjoern A. Zeeb break;
5370*5c1def83SBjoern A. Zeeb case NL80211_IFTYPE_MESH_POINT:
5371*5c1def83SBjoern A. Zeeb arvif->vdev_subtype = WMI_VDEV_SUBTYPE_MESH_11S;
5372*5c1def83SBjoern A. Zeeb fallthrough;
5373*5c1def83SBjoern A. Zeeb case NL80211_IFTYPE_AP:
5374*5c1def83SBjoern A. Zeeb arvif->vdev_type = WMI_VDEV_TYPE_AP;
5375*5c1def83SBjoern A. Zeeb break;
5376*5c1def83SBjoern A. Zeeb case NL80211_IFTYPE_MONITOR:
5377*5c1def83SBjoern A. Zeeb arvif->vdev_type = WMI_VDEV_TYPE_MONITOR;
5378*5c1def83SBjoern A. Zeeb ar->monitor_vdev_id = bit;
5379*5c1def83SBjoern A. Zeeb break;
5380*5c1def83SBjoern A. Zeeb default:
5381*5c1def83SBjoern A. Zeeb WARN_ON(1);
5382*5c1def83SBjoern A. Zeeb break;
5383*5c1def83SBjoern A. Zeeb }
5384*5c1def83SBjoern A. Zeeb
5385*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac add interface id %d type %d subtype %d map %llx\n",
5386*5c1def83SBjoern A. Zeeb arvif->vdev_id, arvif->vdev_type, arvif->vdev_subtype,
5387*5c1def83SBjoern A. Zeeb ab->free_vdev_map);
5388*5c1def83SBjoern A. Zeeb
5389*5c1def83SBjoern A. Zeeb vif->cab_queue = arvif->vdev_id % (ATH12K_HW_MAX_QUEUES - 1);
5390*5c1def83SBjoern A. Zeeb for (i = 0; i < ARRAY_SIZE(vif->hw_queue); i++)
5391*5c1def83SBjoern A. Zeeb vif->hw_queue[i] = i % (ATH12K_HW_MAX_QUEUES - 1);
5392*5c1def83SBjoern A. Zeeb
5393*5c1def83SBjoern A. Zeeb ath12k_mac_setup_vdev_create_arg(arvif, &vdev_arg);
5394*5c1def83SBjoern A. Zeeb
5395*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_create(ar, vif->addr, &vdev_arg);
5396*5c1def83SBjoern A. Zeeb if (ret) {
5397*5c1def83SBjoern A. Zeeb ath12k_warn(ab, "failed to create WMI vdev %d: %d\n",
5398*5c1def83SBjoern A. Zeeb arvif->vdev_id, ret);
5399*5c1def83SBjoern A. Zeeb goto err;
5400*5c1def83SBjoern A. Zeeb }
5401*5c1def83SBjoern A. Zeeb
5402*5c1def83SBjoern A. Zeeb ar->num_created_vdevs++;
5403*5c1def83SBjoern A. Zeeb ath12k_dbg(ab, ATH12K_DBG_MAC, "vdev %pM created, vdev_id %d\n",
5404*5c1def83SBjoern A. Zeeb vif->addr, arvif->vdev_id);
5405*5c1def83SBjoern A. Zeeb ar->allocated_vdev_map |= 1LL << arvif->vdev_id;
5406*5c1def83SBjoern A. Zeeb ab->free_vdev_map &= ~(1LL << arvif->vdev_id);
5407*5c1def83SBjoern A. Zeeb
5408*5c1def83SBjoern A. Zeeb spin_lock_bh(&ar->data_lock);
5409*5c1def83SBjoern A. Zeeb list_add(&arvif->list, &ar->arvifs);
5410*5c1def83SBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
5411*5c1def83SBjoern A. Zeeb
5412*5c1def83SBjoern A. Zeeb ath12k_mac_op_update_vif_offload(hw, vif);
5413*5c1def83SBjoern A. Zeeb
5414*5c1def83SBjoern A. Zeeb nss = hweight32(ar->cfg_tx_chainmask) ? : 1;
5415*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
5416*5c1def83SBjoern A. Zeeb WMI_VDEV_PARAM_NSS, nss);
5417*5c1def83SBjoern A. Zeeb if (ret) {
5418*5c1def83SBjoern A. Zeeb ath12k_warn(ab, "failed to set vdev %d chainmask 0x%x, nss %d :%d\n",
5419*5c1def83SBjoern A. Zeeb arvif->vdev_id, ar->cfg_tx_chainmask, nss, ret);
5420*5c1def83SBjoern A. Zeeb goto err_vdev_del;
5421*5c1def83SBjoern A. Zeeb }
5422*5c1def83SBjoern A. Zeeb
5423*5c1def83SBjoern A. Zeeb switch (arvif->vdev_type) {
5424*5c1def83SBjoern A. Zeeb case WMI_VDEV_TYPE_AP:
5425*5c1def83SBjoern A. Zeeb peer_param.vdev_id = arvif->vdev_id;
5426*5c1def83SBjoern A. Zeeb peer_param.peer_addr = vif->addr;
5427*5c1def83SBjoern A. Zeeb peer_param.peer_type = WMI_PEER_TYPE_DEFAULT;
5428*5c1def83SBjoern A. Zeeb ret = ath12k_peer_create(ar, arvif, NULL, &peer_param);
5429*5c1def83SBjoern A. Zeeb if (ret) {
5430*5c1def83SBjoern A. Zeeb ath12k_warn(ab, "failed to vdev %d create peer for AP: %d\n",
5431*5c1def83SBjoern A. Zeeb arvif->vdev_id, ret);
5432*5c1def83SBjoern A. Zeeb goto err_vdev_del;
5433*5c1def83SBjoern A. Zeeb }
5434*5c1def83SBjoern A. Zeeb
5435*5c1def83SBjoern A. Zeeb ret = ath12k_mac_set_kickout(arvif);
5436*5c1def83SBjoern A. Zeeb if (ret) {
5437*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to set vdev %i kickout parameters: %d\n",
5438*5c1def83SBjoern A. Zeeb arvif->vdev_id, ret);
5439*5c1def83SBjoern A. Zeeb goto err_peer_del;
5440*5c1def83SBjoern A. Zeeb }
5441*5c1def83SBjoern A. Zeeb break;
5442*5c1def83SBjoern A. Zeeb case WMI_VDEV_TYPE_STA:
5443*5c1def83SBjoern A. Zeeb param_id = WMI_STA_PS_PARAM_RX_WAKE_POLICY;
5444*5c1def83SBjoern A. Zeeb param_value = WMI_STA_PS_RX_WAKE_POLICY_WAKE;
5445*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_set_sta_ps_param(ar, arvif->vdev_id,
5446*5c1def83SBjoern A. Zeeb param_id, param_value);
5447*5c1def83SBjoern A. Zeeb if (ret) {
5448*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to set vdev %d RX wake policy: %d\n",
5449*5c1def83SBjoern A. Zeeb arvif->vdev_id, ret);
5450*5c1def83SBjoern A. Zeeb goto err_peer_del;
5451*5c1def83SBjoern A. Zeeb }
5452*5c1def83SBjoern A. Zeeb
5453*5c1def83SBjoern A. Zeeb param_id = WMI_STA_PS_PARAM_TX_WAKE_THRESHOLD;
5454*5c1def83SBjoern A. Zeeb param_value = WMI_STA_PS_TX_WAKE_THRESHOLD_ALWAYS;
5455*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_set_sta_ps_param(ar, arvif->vdev_id,
5456*5c1def83SBjoern A. Zeeb param_id, param_value);
5457*5c1def83SBjoern A. Zeeb if (ret) {
5458*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to set vdev %d TX wake threshold: %d\n",
5459*5c1def83SBjoern A. Zeeb arvif->vdev_id, ret);
5460*5c1def83SBjoern A. Zeeb goto err_peer_del;
5461*5c1def83SBjoern A. Zeeb }
5462*5c1def83SBjoern A. Zeeb
5463*5c1def83SBjoern A. Zeeb param_id = WMI_STA_PS_PARAM_PSPOLL_COUNT;
5464*5c1def83SBjoern A. Zeeb param_value = WMI_STA_PS_PSPOLL_COUNT_NO_MAX;
5465*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_set_sta_ps_param(ar, arvif->vdev_id,
5466*5c1def83SBjoern A. Zeeb param_id, param_value);
5467*5c1def83SBjoern A. Zeeb if (ret) {
5468*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to set vdev %d pspoll count: %d\n",
5469*5c1def83SBjoern A. Zeeb arvif->vdev_id, ret);
5470*5c1def83SBjoern A. Zeeb goto err_peer_del;
5471*5c1def83SBjoern A. Zeeb }
5472*5c1def83SBjoern A. Zeeb
5473*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_pdev_set_ps_mode(ar, arvif->vdev_id, false);
5474*5c1def83SBjoern A. Zeeb if (ret) {
5475*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to disable vdev %d ps mode: %d\n",
5476*5c1def83SBjoern A. Zeeb arvif->vdev_id, ret);
5477*5c1def83SBjoern A. Zeeb goto err_peer_del;
5478*5c1def83SBjoern A. Zeeb }
5479*5c1def83SBjoern A. Zeeb break;
5480*5c1def83SBjoern A. Zeeb default:
5481*5c1def83SBjoern A. Zeeb break;
5482*5c1def83SBjoern A. Zeeb }
5483*5c1def83SBjoern A. Zeeb
5484*5c1def83SBjoern A. Zeeb arvif->txpower = vif->bss_conf.txpower;
5485*5c1def83SBjoern A. Zeeb ret = ath12k_mac_txpower_recalc(ar);
5486*5c1def83SBjoern A. Zeeb if (ret)
5487*5c1def83SBjoern A. Zeeb goto err_peer_del;
5488*5c1def83SBjoern A. Zeeb
5489*5c1def83SBjoern A. Zeeb param_id = WMI_VDEV_PARAM_RTS_THRESHOLD;
5490*5c1def83SBjoern A. Zeeb param_value = ar->hw->wiphy->rts_threshold;
5491*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
5492*5c1def83SBjoern A. Zeeb param_id, param_value);
5493*5c1def83SBjoern A. Zeeb if (ret) {
5494*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to set rts threshold for vdev %d: %d\n",
5495*5c1def83SBjoern A. Zeeb arvif->vdev_id, ret);
5496*5c1def83SBjoern A. Zeeb }
5497*5c1def83SBjoern A. Zeeb
5498*5c1def83SBjoern A. Zeeb ath12k_dp_vdev_tx_attach(ar, arvif);
5499*5c1def83SBjoern A. Zeeb
5500*5c1def83SBjoern A. Zeeb if (vif->type != NL80211_IFTYPE_MONITOR && ar->monitor_conf_enabled)
5501*5c1def83SBjoern A. Zeeb ath12k_mac_monitor_vdev_create(ar);
5502*5c1def83SBjoern A. Zeeb
5503*5c1def83SBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
5504*5c1def83SBjoern A. Zeeb
5505*5c1def83SBjoern A. Zeeb return ret;
5506*5c1def83SBjoern A. Zeeb
5507*5c1def83SBjoern A. Zeeb err_peer_del:
5508*5c1def83SBjoern A. Zeeb if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
5509*5c1def83SBjoern A. Zeeb reinit_completion(&ar->peer_delete_done);
5510*5c1def83SBjoern A. Zeeb
5511*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_send_peer_delete_cmd(ar, vif->addr,
5512*5c1def83SBjoern A. Zeeb arvif->vdev_id);
5513*5c1def83SBjoern A. Zeeb if (ret) {
5514*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to delete peer vdev_id %d addr %pM\n",
5515*5c1def83SBjoern A. Zeeb arvif->vdev_id, vif->addr);
5516*5c1def83SBjoern A. Zeeb goto err;
5517*5c1def83SBjoern A. Zeeb }
5518*5c1def83SBjoern A. Zeeb
5519*5c1def83SBjoern A. Zeeb ret = ath12k_wait_for_peer_delete_done(ar, arvif->vdev_id,
5520*5c1def83SBjoern A. Zeeb vif->addr);
5521*5c1def83SBjoern A. Zeeb if (ret)
5522*5c1def83SBjoern A. Zeeb goto err;
5523*5c1def83SBjoern A. Zeeb
5524*5c1def83SBjoern A. Zeeb ar->num_peers--;
5525*5c1def83SBjoern A. Zeeb }
5526*5c1def83SBjoern A. Zeeb
5527*5c1def83SBjoern A. Zeeb err_vdev_del:
5528*5c1def83SBjoern A. Zeeb ath12k_wmi_vdev_delete(ar, arvif->vdev_id);
5529*5c1def83SBjoern A. Zeeb ar->num_created_vdevs--;
5530*5c1def83SBjoern A. Zeeb ar->allocated_vdev_map &= ~(1LL << arvif->vdev_id);
5531*5c1def83SBjoern A. Zeeb ab->free_vdev_map |= 1LL << arvif->vdev_id;
5532*5c1def83SBjoern A. Zeeb ab->free_vdev_stats_id_map &= ~(1LL << arvif->vdev_stats_id);
5533*5c1def83SBjoern A. Zeeb spin_lock_bh(&ar->data_lock);
5534*5c1def83SBjoern A. Zeeb list_del(&arvif->list);
5535*5c1def83SBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
5536*5c1def83SBjoern A. Zeeb
5537*5c1def83SBjoern A. Zeeb err:
5538*5c1def83SBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
5539*5c1def83SBjoern A. Zeeb
5540*5c1def83SBjoern A. Zeeb return ret;
5541*5c1def83SBjoern A. Zeeb }
5542*5c1def83SBjoern A. Zeeb
ath12k_mac_vif_unref(struct ath12k_dp * dp,struct ieee80211_vif * vif)5543*5c1def83SBjoern A. Zeeb static void ath12k_mac_vif_unref(struct ath12k_dp *dp, struct ieee80211_vif *vif)
5544*5c1def83SBjoern A. Zeeb {
5545*5c1def83SBjoern A. Zeeb struct ath12k_tx_desc_info *tx_desc_info;
5546*5c1def83SBjoern A. Zeeb struct ath12k_skb_cb *skb_cb;
5547*5c1def83SBjoern A. Zeeb struct sk_buff *skb;
5548*5c1def83SBjoern A. Zeeb int i;
5549*5c1def83SBjoern A. Zeeb
5550*5c1def83SBjoern A. Zeeb for (i = 0; i < ATH12K_HW_MAX_QUEUES; i++) {
5551*5c1def83SBjoern A. Zeeb spin_lock_bh(&dp->tx_desc_lock[i]);
5552*5c1def83SBjoern A. Zeeb
5553*5c1def83SBjoern A. Zeeb list_for_each_entry(tx_desc_info, &dp->tx_desc_used_list[i],
5554*5c1def83SBjoern A. Zeeb list) {
5555*5c1def83SBjoern A. Zeeb skb = tx_desc_info->skb;
5556*5c1def83SBjoern A. Zeeb if (!skb)
5557*5c1def83SBjoern A. Zeeb continue;
5558*5c1def83SBjoern A. Zeeb
5559*5c1def83SBjoern A. Zeeb skb_cb = ATH12K_SKB_CB(skb);
5560*5c1def83SBjoern A. Zeeb if (skb_cb->vif == vif)
5561*5c1def83SBjoern A. Zeeb skb_cb->vif = NULL;
5562*5c1def83SBjoern A. Zeeb }
5563*5c1def83SBjoern A. Zeeb
5564*5c1def83SBjoern A. Zeeb spin_unlock_bh(&dp->tx_desc_lock[i]);
5565*5c1def83SBjoern A. Zeeb }
5566*5c1def83SBjoern A. Zeeb }
5567*5c1def83SBjoern A. Zeeb
ath12k_mac_op_remove_interface(struct ieee80211_hw * hw,struct ieee80211_vif * vif)5568*5c1def83SBjoern A. Zeeb static void ath12k_mac_op_remove_interface(struct ieee80211_hw *hw,
5569*5c1def83SBjoern A. Zeeb struct ieee80211_vif *vif)
5570*5c1def83SBjoern A. Zeeb {
5571*5c1def83SBjoern A. Zeeb struct ath12k *ar = hw->priv;
5572*5c1def83SBjoern A. Zeeb struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
5573*5c1def83SBjoern A. Zeeb struct ath12k_base *ab = ar->ab;
5574*5c1def83SBjoern A. Zeeb unsigned long time_left;
5575*5c1def83SBjoern A. Zeeb int ret;
5576*5c1def83SBjoern A. Zeeb
5577*5c1def83SBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
5578*5c1def83SBjoern A. Zeeb
5579*5c1def83SBjoern A. Zeeb ath12k_dbg(ab, ATH12K_DBG_MAC, "mac remove interface (vdev %d)\n",
5580*5c1def83SBjoern A. Zeeb arvif->vdev_id);
5581*5c1def83SBjoern A. Zeeb
5582*5c1def83SBjoern A. Zeeb if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
5583*5c1def83SBjoern A. Zeeb ret = ath12k_peer_delete(ar, arvif->vdev_id, vif->addr);
5584*5c1def83SBjoern A. Zeeb if (ret)
5585*5c1def83SBjoern A. Zeeb ath12k_warn(ab, "failed to submit AP self-peer removal on vdev %d: %d\n",
5586*5c1def83SBjoern A. Zeeb arvif->vdev_id, ret);
5587*5c1def83SBjoern A. Zeeb }
5588*5c1def83SBjoern A. Zeeb
5589*5c1def83SBjoern A. Zeeb reinit_completion(&ar->vdev_delete_done);
5590*5c1def83SBjoern A. Zeeb
5591*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_delete(ar, arvif->vdev_id);
5592*5c1def83SBjoern A. Zeeb if (ret) {
5593*5c1def83SBjoern A. Zeeb ath12k_warn(ab, "failed to delete WMI vdev %d: %d\n",
5594*5c1def83SBjoern A. Zeeb arvif->vdev_id, ret);
5595*5c1def83SBjoern A. Zeeb goto err_vdev_del;
5596*5c1def83SBjoern A. Zeeb }
5597*5c1def83SBjoern A. Zeeb
5598*5c1def83SBjoern A. Zeeb time_left = wait_for_completion_timeout(&ar->vdev_delete_done,
5599*5c1def83SBjoern A. Zeeb ATH12K_VDEV_DELETE_TIMEOUT_HZ);
5600*5c1def83SBjoern A. Zeeb if (time_left == 0) {
5601*5c1def83SBjoern A. Zeeb ath12k_warn(ab, "Timeout in receiving vdev delete response\n");
5602*5c1def83SBjoern A. Zeeb goto err_vdev_del;
5603*5c1def83SBjoern A. Zeeb }
5604*5c1def83SBjoern A. Zeeb
5605*5c1def83SBjoern A. Zeeb if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
5606*5c1def83SBjoern A. Zeeb ar->monitor_vdev_id = -1;
5607*5c1def83SBjoern A. Zeeb ar->monitor_vdev_created = false;
5608*5c1def83SBjoern A. Zeeb } else if (ar->monitor_vdev_created && !ar->monitor_started) {
5609*5c1def83SBjoern A. Zeeb ret = ath12k_mac_monitor_vdev_delete(ar);
5610*5c1def83SBjoern A. Zeeb }
5611*5c1def83SBjoern A. Zeeb
5612*5c1def83SBjoern A. Zeeb ab->free_vdev_map |= 1LL << (arvif->vdev_id);
5613*5c1def83SBjoern A. Zeeb ar->allocated_vdev_map &= ~(1LL << arvif->vdev_id);
5614*5c1def83SBjoern A. Zeeb ab->free_vdev_stats_id_map &= ~(1LL << arvif->vdev_stats_id);
5615*5c1def83SBjoern A. Zeeb ar->num_created_vdevs--;
5616*5c1def83SBjoern A. Zeeb
5617*5c1def83SBjoern A. Zeeb ath12k_dbg(ab, ATH12K_DBG_MAC, "vdev %pM deleted, vdev_id %d\n",
5618*5c1def83SBjoern A. Zeeb vif->addr, arvif->vdev_id);
5619*5c1def83SBjoern A. Zeeb
5620*5c1def83SBjoern A. Zeeb err_vdev_del:
5621*5c1def83SBjoern A. Zeeb spin_lock_bh(&ar->data_lock);
5622*5c1def83SBjoern A. Zeeb list_del(&arvif->list);
5623*5c1def83SBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
5624*5c1def83SBjoern A. Zeeb
5625*5c1def83SBjoern A. Zeeb ath12k_peer_cleanup(ar, arvif->vdev_id);
5626*5c1def83SBjoern A. Zeeb
5627*5c1def83SBjoern A. Zeeb idr_for_each(&ar->txmgmt_idr,
5628*5c1def83SBjoern A. Zeeb ath12k_mac_vif_txmgmt_idr_remove, vif);
5629*5c1def83SBjoern A. Zeeb
5630*5c1def83SBjoern A. Zeeb ath12k_mac_vif_unref(&ab->dp, vif);
5631*5c1def83SBjoern A. Zeeb ath12k_dp_tx_put_bank_profile(&ab->dp, arvif->bank_id);
5632*5c1def83SBjoern A. Zeeb
5633*5c1def83SBjoern A. Zeeb /* Recalc txpower for remaining vdev */
5634*5c1def83SBjoern A. Zeeb ath12k_mac_txpower_recalc(ar);
5635*5c1def83SBjoern A. Zeeb clear_bit(ATH12K_FLAG_MONITOR_ENABLED, &ar->monitor_flags);
5636*5c1def83SBjoern A. Zeeb
5637*5c1def83SBjoern A. Zeeb /* TODO: recal traffic pause state based on the available vdevs */
5638*5c1def83SBjoern A. Zeeb
5639*5c1def83SBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
5640*5c1def83SBjoern A. Zeeb }
5641*5c1def83SBjoern A. Zeeb
5642*5c1def83SBjoern A. Zeeb /* FIXME: Has to be verified. */
5643*5c1def83SBjoern A. Zeeb #define SUPPORTED_FILTERS \
5644*5c1def83SBjoern A. Zeeb (FIF_ALLMULTI | \
5645*5c1def83SBjoern A. Zeeb FIF_CONTROL | \
5646*5c1def83SBjoern A. Zeeb FIF_PSPOLL | \
5647*5c1def83SBjoern A. Zeeb FIF_OTHER_BSS | \
5648*5c1def83SBjoern A. Zeeb FIF_BCN_PRBRESP_PROMISC | \
5649*5c1def83SBjoern A. Zeeb FIF_PROBE_REQ | \
5650*5c1def83SBjoern A. Zeeb FIF_FCSFAIL)
5651*5c1def83SBjoern A. Zeeb
ath12k_mac_op_configure_filter(struct ieee80211_hw * hw,unsigned int changed_flags,unsigned int * total_flags,u64 multicast)5652*5c1def83SBjoern A. Zeeb static void ath12k_mac_op_configure_filter(struct ieee80211_hw *hw,
5653*5c1def83SBjoern A. Zeeb unsigned int changed_flags,
5654*5c1def83SBjoern A. Zeeb unsigned int *total_flags,
5655*5c1def83SBjoern A. Zeeb u64 multicast)
5656*5c1def83SBjoern A. Zeeb {
5657*5c1def83SBjoern A. Zeeb struct ath12k *ar = hw->priv;
5658*5c1def83SBjoern A. Zeeb bool reset_flag;
5659*5c1def83SBjoern A. Zeeb int ret;
5660*5c1def83SBjoern A. Zeeb
5661*5c1def83SBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
5662*5c1def83SBjoern A. Zeeb
5663*5c1def83SBjoern A. Zeeb changed_flags &= SUPPORTED_FILTERS;
5664*5c1def83SBjoern A. Zeeb *total_flags &= SUPPORTED_FILTERS;
5665*5c1def83SBjoern A. Zeeb ar->filter_flags = *total_flags;
5666*5c1def83SBjoern A. Zeeb
5667*5c1def83SBjoern A. Zeeb /* For monitor mode */
5668*5c1def83SBjoern A. Zeeb reset_flag = !(ar->filter_flags & FIF_BCN_PRBRESP_PROMISC);
5669*5c1def83SBjoern A. Zeeb
5670*5c1def83SBjoern A. Zeeb ret = ath12k_dp_tx_htt_monitor_mode_ring_config(ar, reset_flag);
5671*5c1def83SBjoern A. Zeeb if (!ret) {
5672*5c1def83SBjoern A. Zeeb if (!reset_flag)
5673*5c1def83SBjoern A. Zeeb set_bit(ATH12K_FLAG_MONITOR_ENABLED, &ar->monitor_flags);
5674*5c1def83SBjoern A. Zeeb else
5675*5c1def83SBjoern A. Zeeb clear_bit(ATH12K_FLAG_MONITOR_ENABLED, &ar->monitor_flags);
5676*5c1def83SBjoern A. Zeeb } else {
5677*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab,
5678*5c1def83SBjoern A. Zeeb "fail to set monitor filter: %d\n", ret);
5679*5c1def83SBjoern A. Zeeb }
5680*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
5681*5c1def83SBjoern A. Zeeb "changed_flags:0x%x, total_flags:0x%x, reset_flag:%d\n",
5682*5c1def83SBjoern A. Zeeb changed_flags, *total_flags, reset_flag);
5683*5c1def83SBjoern A. Zeeb
5684*5c1def83SBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
5685*5c1def83SBjoern A. Zeeb }
5686*5c1def83SBjoern A. Zeeb
ath12k_mac_op_get_antenna(struct ieee80211_hw * hw,u32 * tx_ant,u32 * rx_ant)5687*5c1def83SBjoern A. Zeeb static int ath12k_mac_op_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
5688*5c1def83SBjoern A. Zeeb {
5689*5c1def83SBjoern A. Zeeb struct ath12k *ar = hw->priv;
5690*5c1def83SBjoern A. Zeeb
5691*5c1def83SBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
5692*5c1def83SBjoern A. Zeeb
5693*5c1def83SBjoern A. Zeeb *tx_ant = ar->cfg_tx_chainmask;
5694*5c1def83SBjoern A. Zeeb *rx_ant = ar->cfg_rx_chainmask;
5695*5c1def83SBjoern A. Zeeb
5696*5c1def83SBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
5697*5c1def83SBjoern A. Zeeb
5698*5c1def83SBjoern A. Zeeb return 0;
5699*5c1def83SBjoern A. Zeeb }
5700*5c1def83SBjoern A. Zeeb
ath12k_mac_op_set_antenna(struct ieee80211_hw * hw,u32 tx_ant,u32 rx_ant)5701*5c1def83SBjoern A. Zeeb static int ath12k_mac_op_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
5702*5c1def83SBjoern A. Zeeb {
5703*5c1def83SBjoern A. Zeeb struct ath12k *ar = hw->priv;
5704*5c1def83SBjoern A. Zeeb int ret;
5705*5c1def83SBjoern A. Zeeb
5706*5c1def83SBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
5707*5c1def83SBjoern A. Zeeb ret = __ath12k_set_antenna(ar, tx_ant, rx_ant);
5708*5c1def83SBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
5709*5c1def83SBjoern A. Zeeb
5710*5c1def83SBjoern A. Zeeb return ret;
5711*5c1def83SBjoern A. Zeeb }
5712*5c1def83SBjoern A. Zeeb
ath12k_mac_op_ampdu_action(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_ampdu_params * params)5713*5c1def83SBjoern A. Zeeb static int ath12k_mac_op_ampdu_action(struct ieee80211_hw *hw,
5714*5c1def83SBjoern A. Zeeb struct ieee80211_vif *vif,
5715*5c1def83SBjoern A. Zeeb struct ieee80211_ampdu_params *params)
5716*5c1def83SBjoern A. Zeeb {
5717*5c1def83SBjoern A. Zeeb struct ath12k *ar = hw->priv;
5718*5c1def83SBjoern A. Zeeb int ret = -EINVAL;
5719*5c1def83SBjoern A. Zeeb
5720*5c1def83SBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
5721*5c1def83SBjoern A. Zeeb
5722*5c1def83SBjoern A. Zeeb switch (params->action) {
5723*5c1def83SBjoern A. Zeeb case IEEE80211_AMPDU_RX_START:
5724*5c1def83SBjoern A. Zeeb ret = ath12k_dp_rx_ampdu_start(ar, params);
5725*5c1def83SBjoern A. Zeeb break;
5726*5c1def83SBjoern A. Zeeb case IEEE80211_AMPDU_RX_STOP:
5727*5c1def83SBjoern A. Zeeb ret = ath12k_dp_rx_ampdu_stop(ar, params);
5728*5c1def83SBjoern A. Zeeb break;
5729*5c1def83SBjoern A. Zeeb case IEEE80211_AMPDU_TX_START:
5730*5c1def83SBjoern A. Zeeb case IEEE80211_AMPDU_TX_STOP_CONT:
5731*5c1def83SBjoern A. Zeeb case IEEE80211_AMPDU_TX_STOP_FLUSH:
5732*5c1def83SBjoern A. Zeeb case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
5733*5c1def83SBjoern A. Zeeb case IEEE80211_AMPDU_TX_OPERATIONAL:
5734*5c1def83SBjoern A. Zeeb /* Tx A-MPDU aggregation offloaded to hw/fw so deny mac80211
5735*5c1def83SBjoern A. Zeeb * Tx aggregation requests.
5736*5c1def83SBjoern A. Zeeb */
5737*5c1def83SBjoern A. Zeeb ret = -EOPNOTSUPP;
5738*5c1def83SBjoern A. Zeeb break;
5739*5c1def83SBjoern A. Zeeb }
5740*5c1def83SBjoern A. Zeeb
5741*5c1def83SBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
5742*5c1def83SBjoern A. Zeeb
5743*5c1def83SBjoern A. Zeeb return ret;
5744*5c1def83SBjoern A. Zeeb }
5745*5c1def83SBjoern A. Zeeb
ath12k_mac_op_add_chanctx(struct ieee80211_hw * hw,struct ieee80211_chanctx_conf * ctx)5746*5c1def83SBjoern A. Zeeb static int ath12k_mac_op_add_chanctx(struct ieee80211_hw *hw,
5747*5c1def83SBjoern A. Zeeb struct ieee80211_chanctx_conf *ctx)
5748*5c1def83SBjoern A. Zeeb {
5749*5c1def83SBjoern A. Zeeb struct ath12k *ar = hw->priv;
5750*5c1def83SBjoern A. Zeeb struct ath12k_base *ab = ar->ab;
5751*5c1def83SBjoern A. Zeeb
5752*5c1def83SBjoern A. Zeeb ath12k_dbg(ab, ATH12K_DBG_MAC,
5753*5c1def83SBjoern A. Zeeb "mac chanctx add freq %u width %d ptr %pK\n",
5754*5c1def83SBjoern A. Zeeb ctx->def.chan->center_freq, ctx->def.width, ctx);
5755*5c1def83SBjoern A. Zeeb
5756*5c1def83SBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
5757*5c1def83SBjoern A. Zeeb
5758*5c1def83SBjoern A. Zeeb spin_lock_bh(&ar->data_lock);
5759*5c1def83SBjoern A. Zeeb /* TODO: In case of multiple channel context, populate rx_channel from
5760*5c1def83SBjoern A. Zeeb * Rx PPDU desc information.
5761*5c1def83SBjoern A. Zeeb */
5762*5c1def83SBjoern A. Zeeb ar->rx_channel = ctx->def.chan;
5763*5c1def83SBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
5764*5c1def83SBjoern A. Zeeb
5765*5c1def83SBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
5766*5c1def83SBjoern A. Zeeb
5767*5c1def83SBjoern A. Zeeb return 0;
5768*5c1def83SBjoern A. Zeeb }
5769*5c1def83SBjoern A. Zeeb
ath12k_mac_op_remove_chanctx(struct ieee80211_hw * hw,struct ieee80211_chanctx_conf * ctx)5770*5c1def83SBjoern A. Zeeb static void ath12k_mac_op_remove_chanctx(struct ieee80211_hw *hw,
5771*5c1def83SBjoern A. Zeeb struct ieee80211_chanctx_conf *ctx)
5772*5c1def83SBjoern A. Zeeb {
5773*5c1def83SBjoern A. Zeeb struct ath12k *ar = hw->priv;
5774*5c1def83SBjoern A. Zeeb struct ath12k_base *ab = ar->ab;
5775*5c1def83SBjoern A. Zeeb
5776*5c1def83SBjoern A. Zeeb ath12k_dbg(ab, ATH12K_DBG_MAC,
5777*5c1def83SBjoern A. Zeeb "mac chanctx remove freq %u width %d ptr %pK\n",
5778*5c1def83SBjoern A. Zeeb ctx->def.chan->center_freq, ctx->def.width, ctx);
5779*5c1def83SBjoern A. Zeeb
5780*5c1def83SBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
5781*5c1def83SBjoern A. Zeeb
5782*5c1def83SBjoern A. Zeeb spin_lock_bh(&ar->data_lock);
5783*5c1def83SBjoern A. Zeeb /* TODO: In case of there is one more channel context left, populate
5784*5c1def83SBjoern A. Zeeb * rx_channel with the channel of that remaining channel context.
5785*5c1def83SBjoern A. Zeeb */
5786*5c1def83SBjoern A. Zeeb ar->rx_channel = NULL;
5787*5c1def83SBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
5788*5c1def83SBjoern A. Zeeb
5789*5c1def83SBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
5790*5c1def83SBjoern A. Zeeb }
5791*5c1def83SBjoern A. Zeeb
5792*5c1def83SBjoern A. Zeeb static int
ath12k_mac_vdev_start_restart(struct ath12k_vif * arvif,const struct cfg80211_chan_def * chandef,bool restart)5793*5c1def83SBjoern A. Zeeb ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif,
5794*5c1def83SBjoern A. Zeeb const struct cfg80211_chan_def *chandef,
5795*5c1def83SBjoern A. Zeeb bool restart)
5796*5c1def83SBjoern A. Zeeb {
5797*5c1def83SBjoern A. Zeeb struct ath12k *ar = arvif->ar;
5798*5c1def83SBjoern A. Zeeb struct ath12k_base *ab = ar->ab;
5799*5c1def83SBjoern A. Zeeb struct wmi_vdev_start_req_arg arg = {};
5800*5c1def83SBjoern A. Zeeb int he_support = arvif->vif->bss_conf.he_support;
5801*5c1def83SBjoern A. Zeeb int ret;
5802*5c1def83SBjoern A. Zeeb
5803*5c1def83SBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
5804*5c1def83SBjoern A. Zeeb
5805*5c1def83SBjoern A. Zeeb reinit_completion(&ar->vdev_setup_done);
5806*5c1def83SBjoern A. Zeeb
5807*5c1def83SBjoern A. Zeeb arg.vdev_id = arvif->vdev_id;
5808*5c1def83SBjoern A. Zeeb arg.dtim_period = arvif->dtim_period;
5809*5c1def83SBjoern A. Zeeb arg.bcn_intval = arvif->beacon_interval;
5810*5c1def83SBjoern A. Zeeb arg.punct_bitmap = ~arvif->punct_bitmap;
5811*5c1def83SBjoern A. Zeeb
5812*5c1def83SBjoern A. Zeeb arg.freq = chandef->chan->center_freq;
5813*5c1def83SBjoern A. Zeeb arg.band_center_freq1 = chandef->center_freq1;
5814*5c1def83SBjoern A. Zeeb arg.band_center_freq2 = chandef->center_freq2;
5815*5c1def83SBjoern A. Zeeb arg.mode = ath12k_phymodes[chandef->chan->band][chandef->width];
5816*5c1def83SBjoern A. Zeeb
5817*5c1def83SBjoern A. Zeeb arg.min_power = 0;
5818*5c1def83SBjoern A. Zeeb arg.max_power = chandef->chan->max_power * 2;
5819*5c1def83SBjoern A. Zeeb arg.max_reg_power = chandef->chan->max_reg_power * 2;
5820*5c1def83SBjoern A. Zeeb arg.max_antenna_gain = chandef->chan->max_antenna_gain * 2;
5821*5c1def83SBjoern A. Zeeb
5822*5c1def83SBjoern A. Zeeb arg.pref_tx_streams = ar->num_tx_chains;
5823*5c1def83SBjoern A. Zeeb arg.pref_rx_streams = ar->num_rx_chains;
5824*5c1def83SBjoern A. Zeeb
5825*5c1def83SBjoern A. Zeeb if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
5826*5c1def83SBjoern A. Zeeb arg.ssid = arvif->u.ap.ssid;
5827*5c1def83SBjoern A. Zeeb arg.ssid_len = arvif->u.ap.ssid_len;
5828*5c1def83SBjoern A. Zeeb arg.hidden_ssid = arvif->u.ap.hidden_ssid;
5829*5c1def83SBjoern A. Zeeb
5830*5c1def83SBjoern A. Zeeb /* For now allow DFS for AP mode */
5831*5c1def83SBjoern A. Zeeb arg.chan_radar = !!(chandef->chan->flags & IEEE80211_CHAN_RADAR);
5832*5c1def83SBjoern A. Zeeb
5833*5c1def83SBjoern A. Zeeb arg.passive = arg.chan_radar;
5834*5c1def83SBjoern A. Zeeb
5835*5c1def83SBjoern A. Zeeb spin_lock_bh(&ab->base_lock);
5836*5c1def83SBjoern A. Zeeb arg.regdomain = ar->ab->dfs_region;
5837*5c1def83SBjoern A. Zeeb spin_unlock_bh(&ab->base_lock);
5838*5c1def83SBjoern A. Zeeb
5839*5c1def83SBjoern A. Zeeb /* TODO: Notify if secondary 80Mhz also needs radar detection */
5840*5c1def83SBjoern A. Zeeb if (he_support) {
5841*5c1def83SBjoern A. Zeeb ret = ath12k_set_he_mu_sounding_mode(ar, arvif);
5842*5c1def83SBjoern A. Zeeb if (ret) {
5843*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to set he mode vdev %i\n",
5844*5c1def83SBjoern A. Zeeb arg.vdev_id);
5845*5c1def83SBjoern A. Zeeb return ret;
5846*5c1def83SBjoern A. Zeeb }
5847*5c1def83SBjoern A. Zeeb }
5848*5c1def83SBjoern A. Zeeb }
5849*5c1def83SBjoern A. Zeeb
5850*5c1def83SBjoern A. Zeeb arg.passive |= !!(chandef->chan->flags & IEEE80211_CHAN_NO_IR);
5851*5c1def83SBjoern A. Zeeb
5852*5c1def83SBjoern A. Zeeb ath12k_dbg(ab, ATH12K_DBG_MAC,
5853*5c1def83SBjoern A. Zeeb "mac vdev %d start center_freq %d phymode %s punct_bitmap 0x%x\n",
5854*5c1def83SBjoern A. Zeeb arg.vdev_id, arg.freq,
5855*5c1def83SBjoern A. Zeeb ath12k_mac_phymode_str(arg.mode), arg.punct_bitmap);
5856*5c1def83SBjoern A. Zeeb
5857*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_start(ar, &arg, restart);
5858*5c1def83SBjoern A. Zeeb if (ret) {
5859*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to %s WMI vdev %i\n",
5860*5c1def83SBjoern A. Zeeb restart ? "restart" : "start", arg.vdev_id);
5861*5c1def83SBjoern A. Zeeb return ret;
5862*5c1def83SBjoern A. Zeeb }
5863*5c1def83SBjoern A. Zeeb
5864*5c1def83SBjoern A. Zeeb ret = ath12k_mac_vdev_setup_sync(ar);
5865*5c1def83SBjoern A. Zeeb if (ret) {
5866*5c1def83SBjoern A. Zeeb ath12k_warn(ab, "failed to synchronize setup for vdev %i %s: %d\n",
5867*5c1def83SBjoern A. Zeeb arg.vdev_id, restart ? "restart" : "start", ret);
5868*5c1def83SBjoern A. Zeeb return ret;
5869*5c1def83SBjoern A. Zeeb }
5870*5c1def83SBjoern A. Zeeb
5871*5c1def83SBjoern A. Zeeb ar->num_started_vdevs++;
5872*5c1def83SBjoern A. Zeeb ath12k_dbg(ab, ATH12K_DBG_MAC, "vdev %pM started, vdev_id %d\n",
5873*5c1def83SBjoern A. Zeeb arvif->vif->addr, arvif->vdev_id);
5874*5c1def83SBjoern A. Zeeb
5875*5c1def83SBjoern A. Zeeb /* Enable CAC Flag in the driver by checking the channel DFS cac time,
5876*5c1def83SBjoern A. Zeeb * i.e dfs_cac_ms value which will be valid only for radar channels
5877*5c1def83SBjoern A. Zeeb * and state as NL80211_DFS_USABLE which indicates CAC needs to be
5878*5c1def83SBjoern A. Zeeb * done before channel usage. This flags is used to drop rx packets.
5879*5c1def83SBjoern A. Zeeb * during CAC.
5880*5c1def83SBjoern A. Zeeb */
5881*5c1def83SBjoern A. Zeeb /* TODO: Set the flag for other interface types as required */
5882*5c1def83SBjoern A. Zeeb if (arvif->vdev_type == WMI_VDEV_TYPE_AP &&
5883*5c1def83SBjoern A. Zeeb chandef->chan->dfs_cac_ms &&
5884*5c1def83SBjoern A. Zeeb chandef->chan->dfs_state == NL80211_DFS_USABLE) {
5885*5c1def83SBjoern A. Zeeb set_bit(ATH12K_CAC_RUNNING, &ar->dev_flags);
5886*5c1def83SBjoern A. Zeeb ath12k_dbg(ab, ATH12K_DBG_MAC,
5887*5c1def83SBjoern A. Zeeb "CAC Started in chan_freq %d for vdev %d\n",
5888*5c1def83SBjoern A. Zeeb arg.freq, arg.vdev_id);
5889*5c1def83SBjoern A. Zeeb }
5890*5c1def83SBjoern A. Zeeb
5891*5c1def83SBjoern A. Zeeb ret = ath12k_mac_set_txbf_conf(arvif);
5892*5c1def83SBjoern A. Zeeb if (ret)
5893*5c1def83SBjoern A. Zeeb ath12k_warn(ab, "failed to set txbf conf for vdev %d: %d\n",
5894*5c1def83SBjoern A. Zeeb arvif->vdev_id, ret);
5895*5c1def83SBjoern A. Zeeb
5896*5c1def83SBjoern A. Zeeb return 0;
5897*5c1def83SBjoern A. Zeeb }
5898*5c1def83SBjoern A. Zeeb
ath12k_mac_vdev_stop(struct ath12k_vif * arvif)5899*5c1def83SBjoern A. Zeeb static int ath12k_mac_vdev_stop(struct ath12k_vif *arvif)
5900*5c1def83SBjoern A. Zeeb {
5901*5c1def83SBjoern A. Zeeb struct ath12k *ar = arvif->ar;
5902*5c1def83SBjoern A. Zeeb int ret;
5903*5c1def83SBjoern A. Zeeb
5904*5c1def83SBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
5905*5c1def83SBjoern A. Zeeb
5906*5c1def83SBjoern A. Zeeb reinit_completion(&ar->vdev_setup_done);
5907*5c1def83SBjoern A. Zeeb
5908*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_stop(ar, arvif->vdev_id);
5909*5c1def83SBjoern A. Zeeb if (ret) {
5910*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to stop WMI vdev %i: %d\n",
5911*5c1def83SBjoern A. Zeeb arvif->vdev_id, ret);
5912*5c1def83SBjoern A. Zeeb goto err;
5913*5c1def83SBjoern A. Zeeb }
5914*5c1def83SBjoern A. Zeeb
5915*5c1def83SBjoern A. Zeeb ret = ath12k_mac_vdev_setup_sync(ar);
5916*5c1def83SBjoern A. Zeeb if (ret) {
5917*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to synchronize setup for vdev %i: %d\n",
5918*5c1def83SBjoern A. Zeeb arvif->vdev_id, ret);
5919*5c1def83SBjoern A. Zeeb goto err;
5920*5c1def83SBjoern A. Zeeb }
5921*5c1def83SBjoern A. Zeeb
5922*5c1def83SBjoern A. Zeeb WARN_ON(ar->num_started_vdevs == 0);
5923*5c1def83SBjoern A. Zeeb
5924*5c1def83SBjoern A. Zeeb ar->num_started_vdevs--;
5925*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "vdev %pM stopped, vdev_id %d\n",
5926*5c1def83SBjoern A. Zeeb arvif->vif->addr, arvif->vdev_id);
5927*5c1def83SBjoern A. Zeeb
5928*5c1def83SBjoern A. Zeeb if (test_bit(ATH12K_CAC_RUNNING, &ar->dev_flags)) {
5929*5c1def83SBjoern A. Zeeb clear_bit(ATH12K_CAC_RUNNING, &ar->dev_flags);
5930*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "CAC Stopped for vdev %d\n",
5931*5c1def83SBjoern A. Zeeb arvif->vdev_id);
5932*5c1def83SBjoern A. Zeeb }
5933*5c1def83SBjoern A. Zeeb
5934*5c1def83SBjoern A. Zeeb return 0;
5935*5c1def83SBjoern A. Zeeb err:
5936*5c1def83SBjoern A. Zeeb return ret;
5937*5c1def83SBjoern A. Zeeb }
5938*5c1def83SBjoern A. Zeeb
ath12k_mac_vdev_start(struct ath12k_vif * arvif,const struct cfg80211_chan_def * chandef)5939*5c1def83SBjoern A. Zeeb static int ath12k_mac_vdev_start(struct ath12k_vif *arvif,
5940*5c1def83SBjoern A. Zeeb const struct cfg80211_chan_def *chandef)
5941*5c1def83SBjoern A. Zeeb {
5942*5c1def83SBjoern A. Zeeb return ath12k_mac_vdev_start_restart(arvif, chandef, false);
5943*5c1def83SBjoern A. Zeeb }
5944*5c1def83SBjoern A. Zeeb
ath12k_mac_vdev_restart(struct ath12k_vif * arvif,const struct cfg80211_chan_def * chandef)5945*5c1def83SBjoern A. Zeeb static int ath12k_mac_vdev_restart(struct ath12k_vif *arvif,
5946*5c1def83SBjoern A. Zeeb const struct cfg80211_chan_def *chandef)
5947*5c1def83SBjoern A. Zeeb {
5948*5c1def83SBjoern A. Zeeb return ath12k_mac_vdev_start_restart(arvif, chandef, true);
5949*5c1def83SBjoern A. Zeeb }
5950*5c1def83SBjoern A. Zeeb
5951*5c1def83SBjoern A. Zeeb struct ath12k_mac_change_chanctx_arg {
5952*5c1def83SBjoern A. Zeeb struct ieee80211_chanctx_conf *ctx;
5953*5c1def83SBjoern A. Zeeb struct ieee80211_vif_chanctx_switch *vifs;
5954*5c1def83SBjoern A. Zeeb int n_vifs;
5955*5c1def83SBjoern A. Zeeb int next_vif;
5956*5c1def83SBjoern A. Zeeb };
5957*5c1def83SBjoern A. Zeeb
5958*5c1def83SBjoern A. Zeeb static void
ath12k_mac_change_chanctx_cnt_iter(void * data,u8 * mac,struct ieee80211_vif * vif)5959*5c1def83SBjoern A. Zeeb ath12k_mac_change_chanctx_cnt_iter(void *data, u8 *mac,
5960*5c1def83SBjoern A. Zeeb struct ieee80211_vif *vif)
5961*5c1def83SBjoern A. Zeeb {
5962*5c1def83SBjoern A. Zeeb struct ath12k_mac_change_chanctx_arg *arg = data;
5963*5c1def83SBjoern A. Zeeb
5964*5c1def83SBjoern A. Zeeb if (rcu_access_pointer(vif->bss_conf.chanctx_conf) != arg->ctx)
5965*5c1def83SBjoern A. Zeeb return;
5966*5c1def83SBjoern A. Zeeb
5967*5c1def83SBjoern A. Zeeb arg->n_vifs++;
5968*5c1def83SBjoern A. Zeeb }
5969*5c1def83SBjoern A. Zeeb
5970*5c1def83SBjoern A. Zeeb static void
ath12k_mac_change_chanctx_fill_iter(void * data,u8 * mac,struct ieee80211_vif * vif)5971*5c1def83SBjoern A. Zeeb ath12k_mac_change_chanctx_fill_iter(void *data, u8 *mac,
5972*5c1def83SBjoern A. Zeeb struct ieee80211_vif *vif)
5973*5c1def83SBjoern A. Zeeb {
5974*5c1def83SBjoern A. Zeeb struct ath12k_mac_change_chanctx_arg *arg = data;
5975*5c1def83SBjoern A. Zeeb struct ieee80211_chanctx_conf *ctx;
5976*5c1def83SBjoern A. Zeeb
5977*5c1def83SBjoern A. Zeeb ctx = rcu_access_pointer(vif->bss_conf.chanctx_conf);
5978*5c1def83SBjoern A. Zeeb if (ctx != arg->ctx)
5979*5c1def83SBjoern A. Zeeb return;
5980*5c1def83SBjoern A. Zeeb
5981*5c1def83SBjoern A. Zeeb if (WARN_ON(arg->next_vif == arg->n_vifs))
5982*5c1def83SBjoern A. Zeeb return;
5983*5c1def83SBjoern A. Zeeb
5984*5c1def83SBjoern A. Zeeb arg->vifs[arg->next_vif].vif = vif;
5985*5c1def83SBjoern A. Zeeb arg->vifs[arg->next_vif].old_ctx = ctx;
5986*5c1def83SBjoern A. Zeeb arg->vifs[arg->next_vif].new_ctx = ctx;
5987*5c1def83SBjoern A. Zeeb arg->next_vif++;
5988*5c1def83SBjoern A. Zeeb }
5989*5c1def83SBjoern A. Zeeb
5990*5c1def83SBjoern A. Zeeb static void
ath12k_mac_update_vif_chan(struct ath12k * ar,struct ieee80211_vif_chanctx_switch * vifs,int n_vifs)5991*5c1def83SBjoern A. Zeeb ath12k_mac_update_vif_chan(struct ath12k *ar,
5992*5c1def83SBjoern A. Zeeb struct ieee80211_vif_chanctx_switch *vifs,
5993*5c1def83SBjoern A. Zeeb int n_vifs)
5994*5c1def83SBjoern A. Zeeb {
5995*5c1def83SBjoern A. Zeeb struct ath12k_base *ab = ar->ab;
5996*5c1def83SBjoern A. Zeeb struct ath12k_vif *arvif;
5997*5c1def83SBjoern A. Zeeb int ret;
5998*5c1def83SBjoern A. Zeeb int i;
5999*5c1def83SBjoern A. Zeeb bool monitor_vif = false;
6000*5c1def83SBjoern A. Zeeb
6001*5c1def83SBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
6002*5c1def83SBjoern A. Zeeb
6003*5c1def83SBjoern A. Zeeb for (i = 0; i < n_vifs; i++) {
6004*5c1def83SBjoern A. Zeeb arvif = (void *)vifs[i].vif->drv_priv;
6005*5c1def83SBjoern A. Zeeb
6006*5c1def83SBjoern A. Zeeb if (vifs[i].vif->type == NL80211_IFTYPE_MONITOR)
6007*5c1def83SBjoern A. Zeeb monitor_vif = true;
6008*5c1def83SBjoern A. Zeeb
6009*5c1def83SBjoern A. Zeeb ath12k_dbg(ab, ATH12K_DBG_MAC,
6010*5c1def83SBjoern A. Zeeb "mac chanctx switch vdev_id %i freq %u->%u width %d->%d\n",
6011*5c1def83SBjoern A. Zeeb arvif->vdev_id,
6012*5c1def83SBjoern A. Zeeb vifs[i].old_ctx->def.chan->center_freq,
6013*5c1def83SBjoern A. Zeeb vifs[i].new_ctx->def.chan->center_freq,
6014*5c1def83SBjoern A. Zeeb vifs[i].old_ctx->def.width,
6015*5c1def83SBjoern A. Zeeb vifs[i].new_ctx->def.width);
6016*5c1def83SBjoern A. Zeeb
6017*5c1def83SBjoern A. Zeeb if (WARN_ON(!arvif->is_started))
6018*5c1def83SBjoern A. Zeeb continue;
6019*5c1def83SBjoern A. Zeeb
6020*5c1def83SBjoern A. Zeeb if (WARN_ON(!arvif->is_up))
6021*5c1def83SBjoern A. Zeeb continue;
6022*5c1def83SBjoern A. Zeeb
6023*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_down(ar, arvif->vdev_id);
6024*5c1def83SBjoern A. Zeeb if (ret) {
6025*5c1def83SBjoern A. Zeeb ath12k_warn(ab, "failed to down vdev %d: %d\n",
6026*5c1def83SBjoern A. Zeeb arvif->vdev_id, ret);
6027*5c1def83SBjoern A. Zeeb continue;
6028*5c1def83SBjoern A. Zeeb }
6029*5c1def83SBjoern A. Zeeb }
6030*5c1def83SBjoern A. Zeeb
6031*5c1def83SBjoern A. Zeeb /* All relevant vdevs are downed and associated channel resources
6032*5c1def83SBjoern A. Zeeb * should be available for the channel switch now.
6033*5c1def83SBjoern A. Zeeb */
6034*5c1def83SBjoern A. Zeeb
6035*5c1def83SBjoern A. Zeeb /* TODO: Update ar->rx_channel */
6036*5c1def83SBjoern A. Zeeb
6037*5c1def83SBjoern A. Zeeb for (i = 0; i < n_vifs; i++) {
6038*5c1def83SBjoern A. Zeeb arvif = (void *)vifs[i].vif->drv_priv;
6039*5c1def83SBjoern A. Zeeb
6040*5c1def83SBjoern A. Zeeb if (WARN_ON(!arvif->is_started))
6041*5c1def83SBjoern A. Zeeb continue;
6042*5c1def83SBjoern A. Zeeb
6043*5c1def83SBjoern A. Zeeb if (WARN_ON(!arvif->is_up))
6044*5c1def83SBjoern A. Zeeb continue;
6045*5c1def83SBjoern A. Zeeb
6046*5c1def83SBjoern A. Zeeb ret = ath12k_mac_vdev_restart(arvif, &vifs[i].new_ctx->def);
6047*5c1def83SBjoern A. Zeeb if (ret) {
6048*5c1def83SBjoern A. Zeeb ath12k_warn(ab, "failed to restart vdev %d: %d\n",
6049*5c1def83SBjoern A. Zeeb arvif->vdev_id, ret);
6050*5c1def83SBjoern A. Zeeb continue;
6051*5c1def83SBjoern A. Zeeb }
6052*5c1def83SBjoern A. Zeeb
6053*5c1def83SBjoern A. Zeeb ret = ath12k_mac_setup_bcn_tmpl(arvif);
6054*5c1def83SBjoern A. Zeeb if (ret)
6055*5c1def83SBjoern A. Zeeb ath12k_warn(ab, "failed to update bcn tmpl during csa: %d\n",
6056*5c1def83SBjoern A. Zeeb ret);
6057*5c1def83SBjoern A. Zeeb
6058*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid,
6059*5c1def83SBjoern A. Zeeb arvif->bssid);
6060*5c1def83SBjoern A. Zeeb if (ret) {
6061*5c1def83SBjoern A. Zeeb ath12k_warn(ab, "failed to bring vdev up %d: %d\n",
6062*5c1def83SBjoern A. Zeeb arvif->vdev_id, ret);
6063*5c1def83SBjoern A. Zeeb continue;
6064*5c1def83SBjoern A. Zeeb }
6065*5c1def83SBjoern A. Zeeb }
6066*5c1def83SBjoern A. Zeeb
6067*5c1def83SBjoern A. Zeeb /* Restart the internal monitor vdev on new channel */
6068*5c1def83SBjoern A. Zeeb if (!monitor_vif && ar->monitor_vdev_created) {
6069*5c1def83SBjoern A. Zeeb if (!ath12k_mac_monitor_stop(ar))
6070*5c1def83SBjoern A. Zeeb ath12k_mac_monitor_start(ar);
6071*5c1def83SBjoern A. Zeeb }
6072*5c1def83SBjoern A. Zeeb }
6073*5c1def83SBjoern A. Zeeb
6074*5c1def83SBjoern A. Zeeb static void
ath12k_mac_update_active_vif_chan(struct ath12k * ar,struct ieee80211_chanctx_conf * ctx)6075*5c1def83SBjoern A. Zeeb ath12k_mac_update_active_vif_chan(struct ath12k *ar,
6076*5c1def83SBjoern A. Zeeb struct ieee80211_chanctx_conf *ctx)
6077*5c1def83SBjoern A. Zeeb {
6078*5c1def83SBjoern A. Zeeb struct ath12k_mac_change_chanctx_arg arg = { .ctx = ctx };
6079*5c1def83SBjoern A. Zeeb
6080*5c1def83SBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
6081*5c1def83SBjoern A. Zeeb
6082*5c1def83SBjoern A. Zeeb ieee80211_iterate_active_interfaces_atomic(ar->hw,
6083*5c1def83SBjoern A. Zeeb IEEE80211_IFACE_ITER_NORMAL,
6084*5c1def83SBjoern A. Zeeb ath12k_mac_change_chanctx_cnt_iter,
6085*5c1def83SBjoern A. Zeeb &arg);
6086*5c1def83SBjoern A. Zeeb if (arg.n_vifs == 0)
6087*5c1def83SBjoern A. Zeeb return;
6088*5c1def83SBjoern A. Zeeb
6089*5c1def83SBjoern A. Zeeb arg.vifs = kcalloc(arg.n_vifs, sizeof(arg.vifs[0]), GFP_KERNEL);
6090*5c1def83SBjoern A. Zeeb if (!arg.vifs)
6091*5c1def83SBjoern A. Zeeb return;
6092*5c1def83SBjoern A. Zeeb
6093*5c1def83SBjoern A. Zeeb ieee80211_iterate_active_interfaces_atomic(ar->hw,
6094*5c1def83SBjoern A. Zeeb IEEE80211_IFACE_ITER_NORMAL,
6095*5c1def83SBjoern A. Zeeb ath12k_mac_change_chanctx_fill_iter,
6096*5c1def83SBjoern A. Zeeb &arg);
6097*5c1def83SBjoern A. Zeeb
6098*5c1def83SBjoern A. Zeeb ath12k_mac_update_vif_chan(ar, arg.vifs, arg.n_vifs);
6099*5c1def83SBjoern A. Zeeb
6100*5c1def83SBjoern A. Zeeb kfree(arg.vifs);
6101*5c1def83SBjoern A. Zeeb }
6102*5c1def83SBjoern A. Zeeb
ath12k_mac_op_change_chanctx(struct ieee80211_hw * hw,struct ieee80211_chanctx_conf * ctx,u32 changed)6103*5c1def83SBjoern A. Zeeb static void ath12k_mac_op_change_chanctx(struct ieee80211_hw *hw,
6104*5c1def83SBjoern A. Zeeb struct ieee80211_chanctx_conf *ctx,
6105*5c1def83SBjoern A. Zeeb u32 changed)
6106*5c1def83SBjoern A. Zeeb {
6107*5c1def83SBjoern A. Zeeb struct ath12k *ar = hw->priv;
6108*5c1def83SBjoern A. Zeeb struct ath12k_base *ab = ar->ab;
6109*5c1def83SBjoern A. Zeeb
6110*5c1def83SBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
6111*5c1def83SBjoern A. Zeeb
6112*5c1def83SBjoern A. Zeeb ath12k_dbg(ab, ATH12K_DBG_MAC,
6113*5c1def83SBjoern A. Zeeb "mac chanctx change freq %u width %d ptr %pK changed %x\n",
6114*5c1def83SBjoern A. Zeeb ctx->def.chan->center_freq, ctx->def.width, ctx, changed);
6115*5c1def83SBjoern A. Zeeb
6116*5c1def83SBjoern A. Zeeb /* This shouldn't really happen because channel switching should use
6117*5c1def83SBjoern A. Zeeb * switch_vif_chanctx().
6118*5c1def83SBjoern A. Zeeb */
6119*5c1def83SBjoern A. Zeeb if (WARN_ON(changed & IEEE80211_CHANCTX_CHANGE_CHANNEL))
6120*5c1def83SBjoern A. Zeeb goto unlock;
6121*5c1def83SBjoern A. Zeeb
6122*5c1def83SBjoern A. Zeeb if (changed & IEEE80211_CHANCTX_CHANGE_WIDTH)
6123*5c1def83SBjoern A. Zeeb ath12k_mac_update_active_vif_chan(ar, ctx);
6124*5c1def83SBjoern A. Zeeb
6125*5c1def83SBjoern A. Zeeb /* TODO: Recalc radar detection */
6126*5c1def83SBjoern A. Zeeb
6127*5c1def83SBjoern A. Zeeb unlock:
6128*5c1def83SBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
6129*5c1def83SBjoern A. Zeeb }
6130*5c1def83SBjoern A. Zeeb
ath12k_start_vdev_delay(struct ieee80211_hw * hw,struct ieee80211_vif * vif)6131*5c1def83SBjoern A. Zeeb static int ath12k_start_vdev_delay(struct ieee80211_hw *hw,
6132*5c1def83SBjoern A. Zeeb struct ieee80211_vif *vif)
6133*5c1def83SBjoern A. Zeeb {
6134*5c1def83SBjoern A. Zeeb struct ath12k *ar = hw->priv;
6135*5c1def83SBjoern A. Zeeb struct ath12k_base *ab = ar->ab;
6136*5c1def83SBjoern A. Zeeb struct ath12k_vif *arvif = (void *)vif->drv_priv;
6137*5c1def83SBjoern A. Zeeb int ret;
6138*5c1def83SBjoern A. Zeeb
6139*5c1def83SBjoern A. Zeeb if (WARN_ON(arvif->is_started))
6140*5c1def83SBjoern A. Zeeb return -EBUSY;
6141*5c1def83SBjoern A. Zeeb
6142*5c1def83SBjoern A. Zeeb ret = ath12k_mac_vdev_start(arvif, &arvif->chanctx.def);
6143*5c1def83SBjoern A. Zeeb if (ret) {
6144*5c1def83SBjoern A. Zeeb ath12k_warn(ab, "failed to start vdev %i addr %pM on freq %d: %d\n",
6145*5c1def83SBjoern A. Zeeb arvif->vdev_id, vif->addr,
6146*5c1def83SBjoern A. Zeeb arvif->chanctx.def.chan->center_freq, ret);
6147*5c1def83SBjoern A. Zeeb return ret;
6148*5c1def83SBjoern A. Zeeb }
6149*5c1def83SBjoern A. Zeeb
6150*5c1def83SBjoern A. Zeeb if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
6151*5c1def83SBjoern A. Zeeb ret = ath12k_monitor_vdev_up(ar, arvif->vdev_id);
6152*5c1def83SBjoern A. Zeeb if (ret) {
6153*5c1def83SBjoern A. Zeeb ath12k_warn(ab, "failed put monitor up: %d\n", ret);
6154*5c1def83SBjoern A. Zeeb return ret;
6155*5c1def83SBjoern A. Zeeb }
6156*5c1def83SBjoern A. Zeeb }
6157*5c1def83SBjoern A. Zeeb
6158*5c1def83SBjoern A. Zeeb arvif->is_started = true;
6159*5c1def83SBjoern A. Zeeb
6160*5c1def83SBjoern A. Zeeb /* TODO: Setup ps and cts/rts protection */
6161*5c1def83SBjoern A. Zeeb return 0;
6162*5c1def83SBjoern A. Zeeb }
6163*5c1def83SBjoern A. Zeeb
6164*5c1def83SBjoern A. Zeeb 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)6165*5c1def83SBjoern A. Zeeb ath12k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
6166*5c1def83SBjoern A. Zeeb struct ieee80211_vif *vif,
6167*5c1def83SBjoern A. Zeeb struct ieee80211_bss_conf *link_conf,
6168*5c1def83SBjoern A. Zeeb struct ieee80211_chanctx_conf *ctx)
6169*5c1def83SBjoern A. Zeeb {
6170*5c1def83SBjoern A. Zeeb struct ath12k *ar = hw->priv;
6171*5c1def83SBjoern A. Zeeb struct ath12k_base *ab = ar->ab;
6172*5c1def83SBjoern A. Zeeb struct ath12k_vif *arvif = (void *)vif->drv_priv;
6173*5c1def83SBjoern A. Zeeb int ret;
6174*5c1def83SBjoern A. Zeeb struct ath12k_wmi_peer_create_arg param;
6175*5c1def83SBjoern A. Zeeb
6176*5c1def83SBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
6177*5c1def83SBjoern A. Zeeb
6178*5c1def83SBjoern A. Zeeb ath12k_dbg(ab, ATH12K_DBG_MAC,
6179*5c1def83SBjoern A. Zeeb "mac chanctx assign ptr %pK vdev_id %i\n",
6180*5c1def83SBjoern A. Zeeb ctx, arvif->vdev_id);
6181*5c1def83SBjoern A. Zeeb
6182*5c1def83SBjoern A. Zeeb arvif->punct_bitmap = link_conf->eht_puncturing;
6183*5c1def83SBjoern A. Zeeb
6184*5c1def83SBjoern A. Zeeb /* for some targets bss peer must be created before vdev_start */
6185*5c1def83SBjoern A. Zeeb if (ab->hw_params->vdev_start_delay &&
6186*5c1def83SBjoern A. Zeeb arvif->vdev_type != WMI_VDEV_TYPE_AP &&
6187*5c1def83SBjoern A. Zeeb arvif->vdev_type != WMI_VDEV_TYPE_MONITOR &&
6188*5c1def83SBjoern A. Zeeb !ath12k_peer_exist_by_vdev_id(ab, arvif->vdev_id)) {
6189*5c1def83SBjoern A. Zeeb memcpy(&arvif->chanctx, ctx, sizeof(*ctx));
6190*5c1def83SBjoern A. Zeeb ret = 0;
6191*5c1def83SBjoern A. Zeeb goto out;
6192*5c1def83SBjoern A. Zeeb }
6193*5c1def83SBjoern A. Zeeb
6194*5c1def83SBjoern A. Zeeb if (WARN_ON(arvif->is_started)) {
6195*5c1def83SBjoern A. Zeeb ret = -EBUSY;
6196*5c1def83SBjoern A. Zeeb goto out;
6197*5c1def83SBjoern A. Zeeb }
6198*5c1def83SBjoern A. Zeeb
6199*5c1def83SBjoern A. Zeeb if (ab->hw_params->vdev_start_delay &&
6200*5c1def83SBjoern A. Zeeb (arvif->vdev_type == WMI_VDEV_TYPE_AP ||
6201*5c1def83SBjoern A. Zeeb arvif->vdev_type == WMI_VDEV_TYPE_MONITOR)) {
6202*5c1def83SBjoern A. Zeeb param.vdev_id = arvif->vdev_id;
6203*5c1def83SBjoern A. Zeeb param.peer_type = WMI_PEER_TYPE_DEFAULT;
6204*5c1def83SBjoern A. Zeeb param.peer_addr = ar->mac_addr;
6205*5c1def83SBjoern A. Zeeb
6206*5c1def83SBjoern A. Zeeb ret = ath12k_peer_create(ar, arvif, NULL, ¶m);
6207*5c1def83SBjoern A. Zeeb if (ret) {
6208*5c1def83SBjoern A. Zeeb ath12k_warn(ab, "failed to create peer after vdev start delay: %d",
6209*5c1def83SBjoern A. Zeeb ret);
6210*5c1def83SBjoern A. Zeeb goto out;
6211*5c1def83SBjoern A. Zeeb }
6212*5c1def83SBjoern A. Zeeb }
6213*5c1def83SBjoern A. Zeeb
6214*5c1def83SBjoern A. Zeeb if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
6215*5c1def83SBjoern A. Zeeb ret = ath12k_mac_monitor_start(ar);
6216*5c1def83SBjoern A. Zeeb if (ret)
6217*5c1def83SBjoern A. Zeeb goto out;
6218*5c1def83SBjoern A. Zeeb arvif->is_started = true;
6219*5c1def83SBjoern A. Zeeb goto out;
6220*5c1def83SBjoern A. Zeeb }
6221*5c1def83SBjoern A. Zeeb
6222*5c1def83SBjoern A. Zeeb ret = ath12k_mac_vdev_start(arvif, &ctx->def);
6223*5c1def83SBjoern A. Zeeb if (ret) {
6224*5c1def83SBjoern A. Zeeb ath12k_warn(ab, "failed to start vdev %i addr %pM on freq %d: %d\n",
6225*5c1def83SBjoern A. Zeeb arvif->vdev_id, vif->addr,
6226*5c1def83SBjoern A. Zeeb ctx->def.chan->center_freq, ret);
6227*5c1def83SBjoern A. Zeeb goto out;
6228*5c1def83SBjoern A. Zeeb }
6229*5c1def83SBjoern A. Zeeb
6230*5c1def83SBjoern A. Zeeb if (arvif->vdev_type != WMI_VDEV_TYPE_MONITOR && ar->monitor_vdev_created)
6231*5c1def83SBjoern A. Zeeb ath12k_mac_monitor_start(ar);
6232*5c1def83SBjoern A. Zeeb
6233*5c1def83SBjoern A. Zeeb arvif->is_started = true;
6234*5c1def83SBjoern A. Zeeb
6235*5c1def83SBjoern A. Zeeb /* TODO: Setup ps and cts/rts protection */
6236*5c1def83SBjoern A. Zeeb
6237*5c1def83SBjoern A. Zeeb out:
6238*5c1def83SBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
6239*5c1def83SBjoern A. Zeeb
6240*5c1def83SBjoern A. Zeeb return ret;
6241*5c1def83SBjoern A. Zeeb }
6242*5c1def83SBjoern A. Zeeb
6243*5c1def83SBjoern A. Zeeb 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)6244*5c1def83SBjoern A. Zeeb ath12k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw,
6245*5c1def83SBjoern A. Zeeb struct ieee80211_vif *vif,
6246*5c1def83SBjoern A. Zeeb struct ieee80211_bss_conf *link_conf,
6247*5c1def83SBjoern A. Zeeb struct ieee80211_chanctx_conf *ctx)
6248*5c1def83SBjoern A. Zeeb {
6249*5c1def83SBjoern A. Zeeb struct ath12k *ar = hw->priv;
6250*5c1def83SBjoern A. Zeeb struct ath12k_base *ab = ar->ab;
6251*5c1def83SBjoern A. Zeeb struct ath12k_vif *arvif = (void *)vif->drv_priv;
6252*5c1def83SBjoern A. Zeeb int ret;
6253*5c1def83SBjoern A. Zeeb
6254*5c1def83SBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
6255*5c1def83SBjoern A. Zeeb
6256*5c1def83SBjoern A. Zeeb ath12k_dbg(ab, ATH12K_DBG_MAC,
6257*5c1def83SBjoern A. Zeeb "mac chanctx unassign ptr %pK vdev_id %i\n",
6258*5c1def83SBjoern A. Zeeb ctx, arvif->vdev_id);
6259*5c1def83SBjoern A. Zeeb
6260*5c1def83SBjoern A. Zeeb WARN_ON(!arvif->is_started);
6261*5c1def83SBjoern A. Zeeb
6262*5c1def83SBjoern A. Zeeb if (ab->hw_params->vdev_start_delay &&
6263*5c1def83SBjoern A. Zeeb arvif->vdev_type == WMI_VDEV_TYPE_MONITOR &&
6264*5c1def83SBjoern A. Zeeb ath12k_peer_find_by_addr(ab, ar->mac_addr))
6265*5c1def83SBjoern A. Zeeb ath12k_peer_delete(ar, arvif->vdev_id, ar->mac_addr);
6266*5c1def83SBjoern A. Zeeb
6267*5c1def83SBjoern A. Zeeb if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
6268*5c1def83SBjoern A. Zeeb ret = ath12k_mac_monitor_stop(ar);
6269*5c1def83SBjoern A. Zeeb if (ret) {
6270*5c1def83SBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
6271*5c1def83SBjoern A. Zeeb return;
6272*5c1def83SBjoern A. Zeeb }
6273*5c1def83SBjoern A. Zeeb
6274*5c1def83SBjoern A. Zeeb arvif->is_started = false;
6275*5c1def83SBjoern A. Zeeb }
6276*5c1def83SBjoern A. Zeeb
6277*5c1def83SBjoern A. Zeeb ret = ath12k_mac_vdev_stop(arvif);
6278*5c1def83SBjoern A. Zeeb if (ret)
6279*5c1def83SBjoern A. Zeeb ath12k_warn(ab, "failed to stop vdev %i: %d\n",
6280*5c1def83SBjoern A. Zeeb arvif->vdev_id, ret);
6281*5c1def83SBjoern A. Zeeb
6282*5c1def83SBjoern A. Zeeb arvif->is_started = false;
6283*5c1def83SBjoern A. Zeeb
6284*5c1def83SBjoern A. Zeeb if (ab->hw_params->vdev_start_delay &&
6285*5c1def83SBjoern A. Zeeb arvif->vdev_type == WMI_VDEV_TYPE_MONITOR)
6286*5c1def83SBjoern A. Zeeb ath12k_wmi_vdev_down(ar, arvif->vdev_id);
6287*5c1def83SBjoern A. Zeeb
6288*5c1def83SBjoern A. Zeeb if (arvif->vdev_type != WMI_VDEV_TYPE_MONITOR &&
6289*5c1def83SBjoern A. Zeeb ar->num_started_vdevs == 1 && ar->monitor_vdev_created)
6290*5c1def83SBjoern A. Zeeb ath12k_mac_monitor_stop(ar);
6291*5c1def83SBjoern A. Zeeb
6292*5c1def83SBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
6293*5c1def83SBjoern A. Zeeb }
6294*5c1def83SBjoern A. Zeeb
6295*5c1def83SBjoern A. Zeeb 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)6296*5c1def83SBjoern A. Zeeb ath12k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw,
6297*5c1def83SBjoern A. Zeeb struct ieee80211_vif_chanctx_switch *vifs,
6298*5c1def83SBjoern A. Zeeb int n_vifs,
6299*5c1def83SBjoern A. Zeeb enum ieee80211_chanctx_switch_mode mode)
6300*5c1def83SBjoern A. Zeeb {
6301*5c1def83SBjoern A. Zeeb struct ath12k *ar = hw->priv;
6302*5c1def83SBjoern A. Zeeb
6303*5c1def83SBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
6304*5c1def83SBjoern A. Zeeb
6305*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
6306*5c1def83SBjoern A. Zeeb "mac chanctx switch n_vifs %d mode %d\n",
6307*5c1def83SBjoern A. Zeeb n_vifs, mode);
6308*5c1def83SBjoern A. Zeeb ath12k_mac_update_vif_chan(ar, vifs, n_vifs);
6309*5c1def83SBjoern A. Zeeb
6310*5c1def83SBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
6311*5c1def83SBjoern A. Zeeb
6312*5c1def83SBjoern A. Zeeb return 0;
6313*5c1def83SBjoern A. Zeeb }
6314*5c1def83SBjoern A. Zeeb
6315*5c1def83SBjoern A. Zeeb static int
ath12k_set_vdev_param_to_all_vifs(struct ath12k * ar,int param,u32 value)6316*5c1def83SBjoern A. Zeeb ath12k_set_vdev_param_to_all_vifs(struct ath12k *ar, int param, u32 value)
6317*5c1def83SBjoern A. Zeeb {
6318*5c1def83SBjoern A. Zeeb struct ath12k_vif *arvif;
6319*5c1def83SBjoern A. Zeeb int ret = 0;
6320*5c1def83SBjoern A. Zeeb
6321*5c1def83SBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
6322*5c1def83SBjoern A. Zeeb list_for_each_entry(arvif, &ar->arvifs, list) {
6323*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "setting mac vdev %d param %d value %d\n",
6324*5c1def83SBjoern A. Zeeb param, arvif->vdev_id, value);
6325*5c1def83SBjoern A. Zeeb
6326*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
6327*5c1def83SBjoern A. Zeeb param, value);
6328*5c1def83SBjoern A. Zeeb if (ret) {
6329*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to set param %d for vdev %d: %d\n",
6330*5c1def83SBjoern A. Zeeb param, arvif->vdev_id, ret);
6331*5c1def83SBjoern A. Zeeb break;
6332*5c1def83SBjoern A. Zeeb }
6333*5c1def83SBjoern A. Zeeb }
6334*5c1def83SBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
6335*5c1def83SBjoern A. Zeeb return ret;
6336*5c1def83SBjoern A. Zeeb }
6337*5c1def83SBjoern A. Zeeb
6338*5c1def83SBjoern A. Zeeb /* mac80211 stores device specific RTS/Fragmentation threshold value,
6339*5c1def83SBjoern A. Zeeb * this is set interface specific to firmware from ath12k driver
6340*5c1def83SBjoern A. Zeeb */
ath12k_mac_op_set_rts_threshold(struct ieee80211_hw * hw,u32 value)6341*5c1def83SBjoern A. Zeeb static int ath12k_mac_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
6342*5c1def83SBjoern A. Zeeb {
6343*5c1def83SBjoern A. Zeeb struct ath12k *ar = hw->priv;
6344*5c1def83SBjoern A. Zeeb int param_id = WMI_VDEV_PARAM_RTS_THRESHOLD;
6345*5c1def83SBjoern A. Zeeb
6346*5c1def83SBjoern A. Zeeb return ath12k_set_vdev_param_to_all_vifs(ar, param_id, value);
6347*5c1def83SBjoern A. Zeeb }
6348*5c1def83SBjoern A. Zeeb
ath12k_mac_op_set_frag_threshold(struct ieee80211_hw * hw,u32 value)6349*5c1def83SBjoern A. Zeeb static int ath12k_mac_op_set_frag_threshold(struct ieee80211_hw *hw, u32 value)
6350*5c1def83SBjoern A. Zeeb {
6351*5c1def83SBjoern A. Zeeb /* Even though there's a WMI vdev param for fragmentation threshold no
6352*5c1def83SBjoern A. Zeeb * known firmware actually implements it. Moreover it is not possible to
6353*5c1def83SBjoern A. Zeeb * rely frame fragmentation to mac80211 because firmware clears the
6354*5c1def83SBjoern A. Zeeb * "more fragments" bit in frame control making it impossible for remote
6355*5c1def83SBjoern A. Zeeb * devices to reassemble frames.
6356*5c1def83SBjoern A. Zeeb *
6357*5c1def83SBjoern A. Zeeb * Hence implement a dummy callback just to say fragmentation isn't
6358*5c1def83SBjoern A. Zeeb * supported. This effectively prevents mac80211 from doing frame
6359*5c1def83SBjoern A. Zeeb * fragmentation in software.
6360*5c1def83SBjoern A. Zeeb */
6361*5c1def83SBjoern A. Zeeb return -EOPNOTSUPP;
6362*5c1def83SBjoern A. Zeeb }
6363*5c1def83SBjoern A. Zeeb
ath12k_mac_op_flush(struct ieee80211_hw * hw,struct ieee80211_vif * vif,u32 queues,bool drop)6364*5c1def83SBjoern A. Zeeb static void ath12k_mac_op_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
6365*5c1def83SBjoern A. Zeeb u32 queues, bool drop)
6366*5c1def83SBjoern A. Zeeb {
6367*5c1def83SBjoern A. Zeeb struct ath12k *ar = hw->priv;
6368*5c1def83SBjoern A. Zeeb long time_left;
6369*5c1def83SBjoern A. Zeeb
6370*5c1def83SBjoern A. Zeeb if (drop)
6371*5c1def83SBjoern A. Zeeb return;
6372*5c1def83SBjoern A. Zeeb
6373*5c1def83SBjoern A. Zeeb time_left = wait_event_timeout(ar->dp.tx_empty_waitq,
6374*5c1def83SBjoern A. Zeeb (atomic_read(&ar->dp.num_tx_pending) == 0),
6375*5c1def83SBjoern A. Zeeb ATH12K_FLUSH_TIMEOUT);
6376*5c1def83SBjoern A. Zeeb if (time_left == 0)
6377*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to flush transmit queue %ld\n", time_left);
6378*5c1def83SBjoern A. Zeeb
6379*5c1def83SBjoern A. Zeeb time_left = wait_event_timeout(ar->txmgmt_empty_waitq,
6380*5c1def83SBjoern A. Zeeb (atomic_read(&ar->num_pending_mgmt_tx) == 0),
6381*5c1def83SBjoern A. Zeeb ATH12K_FLUSH_TIMEOUT);
6382*5c1def83SBjoern A. Zeeb if (time_left == 0)
6383*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to flush mgmt transmit queue %ld\n",
6384*5c1def83SBjoern A. Zeeb time_left);
6385*5c1def83SBjoern A. Zeeb }
6386*5c1def83SBjoern A. Zeeb
6387*5c1def83SBjoern A. Zeeb static int
ath12k_mac_bitrate_mask_num_ht_rates(struct ath12k * ar,enum nl80211_band band,const struct cfg80211_bitrate_mask * mask)6388*5c1def83SBjoern A. Zeeb ath12k_mac_bitrate_mask_num_ht_rates(struct ath12k *ar,
6389*5c1def83SBjoern A. Zeeb enum nl80211_band band,
6390*5c1def83SBjoern A. Zeeb const struct cfg80211_bitrate_mask *mask)
6391*5c1def83SBjoern A. Zeeb {
6392*5c1def83SBjoern A. Zeeb int num_rates = 0;
6393*5c1def83SBjoern A. Zeeb int i;
6394*5c1def83SBjoern A. Zeeb
6395*5c1def83SBjoern A. Zeeb for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++)
6396*5c1def83SBjoern A. Zeeb num_rates += hweight16(mask->control[band].ht_mcs[i]);
6397*5c1def83SBjoern A. Zeeb
6398*5c1def83SBjoern A. Zeeb return num_rates;
6399*5c1def83SBjoern A. Zeeb }
6400*5c1def83SBjoern A. Zeeb
6401*5c1def83SBjoern A. Zeeb static bool
ath12k_mac_has_single_legacy_rate(struct ath12k * ar,enum nl80211_band band,const struct cfg80211_bitrate_mask * mask)6402*5c1def83SBjoern A. Zeeb ath12k_mac_has_single_legacy_rate(struct ath12k *ar,
6403*5c1def83SBjoern A. Zeeb enum nl80211_band band,
6404*5c1def83SBjoern A. Zeeb const struct cfg80211_bitrate_mask *mask)
6405*5c1def83SBjoern A. Zeeb {
6406*5c1def83SBjoern A. Zeeb int num_rates = 0;
6407*5c1def83SBjoern A. Zeeb
6408*5c1def83SBjoern A. Zeeb num_rates = hweight32(mask->control[band].legacy);
6409*5c1def83SBjoern A. Zeeb
6410*5c1def83SBjoern A. Zeeb if (ath12k_mac_bitrate_mask_num_ht_rates(ar, band, mask))
6411*5c1def83SBjoern A. Zeeb return false;
6412*5c1def83SBjoern A. Zeeb
6413*5c1def83SBjoern A. Zeeb if (ath12k_mac_bitrate_mask_num_vht_rates(ar, band, mask))
6414*5c1def83SBjoern A. Zeeb return false;
6415*5c1def83SBjoern A. Zeeb
6416*5c1def83SBjoern A. Zeeb return num_rates == 1;
6417*5c1def83SBjoern A. Zeeb }
6418*5c1def83SBjoern A. Zeeb
6419*5c1def83SBjoern A. Zeeb static bool
ath12k_mac_bitrate_mask_get_single_nss(struct ath12k * ar,enum nl80211_band band,const struct cfg80211_bitrate_mask * mask,int * nss)6420*5c1def83SBjoern A. Zeeb ath12k_mac_bitrate_mask_get_single_nss(struct ath12k *ar,
6421*5c1def83SBjoern A. Zeeb enum nl80211_band band,
6422*5c1def83SBjoern A. Zeeb const struct cfg80211_bitrate_mask *mask,
6423*5c1def83SBjoern A. Zeeb int *nss)
6424*5c1def83SBjoern A. Zeeb {
6425*5c1def83SBjoern A. Zeeb struct ieee80211_supported_band *sband = &ar->mac.sbands[band];
6426*5c1def83SBjoern A. Zeeb u16 vht_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map);
6427*5c1def83SBjoern A. Zeeb u8 ht_nss_mask = 0;
6428*5c1def83SBjoern A. Zeeb u8 vht_nss_mask = 0;
6429*5c1def83SBjoern A. Zeeb int i;
6430*5c1def83SBjoern A. Zeeb
6431*5c1def83SBjoern A. Zeeb /* No need to consider legacy here. Basic rates are always present
6432*5c1def83SBjoern A. Zeeb * in bitrate mask
6433*5c1def83SBjoern A. Zeeb */
6434*5c1def83SBjoern A. Zeeb
6435*5c1def83SBjoern A. Zeeb for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++) {
6436*5c1def83SBjoern A. Zeeb if (mask->control[band].ht_mcs[i] == 0)
6437*5c1def83SBjoern A. Zeeb continue;
6438*5c1def83SBjoern A. Zeeb else if (mask->control[band].ht_mcs[i] ==
6439*5c1def83SBjoern A. Zeeb sband->ht_cap.mcs.rx_mask[i])
6440*5c1def83SBjoern A. Zeeb ht_nss_mask |= BIT(i);
6441*5c1def83SBjoern A. Zeeb else
6442*5c1def83SBjoern A. Zeeb return false;
6443*5c1def83SBjoern A. Zeeb }
6444*5c1def83SBjoern A. Zeeb
6445*5c1def83SBjoern A. Zeeb for (i = 0; i < ARRAY_SIZE(mask->control[band].vht_mcs); i++) {
6446*5c1def83SBjoern A. Zeeb if (mask->control[band].vht_mcs[i] == 0)
6447*5c1def83SBjoern A. Zeeb continue;
6448*5c1def83SBjoern A. Zeeb else if (mask->control[band].vht_mcs[i] ==
6449*5c1def83SBjoern A. Zeeb ath12k_mac_get_max_vht_mcs_map(vht_mcs_map, i))
6450*5c1def83SBjoern A. Zeeb vht_nss_mask |= BIT(i);
6451*5c1def83SBjoern A. Zeeb else
6452*5c1def83SBjoern A. Zeeb return false;
6453*5c1def83SBjoern A. Zeeb }
6454*5c1def83SBjoern A. Zeeb
6455*5c1def83SBjoern A. Zeeb if (ht_nss_mask != vht_nss_mask)
6456*5c1def83SBjoern A. Zeeb return false;
6457*5c1def83SBjoern A. Zeeb
6458*5c1def83SBjoern A. Zeeb if (ht_nss_mask == 0)
6459*5c1def83SBjoern A. Zeeb return false;
6460*5c1def83SBjoern A. Zeeb
6461*5c1def83SBjoern A. Zeeb if (BIT(fls(ht_nss_mask)) - 1 != ht_nss_mask)
6462*5c1def83SBjoern A. Zeeb return false;
6463*5c1def83SBjoern A. Zeeb
6464*5c1def83SBjoern A. Zeeb *nss = fls(ht_nss_mask);
6465*5c1def83SBjoern A. Zeeb
6466*5c1def83SBjoern A. Zeeb return true;
6467*5c1def83SBjoern A. Zeeb }
6468*5c1def83SBjoern A. Zeeb
6469*5c1def83SBjoern A. Zeeb 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)6470*5c1def83SBjoern A. Zeeb ath12k_mac_get_single_legacy_rate(struct ath12k *ar,
6471*5c1def83SBjoern A. Zeeb enum nl80211_band band,
6472*5c1def83SBjoern A. Zeeb const struct cfg80211_bitrate_mask *mask,
6473*5c1def83SBjoern A. Zeeb u32 *rate, u8 *nss)
6474*5c1def83SBjoern A. Zeeb {
6475*5c1def83SBjoern A. Zeeb int rate_idx;
6476*5c1def83SBjoern A. Zeeb u16 bitrate;
6477*5c1def83SBjoern A. Zeeb u8 preamble;
6478*5c1def83SBjoern A. Zeeb u8 hw_rate;
6479*5c1def83SBjoern A. Zeeb
6480*5c1def83SBjoern A. Zeeb if (hweight32(mask->control[band].legacy) != 1)
6481*5c1def83SBjoern A. Zeeb return -EINVAL;
6482*5c1def83SBjoern A. Zeeb
6483*5c1def83SBjoern A. Zeeb rate_idx = ffs(mask->control[band].legacy) - 1;
6484*5c1def83SBjoern A. Zeeb
6485*5c1def83SBjoern A. Zeeb if (band == NL80211_BAND_5GHZ || band == NL80211_BAND_6GHZ)
6486*5c1def83SBjoern A. Zeeb rate_idx += ATH12K_MAC_FIRST_OFDM_RATE_IDX;
6487*5c1def83SBjoern A. Zeeb
6488*5c1def83SBjoern A. Zeeb hw_rate = ath12k_legacy_rates[rate_idx].hw_value;
6489*5c1def83SBjoern A. Zeeb bitrate = ath12k_legacy_rates[rate_idx].bitrate;
6490*5c1def83SBjoern A. Zeeb
6491*5c1def83SBjoern A. Zeeb if (ath12k_mac_bitrate_is_cck(bitrate))
6492*5c1def83SBjoern A. Zeeb preamble = WMI_RATE_PREAMBLE_CCK;
6493*5c1def83SBjoern A. Zeeb else
6494*5c1def83SBjoern A. Zeeb preamble = WMI_RATE_PREAMBLE_OFDM;
6495*5c1def83SBjoern A. Zeeb
6496*5c1def83SBjoern A. Zeeb *nss = 1;
6497*5c1def83SBjoern A. Zeeb *rate = ATH12K_HW_RATE_CODE(hw_rate, 0, preamble);
6498*5c1def83SBjoern A. Zeeb
6499*5c1def83SBjoern A. Zeeb return 0;
6500*5c1def83SBjoern A. Zeeb }
6501*5c1def83SBjoern A. Zeeb
ath12k_mac_set_fixed_rate_params(struct ath12k_vif * arvif,u32 rate,u8 nss,u8 sgi,u8 ldpc)6502*5c1def83SBjoern A. Zeeb static int ath12k_mac_set_fixed_rate_params(struct ath12k_vif *arvif,
6503*5c1def83SBjoern A. Zeeb u32 rate, u8 nss, u8 sgi, u8 ldpc)
6504*5c1def83SBjoern A. Zeeb {
6505*5c1def83SBjoern A. Zeeb struct ath12k *ar = arvif->ar;
6506*5c1def83SBjoern A. Zeeb u32 vdev_param;
6507*5c1def83SBjoern A. Zeeb int ret;
6508*5c1def83SBjoern A. Zeeb
6509*5c1def83SBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
6510*5c1def83SBjoern A. Zeeb
6511*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac set fixed rate params vdev %i rate 0x%02x nss %u sgi %u\n",
6512*5c1def83SBjoern A. Zeeb arvif->vdev_id, rate, nss, sgi);
6513*5c1def83SBjoern A. Zeeb
6514*5c1def83SBjoern A. Zeeb vdev_param = WMI_VDEV_PARAM_FIXED_RATE;
6515*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
6516*5c1def83SBjoern A. Zeeb vdev_param, rate);
6517*5c1def83SBjoern A. Zeeb if (ret) {
6518*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to set fixed rate param 0x%02x: %d\n",
6519*5c1def83SBjoern A. Zeeb rate, ret);
6520*5c1def83SBjoern A. Zeeb return ret;
6521*5c1def83SBjoern A. Zeeb }
6522*5c1def83SBjoern A. Zeeb
6523*5c1def83SBjoern A. Zeeb vdev_param = WMI_VDEV_PARAM_NSS;
6524*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
6525*5c1def83SBjoern A. Zeeb vdev_param, nss);
6526*5c1def83SBjoern A. Zeeb if (ret) {
6527*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to set nss param %d: %d\n",
6528*5c1def83SBjoern A. Zeeb nss, ret);
6529*5c1def83SBjoern A. Zeeb return ret;
6530*5c1def83SBjoern A. Zeeb }
6531*5c1def83SBjoern A. Zeeb
6532*5c1def83SBjoern A. Zeeb vdev_param = WMI_VDEV_PARAM_SGI;
6533*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
6534*5c1def83SBjoern A. Zeeb vdev_param, sgi);
6535*5c1def83SBjoern A. Zeeb if (ret) {
6536*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to set sgi param %d: %d\n",
6537*5c1def83SBjoern A. Zeeb sgi, ret);
6538*5c1def83SBjoern A. Zeeb return ret;
6539*5c1def83SBjoern A. Zeeb }
6540*5c1def83SBjoern A. Zeeb
6541*5c1def83SBjoern A. Zeeb vdev_param = WMI_VDEV_PARAM_LDPC;
6542*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
6543*5c1def83SBjoern A. Zeeb vdev_param, ldpc);
6544*5c1def83SBjoern A. Zeeb if (ret) {
6545*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to set ldpc param %d: %d\n",
6546*5c1def83SBjoern A. Zeeb ldpc, ret);
6547*5c1def83SBjoern A. Zeeb return ret;
6548*5c1def83SBjoern A. Zeeb }
6549*5c1def83SBjoern A. Zeeb
6550*5c1def83SBjoern A. Zeeb return 0;
6551*5c1def83SBjoern A. Zeeb }
6552*5c1def83SBjoern A. Zeeb
6553*5c1def83SBjoern A. Zeeb static bool
ath12k_mac_vht_mcs_range_present(struct ath12k * ar,enum nl80211_band band,const struct cfg80211_bitrate_mask * mask)6554*5c1def83SBjoern A. Zeeb ath12k_mac_vht_mcs_range_present(struct ath12k *ar,
6555*5c1def83SBjoern A. Zeeb enum nl80211_band band,
6556*5c1def83SBjoern A. Zeeb const struct cfg80211_bitrate_mask *mask)
6557*5c1def83SBjoern A. Zeeb {
6558*5c1def83SBjoern A. Zeeb int i;
6559*5c1def83SBjoern A. Zeeb u16 vht_mcs;
6560*5c1def83SBjoern A. Zeeb
6561*5c1def83SBjoern A. Zeeb for (i = 0; i < NL80211_VHT_NSS_MAX; i++) {
6562*5c1def83SBjoern A. Zeeb vht_mcs = mask->control[band].vht_mcs[i];
6563*5c1def83SBjoern A. Zeeb
6564*5c1def83SBjoern A. Zeeb switch (vht_mcs) {
6565*5c1def83SBjoern A. Zeeb case 0:
6566*5c1def83SBjoern A. Zeeb case BIT(8) - 1:
6567*5c1def83SBjoern A. Zeeb case BIT(9) - 1:
6568*5c1def83SBjoern A. Zeeb case BIT(10) - 1:
6569*5c1def83SBjoern A. Zeeb break;
6570*5c1def83SBjoern A. Zeeb default:
6571*5c1def83SBjoern A. Zeeb return false;
6572*5c1def83SBjoern A. Zeeb }
6573*5c1def83SBjoern A. Zeeb }
6574*5c1def83SBjoern A. Zeeb
6575*5c1def83SBjoern A. Zeeb return true;
6576*5c1def83SBjoern A. Zeeb }
6577*5c1def83SBjoern A. Zeeb
ath12k_mac_set_bitrate_mask_iter(void * data,struct ieee80211_sta * sta)6578*5c1def83SBjoern A. Zeeb static void ath12k_mac_set_bitrate_mask_iter(void *data,
6579*5c1def83SBjoern A. Zeeb struct ieee80211_sta *sta)
6580*5c1def83SBjoern A. Zeeb {
6581*5c1def83SBjoern A. Zeeb struct ath12k_vif *arvif = data;
6582*5c1def83SBjoern A. Zeeb struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv;
6583*5c1def83SBjoern A. Zeeb struct ath12k *ar = arvif->ar;
6584*5c1def83SBjoern A. Zeeb
6585*5c1def83SBjoern A. Zeeb spin_lock_bh(&ar->data_lock);
6586*5c1def83SBjoern A. Zeeb arsta->changed |= IEEE80211_RC_SUPP_RATES_CHANGED;
6587*5c1def83SBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
6588*5c1def83SBjoern A. Zeeb
6589*5c1def83SBjoern A. Zeeb ieee80211_queue_work(ar->hw, &arsta->update_wk);
6590*5c1def83SBjoern A. Zeeb }
6591*5c1def83SBjoern A. Zeeb
ath12k_mac_disable_peer_fixed_rate(void * data,struct ieee80211_sta * sta)6592*5c1def83SBjoern A. Zeeb static void ath12k_mac_disable_peer_fixed_rate(void *data,
6593*5c1def83SBjoern A. Zeeb struct ieee80211_sta *sta)
6594*5c1def83SBjoern A. Zeeb {
6595*5c1def83SBjoern A. Zeeb struct ath12k_vif *arvif = data;
6596*5c1def83SBjoern A. Zeeb struct ath12k *ar = arvif->ar;
6597*5c1def83SBjoern A. Zeeb int ret;
6598*5c1def83SBjoern A. Zeeb
6599*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_set_peer_param(ar, sta->addr,
6600*5c1def83SBjoern A. Zeeb arvif->vdev_id,
6601*5c1def83SBjoern A. Zeeb WMI_PEER_PARAM_FIXED_RATE,
6602*5c1def83SBjoern A. Zeeb WMI_FIXED_RATE_NONE);
6603*5c1def83SBjoern A. Zeeb if (ret)
6604*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab,
6605*5c1def83SBjoern A. Zeeb "failed to disable peer fixed rate for STA %pM ret %d\n",
6606*5c1def83SBjoern A. Zeeb sta->addr, ret);
6607*5c1def83SBjoern A. Zeeb }
6608*5c1def83SBjoern A. Zeeb
6609*5c1def83SBjoern A. Zeeb static int
ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw * hw,struct ieee80211_vif * vif,const struct cfg80211_bitrate_mask * mask)6610*5c1def83SBjoern A. Zeeb ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
6611*5c1def83SBjoern A. Zeeb struct ieee80211_vif *vif,
6612*5c1def83SBjoern A. Zeeb const struct cfg80211_bitrate_mask *mask)
6613*5c1def83SBjoern A. Zeeb {
6614*5c1def83SBjoern A. Zeeb struct ath12k_vif *arvif = (void *)vif->drv_priv;
6615*5c1def83SBjoern A. Zeeb struct cfg80211_chan_def def;
6616*5c1def83SBjoern A. Zeeb struct ath12k *ar = arvif->ar;
6617*5c1def83SBjoern A. Zeeb enum nl80211_band band;
6618*5c1def83SBjoern A. Zeeb const u8 *ht_mcs_mask;
6619*5c1def83SBjoern A. Zeeb const u16 *vht_mcs_mask;
6620*5c1def83SBjoern A. Zeeb u32 rate;
6621*5c1def83SBjoern A. Zeeb u8 nss;
6622*5c1def83SBjoern A. Zeeb u8 sgi;
6623*5c1def83SBjoern A. Zeeb u8 ldpc;
6624*5c1def83SBjoern A. Zeeb int single_nss;
6625*5c1def83SBjoern A. Zeeb int ret;
6626*5c1def83SBjoern A. Zeeb int num_rates;
6627*5c1def83SBjoern A. Zeeb
6628*5c1def83SBjoern A. Zeeb if (ath12k_mac_vif_chan(vif, &def))
6629*5c1def83SBjoern A. Zeeb return -EPERM;
6630*5c1def83SBjoern A. Zeeb
6631*5c1def83SBjoern A. Zeeb band = def.chan->band;
6632*5c1def83SBjoern A. Zeeb ht_mcs_mask = mask->control[band].ht_mcs;
6633*5c1def83SBjoern A. Zeeb vht_mcs_mask = mask->control[band].vht_mcs;
6634*5c1def83SBjoern A. Zeeb ldpc = !!(ar->ht_cap_info & WMI_HT_CAP_LDPC);
6635*5c1def83SBjoern A. Zeeb
6636*5c1def83SBjoern A. Zeeb sgi = mask->control[band].gi;
6637*5c1def83SBjoern A. Zeeb if (sgi == NL80211_TXRATE_FORCE_LGI)
6638*5c1def83SBjoern A. Zeeb return -EINVAL;
6639*5c1def83SBjoern A. Zeeb
6640*5c1def83SBjoern A. Zeeb /* mac80211 doesn't support sending a fixed HT/VHT MCS alone, rather it
6641*5c1def83SBjoern A. Zeeb * requires passing at least one of used basic rates along with them.
6642*5c1def83SBjoern A. Zeeb * Fixed rate setting across different preambles(legacy, HT, VHT) is
6643*5c1def83SBjoern A. Zeeb * not supported by the FW. Hence use of FIXED_RATE vdev param is not
6644*5c1def83SBjoern A. Zeeb * suitable for setting single HT/VHT rates.
6645*5c1def83SBjoern A. Zeeb * But, there could be a single basic rate passed from userspace which
6646*5c1def83SBjoern A. Zeeb * can be done through the FIXED_RATE param.
6647*5c1def83SBjoern A. Zeeb */
6648*5c1def83SBjoern A. Zeeb if (ath12k_mac_has_single_legacy_rate(ar, band, mask)) {
6649*5c1def83SBjoern A. Zeeb ret = ath12k_mac_get_single_legacy_rate(ar, band, mask, &rate,
6650*5c1def83SBjoern A. Zeeb &nss);
6651*5c1def83SBjoern A. Zeeb if (ret) {
6652*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to get single legacy rate for vdev %i: %d\n",
6653*5c1def83SBjoern A. Zeeb arvif->vdev_id, ret);
6654*5c1def83SBjoern A. Zeeb return ret;
6655*5c1def83SBjoern A. Zeeb }
6656*5c1def83SBjoern A. Zeeb ieee80211_iterate_stations_atomic(ar->hw,
6657*5c1def83SBjoern A. Zeeb ath12k_mac_disable_peer_fixed_rate,
6658*5c1def83SBjoern A. Zeeb arvif);
6659*5c1def83SBjoern A. Zeeb } else if (ath12k_mac_bitrate_mask_get_single_nss(ar, band, mask,
6660*5c1def83SBjoern A. Zeeb &single_nss)) {
6661*5c1def83SBjoern A. Zeeb rate = WMI_FIXED_RATE_NONE;
6662*5c1def83SBjoern A. Zeeb nss = single_nss;
6663*5c1def83SBjoern A. Zeeb } else {
6664*5c1def83SBjoern A. Zeeb rate = WMI_FIXED_RATE_NONE;
6665*5c1def83SBjoern A. Zeeb nss = min_t(u32, ar->num_tx_chains,
6666*5c1def83SBjoern A. Zeeb max(ath12k_mac_max_ht_nss(ht_mcs_mask),
6667*5c1def83SBjoern A. Zeeb ath12k_mac_max_vht_nss(vht_mcs_mask)));
6668*5c1def83SBjoern A. Zeeb
6669*5c1def83SBjoern A. Zeeb /* If multiple rates across different preambles are given
6670*5c1def83SBjoern A. Zeeb * we can reconfigure this info with all peers using PEER_ASSOC
6671*5c1def83SBjoern A. Zeeb * command with the below exception cases.
6672*5c1def83SBjoern A. Zeeb * - Single VHT Rate : peer_assoc command accommodates only MCS
6673*5c1def83SBjoern A. Zeeb * range values i.e 0-7, 0-8, 0-9 for VHT. Though mac80211
6674*5c1def83SBjoern A. Zeeb * mandates passing basic rates along with HT/VHT rates, FW
6675*5c1def83SBjoern A. Zeeb * doesn't allow switching from VHT to Legacy. Hence instead of
6676*5c1def83SBjoern A. Zeeb * setting legacy and VHT rates using RATEMASK_CMD vdev cmd,
6677*5c1def83SBjoern A. Zeeb * we could set this VHT rate as peer fixed rate param, which
6678*5c1def83SBjoern A. Zeeb * will override FIXED rate and FW rate control algorithm.
6679*5c1def83SBjoern A. Zeeb * If single VHT rate is passed along with HT rates, we select
6680*5c1def83SBjoern A. Zeeb * the VHT rate as fixed rate for vht peers.
6681*5c1def83SBjoern A. Zeeb * - Multiple VHT Rates : When Multiple VHT rates are given,this
6682*5c1def83SBjoern A. Zeeb * can be set using RATEMASK CMD which uses FW rate-ctl alg.
6683*5c1def83SBjoern A. Zeeb * TODO: Setting multiple VHT MCS and replacing peer_assoc with
6684*5c1def83SBjoern A. Zeeb * RATEMASK_CMDID can cover all use cases of setting rates
6685*5c1def83SBjoern A. Zeeb * across multiple preambles and rates within same type.
6686*5c1def83SBjoern A. Zeeb * But requires more validation of the command at this point.
6687*5c1def83SBjoern A. Zeeb */
6688*5c1def83SBjoern A. Zeeb
6689*5c1def83SBjoern A. Zeeb num_rates = ath12k_mac_bitrate_mask_num_vht_rates(ar, band,
6690*5c1def83SBjoern A. Zeeb mask);
6691*5c1def83SBjoern A. Zeeb
6692*5c1def83SBjoern A. Zeeb if (!ath12k_mac_vht_mcs_range_present(ar, band, mask) &&
6693*5c1def83SBjoern A. Zeeb num_rates > 1) {
6694*5c1def83SBjoern A. Zeeb /* TODO: Handle multiple VHT MCS values setting using
6695*5c1def83SBjoern A. Zeeb * RATEMASK CMD
6696*5c1def83SBjoern A. Zeeb */
6697*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab,
6698*5c1def83SBjoern A. Zeeb "Setting more than one MCS Value in bitrate mask not supported\n");
6699*5c1def83SBjoern A. Zeeb return -EINVAL;
6700*5c1def83SBjoern A. Zeeb }
6701*5c1def83SBjoern A. Zeeb
6702*5c1def83SBjoern A. Zeeb ieee80211_iterate_stations_atomic(ar->hw,
6703*5c1def83SBjoern A. Zeeb ath12k_mac_disable_peer_fixed_rate,
6704*5c1def83SBjoern A. Zeeb arvif);
6705*5c1def83SBjoern A. Zeeb
6706*5c1def83SBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
6707*5c1def83SBjoern A. Zeeb
6708*5c1def83SBjoern A. Zeeb arvif->bitrate_mask = *mask;
6709*5c1def83SBjoern A. Zeeb ieee80211_iterate_stations_atomic(ar->hw,
6710*5c1def83SBjoern A. Zeeb ath12k_mac_set_bitrate_mask_iter,
6711*5c1def83SBjoern A. Zeeb arvif);
6712*5c1def83SBjoern A. Zeeb
6713*5c1def83SBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
6714*5c1def83SBjoern A. Zeeb }
6715*5c1def83SBjoern A. Zeeb
6716*5c1def83SBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
6717*5c1def83SBjoern A. Zeeb
6718*5c1def83SBjoern A. Zeeb ret = ath12k_mac_set_fixed_rate_params(arvif, rate, nss, sgi, ldpc);
6719*5c1def83SBjoern A. Zeeb if (ret) {
6720*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to set fixed rate params on vdev %i: %d\n",
6721*5c1def83SBjoern A. Zeeb arvif->vdev_id, ret);
6722*5c1def83SBjoern A. Zeeb }
6723*5c1def83SBjoern A. Zeeb
6724*5c1def83SBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
6725*5c1def83SBjoern A. Zeeb
6726*5c1def83SBjoern A. Zeeb return ret;
6727*5c1def83SBjoern A. Zeeb }
6728*5c1def83SBjoern A. Zeeb
6729*5c1def83SBjoern A. Zeeb static void
ath12k_mac_op_reconfig_complete(struct ieee80211_hw * hw,enum ieee80211_reconfig_type reconfig_type)6730*5c1def83SBjoern A. Zeeb ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw,
6731*5c1def83SBjoern A. Zeeb enum ieee80211_reconfig_type reconfig_type)
6732*5c1def83SBjoern A. Zeeb {
6733*5c1def83SBjoern A. Zeeb struct ath12k *ar = hw->priv;
6734*5c1def83SBjoern A. Zeeb struct ath12k_base *ab = ar->ab;
6735*5c1def83SBjoern A. Zeeb struct ath12k_vif *arvif;
6736*5c1def83SBjoern A. Zeeb int recovery_count;
6737*5c1def83SBjoern A. Zeeb
6738*5c1def83SBjoern A. Zeeb if (reconfig_type != IEEE80211_RECONFIG_TYPE_RESTART)
6739*5c1def83SBjoern A. Zeeb return;
6740*5c1def83SBjoern A. Zeeb
6741*5c1def83SBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
6742*5c1def83SBjoern A. Zeeb
6743*5c1def83SBjoern A. Zeeb if (ar->state == ATH12K_STATE_RESTARTED) {
6744*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "pdev %d successfully recovered\n",
6745*5c1def83SBjoern A. Zeeb ar->pdev->pdev_id);
6746*5c1def83SBjoern A. Zeeb ar->state = ATH12K_STATE_ON;
6747*5c1def83SBjoern A. Zeeb ieee80211_wake_queues(ar->hw);
6748*5c1def83SBjoern A. Zeeb
6749*5c1def83SBjoern A. Zeeb if (ab->is_reset) {
6750*5c1def83SBjoern A. Zeeb recovery_count = atomic_inc_return(&ab->recovery_count);
6751*5c1def83SBjoern A. Zeeb ath12k_dbg(ab, ATH12K_DBG_BOOT, "recovery count %d\n",
6752*5c1def83SBjoern A. Zeeb recovery_count);
6753*5c1def83SBjoern A. Zeeb /* When there are multiple radios in an SOC,
6754*5c1def83SBjoern A. Zeeb * the recovery has to be done for each radio
6755*5c1def83SBjoern A. Zeeb */
6756*5c1def83SBjoern A. Zeeb if (recovery_count == ab->num_radios) {
6757*5c1def83SBjoern A. Zeeb atomic_dec(&ab->reset_count);
6758*5c1def83SBjoern A. Zeeb complete(&ab->reset_complete);
6759*5c1def83SBjoern A. Zeeb ab->is_reset = false;
6760*5c1def83SBjoern A. Zeeb atomic_set(&ab->fail_cont_count, 0);
6761*5c1def83SBjoern A. Zeeb ath12k_dbg(ab, ATH12K_DBG_BOOT, "reset success\n");
6762*5c1def83SBjoern A. Zeeb }
6763*5c1def83SBjoern A. Zeeb }
6764*5c1def83SBjoern A. Zeeb
6765*5c1def83SBjoern A. Zeeb list_for_each_entry(arvif, &ar->arvifs, list) {
6766*5c1def83SBjoern A. Zeeb ath12k_dbg(ab, ATH12K_DBG_BOOT,
6767*5c1def83SBjoern A. Zeeb "reconfig cipher %d up %d vdev type %d\n",
6768*5c1def83SBjoern A. Zeeb arvif->key_cipher,
6769*5c1def83SBjoern A. Zeeb arvif->is_up,
6770*5c1def83SBjoern A. Zeeb arvif->vdev_type);
6771*5c1def83SBjoern A. Zeeb /* After trigger disconnect, then upper layer will
6772*5c1def83SBjoern A. Zeeb * trigger connect again, then the PN number of
6773*5c1def83SBjoern A. Zeeb * upper layer will be reset to keep up with AP
6774*5c1def83SBjoern A. Zeeb * side, hence PN number mis-match will not happened.
6775*5c1def83SBjoern A. Zeeb */
6776*5c1def83SBjoern A. Zeeb if (arvif->is_up &&
6777*5c1def83SBjoern A. Zeeb arvif->vdev_type == WMI_VDEV_TYPE_STA &&
6778*5c1def83SBjoern A. Zeeb arvif->vdev_subtype == WMI_VDEV_SUBTYPE_NONE) {
6779*5c1def83SBjoern A. Zeeb ieee80211_hw_restart_disconnect(arvif->vif);
6780*5c1def83SBjoern A. Zeeb ath12k_dbg(ab, ATH12K_DBG_BOOT,
6781*5c1def83SBjoern A. Zeeb "restart disconnect\n");
6782*5c1def83SBjoern A. Zeeb }
6783*5c1def83SBjoern A. Zeeb }
6784*5c1def83SBjoern A. Zeeb }
6785*5c1def83SBjoern A. Zeeb
6786*5c1def83SBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
6787*5c1def83SBjoern A. Zeeb }
6788*5c1def83SBjoern A. Zeeb
6789*5c1def83SBjoern A. Zeeb static void
ath12k_mac_update_bss_chan_survey(struct ath12k * ar,struct ieee80211_channel * channel)6790*5c1def83SBjoern A. Zeeb ath12k_mac_update_bss_chan_survey(struct ath12k *ar,
6791*5c1def83SBjoern A. Zeeb struct ieee80211_channel *channel)
6792*5c1def83SBjoern A. Zeeb {
6793*5c1def83SBjoern A. Zeeb int ret;
6794*5c1def83SBjoern A. Zeeb enum wmi_bss_chan_info_req_type type = WMI_BSS_SURVEY_REQ_TYPE_READ;
6795*5c1def83SBjoern A. Zeeb
6796*5c1def83SBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
6797*5c1def83SBjoern A. Zeeb
6798*5c1def83SBjoern A. Zeeb if (!test_bit(WMI_TLV_SERVICE_BSS_CHANNEL_INFO_64, ar->ab->wmi_ab.svc_map) ||
6799*5c1def83SBjoern A. Zeeb ar->rx_channel != channel)
6800*5c1def83SBjoern A. Zeeb return;
6801*5c1def83SBjoern A. Zeeb
6802*5c1def83SBjoern A. Zeeb if (ar->scan.state != ATH12K_SCAN_IDLE) {
6803*5c1def83SBjoern A. Zeeb ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
6804*5c1def83SBjoern A. Zeeb "ignoring bss chan info req while scanning..\n");
6805*5c1def83SBjoern A. Zeeb return;
6806*5c1def83SBjoern A. Zeeb }
6807*5c1def83SBjoern A. Zeeb
6808*5c1def83SBjoern A. Zeeb reinit_completion(&ar->bss_survey_done);
6809*5c1def83SBjoern A. Zeeb
6810*5c1def83SBjoern A. Zeeb ret = ath12k_wmi_pdev_bss_chan_info_request(ar, type);
6811*5c1def83SBjoern A. Zeeb if (ret) {
6812*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "failed to send pdev bss chan info request\n");
6813*5c1def83SBjoern A. Zeeb return;
6814*5c1def83SBjoern A. Zeeb }
6815*5c1def83SBjoern A. Zeeb
6816*5c1def83SBjoern A. Zeeb ret = wait_for_completion_timeout(&ar->bss_survey_done, 3 * HZ);
6817*5c1def83SBjoern A. Zeeb if (ret == 0)
6818*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "bss channel survey timed out\n");
6819*5c1def83SBjoern A. Zeeb }
6820*5c1def83SBjoern A. Zeeb
ath12k_mac_op_get_survey(struct ieee80211_hw * hw,int idx,struct survey_info * survey)6821*5c1def83SBjoern A. Zeeb static int ath12k_mac_op_get_survey(struct ieee80211_hw *hw, int idx,
6822*5c1def83SBjoern A. Zeeb struct survey_info *survey)
6823*5c1def83SBjoern A. Zeeb {
6824*5c1def83SBjoern A. Zeeb struct ath12k *ar = hw->priv;
6825*5c1def83SBjoern A. Zeeb struct ieee80211_supported_band *sband;
6826*5c1def83SBjoern A. Zeeb struct survey_info *ar_survey;
6827*5c1def83SBjoern A. Zeeb int ret = 0;
6828*5c1def83SBjoern A. Zeeb
6829*5c1def83SBjoern A. Zeeb if (idx >= ATH12K_NUM_CHANS)
6830*5c1def83SBjoern A. Zeeb return -ENOENT;
6831*5c1def83SBjoern A. Zeeb
6832*5c1def83SBjoern A. Zeeb ar_survey = &ar->survey[idx];
6833*5c1def83SBjoern A. Zeeb
6834*5c1def83SBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
6835*5c1def83SBjoern A. Zeeb
6836*5c1def83SBjoern A. Zeeb sband = hw->wiphy->bands[NL80211_BAND_2GHZ];
6837*5c1def83SBjoern A. Zeeb if (sband && idx >= sband->n_channels) {
6838*5c1def83SBjoern A. Zeeb idx -= sband->n_channels;
6839*5c1def83SBjoern A. Zeeb sband = NULL;
6840*5c1def83SBjoern A. Zeeb }
6841*5c1def83SBjoern A. Zeeb
6842*5c1def83SBjoern A. Zeeb if (!sband)
6843*5c1def83SBjoern A. Zeeb sband = hw->wiphy->bands[NL80211_BAND_5GHZ];
6844*5c1def83SBjoern A. Zeeb
6845*5c1def83SBjoern A. Zeeb if (!sband || idx >= sband->n_channels) {
6846*5c1def83SBjoern A. Zeeb ret = -ENOENT;
6847*5c1def83SBjoern A. Zeeb goto exit;
6848*5c1def83SBjoern A. Zeeb }
6849*5c1def83SBjoern A. Zeeb
6850*5c1def83SBjoern A. Zeeb ath12k_mac_update_bss_chan_survey(ar, &sband->channels[idx]);
6851*5c1def83SBjoern A. Zeeb
6852*5c1def83SBjoern A. Zeeb spin_lock_bh(&ar->data_lock);
6853*5c1def83SBjoern A. Zeeb memcpy(survey, ar_survey, sizeof(*survey));
6854*5c1def83SBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
6855*5c1def83SBjoern A. Zeeb
6856*5c1def83SBjoern A. Zeeb survey->channel = &sband->channels[idx];
6857*5c1def83SBjoern A. Zeeb
6858*5c1def83SBjoern A. Zeeb if (ar->rx_channel == survey->channel)
6859*5c1def83SBjoern A. Zeeb survey->filled |= SURVEY_INFO_IN_USE;
6860*5c1def83SBjoern A. Zeeb
6861*5c1def83SBjoern A. Zeeb exit:
6862*5c1def83SBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
6863*5c1def83SBjoern A. Zeeb return ret;
6864*5c1def83SBjoern A. Zeeb }
6865*5c1def83SBjoern A. Zeeb
ath12k_mac_op_sta_statistics(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct station_info * sinfo)6866*5c1def83SBjoern A. Zeeb static void ath12k_mac_op_sta_statistics(struct ieee80211_hw *hw,
6867*5c1def83SBjoern A. Zeeb struct ieee80211_vif *vif,
6868*5c1def83SBjoern A. Zeeb struct ieee80211_sta *sta,
6869*5c1def83SBjoern A. Zeeb struct station_info *sinfo)
6870*5c1def83SBjoern A. Zeeb {
6871*5c1def83SBjoern A. Zeeb struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv;
6872*5c1def83SBjoern A. Zeeb
6873*5c1def83SBjoern A. Zeeb sinfo->rx_duration = arsta->rx_duration;
6874*5c1def83SBjoern A. Zeeb sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_DURATION);
6875*5c1def83SBjoern A. Zeeb
6876*5c1def83SBjoern A. Zeeb sinfo->tx_duration = arsta->tx_duration;
6877*5c1def83SBjoern A. Zeeb sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_DURATION);
6878*5c1def83SBjoern A. Zeeb
6879*5c1def83SBjoern A. Zeeb if (!arsta->txrate.legacy && !arsta->txrate.nss)
6880*5c1def83SBjoern A. Zeeb return;
6881*5c1def83SBjoern A. Zeeb
6882*5c1def83SBjoern A. Zeeb if (arsta->txrate.legacy) {
6883*5c1def83SBjoern A. Zeeb sinfo->txrate.legacy = arsta->txrate.legacy;
6884*5c1def83SBjoern A. Zeeb } else {
6885*5c1def83SBjoern A. Zeeb sinfo->txrate.mcs = arsta->txrate.mcs;
6886*5c1def83SBjoern A. Zeeb sinfo->txrate.nss = arsta->txrate.nss;
6887*5c1def83SBjoern A. Zeeb sinfo->txrate.bw = arsta->txrate.bw;
6888*5c1def83SBjoern A. Zeeb sinfo->txrate.he_gi = arsta->txrate.he_gi;
6889*5c1def83SBjoern A. Zeeb sinfo->txrate.he_dcm = arsta->txrate.he_dcm;
6890*5c1def83SBjoern A. Zeeb sinfo->txrate.he_ru_alloc = arsta->txrate.he_ru_alloc;
6891*5c1def83SBjoern A. Zeeb }
6892*5c1def83SBjoern A. Zeeb sinfo->txrate.flags = arsta->txrate.flags;
6893*5c1def83SBjoern A. Zeeb sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
6894*5c1def83SBjoern A. Zeeb
6895*5c1def83SBjoern A. Zeeb /* TODO: Use real NF instead of default one. */
6896*5c1def83SBjoern A. Zeeb sinfo->signal = arsta->rssi_comb + ATH12K_DEFAULT_NOISE_FLOOR;
6897*5c1def83SBjoern A. Zeeb sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL);
6898*5c1def83SBjoern A. Zeeb }
6899*5c1def83SBjoern A. Zeeb
6900*5c1def83SBjoern A. Zeeb static const struct ieee80211_ops ath12k_ops = {
6901*5c1def83SBjoern A. Zeeb .tx = ath12k_mac_op_tx,
6902*5c1def83SBjoern A. Zeeb .wake_tx_queue = ieee80211_handle_wake_tx_queue,
6903*5c1def83SBjoern A. Zeeb .start = ath12k_mac_op_start,
6904*5c1def83SBjoern A. Zeeb .stop = ath12k_mac_op_stop,
6905*5c1def83SBjoern A. Zeeb .reconfig_complete = ath12k_mac_op_reconfig_complete,
6906*5c1def83SBjoern A. Zeeb .add_interface = ath12k_mac_op_add_interface,
6907*5c1def83SBjoern A. Zeeb .remove_interface = ath12k_mac_op_remove_interface,
6908*5c1def83SBjoern A. Zeeb .update_vif_offload = ath12k_mac_op_update_vif_offload,
6909*5c1def83SBjoern A. Zeeb .config = ath12k_mac_op_config,
6910*5c1def83SBjoern A. Zeeb .bss_info_changed = ath12k_mac_op_bss_info_changed,
6911*5c1def83SBjoern A. Zeeb .configure_filter = ath12k_mac_op_configure_filter,
6912*5c1def83SBjoern A. Zeeb .hw_scan = ath12k_mac_op_hw_scan,
6913*5c1def83SBjoern A. Zeeb .cancel_hw_scan = ath12k_mac_op_cancel_hw_scan,
6914*5c1def83SBjoern A. Zeeb .set_key = ath12k_mac_op_set_key,
6915*5c1def83SBjoern A. Zeeb .sta_state = ath12k_mac_op_sta_state,
6916*5c1def83SBjoern A. Zeeb .sta_set_txpwr = ath12k_mac_op_sta_set_txpwr,
6917*5c1def83SBjoern A. Zeeb .sta_rc_update = ath12k_mac_op_sta_rc_update,
6918*5c1def83SBjoern A. Zeeb .conf_tx = ath12k_mac_op_conf_tx,
6919*5c1def83SBjoern A. Zeeb .set_antenna = ath12k_mac_op_set_antenna,
6920*5c1def83SBjoern A. Zeeb .get_antenna = ath12k_mac_op_get_antenna,
6921*5c1def83SBjoern A. Zeeb .ampdu_action = ath12k_mac_op_ampdu_action,
6922*5c1def83SBjoern A. Zeeb .add_chanctx = ath12k_mac_op_add_chanctx,
6923*5c1def83SBjoern A. Zeeb .remove_chanctx = ath12k_mac_op_remove_chanctx,
6924*5c1def83SBjoern A. Zeeb .change_chanctx = ath12k_mac_op_change_chanctx,
6925*5c1def83SBjoern A. Zeeb .assign_vif_chanctx = ath12k_mac_op_assign_vif_chanctx,
6926*5c1def83SBjoern A. Zeeb .unassign_vif_chanctx = ath12k_mac_op_unassign_vif_chanctx,
6927*5c1def83SBjoern A. Zeeb .switch_vif_chanctx = ath12k_mac_op_switch_vif_chanctx,
6928*5c1def83SBjoern A. Zeeb .set_rts_threshold = ath12k_mac_op_set_rts_threshold,
6929*5c1def83SBjoern A. Zeeb .set_frag_threshold = ath12k_mac_op_set_frag_threshold,
6930*5c1def83SBjoern A. Zeeb .set_bitrate_mask = ath12k_mac_op_set_bitrate_mask,
6931*5c1def83SBjoern A. Zeeb .get_survey = ath12k_mac_op_get_survey,
6932*5c1def83SBjoern A. Zeeb .flush = ath12k_mac_op_flush,
6933*5c1def83SBjoern A. Zeeb .sta_statistics = ath12k_mac_op_sta_statistics,
6934*5c1def83SBjoern A. Zeeb };
6935*5c1def83SBjoern A. Zeeb
ath12k_mac_update_ch_list(struct ath12k * ar,struct ieee80211_supported_band * band,u32 freq_low,u32 freq_high)6936*5c1def83SBjoern A. Zeeb static void ath12k_mac_update_ch_list(struct ath12k *ar,
6937*5c1def83SBjoern A. Zeeb struct ieee80211_supported_band *band,
6938*5c1def83SBjoern A. Zeeb u32 freq_low, u32 freq_high)
6939*5c1def83SBjoern A. Zeeb {
6940*5c1def83SBjoern A. Zeeb int i;
6941*5c1def83SBjoern A. Zeeb
6942*5c1def83SBjoern A. Zeeb if (!(freq_low && freq_high))
6943*5c1def83SBjoern A. Zeeb return;
6944*5c1def83SBjoern A. Zeeb
6945*5c1def83SBjoern A. Zeeb for (i = 0; i < band->n_channels; i++) {
6946*5c1def83SBjoern A. Zeeb if (band->channels[i].center_freq < freq_low ||
6947*5c1def83SBjoern A. Zeeb band->channels[i].center_freq > freq_high)
6948*5c1def83SBjoern A. Zeeb band->channels[i].flags |= IEEE80211_CHAN_DISABLED;
6949*5c1def83SBjoern A. Zeeb }
6950*5c1def83SBjoern A. Zeeb }
6951*5c1def83SBjoern A. Zeeb
ath12k_get_phy_id(struct ath12k * ar,u32 band)6952*5c1def83SBjoern A. Zeeb static u32 ath12k_get_phy_id(struct ath12k *ar, u32 band)
6953*5c1def83SBjoern A. Zeeb {
6954*5c1def83SBjoern A. Zeeb struct ath12k_pdev *pdev = ar->pdev;
6955*5c1def83SBjoern A. Zeeb struct ath12k_pdev_cap *pdev_cap = &pdev->cap;
6956*5c1def83SBjoern A. Zeeb
6957*5c1def83SBjoern A. Zeeb if (band == WMI_HOST_WLAN_2G_CAP)
6958*5c1def83SBjoern A. Zeeb return pdev_cap->band[NL80211_BAND_2GHZ].phy_id;
6959*5c1def83SBjoern A. Zeeb
6960*5c1def83SBjoern A. Zeeb if (band == WMI_HOST_WLAN_5G_CAP)
6961*5c1def83SBjoern A. Zeeb return pdev_cap->band[NL80211_BAND_5GHZ].phy_id;
6962*5c1def83SBjoern A. Zeeb
6963*5c1def83SBjoern A. Zeeb ath12k_warn(ar->ab, "unsupported phy cap:%d\n", band);
6964*5c1def83SBjoern A. Zeeb
6965*5c1def83SBjoern A. Zeeb return 0;
6966*5c1def83SBjoern A. Zeeb }
6967*5c1def83SBjoern A. Zeeb
ath12k_mac_setup_channels_rates(struct ath12k * ar,u32 supported_bands)6968*5c1def83SBjoern A. Zeeb static int ath12k_mac_setup_channels_rates(struct ath12k *ar,
6969*5c1def83SBjoern A. Zeeb u32 supported_bands)
6970*5c1def83SBjoern A. Zeeb {
6971*5c1def83SBjoern A. Zeeb struct ieee80211_supported_band *band;
6972*5c1def83SBjoern A. Zeeb struct ath12k_wmi_hal_reg_capabilities_ext_arg *reg_cap;
6973*5c1def83SBjoern A. Zeeb void *channels;
6974*5c1def83SBjoern A. Zeeb u32 phy_id;
6975*5c1def83SBjoern A. Zeeb
6976*5c1def83SBjoern A. Zeeb BUILD_BUG_ON((ARRAY_SIZE(ath12k_2ghz_channels) +
6977*5c1def83SBjoern A. Zeeb ARRAY_SIZE(ath12k_5ghz_channels) +
6978*5c1def83SBjoern A. Zeeb ARRAY_SIZE(ath12k_6ghz_channels)) !=
6979*5c1def83SBjoern A. Zeeb ATH12K_NUM_CHANS);
6980*5c1def83SBjoern A. Zeeb
6981*5c1def83SBjoern A. Zeeb reg_cap = &ar->ab->hal_reg_cap[ar->pdev_idx];
6982*5c1def83SBjoern A. Zeeb
6983*5c1def83SBjoern A. Zeeb if (supported_bands & WMI_HOST_WLAN_2G_CAP) {
6984*5c1def83SBjoern A. Zeeb channels = kmemdup(ath12k_2ghz_channels,
6985*5c1def83SBjoern A. Zeeb sizeof(ath12k_2ghz_channels),
6986*5c1def83SBjoern A. Zeeb GFP_KERNEL);
6987*5c1def83SBjoern A. Zeeb if (!channels)
6988*5c1def83SBjoern A. Zeeb return -ENOMEM;
6989*5c1def83SBjoern A. Zeeb
6990*5c1def83SBjoern A. Zeeb band = &ar->mac.sbands[NL80211_BAND_2GHZ];
6991*5c1def83SBjoern A. Zeeb band->band = NL80211_BAND_2GHZ;
6992*5c1def83SBjoern A. Zeeb band->n_channels = ARRAY_SIZE(ath12k_2ghz_channels);
6993*5c1def83SBjoern A. Zeeb band->channels = channels;
6994*5c1def83SBjoern A. Zeeb band->n_bitrates = ath12k_g_rates_size;
6995*5c1def83SBjoern A. Zeeb band->bitrates = ath12k_g_rates;
6996*5c1def83SBjoern A. Zeeb ar->hw->wiphy->bands[NL80211_BAND_2GHZ] = band;
6997*5c1def83SBjoern A. Zeeb
6998*5c1def83SBjoern A. Zeeb if (ar->ab->hw_params->single_pdev_only) {
6999*5c1def83SBjoern A. Zeeb phy_id = ath12k_get_phy_id(ar, WMI_HOST_WLAN_2G_CAP);
7000*5c1def83SBjoern A. Zeeb reg_cap = &ar->ab->hal_reg_cap[phy_id];
7001*5c1def83SBjoern A. Zeeb }
7002*5c1def83SBjoern A. Zeeb ath12k_mac_update_ch_list(ar, band,
7003*5c1def83SBjoern A. Zeeb reg_cap->low_2ghz_chan,
7004*5c1def83SBjoern A. Zeeb reg_cap->high_2ghz_chan);
7005*5c1def83SBjoern A. Zeeb }
7006*5c1def83SBjoern A. Zeeb
7007*5c1def83SBjoern A. Zeeb if (supported_bands & WMI_HOST_WLAN_5G_CAP) {
7008*5c1def83SBjoern A. Zeeb if (reg_cap->high_5ghz_chan >= ATH12K_MAX_6G_FREQ) {
7009*5c1def83SBjoern A. Zeeb channels = kmemdup(ath12k_6ghz_channels,
7010*5c1def83SBjoern A. Zeeb sizeof(ath12k_6ghz_channels), GFP_KERNEL);
7011*5c1def83SBjoern A. Zeeb if (!channels) {
7012*5c1def83SBjoern A. Zeeb kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels);
7013*5c1def83SBjoern A. Zeeb return -ENOMEM;
7014*5c1def83SBjoern A. Zeeb }
7015*5c1def83SBjoern A. Zeeb
7016*5c1def83SBjoern A. Zeeb ar->supports_6ghz = true;
7017*5c1def83SBjoern A. Zeeb band = &ar->mac.sbands[NL80211_BAND_6GHZ];
7018*5c1def83SBjoern A. Zeeb band->band = NL80211_BAND_6GHZ;
7019*5c1def83SBjoern A. Zeeb band->n_channels = ARRAY_SIZE(ath12k_6ghz_channels);
7020*5c1def83SBjoern A. Zeeb band->channels = channels;
7021*5c1def83SBjoern A. Zeeb band->n_bitrates = ath12k_a_rates_size;
7022*5c1def83SBjoern A. Zeeb band->bitrates = ath12k_a_rates;
7023*5c1def83SBjoern A. Zeeb ar->hw->wiphy->bands[NL80211_BAND_6GHZ] = band;
7024*5c1def83SBjoern A. Zeeb ath12k_mac_update_ch_list(ar, band,
7025*5c1def83SBjoern A. Zeeb reg_cap->low_5ghz_chan,
7026*5c1def83SBjoern A. Zeeb reg_cap->high_5ghz_chan);
7027*5c1def83SBjoern A. Zeeb }
7028*5c1def83SBjoern A. Zeeb
7029*5c1def83SBjoern A. Zeeb if (reg_cap->low_5ghz_chan < ATH12K_MIN_6G_FREQ) {
7030*5c1def83SBjoern A. Zeeb channels = kmemdup(ath12k_5ghz_channels,
7031*5c1def83SBjoern A. Zeeb sizeof(ath12k_5ghz_channels),
7032*5c1def83SBjoern A. Zeeb GFP_KERNEL);
7033*5c1def83SBjoern A. Zeeb if (!channels) {
7034*5c1def83SBjoern A. Zeeb kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels);
7035*5c1def83SBjoern A. Zeeb kfree(ar->mac.sbands[NL80211_BAND_6GHZ].channels);
7036*5c1def83SBjoern A. Zeeb return -ENOMEM;
7037*5c1def83SBjoern A. Zeeb }
7038*5c1def83SBjoern A. Zeeb
7039*5c1def83SBjoern A. Zeeb band = &ar->mac.sbands[NL80211_BAND_5GHZ];
7040*5c1def83SBjoern A. Zeeb band->band = NL80211_BAND_5GHZ;
7041*5c1def83SBjoern A. Zeeb band->n_channels = ARRAY_SIZE(ath12k_5ghz_channels);
7042*5c1def83SBjoern A. Zeeb band->channels = channels;
7043*5c1def83SBjoern A. Zeeb band->n_bitrates = ath12k_a_rates_size;
7044*5c1def83SBjoern A. Zeeb band->bitrates = ath12k_a_rates;
7045*5c1def83SBjoern A. Zeeb ar->hw->wiphy->bands[NL80211_BAND_5GHZ] = band;
7046*5c1def83SBjoern A. Zeeb
7047*5c1def83SBjoern A. Zeeb if (ar->ab->hw_params->single_pdev_only) {
7048*5c1def83SBjoern A. Zeeb phy_id = ath12k_get_phy_id(ar, WMI_HOST_WLAN_5G_CAP);
7049*5c1def83SBjoern A. Zeeb reg_cap = &ar->ab->hal_reg_cap[phy_id];
7050*5c1def83SBjoern A. Zeeb }
7051*5c1def83SBjoern A. Zeeb
7052*5c1def83SBjoern A. Zeeb ath12k_mac_update_ch_list(ar, band,
7053*5c1def83SBjoern A. Zeeb reg_cap->low_5ghz_chan,
7054*5c1def83SBjoern A. Zeeb reg_cap->high_5ghz_chan);
7055*5c1def83SBjoern A. Zeeb }
7056*5c1def83SBjoern A. Zeeb }
7057*5c1def83SBjoern A. Zeeb
7058*5c1def83SBjoern A. Zeeb return 0;
7059*5c1def83SBjoern A. Zeeb }
7060*5c1def83SBjoern A. Zeeb
ath12k_mac_setup_iface_combinations(struct ath12k * ar)7061*5c1def83SBjoern A. Zeeb static int ath12k_mac_setup_iface_combinations(struct ath12k *ar)
7062*5c1def83SBjoern A. Zeeb {
7063*5c1def83SBjoern A. Zeeb struct ath12k_base *ab = ar->ab;
7064*5c1def83SBjoern A. Zeeb struct ieee80211_iface_combination *combinations;
7065*5c1def83SBjoern A. Zeeb struct ieee80211_iface_limit *limits;
7066*5c1def83SBjoern A. Zeeb int n_limits, max_interfaces;
7067*5c1def83SBjoern A. Zeeb bool ap, mesh;
7068*5c1def83SBjoern A. Zeeb
7069*5c1def83SBjoern A. Zeeb ap = ab->hw_params->interface_modes & BIT(NL80211_IFTYPE_AP);
7070*5c1def83SBjoern A. Zeeb
7071*5c1def83SBjoern A. Zeeb mesh = IS_ENABLED(CONFIG_MAC80211_MESH) &&
7072*5c1def83SBjoern A. Zeeb ab->hw_params->interface_modes & BIT(NL80211_IFTYPE_MESH_POINT);
7073*5c1def83SBjoern A. Zeeb
7074*5c1def83SBjoern A. Zeeb combinations = kzalloc(sizeof(*combinations), GFP_KERNEL);
7075*5c1def83SBjoern A. Zeeb if (!combinations)
7076*5c1def83SBjoern A. Zeeb return -ENOMEM;
7077*5c1def83SBjoern A. Zeeb
7078*5c1def83SBjoern A. Zeeb if (ap || mesh) {
7079*5c1def83SBjoern A. Zeeb n_limits = 2;
7080*5c1def83SBjoern A. Zeeb max_interfaces = 16;
7081*5c1def83SBjoern A. Zeeb } else {
7082*5c1def83SBjoern A. Zeeb n_limits = 1;
7083*5c1def83SBjoern A. Zeeb max_interfaces = 1;
7084*5c1def83SBjoern A. Zeeb }
7085*5c1def83SBjoern A. Zeeb
7086*5c1def83SBjoern A. Zeeb limits = kcalloc(n_limits, sizeof(*limits), GFP_KERNEL);
7087*5c1def83SBjoern A. Zeeb if (!limits) {
7088*5c1def83SBjoern A. Zeeb kfree(combinations);
7089*5c1def83SBjoern A. Zeeb return -ENOMEM;
7090*5c1def83SBjoern A. Zeeb }
7091*5c1def83SBjoern A. Zeeb
7092*5c1def83SBjoern A. Zeeb limits[0].max = 1;
7093*5c1def83SBjoern A. Zeeb limits[0].types |= BIT(NL80211_IFTYPE_STATION);
7094*5c1def83SBjoern A. Zeeb
7095*5c1def83SBjoern A. Zeeb if (ap) {
7096*5c1def83SBjoern A. Zeeb limits[1].max = max_interfaces;
7097*5c1def83SBjoern A. Zeeb limits[1].types |= BIT(NL80211_IFTYPE_AP);
7098*5c1def83SBjoern A. Zeeb }
7099*5c1def83SBjoern A. Zeeb
7100*5c1def83SBjoern A. Zeeb if (mesh)
7101*5c1def83SBjoern A. Zeeb limits[1].types |= BIT(NL80211_IFTYPE_MESH_POINT);
7102*5c1def83SBjoern A. Zeeb
7103*5c1def83SBjoern A. Zeeb combinations[0].limits = limits;
7104*5c1def83SBjoern A. Zeeb combinations[0].n_limits = n_limits;
7105*5c1def83SBjoern A. Zeeb combinations[0].max_interfaces = max_interfaces;
7106*5c1def83SBjoern A. Zeeb combinations[0].num_different_channels = 1;
7107*5c1def83SBjoern A. Zeeb combinations[0].beacon_int_infra_match = true;
7108*5c1def83SBjoern A. Zeeb combinations[0].beacon_int_min_gcd = 100;
7109*5c1def83SBjoern A. Zeeb combinations[0].radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |
7110*5c1def83SBjoern A. Zeeb BIT(NL80211_CHAN_WIDTH_20) |
7111*5c1def83SBjoern A. Zeeb BIT(NL80211_CHAN_WIDTH_40) |
7112*5c1def83SBjoern A. Zeeb BIT(NL80211_CHAN_WIDTH_80);
7113*5c1def83SBjoern A. Zeeb
7114*5c1def83SBjoern A. Zeeb ar->hw->wiphy->iface_combinations = combinations;
7115*5c1def83SBjoern A. Zeeb ar->hw->wiphy->n_iface_combinations = 1;
7116*5c1def83SBjoern A. Zeeb
7117*5c1def83SBjoern A. Zeeb return 0;
7118*5c1def83SBjoern A. Zeeb }
7119*5c1def83SBjoern A. Zeeb
7120*5c1def83SBjoern A. Zeeb static const u8 ath12k_if_types_ext_capa[] = {
7121*5c1def83SBjoern A. Zeeb [0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
7122*5c1def83SBjoern A. Zeeb [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
7123*5c1def83SBjoern A. Zeeb };
7124*5c1def83SBjoern A. Zeeb
7125*5c1def83SBjoern A. Zeeb static const u8 ath12k_if_types_ext_capa_sta[] = {
7126*5c1def83SBjoern A. Zeeb [0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
7127*5c1def83SBjoern A. Zeeb [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
7128*5c1def83SBjoern A. Zeeb [9] = WLAN_EXT_CAPA10_TWT_REQUESTER_SUPPORT,
7129*5c1def83SBjoern A. Zeeb };
7130*5c1def83SBjoern A. Zeeb
7131*5c1def83SBjoern A. Zeeb static const u8 ath12k_if_types_ext_capa_ap[] = {
7132*5c1def83SBjoern A. Zeeb [0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
7133*5c1def83SBjoern A. Zeeb [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
7134*5c1def83SBjoern A. Zeeb [9] = WLAN_EXT_CAPA10_TWT_RESPONDER_SUPPORT,
7135*5c1def83SBjoern A. Zeeb };
7136*5c1def83SBjoern A. Zeeb
7137*5c1def83SBjoern A. Zeeb static const struct wiphy_iftype_ext_capab ath12k_iftypes_ext_capa[] = {
7138*5c1def83SBjoern A. Zeeb {
7139*5c1def83SBjoern A. Zeeb .extended_capabilities = ath12k_if_types_ext_capa,
7140*5c1def83SBjoern A. Zeeb .extended_capabilities_mask = ath12k_if_types_ext_capa,
7141*5c1def83SBjoern A. Zeeb .extended_capabilities_len = sizeof(ath12k_if_types_ext_capa),
7142*5c1def83SBjoern A. Zeeb }, {
7143*5c1def83SBjoern A. Zeeb .iftype = NL80211_IFTYPE_STATION,
7144*5c1def83SBjoern A. Zeeb .extended_capabilities = ath12k_if_types_ext_capa_sta,
7145*5c1def83SBjoern A. Zeeb .extended_capabilities_mask = ath12k_if_types_ext_capa_sta,
7146*5c1def83SBjoern A. Zeeb .extended_capabilities_len =
7147*5c1def83SBjoern A. Zeeb sizeof(ath12k_if_types_ext_capa_sta),
7148*5c1def83SBjoern A. Zeeb }, {
7149*5c1def83SBjoern A. Zeeb .iftype = NL80211_IFTYPE_AP,
7150*5c1def83SBjoern A. Zeeb .extended_capabilities = ath12k_if_types_ext_capa_ap,
7151*5c1def83SBjoern A. Zeeb .extended_capabilities_mask = ath12k_if_types_ext_capa_ap,
7152*5c1def83SBjoern A. Zeeb .extended_capabilities_len =
7153*5c1def83SBjoern A. Zeeb sizeof(ath12k_if_types_ext_capa_ap),
7154*5c1def83SBjoern A. Zeeb },
7155*5c1def83SBjoern A. Zeeb };
7156*5c1def83SBjoern A. Zeeb
__ath12k_mac_unregister(struct ath12k * ar)7157*5c1def83SBjoern A. Zeeb static void __ath12k_mac_unregister(struct ath12k *ar)
7158*5c1def83SBjoern A. Zeeb {
7159*5c1def83SBjoern A. Zeeb cancel_work_sync(&ar->regd_update_work);
7160*5c1def83SBjoern A. Zeeb
7161*5c1def83SBjoern A. Zeeb ieee80211_unregister_hw(ar->hw);
7162*5c1def83SBjoern A. Zeeb
7163*5c1def83SBjoern A. Zeeb idr_for_each(&ar->txmgmt_idr, ath12k_mac_tx_mgmt_pending_free, ar);
7164*5c1def83SBjoern A. Zeeb idr_destroy(&ar->txmgmt_idr);
7165*5c1def83SBjoern A. Zeeb
7166*5c1def83SBjoern A. Zeeb kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels);
7167*5c1def83SBjoern A. Zeeb kfree(ar->mac.sbands[NL80211_BAND_5GHZ].channels);
7168*5c1def83SBjoern A. Zeeb kfree(ar->mac.sbands[NL80211_BAND_6GHZ].channels);
7169*5c1def83SBjoern A. Zeeb
7170*5c1def83SBjoern A. Zeeb kfree(ar->hw->wiphy->iface_combinations[0].limits);
7171*5c1def83SBjoern A. Zeeb kfree(ar->hw->wiphy->iface_combinations);
7172*5c1def83SBjoern A. Zeeb
7173*5c1def83SBjoern A. Zeeb SET_IEEE80211_DEV(ar->hw, NULL);
7174*5c1def83SBjoern A. Zeeb }
7175*5c1def83SBjoern A. Zeeb
ath12k_mac_unregister(struct ath12k_base * ab)7176*5c1def83SBjoern A. Zeeb void ath12k_mac_unregister(struct ath12k_base *ab)
7177*5c1def83SBjoern A. Zeeb {
7178*5c1def83SBjoern A. Zeeb struct ath12k *ar;
7179*5c1def83SBjoern A. Zeeb struct ath12k_pdev *pdev;
7180*5c1def83SBjoern A. Zeeb int i;
7181*5c1def83SBjoern A. Zeeb
7182*5c1def83SBjoern A. Zeeb for (i = 0; i < ab->num_radios; i++) {
7183*5c1def83SBjoern A. Zeeb pdev = &ab->pdevs[i];
7184*5c1def83SBjoern A. Zeeb ar = pdev->ar;
7185*5c1def83SBjoern A. Zeeb if (!ar)
7186*5c1def83SBjoern A. Zeeb continue;
7187*5c1def83SBjoern A. Zeeb
7188*5c1def83SBjoern A. Zeeb __ath12k_mac_unregister(ar);
7189*5c1def83SBjoern A. Zeeb }
7190*5c1def83SBjoern A. Zeeb }
7191*5c1def83SBjoern A. Zeeb
__ath12k_mac_register(struct ath12k * ar)7192*5c1def83SBjoern A. Zeeb static int __ath12k_mac_register(struct ath12k *ar)
7193*5c1def83SBjoern A. Zeeb {
7194*5c1def83SBjoern A. Zeeb struct ath12k_base *ab = ar->ab;
7195*5c1def83SBjoern A. Zeeb struct ath12k_pdev_cap *cap = &ar->pdev->cap;
7196*5c1def83SBjoern A. Zeeb static const u32 cipher_suites[] = {
7197*5c1def83SBjoern A. Zeeb WLAN_CIPHER_SUITE_TKIP,
7198*5c1def83SBjoern A. Zeeb WLAN_CIPHER_SUITE_CCMP,
7199*5c1def83SBjoern A. Zeeb WLAN_CIPHER_SUITE_AES_CMAC,
7200*5c1def83SBjoern A. Zeeb WLAN_CIPHER_SUITE_BIP_CMAC_256,
7201*5c1def83SBjoern A. Zeeb WLAN_CIPHER_SUITE_BIP_GMAC_128,
7202*5c1def83SBjoern A. Zeeb WLAN_CIPHER_SUITE_BIP_GMAC_256,
7203*5c1def83SBjoern A. Zeeb WLAN_CIPHER_SUITE_GCMP,
7204*5c1def83SBjoern A. Zeeb WLAN_CIPHER_SUITE_GCMP_256,
7205*5c1def83SBjoern A. Zeeb WLAN_CIPHER_SUITE_CCMP_256,
7206*5c1def83SBjoern A. Zeeb };
7207*5c1def83SBjoern A. Zeeb int ret;
7208*5c1def83SBjoern A. Zeeb u32 ht_cap = 0;
7209*5c1def83SBjoern A. Zeeb
7210*5c1def83SBjoern A. Zeeb ath12k_pdev_caps_update(ar);
7211*5c1def83SBjoern A. Zeeb
7212*5c1def83SBjoern A. Zeeb SET_IEEE80211_PERM_ADDR(ar->hw, ar->mac_addr);
7213*5c1def83SBjoern A. Zeeb
7214*5c1def83SBjoern A. Zeeb SET_IEEE80211_DEV(ar->hw, ab->dev);
7215*5c1def83SBjoern A. Zeeb
7216*5c1def83SBjoern A. Zeeb ret = ath12k_mac_setup_channels_rates(ar,
7217*5c1def83SBjoern A. Zeeb cap->supported_bands);
7218*5c1def83SBjoern A. Zeeb if (ret)
7219*5c1def83SBjoern A. Zeeb goto err;
7220*5c1def83SBjoern A. Zeeb
7221*5c1def83SBjoern A. Zeeb ath12k_mac_setup_ht_vht_cap(ar, cap, &ht_cap);
7222*5c1def83SBjoern A. Zeeb ath12k_mac_setup_sband_iftype_data(ar, cap);
7223*5c1def83SBjoern A. Zeeb
7224*5c1def83SBjoern A. Zeeb ret = ath12k_mac_setup_iface_combinations(ar);
7225*5c1def83SBjoern A. Zeeb if (ret) {
7226*5c1def83SBjoern A. Zeeb ath12k_err(ar->ab, "failed to setup interface combinations: %d\n", ret);
7227*5c1def83SBjoern A. Zeeb goto err_free_channels;
7228*5c1def83SBjoern A. Zeeb }
7229*5c1def83SBjoern A. Zeeb
7230*5c1def83SBjoern A. Zeeb ar->hw->wiphy->available_antennas_rx = cap->rx_chain_mask;
7231*5c1def83SBjoern A. Zeeb ar->hw->wiphy->available_antennas_tx = cap->tx_chain_mask;
7232*5c1def83SBjoern A. Zeeb
7233*5c1def83SBjoern A. Zeeb ar->hw->wiphy->interface_modes = ab->hw_params->interface_modes;
7234*5c1def83SBjoern A. Zeeb
7235*5c1def83SBjoern A. Zeeb ieee80211_hw_set(ar->hw, SIGNAL_DBM);
7236*5c1def83SBjoern A. Zeeb ieee80211_hw_set(ar->hw, SUPPORTS_PS);
7237*5c1def83SBjoern A. Zeeb ieee80211_hw_set(ar->hw, SUPPORTS_DYNAMIC_PS);
7238*5c1def83SBjoern A. Zeeb ieee80211_hw_set(ar->hw, MFP_CAPABLE);
7239*5c1def83SBjoern A. Zeeb ieee80211_hw_set(ar->hw, REPORTS_TX_ACK_STATUS);
7240*5c1def83SBjoern A. Zeeb ieee80211_hw_set(ar->hw, HAS_RATE_CONTROL);
7241*5c1def83SBjoern A. Zeeb ieee80211_hw_set(ar->hw, AP_LINK_PS);
7242*5c1def83SBjoern A. Zeeb ieee80211_hw_set(ar->hw, SPECTRUM_MGMT);
7243*5c1def83SBjoern A. Zeeb ieee80211_hw_set(ar->hw, CONNECTION_MONITOR);
7244*5c1def83SBjoern A. Zeeb ieee80211_hw_set(ar->hw, SUPPORTS_PER_STA_GTK);
7245*5c1def83SBjoern A. Zeeb ieee80211_hw_set(ar->hw, CHANCTX_STA_CSA);
7246*5c1def83SBjoern A. Zeeb ieee80211_hw_set(ar->hw, QUEUE_CONTROL);
7247*5c1def83SBjoern A. Zeeb ieee80211_hw_set(ar->hw, SUPPORTS_TX_FRAG);
7248*5c1def83SBjoern A. Zeeb ieee80211_hw_set(ar->hw, REPORTS_LOW_ACK);
7249*5c1def83SBjoern A. Zeeb
7250*5c1def83SBjoern A. Zeeb if (ht_cap & WMI_HT_CAP_ENABLED) {
7251*5c1def83SBjoern A. Zeeb ieee80211_hw_set(ar->hw, AMPDU_AGGREGATION);
7252*5c1def83SBjoern A. Zeeb ieee80211_hw_set(ar->hw, TX_AMPDU_SETUP_IN_HW);
7253*5c1def83SBjoern A. Zeeb ieee80211_hw_set(ar->hw, SUPPORTS_REORDERING_BUFFER);
7254*5c1def83SBjoern A. Zeeb ieee80211_hw_set(ar->hw, SUPPORTS_AMSDU_IN_AMPDU);
7255*5c1def83SBjoern A. Zeeb ieee80211_hw_set(ar->hw, USES_RSS);
7256*5c1def83SBjoern A. Zeeb }
7257*5c1def83SBjoern A. Zeeb
7258*5c1def83SBjoern A. Zeeb ar->hw->wiphy->features |= NL80211_FEATURE_STATIC_SMPS;
7259*5c1def83SBjoern A. Zeeb ar->hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
7260*5c1def83SBjoern A. Zeeb
7261*5c1def83SBjoern A. Zeeb /* TODO: Check if HT capability advertised from firmware is different
7262*5c1def83SBjoern A. Zeeb * for each band for a dual band capable radio. It will be tricky to
7263*5c1def83SBjoern A. Zeeb * handle it when the ht capability different for each band.
7264*5c1def83SBjoern A. Zeeb */
7265*5c1def83SBjoern A. Zeeb if (ht_cap & WMI_HT_CAP_DYNAMIC_SMPS)
7266*5c1def83SBjoern A. Zeeb ar->hw->wiphy->features |= NL80211_FEATURE_DYNAMIC_SMPS;
7267*5c1def83SBjoern A. Zeeb
7268*5c1def83SBjoern A. Zeeb ar->hw->wiphy->max_scan_ssids = WLAN_SCAN_PARAMS_MAX_SSID;
7269*5c1def83SBjoern A. Zeeb ar->hw->wiphy->max_scan_ie_len = WLAN_SCAN_PARAMS_MAX_IE_LEN;
7270*5c1def83SBjoern A. Zeeb
7271*5c1def83SBjoern A. Zeeb ar->hw->max_listen_interval = ATH12K_MAX_HW_LISTEN_INTERVAL;
7272*5c1def83SBjoern A. Zeeb
7273*5c1def83SBjoern A. Zeeb ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
7274*5c1def83SBjoern A. Zeeb ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
7275*5c1def83SBjoern A. Zeeb ar->hw->wiphy->max_remain_on_channel_duration = 5000;
7276*5c1def83SBjoern A. Zeeb
7277*5c1def83SBjoern A. Zeeb ar->hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
7278*5c1def83SBjoern A. Zeeb ar->hw->wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE |
7279*5c1def83SBjoern A. Zeeb NL80211_FEATURE_AP_SCAN;
7280*5c1def83SBjoern A. Zeeb
7281*5c1def83SBjoern A. Zeeb ar->max_num_stations = TARGET_NUM_STATIONS;
7282*5c1def83SBjoern A. Zeeb ar->max_num_peers = TARGET_NUM_PEERS_PDEV;
7283*5c1def83SBjoern A. Zeeb
7284*5c1def83SBjoern A. Zeeb ar->hw->wiphy->max_ap_assoc_sta = ar->max_num_stations;
7285*5c1def83SBjoern A. Zeeb
7286*5c1def83SBjoern A. Zeeb ar->hw->queues = ATH12K_HW_MAX_QUEUES;
7287*5c1def83SBjoern A. Zeeb ar->hw->wiphy->tx_queue_len = ATH12K_QUEUE_LEN;
7288*5c1def83SBjoern A. Zeeb ar->hw->offchannel_tx_hw_queue = ATH12K_HW_MAX_QUEUES - 1;
7289*5c1def83SBjoern A. Zeeb ar->hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE;
7290*5c1def83SBjoern A. Zeeb
7291*5c1def83SBjoern A. Zeeb ar->hw->vif_data_size = sizeof(struct ath12k_vif);
7292*5c1def83SBjoern A. Zeeb ar->hw->sta_data_size = sizeof(struct ath12k_sta);
7293*5c1def83SBjoern A. Zeeb
7294*5c1def83SBjoern A. Zeeb wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
7295*5c1def83SBjoern A. Zeeb wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_STA_TX_PWR);
7296*5c1def83SBjoern A. Zeeb
7297*5c1def83SBjoern A. Zeeb ar->hw->wiphy->cipher_suites = cipher_suites;
7298*5c1def83SBjoern A. Zeeb ar->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
7299*5c1def83SBjoern A. Zeeb
7300*5c1def83SBjoern A. Zeeb ar->hw->wiphy->iftype_ext_capab = ath12k_iftypes_ext_capa;
7301*5c1def83SBjoern A. Zeeb ar->hw->wiphy->num_iftype_ext_capab =
7302*5c1def83SBjoern A. Zeeb ARRAY_SIZE(ath12k_iftypes_ext_capa);
7303*5c1def83SBjoern A. Zeeb
7304*5c1def83SBjoern A. Zeeb if (ar->supports_6ghz) {
7305*5c1def83SBjoern A. Zeeb wiphy_ext_feature_set(ar->hw->wiphy,
7306*5c1def83SBjoern A. Zeeb NL80211_EXT_FEATURE_FILS_DISCOVERY);
7307*5c1def83SBjoern A. Zeeb wiphy_ext_feature_set(ar->hw->wiphy,
7308*5c1def83SBjoern A. Zeeb NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP);
7309*5c1def83SBjoern A. Zeeb }
7310*5c1def83SBjoern A. Zeeb
7311*5c1def83SBjoern A. Zeeb wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_PUNCT);
7312*5c1def83SBjoern A. Zeeb
7313*5c1def83SBjoern A. Zeeb ath12k_reg_init(ar);
7314*5c1def83SBjoern A. Zeeb
7315*5c1def83SBjoern A. Zeeb if (!test_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags)) {
7316*5c1def83SBjoern A. Zeeb ar->hw->netdev_features = NETIF_F_HW_CSUM;
7317*5c1def83SBjoern A. Zeeb ieee80211_hw_set(ar->hw, SW_CRYPTO_CONTROL);
7318*5c1def83SBjoern A. Zeeb ieee80211_hw_set(ar->hw, SUPPORT_FAST_XMIT);
7319*5c1def83SBjoern A. Zeeb }
7320*5c1def83SBjoern A. Zeeb
7321*5c1def83SBjoern A. Zeeb ret = ieee80211_register_hw(ar->hw);
7322*5c1def83SBjoern A. Zeeb if (ret) {
7323*5c1def83SBjoern A. Zeeb ath12k_err(ar->ab, "ieee80211 registration failed: %d\n", ret);
7324*5c1def83SBjoern A. Zeeb goto err_free_if_combs;
7325*5c1def83SBjoern A. Zeeb }
7326*5c1def83SBjoern A. Zeeb
7327*5c1def83SBjoern A. Zeeb if (!ab->hw_params->supports_monitor)
7328*5c1def83SBjoern A. Zeeb /* There's a race between calling ieee80211_register_hw()
7329*5c1def83SBjoern A. Zeeb * and here where the monitor mode is enabled for a little
7330*5c1def83SBjoern A. Zeeb * while. But that time is so short and in practise it make
7331*5c1def83SBjoern A. Zeeb * a difference in real life.
7332*5c1def83SBjoern A. Zeeb */
7333*5c1def83SBjoern A. Zeeb ar->hw->wiphy->interface_modes &= ~BIT(NL80211_IFTYPE_MONITOR);
7334*5c1def83SBjoern A. Zeeb
7335*5c1def83SBjoern A. Zeeb /* Apply the regd received during initialization */
7336*5c1def83SBjoern A. Zeeb ret = ath12k_regd_update(ar, true);
7337*5c1def83SBjoern A. Zeeb if (ret) {
7338*5c1def83SBjoern A. Zeeb ath12k_err(ar->ab, "ath12k regd update failed: %d\n", ret);
7339*5c1def83SBjoern A. Zeeb goto err_unregister_hw;
7340*5c1def83SBjoern A. Zeeb }
7341*5c1def83SBjoern A. Zeeb
7342*5c1def83SBjoern A. Zeeb return 0;
7343*5c1def83SBjoern A. Zeeb
7344*5c1def83SBjoern A. Zeeb err_unregister_hw:
7345*5c1def83SBjoern A. Zeeb ieee80211_unregister_hw(ar->hw);
7346*5c1def83SBjoern A. Zeeb
7347*5c1def83SBjoern A. Zeeb err_free_if_combs:
7348*5c1def83SBjoern A. Zeeb kfree(ar->hw->wiphy->iface_combinations[0].limits);
7349*5c1def83SBjoern A. Zeeb kfree(ar->hw->wiphy->iface_combinations);
7350*5c1def83SBjoern A. Zeeb
7351*5c1def83SBjoern A. Zeeb err_free_channels:
7352*5c1def83SBjoern A. Zeeb kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels);
7353*5c1def83SBjoern A. Zeeb kfree(ar->mac.sbands[NL80211_BAND_5GHZ].channels);
7354*5c1def83SBjoern A. Zeeb kfree(ar->mac.sbands[NL80211_BAND_6GHZ].channels);
7355*5c1def83SBjoern A. Zeeb
7356*5c1def83SBjoern A. Zeeb err:
7357*5c1def83SBjoern A. Zeeb SET_IEEE80211_DEV(ar->hw, NULL);
7358*5c1def83SBjoern A. Zeeb return ret;
7359*5c1def83SBjoern A. Zeeb }
7360*5c1def83SBjoern A. Zeeb
ath12k_mac_register(struct ath12k_base * ab)7361*5c1def83SBjoern A. Zeeb int ath12k_mac_register(struct ath12k_base *ab)
7362*5c1def83SBjoern A. Zeeb {
7363*5c1def83SBjoern A. Zeeb struct ath12k *ar;
7364*5c1def83SBjoern A. Zeeb struct ath12k_pdev *pdev;
7365*5c1def83SBjoern A. Zeeb int i;
7366*5c1def83SBjoern A. Zeeb int ret;
7367*5c1def83SBjoern A. Zeeb
7368*5c1def83SBjoern A. Zeeb if (test_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags))
7369*5c1def83SBjoern A. Zeeb return 0;
7370*5c1def83SBjoern A. Zeeb
7371*5c1def83SBjoern A. Zeeb for (i = 0; i < ab->num_radios; i++) {
7372*5c1def83SBjoern A. Zeeb pdev = &ab->pdevs[i];
7373*5c1def83SBjoern A. Zeeb ar = pdev->ar;
7374*5c1def83SBjoern A. Zeeb if (ab->pdevs_macaddr_valid) {
7375*5c1def83SBjoern A. Zeeb ether_addr_copy(ar->mac_addr, pdev->mac_addr);
7376*5c1def83SBjoern A. Zeeb } else {
7377*5c1def83SBjoern A. Zeeb ether_addr_copy(ar->mac_addr, ab->mac_addr);
7378*5c1def83SBjoern A. Zeeb ar->mac_addr[4] += i;
7379*5c1def83SBjoern A. Zeeb }
7380*5c1def83SBjoern A. Zeeb
7381*5c1def83SBjoern A. Zeeb ret = __ath12k_mac_register(ar);
7382*5c1def83SBjoern A. Zeeb if (ret)
7383*5c1def83SBjoern A. Zeeb goto err_cleanup;
7384*5c1def83SBjoern A. Zeeb
7385*5c1def83SBjoern A. Zeeb init_waitqueue_head(&ar->txmgmt_empty_waitq);
7386*5c1def83SBjoern A. Zeeb idr_init(&ar->txmgmt_idr);
7387*5c1def83SBjoern A. Zeeb spin_lock_init(&ar->txmgmt_idr_lock);
7388*5c1def83SBjoern A. Zeeb }
7389*5c1def83SBjoern A. Zeeb
7390*5c1def83SBjoern A. Zeeb /* Initialize channel counters frequency value in hertz */
7391*5c1def83SBjoern A. Zeeb ab->cc_freq_hz = 320000;
7392*5c1def83SBjoern A. Zeeb ab->free_vdev_map = (1LL << (ab->num_radios * TARGET_NUM_VDEVS)) - 1;
7393*5c1def83SBjoern A. Zeeb
7394*5c1def83SBjoern A. Zeeb return 0;
7395*5c1def83SBjoern A. Zeeb
7396*5c1def83SBjoern A. Zeeb err_cleanup:
7397*5c1def83SBjoern A. Zeeb for (i = i - 1; i >= 0; i--) {
7398*5c1def83SBjoern A. Zeeb pdev = &ab->pdevs[i];
7399*5c1def83SBjoern A. Zeeb ar = pdev->ar;
7400*5c1def83SBjoern A. Zeeb __ath12k_mac_unregister(ar);
7401*5c1def83SBjoern A. Zeeb }
7402*5c1def83SBjoern A. Zeeb
7403*5c1def83SBjoern A. Zeeb return ret;
7404*5c1def83SBjoern A. Zeeb }
7405*5c1def83SBjoern A. Zeeb
ath12k_mac_allocate(struct ath12k_base * ab)7406*5c1def83SBjoern A. Zeeb int ath12k_mac_allocate(struct ath12k_base *ab)
7407*5c1def83SBjoern A. Zeeb {
7408*5c1def83SBjoern A. Zeeb struct ieee80211_hw *hw;
7409*5c1def83SBjoern A. Zeeb struct ath12k *ar;
7410*5c1def83SBjoern A. Zeeb struct ath12k_pdev *pdev;
7411*5c1def83SBjoern A. Zeeb int ret;
7412*5c1def83SBjoern A. Zeeb int i;
7413*5c1def83SBjoern A. Zeeb
7414*5c1def83SBjoern A. Zeeb if (test_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags))
7415*5c1def83SBjoern A. Zeeb return 0;
7416*5c1def83SBjoern A. Zeeb
7417*5c1def83SBjoern A. Zeeb for (i = 0; i < ab->num_radios; i++) {
7418*5c1def83SBjoern A. Zeeb pdev = &ab->pdevs[i];
7419*5c1def83SBjoern A. Zeeb hw = ieee80211_alloc_hw(sizeof(struct ath12k), &ath12k_ops);
7420*5c1def83SBjoern A. Zeeb if (!hw) {
7421*5c1def83SBjoern A. Zeeb ath12k_warn(ab, "failed to allocate mac80211 hw device\n");
7422*5c1def83SBjoern A. Zeeb ret = -ENOMEM;
7423*5c1def83SBjoern A. Zeeb goto err_free_mac;
7424*5c1def83SBjoern A. Zeeb }
7425*5c1def83SBjoern A. Zeeb
7426*5c1def83SBjoern A. Zeeb ar = hw->priv;
7427*5c1def83SBjoern A. Zeeb ar->hw = hw;
7428*5c1def83SBjoern A. Zeeb ar->ab = ab;
7429*5c1def83SBjoern A. Zeeb ar->pdev = pdev;
7430*5c1def83SBjoern A. Zeeb ar->pdev_idx = i;
7431*5c1def83SBjoern A. Zeeb ar->lmac_id = ath12k_hw_get_mac_from_pdev_id(ab->hw_params, i);
7432*5c1def83SBjoern A. Zeeb
7433*5c1def83SBjoern A. Zeeb ar->wmi = &ab->wmi_ab.wmi[i];
7434*5c1def83SBjoern A. Zeeb /* FIXME: wmi[0] is already initialized during attach,
7435*5c1def83SBjoern A. Zeeb * Should we do this again?
7436*5c1def83SBjoern A. Zeeb */
7437*5c1def83SBjoern A. Zeeb ath12k_wmi_pdev_attach(ab, i);
7438*5c1def83SBjoern A. Zeeb
7439*5c1def83SBjoern A. Zeeb ar->cfg_tx_chainmask = pdev->cap.tx_chain_mask;
7440*5c1def83SBjoern A. Zeeb ar->cfg_rx_chainmask = pdev->cap.rx_chain_mask;
7441*5c1def83SBjoern A. Zeeb ar->num_tx_chains = hweight32(pdev->cap.tx_chain_mask);
7442*5c1def83SBjoern A. Zeeb ar->num_rx_chains = hweight32(pdev->cap.rx_chain_mask);
7443*5c1def83SBjoern A. Zeeb
7444*5c1def83SBjoern A. Zeeb pdev->ar = ar;
7445*5c1def83SBjoern A. Zeeb spin_lock_init(&ar->data_lock);
7446*5c1def83SBjoern A. Zeeb INIT_LIST_HEAD(&ar->arvifs);
7447*5c1def83SBjoern A. Zeeb INIT_LIST_HEAD(&ar->ppdu_stats_info);
7448*5c1def83SBjoern A. Zeeb mutex_init(&ar->conf_mutex);
7449*5c1def83SBjoern A. Zeeb init_completion(&ar->vdev_setup_done);
7450*5c1def83SBjoern A. Zeeb init_completion(&ar->vdev_delete_done);
7451*5c1def83SBjoern A. Zeeb init_completion(&ar->peer_assoc_done);
7452*5c1def83SBjoern A. Zeeb init_completion(&ar->peer_delete_done);
7453*5c1def83SBjoern A. Zeeb init_completion(&ar->install_key_done);
7454*5c1def83SBjoern A. Zeeb init_completion(&ar->bss_survey_done);
7455*5c1def83SBjoern A. Zeeb init_completion(&ar->scan.started);
7456*5c1def83SBjoern A. Zeeb init_completion(&ar->scan.completed);
7457*5c1def83SBjoern A. Zeeb
7458*5c1def83SBjoern A. Zeeb INIT_DELAYED_WORK(&ar->scan.timeout, ath12k_scan_timeout_work);
7459*5c1def83SBjoern A. Zeeb INIT_WORK(&ar->regd_update_work, ath12k_regd_update_work);
7460*5c1def83SBjoern A. Zeeb
7461*5c1def83SBjoern A. Zeeb INIT_WORK(&ar->wmi_mgmt_tx_work, ath12k_mgmt_over_wmi_tx_work);
7462*5c1def83SBjoern A. Zeeb skb_queue_head_init(&ar->wmi_mgmt_tx_queue);
7463*5c1def83SBjoern A. Zeeb clear_bit(ATH12K_FLAG_MONITOR_ENABLED, &ar->monitor_flags);
7464*5c1def83SBjoern A. Zeeb }
7465*5c1def83SBjoern A. Zeeb
7466*5c1def83SBjoern A. Zeeb return 0;
7467*5c1def83SBjoern A. Zeeb
7468*5c1def83SBjoern A. Zeeb err_free_mac:
7469*5c1def83SBjoern A. Zeeb ath12k_mac_destroy(ab);
7470*5c1def83SBjoern A. Zeeb
7471*5c1def83SBjoern A. Zeeb return ret;
7472*5c1def83SBjoern A. Zeeb }
7473*5c1def83SBjoern A. Zeeb
ath12k_mac_destroy(struct ath12k_base * ab)7474*5c1def83SBjoern A. Zeeb void ath12k_mac_destroy(struct ath12k_base *ab)
7475*5c1def83SBjoern A. Zeeb {
7476*5c1def83SBjoern A. Zeeb struct ath12k *ar;
7477*5c1def83SBjoern A. Zeeb struct ath12k_pdev *pdev;
7478*5c1def83SBjoern A. Zeeb int i;
7479*5c1def83SBjoern A. Zeeb
7480*5c1def83SBjoern A. Zeeb for (i = 0; i < ab->num_radios; i++) {
7481*5c1def83SBjoern A. Zeeb pdev = &ab->pdevs[i];
7482*5c1def83SBjoern A. Zeeb ar = pdev->ar;
7483*5c1def83SBjoern A. Zeeb if (!ar)
7484*5c1def83SBjoern A. Zeeb continue;
7485*5c1def83SBjoern A. Zeeb
7486*5c1def83SBjoern A. Zeeb ieee80211_free_hw(ar->hw);
7487*5c1def83SBjoern A. Zeeb pdev->ar = NULL;
7488*5c1def83SBjoern A. Zeeb }
7489*5c1def83SBjoern A. Zeeb }
7490