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