1dd4f32aeSBjoern A. Zeeb // SPDX-License-Identifier: BSD-3-Clause-Clear
2dd4f32aeSBjoern A. Zeeb /*
3dd4f32aeSBjoern A. Zeeb * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
428348caeSBjoern A. Zeeb * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
5dd4f32aeSBjoern A. Zeeb */
6dd4f32aeSBjoern A. Zeeb
7dd4f32aeSBjoern A. Zeeb #include <net/mac80211.h>
8dd4f32aeSBjoern A. Zeeb #include <linux/etherdevice.h>
928348caeSBjoern A. Zeeb #include <linux/bitfield.h>
1028348caeSBjoern A. Zeeb #include <linux/inetdevice.h>
1128348caeSBjoern A. Zeeb #include <net/if_inet6.h>
1228348caeSBjoern A. Zeeb #include <net/ipv6.h>
1328348caeSBjoern A. Zeeb
14dd4f32aeSBjoern A. Zeeb #include "mac.h"
15dd4f32aeSBjoern A. Zeeb #include "core.h"
16dd4f32aeSBjoern A. Zeeb #include "debug.h"
17dd4f32aeSBjoern A. Zeeb #include "wmi.h"
18dd4f32aeSBjoern A. Zeeb #include "hw.h"
19dd4f32aeSBjoern A. Zeeb #include "dp_tx.h"
20dd4f32aeSBjoern A. Zeeb #include "dp_rx.h"
21dd4f32aeSBjoern A. Zeeb #include "testmode.h"
22dd4f32aeSBjoern A. Zeeb #include "peer.h"
23dd4f32aeSBjoern A. Zeeb #include "debugfs_sta.h"
2428348caeSBjoern A. Zeeb #include "hif.h"
2528348caeSBjoern A. Zeeb #include "wow.h"
26dd4f32aeSBjoern A. Zeeb
27dd4f32aeSBjoern A. Zeeb #define CHAN2G(_channel, _freq, _flags) { \
28dd4f32aeSBjoern A. Zeeb .band = NL80211_BAND_2GHZ, \
29dd4f32aeSBjoern A. Zeeb .hw_value = (_channel), \
30dd4f32aeSBjoern A. Zeeb .center_freq = (_freq), \
31dd4f32aeSBjoern A. Zeeb .flags = (_flags), \
32dd4f32aeSBjoern A. Zeeb .max_antenna_gain = 0, \
33dd4f32aeSBjoern A. Zeeb .max_power = 30, \
34dd4f32aeSBjoern A. Zeeb }
35dd4f32aeSBjoern A. Zeeb
36dd4f32aeSBjoern A. Zeeb #define CHAN5G(_channel, _freq, _flags) { \
37dd4f32aeSBjoern A. Zeeb .band = NL80211_BAND_5GHZ, \
38dd4f32aeSBjoern A. Zeeb .hw_value = (_channel), \
39dd4f32aeSBjoern A. Zeeb .center_freq = (_freq), \
40dd4f32aeSBjoern A. Zeeb .flags = (_flags), \
41dd4f32aeSBjoern A. Zeeb .max_antenna_gain = 0, \
42dd4f32aeSBjoern A. Zeeb .max_power = 30, \
43dd4f32aeSBjoern A. Zeeb }
44dd4f32aeSBjoern A. Zeeb
45dd4f32aeSBjoern A. Zeeb #define CHAN6G(_channel, _freq, _flags) { \
46dd4f32aeSBjoern A. Zeeb .band = NL80211_BAND_6GHZ, \
47dd4f32aeSBjoern A. Zeeb .hw_value = (_channel), \
48dd4f32aeSBjoern A. Zeeb .center_freq = (_freq), \
49dd4f32aeSBjoern A. Zeeb .flags = (_flags), \
50dd4f32aeSBjoern A. Zeeb .max_antenna_gain = 0, \
51dd4f32aeSBjoern A. Zeeb .max_power = 30, \
52dd4f32aeSBjoern A. Zeeb }
53dd4f32aeSBjoern A. Zeeb
54dd4f32aeSBjoern A. Zeeb static const struct ieee80211_channel ath11k_2ghz_channels[] = {
55dd4f32aeSBjoern A. Zeeb CHAN2G(1, 2412, 0),
56dd4f32aeSBjoern A. Zeeb CHAN2G(2, 2417, 0),
57dd4f32aeSBjoern A. Zeeb CHAN2G(3, 2422, 0),
58dd4f32aeSBjoern A. Zeeb CHAN2G(4, 2427, 0),
59dd4f32aeSBjoern A. Zeeb CHAN2G(5, 2432, 0),
60dd4f32aeSBjoern A. Zeeb CHAN2G(6, 2437, 0),
61dd4f32aeSBjoern A. Zeeb CHAN2G(7, 2442, 0),
62dd4f32aeSBjoern A. Zeeb CHAN2G(8, 2447, 0),
63dd4f32aeSBjoern A. Zeeb CHAN2G(9, 2452, 0),
64dd4f32aeSBjoern A. Zeeb CHAN2G(10, 2457, 0),
65dd4f32aeSBjoern A. Zeeb CHAN2G(11, 2462, 0),
66dd4f32aeSBjoern A. Zeeb CHAN2G(12, 2467, 0),
67dd4f32aeSBjoern A. Zeeb CHAN2G(13, 2472, 0),
68dd4f32aeSBjoern A. Zeeb CHAN2G(14, 2484, 0),
69dd4f32aeSBjoern A. Zeeb };
70dd4f32aeSBjoern A. Zeeb
71dd4f32aeSBjoern A. Zeeb static const struct ieee80211_channel ath11k_5ghz_channels[] = {
72dd4f32aeSBjoern A. Zeeb CHAN5G(36, 5180, 0),
73dd4f32aeSBjoern A. Zeeb CHAN5G(40, 5200, 0),
74dd4f32aeSBjoern A. Zeeb CHAN5G(44, 5220, 0),
75dd4f32aeSBjoern A. Zeeb CHAN5G(48, 5240, 0),
76dd4f32aeSBjoern A. Zeeb CHAN5G(52, 5260, 0),
77dd4f32aeSBjoern A. Zeeb CHAN5G(56, 5280, 0),
78dd4f32aeSBjoern A. Zeeb CHAN5G(60, 5300, 0),
79dd4f32aeSBjoern A. Zeeb CHAN5G(64, 5320, 0),
80dd4f32aeSBjoern A. Zeeb CHAN5G(100, 5500, 0),
81dd4f32aeSBjoern A. Zeeb CHAN5G(104, 5520, 0),
82dd4f32aeSBjoern A. Zeeb CHAN5G(108, 5540, 0),
83dd4f32aeSBjoern A. Zeeb CHAN5G(112, 5560, 0),
84dd4f32aeSBjoern A. Zeeb CHAN5G(116, 5580, 0),
85dd4f32aeSBjoern A. Zeeb CHAN5G(120, 5600, 0),
86dd4f32aeSBjoern A. Zeeb CHAN5G(124, 5620, 0),
87dd4f32aeSBjoern A. Zeeb CHAN5G(128, 5640, 0),
88dd4f32aeSBjoern A. Zeeb CHAN5G(132, 5660, 0),
89dd4f32aeSBjoern A. Zeeb CHAN5G(136, 5680, 0),
90dd4f32aeSBjoern A. Zeeb CHAN5G(140, 5700, 0),
91dd4f32aeSBjoern A. Zeeb CHAN5G(144, 5720, 0),
92dd4f32aeSBjoern A. Zeeb CHAN5G(149, 5745, 0),
93dd4f32aeSBjoern A. Zeeb CHAN5G(153, 5765, 0),
94dd4f32aeSBjoern A. Zeeb CHAN5G(157, 5785, 0),
95dd4f32aeSBjoern A. Zeeb CHAN5G(161, 5805, 0),
96dd4f32aeSBjoern A. Zeeb CHAN5G(165, 5825, 0),
97dd4f32aeSBjoern A. Zeeb CHAN5G(169, 5845, 0),
98dd4f32aeSBjoern A. Zeeb CHAN5G(173, 5865, 0),
9928348caeSBjoern A. Zeeb CHAN5G(177, 5885, 0),
100dd4f32aeSBjoern A. Zeeb };
101dd4f32aeSBjoern A. Zeeb
102dd4f32aeSBjoern A. Zeeb static const struct ieee80211_channel ath11k_6ghz_channels[] = {
103dd4f32aeSBjoern A. Zeeb CHAN6G(1, 5955, 0),
104dd4f32aeSBjoern A. Zeeb CHAN6G(5, 5975, 0),
105dd4f32aeSBjoern A. Zeeb CHAN6G(9, 5995, 0),
106dd4f32aeSBjoern A. Zeeb CHAN6G(13, 6015, 0),
107dd4f32aeSBjoern A. Zeeb CHAN6G(17, 6035, 0),
108dd4f32aeSBjoern A. Zeeb CHAN6G(21, 6055, 0),
109dd4f32aeSBjoern A. Zeeb CHAN6G(25, 6075, 0),
110dd4f32aeSBjoern A. Zeeb CHAN6G(29, 6095, 0),
111dd4f32aeSBjoern A. Zeeb CHAN6G(33, 6115, 0),
112dd4f32aeSBjoern A. Zeeb CHAN6G(37, 6135, 0),
113dd4f32aeSBjoern A. Zeeb CHAN6G(41, 6155, 0),
114dd4f32aeSBjoern A. Zeeb CHAN6G(45, 6175, 0),
115dd4f32aeSBjoern A. Zeeb CHAN6G(49, 6195, 0),
116dd4f32aeSBjoern A. Zeeb CHAN6G(53, 6215, 0),
117dd4f32aeSBjoern A. Zeeb CHAN6G(57, 6235, 0),
118dd4f32aeSBjoern A. Zeeb CHAN6G(61, 6255, 0),
119dd4f32aeSBjoern A. Zeeb CHAN6G(65, 6275, 0),
120dd4f32aeSBjoern A. Zeeb CHAN6G(69, 6295, 0),
121dd4f32aeSBjoern A. Zeeb CHAN6G(73, 6315, 0),
122dd4f32aeSBjoern A. Zeeb CHAN6G(77, 6335, 0),
123dd4f32aeSBjoern A. Zeeb CHAN6G(81, 6355, 0),
124dd4f32aeSBjoern A. Zeeb CHAN6G(85, 6375, 0),
125dd4f32aeSBjoern A. Zeeb CHAN6G(89, 6395, 0),
126dd4f32aeSBjoern A. Zeeb CHAN6G(93, 6415, 0),
127dd4f32aeSBjoern A. Zeeb CHAN6G(97, 6435, 0),
128dd4f32aeSBjoern A. Zeeb CHAN6G(101, 6455, 0),
129dd4f32aeSBjoern A. Zeeb CHAN6G(105, 6475, 0),
130dd4f32aeSBjoern A. Zeeb CHAN6G(109, 6495, 0),
131dd4f32aeSBjoern A. Zeeb CHAN6G(113, 6515, 0),
132dd4f32aeSBjoern A. Zeeb CHAN6G(117, 6535, 0),
133dd4f32aeSBjoern A. Zeeb CHAN6G(121, 6555, 0),
134dd4f32aeSBjoern A. Zeeb CHAN6G(125, 6575, 0),
135dd4f32aeSBjoern A. Zeeb CHAN6G(129, 6595, 0),
136dd4f32aeSBjoern A. Zeeb CHAN6G(133, 6615, 0),
137dd4f32aeSBjoern A. Zeeb CHAN6G(137, 6635, 0),
138dd4f32aeSBjoern A. Zeeb CHAN6G(141, 6655, 0),
139dd4f32aeSBjoern A. Zeeb CHAN6G(145, 6675, 0),
140dd4f32aeSBjoern A. Zeeb CHAN6G(149, 6695, 0),
141dd4f32aeSBjoern A. Zeeb CHAN6G(153, 6715, 0),
142dd4f32aeSBjoern A. Zeeb CHAN6G(157, 6735, 0),
143dd4f32aeSBjoern A. Zeeb CHAN6G(161, 6755, 0),
144dd4f32aeSBjoern A. Zeeb CHAN6G(165, 6775, 0),
145dd4f32aeSBjoern A. Zeeb CHAN6G(169, 6795, 0),
146dd4f32aeSBjoern A. Zeeb CHAN6G(173, 6815, 0),
147dd4f32aeSBjoern A. Zeeb CHAN6G(177, 6835, 0),
148dd4f32aeSBjoern A. Zeeb CHAN6G(181, 6855, 0),
149dd4f32aeSBjoern A. Zeeb CHAN6G(185, 6875, 0),
150dd4f32aeSBjoern A. Zeeb CHAN6G(189, 6895, 0),
151dd4f32aeSBjoern A. Zeeb CHAN6G(193, 6915, 0),
152dd4f32aeSBjoern A. Zeeb CHAN6G(197, 6935, 0),
153dd4f32aeSBjoern A. Zeeb CHAN6G(201, 6955, 0),
154dd4f32aeSBjoern A. Zeeb CHAN6G(205, 6975, 0),
155dd4f32aeSBjoern A. Zeeb CHAN6G(209, 6995, 0),
156dd4f32aeSBjoern A. Zeeb CHAN6G(213, 7015, 0),
157dd4f32aeSBjoern A. Zeeb CHAN6G(217, 7035, 0),
158dd4f32aeSBjoern A. Zeeb CHAN6G(221, 7055, 0),
159dd4f32aeSBjoern A. Zeeb CHAN6G(225, 7075, 0),
160dd4f32aeSBjoern A. Zeeb CHAN6G(229, 7095, 0),
161dd4f32aeSBjoern A. Zeeb CHAN6G(233, 7115, 0),
162dd4f32aeSBjoern A. Zeeb
163dd4f32aeSBjoern A. Zeeb /* new addition in IEEE Std 802.11ax-2021 */
164dd4f32aeSBjoern A. Zeeb CHAN6G(2, 5935, 0),
165dd4f32aeSBjoern A. Zeeb };
166dd4f32aeSBjoern A. Zeeb
167dd4f32aeSBjoern A. Zeeb static struct ieee80211_rate ath11k_legacy_rates[] = {
168dd4f32aeSBjoern A. Zeeb { .bitrate = 10,
169dd4f32aeSBjoern A. Zeeb .hw_value = ATH11K_HW_RATE_CCK_LP_1M },
170dd4f32aeSBjoern A. Zeeb { .bitrate = 20,
171dd4f32aeSBjoern A. Zeeb .hw_value = ATH11K_HW_RATE_CCK_LP_2M,
172dd4f32aeSBjoern A. Zeeb .hw_value_short = ATH11K_HW_RATE_CCK_SP_2M,
173dd4f32aeSBjoern A. Zeeb .flags = IEEE80211_RATE_SHORT_PREAMBLE },
174dd4f32aeSBjoern A. Zeeb { .bitrate = 55,
175dd4f32aeSBjoern A. Zeeb .hw_value = ATH11K_HW_RATE_CCK_LP_5_5M,
176dd4f32aeSBjoern A. Zeeb .hw_value_short = ATH11K_HW_RATE_CCK_SP_5_5M,
177dd4f32aeSBjoern A. Zeeb .flags = IEEE80211_RATE_SHORT_PREAMBLE },
178dd4f32aeSBjoern A. Zeeb { .bitrate = 110,
179dd4f32aeSBjoern A. Zeeb .hw_value = ATH11K_HW_RATE_CCK_LP_11M,
180dd4f32aeSBjoern A. Zeeb .hw_value_short = ATH11K_HW_RATE_CCK_SP_11M,
181dd4f32aeSBjoern A. Zeeb .flags = IEEE80211_RATE_SHORT_PREAMBLE },
182dd4f32aeSBjoern A. Zeeb
183dd4f32aeSBjoern A. Zeeb { .bitrate = 60, .hw_value = ATH11K_HW_RATE_OFDM_6M },
184dd4f32aeSBjoern A. Zeeb { .bitrate = 90, .hw_value = ATH11K_HW_RATE_OFDM_9M },
185dd4f32aeSBjoern A. Zeeb { .bitrate = 120, .hw_value = ATH11K_HW_RATE_OFDM_12M },
186dd4f32aeSBjoern A. Zeeb { .bitrate = 180, .hw_value = ATH11K_HW_RATE_OFDM_18M },
187dd4f32aeSBjoern A. Zeeb { .bitrate = 240, .hw_value = ATH11K_HW_RATE_OFDM_24M },
188dd4f32aeSBjoern A. Zeeb { .bitrate = 360, .hw_value = ATH11K_HW_RATE_OFDM_36M },
189dd4f32aeSBjoern A. Zeeb { .bitrate = 480, .hw_value = ATH11K_HW_RATE_OFDM_48M },
190dd4f32aeSBjoern A. Zeeb { .bitrate = 540, .hw_value = ATH11K_HW_RATE_OFDM_54M },
191dd4f32aeSBjoern A. Zeeb };
192dd4f32aeSBjoern A. Zeeb
193dd4f32aeSBjoern A. Zeeb static const int
194dd4f32aeSBjoern A. Zeeb ath11k_phymodes[NUM_NL80211_BANDS][ATH11K_CHAN_WIDTH_NUM] = {
195dd4f32aeSBjoern A. Zeeb [NL80211_BAND_2GHZ] = {
196dd4f32aeSBjoern A. Zeeb [NL80211_CHAN_WIDTH_5] = MODE_UNKNOWN,
197dd4f32aeSBjoern A. Zeeb [NL80211_CHAN_WIDTH_10] = MODE_UNKNOWN,
198dd4f32aeSBjoern A. Zeeb [NL80211_CHAN_WIDTH_20_NOHT] = MODE_11AX_HE20_2G,
199dd4f32aeSBjoern A. Zeeb [NL80211_CHAN_WIDTH_20] = MODE_11AX_HE20_2G,
200dd4f32aeSBjoern A. Zeeb [NL80211_CHAN_WIDTH_40] = MODE_11AX_HE40_2G,
201dd4f32aeSBjoern A. Zeeb [NL80211_CHAN_WIDTH_80] = MODE_11AX_HE80_2G,
202dd4f32aeSBjoern A. Zeeb [NL80211_CHAN_WIDTH_80P80] = MODE_UNKNOWN,
203dd4f32aeSBjoern A. Zeeb [NL80211_CHAN_WIDTH_160] = MODE_UNKNOWN,
204dd4f32aeSBjoern A. Zeeb },
205dd4f32aeSBjoern A. Zeeb [NL80211_BAND_5GHZ] = {
206dd4f32aeSBjoern A. Zeeb [NL80211_CHAN_WIDTH_5] = MODE_UNKNOWN,
207dd4f32aeSBjoern A. Zeeb [NL80211_CHAN_WIDTH_10] = MODE_UNKNOWN,
208dd4f32aeSBjoern A. Zeeb [NL80211_CHAN_WIDTH_20_NOHT] = MODE_11AX_HE20,
209dd4f32aeSBjoern A. Zeeb [NL80211_CHAN_WIDTH_20] = MODE_11AX_HE20,
210dd4f32aeSBjoern A. Zeeb [NL80211_CHAN_WIDTH_40] = MODE_11AX_HE40,
211dd4f32aeSBjoern A. Zeeb [NL80211_CHAN_WIDTH_80] = MODE_11AX_HE80,
212dd4f32aeSBjoern A. Zeeb [NL80211_CHAN_WIDTH_160] = MODE_11AX_HE160,
213dd4f32aeSBjoern A. Zeeb [NL80211_CHAN_WIDTH_80P80] = MODE_11AX_HE80_80,
214dd4f32aeSBjoern A. Zeeb },
215dd4f32aeSBjoern A. Zeeb [NL80211_BAND_6GHZ] = {
216dd4f32aeSBjoern A. Zeeb [NL80211_CHAN_WIDTH_5] = MODE_UNKNOWN,
217dd4f32aeSBjoern A. Zeeb [NL80211_CHAN_WIDTH_10] = MODE_UNKNOWN,
218dd4f32aeSBjoern A. Zeeb [NL80211_CHAN_WIDTH_20_NOHT] = MODE_11AX_HE20,
219dd4f32aeSBjoern A. Zeeb [NL80211_CHAN_WIDTH_20] = MODE_11AX_HE20,
220dd4f32aeSBjoern A. Zeeb [NL80211_CHAN_WIDTH_40] = MODE_11AX_HE40,
221dd4f32aeSBjoern A. Zeeb [NL80211_CHAN_WIDTH_80] = MODE_11AX_HE80,
222dd4f32aeSBjoern A. Zeeb [NL80211_CHAN_WIDTH_160] = MODE_11AX_HE160,
223dd4f32aeSBjoern A. Zeeb [NL80211_CHAN_WIDTH_80P80] = MODE_11AX_HE80_80,
224dd4f32aeSBjoern A. Zeeb },
225dd4f32aeSBjoern A. Zeeb
226dd4f32aeSBjoern A. Zeeb };
227dd4f32aeSBjoern A. Zeeb
228dd4f32aeSBjoern A. Zeeb const struct htt_rx_ring_tlv_filter ath11k_mac_mon_status_filter_default = {
229dd4f32aeSBjoern A. Zeeb .rx_filter = HTT_RX_FILTER_TLV_FLAGS_MPDU_START |
230dd4f32aeSBjoern A. Zeeb HTT_RX_FILTER_TLV_FLAGS_PPDU_END |
231dd4f32aeSBjoern A. Zeeb HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE,
232dd4f32aeSBjoern A. Zeeb .pkt_filter_flags0 = HTT_RX_FP_MGMT_FILTER_FLAGS0,
233dd4f32aeSBjoern A. Zeeb .pkt_filter_flags1 = HTT_RX_FP_MGMT_FILTER_FLAGS1,
234dd4f32aeSBjoern A. Zeeb .pkt_filter_flags2 = HTT_RX_FP_CTRL_FILTER_FLASG2,
235dd4f32aeSBjoern A. Zeeb .pkt_filter_flags3 = HTT_RX_FP_DATA_FILTER_FLASG3 |
236dd4f32aeSBjoern A. Zeeb HTT_RX_FP_CTRL_FILTER_FLASG3
237dd4f32aeSBjoern A. Zeeb };
238dd4f32aeSBjoern A. Zeeb
239dd4f32aeSBjoern A. Zeeb #define ATH11K_MAC_FIRST_OFDM_RATE_IDX 4
240dd4f32aeSBjoern A. Zeeb #define ath11k_g_rates ath11k_legacy_rates
241dd4f32aeSBjoern A. Zeeb #define ath11k_g_rates_size (ARRAY_SIZE(ath11k_legacy_rates))
242dd4f32aeSBjoern A. Zeeb #define ath11k_a_rates (ath11k_legacy_rates + 4)
243dd4f32aeSBjoern A. Zeeb #define ath11k_a_rates_size (ARRAY_SIZE(ath11k_legacy_rates) - 4)
244dd4f32aeSBjoern A. Zeeb
24528348caeSBjoern A. Zeeb #define ATH11K_MAC_SCAN_CMD_EVT_OVERHEAD 200 /* in msecs */
24628348caeSBjoern A. Zeeb
24728348caeSBjoern A. Zeeb /* Overhead due to the processing of channel switch events from FW */
24828348caeSBjoern A. Zeeb #define ATH11K_SCAN_CHANNEL_SWITCH_WMI_EVT_OVERHEAD 10 /* in msecs */
249dd4f32aeSBjoern A. Zeeb
250dd4f32aeSBjoern A. Zeeb static const u32 ath11k_smps_map[] = {
251dd4f32aeSBjoern A. Zeeb [WLAN_HT_CAP_SM_PS_STATIC] = WMI_PEER_SMPS_STATIC,
252dd4f32aeSBjoern A. Zeeb [WLAN_HT_CAP_SM_PS_DYNAMIC] = WMI_PEER_SMPS_DYNAMIC,
253dd4f32aeSBjoern A. Zeeb [WLAN_HT_CAP_SM_PS_INVALID] = WMI_PEER_SMPS_PS_NONE,
254dd4f32aeSBjoern A. Zeeb [WLAN_HT_CAP_SM_PS_DISABLED] = WMI_PEER_SMPS_PS_NONE,
255dd4f32aeSBjoern A. Zeeb };
256dd4f32aeSBjoern A. Zeeb
257dd4f32aeSBjoern A. Zeeb static int ath11k_start_vdev_delay(struct ieee80211_hw *hw,
258dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif);
259dd4f32aeSBjoern A. Zeeb
ath11k_mac_phy_he_ru_to_nl80211_he_ru_alloc(u16 ru_phy)260dd4f32aeSBjoern A. Zeeb enum nl80211_he_ru_alloc ath11k_mac_phy_he_ru_to_nl80211_he_ru_alloc(u16 ru_phy)
261dd4f32aeSBjoern A. Zeeb {
262dd4f32aeSBjoern A. Zeeb enum nl80211_he_ru_alloc ret;
263dd4f32aeSBjoern A. Zeeb
264dd4f32aeSBjoern A. Zeeb switch (ru_phy) {
265dd4f32aeSBjoern A. Zeeb case RU_26:
266dd4f32aeSBjoern A. Zeeb ret = NL80211_RATE_INFO_HE_RU_ALLOC_26;
267dd4f32aeSBjoern A. Zeeb break;
268dd4f32aeSBjoern A. Zeeb case RU_52:
269dd4f32aeSBjoern A. Zeeb ret = NL80211_RATE_INFO_HE_RU_ALLOC_52;
270dd4f32aeSBjoern A. Zeeb break;
271dd4f32aeSBjoern A. Zeeb case RU_106:
272dd4f32aeSBjoern A. Zeeb ret = NL80211_RATE_INFO_HE_RU_ALLOC_106;
273dd4f32aeSBjoern A. Zeeb break;
274dd4f32aeSBjoern A. Zeeb case RU_242:
275dd4f32aeSBjoern A. Zeeb ret = NL80211_RATE_INFO_HE_RU_ALLOC_242;
276dd4f32aeSBjoern A. Zeeb break;
277dd4f32aeSBjoern A. Zeeb case RU_484:
278dd4f32aeSBjoern A. Zeeb ret = NL80211_RATE_INFO_HE_RU_ALLOC_484;
279dd4f32aeSBjoern A. Zeeb break;
280dd4f32aeSBjoern A. Zeeb case RU_996:
281dd4f32aeSBjoern A. Zeeb ret = NL80211_RATE_INFO_HE_RU_ALLOC_996;
282dd4f32aeSBjoern A. Zeeb break;
283dd4f32aeSBjoern A. Zeeb default:
284dd4f32aeSBjoern A. Zeeb ret = NL80211_RATE_INFO_HE_RU_ALLOC_26;
285dd4f32aeSBjoern A. Zeeb break;
286dd4f32aeSBjoern A. Zeeb }
287dd4f32aeSBjoern A. Zeeb
288dd4f32aeSBjoern A. Zeeb return ret;
289dd4f32aeSBjoern A. Zeeb }
290dd4f32aeSBjoern A. Zeeb
ath11k_mac_he_ru_tones_to_nl80211_he_ru_alloc(u16 ru_tones)291dd4f32aeSBjoern A. Zeeb enum nl80211_he_ru_alloc ath11k_mac_he_ru_tones_to_nl80211_he_ru_alloc(u16 ru_tones)
292dd4f32aeSBjoern A. Zeeb {
293dd4f32aeSBjoern A. Zeeb enum nl80211_he_ru_alloc ret;
294dd4f32aeSBjoern A. Zeeb
295dd4f32aeSBjoern A. Zeeb switch (ru_tones) {
296dd4f32aeSBjoern A. Zeeb case 26:
297dd4f32aeSBjoern A. Zeeb ret = NL80211_RATE_INFO_HE_RU_ALLOC_26;
298dd4f32aeSBjoern A. Zeeb break;
299dd4f32aeSBjoern A. Zeeb case 52:
300dd4f32aeSBjoern A. Zeeb ret = NL80211_RATE_INFO_HE_RU_ALLOC_52;
301dd4f32aeSBjoern A. Zeeb break;
302dd4f32aeSBjoern A. Zeeb case 106:
303dd4f32aeSBjoern A. Zeeb ret = NL80211_RATE_INFO_HE_RU_ALLOC_106;
304dd4f32aeSBjoern A. Zeeb break;
305dd4f32aeSBjoern A. Zeeb case 242:
306dd4f32aeSBjoern A. Zeeb ret = NL80211_RATE_INFO_HE_RU_ALLOC_242;
307dd4f32aeSBjoern A. Zeeb break;
308dd4f32aeSBjoern A. Zeeb case 484:
309dd4f32aeSBjoern A. Zeeb ret = NL80211_RATE_INFO_HE_RU_ALLOC_484;
310dd4f32aeSBjoern A. Zeeb break;
311dd4f32aeSBjoern A. Zeeb case 996:
312dd4f32aeSBjoern A. Zeeb ret = NL80211_RATE_INFO_HE_RU_ALLOC_996;
313dd4f32aeSBjoern A. Zeeb break;
314dd4f32aeSBjoern A. Zeeb case (996 * 2):
315dd4f32aeSBjoern A. Zeeb ret = NL80211_RATE_INFO_HE_RU_ALLOC_2x996;
316dd4f32aeSBjoern A. Zeeb break;
317dd4f32aeSBjoern A. Zeeb default:
318dd4f32aeSBjoern A. Zeeb ret = NL80211_RATE_INFO_HE_RU_ALLOC_26;
319dd4f32aeSBjoern A. Zeeb break;
320dd4f32aeSBjoern A. Zeeb }
321dd4f32aeSBjoern A. Zeeb
322dd4f32aeSBjoern A. Zeeb return ret;
323dd4f32aeSBjoern A. Zeeb }
324dd4f32aeSBjoern A. Zeeb
ath11k_mac_he_gi_to_nl80211_he_gi(u8 sgi)325dd4f32aeSBjoern A. Zeeb enum nl80211_he_gi ath11k_mac_he_gi_to_nl80211_he_gi(u8 sgi)
326dd4f32aeSBjoern A. Zeeb {
327dd4f32aeSBjoern A. Zeeb enum nl80211_he_gi ret;
328dd4f32aeSBjoern A. Zeeb
329dd4f32aeSBjoern A. Zeeb switch (sgi) {
330dd4f32aeSBjoern A. Zeeb case RX_MSDU_START_SGI_0_8_US:
331dd4f32aeSBjoern A. Zeeb ret = NL80211_RATE_INFO_HE_GI_0_8;
332dd4f32aeSBjoern A. Zeeb break;
333dd4f32aeSBjoern A. Zeeb case RX_MSDU_START_SGI_1_6_US:
334dd4f32aeSBjoern A. Zeeb ret = NL80211_RATE_INFO_HE_GI_1_6;
335dd4f32aeSBjoern A. Zeeb break;
336dd4f32aeSBjoern A. Zeeb case RX_MSDU_START_SGI_3_2_US:
337dd4f32aeSBjoern A. Zeeb ret = NL80211_RATE_INFO_HE_GI_3_2;
338dd4f32aeSBjoern A. Zeeb break;
339dd4f32aeSBjoern A. Zeeb default:
340dd4f32aeSBjoern A. Zeeb ret = NL80211_RATE_INFO_HE_GI_0_8;
341dd4f32aeSBjoern A. Zeeb break;
342dd4f32aeSBjoern A. Zeeb }
343dd4f32aeSBjoern A. Zeeb
344dd4f32aeSBjoern A. Zeeb return ret;
345dd4f32aeSBjoern A. Zeeb }
346dd4f32aeSBjoern A. Zeeb
ath11k_mac_bw_to_mac80211_bw(u8 bw)347dd4f32aeSBjoern A. Zeeb u8 ath11k_mac_bw_to_mac80211_bw(u8 bw)
348dd4f32aeSBjoern A. Zeeb {
349dd4f32aeSBjoern A. Zeeb u8 ret = 0;
350dd4f32aeSBjoern A. Zeeb
351dd4f32aeSBjoern A. Zeeb switch (bw) {
352dd4f32aeSBjoern A. Zeeb case ATH11K_BW_20:
353dd4f32aeSBjoern A. Zeeb ret = RATE_INFO_BW_20;
354dd4f32aeSBjoern A. Zeeb break;
355dd4f32aeSBjoern A. Zeeb case ATH11K_BW_40:
356dd4f32aeSBjoern A. Zeeb ret = RATE_INFO_BW_40;
357dd4f32aeSBjoern A. Zeeb break;
358dd4f32aeSBjoern A. Zeeb case ATH11K_BW_80:
359dd4f32aeSBjoern A. Zeeb ret = RATE_INFO_BW_80;
360dd4f32aeSBjoern A. Zeeb break;
361dd4f32aeSBjoern A. Zeeb case ATH11K_BW_160:
362dd4f32aeSBjoern A. Zeeb ret = RATE_INFO_BW_160;
363dd4f32aeSBjoern A. Zeeb break;
364dd4f32aeSBjoern A. Zeeb }
365dd4f32aeSBjoern A. Zeeb
366dd4f32aeSBjoern A. Zeeb return ret;
367dd4f32aeSBjoern A. Zeeb }
368dd4f32aeSBjoern A. Zeeb
ath11k_mac_mac80211_bw_to_ath11k_bw(enum rate_info_bw bw)369dd4f32aeSBjoern A. Zeeb enum ath11k_supported_bw ath11k_mac_mac80211_bw_to_ath11k_bw(enum rate_info_bw bw)
370dd4f32aeSBjoern A. Zeeb {
371dd4f32aeSBjoern A. Zeeb switch (bw) {
372dd4f32aeSBjoern A. Zeeb case RATE_INFO_BW_20:
373dd4f32aeSBjoern A. Zeeb return ATH11K_BW_20;
374dd4f32aeSBjoern A. Zeeb case RATE_INFO_BW_40:
375dd4f32aeSBjoern A. Zeeb return ATH11K_BW_40;
376dd4f32aeSBjoern A. Zeeb case RATE_INFO_BW_80:
377dd4f32aeSBjoern A. Zeeb return ATH11K_BW_80;
378dd4f32aeSBjoern A. Zeeb case RATE_INFO_BW_160:
379dd4f32aeSBjoern A. Zeeb return ATH11K_BW_160;
380dd4f32aeSBjoern A. Zeeb default:
381dd4f32aeSBjoern A. Zeeb return ATH11K_BW_20;
382dd4f32aeSBjoern A. Zeeb }
383dd4f32aeSBjoern A. Zeeb }
384dd4f32aeSBjoern A. Zeeb
ath11k_mac_hw_ratecode_to_legacy_rate(u8 hw_rc,u8 preamble,u8 * rateidx,u16 * rate)385dd4f32aeSBjoern A. Zeeb int ath11k_mac_hw_ratecode_to_legacy_rate(u8 hw_rc, u8 preamble, u8 *rateidx,
386dd4f32aeSBjoern A. Zeeb u16 *rate)
387dd4f32aeSBjoern A. Zeeb {
388dd4f32aeSBjoern A. Zeeb /* As default, it is OFDM rates */
389dd4f32aeSBjoern A. Zeeb int i = ATH11K_MAC_FIRST_OFDM_RATE_IDX;
390dd4f32aeSBjoern A. Zeeb int max_rates_idx = ath11k_g_rates_size;
391dd4f32aeSBjoern A. Zeeb
392dd4f32aeSBjoern A. Zeeb if (preamble == WMI_RATE_PREAMBLE_CCK) {
393dd4f32aeSBjoern A. Zeeb hw_rc &= ~ATH11k_HW_RATECODE_CCK_SHORT_PREAM_MASK;
394dd4f32aeSBjoern A. Zeeb i = 0;
395dd4f32aeSBjoern A. Zeeb max_rates_idx = ATH11K_MAC_FIRST_OFDM_RATE_IDX;
396dd4f32aeSBjoern A. Zeeb }
397dd4f32aeSBjoern A. Zeeb
398dd4f32aeSBjoern A. Zeeb while (i < max_rates_idx) {
399dd4f32aeSBjoern A. Zeeb if (hw_rc == ath11k_legacy_rates[i].hw_value) {
400dd4f32aeSBjoern A. Zeeb *rateidx = i;
401dd4f32aeSBjoern A. Zeeb *rate = ath11k_legacy_rates[i].bitrate;
402dd4f32aeSBjoern A. Zeeb return 0;
403dd4f32aeSBjoern A. Zeeb }
404dd4f32aeSBjoern A. Zeeb i++;
405dd4f32aeSBjoern A. Zeeb }
406dd4f32aeSBjoern A. Zeeb
407dd4f32aeSBjoern A. Zeeb return -EINVAL;
408dd4f32aeSBjoern A. Zeeb }
409dd4f32aeSBjoern A. Zeeb
get_num_chains(u32 mask)410dd4f32aeSBjoern A. Zeeb static int get_num_chains(u32 mask)
411dd4f32aeSBjoern A. Zeeb {
412dd4f32aeSBjoern A. Zeeb int num_chains = 0;
413dd4f32aeSBjoern A. Zeeb
414dd4f32aeSBjoern A. Zeeb while (mask) {
415dd4f32aeSBjoern A. Zeeb if (mask & BIT(0))
416dd4f32aeSBjoern A. Zeeb num_chains++;
417dd4f32aeSBjoern A. Zeeb mask >>= 1;
418dd4f32aeSBjoern A. Zeeb }
419dd4f32aeSBjoern A. Zeeb
420dd4f32aeSBjoern A. Zeeb return num_chains;
421dd4f32aeSBjoern A. Zeeb }
422dd4f32aeSBjoern A. Zeeb
ath11k_mac_bitrate_to_idx(const struct ieee80211_supported_band * sband,u32 bitrate)423dd4f32aeSBjoern A. Zeeb u8 ath11k_mac_bitrate_to_idx(const struct ieee80211_supported_band *sband,
424dd4f32aeSBjoern A. Zeeb u32 bitrate)
425dd4f32aeSBjoern A. Zeeb {
426dd4f32aeSBjoern A. Zeeb int i;
427dd4f32aeSBjoern A. Zeeb
428dd4f32aeSBjoern A. Zeeb for (i = 0; i < sband->n_bitrates; i++)
429dd4f32aeSBjoern A. Zeeb if (sband->bitrates[i].bitrate == bitrate)
430dd4f32aeSBjoern A. Zeeb return i;
431dd4f32aeSBjoern A. Zeeb
432dd4f32aeSBjoern A. Zeeb return 0;
433dd4f32aeSBjoern A. Zeeb }
434dd4f32aeSBjoern A. Zeeb
435dd4f32aeSBjoern A. Zeeb static u32
ath11k_mac_max_ht_nss(const u8 * ht_mcs_mask)43628348caeSBjoern A. Zeeb ath11k_mac_max_ht_nss(const u8 *ht_mcs_mask)
437dd4f32aeSBjoern A. Zeeb {
438dd4f32aeSBjoern A. Zeeb int nss;
439dd4f32aeSBjoern A. Zeeb
440dd4f32aeSBjoern A. Zeeb for (nss = IEEE80211_HT_MCS_MASK_LEN - 1; nss >= 0; nss--)
441dd4f32aeSBjoern A. Zeeb if (ht_mcs_mask[nss])
442dd4f32aeSBjoern A. Zeeb return nss + 1;
443dd4f32aeSBjoern A. Zeeb
444dd4f32aeSBjoern A. Zeeb return 1;
445dd4f32aeSBjoern A. Zeeb }
446dd4f32aeSBjoern A. Zeeb
447dd4f32aeSBjoern A. Zeeb static u32
ath11k_mac_max_vht_nss(const u16 * vht_mcs_mask)44828348caeSBjoern A. Zeeb ath11k_mac_max_vht_nss(const u16 *vht_mcs_mask)
449dd4f32aeSBjoern A. Zeeb {
450dd4f32aeSBjoern A. Zeeb int nss;
451dd4f32aeSBjoern A. Zeeb
452dd4f32aeSBjoern A. Zeeb for (nss = NL80211_VHT_NSS_MAX - 1; nss >= 0; nss--)
453dd4f32aeSBjoern A. Zeeb if (vht_mcs_mask[nss])
454dd4f32aeSBjoern A. Zeeb return nss + 1;
455dd4f32aeSBjoern A. Zeeb
456dd4f32aeSBjoern A. Zeeb return 1;
457dd4f32aeSBjoern A. Zeeb }
458dd4f32aeSBjoern A. Zeeb
459dd4f32aeSBjoern A. Zeeb static u32
ath11k_mac_max_he_nss(const u16 * he_mcs_mask)46028348caeSBjoern A. Zeeb ath11k_mac_max_he_nss(const u16 *he_mcs_mask)
461dd4f32aeSBjoern A. Zeeb {
462dd4f32aeSBjoern A. Zeeb int nss;
463dd4f32aeSBjoern A. Zeeb
464dd4f32aeSBjoern A. Zeeb for (nss = NL80211_HE_NSS_MAX - 1; nss >= 0; nss--)
465dd4f32aeSBjoern A. Zeeb if (he_mcs_mask[nss])
466dd4f32aeSBjoern A. Zeeb return nss + 1;
467dd4f32aeSBjoern A. Zeeb
468dd4f32aeSBjoern A. Zeeb return 1;
469dd4f32aeSBjoern A. Zeeb }
470dd4f32aeSBjoern A. Zeeb
ath11k_parse_mpdudensity(u8 mpdudensity)471dd4f32aeSBjoern A. Zeeb static u8 ath11k_parse_mpdudensity(u8 mpdudensity)
472dd4f32aeSBjoern A. Zeeb {
473dd4f32aeSBjoern A. Zeeb /* 802.11n D2.0 defined values for "Minimum MPDU Start Spacing":
474dd4f32aeSBjoern A. Zeeb * 0 for no restriction
475dd4f32aeSBjoern A. Zeeb * 1 for 1/4 us
476dd4f32aeSBjoern A. Zeeb * 2 for 1/2 us
477dd4f32aeSBjoern A. Zeeb * 3 for 1 us
478dd4f32aeSBjoern A. Zeeb * 4 for 2 us
479dd4f32aeSBjoern A. Zeeb * 5 for 4 us
480dd4f32aeSBjoern A. Zeeb * 6 for 8 us
481dd4f32aeSBjoern A. Zeeb * 7 for 16 us
482dd4f32aeSBjoern A. Zeeb */
483dd4f32aeSBjoern A. Zeeb switch (mpdudensity) {
484dd4f32aeSBjoern A. Zeeb case 0:
485dd4f32aeSBjoern A. Zeeb return 0;
486dd4f32aeSBjoern A. Zeeb case 1:
487dd4f32aeSBjoern A. Zeeb case 2:
488dd4f32aeSBjoern A. Zeeb case 3:
489dd4f32aeSBjoern A. Zeeb /* Our lower layer calculations limit our precision to
490dd4f32aeSBjoern A. Zeeb * 1 microsecond
491dd4f32aeSBjoern A. Zeeb */
492dd4f32aeSBjoern A. Zeeb return 1;
493dd4f32aeSBjoern A. Zeeb case 4:
494dd4f32aeSBjoern A. Zeeb return 2;
495dd4f32aeSBjoern A. Zeeb case 5:
496dd4f32aeSBjoern A. Zeeb return 4;
497dd4f32aeSBjoern A. Zeeb case 6:
498dd4f32aeSBjoern A. Zeeb return 8;
499dd4f32aeSBjoern A. Zeeb case 7:
500dd4f32aeSBjoern A. Zeeb return 16;
501dd4f32aeSBjoern A. Zeeb default:
502dd4f32aeSBjoern A. Zeeb return 0;
503dd4f32aeSBjoern A. Zeeb }
504dd4f32aeSBjoern A. Zeeb }
505dd4f32aeSBjoern A. Zeeb
ath11k_mac_vif_chan(struct ieee80211_vif * vif,struct cfg80211_chan_def * def)506dd4f32aeSBjoern A. Zeeb static int ath11k_mac_vif_chan(struct ieee80211_vif *vif,
507dd4f32aeSBjoern A. Zeeb struct cfg80211_chan_def *def)
508dd4f32aeSBjoern A. Zeeb {
509dd4f32aeSBjoern A. Zeeb struct ieee80211_chanctx_conf *conf;
510dd4f32aeSBjoern A. Zeeb
511dd4f32aeSBjoern A. Zeeb rcu_read_lock();
51228348caeSBjoern A. Zeeb conf = rcu_dereference(vif->bss_conf.chanctx_conf);
513dd4f32aeSBjoern A. Zeeb if (!conf) {
514dd4f32aeSBjoern A. Zeeb rcu_read_unlock();
515dd4f32aeSBjoern A. Zeeb return -ENOENT;
516dd4f32aeSBjoern A. Zeeb }
517dd4f32aeSBjoern A. Zeeb
518dd4f32aeSBjoern A. Zeeb *def = conf->def;
519dd4f32aeSBjoern A. Zeeb rcu_read_unlock();
520dd4f32aeSBjoern A. Zeeb
521dd4f32aeSBjoern A. Zeeb return 0;
522dd4f32aeSBjoern A. Zeeb }
523dd4f32aeSBjoern A. Zeeb
ath11k_mac_bitrate_is_cck(int bitrate)524dd4f32aeSBjoern A. Zeeb static bool ath11k_mac_bitrate_is_cck(int bitrate)
525dd4f32aeSBjoern A. Zeeb {
526dd4f32aeSBjoern A. Zeeb switch (bitrate) {
527dd4f32aeSBjoern A. Zeeb case 10:
528dd4f32aeSBjoern A. Zeeb case 20:
529dd4f32aeSBjoern A. Zeeb case 55:
530dd4f32aeSBjoern A. Zeeb case 110:
531dd4f32aeSBjoern A. Zeeb return true;
532dd4f32aeSBjoern A. Zeeb }
533dd4f32aeSBjoern A. Zeeb
534dd4f32aeSBjoern A. Zeeb return false;
535dd4f32aeSBjoern A. Zeeb }
536dd4f32aeSBjoern A. Zeeb
ath11k_mac_hw_rate_to_idx(const struct ieee80211_supported_band * sband,u8 hw_rate,bool cck)537dd4f32aeSBjoern A. Zeeb u8 ath11k_mac_hw_rate_to_idx(const struct ieee80211_supported_band *sband,
538dd4f32aeSBjoern A. Zeeb u8 hw_rate, bool cck)
539dd4f32aeSBjoern A. Zeeb {
540dd4f32aeSBjoern A. Zeeb const struct ieee80211_rate *rate;
541dd4f32aeSBjoern A. Zeeb int i;
542dd4f32aeSBjoern A. Zeeb
543dd4f32aeSBjoern A. Zeeb for (i = 0; i < sband->n_bitrates; i++) {
544dd4f32aeSBjoern A. Zeeb rate = &sband->bitrates[i];
545dd4f32aeSBjoern A. Zeeb
546dd4f32aeSBjoern A. Zeeb if (ath11k_mac_bitrate_is_cck(rate->bitrate) != cck)
547dd4f32aeSBjoern A. Zeeb continue;
548dd4f32aeSBjoern A. Zeeb
549dd4f32aeSBjoern A. Zeeb if (rate->hw_value == hw_rate)
550dd4f32aeSBjoern A. Zeeb return i;
551dd4f32aeSBjoern A. Zeeb else if (rate->flags & IEEE80211_RATE_SHORT_PREAMBLE &&
552dd4f32aeSBjoern A. Zeeb rate->hw_value_short == hw_rate)
553dd4f32aeSBjoern A. Zeeb return i;
554dd4f32aeSBjoern A. Zeeb }
555dd4f32aeSBjoern A. Zeeb
556dd4f32aeSBjoern A. Zeeb return 0;
557dd4f32aeSBjoern A. Zeeb }
558dd4f32aeSBjoern A. Zeeb
ath11k_mac_bitrate_to_rate(int bitrate)559dd4f32aeSBjoern A. Zeeb static u8 ath11k_mac_bitrate_to_rate(int bitrate)
560dd4f32aeSBjoern A. Zeeb {
561dd4f32aeSBjoern A. Zeeb return DIV_ROUND_UP(bitrate, 5) |
562dd4f32aeSBjoern A. Zeeb (ath11k_mac_bitrate_is_cck(bitrate) ? BIT(7) : 0);
563dd4f32aeSBjoern A. Zeeb }
564dd4f32aeSBjoern A. Zeeb
ath11k_get_arvif_iter(void * data,u8 * mac,struct ieee80211_vif * vif)565dd4f32aeSBjoern A. Zeeb static void ath11k_get_arvif_iter(void *data, u8 *mac,
566dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif)
567dd4f32aeSBjoern A. Zeeb {
568dd4f32aeSBjoern A. Zeeb struct ath11k_vif_iter *arvif_iter = data;
569dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif = (void *)vif->drv_priv;
570dd4f32aeSBjoern A. Zeeb
571dd4f32aeSBjoern A. Zeeb if (arvif->vdev_id == arvif_iter->vdev_id)
572dd4f32aeSBjoern A. Zeeb arvif_iter->arvif = arvif;
573dd4f32aeSBjoern A. Zeeb }
574dd4f32aeSBjoern A. Zeeb
ath11k_mac_get_arvif(struct ath11k * ar,u32 vdev_id)575dd4f32aeSBjoern A. Zeeb struct ath11k_vif *ath11k_mac_get_arvif(struct ath11k *ar, u32 vdev_id)
576dd4f32aeSBjoern A. Zeeb {
577dd4f32aeSBjoern A. Zeeb struct ath11k_vif_iter arvif_iter;
578dd4f32aeSBjoern A. Zeeb u32 flags;
579dd4f32aeSBjoern A. Zeeb
580dd4f32aeSBjoern A. Zeeb memset(&arvif_iter, 0, sizeof(struct ath11k_vif_iter));
581dd4f32aeSBjoern A. Zeeb arvif_iter.vdev_id = vdev_id;
582dd4f32aeSBjoern A. Zeeb
583dd4f32aeSBjoern A. Zeeb flags = IEEE80211_IFACE_ITER_RESUME_ALL;
584dd4f32aeSBjoern A. Zeeb ieee80211_iterate_active_interfaces_atomic(ar->hw,
585dd4f32aeSBjoern A. Zeeb flags,
586dd4f32aeSBjoern A. Zeeb ath11k_get_arvif_iter,
587dd4f32aeSBjoern A. Zeeb &arvif_iter);
588dd4f32aeSBjoern A. Zeeb if (!arvif_iter.arvif) {
589dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "No VIF found for vdev %d\n", vdev_id);
590dd4f32aeSBjoern A. Zeeb return NULL;
591dd4f32aeSBjoern A. Zeeb }
592dd4f32aeSBjoern A. Zeeb
593dd4f32aeSBjoern A. Zeeb return arvif_iter.arvif;
594dd4f32aeSBjoern A. Zeeb }
595dd4f32aeSBjoern A. Zeeb
ath11k_mac_get_arvif_by_vdev_id(struct ath11k_base * ab,u32 vdev_id)596dd4f32aeSBjoern A. Zeeb struct ath11k_vif *ath11k_mac_get_arvif_by_vdev_id(struct ath11k_base *ab,
597dd4f32aeSBjoern A. Zeeb u32 vdev_id)
598dd4f32aeSBjoern A. Zeeb {
599dd4f32aeSBjoern A. Zeeb int i;
600dd4f32aeSBjoern A. Zeeb struct ath11k_pdev *pdev;
601dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif;
602dd4f32aeSBjoern A. Zeeb
603dd4f32aeSBjoern A. Zeeb for (i = 0; i < ab->num_radios; i++) {
604dd4f32aeSBjoern A. Zeeb pdev = rcu_dereference(ab->pdevs_active[i]);
605dd4f32aeSBjoern A. Zeeb if (pdev && pdev->ar &&
606dd4f32aeSBjoern A. Zeeb (pdev->ar->allocated_vdev_map & (1LL << vdev_id))) {
607dd4f32aeSBjoern A. Zeeb arvif = ath11k_mac_get_arvif(pdev->ar, vdev_id);
608dd4f32aeSBjoern A. Zeeb if (arvif)
609dd4f32aeSBjoern A. Zeeb return arvif;
610dd4f32aeSBjoern A. Zeeb }
611dd4f32aeSBjoern A. Zeeb }
612dd4f32aeSBjoern A. Zeeb
613dd4f32aeSBjoern A. Zeeb return NULL;
614dd4f32aeSBjoern A. Zeeb }
615dd4f32aeSBjoern A. Zeeb
ath11k_mac_get_ar_by_vdev_id(struct ath11k_base * ab,u32 vdev_id)616dd4f32aeSBjoern A. Zeeb struct ath11k *ath11k_mac_get_ar_by_vdev_id(struct ath11k_base *ab, u32 vdev_id)
617dd4f32aeSBjoern A. Zeeb {
618dd4f32aeSBjoern A. Zeeb int i;
619dd4f32aeSBjoern A. Zeeb struct ath11k_pdev *pdev;
620dd4f32aeSBjoern A. Zeeb
621dd4f32aeSBjoern A. Zeeb for (i = 0; i < ab->num_radios; i++) {
622dd4f32aeSBjoern A. Zeeb pdev = rcu_dereference(ab->pdevs_active[i]);
623dd4f32aeSBjoern A. Zeeb if (pdev && pdev->ar) {
624dd4f32aeSBjoern A. Zeeb if (pdev->ar->allocated_vdev_map & (1LL << vdev_id))
625dd4f32aeSBjoern A. Zeeb return pdev->ar;
626dd4f32aeSBjoern A. Zeeb }
627dd4f32aeSBjoern A. Zeeb }
628dd4f32aeSBjoern A. Zeeb
629dd4f32aeSBjoern A. Zeeb return NULL;
630dd4f32aeSBjoern A. Zeeb }
631dd4f32aeSBjoern A. Zeeb
ath11k_mac_get_ar_by_pdev_id(struct ath11k_base * ab,u32 pdev_id)632dd4f32aeSBjoern A. Zeeb struct ath11k *ath11k_mac_get_ar_by_pdev_id(struct ath11k_base *ab, u32 pdev_id)
633dd4f32aeSBjoern A. Zeeb {
634dd4f32aeSBjoern A. Zeeb int i;
635dd4f32aeSBjoern A. Zeeb struct ath11k_pdev *pdev;
636dd4f32aeSBjoern A. Zeeb
637dd4f32aeSBjoern A. Zeeb if (ab->hw_params.single_pdev_only) {
638dd4f32aeSBjoern A. Zeeb pdev = rcu_dereference(ab->pdevs_active[0]);
639dd4f32aeSBjoern A. Zeeb return pdev ? pdev->ar : NULL;
640dd4f32aeSBjoern A. Zeeb }
641dd4f32aeSBjoern A. Zeeb
642dd4f32aeSBjoern A. Zeeb if (WARN_ON(pdev_id > ab->num_radios))
643dd4f32aeSBjoern A. Zeeb return NULL;
644dd4f32aeSBjoern A. Zeeb
645dd4f32aeSBjoern A. Zeeb for (i = 0; i < ab->num_radios; i++) {
64628348caeSBjoern A. Zeeb if (ab->fw_mode == ATH11K_FIRMWARE_MODE_FTM)
64728348caeSBjoern A. Zeeb pdev = &ab->pdevs[i];
64828348caeSBjoern A. Zeeb else
649dd4f32aeSBjoern A. Zeeb pdev = rcu_dereference(ab->pdevs_active[i]);
650dd4f32aeSBjoern A. Zeeb
651dd4f32aeSBjoern A. Zeeb if (pdev && pdev->pdev_id == pdev_id)
652dd4f32aeSBjoern A. Zeeb return (pdev->ar ? pdev->ar : NULL);
653dd4f32aeSBjoern A. Zeeb }
654dd4f32aeSBjoern A. Zeeb
655dd4f32aeSBjoern A. Zeeb return NULL;
656dd4f32aeSBjoern A. Zeeb }
657dd4f32aeSBjoern A. Zeeb
ath11k_mac_get_vif_up(struct ath11k_base * ab)658dd4f32aeSBjoern A. Zeeb struct ath11k_vif *ath11k_mac_get_vif_up(struct ath11k_base *ab)
659dd4f32aeSBjoern A. Zeeb {
660dd4f32aeSBjoern A. Zeeb struct ath11k *ar;
661dd4f32aeSBjoern A. Zeeb struct ath11k_pdev *pdev;
662dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif;
663dd4f32aeSBjoern A. Zeeb int i;
664dd4f32aeSBjoern A. Zeeb
665dd4f32aeSBjoern A. Zeeb for (i = 0; i < ab->num_radios; i++) {
666dd4f32aeSBjoern A. Zeeb pdev = &ab->pdevs[i];
667dd4f32aeSBjoern A. Zeeb ar = pdev->ar;
668dd4f32aeSBjoern A. Zeeb list_for_each_entry(arvif, &ar->arvifs, list) {
669dd4f32aeSBjoern A. Zeeb if (arvif->is_up)
670dd4f32aeSBjoern A. Zeeb return arvif;
671dd4f32aeSBjoern A. Zeeb }
672dd4f32aeSBjoern A. Zeeb }
673dd4f32aeSBjoern A. Zeeb
674dd4f32aeSBjoern A. Zeeb return NULL;
675dd4f32aeSBjoern A. Zeeb }
676dd4f32aeSBjoern A. Zeeb
ath11k_mac_band_match(enum nl80211_band band1,enum WMI_HOST_WLAN_BAND band2)677dd4f32aeSBjoern A. Zeeb static bool ath11k_mac_band_match(enum nl80211_band band1, enum WMI_HOST_WLAN_BAND band2)
678dd4f32aeSBjoern A. Zeeb {
679dd4f32aeSBjoern A. Zeeb return (((band1 == NL80211_BAND_2GHZ) && (band2 & WMI_HOST_WLAN_2G_CAP)) ||
680dd4f32aeSBjoern A. Zeeb (((band1 == NL80211_BAND_5GHZ) || (band1 == NL80211_BAND_6GHZ)) &&
681dd4f32aeSBjoern A. Zeeb (band2 & WMI_HOST_WLAN_5G_CAP)));
682dd4f32aeSBjoern A. Zeeb }
683dd4f32aeSBjoern A. Zeeb
ath11k_mac_get_target_pdev_id_from_vif(struct ath11k_vif * arvif)684dd4f32aeSBjoern A. Zeeb u8 ath11k_mac_get_target_pdev_id_from_vif(struct ath11k_vif *arvif)
685dd4f32aeSBjoern A. Zeeb {
686dd4f32aeSBjoern A. Zeeb struct ath11k *ar = arvif->ar;
687dd4f32aeSBjoern A. Zeeb struct ath11k_base *ab = ar->ab;
688dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif = arvif->vif;
689dd4f32aeSBjoern A. Zeeb struct cfg80211_chan_def def;
690dd4f32aeSBjoern A. Zeeb enum nl80211_band band;
691dd4f32aeSBjoern A. Zeeb u8 pdev_id = ab->target_pdev_ids[0].pdev_id;
692dd4f32aeSBjoern A. Zeeb int i;
693dd4f32aeSBjoern A. Zeeb
694dd4f32aeSBjoern A. Zeeb if (WARN_ON(ath11k_mac_vif_chan(vif, &def)))
695dd4f32aeSBjoern A. Zeeb return pdev_id;
696dd4f32aeSBjoern A. Zeeb
697dd4f32aeSBjoern A. Zeeb band = def.chan->band;
698dd4f32aeSBjoern A. Zeeb
699dd4f32aeSBjoern A. Zeeb for (i = 0; i < ab->target_pdev_count; i++) {
700dd4f32aeSBjoern A. Zeeb if (ath11k_mac_band_match(band, ab->target_pdev_ids[i].supported_bands))
701dd4f32aeSBjoern A. Zeeb return ab->target_pdev_ids[i].pdev_id;
702dd4f32aeSBjoern A. Zeeb }
703dd4f32aeSBjoern A. Zeeb
704dd4f32aeSBjoern A. Zeeb return pdev_id;
705dd4f32aeSBjoern A. Zeeb }
706dd4f32aeSBjoern A. Zeeb
ath11k_mac_get_target_pdev_id(struct ath11k * ar)707dd4f32aeSBjoern A. Zeeb u8 ath11k_mac_get_target_pdev_id(struct ath11k *ar)
708dd4f32aeSBjoern A. Zeeb {
709dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif;
710dd4f32aeSBjoern A. Zeeb
711dd4f32aeSBjoern A. Zeeb arvif = ath11k_mac_get_vif_up(ar->ab);
712dd4f32aeSBjoern A. Zeeb
713dd4f32aeSBjoern A. Zeeb if (arvif)
714dd4f32aeSBjoern A. Zeeb return ath11k_mac_get_target_pdev_id_from_vif(arvif);
715dd4f32aeSBjoern A. Zeeb else
716dd4f32aeSBjoern A. Zeeb return ar->ab->target_pdev_ids[0].pdev_id;
717dd4f32aeSBjoern A. Zeeb }
718dd4f32aeSBjoern A. Zeeb
ath11k_pdev_caps_update(struct ath11k * ar)719dd4f32aeSBjoern A. Zeeb static void ath11k_pdev_caps_update(struct ath11k *ar)
720dd4f32aeSBjoern A. Zeeb {
721dd4f32aeSBjoern A. Zeeb struct ath11k_base *ab = ar->ab;
722dd4f32aeSBjoern A. Zeeb
723dd4f32aeSBjoern A. Zeeb ar->max_tx_power = ab->target_caps.hw_max_tx_power;
724dd4f32aeSBjoern A. Zeeb
725dd4f32aeSBjoern A. Zeeb /* FIXME Set min_tx_power to ab->target_caps.hw_min_tx_power.
726dd4f32aeSBjoern A. Zeeb * But since the received value in svcrdy is same as hw_max_tx_power,
727dd4f32aeSBjoern A. Zeeb * we can set ar->min_tx_power to 0 currently until
728dd4f32aeSBjoern A. Zeeb * this is fixed in firmware
729dd4f32aeSBjoern A. Zeeb */
730dd4f32aeSBjoern A. Zeeb ar->min_tx_power = 0;
731dd4f32aeSBjoern A. Zeeb
732dd4f32aeSBjoern A. Zeeb ar->txpower_limit_2g = ar->max_tx_power;
733dd4f32aeSBjoern A. Zeeb ar->txpower_limit_5g = ar->max_tx_power;
734dd4f32aeSBjoern A. Zeeb ar->txpower_scale = WMI_HOST_TP_SCALE_MAX;
735dd4f32aeSBjoern A. Zeeb }
736dd4f32aeSBjoern A. Zeeb
ath11k_mac_txpower_recalc(struct ath11k * ar)737dd4f32aeSBjoern A. Zeeb static int ath11k_mac_txpower_recalc(struct ath11k *ar)
738dd4f32aeSBjoern A. Zeeb {
739dd4f32aeSBjoern A. Zeeb struct ath11k_pdev *pdev = ar->pdev;
740dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif;
741dd4f32aeSBjoern A. Zeeb int ret, txpower = -1;
742dd4f32aeSBjoern A. Zeeb u32 param;
743dd4f32aeSBjoern A. Zeeb
744dd4f32aeSBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
745dd4f32aeSBjoern A. Zeeb
746dd4f32aeSBjoern A. Zeeb list_for_each_entry(arvif, &ar->arvifs, list) {
747dd4f32aeSBjoern A. Zeeb if (arvif->txpower <= 0)
748dd4f32aeSBjoern A. Zeeb continue;
749dd4f32aeSBjoern A. Zeeb
750dd4f32aeSBjoern A. Zeeb if (txpower == -1)
751dd4f32aeSBjoern A. Zeeb txpower = arvif->txpower;
752dd4f32aeSBjoern A. Zeeb else
753dd4f32aeSBjoern A. Zeeb txpower = min(txpower, arvif->txpower);
754dd4f32aeSBjoern A. Zeeb }
755dd4f32aeSBjoern A. Zeeb
756dd4f32aeSBjoern A. Zeeb if (txpower == -1)
757dd4f32aeSBjoern A. Zeeb return 0;
758dd4f32aeSBjoern A. Zeeb
759dd4f32aeSBjoern A. Zeeb /* txpwr is set as 2 units per dBm in FW*/
760dd4f32aeSBjoern A. Zeeb txpower = min_t(u32, max_t(u32, ar->min_tx_power, txpower),
761dd4f32aeSBjoern A. Zeeb ar->max_tx_power) * 2;
762dd4f32aeSBjoern A. Zeeb
763dd4f32aeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "txpower to set in hw %d\n",
764dd4f32aeSBjoern A. Zeeb txpower / 2);
765dd4f32aeSBjoern A. Zeeb
766dd4f32aeSBjoern A. Zeeb if ((pdev->cap.supported_bands & WMI_HOST_WLAN_2G_CAP) &&
767dd4f32aeSBjoern A. Zeeb ar->txpower_limit_2g != txpower) {
768dd4f32aeSBjoern A. Zeeb param = WMI_PDEV_PARAM_TXPOWER_LIMIT2G;
769dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_pdev_set_param(ar, param,
770dd4f32aeSBjoern A. Zeeb txpower, ar->pdev->pdev_id);
771dd4f32aeSBjoern A. Zeeb if (ret)
772dd4f32aeSBjoern A. Zeeb goto fail;
773dd4f32aeSBjoern A. Zeeb ar->txpower_limit_2g = txpower;
774dd4f32aeSBjoern A. Zeeb }
775dd4f32aeSBjoern A. Zeeb
776dd4f32aeSBjoern A. Zeeb if ((pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP) &&
777dd4f32aeSBjoern A. Zeeb ar->txpower_limit_5g != txpower) {
778dd4f32aeSBjoern A. Zeeb param = WMI_PDEV_PARAM_TXPOWER_LIMIT5G;
779dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_pdev_set_param(ar, param,
780dd4f32aeSBjoern A. Zeeb txpower, ar->pdev->pdev_id);
781dd4f32aeSBjoern A. Zeeb if (ret)
782dd4f32aeSBjoern A. Zeeb goto fail;
783dd4f32aeSBjoern A. Zeeb ar->txpower_limit_5g = txpower;
784dd4f32aeSBjoern A. Zeeb }
785dd4f32aeSBjoern A. Zeeb
786dd4f32aeSBjoern A. Zeeb return 0;
787dd4f32aeSBjoern A. Zeeb
788dd4f32aeSBjoern A. Zeeb fail:
789dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to recalc txpower limit %d using pdev param %d: %d\n",
790dd4f32aeSBjoern A. Zeeb txpower / 2, param, ret);
791dd4f32aeSBjoern A. Zeeb return ret;
792dd4f32aeSBjoern A. Zeeb }
793dd4f32aeSBjoern A. Zeeb
ath11k_recalc_rtscts_prot(struct ath11k_vif * arvif)794dd4f32aeSBjoern A. Zeeb static int ath11k_recalc_rtscts_prot(struct ath11k_vif *arvif)
795dd4f32aeSBjoern A. Zeeb {
796dd4f32aeSBjoern A. Zeeb struct ath11k *ar = arvif->ar;
797dd4f32aeSBjoern A. Zeeb u32 vdev_param, rts_cts = 0;
798dd4f32aeSBjoern A. Zeeb int ret;
799dd4f32aeSBjoern A. Zeeb
800dd4f32aeSBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
801dd4f32aeSBjoern A. Zeeb
802dd4f32aeSBjoern A. Zeeb vdev_param = WMI_VDEV_PARAM_ENABLE_RTSCTS;
803dd4f32aeSBjoern A. Zeeb
804dd4f32aeSBjoern A. Zeeb /* Enable RTS/CTS protection for sw retries (when legacy stations
805dd4f32aeSBjoern A. Zeeb * are in BSS) or by default only for second rate series.
806dd4f32aeSBjoern A. Zeeb * TODO: Check if we need to enable CTS 2 Self in any case
807dd4f32aeSBjoern A. Zeeb */
808dd4f32aeSBjoern A. Zeeb rts_cts = WMI_USE_RTS_CTS;
809dd4f32aeSBjoern A. Zeeb
810dd4f32aeSBjoern A. Zeeb if (arvif->num_legacy_stations > 0)
811dd4f32aeSBjoern A. Zeeb rts_cts |= WMI_RTSCTS_ACROSS_SW_RETRIES << 4;
812dd4f32aeSBjoern A. Zeeb else
813dd4f32aeSBjoern A. Zeeb rts_cts |= WMI_RTSCTS_FOR_SECOND_RATESERIES << 4;
814dd4f32aeSBjoern A. Zeeb
815dd4f32aeSBjoern A. Zeeb /* Need not send duplicate param value to firmware */
816dd4f32aeSBjoern A. Zeeb if (arvif->rtscts_prot_mode == rts_cts)
817dd4f32aeSBjoern A. Zeeb return 0;
818dd4f32aeSBjoern A. Zeeb
819dd4f32aeSBjoern A. Zeeb arvif->rtscts_prot_mode = rts_cts;
820dd4f32aeSBjoern A. Zeeb
82128348caeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev %d recalc rts/cts prot %d\n",
822dd4f32aeSBjoern A. Zeeb arvif->vdev_id, rts_cts);
823dd4f32aeSBjoern A. Zeeb
824dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
825dd4f32aeSBjoern A. Zeeb vdev_param, rts_cts);
826dd4f32aeSBjoern A. Zeeb if (ret)
827dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to recalculate rts/cts prot for vdev %d: %d\n",
828dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ret);
829dd4f32aeSBjoern A. Zeeb
830dd4f32aeSBjoern A. Zeeb return ret;
831dd4f32aeSBjoern A. Zeeb }
832dd4f32aeSBjoern A. Zeeb
ath11k_mac_set_kickout(struct ath11k_vif * arvif)833dd4f32aeSBjoern A. Zeeb static int ath11k_mac_set_kickout(struct ath11k_vif *arvif)
834dd4f32aeSBjoern A. Zeeb {
835dd4f32aeSBjoern A. Zeeb struct ath11k *ar = arvif->ar;
836dd4f32aeSBjoern A. Zeeb u32 param;
837dd4f32aeSBjoern A. Zeeb int ret;
838dd4f32aeSBjoern A. Zeeb
839dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_STA_KICKOUT_TH,
840dd4f32aeSBjoern A. Zeeb ATH11K_KICKOUT_THRESHOLD,
841dd4f32aeSBjoern A. Zeeb ar->pdev->pdev_id);
842dd4f32aeSBjoern A. Zeeb if (ret) {
843dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to set kickout threshold on vdev %i: %d\n",
844dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ret);
845dd4f32aeSBjoern A. Zeeb return ret;
846dd4f32aeSBjoern A. Zeeb }
847dd4f32aeSBjoern A. Zeeb
848dd4f32aeSBjoern A. Zeeb param = WMI_VDEV_PARAM_AP_KEEPALIVE_MIN_IDLE_INACTIVE_TIME_SECS;
849dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, param,
850dd4f32aeSBjoern A. Zeeb ATH11K_KEEPALIVE_MIN_IDLE);
851dd4f32aeSBjoern A. Zeeb if (ret) {
852dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to set keepalive minimum idle time on vdev %i: %d\n",
853dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ret);
854dd4f32aeSBjoern A. Zeeb return ret;
855dd4f32aeSBjoern A. Zeeb }
856dd4f32aeSBjoern A. Zeeb
857dd4f32aeSBjoern A. Zeeb param = WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_IDLE_INACTIVE_TIME_SECS;
858dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, param,
859dd4f32aeSBjoern A. Zeeb ATH11K_KEEPALIVE_MAX_IDLE);
860dd4f32aeSBjoern A. Zeeb if (ret) {
861dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to set keepalive maximum idle time on vdev %i: %d\n",
862dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ret);
863dd4f32aeSBjoern A. Zeeb return ret;
864dd4f32aeSBjoern A. Zeeb }
865dd4f32aeSBjoern A. Zeeb
866dd4f32aeSBjoern A. Zeeb param = WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS;
867dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, param,
868dd4f32aeSBjoern A. Zeeb ATH11K_KEEPALIVE_MAX_UNRESPONSIVE);
869dd4f32aeSBjoern A. Zeeb if (ret) {
870dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to set keepalive maximum unresponsive time on vdev %i: %d\n",
871dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ret);
872dd4f32aeSBjoern A. Zeeb return ret;
873dd4f32aeSBjoern A. Zeeb }
874dd4f32aeSBjoern A. Zeeb
875dd4f32aeSBjoern A. Zeeb return 0;
876dd4f32aeSBjoern A. Zeeb }
877dd4f32aeSBjoern A. Zeeb
ath11k_mac_peer_cleanup_all(struct ath11k * ar)878dd4f32aeSBjoern A. Zeeb void ath11k_mac_peer_cleanup_all(struct ath11k *ar)
879dd4f32aeSBjoern A. Zeeb {
880dd4f32aeSBjoern A. Zeeb struct ath11k_peer *peer, *tmp;
881dd4f32aeSBjoern A. Zeeb struct ath11k_base *ab = ar->ab;
882dd4f32aeSBjoern A. Zeeb
883dd4f32aeSBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
884dd4f32aeSBjoern A. Zeeb
88528348caeSBjoern A. Zeeb mutex_lock(&ab->tbl_mtx_lock);
886dd4f32aeSBjoern A. Zeeb spin_lock_bh(&ab->base_lock);
887dd4f32aeSBjoern A. Zeeb list_for_each_entry_safe(peer, tmp, &ab->peers, list) {
888dd4f32aeSBjoern A. Zeeb ath11k_peer_rx_tid_cleanup(ar, peer);
88928348caeSBjoern A. Zeeb ath11k_peer_rhash_delete(ab, peer);
890dd4f32aeSBjoern A. Zeeb list_del(&peer->list);
891dd4f32aeSBjoern A. Zeeb kfree(peer);
892dd4f32aeSBjoern A. Zeeb }
893dd4f32aeSBjoern A. Zeeb spin_unlock_bh(&ab->base_lock);
89428348caeSBjoern A. Zeeb mutex_unlock(&ab->tbl_mtx_lock);
895dd4f32aeSBjoern A. Zeeb
896dd4f32aeSBjoern A. Zeeb ar->num_peers = 0;
897dd4f32aeSBjoern A. Zeeb ar->num_stations = 0;
898dd4f32aeSBjoern A. Zeeb }
899dd4f32aeSBjoern A. Zeeb
ath11k_mac_vdev_setup_sync(struct ath11k * ar)900dd4f32aeSBjoern A. Zeeb static inline int ath11k_mac_vdev_setup_sync(struct ath11k *ar)
901dd4f32aeSBjoern A. Zeeb {
902dd4f32aeSBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
903dd4f32aeSBjoern A. Zeeb
904dd4f32aeSBjoern A. Zeeb if (test_bit(ATH11K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))
905dd4f32aeSBjoern A. Zeeb return -ESHUTDOWN;
906dd4f32aeSBjoern A. Zeeb
907dd4f32aeSBjoern A. Zeeb if (!wait_for_completion_timeout(&ar->vdev_setup_done,
908dd4f32aeSBjoern A. Zeeb ATH11K_VDEV_SETUP_TIMEOUT_HZ))
909dd4f32aeSBjoern A. Zeeb return -ETIMEDOUT;
910dd4f32aeSBjoern A. Zeeb
911dd4f32aeSBjoern A. Zeeb return ar->last_wmi_vdev_start_status ? -EINVAL : 0;
912dd4f32aeSBjoern A. Zeeb }
913dd4f32aeSBjoern A. Zeeb
914dd4f32aeSBjoern A. Zeeb static void
ath11k_mac_get_any_chandef_iter(struct ieee80211_hw * hw,struct ieee80211_chanctx_conf * conf,void * data)915dd4f32aeSBjoern A. Zeeb ath11k_mac_get_any_chandef_iter(struct ieee80211_hw *hw,
916dd4f32aeSBjoern A. Zeeb struct ieee80211_chanctx_conf *conf,
917dd4f32aeSBjoern A. Zeeb void *data)
918dd4f32aeSBjoern A. Zeeb {
919dd4f32aeSBjoern A. Zeeb struct cfg80211_chan_def **def = data;
920dd4f32aeSBjoern A. Zeeb
921dd4f32aeSBjoern A. Zeeb *def = &conf->def;
922dd4f32aeSBjoern A. Zeeb }
923dd4f32aeSBjoern A. Zeeb
ath11k_mac_monitor_vdev_start(struct ath11k * ar,int vdev_id,struct cfg80211_chan_def * chandef)924dd4f32aeSBjoern A. Zeeb static int ath11k_mac_monitor_vdev_start(struct ath11k *ar, int vdev_id,
925dd4f32aeSBjoern A. Zeeb struct cfg80211_chan_def *chandef)
926dd4f32aeSBjoern A. Zeeb {
927dd4f32aeSBjoern A. Zeeb struct ieee80211_channel *channel;
928dd4f32aeSBjoern A. Zeeb struct wmi_vdev_start_req_arg arg = {};
929dd4f32aeSBjoern A. Zeeb int ret;
930dd4f32aeSBjoern A. Zeeb
931dd4f32aeSBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
932dd4f32aeSBjoern A. Zeeb
933dd4f32aeSBjoern A. Zeeb channel = chandef->chan;
934dd4f32aeSBjoern A. Zeeb
935dd4f32aeSBjoern A. Zeeb arg.vdev_id = vdev_id;
936dd4f32aeSBjoern A. Zeeb arg.channel.freq = channel->center_freq;
937dd4f32aeSBjoern A. Zeeb arg.channel.band_center_freq1 = chandef->center_freq1;
938dd4f32aeSBjoern A. Zeeb arg.channel.band_center_freq2 = chandef->center_freq2;
939dd4f32aeSBjoern A. Zeeb
940dd4f32aeSBjoern A. Zeeb arg.channel.mode = ath11k_phymodes[chandef->chan->band][chandef->width];
941dd4f32aeSBjoern A. Zeeb arg.channel.chan_radar = !!(channel->flags & IEEE80211_CHAN_RADAR);
942dd4f32aeSBjoern A. Zeeb
943dd4f32aeSBjoern A. Zeeb arg.channel.min_power = 0;
944dd4f32aeSBjoern A. Zeeb arg.channel.max_power = channel->max_power;
945dd4f32aeSBjoern A. Zeeb arg.channel.max_reg_power = channel->max_reg_power;
946dd4f32aeSBjoern A. Zeeb arg.channel.max_antenna_gain = channel->max_antenna_gain;
947dd4f32aeSBjoern A. Zeeb
948dd4f32aeSBjoern A. Zeeb arg.pref_tx_streams = ar->num_tx_chains;
949dd4f32aeSBjoern A. Zeeb arg.pref_rx_streams = ar->num_rx_chains;
950dd4f32aeSBjoern A. Zeeb
951dd4f32aeSBjoern A. Zeeb arg.channel.passive = !!(chandef->chan->flags & IEEE80211_CHAN_NO_IR);
952dd4f32aeSBjoern A. Zeeb
953dd4f32aeSBjoern A. Zeeb reinit_completion(&ar->vdev_setup_done);
954dd4f32aeSBjoern A. Zeeb reinit_completion(&ar->vdev_delete_done);
955dd4f32aeSBjoern A. Zeeb
956dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_vdev_start(ar, &arg, false);
957dd4f32aeSBjoern A. Zeeb if (ret) {
958dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to request monitor vdev %i start: %d\n",
959dd4f32aeSBjoern A. Zeeb vdev_id, ret);
960dd4f32aeSBjoern A. Zeeb return ret;
961dd4f32aeSBjoern A. Zeeb }
962dd4f32aeSBjoern A. Zeeb
963dd4f32aeSBjoern A. Zeeb ret = ath11k_mac_vdev_setup_sync(ar);
964dd4f32aeSBjoern A. Zeeb if (ret) {
965dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to synchronize setup for monitor vdev %i start: %d\n",
966dd4f32aeSBjoern A. Zeeb vdev_id, ret);
967dd4f32aeSBjoern A. Zeeb return ret;
968dd4f32aeSBjoern A. Zeeb }
969dd4f32aeSBjoern A. Zeeb
97028348caeSBjoern A. Zeeb ret = ath11k_wmi_vdev_up(ar, vdev_id, 0, ar->mac_addr, NULL, 0, 0);
971dd4f32aeSBjoern A. Zeeb if (ret) {
972dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to put up monitor vdev %i: %d\n",
973dd4f32aeSBjoern A. Zeeb vdev_id, ret);
974dd4f32aeSBjoern A. Zeeb goto vdev_stop;
975dd4f32aeSBjoern A. Zeeb }
976dd4f32aeSBjoern A. Zeeb
97728348caeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "monitor vdev %i started\n",
978dd4f32aeSBjoern A. Zeeb vdev_id);
979dd4f32aeSBjoern A. Zeeb
980dd4f32aeSBjoern A. Zeeb return 0;
981dd4f32aeSBjoern A. Zeeb
982dd4f32aeSBjoern A. Zeeb vdev_stop:
983dd4f32aeSBjoern A. Zeeb reinit_completion(&ar->vdev_setup_done);
984dd4f32aeSBjoern A. Zeeb
985dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_vdev_stop(ar, vdev_id);
986dd4f32aeSBjoern A. Zeeb if (ret) {
987dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to stop monitor vdev %i after start failure: %d\n",
988dd4f32aeSBjoern A. Zeeb vdev_id, ret);
989dd4f32aeSBjoern A. Zeeb return ret;
990dd4f32aeSBjoern A. Zeeb }
991dd4f32aeSBjoern A. Zeeb
992dd4f32aeSBjoern A. Zeeb ret = ath11k_mac_vdev_setup_sync(ar);
993dd4f32aeSBjoern A. Zeeb if (ret) {
994dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to synchronize setup for vdev %i stop: %d\n",
995dd4f32aeSBjoern A. Zeeb vdev_id, ret);
996dd4f32aeSBjoern A. Zeeb return ret;
997dd4f32aeSBjoern A. Zeeb }
998dd4f32aeSBjoern A. Zeeb
999dd4f32aeSBjoern A. Zeeb return -EIO;
1000dd4f32aeSBjoern A. Zeeb }
1001dd4f32aeSBjoern A. Zeeb
ath11k_mac_monitor_vdev_stop(struct ath11k * ar)1002dd4f32aeSBjoern A. Zeeb static int ath11k_mac_monitor_vdev_stop(struct ath11k *ar)
1003dd4f32aeSBjoern A. Zeeb {
1004dd4f32aeSBjoern A. Zeeb int ret;
1005dd4f32aeSBjoern A. Zeeb
1006dd4f32aeSBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
1007dd4f32aeSBjoern A. Zeeb
1008dd4f32aeSBjoern A. Zeeb reinit_completion(&ar->vdev_setup_done);
1009dd4f32aeSBjoern A. Zeeb
1010dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_vdev_stop(ar, ar->monitor_vdev_id);
1011dd4f32aeSBjoern A. Zeeb if (ret) {
1012dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to request monitor vdev %i stop: %d\n",
1013dd4f32aeSBjoern A. Zeeb ar->monitor_vdev_id, ret);
1014dd4f32aeSBjoern A. Zeeb return ret;
1015dd4f32aeSBjoern A. Zeeb }
1016dd4f32aeSBjoern A. Zeeb
1017dd4f32aeSBjoern A. Zeeb ret = ath11k_mac_vdev_setup_sync(ar);
1018dd4f32aeSBjoern A. Zeeb if (ret) {
1019dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to synchronize monitor vdev %i stop: %d\n",
1020dd4f32aeSBjoern A. Zeeb ar->monitor_vdev_id, ret);
1021dd4f32aeSBjoern A. Zeeb return ret;
1022dd4f32aeSBjoern A. Zeeb }
1023dd4f32aeSBjoern A. Zeeb
1024dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_vdev_down(ar, ar->monitor_vdev_id);
1025dd4f32aeSBjoern A. Zeeb if (ret) {
1026dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to put down monitor vdev %i: %d\n",
1027dd4f32aeSBjoern A. Zeeb ar->monitor_vdev_id, ret);
1028dd4f32aeSBjoern A. Zeeb return ret;
1029dd4f32aeSBjoern A. Zeeb }
1030dd4f32aeSBjoern A. Zeeb
103128348caeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "monitor vdev %i stopped\n",
1032dd4f32aeSBjoern A. Zeeb ar->monitor_vdev_id);
1033dd4f32aeSBjoern A. Zeeb
1034dd4f32aeSBjoern A. Zeeb return 0;
1035dd4f32aeSBjoern A. Zeeb }
1036dd4f32aeSBjoern A. Zeeb
ath11k_mac_monitor_vdev_create(struct ath11k * ar)1037dd4f32aeSBjoern A. Zeeb static int ath11k_mac_monitor_vdev_create(struct ath11k *ar)
1038dd4f32aeSBjoern A. Zeeb {
1039dd4f32aeSBjoern A. Zeeb struct ath11k_pdev *pdev = ar->pdev;
1040dd4f32aeSBjoern A. Zeeb struct vdev_create_params param = {};
1041dd4f32aeSBjoern A. Zeeb int bit, ret;
1042dd4f32aeSBjoern A. Zeeb u8 tmp_addr[6] = {0};
1043dd4f32aeSBjoern A. Zeeb u16 nss;
1044dd4f32aeSBjoern A. Zeeb
1045dd4f32aeSBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
1046dd4f32aeSBjoern A. Zeeb
1047dd4f32aeSBjoern A. Zeeb if (test_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags))
1048dd4f32aeSBjoern A. Zeeb return 0;
1049dd4f32aeSBjoern A. Zeeb
1050dd4f32aeSBjoern A. Zeeb if (ar->ab->free_vdev_map == 0) {
1051dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to find free vdev id for monitor vdev\n");
1052dd4f32aeSBjoern A. Zeeb return -ENOMEM;
1053dd4f32aeSBjoern A. Zeeb }
1054dd4f32aeSBjoern A. Zeeb
1055dd4f32aeSBjoern A. Zeeb bit = __ffs64(ar->ab->free_vdev_map);
1056dd4f32aeSBjoern A. Zeeb
1057dd4f32aeSBjoern A. Zeeb ar->monitor_vdev_id = bit;
1058dd4f32aeSBjoern A. Zeeb
1059dd4f32aeSBjoern A. Zeeb param.if_id = ar->monitor_vdev_id;
1060dd4f32aeSBjoern A. Zeeb param.type = WMI_VDEV_TYPE_MONITOR;
1061dd4f32aeSBjoern A. Zeeb param.subtype = WMI_VDEV_SUBTYPE_NONE;
1062dd4f32aeSBjoern A. Zeeb param.pdev_id = pdev->pdev_id;
1063dd4f32aeSBjoern A. Zeeb
1064dd4f32aeSBjoern A. Zeeb if (pdev->cap.supported_bands & WMI_HOST_WLAN_2G_CAP) {
1065dd4f32aeSBjoern A. Zeeb param.chains[NL80211_BAND_2GHZ].tx = ar->num_tx_chains;
1066dd4f32aeSBjoern A. Zeeb param.chains[NL80211_BAND_2GHZ].rx = ar->num_rx_chains;
1067dd4f32aeSBjoern A. Zeeb }
1068dd4f32aeSBjoern A. Zeeb if (pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP) {
1069dd4f32aeSBjoern A. Zeeb param.chains[NL80211_BAND_5GHZ].tx = ar->num_tx_chains;
1070dd4f32aeSBjoern A. Zeeb param.chains[NL80211_BAND_5GHZ].rx = ar->num_rx_chains;
1071dd4f32aeSBjoern A. Zeeb }
1072dd4f32aeSBjoern A. Zeeb
1073dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_vdev_create(ar, tmp_addr, ¶m);
1074dd4f32aeSBjoern A. Zeeb if (ret) {
1075dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to request monitor vdev %i creation: %d\n",
1076dd4f32aeSBjoern A. Zeeb ar->monitor_vdev_id, ret);
1077dd4f32aeSBjoern A. Zeeb ar->monitor_vdev_id = -1;
1078dd4f32aeSBjoern A. Zeeb return ret;
1079dd4f32aeSBjoern A. Zeeb }
1080dd4f32aeSBjoern A. Zeeb
1081dd4f32aeSBjoern A. Zeeb nss = get_num_chains(ar->cfg_tx_chainmask) ? : 1;
1082dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_vdev_set_param_cmd(ar, ar->monitor_vdev_id,
1083dd4f32aeSBjoern A. Zeeb WMI_VDEV_PARAM_NSS, nss);
1084dd4f32aeSBjoern A. Zeeb if (ret) {
1085dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to set vdev %d chainmask 0x%x, nss %d :%d\n",
1086dd4f32aeSBjoern A. Zeeb ar->monitor_vdev_id, ar->cfg_tx_chainmask, nss, ret);
1087dd4f32aeSBjoern A. Zeeb goto err_vdev_del;
1088dd4f32aeSBjoern A. Zeeb }
1089dd4f32aeSBjoern A. Zeeb
1090dd4f32aeSBjoern A. Zeeb ret = ath11k_mac_txpower_recalc(ar);
1091dd4f32aeSBjoern A. Zeeb if (ret) {
1092dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to recalc txpower for monitor vdev %d: %d\n",
1093dd4f32aeSBjoern A. Zeeb ar->monitor_vdev_id, ret);
1094dd4f32aeSBjoern A. Zeeb goto err_vdev_del;
1095dd4f32aeSBjoern A. Zeeb }
1096dd4f32aeSBjoern A. Zeeb
1097dd4f32aeSBjoern A. Zeeb ar->allocated_vdev_map |= 1LL << ar->monitor_vdev_id;
1098dd4f32aeSBjoern A. Zeeb ar->ab->free_vdev_map &= ~(1LL << ar->monitor_vdev_id);
1099dd4f32aeSBjoern A. Zeeb ar->num_created_vdevs++;
1100dd4f32aeSBjoern A. Zeeb set_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags);
1101dd4f32aeSBjoern A. Zeeb
110228348caeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "monitor vdev %d created\n",
1103dd4f32aeSBjoern A. Zeeb ar->monitor_vdev_id);
1104dd4f32aeSBjoern A. Zeeb
1105dd4f32aeSBjoern A. Zeeb return 0;
1106dd4f32aeSBjoern A. Zeeb
1107dd4f32aeSBjoern A. Zeeb err_vdev_del:
1108dd4f32aeSBjoern A. Zeeb ath11k_wmi_vdev_delete(ar, ar->monitor_vdev_id);
1109dd4f32aeSBjoern A. Zeeb ar->monitor_vdev_id = -1;
1110dd4f32aeSBjoern A. Zeeb return ret;
1111dd4f32aeSBjoern A. Zeeb }
1112dd4f32aeSBjoern A. Zeeb
ath11k_mac_monitor_vdev_delete(struct ath11k * ar)1113dd4f32aeSBjoern A. Zeeb static int ath11k_mac_monitor_vdev_delete(struct ath11k *ar)
1114dd4f32aeSBjoern A. Zeeb {
1115dd4f32aeSBjoern A. Zeeb int ret;
1116dd4f32aeSBjoern A. Zeeb unsigned long time_left;
1117dd4f32aeSBjoern A. Zeeb
1118dd4f32aeSBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
1119dd4f32aeSBjoern A. Zeeb
1120dd4f32aeSBjoern A. Zeeb if (!test_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags))
1121dd4f32aeSBjoern A. Zeeb return 0;
1122dd4f32aeSBjoern A. Zeeb
1123dd4f32aeSBjoern A. Zeeb reinit_completion(&ar->vdev_delete_done);
1124dd4f32aeSBjoern A. Zeeb
1125dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_vdev_delete(ar, ar->monitor_vdev_id);
1126dd4f32aeSBjoern A. Zeeb if (ret) {
1127dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to request wmi monitor vdev %i removal: %d\n",
1128dd4f32aeSBjoern A. Zeeb ar->monitor_vdev_id, ret);
1129dd4f32aeSBjoern A. Zeeb return ret;
1130dd4f32aeSBjoern A. Zeeb }
1131dd4f32aeSBjoern A. Zeeb
1132dd4f32aeSBjoern A. Zeeb time_left = wait_for_completion_timeout(&ar->vdev_delete_done,
1133dd4f32aeSBjoern A. Zeeb ATH11K_VDEV_DELETE_TIMEOUT_HZ);
1134dd4f32aeSBjoern A. Zeeb if (time_left == 0) {
1135dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "Timeout in receiving vdev delete response\n");
1136dd4f32aeSBjoern A. Zeeb } else {
113728348caeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "monitor vdev %d deleted\n",
1138dd4f32aeSBjoern A. Zeeb ar->monitor_vdev_id);
1139dd4f32aeSBjoern A. Zeeb
1140dd4f32aeSBjoern A. Zeeb ar->allocated_vdev_map &= ~(1LL << ar->monitor_vdev_id);
1141dd4f32aeSBjoern A. Zeeb ar->ab->free_vdev_map |= 1LL << (ar->monitor_vdev_id);
1142dd4f32aeSBjoern A. Zeeb ar->num_created_vdevs--;
1143dd4f32aeSBjoern A. Zeeb ar->monitor_vdev_id = -1;
1144dd4f32aeSBjoern A. Zeeb clear_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags);
1145dd4f32aeSBjoern A. Zeeb }
1146dd4f32aeSBjoern A. Zeeb
1147dd4f32aeSBjoern A. Zeeb return ret;
1148dd4f32aeSBjoern A. Zeeb }
1149dd4f32aeSBjoern A. Zeeb
ath11k_mac_monitor_start(struct ath11k * ar)1150dd4f32aeSBjoern A. Zeeb static int ath11k_mac_monitor_start(struct ath11k *ar)
1151dd4f32aeSBjoern A. Zeeb {
1152dd4f32aeSBjoern A. Zeeb struct cfg80211_chan_def *chandef = NULL;
1153dd4f32aeSBjoern A. Zeeb int ret;
1154dd4f32aeSBjoern A. Zeeb
1155dd4f32aeSBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
1156dd4f32aeSBjoern A. Zeeb
1157dd4f32aeSBjoern A. Zeeb if (test_bit(ATH11K_FLAG_MONITOR_STARTED, &ar->monitor_flags))
1158dd4f32aeSBjoern A. Zeeb return 0;
1159dd4f32aeSBjoern A. Zeeb
1160dd4f32aeSBjoern A. Zeeb ieee80211_iter_chan_contexts_atomic(ar->hw,
1161dd4f32aeSBjoern A. Zeeb ath11k_mac_get_any_chandef_iter,
1162dd4f32aeSBjoern A. Zeeb &chandef);
1163dd4f32aeSBjoern A. Zeeb if (!chandef)
1164dd4f32aeSBjoern A. Zeeb return 0;
1165dd4f32aeSBjoern A. Zeeb
1166dd4f32aeSBjoern A. Zeeb ret = ath11k_mac_monitor_vdev_start(ar, ar->monitor_vdev_id, chandef);
1167dd4f32aeSBjoern A. Zeeb if (ret) {
1168dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to start monitor vdev: %d\n", ret);
1169dd4f32aeSBjoern A. Zeeb ath11k_mac_monitor_vdev_delete(ar);
1170dd4f32aeSBjoern A. Zeeb return ret;
1171dd4f32aeSBjoern A. Zeeb }
1172dd4f32aeSBjoern A. Zeeb
1173dd4f32aeSBjoern A. Zeeb set_bit(ATH11K_FLAG_MONITOR_STARTED, &ar->monitor_flags);
1174dd4f32aeSBjoern A. Zeeb
1175dd4f32aeSBjoern A. Zeeb ar->num_started_vdevs++;
1176dd4f32aeSBjoern A. Zeeb ret = ath11k_dp_tx_htt_monitor_mode_ring_config(ar, false);
1177dd4f32aeSBjoern A. Zeeb if (ret) {
1178dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to configure htt monitor mode ring during start: %d",
1179dd4f32aeSBjoern A. Zeeb ret);
1180dd4f32aeSBjoern A. Zeeb return ret;
1181dd4f32aeSBjoern A. Zeeb }
1182dd4f32aeSBjoern A. Zeeb
118328348caeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "monitor started\n");
1184dd4f32aeSBjoern A. Zeeb
1185dd4f32aeSBjoern A. Zeeb return 0;
1186dd4f32aeSBjoern A. Zeeb }
1187dd4f32aeSBjoern A. Zeeb
ath11k_mac_monitor_stop(struct ath11k * ar)1188dd4f32aeSBjoern A. Zeeb static int ath11k_mac_monitor_stop(struct ath11k *ar)
1189dd4f32aeSBjoern A. Zeeb {
1190dd4f32aeSBjoern A. Zeeb int ret;
1191dd4f32aeSBjoern A. Zeeb
1192dd4f32aeSBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
1193dd4f32aeSBjoern A. Zeeb
1194dd4f32aeSBjoern A. Zeeb if (!test_bit(ATH11K_FLAG_MONITOR_STARTED, &ar->monitor_flags))
1195dd4f32aeSBjoern A. Zeeb return 0;
1196dd4f32aeSBjoern A. Zeeb
1197dd4f32aeSBjoern A. Zeeb ret = ath11k_mac_monitor_vdev_stop(ar);
1198dd4f32aeSBjoern A. Zeeb if (ret) {
1199dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to stop monitor vdev: %d\n", ret);
1200dd4f32aeSBjoern A. Zeeb return ret;
1201dd4f32aeSBjoern A. Zeeb }
1202dd4f32aeSBjoern A. Zeeb
1203dd4f32aeSBjoern A. Zeeb clear_bit(ATH11K_FLAG_MONITOR_STARTED, &ar->monitor_flags);
1204dd4f32aeSBjoern A. Zeeb ar->num_started_vdevs--;
1205dd4f32aeSBjoern A. Zeeb
1206dd4f32aeSBjoern A. Zeeb ret = ath11k_dp_tx_htt_monitor_mode_ring_config(ar, true);
1207dd4f32aeSBjoern A. Zeeb if (ret) {
1208dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to configure htt monitor mode ring during stop: %d",
1209dd4f32aeSBjoern A. Zeeb ret);
1210dd4f32aeSBjoern A. Zeeb return ret;
1211dd4f32aeSBjoern A. Zeeb }
1212dd4f32aeSBjoern A. Zeeb
121328348caeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "monitor stopped ret %d\n", ret);
1214dd4f32aeSBjoern A. Zeeb
1215dd4f32aeSBjoern A. Zeeb return 0;
1216dd4f32aeSBjoern A. Zeeb }
1217dd4f32aeSBjoern A. Zeeb
ath11k_mac_vif_setup_ps(struct ath11k_vif * arvif)1218dd4f32aeSBjoern A. Zeeb static int ath11k_mac_vif_setup_ps(struct ath11k_vif *arvif)
1219dd4f32aeSBjoern A. Zeeb {
1220dd4f32aeSBjoern A. Zeeb struct ath11k *ar = arvif->ar;
1221dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif = arvif->vif;
1222dd4f32aeSBjoern A. Zeeb struct ieee80211_conf *conf = &ar->hw->conf;
1223dd4f32aeSBjoern A. Zeeb enum wmi_sta_powersave_param param;
1224dd4f32aeSBjoern A. Zeeb enum wmi_sta_ps_mode psmode;
1225dd4f32aeSBjoern A. Zeeb int ret;
1226dd4f32aeSBjoern A. Zeeb int timeout;
1227dd4f32aeSBjoern A. Zeeb bool enable_ps;
1228dd4f32aeSBjoern A. Zeeb
1229dd4f32aeSBjoern A. Zeeb lockdep_assert_held(&arvif->ar->conf_mutex);
1230dd4f32aeSBjoern A. Zeeb
1231dd4f32aeSBjoern A. Zeeb if (arvif->vif->type != NL80211_IFTYPE_STATION)
1232dd4f32aeSBjoern A. Zeeb return 0;
1233dd4f32aeSBjoern A. Zeeb
1234dd4f32aeSBjoern A. Zeeb enable_ps = arvif->ps;
1235dd4f32aeSBjoern A. Zeeb
1236dd4f32aeSBjoern A. Zeeb if (!arvif->is_started) {
1237dd4f32aeSBjoern A. Zeeb /* mac80211 can update vif powersave state while disconnected.
1238dd4f32aeSBjoern A. Zeeb * Firmware doesn't behave nicely and consumes more power than
1239dd4f32aeSBjoern A. Zeeb * necessary if PS is disabled on a non-started vdev. Hence
1240dd4f32aeSBjoern A. Zeeb * force-enable PS for non-running vdevs.
1241dd4f32aeSBjoern A. Zeeb */
1242dd4f32aeSBjoern A. Zeeb psmode = WMI_STA_PS_MODE_ENABLED;
1243dd4f32aeSBjoern A. Zeeb } else if (enable_ps) {
1244dd4f32aeSBjoern A. Zeeb psmode = WMI_STA_PS_MODE_ENABLED;
1245dd4f32aeSBjoern A. Zeeb param = WMI_STA_PS_PARAM_INACTIVITY_TIME;
1246dd4f32aeSBjoern A. Zeeb
1247dd4f32aeSBjoern A. Zeeb timeout = conf->dynamic_ps_timeout;
1248dd4f32aeSBjoern A. Zeeb if (timeout == 0) {
1249dd4f32aeSBjoern A. Zeeb /* firmware doesn't like 0 */
1250dd4f32aeSBjoern A. Zeeb timeout = ieee80211_tu_to_usec(vif->bss_conf.beacon_int) / 1000;
1251dd4f32aeSBjoern A. Zeeb }
1252dd4f32aeSBjoern A. Zeeb
1253dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_set_sta_ps_param(ar, arvif->vdev_id, param,
1254dd4f32aeSBjoern A. Zeeb timeout);
1255dd4f32aeSBjoern A. Zeeb if (ret) {
1256dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to set inactivity time for vdev %d: %i\n",
1257dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ret);
1258dd4f32aeSBjoern A. Zeeb return ret;
1259dd4f32aeSBjoern A. Zeeb }
1260dd4f32aeSBjoern A. Zeeb } else {
1261dd4f32aeSBjoern A. Zeeb psmode = WMI_STA_PS_MODE_DISABLED;
1262dd4f32aeSBjoern A. Zeeb }
1263dd4f32aeSBjoern A. Zeeb
126428348caeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev %d psmode %s\n",
1265dd4f32aeSBjoern A. Zeeb arvif->vdev_id, psmode ? "enable" : "disable");
1266dd4f32aeSBjoern A. Zeeb
1267dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_pdev_set_ps_mode(ar, arvif->vdev_id, psmode);
1268dd4f32aeSBjoern A. Zeeb if (ret) {
1269dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to set sta power save mode %d for vdev %d: %d\n",
1270dd4f32aeSBjoern A. Zeeb psmode, arvif->vdev_id, ret);
1271dd4f32aeSBjoern A. Zeeb return ret;
1272dd4f32aeSBjoern A. Zeeb }
1273dd4f32aeSBjoern A. Zeeb
1274dd4f32aeSBjoern A. Zeeb return 0;
1275dd4f32aeSBjoern A. Zeeb }
1276dd4f32aeSBjoern A. Zeeb
ath11k_mac_config_ps(struct ath11k * ar)1277dd4f32aeSBjoern A. Zeeb static int ath11k_mac_config_ps(struct ath11k *ar)
1278dd4f32aeSBjoern A. Zeeb {
1279dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif;
1280dd4f32aeSBjoern A. Zeeb int ret = 0;
1281dd4f32aeSBjoern A. Zeeb
1282dd4f32aeSBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
1283dd4f32aeSBjoern A. Zeeb
1284dd4f32aeSBjoern A. Zeeb list_for_each_entry(arvif, &ar->arvifs, list) {
1285dd4f32aeSBjoern A. Zeeb ret = ath11k_mac_vif_setup_ps(arvif);
1286dd4f32aeSBjoern A. Zeeb if (ret) {
1287dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to setup powersave: %d\n", ret);
1288dd4f32aeSBjoern A. Zeeb break;
1289dd4f32aeSBjoern A. Zeeb }
1290dd4f32aeSBjoern A. Zeeb }
1291dd4f32aeSBjoern A. Zeeb
1292dd4f32aeSBjoern A. Zeeb return ret;
1293dd4f32aeSBjoern A. Zeeb }
1294dd4f32aeSBjoern A. Zeeb
ath11k_mac_op_config(struct ieee80211_hw * hw,u32 changed)1295dd4f32aeSBjoern A. Zeeb static int ath11k_mac_op_config(struct ieee80211_hw *hw, u32 changed)
1296dd4f32aeSBjoern A. Zeeb {
1297dd4f32aeSBjoern A. Zeeb struct ath11k *ar = hw->priv;
1298dd4f32aeSBjoern A. Zeeb struct ieee80211_conf *conf = &hw->conf;
1299dd4f32aeSBjoern A. Zeeb int ret = 0;
1300dd4f32aeSBjoern A. Zeeb
1301dd4f32aeSBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
1302dd4f32aeSBjoern A. Zeeb
1303dd4f32aeSBjoern A. Zeeb if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
1304dd4f32aeSBjoern A. Zeeb if (conf->flags & IEEE80211_CONF_MONITOR) {
1305dd4f32aeSBjoern A. Zeeb set_bit(ATH11K_FLAG_MONITOR_CONF_ENABLED, &ar->monitor_flags);
1306dd4f32aeSBjoern A. Zeeb
1307dd4f32aeSBjoern A. Zeeb if (test_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED,
1308dd4f32aeSBjoern A. Zeeb &ar->monitor_flags))
1309dd4f32aeSBjoern A. Zeeb goto out;
1310dd4f32aeSBjoern A. Zeeb
1311dd4f32aeSBjoern A. Zeeb ret = ath11k_mac_monitor_vdev_create(ar);
1312dd4f32aeSBjoern A. Zeeb if (ret) {
1313dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to create monitor vdev: %d",
1314dd4f32aeSBjoern A. Zeeb ret);
1315dd4f32aeSBjoern A. Zeeb goto out;
1316dd4f32aeSBjoern A. Zeeb }
1317dd4f32aeSBjoern A. Zeeb
1318dd4f32aeSBjoern A. Zeeb ret = ath11k_mac_monitor_start(ar);
1319dd4f32aeSBjoern A. Zeeb if (ret) {
1320dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to start monitor: %d",
1321dd4f32aeSBjoern A. Zeeb ret);
1322dd4f32aeSBjoern A. Zeeb goto err_mon_del;
1323dd4f32aeSBjoern A. Zeeb }
1324dd4f32aeSBjoern A. Zeeb } else {
1325dd4f32aeSBjoern A. Zeeb clear_bit(ATH11K_FLAG_MONITOR_CONF_ENABLED, &ar->monitor_flags);
1326dd4f32aeSBjoern A. Zeeb
1327dd4f32aeSBjoern A. Zeeb if (!test_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED,
1328dd4f32aeSBjoern A. Zeeb &ar->monitor_flags))
1329dd4f32aeSBjoern A. Zeeb goto out;
1330dd4f32aeSBjoern A. Zeeb
1331dd4f32aeSBjoern A. Zeeb ret = ath11k_mac_monitor_stop(ar);
1332dd4f32aeSBjoern A. Zeeb if (ret) {
1333dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to stop monitor: %d",
1334dd4f32aeSBjoern A. Zeeb ret);
1335dd4f32aeSBjoern A. Zeeb goto out;
1336dd4f32aeSBjoern A. Zeeb }
1337dd4f32aeSBjoern A. Zeeb
1338dd4f32aeSBjoern A. Zeeb ret = ath11k_mac_monitor_vdev_delete(ar);
1339dd4f32aeSBjoern A. Zeeb if (ret) {
1340dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to delete monitor vdev: %d",
1341dd4f32aeSBjoern A. Zeeb ret);
1342dd4f32aeSBjoern A. Zeeb goto out;
1343dd4f32aeSBjoern A. Zeeb }
1344dd4f32aeSBjoern A. Zeeb }
1345dd4f32aeSBjoern A. Zeeb }
1346dd4f32aeSBjoern A. Zeeb
1347dd4f32aeSBjoern A. Zeeb out:
1348dd4f32aeSBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
1349dd4f32aeSBjoern A. Zeeb return ret;
1350dd4f32aeSBjoern A. Zeeb
1351dd4f32aeSBjoern A. Zeeb err_mon_del:
1352dd4f32aeSBjoern A. Zeeb ath11k_mac_monitor_vdev_delete(ar);
1353dd4f32aeSBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
1354dd4f32aeSBjoern A. Zeeb return ret;
1355dd4f32aeSBjoern A. Zeeb }
1356dd4f32aeSBjoern A. Zeeb
ath11k_mac_setup_nontx_vif_rsnie(struct ath11k_vif * arvif,bool tx_arvif_rsnie_present,const u8 * profile,u8 profile_len)135728348caeSBjoern A. Zeeb static void ath11k_mac_setup_nontx_vif_rsnie(struct ath11k_vif *arvif,
135828348caeSBjoern A. Zeeb bool tx_arvif_rsnie_present,
135928348caeSBjoern A. Zeeb const u8 *profile, u8 profile_len)
1360dd4f32aeSBjoern A. Zeeb {
136128348caeSBjoern A. Zeeb if (cfg80211_find_ie(WLAN_EID_RSN, profile, profile_len)) {
136228348caeSBjoern A. Zeeb arvif->rsnie_present = true;
136328348caeSBjoern A. Zeeb } else if (tx_arvif_rsnie_present) {
136428348caeSBjoern A. Zeeb int i;
136528348caeSBjoern A. Zeeb u8 nie_len;
136628348caeSBjoern A. Zeeb const u8 *nie = cfg80211_find_ext_ie(WLAN_EID_EXT_NON_INHERITANCE,
136728348caeSBjoern A. Zeeb profile, profile_len);
136828348caeSBjoern A. Zeeb if (!nie)
136928348caeSBjoern A. Zeeb return;
1370dd4f32aeSBjoern A. Zeeb
137128348caeSBjoern A. Zeeb nie_len = nie[1];
137228348caeSBjoern A. Zeeb nie += 2;
137328348caeSBjoern A. Zeeb for (i = 0; i < nie_len; i++) {
137428348caeSBjoern A. Zeeb if (nie[i] == WLAN_EID_RSN) {
137528348caeSBjoern A. Zeeb arvif->rsnie_present = false;
137628348caeSBjoern A. Zeeb break;
137728348caeSBjoern A. Zeeb }
137828348caeSBjoern A. Zeeb }
137928348caeSBjoern A. Zeeb }
1380dd4f32aeSBjoern A. Zeeb }
1381dd4f32aeSBjoern A. Zeeb
ath11k_mac_set_nontx_vif_params(struct ath11k_vif * tx_arvif,struct ath11k_vif * arvif,struct sk_buff * bcn)138228348caeSBjoern A. Zeeb static bool ath11k_mac_set_nontx_vif_params(struct ath11k_vif *tx_arvif,
138328348caeSBjoern A. Zeeb struct ath11k_vif *arvif,
138428348caeSBjoern A. Zeeb struct sk_buff *bcn)
138528348caeSBjoern A. Zeeb {
138628348caeSBjoern A. Zeeb struct ieee80211_mgmt *mgmt;
138728348caeSBjoern A. Zeeb const u8 *ies, *profile, *next_profile;
138828348caeSBjoern A. Zeeb int ies_len;
138928348caeSBjoern A. Zeeb
1390dd4f32aeSBjoern A. Zeeb ies = bcn->data + ieee80211_get_hdrlen_from_skb(bcn);
139128348caeSBjoern A. Zeeb mgmt = (struct ieee80211_mgmt *)bcn->data;
139228348caeSBjoern A. Zeeb ies += sizeof(mgmt->u.beacon);
139328348caeSBjoern A. Zeeb ies_len = skb_tail_pointer(bcn) - ies;
139428348caeSBjoern A. Zeeb
139528348caeSBjoern A. Zeeb ies = cfg80211_find_ie(WLAN_EID_MULTIPLE_BSSID, ies, ies_len);
139628348caeSBjoern A. Zeeb arvif->rsnie_present = tx_arvif->rsnie_present;
139728348caeSBjoern A. Zeeb
139828348caeSBjoern A. Zeeb while (ies) {
139928348caeSBjoern A. Zeeb u8 mbssid_len;
140028348caeSBjoern A. Zeeb
140128348caeSBjoern A. Zeeb ies_len -= (2 + ies[1]);
140228348caeSBjoern A. Zeeb mbssid_len = ies[1] - 1;
140328348caeSBjoern A. Zeeb profile = &ies[3];
140428348caeSBjoern A. Zeeb
140528348caeSBjoern A. Zeeb while (mbssid_len) {
140628348caeSBjoern A. Zeeb u8 profile_len;
140728348caeSBjoern A. Zeeb
140828348caeSBjoern A. Zeeb profile_len = profile[1];
140928348caeSBjoern A. Zeeb next_profile = profile + (2 + profile_len);
141028348caeSBjoern A. Zeeb mbssid_len -= (2 + profile_len);
141128348caeSBjoern A. Zeeb
141228348caeSBjoern A. Zeeb profile += 2;
141328348caeSBjoern A. Zeeb profile_len -= (2 + profile[1]);
141428348caeSBjoern A. Zeeb profile += (2 + profile[1]); /* nontx capabilities */
141528348caeSBjoern A. Zeeb profile_len -= (2 + profile[1]);
141628348caeSBjoern A. Zeeb profile += (2 + profile[1]); /* SSID */
141728348caeSBjoern A. Zeeb if (profile[2] == arvif->vif->bss_conf.bssid_index) {
141828348caeSBjoern A. Zeeb profile_len -= 5;
141928348caeSBjoern A. Zeeb profile = profile + 5;
142028348caeSBjoern A. Zeeb ath11k_mac_setup_nontx_vif_rsnie(arvif,
142128348caeSBjoern A. Zeeb tx_arvif->rsnie_present,
142228348caeSBjoern A. Zeeb profile,
142328348caeSBjoern A. Zeeb profile_len);
142428348caeSBjoern A. Zeeb return true;
142528348caeSBjoern A. Zeeb }
142628348caeSBjoern A. Zeeb profile = next_profile;
142728348caeSBjoern A. Zeeb }
142828348caeSBjoern A. Zeeb ies = cfg80211_find_ie(WLAN_EID_MULTIPLE_BSSID, profile,
142928348caeSBjoern A. Zeeb ies_len);
143028348caeSBjoern A. Zeeb }
143128348caeSBjoern A. Zeeb
143228348caeSBjoern A. Zeeb return false;
143328348caeSBjoern A. Zeeb }
143428348caeSBjoern A. Zeeb
ath11k_mac_set_vif_params(struct ath11k_vif * arvif,struct sk_buff * bcn)143528348caeSBjoern A. Zeeb static void ath11k_mac_set_vif_params(struct ath11k_vif *arvif,
143628348caeSBjoern A. Zeeb struct sk_buff *bcn)
143728348caeSBjoern A. Zeeb {
143828348caeSBjoern A. Zeeb struct ieee80211_mgmt *mgmt;
143928348caeSBjoern A. Zeeb u8 *ies;
144028348caeSBjoern A. Zeeb
144128348caeSBjoern A. Zeeb ies = bcn->data + ieee80211_get_hdrlen_from_skb(bcn);
144228348caeSBjoern A. Zeeb mgmt = (struct ieee80211_mgmt *)bcn->data;
1443dd4f32aeSBjoern A. Zeeb ies += sizeof(mgmt->u.beacon);
1444dd4f32aeSBjoern A. Zeeb
1445dd4f32aeSBjoern A. Zeeb if (cfg80211_find_ie(WLAN_EID_RSN, ies, (skb_tail_pointer(bcn) - ies)))
1446dd4f32aeSBjoern A. Zeeb arvif->rsnie_present = true;
1447dd4f32aeSBjoern A. Zeeb else
1448dd4f32aeSBjoern A. Zeeb arvif->rsnie_present = false;
1449dd4f32aeSBjoern A. Zeeb
1450dd4f32aeSBjoern A. Zeeb if (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1451dd4f32aeSBjoern A. Zeeb WLAN_OUI_TYPE_MICROSOFT_WPA,
1452dd4f32aeSBjoern A. Zeeb ies, (skb_tail_pointer(bcn) - ies)))
1453dd4f32aeSBjoern A. Zeeb arvif->wpaie_present = true;
1454dd4f32aeSBjoern A. Zeeb else
1455dd4f32aeSBjoern A. Zeeb arvif->wpaie_present = false;
145628348caeSBjoern A. Zeeb }
1457dd4f32aeSBjoern A. Zeeb
ath11k_mac_setup_bcn_tmpl_ema(struct ath11k_vif * arvif)145828348caeSBjoern A. Zeeb static int ath11k_mac_setup_bcn_tmpl_ema(struct ath11k_vif *arvif)
145928348caeSBjoern A. Zeeb {
146028348caeSBjoern A. Zeeb struct ath11k_vif *tx_arvif;
146128348caeSBjoern A. Zeeb struct ieee80211_ema_beacons *beacons;
146228348caeSBjoern A. Zeeb int ret = 0;
146328348caeSBjoern A. Zeeb bool nontx_vif_params_set = false;
146428348caeSBjoern A. Zeeb u32 params = 0;
146528348caeSBjoern A. Zeeb u8 i = 0;
1466dd4f32aeSBjoern A. Zeeb
146728348caeSBjoern A. Zeeb tx_arvif = (void *)arvif->vif->mbssid_tx_vif->drv_priv;
146828348caeSBjoern A. Zeeb
146928348caeSBjoern A. Zeeb beacons = ieee80211_beacon_get_template_ema_list(tx_arvif->ar->hw,
147028348caeSBjoern A. Zeeb tx_arvif->vif, 0);
147128348caeSBjoern A. Zeeb if (!beacons || !beacons->cnt) {
147228348caeSBjoern A. Zeeb ath11k_warn(arvif->ar->ab,
147328348caeSBjoern A. Zeeb "failed to get ema beacon templates from mac80211\n");
147428348caeSBjoern A. Zeeb return -EPERM;
147528348caeSBjoern A. Zeeb }
147628348caeSBjoern A. Zeeb
147728348caeSBjoern A. Zeeb if (tx_arvif == arvif)
147828348caeSBjoern A. Zeeb ath11k_mac_set_vif_params(tx_arvif, beacons->bcn[0].skb);
147928348caeSBjoern A. Zeeb else
148028348caeSBjoern A. Zeeb arvif->wpaie_present = tx_arvif->wpaie_present;
148128348caeSBjoern A. Zeeb
148228348caeSBjoern A. Zeeb for (i = 0; i < beacons->cnt; i++) {
148328348caeSBjoern A. Zeeb if (tx_arvif != arvif && !nontx_vif_params_set)
148428348caeSBjoern A. Zeeb nontx_vif_params_set =
148528348caeSBjoern A. Zeeb ath11k_mac_set_nontx_vif_params(tx_arvif, arvif,
148628348caeSBjoern A. Zeeb beacons->bcn[i].skb);
148728348caeSBjoern A. Zeeb
148828348caeSBjoern A. Zeeb params = beacons->cnt;
148928348caeSBjoern A. Zeeb params |= (i << WMI_EMA_TMPL_IDX_SHIFT);
149028348caeSBjoern A. Zeeb params |= ((!i ? 1 : 0) << WMI_EMA_FIRST_TMPL_SHIFT);
149128348caeSBjoern A. Zeeb params |= ((i + 1 == beacons->cnt ? 1 : 0) << WMI_EMA_LAST_TMPL_SHIFT);
149228348caeSBjoern A. Zeeb
149328348caeSBjoern A. Zeeb ret = ath11k_wmi_bcn_tmpl(tx_arvif->ar, tx_arvif->vdev_id,
149428348caeSBjoern A. Zeeb &beacons->bcn[i].offs,
149528348caeSBjoern A. Zeeb beacons->bcn[i].skb, params);
149628348caeSBjoern A. Zeeb if (ret) {
149728348caeSBjoern A. Zeeb ath11k_warn(tx_arvif->ar->ab,
149828348caeSBjoern A. Zeeb "failed to set ema beacon template id %i error %d\n",
149928348caeSBjoern A. Zeeb i, ret);
150028348caeSBjoern A. Zeeb break;
150128348caeSBjoern A. Zeeb }
150228348caeSBjoern A. Zeeb }
150328348caeSBjoern A. Zeeb
150428348caeSBjoern A. Zeeb ieee80211_beacon_free_ema_list(beacons);
150528348caeSBjoern A. Zeeb
150628348caeSBjoern A. Zeeb if (tx_arvif != arvif && !nontx_vif_params_set)
150728348caeSBjoern A. Zeeb return -EINVAL; /* Profile not found in the beacons */
150828348caeSBjoern A. Zeeb
150928348caeSBjoern A. Zeeb return ret;
151028348caeSBjoern A. Zeeb }
151128348caeSBjoern A. Zeeb
ath11k_mac_setup_bcn_tmpl_mbssid(struct ath11k_vif * arvif)151228348caeSBjoern A. Zeeb static int ath11k_mac_setup_bcn_tmpl_mbssid(struct ath11k_vif *arvif)
151328348caeSBjoern A. Zeeb {
151428348caeSBjoern A. Zeeb struct ath11k *ar = arvif->ar;
151528348caeSBjoern A. Zeeb struct ath11k_base *ab = ar->ab;
151628348caeSBjoern A. Zeeb struct ath11k_vif *tx_arvif = arvif;
151728348caeSBjoern A. Zeeb struct ieee80211_hw *hw = ar->hw;
151828348caeSBjoern A. Zeeb struct ieee80211_vif *vif = arvif->vif;
151928348caeSBjoern A. Zeeb struct ieee80211_mutable_offsets offs = {};
152028348caeSBjoern A. Zeeb struct sk_buff *bcn;
152128348caeSBjoern A. Zeeb int ret;
152228348caeSBjoern A. Zeeb
152328348caeSBjoern A. Zeeb if (arvif->vif->mbssid_tx_vif) {
152428348caeSBjoern A. Zeeb tx_arvif = (void *)arvif->vif->mbssid_tx_vif->drv_priv;
152528348caeSBjoern A. Zeeb if (tx_arvif != arvif) {
152628348caeSBjoern A. Zeeb ar = tx_arvif->ar;
152728348caeSBjoern A. Zeeb ab = ar->ab;
152828348caeSBjoern A. Zeeb hw = ar->hw;
152928348caeSBjoern A. Zeeb vif = tx_arvif->vif;
153028348caeSBjoern A. Zeeb }
153128348caeSBjoern A. Zeeb }
153228348caeSBjoern A. Zeeb
153328348caeSBjoern A. Zeeb bcn = ieee80211_beacon_get_template(hw, vif, &offs, 0);
153428348caeSBjoern A. Zeeb if (!bcn) {
153528348caeSBjoern A. Zeeb ath11k_warn(ab, "failed to get beacon template from mac80211\n");
153628348caeSBjoern A. Zeeb return -EPERM;
153728348caeSBjoern A. Zeeb }
153828348caeSBjoern A. Zeeb
153928348caeSBjoern A. Zeeb if (tx_arvif == arvif)
154028348caeSBjoern A. Zeeb ath11k_mac_set_vif_params(tx_arvif, bcn);
154128348caeSBjoern A. Zeeb else if (!ath11k_mac_set_nontx_vif_params(tx_arvif, arvif, bcn))
154228348caeSBjoern A. Zeeb return -EINVAL;
154328348caeSBjoern A. Zeeb
154428348caeSBjoern A. Zeeb ret = ath11k_wmi_bcn_tmpl(ar, arvif->vdev_id, &offs, bcn, 0);
1545dd4f32aeSBjoern A. Zeeb kfree_skb(bcn);
1546dd4f32aeSBjoern A. Zeeb
1547dd4f32aeSBjoern A. Zeeb if (ret)
1548dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, "failed to submit beacon template command: %d\n",
1549dd4f32aeSBjoern A. Zeeb ret);
1550dd4f32aeSBjoern A. Zeeb
1551dd4f32aeSBjoern A. Zeeb return ret;
1552dd4f32aeSBjoern A. Zeeb }
1553dd4f32aeSBjoern A. Zeeb
ath11k_mac_setup_bcn_tmpl(struct ath11k_vif * arvif)155428348caeSBjoern A. Zeeb static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif)
155528348caeSBjoern A. Zeeb {
155628348caeSBjoern A. Zeeb struct ieee80211_vif *vif = arvif->vif;
155728348caeSBjoern A. Zeeb
155828348caeSBjoern A. Zeeb if (arvif->vdev_type != WMI_VDEV_TYPE_AP)
155928348caeSBjoern A. Zeeb return 0;
156028348caeSBjoern A. Zeeb
156128348caeSBjoern A. Zeeb /* Target does not expect beacon templates for the already up
156228348caeSBjoern A. Zeeb * non-transmitting interfaces, and results in a crash if sent.
156328348caeSBjoern A. Zeeb */
156428348caeSBjoern A. Zeeb if (vif->mbssid_tx_vif &&
156528348caeSBjoern A. Zeeb arvif != (void *)vif->mbssid_tx_vif->drv_priv && arvif->is_up)
156628348caeSBjoern A. Zeeb return 0;
156728348caeSBjoern A. Zeeb
156828348caeSBjoern A. Zeeb if (vif->bss_conf.ema_ap && vif->mbssid_tx_vif)
156928348caeSBjoern A. Zeeb return ath11k_mac_setup_bcn_tmpl_ema(arvif);
157028348caeSBjoern A. Zeeb
157128348caeSBjoern A. Zeeb return ath11k_mac_setup_bcn_tmpl_mbssid(arvif);
157228348caeSBjoern A. Zeeb }
157328348caeSBjoern A. Zeeb
ath11k_mac_bcn_tx_event(struct ath11k_vif * arvif)1574dd4f32aeSBjoern A. Zeeb void ath11k_mac_bcn_tx_event(struct ath11k_vif *arvif)
1575dd4f32aeSBjoern A. Zeeb {
1576dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif = arvif->vif;
1577dd4f32aeSBjoern A. Zeeb
157828348caeSBjoern A. Zeeb if (!vif->bss_conf.color_change_active && !arvif->bcca_zero_sent)
1579dd4f32aeSBjoern A. Zeeb return;
1580dd4f32aeSBjoern A. Zeeb
158128348caeSBjoern A. Zeeb if (vif->bss_conf.color_change_active &&
158228348caeSBjoern A. Zeeb ieee80211_beacon_cntdwn_is_complete(vif)) {
1583dd4f32aeSBjoern A. Zeeb arvif->bcca_zero_sent = true;
1584dd4f32aeSBjoern A. Zeeb ieee80211_color_change_finish(vif);
1585dd4f32aeSBjoern A. Zeeb return;
1586dd4f32aeSBjoern A. Zeeb }
1587dd4f32aeSBjoern A. Zeeb
1588dd4f32aeSBjoern A. Zeeb arvif->bcca_zero_sent = false;
1589dd4f32aeSBjoern A. Zeeb
159028348caeSBjoern A. Zeeb if (vif->bss_conf.color_change_active)
1591dd4f32aeSBjoern A. Zeeb ieee80211_beacon_update_cntdwn(vif);
1592dd4f32aeSBjoern A. Zeeb ath11k_mac_setup_bcn_tmpl(arvif);
1593dd4f32aeSBjoern A. Zeeb }
1594dd4f32aeSBjoern A. Zeeb
ath11k_control_beaconing(struct ath11k_vif * arvif,struct ieee80211_bss_conf * info)1595dd4f32aeSBjoern A. Zeeb static void ath11k_control_beaconing(struct ath11k_vif *arvif,
1596dd4f32aeSBjoern A. Zeeb struct ieee80211_bss_conf *info)
1597dd4f32aeSBjoern A. Zeeb {
1598dd4f32aeSBjoern A. Zeeb struct ath11k *ar = arvif->ar;
159928348caeSBjoern A. Zeeb struct ath11k_vif *tx_arvif = NULL;
1600dd4f32aeSBjoern A. Zeeb int ret = 0;
1601dd4f32aeSBjoern A. Zeeb
1602dd4f32aeSBjoern A. Zeeb lockdep_assert_held(&arvif->ar->conf_mutex);
1603dd4f32aeSBjoern A. Zeeb
1604dd4f32aeSBjoern A. Zeeb if (!info->enable_beacon) {
1605dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_vdev_down(ar, arvif->vdev_id);
1606dd4f32aeSBjoern A. Zeeb if (ret)
1607dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to down vdev_id %i: %d\n",
1608dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ret);
1609dd4f32aeSBjoern A. Zeeb
1610dd4f32aeSBjoern A. Zeeb arvif->is_up = false;
1611dd4f32aeSBjoern A. Zeeb return;
1612dd4f32aeSBjoern A. Zeeb }
1613dd4f32aeSBjoern A. Zeeb
1614dd4f32aeSBjoern A. Zeeb /* Install the beacon template to the FW */
1615dd4f32aeSBjoern A. Zeeb ret = ath11k_mac_setup_bcn_tmpl(arvif);
1616dd4f32aeSBjoern A. Zeeb if (ret) {
1617dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to update bcn tmpl during vdev up: %d\n",
1618dd4f32aeSBjoern A. Zeeb ret);
1619dd4f32aeSBjoern A. Zeeb return;
1620dd4f32aeSBjoern A. Zeeb }
1621dd4f32aeSBjoern A. Zeeb
1622dd4f32aeSBjoern A. Zeeb arvif->tx_seq_no = 0x1000;
1623dd4f32aeSBjoern A. Zeeb
1624dd4f32aeSBjoern A. Zeeb arvif->aid = 0;
1625dd4f32aeSBjoern A. Zeeb
1626dd4f32aeSBjoern A. Zeeb ether_addr_copy(arvif->bssid, info->bssid);
1627dd4f32aeSBjoern A. Zeeb
162828348caeSBjoern A. Zeeb if (arvif->vif->mbssid_tx_vif)
162928348caeSBjoern A. Zeeb tx_arvif = (struct ath11k_vif *)arvif->vif->mbssid_tx_vif->drv_priv;
163028348caeSBjoern A. Zeeb
1631dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid,
163228348caeSBjoern A. Zeeb arvif->bssid,
163328348caeSBjoern A. Zeeb tx_arvif ? tx_arvif->bssid : NULL,
163428348caeSBjoern A. Zeeb info->bssid_index,
163528348caeSBjoern A. Zeeb 1 << info->bssid_indicator);
1636dd4f32aeSBjoern A. Zeeb if (ret) {
1637dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to bring up vdev %d: %i\n",
1638dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ret);
1639dd4f32aeSBjoern A. Zeeb return;
1640dd4f32aeSBjoern A. Zeeb }
1641dd4f32aeSBjoern A. Zeeb
1642dd4f32aeSBjoern A. Zeeb arvif->is_up = true;
1643dd4f32aeSBjoern A. Zeeb
164428348caeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev %d up\n", arvif->vdev_id);
1645dd4f32aeSBjoern A. Zeeb }
1646dd4f32aeSBjoern A. Zeeb
ath11k_mac_handle_beacon_iter(void * data,u8 * mac,struct ieee80211_vif * vif)1647dd4f32aeSBjoern A. Zeeb static void ath11k_mac_handle_beacon_iter(void *data, u8 *mac,
1648dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif)
1649dd4f32aeSBjoern A. Zeeb {
1650dd4f32aeSBjoern A. Zeeb struct sk_buff *skb = data;
1651dd4f32aeSBjoern A. Zeeb struct ieee80211_mgmt *mgmt = (void *)skb->data;
1652dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif = (void *)vif->drv_priv;
1653dd4f32aeSBjoern A. Zeeb
1654dd4f32aeSBjoern A. Zeeb if (vif->type != NL80211_IFTYPE_STATION)
1655dd4f32aeSBjoern A. Zeeb return;
1656dd4f32aeSBjoern A. Zeeb
1657dd4f32aeSBjoern A. Zeeb if (!ether_addr_equal(mgmt->bssid, vif->bss_conf.bssid))
1658dd4f32aeSBjoern A. Zeeb return;
1659dd4f32aeSBjoern A. Zeeb
1660dd4f32aeSBjoern A. Zeeb cancel_delayed_work(&arvif->connection_loss_work);
1661dd4f32aeSBjoern A. Zeeb }
1662dd4f32aeSBjoern A. Zeeb
ath11k_mac_handle_beacon(struct ath11k * ar,struct sk_buff * skb)1663dd4f32aeSBjoern A. Zeeb void ath11k_mac_handle_beacon(struct ath11k *ar, struct sk_buff *skb)
1664dd4f32aeSBjoern A. Zeeb {
1665dd4f32aeSBjoern A. Zeeb ieee80211_iterate_active_interfaces_atomic(ar->hw,
1666dd4f32aeSBjoern A. Zeeb IEEE80211_IFACE_ITER_NORMAL,
1667dd4f32aeSBjoern A. Zeeb ath11k_mac_handle_beacon_iter,
1668dd4f32aeSBjoern A. Zeeb skb);
1669dd4f32aeSBjoern A. Zeeb }
1670dd4f32aeSBjoern A. Zeeb
ath11k_mac_handle_beacon_miss_iter(void * data,u8 * mac,struct ieee80211_vif * vif)1671dd4f32aeSBjoern A. Zeeb static void ath11k_mac_handle_beacon_miss_iter(void *data, u8 *mac,
1672dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif)
1673dd4f32aeSBjoern A. Zeeb {
1674dd4f32aeSBjoern A. Zeeb u32 *vdev_id = data;
1675dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif = (void *)vif->drv_priv;
1676dd4f32aeSBjoern A. Zeeb struct ath11k *ar = arvif->ar;
1677dd4f32aeSBjoern A. Zeeb struct ieee80211_hw *hw = ar->hw;
1678dd4f32aeSBjoern A. Zeeb
1679dd4f32aeSBjoern A. Zeeb if (arvif->vdev_id != *vdev_id)
1680dd4f32aeSBjoern A. Zeeb return;
1681dd4f32aeSBjoern A. Zeeb
1682dd4f32aeSBjoern A. Zeeb if (!arvif->is_up)
1683dd4f32aeSBjoern A. Zeeb return;
1684dd4f32aeSBjoern A. Zeeb
1685dd4f32aeSBjoern A. Zeeb ieee80211_beacon_loss(vif);
1686dd4f32aeSBjoern A. Zeeb
1687dd4f32aeSBjoern A. Zeeb /* Firmware doesn't report beacon loss events repeatedly. If AP probe
1688dd4f32aeSBjoern A. Zeeb * (done by mac80211) succeeds but beacons do not resume then it
1689dd4f32aeSBjoern A. Zeeb * doesn't make sense to continue operation. Queue connection loss work
1690dd4f32aeSBjoern A. Zeeb * which can be cancelled when beacon is received.
1691dd4f32aeSBjoern A. Zeeb */
1692dd4f32aeSBjoern A. Zeeb ieee80211_queue_delayed_work(hw, &arvif->connection_loss_work,
1693dd4f32aeSBjoern A. Zeeb ATH11K_CONNECTION_LOSS_HZ);
1694dd4f32aeSBjoern A. Zeeb }
1695dd4f32aeSBjoern A. Zeeb
ath11k_mac_handle_beacon_miss(struct ath11k * ar,u32 vdev_id)1696dd4f32aeSBjoern A. Zeeb void ath11k_mac_handle_beacon_miss(struct ath11k *ar, u32 vdev_id)
1697dd4f32aeSBjoern A. Zeeb {
1698dd4f32aeSBjoern A. Zeeb ieee80211_iterate_active_interfaces_atomic(ar->hw,
1699dd4f32aeSBjoern A. Zeeb IEEE80211_IFACE_ITER_NORMAL,
1700dd4f32aeSBjoern A. Zeeb ath11k_mac_handle_beacon_miss_iter,
1701dd4f32aeSBjoern A. Zeeb &vdev_id);
1702dd4f32aeSBjoern A. Zeeb }
1703dd4f32aeSBjoern A. Zeeb
ath11k_mac_vif_sta_connection_loss_work(struct work_struct * work)1704dd4f32aeSBjoern A. Zeeb static void ath11k_mac_vif_sta_connection_loss_work(struct work_struct *work)
1705dd4f32aeSBjoern A. Zeeb {
1706dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif = container_of(work, struct ath11k_vif,
1707dd4f32aeSBjoern A. Zeeb connection_loss_work.work);
1708dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif = arvif->vif;
1709dd4f32aeSBjoern A. Zeeb
1710dd4f32aeSBjoern A. Zeeb if (!arvif->is_up)
1711dd4f32aeSBjoern A. Zeeb return;
1712dd4f32aeSBjoern A. Zeeb
1713dd4f32aeSBjoern A. Zeeb ieee80211_connection_loss(vif);
1714dd4f32aeSBjoern A. Zeeb }
1715dd4f32aeSBjoern A. Zeeb
ath11k_peer_assoc_h_basic(struct ath11k * ar,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct peer_assoc_params * arg)1716dd4f32aeSBjoern A. Zeeb static void ath11k_peer_assoc_h_basic(struct ath11k *ar,
1717dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif,
1718dd4f32aeSBjoern A. Zeeb struct ieee80211_sta *sta,
1719dd4f32aeSBjoern A. Zeeb struct peer_assoc_params *arg)
1720dd4f32aeSBjoern A. Zeeb {
1721dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif = (void *)vif->drv_priv;
1722dd4f32aeSBjoern A. Zeeb u32 aid;
1723dd4f32aeSBjoern A. Zeeb
1724dd4f32aeSBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
1725dd4f32aeSBjoern A. Zeeb
1726dd4f32aeSBjoern A. Zeeb if (vif->type == NL80211_IFTYPE_STATION)
172728348caeSBjoern A. Zeeb aid = vif->cfg.aid;
1728dd4f32aeSBjoern A. Zeeb else
1729dd4f32aeSBjoern A. Zeeb aid = sta->aid;
1730dd4f32aeSBjoern A. Zeeb
1731dd4f32aeSBjoern A. Zeeb ether_addr_copy(arg->peer_mac, sta->addr);
1732dd4f32aeSBjoern A. Zeeb arg->vdev_id = arvif->vdev_id;
1733dd4f32aeSBjoern A. Zeeb arg->peer_associd = aid;
1734dd4f32aeSBjoern A. Zeeb arg->auth_flag = true;
1735dd4f32aeSBjoern A. Zeeb /* TODO: STA WAR in ath10k for listen interval required? */
1736dd4f32aeSBjoern A. Zeeb arg->peer_listen_intval = ar->hw->conf.listen_interval;
1737dd4f32aeSBjoern A. Zeeb arg->peer_nss = 1;
1738dd4f32aeSBjoern A. Zeeb arg->peer_caps = vif->bss_conf.assoc_capability;
1739dd4f32aeSBjoern A. Zeeb }
1740dd4f32aeSBjoern A. Zeeb
ath11k_peer_assoc_h_crypto(struct ath11k * ar,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct peer_assoc_params * arg)1741dd4f32aeSBjoern A. Zeeb static void ath11k_peer_assoc_h_crypto(struct ath11k *ar,
1742dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif,
1743dd4f32aeSBjoern A. Zeeb struct ieee80211_sta *sta,
1744dd4f32aeSBjoern A. Zeeb struct peer_assoc_params *arg)
1745dd4f32aeSBjoern A. Zeeb {
1746dd4f32aeSBjoern A. Zeeb struct ieee80211_bss_conf *info = &vif->bss_conf;
1747dd4f32aeSBjoern A. Zeeb struct cfg80211_chan_def def;
1748dd4f32aeSBjoern A. Zeeb struct cfg80211_bss *bss;
1749dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif = (struct ath11k_vif *)vif->drv_priv;
1750dd4f32aeSBjoern A. Zeeb const u8 *rsnie = NULL;
1751dd4f32aeSBjoern A. Zeeb const u8 *wpaie = NULL;
1752dd4f32aeSBjoern A. Zeeb
1753dd4f32aeSBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
1754dd4f32aeSBjoern A. Zeeb
1755dd4f32aeSBjoern A. Zeeb if (WARN_ON(ath11k_mac_vif_chan(vif, &def)))
1756dd4f32aeSBjoern A. Zeeb return;
1757dd4f32aeSBjoern A. Zeeb
1758dd4f32aeSBjoern A. Zeeb bss = cfg80211_get_bss(ar->hw->wiphy, def.chan, info->bssid, NULL, 0,
1759dd4f32aeSBjoern A. Zeeb IEEE80211_BSS_TYPE_ANY, IEEE80211_PRIVACY_ANY);
1760dd4f32aeSBjoern A. Zeeb
1761dd4f32aeSBjoern A. Zeeb if (arvif->rsnie_present || arvif->wpaie_present) {
1762dd4f32aeSBjoern A. Zeeb arg->need_ptk_4_way = true;
1763dd4f32aeSBjoern A. Zeeb if (arvif->wpaie_present)
1764dd4f32aeSBjoern A. Zeeb arg->need_gtk_2_way = true;
1765dd4f32aeSBjoern A. Zeeb } else if (bss) {
1766dd4f32aeSBjoern A. Zeeb const struct cfg80211_bss_ies *ies;
1767dd4f32aeSBjoern A. Zeeb
1768dd4f32aeSBjoern A. Zeeb rcu_read_lock();
1769dd4f32aeSBjoern A. Zeeb rsnie = ieee80211_bss_get_ie(bss, WLAN_EID_RSN);
1770dd4f32aeSBjoern A. Zeeb
1771dd4f32aeSBjoern A. Zeeb ies = rcu_dereference(bss->ies);
1772dd4f32aeSBjoern A. Zeeb
1773dd4f32aeSBjoern A. Zeeb wpaie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1774dd4f32aeSBjoern A. Zeeb WLAN_OUI_TYPE_MICROSOFT_WPA,
1775dd4f32aeSBjoern A. Zeeb ies->data,
1776dd4f32aeSBjoern A. Zeeb ies->len);
1777dd4f32aeSBjoern A. Zeeb rcu_read_unlock();
1778dd4f32aeSBjoern A. Zeeb cfg80211_put_bss(ar->hw->wiphy, bss);
1779dd4f32aeSBjoern A. Zeeb }
1780dd4f32aeSBjoern A. Zeeb
1781dd4f32aeSBjoern A. Zeeb /* FIXME: base on RSN IE/WPA IE is a correct idea? */
1782dd4f32aeSBjoern A. Zeeb if (rsnie || wpaie) {
1783dd4f32aeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
1784dd4f32aeSBjoern A. Zeeb "%s: rsn ie found\n", __func__);
1785dd4f32aeSBjoern A. Zeeb arg->need_ptk_4_way = true;
1786dd4f32aeSBjoern A. Zeeb }
1787dd4f32aeSBjoern A. Zeeb
1788dd4f32aeSBjoern A. Zeeb if (wpaie) {
1789dd4f32aeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
1790dd4f32aeSBjoern A. Zeeb "%s: wpa ie found\n", __func__);
1791dd4f32aeSBjoern A. Zeeb arg->need_gtk_2_way = true;
1792dd4f32aeSBjoern A. Zeeb }
1793dd4f32aeSBjoern A. Zeeb
1794dd4f32aeSBjoern A. Zeeb if (sta->mfp) {
1795dd4f32aeSBjoern A. Zeeb /* TODO: Need to check if FW supports PMF? */
1796dd4f32aeSBjoern A. Zeeb arg->is_pmf_enabled = true;
1797dd4f32aeSBjoern A. Zeeb }
1798dd4f32aeSBjoern A. Zeeb
1799dd4f32aeSBjoern A. Zeeb /* TODO: safe_mode_enabled (bypass 4-way handshake) flag req? */
1800dd4f32aeSBjoern A. Zeeb }
1801dd4f32aeSBjoern A. Zeeb
ath11k_peer_assoc_h_rates(struct ath11k * ar,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct peer_assoc_params * arg)1802dd4f32aeSBjoern A. Zeeb static void ath11k_peer_assoc_h_rates(struct ath11k *ar,
1803dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif,
1804dd4f32aeSBjoern A. Zeeb struct ieee80211_sta *sta,
1805dd4f32aeSBjoern A. Zeeb struct peer_assoc_params *arg)
1806dd4f32aeSBjoern A. Zeeb {
1807dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif = (void *)vif->drv_priv;
1808dd4f32aeSBjoern A. Zeeb struct wmi_rate_set_arg *rateset = &arg->peer_legacy_rates;
1809dd4f32aeSBjoern A. Zeeb struct cfg80211_chan_def def;
1810dd4f32aeSBjoern A. Zeeb const struct ieee80211_supported_band *sband;
1811dd4f32aeSBjoern A. Zeeb const struct ieee80211_rate *rates;
1812dd4f32aeSBjoern A. Zeeb enum nl80211_band band;
1813dd4f32aeSBjoern A. Zeeb u32 ratemask;
1814dd4f32aeSBjoern A. Zeeb u8 rate;
1815dd4f32aeSBjoern A. Zeeb int i;
1816dd4f32aeSBjoern A. Zeeb
1817dd4f32aeSBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
1818dd4f32aeSBjoern A. Zeeb
1819dd4f32aeSBjoern A. Zeeb if (WARN_ON(ath11k_mac_vif_chan(vif, &def)))
1820dd4f32aeSBjoern A. Zeeb return;
1821dd4f32aeSBjoern A. Zeeb
1822dd4f32aeSBjoern A. Zeeb band = def.chan->band;
1823dd4f32aeSBjoern A. Zeeb sband = ar->hw->wiphy->bands[band];
1824dd4f32aeSBjoern A. Zeeb ratemask = sta->deflink.supp_rates[band];
1825dd4f32aeSBjoern A. Zeeb ratemask &= arvif->bitrate_mask.control[band].legacy;
1826dd4f32aeSBjoern A. Zeeb rates = sband->bitrates;
1827dd4f32aeSBjoern A. Zeeb
1828dd4f32aeSBjoern A. Zeeb rateset->num_rates = 0;
1829dd4f32aeSBjoern A. Zeeb
1830dd4f32aeSBjoern A. Zeeb for (i = 0; i < 32; i++, ratemask >>= 1, rates++) {
1831dd4f32aeSBjoern A. Zeeb if (!(ratemask & 1))
1832dd4f32aeSBjoern A. Zeeb continue;
1833dd4f32aeSBjoern A. Zeeb
1834dd4f32aeSBjoern A. Zeeb rate = ath11k_mac_bitrate_to_rate(rates->bitrate);
1835dd4f32aeSBjoern A. Zeeb rateset->rates[rateset->num_rates] = rate;
1836dd4f32aeSBjoern A. Zeeb rateset->num_rates++;
1837dd4f32aeSBjoern A. Zeeb }
1838dd4f32aeSBjoern A. Zeeb }
1839dd4f32aeSBjoern A. Zeeb
1840dd4f32aeSBjoern A. Zeeb static bool
ath11k_peer_assoc_h_ht_masked(const u8 * ht_mcs_mask)184128348caeSBjoern A. Zeeb ath11k_peer_assoc_h_ht_masked(const u8 *ht_mcs_mask)
1842dd4f32aeSBjoern A. Zeeb {
1843dd4f32aeSBjoern A. Zeeb int nss;
1844dd4f32aeSBjoern A. Zeeb
1845dd4f32aeSBjoern A. Zeeb for (nss = 0; nss < IEEE80211_HT_MCS_MASK_LEN; nss++)
1846dd4f32aeSBjoern A. Zeeb if (ht_mcs_mask[nss])
1847dd4f32aeSBjoern A. Zeeb return false;
1848dd4f32aeSBjoern A. Zeeb
1849dd4f32aeSBjoern A. Zeeb return true;
1850dd4f32aeSBjoern A. Zeeb }
1851dd4f32aeSBjoern A. Zeeb
1852dd4f32aeSBjoern A. Zeeb static bool
ath11k_peer_assoc_h_vht_masked(const u16 * vht_mcs_mask)185328348caeSBjoern A. Zeeb ath11k_peer_assoc_h_vht_masked(const u16 *vht_mcs_mask)
1854dd4f32aeSBjoern A. Zeeb {
1855dd4f32aeSBjoern A. Zeeb int nss;
1856dd4f32aeSBjoern A. Zeeb
1857dd4f32aeSBjoern A. Zeeb for (nss = 0; nss < NL80211_VHT_NSS_MAX; nss++)
1858dd4f32aeSBjoern A. Zeeb if (vht_mcs_mask[nss])
1859dd4f32aeSBjoern A. Zeeb return false;
1860dd4f32aeSBjoern A. Zeeb
1861dd4f32aeSBjoern A. Zeeb return true;
1862dd4f32aeSBjoern A. Zeeb }
1863dd4f32aeSBjoern A. Zeeb
ath11k_peer_assoc_h_ht(struct ath11k * ar,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct peer_assoc_params * arg)1864dd4f32aeSBjoern A. Zeeb static void ath11k_peer_assoc_h_ht(struct ath11k *ar,
1865dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif,
1866dd4f32aeSBjoern A. Zeeb struct ieee80211_sta *sta,
1867dd4f32aeSBjoern A. Zeeb struct peer_assoc_params *arg)
1868dd4f32aeSBjoern A. Zeeb {
1869dd4f32aeSBjoern A. Zeeb const struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap;
1870dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif = (void *)vif->drv_priv;
1871dd4f32aeSBjoern A. Zeeb struct cfg80211_chan_def def;
1872dd4f32aeSBjoern A. Zeeb enum nl80211_band band;
1873dd4f32aeSBjoern A. Zeeb const u8 *ht_mcs_mask;
1874dd4f32aeSBjoern A. Zeeb int i, n;
1875dd4f32aeSBjoern A. Zeeb u8 max_nss;
1876dd4f32aeSBjoern A. Zeeb u32 stbc;
1877dd4f32aeSBjoern A. Zeeb
1878dd4f32aeSBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
1879dd4f32aeSBjoern A. Zeeb
1880dd4f32aeSBjoern A. Zeeb if (WARN_ON(ath11k_mac_vif_chan(vif, &def)))
1881dd4f32aeSBjoern A. Zeeb return;
1882dd4f32aeSBjoern A. Zeeb
1883dd4f32aeSBjoern A. Zeeb if (!ht_cap->ht_supported)
1884dd4f32aeSBjoern A. Zeeb return;
1885dd4f32aeSBjoern A. Zeeb
1886dd4f32aeSBjoern A. Zeeb band = def.chan->band;
1887dd4f32aeSBjoern A. Zeeb ht_mcs_mask = arvif->bitrate_mask.control[band].ht_mcs;
1888dd4f32aeSBjoern A. Zeeb
1889dd4f32aeSBjoern A. Zeeb if (ath11k_peer_assoc_h_ht_masked(ht_mcs_mask))
1890dd4f32aeSBjoern A. Zeeb return;
1891dd4f32aeSBjoern A. Zeeb
1892dd4f32aeSBjoern A. Zeeb arg->ht_flag = true;
1893dd4f32aeSBjoern A. Zeeb
1894dd4f32aeSBjoern A. Zeeb arg->peer_max_mpdu = (1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
1895dd4f32aeSBjoern A. Zeeb ht_cap->ampdu_factor)) - 1;
1896dd4f32aeSBjoern A. Zeeb
1897dd4f32aeSBjoern A. Zeeb arg->peer_mpdu_density =
1898dd4f32aeSBjoern A. Zeeb ath11k_parse_mpdudensity(ht_cap->ampdu_density);
1899dd4f32aeSBjoern A. Zeeb
1900dd4f32aeSBjoern A. Zeeb arg->peer_ht_caps = ht_cap->cap;
1901dd4f32aeSBjoern A. Zeeb arg->peer_rate_caps |= WMI_HOST_RC_HT_FLAG;
1902dd4f32aeSBjoern A. Zeeb
1903dd4f32aeSBjoern A. Zeeb if (ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING)
1904dd4f32aeSBjoern A. Zeeb arg->ldpc_flag = true;
1905dd4f32aeSBjoern A. Zeeb
1906dd4f32aeSBjoern A. Zeeb if (sta->deflink.bandwidth >= IEEE80211_STA_RX_BW_40) {
1907dd4f32aeSBjoern A. Zeeb arg->bw_40 = true;
1908dd4f32aeSBjoern A. Zeeb arg->peer_rate_caps |= WMI_HOST_RC_CW40_FLAG;
1909dd4f32aeSBjoern A. Zeeb }
1910dd4f32aeSBjoern A. Zeeb
1911dd4f32aeSBjoern A. Zeeb /* As firmware handles this two flags (IEEE80211_HT_CAP_SGI_20
1912dd4f32aeSBjoern A. Zeeb * and IEEE80211_HT_CAP_SGI_40) for enabling SGI, we reset
1913dd4f32aeSBjoern A. Zeeb * both flags if guard interval is Default GI
1914dd4f32aeSBjoern A. Zeeb */
1915dd4f32aeSBjoern A. Zeeb if (arvif->bitrate_mask.control[band].gi == NL80211_TXRATE_DEFAULT_GI)
1916dd4f32aeSBjoern A. Zeeb arg->peer_ht_caps &= ~(IEEE80211_HT_CAP_SGI_20 |
1917dd4f32aeSBjoern A. Zeeb IEEE80211_HT_CAP_SGI_40);
1918dd4f32aeSBjoern A. Zeeb
1919dd4f32aeSBjoern A. Zeeb if (arvif->bitrate_mask.control[band].gi != NL80211_TXRATE_FORCE_LGI) {
1920dd4f32aeSBjoern A. Zeeb if (ht_cap->cap & (IEEE80211_HT_CAP_SGI_20 |
1921dd4f32aeSBjoern A. Zeeb IEEE80211_HT_CAP_SGI_40))
1922dd4f32aeSBjoern A. Zeeb arg->peer_rate_caps |= WMI_HOST_RC_SGI_FLAG;
1923dd4f32aeSBjoern A. Zeeb }
1924dd4f32aeSBjoern A. Zeeb
1925dd4f32aeSBjoern A. Zeeb if (ht_cap->cap & IEEE80211_HT_CAP_TX_STBC) {
1926dd4f32aeSBjoern A. Zeeb arg->peer_rate_caps |= WMI_HOST_RC_TX_STBC_FLAG;
1927dd4f32aeSBjoern A. Zeeb arg->stbc_flag = true;
1928dd4f32aeSBjoern A. Zeeb }
1929dd4f32aeSBjoern A. Zeeb
1930dd4f32aeSBjoern A. Zeeb if (ht_cap->cap & IEEE80211_HT_CAP_RX_STBC) {
1931dd4f32aeSBjoern A. Zeeb stbc = ht_cap->cap & IEEE80211_HT_CAP_RX_STBC;
1932dd4f32aeSBjoern A. Zeeb stbc = stbc >> IEEE80211_HT_CAP_RX_STBC_SHIFT;
1933dd4f32aeSBjoern A. Zeeb stbc = stbc << WMI_HOST_RC_RX_STBC_FLAG_S;
1934dd4f32aeSBjoern A. Zeeb arg->peer_rate_caps |= stbc;
1935dd4f32aeSBjoern A. Zeeb arg->stbc_flag = true;
1936dd4f32aeSBjoern A. Zeeb }
1937dd4f32aeSBjoern A. Zeeb
1938dd4f32aeSBjoern A. Zeeb if (ht_cap->mcs.rx_mask[1] && ht_cap->mcs.rx_mask[2])
1939dd4f32aeSBjoern A. Zeeb arg->peer_rate_caps |= WMI_HOST_RC_TS_FLAG;
1940dd4f32aeSBjoern A. Zeeb else if (ht_cap->mcs.rx_mask[1])
1941dd4f32aeSBjoern A. Zeeb arg->peer_rate_caps |= WMI_HOST_RC_DS_FLAG;
1942dd4f32aeSBjoern A. Zeeb
1943dd4f32aeSBjoern A. Zeeb for (i = 0, n = 0, max_nss = 0; i < IEEE80211_HT_MCS_MASK_LEN * 8; i++)
1944dd4f32aeSBjoern A. Zeeb if ((ht_cap->mcs.rx_mask[i / 8] & BIT(i % 8)) &&
1945dd4f32aeSBjoern A. Zeeb (ht_mcs_mask[i / 8] & BIT(i % 8))) {
1946dd4f32aeSBjoern A. Zeeb max_nss = (i / 8) + 1;
1947dd4f32aeSBjoern A. Zeeb arg->peer_ht_rates.rates[n++] = i;
1948dd4f32aeSBjoern A. Zeeb }
1949dd4f32aeSBjoern A. Zeeb
1950dd4f32aeSBjoern A. Zeeb /* This is a workaround for HT-enabled STAs which break the spec
1951dd4f32aeSBjoern A. Zeeb * and have no HT capabilities RX mask (no HT RX MCS map).
1952dd4f32aeSBjoern A. Zeeb *
1953dd4f32aeSBjoern A. Zeeb * As per spec, in section 20.3.5 Modulation and coding scheme (MCS),
1954dd4f32aeSBjoern A. Zeeb * MCS 0 through 7 are mandatory in 20MHz with 800 ns GI at all STAs.
1955dd4f32aeSBjoern A. Zeeb *
1956dd4f32aeSBjoern A. Zeeb * Firmware asserts if such situation occurs.
1957dd4f32aeSBjoern A. Zeeb */
1958dd4f32aeSBjoern A. Zeeb if (n == 0) {
1959dd4f32aeSBjoern A. Zeeb arg->peer_ht_rates.num_rates = 8;
1960dd4f32aeSBjoern A. Zeeb for (i = 0; i < arg->peer_ht_rates.num_rates; i++)
1961dd4f32aeSBjoern A. Zeeb arg->peer_ht_rates.rates[i] = i;
1962dd4f32aeSBjoern A. Zeeb } else {
1963dd4f32aeSBjoern A. Zeeb arg->peer_ht_rates.num_rates = n;
1964dd4f32aeSBjoern A. Zeeb arg->peer_nss = min(sta->deflink.rx_nss, max_nss);
1965dd4f32aeSBjoern A. Zeeb }
1966dd4f32aeSBjoern A. Zeeb
196728348caeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "ht peer %pM mcs cnt %d nss %d\n",
1968dd4f32aeSBjoern A. Zeeb arg->peer_mac,
1969dd4f32aeSBjoern A. Zeeb arg->peer_ht_rates.num_rates,
1970dd4f32aeSBjoern A. Zeeb arg->peer_nss);
1971dd4f32aeSBjoern A. Zeeb }
1972dd4f32aeSBjoern A. Zeeb
ath11k_mac_get_max_vht_mcs_map(u16 mcs_map,int nss)1973dd4f32aeSBjoern A. Zeeb static int ath11k_mac_get_max_vht_mcs_map(u16 mcs_map, int nss)
1974dd4f32aeSBjoern A. Zeeb {
1975dd4f32aeSBjoern A. Zeeb switch ((mcs_map >> (2 * nss)) & 0x3) {
1976dd4f32aeSBjoern A. Zeeb case IEEE80211_VHT_MCS_SUPPORT_0_7: return BIT(8) - 1;
1977dd4f32aeSBjoern A. Zeeb case IEEE80211_VHT_MCS_SUPPORT_0_8: return BIT(9) - 1;
1978dd4f32aeSBjoern A. Zeeb case IEEE80211_VHT_MCS_SUPPORT_0_9: return BIT(10) - 1;
1979dd4f32aeSBjoern A. Zeeb }
1980dd4f32aeSBjoern A. Zeeb return 0;
1981dd4f32aeSBjoern A. Zeeb }
1982dd4f32aeSBjoern A. Zeeb
1983dd4f32aeSBjoern A. Zeeb static u16
ath11k_peer_assoc_h_vht_limit(u16 tx_mcs_set,const u16 vht_mcs_limit[NL80211_VHT_NSS_MAX])1984dd4f32aeSBjoern A. Zeeb ath11k_peer_assoc_h_vht_limit(u16 tx_mcs_set,
1985dd4f32aeSBjoern A. Zeeb const u16 vht_mcs_limit[NL80211_VHT_NSS_MAX])
1986dd4f32aeSBjoern A. Zeeb {
1987dd4f32aeSBjoern A. Zeeb int idx_limit;
1988dd4f32aeSBjoern A. Zeeb int nss;
1989dd4f32aeSBjoern A. Zeeb u16 mcs_map;
1990dd4f32aeSBjoern A. Zeeb u16 mcs;
1991dd4f32aeSBjoern A. Zeeb
1992dd4f32aeSBjoern A. Zeeb for (nss = 0; nss < NL80211_VHT_NSS_MAX; nss++) {
1993dd4f32aeSBjoern A. Zeeb mcs_map = ath11k_mac_get_max_vht_mcs_map(tx_mcs_set, nss) &
1994dd4f32aeSBjoern A. Zeeb vht_mcs_limit[nss];
1995dd4f32aeSBjoern A. Zeeb
1996dd4f32aeSBjoern A. Zeeb if (mcs_map)
1997dd4f32aeSBjoern A. Zeeb idx_limit = fls(mcs_map) - 1;
1998dd4f32aeSBjoern A. Zeeb else
1999dd4f32aeSBjoern A. Zeeb idx_limit = -1;
2000dd4f32aeSBjoern A. Zeeb
2001dd4f32aeSBjoern A. Zeeb switch (idx_limit) {
2002dd4f32aeSBjoern A. Zeeb case 0:
2003dd4f32aeSBjoern A. Zeeb case 1:
2004dd4f32aeSBjoern A. Zeeb case 2:
2005dd4f32aeSBjoern A. Zeeb case 3:
2006dd4f32aeSBjoern A. Zeeb case 4:
2007dd4f32aeSBjoern A. Zeeb case 5:
2008dd4f32aeSBjoern A. Zeeb case 6:
2009dd4f32aeSBjoern A. Zeeb case 7:
2010dd4f32aeSBjoern A. Zeeb mcs = IEEE80211_VHT_MCS_SUPPORT_0_7;
2011dd4f32aeSBjoern A. Zeeb break;
2012dd4f32aeSBjoern A. Zeeb case 8:
2013dd4f32aeSBjoern A. Zeeb mcs = IEEE80211_VHT_MCS_SUPPORT_0_8;
2014dd4f32aeSBjoern A. Zeeb break;
2015dd4f32aeSBjoern A. Zeeb case 9:
2016dd4f32aeSBjoern A. Zeeb mcs = IEEE80211_VHT_MCS_SUPPORT_0_9;
2017dd4f32aeSBjoern A. Zeeb break;
2018dd4f32aeSBjoern A. Zeeb default:
2019dd4f32aeSBjoern A. Zeeb WARN_ON(1);
2020dd4f32aeSBjoern A. Zeeb fallthrough;
2021dd4f32aeSBjoern A. Zeeb case -1:
2022dd4f32aeSBjoern A. Zeeb mcs = IEEE80211_VHT_MCS_NOT_SUPPORTED;
2023dd4f32aeSBjoern A. Zeeb break;
2024dd4f32aeSBjoern A. Zeeb }
2025dd4f32aeSBjoern A. Zeeb
2026dd4f32aeSBjoern A. Zeeb tx_mcs_set &= ~(0x3 << (nss * 2));
2027dd4f32aeSBjoern A. Zeeb tx_mcs_set |= mcs << (nss * 2);
2028dd4f32aeSBjoern A. Zeeb }
2029dd4f32aeSBjoern A. Zeeb
2030dd4f32aeSBjoern A. Zeeb return tx_mcs_set;
2031dd4f32aeSBjoern A. Zeeb }
2032dd4f32aeSBjoern A. Zeeb
ath11k_get_nss_160mhz(struct ath11k * ar,u8 max_nss)2033dd4f32aeSBjoern A. Zeeb static u8 ath11k_get_nss_160mhz(struct ath11k *ar,
2034dd4f32aeSBjoern A. Zeeb u8 max_nss)
2035dd4f32aeSBjoern A. Zeeb {
2036dd4f32aeSBjoern A. Zeeb u8 nss_ratio_info = ar->pdev->cap.nss_ratio_info;
2037dd4f32aeSBjoern A. Zeeb u8 max_sup_nss = 0;
2038dd4f32aeSBjoern A. Zeeb
2039dd4f32aeSBjoern A. Zeeb switch (nss_ratio_info) {
2040dd4f32aeSBjoern A. Zeeb case WMI_NSS_RATIO_1BY2_NSS:
2041dd4f32aeSBjoern A. Zeeb max_sup_nss = max_nss >> 1;
2042dd4f32aeSBjoern A. Zeeb break;
2043dd4f32aeSBjoern A. Zeeb case WMI_NSS_RATIO_3BY4_NSS:
2044dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "WMI_NSS_RATIO_3BY4_NSS not supported\n");
2045dd4f32aeSBjoern A. Zeeb break;
2046dd4f32aeSBjoern A. Zeeb case WMI_NSS_RATIO_1_NSS:
2047dd4f32aeSBjoern A. Zeeb max_sup_nss = max_nss;
2048dd4f32aeSBjoern A. Zeeb break;
2049dd4f32aeSBjoern A. Zeeb case WMI_NSS_RATIO_2_NSS:
2050dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "WMI_NSS_RATIO_2_NSS not supported\n");
2051dd4f32aeSBjoern A. Zeeb break;
2052dd4f32aeSBjoern A. Zeeb default:
2053dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "invalid nss ratio received from firmware: %d\n",
2054dd4f32aeSBjoern A. Zeeb nss_ratio_info);
2055dd4f32aeSBjoern A. Zeeb break;
2056dd4f32aeSBjoern A. Zeeb }
2057dd4f32aeSBjoern A. Zeeb
2058dd4f32aeSBjoern A. Zeeb return max_sup_nss;
2059dd4f32aeSBjoern A. Zeeb }
2060dd4f32aeSBjoern A. Zeeb
ath11k_peer_assoc_h_vht(struct ath11k * ar,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct peer_assoc_params * arg)2061dd4f32aeSBjoern A. Zeeb static void ath11k_peer_assoc_h_vht(struct ath11k *ar,
2062dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif,
2063dd4f32aeSBjoern A. Zeeb struct ieee80211_sta *sta,
2064dd4f32aeSBjoern A. Zeeb struct peer_assoc_params *arg)
2065dd4f32aeSBjoern A. Zeeb {
2066dd4f32aeSBjoern A. Zeeb const struct ieee80211_sta_vht_cap *vht_cap = &sta->deflink.vht_cap;
2067dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif = (void *)vif->drv_priv;
2068dd4f32aeSBjoern A. Zeeb struct cfg80211_chan_def def;
2069dd4f32aeSBjoern A. Zeeb enum nl80211_band band;
2070dd4f32aeSBjoern A. Zeeb u16 *vht_mcs_mask;
2071dd4f32aeSBjoern A. Zeeb u8 ampdu_factor;
2072dd4f32aeSBjoern A. Zeeb u8 max_nss, vht_mcs;
2073dd4f32aeSBjoern A. Zeeb int i, vht_nss, nss_idx;
2074dd4f32aeSBjoern A. Zeeb bool user_rate_valid = true;
2075dd4f32aeSBjoern A. Zeeb u32 rx_nss, tx_nss, nss_160;
2076dd4f32aeSBjoern A. Zeeb
2077dd4f32aeSBjoern A. Zeeb if (WARN_ON(ath11k_mac_vif_chan(vif, &def)))
2078dd4f32aeSBjoern A. Zeeb return;
2079dd4f32aeSBjoern A. Zeeb
2080dd4f32aeSBjoern A. Zeeb if (!vht_cap->vht_supported)
2081dd4f32aeSBjoern A. Zeeb return;
2082dd4f32aeSBjoern A. Zeeb
2083dd4f32aeSBjoern A. Zeeb band = def.chan->band;
2084dd4f32aeSBjoern A. Zeeb vht_mcs_mask = arvif->bitrate_mask.control[band].vht_mcs;
2085dd4f32aeSBjoern A. Zeeb
2086dd4f32aeSBjoern A. Zeeb if (ath11k_peer_assoc_h_vht_masked(vht_mcs_mask))
2087dd4f32aeSBjoern A. Zeeb return;
2088dd4f32aeSBjoern A. Zeeb
2089dd4f32aeSBjoern A. Zeeb arg->vht_flag = true;
2090dd4f32aeSBjoern A. Zeeb
2091dd4f32aeSBjoern A. Zeeb /* TODO: similar flags required? */
2092dd4f32aeSBjoern A. Zeeb arg->vht_capable = true;
2093dd4f32aeSBjoern A. Zeeb
2094dd4f32aeSBjoern A. Zeeb if (def.chan->band == NL80211_BAND_2GHZ)
2095dd4f32aeSBjoern A. Zeeb arg->vht_ng_flag = true;
2096dd4f32aeSBjoern A. Zeeb
2097dd4f32aeSBjoern A. Zeeb arg->peer_vht_caps = vht_cap->cap;
2098dd4f32aeSBjoern A. Zeeb
2099dd4f32aeSBjoern A. Zeeb ampdu_factor = (vht_cap->cap &
2100dd4f32aeSBjoern A. Zeeb IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK) >>
2101dd4f32aeSBjoern A. Zeeb IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;
2102dd4f32aeSBjoern A. Zeeb
2103dd4f32aeSBjoern A. Zeeb /* Workaround: Some Netgear/Linksys 11ac APs set Rx A-MPDU factor to
2104dd4f32aeSBjoern A. Zeeb * zero in VHT IE. Using it would result in degraded throughput.
2105dd4f32aeSBjoern A. Zeeb * arg->peer_max_mpdu at this point contains HT max_mpdu so keep
2106dd4f32aeSBjoern A. Zeeb * it if VHT max_mpdu is smaller.
2107dd4f32aeSBjoern A. Zeeb */
2108dd4f32aeSBjoern A. Zeeb arg->peer_max_mpdu = max(arg->peer_max_mpdu,
2109dd4f32aeSBjoern A. Zeeb (1U << (IEEE80211_HT_MAX_AMPDU_FACTOR +
2110dd4f32aeSBjoern A. Zeeb ampdu_factor)) - 1);
2111dd4f32aeSBjoern A. Zeeb
2112dd4f32aeSBjoern A. Zeeb if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80)
2113dd4f32aeSBjoern A. Zeeb arg->bw_80 = true;
2114dd4f32aeSBjoern A. Zeeb
2115dd4f32aeSBjoern A. Zeeb if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160)
2116dd4f32aeSBjoern A. Zeeb arg->bw_160 = true;
2117dd4f32aeSBjoern A. Zeeb
2118dd4f32aeSBjoern A. Zeeb vht_nss = ath11k_mac_max_vht_nss(vht_mcs_mask);
2119dd4f32aeSBjoern A. Zeeb
2120dd4f32aeSBjoern A. Zeeb if (vht_nss > sta->deflink.rx_nss) {
2121dd4f32aeSBjoern A. Zeeb user_rate_valid = false;
2122dd4f32aeSBjoern A. Zeeb for (nss_idx = sta->deflink.rx_nss - 1; nss_idx >= 0; nss_idx--) {
2123dd4f32aeSBjoern A. Zeeb if (vht_mcs_mask[nss_idx]) {
2124dd4f32aeSBjoern A. Zeeb user_rate_valid = true;
2125dd4f32aeSBjoern A. Zeeb break;
2126dd4f32aeSBjoern A. Zeeb }
2127dd4f32aeSBjoern A. Zeeb }
2128dd4f32aeSBjoern A. Zeeb }
2129dd4f32aeSBjoern A. Zeeb
2130dd4f32aeSBjoern A. Zeeb if (!user_rate_valid) {
213128348caeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "setting vht range mcs value to peer supported nss %d for peer %pM\n",
2132dd4f32aeSBjoern A. Zeeb sta->deflink.rx_nss, sta->addr);
2133dd4f32aeSBjoern A. Zeeb vht_mcs_mask[sta->deflink.rx_nss - 1] = vht_mcs_mask[vht_nss - 1];
2134dd4f32aeSBjoern A. Zeeb }
2135dd4f32aeSBjoern A. Zeeb
2136dd4f32aeSBjoern A. Zeeb /* Calculate peer NSS capability from VHT capabilities if STA
2137dd4f32aeSBjoern A. Zeeb * supports VHT.
2138dd4f32aeSBjoern A. Zeeb */
213928348caeSBjoern A. Zeeb for (i = 0, max_nss = 0; i < NL80211_VHT_NSS_MAX; i++) {
2140dd4f32aeSBjoern A. Zeeb vht_mcs = __le16_to_cpu(vht_cap->vht_mcs.rx_mcs_map) >>
2141dd4f32aeSBjoern A. Zeeb (2 * i) & 3;
2142dd4f32aeSBjoern A. Zeeb
2143dd4f32aeSBjoern A. Zeeb if (vht_mcs != IEEE80211_VHT_MCS_NOT_SUPPORTED &&
2144dd4f32aeSBjoern A. Zeeb vht_mcs_mask[i])
2145dd4f32aeSBjoern A. Zeeb max_nss = i + 1;
2146dd4f32aeSBjoern A. Zeeb }
2147dd4f32aeSBjoern A. Zeeb arg->peer_nss = min(sta->deflink.rx_nss, max_nss);
2148dd4f32aeSBjoern A. Zeeb arg->rx_max_rate = __le16_to_cpu(vht_cap->vht_mcs.rx_highest);
2149dd4f32aeSBjoern A. Zeeb arg->rx_mcs_set = __le16_to_cpu(vht_cap->vht_mcs.rx_mcs_map);
2150dd4f32aeSBjoern A. Zeeb arg->tx_max_rate = __le16_to_cpu(vht_cap->vht_mcs.tx_highest);
2151dd4f32aeSBjoern A. Zeeb arg->tx_mcs_set = ath11k_peer_assoc_h_vht_limit(
2152dd4f32aeSBjoern A. Zeeb __le16_to_cpu(vht_cap->vht_mcs.tx_mcs_map), vht_mcs_mask);
2153dd4f32aeSBjoern A. Zeeb
2154dd4f32aeSBjoern A. Zeeb /* In IPQ8074 platform, VHT mcs rate 10 and 11 is enabled by default.
2155dd4f32aeSBjoern A. Zeeb * VHT mcs rate 10 and 11 is not suppoerted in 11ac standard.
2156dd4f32aeSBjoern A. Zeeb * so explicitly disable the VHT MCS rate 10 and 11 in 11ac mode.
2157dd4f32aeSBjoern A. Zeeb */
2158dd4f32aeSBjoern A. Zeeb arg->tx_mcs_set &= ~IEEE80211_VHT_MCS_SUPPORT_0_11_MASK;
2159dd4f32aeSBjoern A. Zeeb arg->tx_mcs_set |= IEEE80211_DISABLE_VHT_MCS_SUPPORT_0_11;
2160dd4f32aeSBjoern A. Zeeb
2161dd4f32aeSBjoern A. Zeeb if ((arg->tx_mcs_set & IEEE80211_VHT_MCS_NOT_SUPPORTED) ==
2162dd4f32aeSBjoern A. Zeeb IEEE80211_VHT_MCS_NOT_SUPPORTED)
2163dd4f32aeSBjoern A. Zeeb arg->peer_vht_caps &= ~IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
2164dd4f32aeSBjoern A. Zeeb
2165dd4f32aeSBjoern A. Zeeb /* TODO: Check */
2166dd4f32aeSBjoern A. Zeeb arg->tx_max_mcs_nss = 0xFF;
2167dd4f32aeSBjoern A. Zeeb
2168dd4f32aeSBjoern A. Zeeb if (arg->peer_phymode == MODE_11AC_VHT160 ||
2169dd4f32aeSBjoern A. Zeeb arg->peer_phymode == MODE_11AC_VHT80_80) {
2170dd4f32aeSBjoern A. Zeeb tx_nss = ath11k_get_nss_160mhz(ar, max_nss);
2171dd4f32aeSBjoern A. Zeeb rx_nss = min(arg->peer_nss, tx_nss);
2172dd4f32aeSBjoern A. Zeeb arg->peer_bw_rxnss_override = ATH11K_BW_NSS_MAP_ENABLE;
2173dd4f32aeSBjoern A. Zeeb
2174dd4f32aeSBjoern A. Zeeb if (!rx_nss) {
2175dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "invalid max_nss\n");
2176dd4f32aeSBjoern A. Zeeb return;
2177dd4f32aeSBjoern A. Zeeb }
2178dd4f32aeSBjoern A. Zeeb
2179dd4f32aeSBjoern A. Zeeb if (arg->peer_phymode == MODE_11AC_VHT160)
2180dd4f32aeSBjoern A. Zeeb nss_160 = FIELD_PREP(ATH11K_PEER_RX_NSS_160MHZ, rx_nss - 1);
2181dd4f32aeSBjoern A. Zeeb else
2182dd4f32aeSBjoern A. Zeeb nss_160 = FIELD_PREP(ATH11K_PEER_RX_NSS_80_80MHZ, rx_nss - 1);
2183dd4f32aeSBjoern A. Zeeb
2184dd4f32aeSBjoern A. Zeeb arg->peer_bw_rxnss_override |= nss_160;
2185dd4f32aeSBjoern A. Zeeb }
2186dd4f32aeSBjoern A. Zeeb
2187dd4f32aeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
218828348caeSBjoern A. Zeeb "vht peer %pM max_mpdu %d flags 0x%x nss_override 0x%x\n",
2189dd4f32aeSBjoern A. Zeeb sta->addr, arg->peer_max_mpdu, arg->peer_flags,
2190dd4f32aeSBjoern A. Zeeb arg->peer_bw_rxnss_override);
2191dd4f32aeSBjoern A. Zeeb }
2192dd4f32aeSBjoern A. Zeeb
ath11k_mac_get_max_he_mcs_map(u16 mcs_map,int nss)2193dd4f32aeSBjoern A. Zeeb static int ath11k_mac_get_max_he_mcs_map(u16 mcs_map, int nss)
2194dd4f32aeSBjoern A. Zeeb {
2195dd4f32aeSBjoern A. Zeeb switch ((mcs_map >> (2 * nss)) & 0x3) {
2196dd4f32aeSBjoern A. Zeeb case IEEE80211_HE_MCS_SUPPORT_0_7: return BIT(8) - 1;
2197dd4f32aeSBjoern A. Zeeb case IEEE80211_HE_MCS_SUPPORT_0_9: return BIT(10) - 1;
2198dd4f32aeSBjoern A. Zeeb case IEEE80211_HE_MCS_SUPPORT_0_11: return BIT(12) - 1;
2199dd4f32aeSBjoern A. Zeeb }
2200dd4f32aeSBjoern A. Zeeb return 0;
2201dd4f32aeSBjoern A. Zeeb }
2202dd4f32aeSBjoern A. Zeeb
ath11k_peer_assoc_h_he_limit(u16 tx_mcs_set,const u16 he_mcs_limit[NL80211_HE_NSS_MAX])2203dd4f32aeSBjoern A. Zeeb static u16 ath11k_peer_assoc_h_he_limit(u16 tx_mcs_set,
2204dd4f32aeSBjoern A. Zeeb const u16 he_mcs_limit[NL80211_HE_NSS_MAX])
2205dd4f32aeSBjoern A. Zeeb {
2206dd4f32aeSBjoern A. Zeeb int idx_limit;
2207dd4f32aeSBjoern A. Zeeb int nss;
2208dd4f32aeSBjoern A. Zeeb u16 mcs_map;
2209dd4f32aeSBjoern A. Zeeb u16 mcs;
2210dd4f32aeSBjoern A. Zeeb
2211dd4f32aeSBjoern A. Zeeb for (nss = 0; nss < NL80211_HE_NSS_MAX; nss++) {
2212dd4f32aeSBjoern A. Zeeb mcs_map = ath11k_mac_get_max_he_mcs_map(tx_mcs_set, nss) &
2213dd4f32aeSBjoern A. Zeeb he_mcs_limit[nss];
2214dd4f32aeSBjoern A. Zeeb
2215dd4f32aeSBjoern A. Zeeb if (mcs_map)
2216dd4f32aeSBjoern A. Zeeb idx_limit = fls(mcs_map) - 1;
2217dd4f32aeSBjoern A. Zeeb else
2218dd4f32aeSBjoern A. Zeeb idx_limit = -1;
2219dd4f32aeSBjoern A. Zeeb
2220dd4f32aeSBjoern A. Zeeb switch (idx_limit) {
2221dd4f32aeSBjoern A. Zeeb case 0 ... 7:
2222dd4f32aeSBjoern A. Zeeb mcs = IEEE80211_HE_MCS_SUPPORT_0_7;
2223dd4f32aeSBjoern A. Zeeb break;
2224dd4f32aeSBjoern A. Zeeb case 8:
2225dd4f32aeSBjoern A. Zeeb case 9:
2226dd4f32aeSBjoern A. Zeeb mcs = IEEE80211_HE_MCS_SUPPORT_0_9;
2227dd4f32aeSBjoern A. Zeeb break;
2228dd4f32aeSBjoern A. Zeeb case 10:
2229dd4f32aeSBjoern A. Zeeb case 11:
2230dd4f32aeSBjoern A. Zeeb mcs = IEEE80211_HE_MCS_SUPPORT_0_11;
2231dd4f32aeSBjoern A. Zeeb break;
2232dd4f32aeSBjoern A. Zeeb default:
2233dd4f32aeSBjoern A. Zeeb WARN_ON(1);
2234dd4f32aeSBjoern A. Zeeb fallthrough;
2235dd4f32aeSBjoern A. Zeeb case -1:
2236dd4f32aeSBjoern A. Zeeb mcs = IEEE80211_HE_MCS_NOT_SUPPORTED;
2237dd4f32aeSBjoern A. Zeeb break;
2238dd4f32aeSBjoern A. Zeeb }
2239dd4f32aeSBjoern A. Zeeb
2240dd4f32aeSBjoern A. Zeeb tx_mcs_set &= ~(0x3 << (nss * 2));
2241dd4f32aeSBjoern A. Zeeb tx_mcs_set |= mcs << (nss * 2);
2242dd4f32aeSBjoern A. Zeeb }
2243dd4f32aeSBjoern A. Zeeb
2244dd4f32aeSBjoern A. Zeeb return tx_mcs_set;
2245dd4f32aeSBjoern A. Zeeb }
2246dd4f32aeSBjoern A. Zeeb
2247dd4f32aeSBjoern A. Zeeb static bool
ath11k_peer_assoc_h_he_masked(const u16 * he_mcs_mask)224828348caeSBjoern A. Zeeb ath11k_peer_assoc_h_he_masked(const u16 *he_mcs_mask)
2249dd4f32aeSBjoern A. Zeeb {
2250dd4f32aeSBjoern A. Zeeb int nss;
2251dd4f32aeSBjoern A. Zeeb
2252dd4f32aeSBjoern A. Zeeb for (nss = 0; nss < NL80211_HE_NSS_MAX; nss++)
2253dd4f32aeSBjoern A. Zeeb if (he_mcs_mask[nss])
2254dd4f32aeSBjoern A. Zeeb return false;
2255dd4f32aeSBjoern A. Zeeb
2256dd4f32aeSBjoern A. Zeeb return true;
2257dd4f32aeSBjoern A. Zeeb }
2258dd4f32aeSBjoern A. Zeeb
ath11k_peer_assoc_h_he(struct ath11k * ar,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct peer_assoc_params * arg)2259dd4f32aeSBjoern A. Zeeb static void ath11k_peer_assoc_h_he(struct ath11k *ar,
2260dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif,
2261dd4f32aeSBjoern A. Zeeb struct ieee80211_sta *sta,
2262dd4f32aeSBjoern A. Zeeb struct peer_assoc_params *arg)
2263dd4f32aeSBjoern A. Zeeb {
2264dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif = (void *)vif->drv_priv;
2265dd4f32aeSBjoern A. Zeeb struct cfg80211_chan_def def;
2266dd4f32aeSBjoern A. Zeeb const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap;
2267dd4f32aeSBjoern A. Zeeb enum nl80211_band band;
226828348caeSBjoern A. Zeeb u16 he_mcs_mask[NL80211_HE_NSS_MAX];
2269dd4f32aeSBjoern A. Zeeb u8 max_nss, he_mcs;
2270dd4f32aeSBjoern A. Zeeb u16 he_tx_mcs = 0, v = 0;
2271dd4f32aeSBjoern A. Zeeb int i, he_nss, nss_idx;
2272dd4f32aeSBjoern A. Zeeb bool user_rate_valid = true;
2273dd4f32aeSBjoern A. Zeeb u32 rx_nss, tx_nss, nss_160;
2274dd4f32aeSBjoern A. Zeeb u8 ampdu_factor, rx_mcs_80, rx_mcs_160;
2275dd4f32aeSBjoern A. Zeeb u16 mcs_160_map, mcs_80_map;
2276dd4f32aeSBjoern A. Zeeb bool support_160;
2277dd4f32aeSBjoern A. Zeeb
2278dd4f32aeSBjoern A. Zeeb if (WARN_ON(ath11k_mac_vif_chan(vif, &def)))
2279dd4f32aeSBjoern A. Zeeb return;
2280dd4f32aeSBjoern A. Zeeb
2281dd4f32aeSBjoern A. Zeeb if (!he_cap->has_he)
2282dd4f32aeSBjoern A. Zeeb return;
2283dd4f32aeSBjoern A. Zeeb
2284dd4f32aeSBjoern A. Zeeb band = def.chan->band;
228528348caeSBjoern A. Zeeb memcpy(he_mcs_mask, arvif->bitrate_mask.control[band].he_mcs,
228628348caeSBjoern A. Zeeb sizeof(he_mcs_mask));
2287dd4f32aeSBjoern A. Zeeb
2288dd4f32aeSBjoern A. Zeeb if (ath11k_peer_assoc_h_he_masked(he_mcs_mask))
2289dd4f32aeSBjoern A. Zeeb return;
2290dd4f32aeSBjoern A. Zeeb
2291dd4f32aeSBjoern A. Zeeb arg->he_flag = true;
2292dd4f32aeSBjoern A. Zeeb support_160 = !!(he_cap->he_cap_elem.phy_cap_info[0] &
2293dd4f32aeSBjoern A. Zeeb IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G);
2294dd4f32aeSBjoern A. Zeeb
2295dd4f32aeSBjoern A. Zeeb /* Supported HE-MCS and NSS Set of peer he_cap is intersection with self he_cp */
2296dd4f32aeSBjoern A. Zeeb mcs_160_map = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160);
2297dd4f32aeSBjoern A. Zeeb mcs_80_map = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80);
2298dd4f32aeSBjoern A. Zeeb
2299dd4f32aeSBjoern A. Zeeb if (support_160) {
2300dd4f32aeSBjoern A. Zeeb for (i = 7; i >= 0; i--) {
2301dd4f32aeSBjoern A. Zeeb u8 mcs_160 = (mcs_160_map >> (2 * i)) & 3;
2302dd4f32aeSBjoern A. Zeeb
2303dd4f32aeSBjoern A. Zeeb if (mcs_160 != IEEE80211_VHT_MCS_NOT_SUPPORTED) {
2304dd4f32aeSBjoern A. Zeeb rx_mcs_160 = i + 1;
2305dd4f32aeSBjoern A. Zeeb break;
2306dd4f32aeSBjoern A. Zeeb }
2307dd4f32aeSBjoern A. Zeeb }
2308dd4f32aeSBjoern A. Zeeb }
2309dd4f32aeSBjoern A. Zeeb
2310dd4f32aeSBjoern A. Zeeb for (i = 7; i >= 0; i--) {
2311dd4f32aeSBjoern A. Zeeb u8 mcs_80 = (mcs_80_map >> (2 * i)) & 3;
2312dd4f32aeSBjoern A. Zeeb
2313dd4f32aeSBjoern A. Zeeb if (mcs_80 != IEEE80211_VHT_MCS_NOT_SUPPORTED) {
2314dd4f32aeSBjoern A. Zeeb rx_mcs_80 = i + 1;
2315dd4f32aeSBjoern A. Zeeb break;
2316dd4f32aeSBjoern A. Zeeb }
2317dd4f32aeSBjoern A. Zeeb }
2318dd4f32aeSBjoern A. Zeeb
2319dd4f32aeSBjoern A. Zeeb if (support_160)
2320dd4f32aeSBjoern A. Zeeb max_nss = min(rx_mcs_80, rx_mcs_160);
2321dd4f32aeSBjoern A. Zeeb else
2322dd4f32aeSBjoern A. Zeeb max_nss = rx_mcs_80;
2323dd4f32aeSBjoern A. Zeeb
2324dd4f32aeSBjoern A. Zeeb arg->peer_nss = min(sta->deflink.rx_nss, max_nss);
2325dd4f32aeSBjoern A. Zeeb
2326dd4f32aeSBjoern A. Zeeb memcpy_and_pad(&arg->peer_he_cap_macinfo,
2327dd4f32aeSBjoern A. Zeeb sizeof(arg->peer_he_cap_macinfo),
2328dd4f32aeSBjoern A. Zeeb he_cap->he_cap_elem.mac_cap_info,
2329dd4f32aeSBjoern A. Zeeb sizeof(he_cap->he_cap_elem.mac_cap_info),
2330dd4f32aeSBjoern A. Zeeb 0);
2331dd4f32aeSBjoern A. Zeeb memcpy_and_pad(&arg->peer_he_cap_phyinfo,
2332dd4f32aeSBjoern A. Zeeb sizeof(arg->peer_he_cap_phyinfo),
2333dd4f32aeSBjoern A. Zeeb he_cap->he_cap_elem.phy_cap_info,
2334dd4f32aeSBjoern A. Zeeb sizeof(he_cap->he_cap_elem.phy_cap_info),
2335dd4f32aeSBjoern A. Zeeb 0);
2336dd4f32aeSBjoern A. Zeeb arg->peer_he_ops = vif->bss_conf.he_oper.params;
2337dd4f32aeSBjoern A. Zeeb
2338dd4f32aeSBjoern A. Zeeb /* the top most byte is used to indicate BSS color info */
2339dd4f32aeSBjoern A. Zeeb arg->peer_he_ops &= 0xffffff;
2340dd4f32aeSBjoern A. Zeeb
2341dd4f32aeSBjoern A. Zeeb /* As per section 26.6.1 11ax Draft5.0, if the Max AMPDU Exponent Extension
2342dd4f32aeSBjoern A. Zeeb * in HE cap is zero, use the arg->peer_max_mpdu as calculated while parsing
2343dd4f32aeSBjoern A. Zeeb * VHT caps(if VHT caps is present) or HT caps (if VHT caps is not present).
2344dd4f32aeSBjoern A. Zeeb *
2345dd4f32aeSBjoern A. Zeeb * For non-zero value of Max AMPDU Extponent Extension in HE MAC caps,
2346dd4f32aeSBjoern A. Zeeb * if a HE STA sends VHT cap and HE cap IE in assoc request then, use
2347dd4f32aeSBjoern A. Zeeb * MAX_AMPDU_LEN_FACTOR as 20 to calculate max_ampdu length.
2348dd4f32aeSBjoern A. Zeeb * If a HE STA that does not send VHT cap, but HE and HT cap in assoc
2349dd4f32aeSBjoern A. Zeeb * request, then use MAX_AMPDU_LEN_FACTOR as 16 to calculate max_ampdu
2350dd4f32aeSBjoern A. Zeeb * length.
2351dd4f32aeSBjoern A. Zeeb */
2352dd4f32aeSBjoern A. Zeeb ampdu_factor = u8_get_bits(he_cap->he_cap_elem.mac_cap_info[3],
2353dd4f32aeSBjoern A. Zeeb IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_MASK);
2354dd4f32aeSBjoern A. Zeeb
2355dd4f32aeSBjoern A. Zeeb if (ampdu_factor) {
2356dd4f32aeSBjoern A. Zeeb if (sta->deflink.vht_cap.vht_supported)
2357dd4f32aeSBjoern A. Zeeb arg->peer_max_mpdu = (1 << (IEEE80211_HE_VHT_MAX_AMPDU_FACTOR +
2358dd4f32aeSBjoern A. Zeeb ampdu_factor)) - 1;
2359dd4f32aeSBjoern A. Zeeb else if (sta->deflink.ht_cap.ht_supported)
2360dd4f32aeSBjoern A. Zeeb arg->peer_max_mpdu = (1 << (IEEE80211_HE_HT_MAX_AMPDU_FACTOR +
2361dd4f32aeSBjoern A. Zeeb ampdu_factor)) - 1;
2362dd4f32aeSBjoern A. Zeeb }
2363dd4f32aeSBjoern A. Zeeb
2364dd4f32aeSBjoern A. Zeeb if (he_cap->he_cap_elem.phy_cap_info[6] &
2365dd4f32aeSBjoern A. Zeeb IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) {
2366dd4f32aeSBjoern A. Zeeb int bit = 7;
2367dd4f32aeSBjoern A. Zeeb int nss, ru;
2368dd4f32aeSBjoern A. Zeeb
2369dd4f32aeSBjoern A. Zeeb arg->peer_ppet.numss_m1 = he_cap->ppe_thres[0] &
2370dd4f32aeSBjoern A. Zeeb IEEE80211_PPE_THRES_NSS_MASK;
2371dd4f32aeSBjoern A. Zeeb arg->peer_ppet.ru_bit_mask =
2372dd4f32aeSBjoern A. Zeeb (he_cap->ppe_thres[0] &
2373dd4f32aeSBjoern A. Zeeb IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK) >>
2374dd4f32aeSBjoern A. Zeeb IEEE80211_PPE_THRES_RU_INDEX_BITMASK_POS;
2375dd4f32aeSBjoern A. Zeeb
2376dd4f32aeSBjoern A. Zeeb for (nss = 0; nss <= arg->peer_ppet.numss_m1; nss++) {
2377dd4f32aeSBjoern A. Zeeb for (ru = 0; ru < 4; ru++) {
2378dd4f32aeSBjoern A. Zeeb u32 val = 0;
2379dd4f32aeSBjoern A. Zeeb int i;
2380dd4f32aeSBjoern A. Zeeb
2381dd4f32aeSBjoern A. Zeeb if ((arg->peer_ppet.ru_bit_mask & BIT(ru)) == 0)
2382dd4f32aeSBjoern A. Zeeb continue;
2383dd4f32aeSBjoern A. Zeeb for (i = 0; i < 6; i++) {
2384dd4f32aeSBjoern A. Zeeb val >>= 1;
2385dd4f32aeSBjoern A. Zeeb val |= ((he_cap->ppe_thres[bit / 8] >>
2386dd4f32aeSBjoern A. Zeeb (bit % 8)) & 0x1) << 5;
2387dd4f32aeSBjoern A. Zeeb bit++;
2388dd4f32aeSBjoern A. Zeeb }
2389dd4f32aeSBjoern A. Zeeb arg->peer_ppet.ppet16_ppet8_ru3_ru0[nss] |=
2390dd4f32aeSBjoern A. Zeeb val << (ru * 6);
2391dd4f32aeSBjoern A. Zeeb }
2392dd4f32aeSBjoern A. Zeeb }
2393dd4f32aeSBjoern A. Zeeb }
2394dd4f32aeSBjoern A. Zeeb
2395dd4f32aeSBjoern A. Zeeb if (he_cap->he_cap_elem.mac_cap_info[0] & IEEE80211_HE_MAC_CAP0_TWT_RES)
2396dd4f32aeSBjoern A. Zeeb arg->twt_responder = true;
2397dd4f32aeSBjoern A. Zeeb if (he_cap->he_cap_elem.mac_cap_info[0] & IEEE80211_HE_MAC_CAP0_TWT_REQ)
2398dd4f32aeSBjoern A. Zeeb arg->twt_requester = true;
2399dd4f32aeSBjoern A. Zeeb
2400dd4f32aeSBjoern A. Zeeb he_nss = ath11k_mac_max_he_nss(he_mcs_mask);
2401dd4f32aeSBjoern A. Zeeb
2402dd4f32aeSBjoern A. Zeeb if (he_nss > sta->deflink.rx_nss) {
2403dd4f32aeSBjoern A. Zeeb user_rate_valid = false;
2404dd4f32aeSBjoern A. Zeeb for (nss_idx = sta->deflink.rx_nss - 1; nss_idx >= 0; nss_idx--) {
2405dd4f32aeSBjoern A. Zeeb if (he_mcs_mask[nss_idx]) {
2406dd4f32aeSBjoern A. Zeeb user_rate_valid = true;
2407dd4f32aeSBjoern A. Zeeb break;
2408dd4f32aeSBjoern A. Zeeb }
2409dd4f32aeSBjoern A. Zeeb }
2410dd4f32aeSBjoern A. Zeeb }
2411dd4f32aeSBjoern A. Zeeb
2412dd4f32aeSBjoern A. Zeeb if (!user_rate_valid) {
241328348caeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "setting he range mcs value to peer supported nss %d for peer %pM\n",
2414dd4f32aeSBjoern A. Zeeb sta->deflink.rx_nss, sta->addr);
2415dd4f32aeSBjoern A. Zeeb he_mcs_mask[sta->deflink.rx_nss - 1] = he_mcs_mask[he_nss - 1];
2416dd4f32aeSBjoern A. Zeeb }
2417dd4f32aeSBjoern A. Zeeb
2418dd4f32aeSBjoern A. Zeeb switch (sta->deflink.bandwidth) {
2419dd4f32aeSBjoern A. Zeeb case IEEE80211_STA_RX_BW_160:
2420dd4f32aeSBjoern A. Zeeb if (he_cap->he_cap_elem.phy_cap_info[0] &
2421dd4f32aeSBjoern A. Zeeb IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G) {
2422dd4f32aeSBjoern A. Zeeb v = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80p80);
2423dd4f32aeSBjoern A. Zeeb v = ath11k_peer_assoc_h_he_limit(v, he_mcs_mask);
2424dd4f32aeSBjoern A. Zeeb arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80_80] = v;
2425dd4f32aeSBjoern A. Zeeb
2426dd4f32aeSBjoern A. Zeeb v = le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_80p80);
2427dd4f32aeSBjoern A. Zeeb arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80_80] = v;
2428dd4f32aeSBjoern A. Zeeb
2429dd4f32aeSBjoern A. Zeeb arg->peer_he_mcs_count++;
2430dd4f32aeSBjoern A. Zeeb he_tx_mcs = v;
2431dd4f32aeSBjoern A. Zeeb }
2432dd4f32aeSBjoern A. Zeeb v = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160);
2433dd4f32aeSBjoern A. Zeeb arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_160] = v;
2434dd4f32aeSBjoern A. Zeeb
2435dd4f32aeSBjoern A. Zeeb v = le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_160);
2436dd4f32aeSBjoern A. Zeeb v = ath11k_peer_assoc_h_he_limit(v, he_mcs_mask);
2437dd4f32aeSBjoern A. Zeeb arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_160] = v;
2438dd4f32aeSBjoern A. Zeeb
2439dd4f32aeSBjoern A. Zeeb arg->peer_he_mcs_count++;
2440dd4f32aeSBjoern A. Zeeb if (!he_tx_mcs)
2441dd4f32aeSBjoern A. Zeeb he_tx_mcs = v;
2442dd4f32aeSBjoern A. Zeeb fallthrough;
2443dd4f32aeSBjoern A. Zeeb
2444dd4f32aeSBjoern A. Zeeb default:
2445dd4f32aeSBjoern A. Zeeb v = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80);
2446dd4f32aeSBjoern A. Zeeb arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80] = v;
2447dd4f32aeSBjoern A. Zeeb
2448dd4f32aeSBjoern A. Zeeb v = le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_80);
2449dd4f32aeSBjoern A. Zeeb v = ath11k_peer_assoc_h_he_limit(v, he_mcs_mask);
2450dd4f32aeSBjoern A. Zeeb arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80] = v;
2451dd4f32aeSBjoern A. Zeeb
2452dd4f32aeSBjoern A. Zeeb arg->peer_he_mcs_count++;
2453dd4f32aeSBjoern A. Zeeb if (!he_tx_mcs)
2454dd4f32aeSBjoern A. Zeeb he_tx_mcs = v;
2455dd4f32aeSBjoern A. Zeeb break;
2456dd4f32aeSBjoern A. Zeeb }
2457dd4f32aeSBjoern A. Zeeb
2458dd4f32aeSBjoern A. Zeeb /* Calculate peer NSS capability from HE capabilities if STA
2459dd4f32aeSBjoern A. Zeeb * supports HE.
2460dd4f32aeSBjoern A. Zeeb */
246128348caeSBjoern A. Zeeb for (i = 0, max_nss = 0; i < NL80211_HE_NSS_MAX; i++) {
2462dd4f32aeSBjoern A. Zeeb he_mcs = he_tx_mcs >> (2 * i) & 3;
2463dd4f32aeSBjoern A. Zeeb
2464dd4f32aeSBjoern A. Zeeb /* In case of fixed rates, MCS Range in he_tx_mcs might have
2465dd4f32aeSBjoern A. Zeeb * unsupported range, with he_mcs_mask set, so check either of them
2466dd4f32aeSBjoern A. Zeeb * to find nss.
2467dd4f32aeSBjoern A. Zeeb */
2468dd4f32aeSBjoern A. Zeeb if (he_mcs != IEEE80211_HE_MCS_NOT_SUPPORTED ||
2469dd4f32aeSBjoern A. Zeeb he_mcs_mask[i])
2470dd4f32aeSBjoern A. Zeeb max_nss = i + 1;
2471dd4f32aeSBjoern A. Zeeb }
2472dd4f32aeSBjoern A. Zeeb arg->peer_nss = min(sta->deflink.rx_nss, max_nss);
2473dd4f32aeSBjoern A. Zeeb
2474dd4f32aeSBjoern A. Zeeb if (arg->peer_phymode == MODE_11AX_HE160 ||
2475dd4f32aeSBjoern A. Zeeb arg->peer_phymode == MODE_11AX_HE80_80) {
2476dd4f32aeSBjoern A. Zeeb tx_nss = ath11k_get_nss_160mhz(ar, max_nss);
2477dd4f32aeSBjoern A. Zeeb rx_nss = min(arg->peer_nss, tx_nss);
2478dd4f32aeSBjoern A. Zeeb arg->peer_bw_rxnss_override = ATH11K_BW_NSS_MAP_ENABLE;
2479dd4f32aeSBjoern A. Zeeb
2480dd4f32aeSBjoern A. Zeeb if (!rx_nss) {
2481dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "invalid max_nss\n");
2482dd4f32aeSBjoern A. Zeeb return;
2483dd4f32aeSBjoern A. Zeeb }
2484dd4f32aeSBjoern A. Zeeb
2485dd4f32aeSBjoern A. Zeeb if (arg->peer_phymode == MODE_11AX_HE160)
2486dd4f32aeSBjoern A. Zeeb nss_160 = FIELD_PREP(ATH11K_PEER_RX_NSS_160MHZ, rx_nss - 1);
2487dd4f32aeSBjoern A. Zeeb else
2488dd4f32aeSBjoern A. Zeeb nss_160 = FIELD_PREP(ATH11K_PEER_RX_NSS_80_80MHZ, rx_nss - 1);
2489dd4f32aeSBjoern A. Zeeb
2490dd4f32aeSBjoern A. Zeeb arg->peer_bw_rxnss_override |= nss_160;
2491dd4f32aeSBjoern A. Zeeb }
2492dd4f32aeSBjoern A. Zeeb
2493dd4f32aeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
249428348caeSBjoern A. Zeeb "he peer %pM nss %d mcs cnt %d nss_override 0x%x\n",
2495dd4f32aeSBjoern A. Zeeb sta->addr, arg->peer_nss,
2496dd4f32aeSBjoern A. Zeeb arg->peer_he_mcs_count,
2497dd4f32aeSBjoern A. Zeeb arg->peer_bw_rxnss_override);
2498dd4f32aeSBjoern A. Zeeb }
2499dd4f32aeSBjoern A. Zeeb
ath11k_peer_assoc_h_he_6ghz(struct ath11k * ar,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct peer_assoc_params * arg)2500dd4f32aeSBjoern A. Zeeb static void ath11k_peer_assoc_h_he_6ghz(struct ath11k *ar,
2501dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif,
2502dd4f32aeSBjoern A. Zeeb struct ieee80211_sta *sta,
2503dd4f32aeSBjoern A. Zeeb struct peer_assoc_params *arg)
2504dd4f32aeSBjoern A. Zeeb {
2505dd4f32aeSBjoern A. Zeeb const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap;
2506dd4f32aeSBjoern A. Zeeb struct cfg80211_chan_def def;
2507dd4f32aeSBjoern A. Zeeb enum nl80211_band band;
2508dd4f32aeSBjoern A. Zeeb u8 ampdu_factor;
2509dd4f32aeSBjoern A. Zeeb
2510dd4f32aeSBjoern A. Zeeb if (WARN_ON(ath11k_mac_vif_chan(vif, &def)))
2511dd4f32aeSBjoern A. Zeeb return;
2512dd4f32aeSBjoern A. Zeeb
2513dd4f32aeSBjoern A. Zeeb band = def.chan->band;
2514dd4f32aeSBjoern A. Zeeb
2515dd4f32aeSBjoern A. Zeeb if (!arg->he_flag || band != NL80211_BAND_6GHZ || !sta->deflink.he_6ghz_capa.capa)
2516dd4f32aeSBjoern A. Zeeb return;
2517dd4f32aeSBjoern A. Zeeb
251828348caeSBjoern A. Zeeb if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
251928348caeSBjoern A. Zeeb arg->bw_40 = true;
252028348caeSBjoern A. Zeeb
2521dd4f32aeSBjoern A. Zeeb if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80)
2522dd4f32aeSBjoern A. Zeeb arg->bw_80 = true;
2523dd4f32aeSBjoern A. Zeeb
2524dd4f32aeSBjoern A. Zeeb if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160)
2525dd4f32aeSBjoern A. Zeeb arg->bw_160 = true;
2526dd4f32aeSBjoern A. Zeeb
2527dd4f32aeSBjoern A. Zeeb arg->peer_he_caps_6ghz = le16_to_cpu(sta->deflink.he_6ghz_capa.capa);
2528dd4f32aeSBjoern A. Zeeb arg->peer_mpdu_density =
2529dd4f32aeSBjoern A. Zeeb ath11k_parse_mpdudensity(FIELD_GET(IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START,
2530dd4f32aeSBjoern A. Zeeb arg->peer_he_caps_6ghz));
2531dd4f32aeSBjoern A. Zeeb
2532dd4f32aeSBjoern A. Zeeb /* From IEEE Std 802.11ax-2021 - Section 10.12.2: An HE STA shall be capable of
2533dd4f32aeSBjoern A. Zeeb * receiving A-MPDU where the A-MPDU pre-EOF padding length is up to the value
2534dd4f32aeSBjoern A. Zeeb * indicated by the Maximum A-MPDU Length Exponent Extension field in the HE
2535dd4f32aeSBjoern A. Zeeb * Capabilities element and the Maximum A-MPDU Length Exponent field in HE 6 GHz
2536dd4f32aeSBjoern A. Zeeb * Band Capabilities element in the 6 GHz band.
2537dd4f32aeSBjoern A. Zeeb *
2538dd4f32aeSBjoern A. Zeeb * Here, we are extracting the Max A-MPDU Exponent Extension from HE caps and
2539dd4f32aeSBjoern A. Zeeb * factor is the Maximum A-MPDU Length Exponent from HE 6 GHZ Band capability.
2540dd4f32aeSBjoern A. Zeeb */
2541dd4f32aeSBjoern A. Zeeb ampdu_factor = FIELD_GET(IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_MASK,
2542dd4f32aeSBjoern A. Zeeb he_cap->he_cap_elem.mac_cap_info[3]) +
2543dd4f32aeSBjoern A. Zeeb FIELD_GET(IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP,
2544dd4f32aeSBjoern A. Zeeb arg->peer_he_caps_6ghz);
2545dd4f32aeSBjoern A. Zeeb
2546dd4f32aeSBjoern A. Zeeb arg->peer_max_mpdu = (1u << (IEEE80211_HE_6GHZ_MAX_AMPDU_FACTOR +
2547dd4f32aeSBjoern A. Zeeb ampdu_factor)) - 1;
2548dd4f32aeSBjoern A. Zeeb }
2549dd4f32aeSBjoern A. Zeeb
ath11k_peer_assoc_h_smps(struct ieee80211_sta * sta,struct peer_assoc_params * arg)2550dd4f32aeSBjoern A. Zeeb static void ath11k_peer_assoc_h_smps(struct ieee80211_sta *sta,
2551dd4f32aeSBjoern A. Zeeb struct peer_assoc_params *arg)
2552dd4f32aeSBjoern A. Zeeb {
2553dd4f32aeSBjoern A. Zeeb const struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap;
2554dd4f32aeSBjoern A. Zeeb int smps;
2555dd4f32aeSBjoern A. Zeeb
2556dd4f32aeSBjoern A. Zeeb if (!ht_cap->ht_supported && !sta->deflink.he_6ghz_capa.capa)
2557dd4f32aeSBjoern A. Zeeb return;
2558dd4f32aeSBjoern A. Zeeb
2559dd4f32aeSBjoern A. Zeeb if (ht_cap->ht_supported) {
2560dd4f32aeSBjoern A. Zeeb smps = ht_cap->cap & IEEE80211_HT_CAP_SM_PS;
2561dd4f32aeSBjoern A. Zeeb smps >>= IEEE80211_HT_CAP_SM_PS_SHIFT;
2562dd4f32aeSBjoern A. Zeeb } else {
2563dd4f32aeSBjoern A. Zeeb smps = le16_get_bits(sta->deflink.he_6ghz_capa.capa,
2564dd4f32aeSBjoern A. Zeeb IEEE80211_HE_6GHZ_CAP_SM_PS);
2565dd4f32aeSBjoern A. Zeeb }
2566dd4f32aeSBjoern A. Zeeb
2567dd4f32aeSBjoern A. Zeeb switch (smps) {
2568dd4f32aeSBjoern A. Zeeb case WLAN_HT_CAP_SM_PS_STATIC:
2569dd4f32aeSBjoern A. Zeeb arg->static_mimops_flag = true;
2570dd4f32aeSBjoern A. Zeeb break;
2571dd4f32aeSBjoern A. Zeeb case WLAN_HT_CAP_SM_PS_DYNAMIC:
2572dd4f32aeSBjoern A. Zeeb arg->dynamic_mimops_flag = true;
2573dd4f32aeSBjoern A. Zeeb break;
2574dd4f32aeSBjoern A. Zeeb case WLAN_HT_CAP_SM_PS_DISABLED:
2575dd4f32aeSBjoern A. Zeeb arg->spatial_mux_flag = true;
2576dd4f32aeSBjoern A. Zeeb break;
2577dd4f32aeSBjoern A. Zeeb default:
2578dd4f32aeSBjoern A. Zeeb break;
2579dd4f32aeSBjoern A. Zeeb }
2580dd4f32aeSBjoern A. Zeeb }
2581dd4f32aeSBjoern A. Zeeb
ath11k_peer_assoc_h_qos(struct ath11k * ar,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct peer_assoc_params * arg)2582dd4f32aeSBjoern A. Zeeb static void ath11k_peer_assoc_h_qos(struct ath11k *ar,
2583dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif,
2584dd4f32aeSBjoern A. Zeeb struct ieee80211_sta *sta,
2585dd4f32aeSBjoern A. Zeeb struct peer_assoc_params *arg)
2586dd4f32aeSBjoern A. Zeeb {
2587dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif = (void *)vif->drv_priv;
2588dd4f32aeSBjoern A. Zeeb
2589dd4f32aeSBjoern A. Zeeb switch (arvif->vdev_type) {
2590dd4f32aeSBjoern A. Zeeb case WMI_VDEV_TYPE_AP:
2591dd4f32aeSBjoern A. Zeeb if (sta->wme) {
2592dd4f32aeSBjoern A. Zeeb /* TODO: Check WME vs QoS */
2593dd4f32aeSBjoern A. Zeeb arg->is_wme_set = true;
2594dd4f32aeSBjoern A. Zeeb arg->qos_flag = true;
2595dd4f32aeSBjoern A. Zeeb }
2596dd4f32aeSBjoern A. Zeeb
2597dd4f32aeSBjoern A. Zeeb if (sta->wme && sta->uapsd_queues) {
2598dd4f32aeSBjoern A. Zeeb /* TODO: Check WME vs QoS */
2599dd4f32aeSBjoern A. Zeeb arg->is_wme_set = true;
2600dd4f32aeSBjoern A. Zeeb arg->apsd_flag = true;
2601dd4f32aeSBjoern A. Zeeb arg->peer_rate_caps |= WMI_HOST_RC_UAPSD_FLAG;
2602dd4f32aeSBjoern A. Zeeb }
2603dd4f32aeSBjoern A. Zeeb break;
2604dd4f32aeSBjoern A. Zeeb case WMI_VDEV_TYPE_STA:
2605dd4f32aeSBjoern A. Zeeb if (sta->wme) {
2606dd4f32aeSBjoern A. Zeeb arg->is_wme_set = true;
2607dd4f32aeSBjoern A. Zeeb arg->qos_flag = true;
2608dd4f32aeSBjoern A. Zeeb }
2609dd4f32aeSBjoern A. Zeeb break;
2610dd4f32aeSBjoern A. Zeeb default:
2611dd4f32aeSBjoern A. Zeeb break;
2612dd4f32aeSBjoern A. Zeeb }
2613dd4f32aeSBjoern A. Zeeb
261428348caeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "peer %pM qos %d\n",
2615dd4f32aeSBjoern A. Zeeb sta->addr, arg->qos_flag);
2616dd4f32aeSBjoern A. Zeeb }
2617dd4f32aeSBjoern A. Zeeb
ath11k_peer_assoc_qos_ap(struct ath11k * ar,struct ath11k_vif * arvif,struct ieee80211_sta * sta)2618dd4f32aeSBjoern A. Zeeb static int ath11k_peer_assoc_qos_ap(struct ath11k *ar,
2619dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif,
2620dd4f32aeSBjoern A. Zeeb struct ieee80211_sta *sta)
2621dd4f32aeSBjoern A. Zeeb {
2622dd4f32aeSBjoern A. Zeeb struct ap_ps_params params;
2623dd4f32aeSBjoern A. Zeeb u32 max_sp;
2624dd4f32aeSBjoern A. Zeeb u32 uapsd;
2625dd4f32aeSBjoern A. Zeeb int ret;
2626dd4f32aeSBjoern A. Zeeb
2627dd4f32aeSBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
2628dd4f32aeSBjoern A. Zeeb
2629dd4f32aeSBjoern A. Zeeb params.vdev_id = arvif->vdev_id;
2630dd4f32aeSBjoern A. Zeeb
263128348caeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "uapsd_queues 0x%x max_sp %d\n",
2632dd4f32aeSBjoern A. Zeeb sta->uapsd_queues, sta->max_sp);
2633dd4f32aeSBjoern A. Zeeb
2634dd4f32aeSBjoern A. Zeeb uapsd = 0;
2635dd4f32aeSBjoern A. Zeeb if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO)
2636dd4f32aeSBjoern A. Zeeb uapsd |= WMI_AP_PS_UAPSD_AC3_DELIVERY_EN |
2637dd4f32aeSBjoern A. Zeeb WMI_AP_PS_UAPSD_AC3_TRIGGER_EN;
2638dd4f32aeSBjoern A. Zeeb if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VI)
2639dd4f32aeSBjoern A. Zeeb uapsd |= WMI_AP_PS_UAPSD_AC2_DELIVERY_EN |
2640dd4f32aeSBjoern A. Zeeb WMI_AP_PS_UAPSD_AC2_TRIGGER_EN;
2641dd4f32aeSBjoern A. Zeeb if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BK)
2642dd4f32aeSBjoern A. Zeeb uapsd |= WMI_AP_PS_UAPSD_AC1_DELIVERY_EN |
2643dd4f32aeSBjoern A. Zeeb WMI_AP_PS_UAPSD_AC1_TRIGGER_EN;
2644dd4f32aeSBjoern A. Zeeb if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BE)
2645dd4f32aeSBjoern A. Zeeb uapsd |= WMI_AP_PS_UAPSD_AC0_DELIVERY_EN |
2646dd4f32aeSBjoern A. Zeeb WMI_AP_PS_UAPSD_AC0_TRIGGER_EN;
2647dd4f32aeSBjoern A. Zeeb
2648dd4f32aeSBjoern A. Zeeb max_sp = 0;
2649dd4f32aeSBjoern A. Zeeb if (sta->max_sp < MAX_WMI_AP_PS_PEER_PARAM_MAX_SP)
2650dd4f32aeSBjoern A. Zeeb max_sp = sta->max_sp;
2651dd4f32aeSBjoern A. Zeeb
2652dd4f32aeSBjoern A. Zeeb params.param = WMI_AP_PS_PEER_PARAM_UAPSD;
2653dd4f32aeSBjoern A. Zeeb params.value = uapsd;
2654dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_send_set_ap_ps_param_cmd(ar, sta->addr, ¶ms);
2655dd4f32aeSBjoern A. Zeeb if (ret)
2656dd4f32aeSBjoern A. Zeeb goto err;
2657dd4f32aeSBjoern A. Zeeb
2658dd4f32aeSBjoern A. Zeeb params.param = WMI_AP_PS_PEER_PARAM_MAX_SP;
2659dd4f32aeSBjoern A. Zeeb params.value = max_sp;
2660dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_send_set_ap_ps_param_cmd(ar, sta->addr, ¶ms);
2661dd4f32aeSBjoern A. Zeeb if (ret)
2662dd4f32aeSBjoern A. Zeeb goto err;
2663dd4f32aeSBjoern A. Zeeb
2664dd4f32aeSBjoern A. Zeeb /* TODO revisit during testing */
2665dd4f32aeSBjoern A. Zeeb params.param = WMI_AP_PS_PEER_PARAM_SIFS_RESP_FRMTYPE;
2666dd4f32aeSBjoern A. Zeeb params.value = DISABLE_SIFS_RESPONSE_TRIGGER;
2667dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_send_set_ap_ps_param_cmd(ar, sta->addr, ¶ms);
2668dd4f32aeSBjoern A. Zeeb if (ret)
2669dd4f32aeSBjoern A. Zeeb goto err;
2670dd4f32aeSBjoern A. Zeeb
2671dd4f32aeSBjoern A. Zeeb params.param = WMI_AP_PS_PEER_PARAM_SIFS_RESP_UAPSD;
2672dd4f32aeSBjoern A. Zeeb params.value = DISABLE_SIFS_RESPONSE_TRIGGER;
2673dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_send_set_ap_ps_param_cmd(ar, sta->addr, ¶ms);
2674dd4f32aeSBjoern A. Zeeb if (ret)
2675dd4f32aeSBjoern A. Zeeb goto err;
2676dd4f32aeSBjoern A. Zeeb
2677dd4f32aeSBjoern A. Zeeb return 0;
2678dd4f32aeSBjoern A. Zeeb
2679dd4f32aeSBjoern A. Zeeb err:
2680dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to set ap ps peer param %d for vdev %i: %d\n",
2681dd4f32aeSBjoern A. Zeeb params.param, arvif->vdev_id, ret);
2682dd4f32aeSBjoern A. Zeeb return ret;
2683dd4f32aeSBjoern A. Zeeb }
2684dd4f32aeSBjoern A. Zeeb
ath11k_mac_sta_has_ofdm_only(struct ieee80211_sta * sta)2685dd4f32aeSBjoern A. Zeeb static bool ath11k_mac_sta_has_ofdm_only(struct ieee80211_sta *sta)
2686dd4f32aeSBjoern A. Zeeb {
2687dd4f32aeSBjoern A. Zeeb return sta->deflink.supp_rates[NL80211_BAND_2GHZ] >>
2688dd4f32aeSBjoern A. Zeeb ATH11K_MAC_FIRST_OFDM_RATE_IDX;
2689dd4f32aeSBjoern A. Zeeb }
2690dd4f32aeSBjoern A. Zeeb
ath11k_mac_get_phymode_vht(struct ath11k * ar,struct ieee80211_sta * sta)2691dd4f32aeSBjoern A. Zeeb static enum wmi_phy_mode ath11k_mac_get_phymode_vht(struct ath11k *ar,
2692dd4f32aeSBjoern A. Zeeb struct ieee80211_sta *sta)
2693dd4f32aeSBjoern A. Zeeb {
2694dd4f32aeSBjoern A. Zeeb if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) {
2695dd4f32aeSBjoern A. Zeeb switch (sta->deflink.vht_cap.cap &
2696dd4f32aeSBjoern A. Zeeb IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) {
2697dd4f32aeSBjoern A. Zeeb case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ:
2698dd4f32aeSBjoern A. Zeeb return MODE_11AC_VHT160;
2699dd4f32aeSBjoern A. Zeeb case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ:
2700dd4f32aeSBjoern A. Zeeb return MODE_11AC_VHT80_80;
2701dd4f32aeSBjoern A. Zeeb default:
2702dd4f32aeSBjoern A. Zeeb /* not sure if this is a valid case? */
2703dd4f32aeSBjoern A. Zeeb return MODE_11AC_VHT160;
2704dd4f32aeSBjoern A. Zeeb }
2705dd4f32aeSBjoern A. Zeeb }
2706dd4f32aeSBjoern A. Zeeb
2707dd4f32aeSBjoern A. Zeeb if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80)
2708dd4f32aeSBjoern A. Zeeb return MODE_11AC_VHT80;
2709dd4f32aeSBjoern A. Zeeb
2710dd4f32aeSBjoern A. Zeeb if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
2711dd4f32aeSBjoern A. Zeeb return MODE_11AC_VHT40;
2712dd4f32aeSBjoern A. Zeeb
2713dd4f32aeSBjoern A. Zeeb if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_20)
2714dd4f32aeSBjoern A. Zeeb return MODE_11AC_VHT20;
2715dd4f32aeSBjoern A. Zeeb
2716dd4f32aeSBjoern A. Zeeb return MODE_UNKNOWN;
2717dd4f32aeSBjoern A. Zeeb }
2718dd4f32aeSBjoern A. Zeeb
ath11k_mac_get_phymode_he(struct ath11k * ar,struct ieee80211_sta * sta)2719dd4f32aeSBjoern A. Zeeb static enum wmi_phy_mode ath11k_mac_get_phymode_he(struct ath11k *ar,
2720dd4f32aeSBjoern A. Zeeb struct ieee80211_sta *sta)
2721dd4f32aeSBjoern A. Zeeb {
2722dd4f32aeSBjoern A. Zeeb if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) {
2723dd4f32aeSBjoern A. Zeeb if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[0] &
2724dd4f32aeSBjoern A. Zeeb IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G)
2725dd4f32aeSBjoern A. Zeeb return MODE_11AX_HE160;
2726dd4f32aeSBjoern A. Zeeb else if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[0] &
2727dd4f32aeSBjoern A. Zeeb IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)
2728dd4f32aeSBjoern A. Zeeb return MODE_11AX_HE80_80;
2729dd4f32aeSBjoern A. Zeeb /* not sure if this is a valid case? */
2730dd4f32aeSBjoern A. Zeeb return MODE_11AX_HE160;
2731dd4f32aeSBjoern A. Zeeb }
2732dd4f32aeSBjoern A. Zeeb
2733dd4f32aeSBjoern A. Zeeb if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80)
2734dd4f32aeSBjoern A. Zeeb return MODE_11AX_HE80;
2735dd4f32aeSBjoern A. Zeeb
2736dd4f32aeSBjoern A. Zeeb if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
2737dd4f32aeSBjoern A. Zeeb return MODE_11AX_HE40;
2738dd4f32aeSBjoern A. Zeeb
2739dd4f32aeSBjoern A. Zeeb if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_20)
2740dd4f32aeSBjoern A. Zeeb return MODE_11AX_HE20;
2741dd4f32aeSBjoern A. Zeeb
2742dd4f32aeSBjoern A. Zeeb return MODE_UNKNOWN;
2743dd4f32aeSBjoern A. Zeeb }
2744dd4f32aeSBjoern A. Zeeb
ath11k_peer_assoc_h_phymode(struct ath11k * ar,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct peer_assoc_params * arg)2745dd4f32aeSBjoern A. Zeeb static void ath11k_peer_assoc_h_phymode(struct ath11k *ar,
2746dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif,
2747dd4f32aeSBjoern A. Zeeb struct ieee80211_sta *sta,
2748dd4f32aeSBjoern A. Zeeb struct peer_assoc_params *arg)
2749dd4f32aeSBjoern A. Zeeb {
2750dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif = (void *)vif->drv_priv;
2751dd4f32aeSBjoern A. Zeeb struct cfg80211_chan_def def;
2752dd4f32aeSBjoern A. Zeeb enum nl80211_band band;
2753dd4f32aeSBjoern A. Zeeb const u8 *ht_mcs_mask;
2754dd4f32aeSBjoern A. Zeeb const u16 *vht_mcs_mask;
2755dd4f32aeSBjoern A. Zeeb const u16 *he_mcs_mask;
2756dd4f32aeSBjoern A. Zeeb enum wmi_phy_mode phymode = MODE_UNKNOWN;
2757dd4f32aeSBjoern A. Zeeb
2758dd4f32aeSBjoern A. Zeeb if (WARN_ON(ath11k_mac_vif_chan(vif, &def)))
2759dd4f32aeSBjoern A. Zeeb return;
2760dd4f32aeSBjoern A. Zeeb
2761dd4f32aeSBjoern A. Zeeb band = def.chan->band;
2762dd4f32aeSBjoern A. Zeeb ht_mcs_mask = arvif->bitrate_mask.control[band].ht_mcs;
2763dd4f32aeSBjoern A. Zeeb vht_mcs_mask = arvif->bitrate_mask.control[band].vht_mcs;
2764dd4f32aeSBjoern A. Zeeb he_mcs_mask = arvif->bitrate_mask.control[band].he_mcs;
2765dd4f32aeSBjoern A. Zeeb
2766dd4f32aeSBjoern A. Zeeb switch (band) {
2767dd4f32aeSBjoern A. Zeeb case NL80211_BAND_2GHZ:
2768dd4f32aeSBjoern A. Zeeb if (sta->deflink.he_cap.has_he &&
2769dd4f32aeSBjoern A. Zeeb !ath11k_peer_assoc_h_he_masked(he_mcs_mask)) {
2770dd4f32aeSBjoern A. Zeeb if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80)
2771dd4f32aeSBjoern A. Zeeb phymode = MODE_11AX_HE80_2G;
2772dd4f32aeSBjoern A. Zeeb else if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
2773dd4f32aeSBjoern A. Zeeb phymode = MODE_11AX_HE40_2G;
2774dd4f32aeSBjoern A. Zeeb else
2775dd4f32aeSBjoern A. Zeeb phymode = MODE_11AX_HE20_2G;
2776dd4f32aeSBjoern A. Zeeb } else if (sta->deflink.vht_cap.vht_supported &&
2777dd4f32aeSBjoern A. Zeeb !ath11k_peer_assoc_h_vht_masked(vht_mcs_mask)) {
2778dd4f32aeSBjoern A. Zeeb if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
2779dd4f32aeSBjoern A. Zeeb phymode = MODE_11AC_VHT40;
2780dd4f32aeSBjoern A. Zeeb else
2781dd4f32aeSBjoern A. Zeeb phymode = MODE_11AC_VHT20;
2782dd4f32aeSBjoern A. Zeeb } else if (sta->deflink.ht_cap.ht_supported &&
2783dd4f32aeSBjoern A. Zeeb !ath11k_peer_assoc_h_ht_masked(ht_mcs_mask)) {
2784dd4f32aeSBjoern A. Zeeb if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
2785dd4f32aeSBjoern A. Zeeb phymode = MODE_11NG_HT40;
2786dd4f32aeSBjoern A. Zeeb else
2787dd4f32aeSBjoern A. Zeeb phymode = MODE_11NG_HT20;
2788dd4f32aeSBjoern A. Zeeb } else if (ath11k_mac_sta_has_ofdm_only(sta)) {
2789dd4f32aeSBjoern A. Zeeb phymode = MODE_11G;
2790dd4f32aeSBjoern A. Zeeb } else {
2791dd4f32aeSBjoern A. Zeeb phymode = MODE_11B;
2792dd4f32aeSBjoern A. Zeeb }
2793dd4f32aeSBjoern A. Zeeb break;
2794dd4f32aeSBjoern A. Zeeb case NL80211_BAND_5GHZ:
2795dd4f32aeSBjoern A. Zeeb case NL80211_BAND_6GHZ:
2796dd4f32aeSBjoern A. Zeeb /* Check HE first */
2797dd4f32aeSBjoern A. Zeeb if (sta->deflink.he_cap.has_he &&
2798dd4f32aeSBjoern A. Zeeb !ath11k_peer_assoc_h_he_masked(he_mcs_mask)) {
2799dd4f32aeSBjoern A. Zeeb phymode = ath11k_mac_get_phymode_he(ar, sta);
2800dd4f32aeSBjoern A. Zeeb } else if (sta->deflink.vht_cap.vht_supported &&
2801dd4f32aeSBjoern A. Zeeb !ath11k_peer_assoc_h_vht_masked(vht_mcs_mask)) {
2802dd4f32aeSBjoern A. Zeeb phymode = ath11k_mac_get_phymode_vht(ar, sta);
2803dd4f32aeSBjoern A. Zeeb } else if (sta->deflink.ht_cap.ht_supported &&
2804dd4f32aeSBjoern A. Zeeb !ath11k_peer_assoc_h_ht_masked(ht_mcs_mask)) {
2805dd4f32aeSBjoern A. Zeeb if (sta->deflink.bandwidth >= IEEE80211_STA_RX_BW_40)
2806dd4f32aeSBjoern A. Zeeb phymode = MODE_11NA_HT40;
2807dd4f32aeSBjoern A. Zeeb else
2808dd4f32aeSBjoern A. Zeeb phymode = MODE_11NA_HT20;
2809dd4f32aeSBjoern A. Zeeb } else {
2810dd4f32aeSBjoern A. Zeeb phymode = MODE_11A;
2811dd4f32aeSBjoern A. Zeeb }
2812dd4f32aeSBjoern A. Zeeb break;
2813dd4f32aeSBjoern A. Zeeb default:
2814dd4f32aeSBjoern A. Zeeb break;
2815dd4f32aeSBjoern A. Zeeb }
2816dd4f32aeSBjoern A. Zeeb
281728348caeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "peer %pM phymode %s\n",
2818dd4f32aeSBjoern A. Zeeb sta->addr, ath11k_wmi_phymode_str(phymode));
2819dd4f32aeSBjoern A. Zeeb
2820dd4f32aeSBjoern A. Zeeb arg->peer_phymode = phymode;
2821dd4f32aeSBjoern A. Zeeb WARN_ON(phymode == MODE_UNKNOWN);
2822dd4f32aeSBjoern A. Zeeb }
2823dd4f32aeSBjoern A. Zeeb
ath11k_peer_assoc_prepare(struct ath11k * ar,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct peer_assoc_params * arg,bool reassoc)2824dd4f32aeSBjoern A. Zeeb static void ath11k_peer_assoc_prepare(struct ath11k *ar,
2825dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif,
2826dd4f32aeSBjoern A. Zeeb struct ieee80211_sta *sta,
2827dd4f32aeSBjoern A. Zeeb struct peer_assoc_params *arg,
2828dd4f32aeSBjoern A. Zeeb bool reassoc)
2829dd4f32aeSBjoern A. Zeeb {
2830dd4f32aeSBjoern A. Zeeb struct ath11k_sta *arsta;
2831dd4f32aeSBjoern A. Zeeb
2832dd4f32aeSBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
2833dd4f32aeSBjoern A. Zeeb
2834dd4f32aeSBjoern A. Zeeb arsta = (struct ath11k_sta *)sta->drv_priv;
2835dd4f32aeSBjoern A. Zeeb
2836dd4f32aeSBjoern A. Zeeb memset(arg, 0, sizeof(*arg));
2837dd4f32aeSBjoern A. Zeeb
2838dd4f32aeSBjoern A. Zeeb reinit_completion(&ar->peer_assoc_done);
2839dd4f32aeSBjoern A. Zeeb
2840dd4f32aeSBjoern A. Zeeb arg->peer_new_assoc = !reassoc;
2841dd4f32aeSBjoern A. Zeeb ath11k_peer_assoc_h_basic(ar, vif, sta, arg);
2842dd4f32aeSBjoern A. Zeeb ath11k_peer_assoc_h_crypto(ar, vif, sta, arg);
2843dd4f32aeSBjoern A. Zeeb ath11k_peer_assoc_h_rates(ar, vif, sta, arg);
2844dd4f32aeSBjoern A. Zeeb ath11k_peer_assoc_h_phymode(ar, vif, sta, arg);
2845dd4f32aeSBjoern A. Zeeb ath11k_peer_assoc_h_ht(ar, vif, sta, arg);
2846dd4f32aeSBjoern A. Zeeb ath11k_peer_assoc_h_vht(ar, vif, sta, arg);
2847dd4f32aeSBjoern A. Zeeb ath11k_peer_assoc_h_he(ar, vif, sta, arg);
2848dd4f32aeSBjoern A. Zeeb ath11k_peer_assoc_h_he_6ghz(ar, vif, sta, arg);
2849dd4f32aeSBjoern A. Zeeb ath11k_peer_assoc_h_qos(ar, vif, sta, arg);
2850dd4f32aeSBjoern A. Zeeb ath11k_peer_assoc_h_smps(sta, arg);
2851dd4f32aeSBjoern A. Zeeb
2852dd4f32aeSBjoern A. Zeeb arsta->peer_nss = arg->peer_nss;
2853dd4f32aeSBjoern A. Zeeb
2854dd4f32aeSBjoern A. Zeeb /* TODO: amsdu_disable req? */
2855dd4f32aeSBjoern A. Zeeb }
2856dd4f32aeSBjoern A. Zeeb
ath11k_setup_peer_smps(struct ath11k * ar,struct ath11k_vif * arvif,const u8 * addr,const struct ieee80211_sta_ht_cap * ht_cap,u16 he_6ghz_capa)2857dd4f32aeSBjoern A. Zeeb static int ath11k_setup_peer_smps(struct ath11k *ar, struct ath11k_vif *arvif,
2858dd4f32aeSBjoern A. Zeeb const u8 *addr,
2859dd4f32aeSBjoern A. Zeeb const struct ieee80211_sta_ht_cap *ht_cap,
2860dd4f32aeSBjoern A. Zeeb u16 he_6ghz_capa)
2861dd4f32aeSBjoern A. Zeeb {
2862dd4f32aeSBjoern A. Zeeb int smps;
2863dd4f32aeSBjoern A. Zeeb
2864dd4f32aeSBjoern A. Zeeb if (!ht_cap->ht_supported && !he_6ghz_capa)
2865dd4f32aeSBjoern A. Zeeb return 0;
2866dd4f32aeSBjoern A. Zeeb
2867dd4f32aeSBjoern A. Zeeb if (ht_cap->ht_supported) {
2868dd4f32aeSBjoern A. Zeeb smps = ht_cap->cap & IEEE80211_HT_CAP_SM_PS;
2869dd4f32aeSBjoern A. Zeeb smps >>= IEEE80211_HT_CAP_SM_PS_SHIFT;
2870dd4f32aeSBjoern A. Zeeb } else {
2871dd4f32aeSBjoern A. Zeeb smps = FIELD_GET(IEEE80211_HE_6GHZ_CAP_SM_PS, he_6ghz_capa);
2872dd4f32aeSBjoern A. Zeeb }
2873dd4f32aeSBjoern A. Zeeb
2874dd4f32aeSBjoern A. Zeeb if (smps >= ARRAY_SIZE(ath11k_smps_map))
2875dd4f32aeSBjoern A. Zeeb return -EINVAL;
2876dd4f32aeSBjoern A. Zeeb
2877dd4f32aeSBjoern A. Zeeb return ath11k_wmi_set_peer_param(ar, addr, arvif->vdev_id,
2878dd4f32aeSBjoern A. Zeeb WMI_PEER_MIMO_PS_STATE,
2879dd4f32aeSBjoern A. Zeeb ath11k_smps_map[smps]);
2880dd4f32aeSBjoern A. Zeeb }
2881dd4f32aeSBjoern A. Zeeb
ath11k_mac_set_he_txbf_conf(struct ath11k_vif * arvif)288228348caeSBjoern A. Zeeb static bool ath11k_mac_set_he_txbf_conf(struct ath11k_vif *arvif)
288328348caeSBjoern A. Zeeb {
288428348caeSBjoern A. Zeeb struct ath11k *ar = arvif->ar;
288528348caeSBjoern A. Zeeb u32 param, value;
288628348caeSBjoern A. Zeeb int ret;
288728348caeSBjoern A. Zeeb
288828348caeSBjoern A. Zeeb if (!arvif->vif->bss_conf.he_support)
288928348caeSBjoern A. Zeeb return true;
289028348caeSBjoern A. Zeeb
289128348caeSBjoern A. Zeeb param = WMI_VDEV_PARAM_SET_HEMU_MODE;
289228348caeSBjoern A. Zeeb value = 0;
289328348caeSBjoern A. Zeeb if (arvif->vif->bss_conf.he_su_beamformer) {
289428348caeSBjoern A. Zeeb value |= FIELD_PREP(HE_MODE_SU_TX_BFER, HE_SU_BFER_ENABLE);
289528348caeSBjoern A. Zeeb if (arvif->vif->bss_conf.he_mu_beamformer &&
289628348caeSBjoern A. Zeeb arvif->vdev_type == WMI_VDEV_TYPE_AP)
289728348caeSBjoern A. Zeeb value |= FIELD_PREP(HE_MODE_MU_TX_BFER, HE_MU_BFER_ENABLE);
289828348caeSBjoern A. Zeeb }
289928348caeSBjoern A. Zeeb
290028348caeSBjoern A. Zeeb if (arvif->vif->type != NL80211_IFTYPE_MESH_POINT) {
290128348caeSBjoern A. Zeeb value |= FIELD_PREP(HE_MODE_DL_OFDMA, HE_DL_MUOFDMA_ENABLE) |
290228348caeSBjoern A. Zeeb FIELD_PREP(HE_MODE_UL_OFDMA, HE_UL_MUOFDMA_ENABLE);
290328348caeSBjoern A. Zeeb
290428348caeSBjoern A. Zeeb if (arvif->vif->bss_conf.he_full_ul_mumimo)
290528348caeSBjoern A. Zeeb value |= FIELD_PREP(HE_MODE_UL_MUMIMO, HE_UL_MUMIMO_ENABLE);
290628348caeSBjoern A. Zeeb
290728348caeSBjoern A. Zeeb if (arvif->vif->bss_conf.he_su_beamformee)
290828348caeSBjoern A. Zeeb value |= FIELD_PREP(HE_MODE_SU_TX_BFEE, HE_SU_BFEE_ENABLE);
290928348caeSBjoern A. Zeeb }
291028348caeSBjoern A. Zeeb
291128348caeSBjoern A. Zeeb ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, param, value);
291228348caeSBjoern A. Zeeb if (ret) {
291328348caeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to set vdev %d HE MU mode: %d\n",
291428348caeSBjoern A. Zeeb arvif->vdev_id, ret);
291528348caeSBjoern A. Zeeb return false;
291628348caeSBjoern A. Zeeb }
291728348caeSBjoern A. Zeeb
291828348caeSBjoern A. Zeeb param = WMI_VDEV_PARAM_SET_HE_SOUNDING_MODE;
291928348caeSBjoern A. Zeeb value = FIELD_PREP(HE_VHT_SOUNDING_MODE, HE_VHT_SOUNDING_MODE_ENABLE) |
292028348caeSBjoern A. Zeeb FIELD_PREP(HE_TRIG_NONTRIG_SOUNDING_MODE,
292128348caeSBjoern A. Zeeb HE_TRIG_NONTRIG_SOUNDING_MODE_ENABLE);
292228348caeSBjoern A. Zeeb ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
292328348caeSBjoern A. Zeeb param, value);
292428348caeSBjoern A. Zeeb if (ret) {
292528348caeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to set vdev %d sounding mode: %d\n",
292628348caeSBjoern A. Zeeb arvif->vdev_id, ret);
292728348caeSBjoern A. Zeeb return false;
292828348caeSBjoern A. Zeeb }
292928348caeSBjoern A. Zeeb return true;
293028348caeSBjoern A. Zeeb }
293128348caeSBjoern A. Zeeb
ath11k_mac_vif_recalc_sta_he_txbf(struct ath11k * ar,struct ieee80211_vif * vif,struct ieee80211_sta_he_cap * he_cap)293228348caeSBjoern A. Zeeb static bool ath11k_mac_vif_recalc_sta_he_txbf(struct ath11k *ar,
293328348caeSBjoern A. Zeeb struct ieee80211_vif *vif,
293428348caeSBjoern A. Zeeb struct ieee80211_sta_he_cap *he_cap)
293528348caeSBjoern A. Zeeb {
293628348caeSBjoern A. Zeeb struct ath11k_vif *arvif = (void *)vif->drv_priv;
293728348caeSBjoern A. Zeeb struct ieee80211_he_cap_elem he_cap_elem = {0};
293828348caeSBjoern A. Zeeb struct ieee80211_sta_he_cap *cap_band = NULL;
293928348caeSBjoern A. Zeeb struct cfg80211_chan_def def;
294028348caeSBjoern A. Zeeb u32 param = WMI_VDEV_PARAM_SET_HEMU_MODE;
294128348caeSBjoern A. Zeeb u32 hemode = 0;
294228348caeSBjoern A. Zeeb int ret;
294328348caeSBjoern A. Zeeb
294428348caeSBjoern A. Zeeb if (!vif->bss_conf.he_support)
294528348caeSBjoern A. Zeeb return true;
294628348caeSBjoern A. Zeeb
294728348caeSBjoern A. Zeeb if (vif->type != NL80211_IFTYPE_STATION)
294828348caeSBjoern A. Zeeb return false;
294928348caeSBjoern A. Zeeb
295028348caeSBjoern A. Zeeb if (WARN_ON(ath11k_mac_vif_chan(vif, &def)))
295128348caeSBjoern A. Zeeb return false;
295228348caeSBjoern A. Zeeb
295328348caeSBjoern A. Zeeb if (def.chan->band == NL80211_BAND_2GHZ)
295428348caeSBjoern A. Zeeb cap_band = &ar->mac.iftype[NL80211_BAND_2GHZ][vif->type].he_cap;
295528348caeSBjoern A. Zeeb else
295628348caeSBjoern A. Zeeb cap_band = &ar->mac.iftype[NL80211_BAND_5GHZ][vif->type].he_cap;
295728348caeSBjoern A. Zeeb
295828348caeSBjoern A. Zeeb memcpy(&he_cap_elem, &cap_band->he_cap_elem, sizeof(he_cap_elem));
295928348caeSBjoern A. Zeeb
296028348caeSBjoern A. Zeeb if (HECAP_PHY_SUBFME_GET(he_cap_elem.phy_cap_info)) {
296128348caeSBjoern A. Zeeb if (HECAP_PHY_SUBFMR_GET(he_cap->he_cap_elem.phy_cap_info))
296228348caeSBjoern A. Zeeb hemode |= FIELD_PREP(HE_MODE_SU_TX_BFEE, HE_SU_BFEE_ENABLE);
296328348caeSBjoern A. Zeeb if (HECAP_PHY_MUBFMR_GET(he_cap->he_cap_elem.phy_cap_info))
296428348caeSBjoern A. Zeeb hemode |= FIELD_PREP(HE_MODE_MU_TX_BFEE, HE_MU_BFEE_ENABLE);
296528348caeSBjoern A. Zeeb }
296628348caeSBjoern A. Zeeb
296728348caeSBjoern A. Zeeb if (vif->type != NL80211_IFTYPE_MESH_POINT) {
296828348caeSBjoern A. Zeeb hemode |= FIELD_PREP(HE_MODE_DL_OFDMA, HE_DL_MUOFDMA_ENABLE) |
296928348caeSBjoern A. Zeeb FIELD_PREP(HE_MODE_UL_OFDMA, HE_UL_MUOFDMA_ENABLE);
297028348caeSBjoern A. Zeeb
297128348caeSBjoern A. Zeeb if (HECAP_PHY_ULMUMIMO_GET(he_cap_elem.phy_cap_info))
297228348caeSBjoern A. Zeeb if (HECAP_PHY_ULMUMIMO_GET(he_cap->he_cap_elem.phy_cap_info))
297328348caeSBjoern A. Zeeb hemode |= FIELD_PREP(HE_MODE_UL_MUMIMO,
297428348caeSBjoern A. Zeeb HE_UL_MUMIMO_ENABLE);
297528348caeSBjoern A. Zeeb
297628348caeSBjoern A. Zeeb if (FIELD_GET(HE_MODE_MU_TX_BFEE, hemode))
297728348caeSBjoern A. Zeeb hemode |= FIELD_PREP(HE_MODE_SU_TX_BFEE, HE_SU_BFEE_ENABLE);
297828348caeSBjoern A. Zeeb
297928348caeSBjoern A. Zeeb if (FIELD_GET(HE_MODE_MU_TX_BFER, hemode))
298028348caeSBjoern A. Zeeb hemode |= FIELD_PREP(HE_MODE_SU_TX_BFER, HE_SU_BFER_ENABLE);
298128348caeSBjoern A. Zeeb }
298228348caeSBjoern A. Zeeb
298328348caeSBjoern A. Zeeb ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, param, hemode);
298428348caeSBjoern A. Zeeb if (ret) {
298528348caeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to submit vdev param txbf 0x%x: %d\n",
298628348caeSBjoern A. Zeeb hemode, ret);
298728348caeSBjoern A. Zeeb return false;
298828348caeSBjoern A. Zeeb }
298928348caeSBjoern A. Zeeb
299028348caeSBjoern A. Zeeb return true;
299128348caeSBjoern A. Zeeb }
299228348caeSBjoern A. Zeeb
ath11k_bss_assoc(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_bss_conf * bss_conf)2993dd4f32aeSBjoern A. Zeeb static void ath11k_bss_assoc(struct ieee80211_hw *hw,
2994dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif,
2995dd4f32aeSBjoern A. Zeeb struct ieee80211_bss_conf *bss_conf)
2996dd4f32aeSBjoern A. Zeeb {
2997dd4f32aeSBjoern A. Zeeb struct ath11k *ar = hw->priv;
2998dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif = (void *)vif->drv_priv;
2999dd4f32aeSBjoern A. Zeeb struct peer_assoc_params peer_arg;
3000dd4f32aeSBjoern A. Zeeb struct ieee80211_sta *ap_sta;
3001dd4f32aeSBjoern A. Zeeb struct ath11k_peer *peer;
3002dd4f32aeSBjoern A. Zeeb bool is_auth = false;
300328348caeSBjoern A. Zeeb struct ieee80211_sta_he_cap he_cap;
3004dd4f32aeSBjoern A. Zeeb int ret;
3005dd4f32aeSBjoern A. Zeeb
3006dd4f32aeSBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
3007dd4f32aeSBjoern A. Zeeb
300828348caeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev %i assoc bssid %pM aid %d\n",
3009dd4f32aeSBjoern A. Zeeb arvif->vdev_id, arvif->bssid, arvif->aid);
3010dd4f32aeSBjoern A. Zeeb
3011dd4f32aeSBjoern A. Zeeb rcu_read_lock();
3012dd4f32aeSBjoern A. Zeeb
3013dd4f32aeSBjoern A. Zeeb ap_sta = ieee80211_find_sta(vif, bss_conf->bssid);
3014dd4f32aeSBjoern A. Zeeb if (!ap_sta) {
3015dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to find station entry for bss %pM vdev %i\n",
3016dd4f32aeSBjoern A. Zeeb bss_conf->bssid, arvif->vdev_id);
3017dd4f32aeSBjoern A. Zeeb rcu_read_unlock();
3018dd4f32aeSBjoern A. Zeeb return;
3019dd4f32aeSBjoern A. Zeeb }
3020dd4f32aeSBjoern A. Zeeb
302128348caeSBjoern A. Zeeb /* he_cap here is updated at assoc success for sta mode only */
302228348caeSBjoern A. Zeeb he_cap = ap_sta->deflink.he_cap;
302328348caeSBjoern A. Zeeb
3024dd4f32aeSBjoern A. Zeeb ath11k_peer_assoc_prepare(ar, vif, ap_sta, &peer_arg, false);
3025dd4f32aeSBjoern A. Zeeb
3026dd4f32aeSBjoern A. Zeeb rcu_read_unlock();
3027dd4f32aeSBjoern A. Zeeb
3028dd4f32aeSBjoern A. Zeeb peer_arg.is_assoc = true;
3029dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_send_peer_assoc_cmd(ar, &peer_arg);
3030dd4f32aeSBjoern A. Zeeb if (ret) {
3031dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to run peer assoc for %pM vdev %i: %d\n",
3032dd4f32aeSBjoern A. Zeeb bss_conf->bssid, arvif->vdev_id, ret);
3033dd4f32aeSBjoern A. Zeeb return;
3034dd4f32aeSBjoern A. Zeeb }
3035dd4f32aeSBjoern A. Zeeb
3036dd4f32aeSBjoern A. Zeeb if (!wait_for_completion_timeout(&ar->peer_assoc_done, 1 * HZ)) {
3037dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to get peer assoc conf event for %pM vdev %i\n",
3038dd4f32aeSBjoern A. Zeeb bss_conf->bssid, arvif->vdev_id);
3039dd4f32aeSBjoern A. Zeeb return;
3040dd4f32aeSBjoern A. Zeeb }
3041dd4f32aeSBjoern A. Zeeb
3042dd4f32aeSBjoern A. Zeeb ret = ath11k_setup_peer_smps(ar, arvif, bss_conf->bssid,
3043dd4f32aeSBjoern A. Zeeb &ap_sta->deflink.ht_cap,
3044dd4f32aeSBjoern A. Zeeb le16_to_cpu(ap_sta->deflink.he_6ghz_capa.capa));
3045dd4f32aeSBjoern A. Zeeb if (ret) {
3046dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to setup peer SMPS for vdev %d: %d\n",
3047dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ret);
3048dd4f32aeSBjoern A. Zeeb return;
3049dd4f32aeSBjoern A. Zeeb }
3050dd4f32aeSBjoern A. Zeeb
305128348caeSBjoern A. Zeeb if (!ath11k_mac_vif_recalc_sta_he_txbf(ar, vif, &he_cap)) {
305228348caeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to recalc he txbf for vdev %i on bss %pM\n",
305328348caeSBjoern A. Zeeb arvif->vdev_id, bss_conf->bssid);
305428348caeSBjoern A. Zeeb return;
305528348caeSBjoern A. Zeeb }
305628348caeSBjoern A. Zeeb
3057dd4f32aeSBjoern A. Zeeb WARN_ON(arvif->is_up);
3058dd4f32aeSBjoern A. Zeeb
305928348caeSBjoern A. Zeeb arvif->aid = vif->cfg.aid;
3060dd4f32aeSBjoern A. Zeeb ether_addr_copy(arvif->bssid, bss_conf->bssid);
3061dd4f32aeSBjoern A. Zeeb
306228348caeSBjoern A. Zeeb ret = ath11k_wmi_vdev_up(ar, arvif->vdev_id, arvif->aid, arvif->bssid,
306328348caeSBjoern A. Zeeb NULL, 0, 0);
3064dd4f32aeSBjoern A. Zeeb if (ret) {
3065dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to set vdev %d up: %d\n",
3066dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ret);
3067dd4f32aeSBjoern A. Zeeb return;
3068dd4f32aeSBjoern A. Zeeb }
3069dd4f32aeSBjoern A. Zeeb
3070dd4f32aeSBjoern A. Zeeb arvif->is_up = true;
307128348caeSBjoern A. Zeeb arvif->rekey_data.enable_offload = false;
3072dd4f32aeSBjoern A. Zeeb
3073dd4f32aeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
307428348caeSBjoern A. Zeeb "vdev %d up (associated) bssid %pM aid %d\n",
307528348caeSBjoern A. Zeeb arvif->vdev_id, bss_conf->bssid, vif->cfg.aid);
3076dd4f32aeSBjoern A. Zeeb
3077dd4f32aeSBjoern A. Zeeb spin_lock_bh(&ar->ab->base_lock);
3078dd4f32aeSBjoern A. Zeeb
3079dd4f32aeSBjoern A. Zeeb peer = ath11k_peer_find(ar->ab, arvif->vdev_id, arvif->bssid);
3080dd4f32aeSBjoern A. Zeeb if (peer && peer->is_authorized)
3081dd4f32aeSBjoern A. Zeeb is_auth = true;
3082dd4f32aeSBjoern A. Zeeb
3083dd4f32aeSBjoern A. Zeeb spin_unlock_bh(&ar->ab->base_lock);
3084dd4f32aeSBjoern A. Zeeb
3085dd4f32aeSBjoern A. Zeeb if (is_auth) {
3086dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_set_peer_param(ar, arvif->bssid,
3087dd4f32aeSBjoern A. Zeeb arvif->vdev_id,
3088dd4f32aeSBjoern A. Zeeb WMI_PEER_AUTHORIZE,
3089dd4f32aeSBjoern A. Zeeb 1);
3090dd4f32aeSBjoern A. Zeeb if (ret)
3091dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "Unable to authorize BSS peer: %d\n", ret);
3092dd4f32aeSBjoern A. Zeeb }
3093dd4f32aeSBjoern A. Zeeb
3094dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_send_obss_spr_cmd(ar, arvif->vdev_id,
3095dd4f32aeSBjoern A. Zeeb &bss_conf->he_obss_pd);
3096dd4f32aeSBjoern A. Zeeb if (ret)
3097dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to set vdev %i OBSS PD parameters: %d\n",
3098dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ret);
3099dd4f32aeSBjoern A. Zeeb
3100dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
3101dd4f32aeSBjoern A. Zeeb WMI_VDEV_PARAM_DTIM_POLICY,
3102dd4f32aeSBjoern A. Zeeb WMI_DTIM_POLICY_STICK);
3103dd4f32aeSBjoern A. Zeeb if (ret)
3104dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to set vdev %d dtim policy: %d\n",
3105dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ret);
3106dd4f32aeSBjoern A. Zeeb
3107dd4f32aeSBjoern A. Zeeb ath11k_mac_11d_scan_stop_all(ar->ab);
3108dd4f32aeSBjoern A. Zeeb }
3109dd4f32aeSBjoern A. Zeeb
ath11k_bss_disassoc(struct ieee80211_hw * hw,struct ieee80211_vif * vif)3110dd4f32aeSBjoern A. Zeeb static void ath11k_bss_disassoc(struct ieee80211_hw *hw,
3111dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif)
3112dd4f32aeSBjoern A. Zeeb {
3113dd4f32aeSBjoern A. Zeeb struct ath11k *ar = hw->priv;
3114dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif = (void *)vif->drv_priv;
3115dd4f32aeSBjoern A. Zeeb int ret;
3116dd4f32aeSBjoern A. Zeeb
3117dd4f32aeSBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
3118dd4f32aeSBjoern A. Zeeb
311928348caeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev %i disassoc bssid %pM\n",
3120dd4f32aeSBjoern A. Zeeb arvif->vdev_id, arvif->bssid);
3121dd4f32aeSBjoern A. Zeeb
3122dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_vdev_down(ar, arvif->vdev_id);
3123dd4f32aeSBjoern A. Zeeb if (ret)
3124dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to down vdev %i: %d\n",
3125dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ret);
3126dd4f32aeSBjoern A. Zeeb
3127dd4f32aeSBjoern A. Zeeb arvif->is_up = false;
3128dd4f32aeSBjoern A. Zeeb
312928348caeSBjoern A. Zeeb memset(&arvif->rekey_data, 0, sizeof(arvif->rekey_data));
313028348caeSBjoern A. Zeeb
3131dd4f32aeSBjoern A. Zeeb cancel_delayed_work_sync(&arvif->connection_loss_work);
3132dd4f32aeSBjoern A. Zeeb }
3133dd4f32aeSBjoern A. Zeeb
ath11k_mac_get_rate_hw_value(int bitrate)3134dd4f32aeSBjoern A. Zeeb static u32 ath11k_mac_get_rate_hw_value(int bitrate)
3135dd4f32aeSBjoern A. Zeeb {
3136dd4f32aeSBjoern A. Zeeb u32 preamble;
3137dd4f32aeSBjoern A. Zeeb u16 hw_value;
3138dd4f32aeSBjoern A. Zeeb int rate;
3139dd4f32aeSBjoern A. Zeeb size_t i;
3140dd4f32aeSBjoern A. Zeeb
3141dd4f32aeSBjoern A. Zeeb if (ath11k_mac_bitrate_is_cck(bitrate))
3142dd4f32aeSBjoern A. Zeeb preamble = WMI_RATE_PREAMBLE_CCK;
3143dd4f32aeSBjoern A. Zeeb else
3144dd4f32aeSBjoern A. Zeeb preamble = WMI_RATE_PREAMBLE_OFDM;
3145dd4f32aeSBjoern A. Zeeb
3146dd4f32aeSBjoern A. Zeeb for (i = 0; i < ARRAY_SIZE(ath11k_legacy_rates); i++) {
3147dd4f32aeSBjoern A. Zeeb if (ath11k_legacy_rates[i].bitrate != bitrate)
3148dd4f32aeSBjoern A. Zeeb continue;
3149dd4f32aeSBjoern A. Zeeb
3150dd4f32aeSBjoern A. Zeeb hw_value = ath11k_legacy_rates[i].hw_value;
3151dd4f32aeSBjoern A. Zeeb rate = ATH11K_HW_RATE_CODE(hw_value, 0, preamble);
3152dd4f32aeSBjoern A. Zeeb
3153dd4f32aeSBjoern A. Zeeb return rate;
3154dd4f32aeSBjoern A. Zeeb }
3155dd4f32aeSBjoern A. Zeeb
3156dd4f32aeSBjoern A. Zeeb return -EINVAL;
3157dd4f32aeSBjoern A. Zeeb }
3158dd4f32aeSBjoern A. Zeeb
ath11k_recalculate_mgmt_rate(struct ath11k * ar,struct ieee80211_vif * vif,struct cfg80211_chan_def * def)3159dd4f32aeSBjoern A. Zeeb static void ath11k_recalculate_mgmt_rate(struct ath11k *ar,
3160dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif,
3161dd4f32aeSBjoern A. Zeeb struct cfg80211_chan_def *def)
3162dd4f32aeSBjoern A. Zeeb {
3163dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif = (void *)vif->drv_priv;
3164dd4f32aeSBjoern A. Zeeb const struct ieee80211_supported_band *sband;
3165dd4f32aeSBjoern A. Zeeb u8 basic_rate_idx;
3166dd4f32aeSBjoern A. Zeeb int hw_rate_code;
3167dd4f32aeSBjoern A. Zeeb u32 vdev_param;
3168dd4f32aeSBjoern A. Zeeb u16 bitrate;
3169dd4f32aeSBjoern A. Zeeb int ret;
3170dd4f32aeSBjoern A. Zeeb
3171dd4f32aeSBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
3172dd4f32aeSBjoern A. Zeeb
3173dd4f32aeSBjoern A. Zeeb sband = ar->hw->wiphy->bands[def->chan->band];
3174dd4f32aeSBjoern A. Zeeb basic_rate_idx = ffs(vif->bss_conf.basic_rates) - 1;
3175dd4f32aeSBjoern A. Zeeb bitrate = sband->bitrates[basic_rate_idx].bitrate;
3176dd4f32aeSBjoern A. Zeeb
3177dd4f32aeSBjoern A. Zeeb hw_rate_code = ath11k_mac_get_rate_hw_value(bitrate);
3178dd4f32aeSBjoern A. Zeeb if (hw_rate_code < 0) {
3179dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "bitrate not supported %d\n", bitrate);
3180dd4f32aeSBjoern A. Zeeb return;
3181dd4f32aeSBjoern A. Zeeb }
3182dd4f32aeSBjoern A. Zeeb
3183dd4f32aeSBjoern A. Zeeb vdev_param = WMI_VDEV_PARAM_MGMT_RATE;
3184dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, vdev_param,
3185dd4f32aeSBjoern A. Zeeb hw_rate_code);
3186dd4f32aeSBjoern A. Zeeb if (ret)
3187dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to set mgmt tx rate %d\n", ret);
3188dd4f32aeSBjoern A. Zeeb
3189dd4f32aeSBjoern A. Zeeb /* For WCN6855, firmware will clear this param when vdev starts, hence
3190dd4f32aeSBjoern A. Zeeb * cache it here so that we can reconfigure it once vdev starts.
3191dd4f32aeSBjoern A. Zeeb */
3192dd4f32aeSBjoern A. Zeeb ar->hw_rate_code = hw_rate_code;
3193dd4f32aeSBjoern A. Zeeb
3194dd4f32aeSBjoern A. Zeeb vdev_param = WMI_VDEV_PARAM_BEACON_RATE;
3195dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, vdev_param,
3196dd4f32aeSBjoern A. Zeeb hw_rate_code);
3197dd4f32aeSBjoern A. Zeeb if (ret)
3198dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to set beacon tx rate %d\n", ret);
3199dd4f32aeSBjoern A. Zeeb }
3200dd4f32aeSBjoern A. Zeeb
ath11k_mac_fils_discovery(struct ath11k_vif * arvif,struct ieee80211_bss_conf * info)3201dd4f32aeSBjoern A. Zeeb static int ath11k_mac_fils_discovery(struct ath11k_vif *arvif,
3202dd4f32aeSBjoern A. Zeeb struct ieee80211_bss_conf *info)
3203dd4f32aeSBjoern A. Zeeb {
3204dd4f32aeSBjoern A. Zeeb struct ath11k *ar = arvif->ar;
3205dd4f32aeSBjoern A. Zeeb struct sk_buff *tmpl;
3206dd4f32aeSBjoern A. Zeeb int ret;
3207dd4f32aeSBjoern A. Zeeb u32 interval;
3208dd4f32aeSBjoern A. Zeeb bool unsol_bcast_probe_resp_enabled = false;
3209dd4f32aeSBjoern A. Zeeb
3210dd4f32aeSBjoern A. Zeeb if (info->fils_discovery.max_interval) {
3211dd4f32aeSBjoern A. Zeeb interval = info->fils_discovery.max_interval;
3212dd4f32aeSBjoern A. Zeeb
3213dd4f32aeSBjoern A. Zeeb tmpl = ieee80211_get_fils_discovery_tmpl(ar->hw, arvif->vif);
3214dd4f32aeSBjoern A. Zeeb if (tmpl)
3215dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_fils_discovery_tmpl(ar, arvif->vdev_id,
3216dd4f32aeSBjoern A. Zeeb tmpl);
3217dd4f32aeSBjoern A. Zeeb } else if (info->unsol_bcast_probe_resp_interval) {
3218dd4f32aeSBjoern A. Zeeb unsol_bcast_probe_resp_enabled = 1;
3219dd4f32aeSBjoern A. Zeeb interval = info->unsol_bcast_probe_resp_interval;
3220dd4f32aeSBjoern A. Zeeb
3221dd4f32aeSBjoern A. Zeeb tmpl = ieee80211_get_unsol_bcast_probe_resp_tmpl(ar->hw,
3222dd4f32aeSBjoern A. Zeeb arvif->vif);
3223dd4f32aeSBjoern A. Zeeb if (tmpl)
3224dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_probe_resp_tmpl(ar, arvif->vdev_id,
3225dd4f32aeSBjoern A. Zeeb tmpl);
3226dd4f32aeSBjoern A. Zeeb } else { /* Disable */
3227dd4f32aeSBjoern A. Zeeb return ath11k_wmi_fils_discovery(ar, arvif->vdev_id, 0, false);
3228dd4f32aeSBjoern A. Zeeb }
3229dd4f32aeSBjoern A. Zeeb
3230dd4f32aeSBjoern A. Zeeb if (!tmpl) {
3231dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab,
3232dd4f32aeSBjoern A. Zeeb "mac vdev %i failed to retrieve %s template\n",
3233dd4f32aeSBjoern A. Zeeb arvif->vdev_id, (unsol_bcast_probe_resp_enabled ?
3234dd4f32aeSBjoern A. Zeeb "unsolicited broadcast probe response" :
3235dd4f32aeSBjoern A. Zeeb "FILS discovery"));
3236dd4f32aeSBjoern A. Zeeb return -EPERM;
3237dd4f32aeSBjoern A. Zeeb }
3238dd4f32aeSBjoern A. Zeeb kfree_skb(tmpl);
3239dd4f32aeSBjoern A. Zeeb
3240dd4f32aeSBjoern A. Zeeb if (!ret)
3241dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_fils_discovery(ar, arvif->vdev_id, interval,
3242dd4f32aeSBjoern A. Zeeb unsol_bcast_probe_resp_enabled);
3243dd4f32aeSBjoern A. Zeeb
3244dd4f32aeSBjoern A. Zeeb return ret;
3245dd4f32aeSBjoern A. Zeeb }
3246dd4f32aeSBjoern A. Zeeb
ath11k_mac_config_obss_pd(struct ath11k * ar,struct ieee80211_he_obss_pd * he_obss_pd)3247dd4f32aeSBjoern A. Zeeb static int ath11k_mac_config_obss_pd(struct ath11k *ar,
3248dd4f32aeSBjoern A. Zeeb struct ieee80211_he_obss_pd *he_obss_pd)
3249dd4f32aeSBjoern A. Zeeb {
3250dd4f32aeSBjoern A. Zeeb u32 bitmap[2], param_id, param_val, pdev_id;
3251dd4f32aeSBjoern A. Zeeb int ret;
3252dd4f32aeSBjoern A. Zeeb s8 non_srg_th = 0, srg_th = 0;
3253dd4f32aeSBjoern A. Zeeb
3254dd4f32aeSBjoern A. Zeeb pdev_id = ar->pdev->pdev_id;
3255dd4f32aeSBjoern A. Zeeb
3256dd4f32aeSBjoern A. Zeeb /* Set and enable SRG/non-SRG OBSS PD Threshold */
3257dd4f32aeSBjoern A. Zeeb param_id = WMI_PDEV_PARAM_SET_CMD_OBSS_PD_THRESHOLD;
3258dd4f32aeSBjoern A. Zeeb if (test_bit(ATH11K_FLAG_MONITOR_STARTED, &ar->monitor_flags)) {
3259dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_pdev_set_param(ar, param_id, 0, pdev_id);
3260dd4f32aeSBjoern A. Zeeb if (ret)
3261dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab,
3262dd4f32aeSBjoern A. Zeeb "failed to set obss_pd_threshold for pdev: %u\n",
3263dd4f32aeSBjoern A. Zeeb pdev_id);
3264dd4f32aeSBjoern A. Zeeb return ret;
3265dd4f32aeSBjoern A. Zeeb }
3266dd4f32aeSBjoern A. Zeeb
3267dd4f32aeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
326828348caeSBjoern A. Zeeb "obss pd sr_ctrl %x non_srg_thres %u srg_max %u\n",
3269dd4f32aeSBjoern A. Zeeb he_obss_pd->sr_ctrl, he_obss_pd->non_srg_max_offset,
3270dd4f32aeSBjoern A. Zeeb he_obss_pd->max_offset);
3271dd4f32aeSBjoern A. Zeeb
3272dd4f32aeSBjoern A. Zeeb param_val = 0;
3273dd4f32aeSBjoern A. Zeeb
3274dd4f32aeSBjoern A. Zeeb if (he_obss_pd->sr_ctrl &
3275dd4f32aeSBjoern A. Zeeb IEEE80211_HE_SPR_NON_SRG_OBSS_PD_SR_DISALLOWED) {
3276dd4f32aeSBjoern A. Zeeb non_srg_th = ATH11K_OBSS_PD_MAX_THRESHOLD;
3277dd4f32aeSBjoern A. Zeeb } else {
3278dd4f32aeSBjoern A. Zeeb if (he_obss_pd->sr_ctrl & IEEE80211_HE_SPR_NON_SRG_OFFSET_PRESENT)
3279dd4f32aeSBjoern A. Zeeb non_srg_th = (ATH11K_OBSS_PD_MAX_THRESHOLD +
3280dd4f32aeSBjoern A. Zeeb he_obss_pd->non_srg_max_offset);
3281dd4f32aeSBjoern A. Zeeb else
3282dd4f32aeSBjoern A. Zeeb non_srg_th = ATH11K_OBSS_PD_NON_SRG_MAX_THRESHOLD;
3283dd4f32aeSBjoern A. Zeeb
3284dd4f32aeSBjoern A. Zeeb param_val |= ATH11K_OBSS_PD_NON_SRG_EN;
3285dd4f32aeSBjoern A. Zeeb }
3286dd4f32aeSBjoern A. Zeeb
3287dd4f32aeSBjoern A. Zeeb if (he_obss_pd->sr_ctrl & IEEE80211_HE_SPR_SRG_INFORMATION_PRESENT) {
3288dd4f32aeSBjoern A. Zeeb srg_th = ATH11K_OBSS_PD_MAX_THRESHOLD + he_obss_pd->max_offset;
3289dd4f32aeSBjoern A. Zeeb param_val |= ATH11K_OBSS_PD_SRG_EN;
3290dd4f32aeSBjoern A. Zeeb }
3291dd4f32aeSBjoern A. Zeeb
3292dd4f32aeSBjoern A. Zeeb if (test_bit(WMI_TLV_SERVICE_SRG_SRP_SPATIAL_REUSE_SUPPORT,
3293dd4f32aeSBjoern A. Zeeb ar->ab->wmi_ab.svc_map)) {
3294dd4f32aeSBjoern A. Zeeb param_val |= ATH11K_OBSS_PD_THRESHOLD_IN_DBM;
3295dd4f32aeSBjoern A. Zeeb param_val |= FIELD_PREP(GENMASK(15, 8), srg_th);
3296dd4f32aeSBjoern A. Zeeb } else {
3297dd4f32aeSBjoern A. Zeeb non_srg_th -= ATH11K_DEFAULT_NOISE_FLOOR;
3298dd4f32aeSBjoern A. Zeeb /* SRG not supported and threshold in dB */
3299dd4f32aeSBjoern A. Zeeb param_val &= ~(ATH11K_OBSS_PD_SRG_EN |
3300dd4f32aeSBjoern A. Zeeb ATH11K_OBSS_PD_THRESHOLD_IN_DBM);
3301dd4f32aeSBjoern A. Zeeb }
3302dd4f32aeSBjoern A. Zeeb
3303dd4f32aeSBjoern A. Zeeb param_val |= (non_srg_th & GENMASK(7, 0));
3304dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_pdev_set_param(ar, param_id, param_val, pdev_id);
3305dd4f32aeSBjoern A. Zeeb if (ret) {
3306dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab,
3307dd4f32aeSBjoern A. Zeeb "failed to set obss_pd_threshold for pdev: %u\n",
3308dd4f32aeSBjoern A. Zeeb pdev_id);
3309dd4f32aeSBjoern A. Zeeb return ret;
3310dd4f32aeSBjoern A. Zeeb }
3311dd4f32aeSBjoern A. Zeeb
3312dd4f32aeSBjoern A. Zeeb /* Enable OBSS PD for all access category */
3313dd4f32aeSBjoern A. Zeeb param_id = WMI_PDEV_PARAM_SET_CMD_OBSS_PD_PER_AC;
3314dd4f32aeSBjoern A. Zeeb param_val = 0xf;
3315dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_pdev_set_param(ar, param_id, param_val, pdev_id);
3316dd4f32aeSBjoern A. Zeeb if (ret) {
3317dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab,
3318dd4f32aeSBjoern A. Zeeb "failed to set obss_pd_per_ac for pdev: %u\n",
3319dd4f32aeSBjoern A. Zeeb pdev_id);
3320dd4f32aeSBjoern A. Zeeb return ret;
3321dd4f32aeSBjoern A. Zeeb }
3322dd4f32aeSBjoern A. Zeeb
3323dd4f32aeSBjoern A. Zeeb /* Set SR Prohibit */
3324dd4f32aeSBjoern A. Zeeb param_id = WMI_PDEV_PARAM_ENABLE_SR_PROHIBIT;
3325dd4f32aeSBjoern A. Zeeb param_val = !!(he_obss_pd->sr_ctrl &
3326dd4f32aeSBjoern A. Zeeb IEEE80211_HE_SPR_HESIGA_SR_VAL15_ALLOWED);
3327dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_pdev_set_param(ar, param_id, param_val, pdev_id);
3328dd4f32aeSBjoern A. Zeeb if (ret) {
3329dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to set sr_prohibit for pdev: %u\n",
3330dd4f32aeSBjoern A. Zeeb pdev_id);
3331dd4f32aeSBjoern A. Zeeb return ret;
3332dd4f32aeSBjoern A. Zeeb }
3333dd4f32aeSBjoern A. Zeeb
3334dd4f32aeSBjoern A. Zeeb if (!test_bit(WMI_TLV_SERVICE_SRG_SRP_SPATIAL_REUSE_SUPPORT,
3335dd4f32aeSBjoern A. Zeeb ar->ab->wmi_ab.svc_map))
3336dd4f32aeSBjoern A. Zeeb return 0;
3337dd4f32aeSBjoern A. Zeeb
3338dd4f32aeSBjoern A. Zeeb /* Set SRG BSS Color Bitmap */
3339dd4f32aeSBjoern A. Zeeb memcpy(bitmap, he_obss_pd->bss_color_bitmap, sizeof(bitmap));
3340dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_pdev_set_srg_bss_color_bitmap(ar, bitmap);
3341dd4f32aeSBjoern A. Zeeb if (ret) {
3342dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab,
3343dd4f32aeSBjoern A. Zeeb "failed to set bss_color_bitmap for pdev: %u\n",
3344dd4f32aeSBjoern A. Zeeb pdev_id);
3345dd4f32aeSBjoern A. Zeeb return ret;
3346dd4f32aeSBjoern A. Zeeb }
3347dd4f32aeSBjoern A. Zeeb
3348dd4f32aeSBjoern A. Zeeb /* Set SRG Partial BSSID Bitmap */
3349dd4f32aeSBjoern A. Zeeb memcpy(bitmap, he_obss_pd->partial_bssid_bitmap, sizeof(bitmap));
3350dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_pdev_set_srg_patial_bssid_bitmap(ar, bitmap);
3351dd4f32aeSBjoern A. Zeeb if (ret) {
3352dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab,
3353dd4f32aeSBjoern A. Zeeb "failed to set partial_bssid_bitmap for pdev: %u\n",
3354dd4f32aeSBjoern A. Zeeb pdev_id);
3355dd4f32aeSBjoern A. Zeeb return ret;
3356dd4f32aeSBjoern A. Zeeb }
3357dd4f32aeSBjoern A. Zeeb
3358dd4f32aeSBjoern A. Zeeb memset(bitmap, 0xff, sizeof(bitmap));
3359dd4f32aeSBjoern A. Zeeb
3360dd4f32aeSBjoern A. Zeeb /* Enable all BSS Colors for SRG */
3361dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_pdev_srg_obss_color_enable_bitmap(ar, bitmap);
3362dd4f32aeSBjoern A. Zeeb if (ret) {
3363dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab,
3364dd4f32aeSBjoern A. Zeeb "failed to set srg_color_en_bitmap pdev: %u\n",
3365dd4f32aeSBjoern A. Zeeb pdev_id);
3366dd4f32aeSBjoern A. Zeeb return ret;
3367dd4f32aeSBjoern A. Zeeb }
3368dd4f32aeSBjoern A. Zeeb
336928348caeSBjoern A. Zeeb /* Enable all partial BSSID mask for SRG */
3370dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_pdev_srg_obss_bssid_enable_bitmap(ar, bitmap);
3371dd4f32aeSBjoern A. Zeeb if (ret) {
3372dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab,
3373dd4f32aeSBjoern A. Zeeb "failed to set srg_bssid_en_bitmap pdev: %u\n",
3374dd4f32aeSBjoern A. Zeeb pdev_id);
3375dd4f32aeSBjoern A. Zeeb return ret;
3376dd4f32aeSBjoern A. Zeeb }
3377dd4f32aeSBjoern A. Zeeb
3378dd4f32aeSBjoern A. Zeeb /* Enable all BSS Colors for non-SRG */
3379dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_pdev_non_srg_obss_color_enable_bitmap(ar, bitmap);
3380dd4f32aeSBjoern A. Zeeb if (ret) {
3381dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab,
3382dd4f32aeSBjoern A. Zeeb "failed to set non_srg_color_en_bitmap pdev: %u\n",
3383dd4f32aeSBjoern A. Zeeb pdev_id);
3384dd4f32aeSBjoern A. Zeeb return ret;
3385dd4f32aeSBjoern A. Zeeb }
3386dd4f32aeSBjoern A. Zeeb
338728348caeSBjoern A. Zeeb /* Enable all partial BSSID mask for non-SRG */
3388dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_pdev_non_srg_obss_bssid_enable_bitmap(ar, bitmap);
3389dd4f32aeSBjoern A. Zeeb if (ret) {
3390dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab,
3391dd4f32aeSBjoern A. Zeeb "failed to set non_srg_bssid_en_bitmap pdev: %u\n",
3392dd4f32aeSBjoern A. Zeeb pdev_id);
3393dd4f32aeSBjoern A. Zeeb return ret;
3394dd4f32aeSBjoern A. Zeeb }
3395dd4f32aeSBjoern A. Zeeb
3396dd4f32aeSBjoern A. Zeeb return 0;
3397dd4f32aeSBjoern A. Zeeb }
3398dd4f32aeSBjoern A. Zeeb
ath11k_mac_op_bss_info_changed(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_bss_conf * info,u64 changed)3399dd4f32aeSBjoern A. Zeeb static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
3400dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif,
3401dd4f32aeSBjoern A. Zeeb struct ieee80211_bss_conf *info,
3402dd4f32aeSBjoern A. Zeeb u64 changed)
3403dd4f32aeSBjoern A. Zeeb {
3404dd4f32aeSBjoern A. Zeeb struct ath11k *ar = hw->priv;
3405dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
3406dd4f32aeSBjoern A. Zeeb struct cfg80211_chan_def def;
3407dd4f32aeSBjoern A. Zeeb u32 param_id, param_value;
3408dd4f32aeSBjoern A. Zeeb enum nl80211_band band;
3409dd4f32aeSBjoern A. Zeeb u32 vdev_param;
3410dd4f32aeSBjoern A. Zeeb int mcast_rate;
3411dd4f32aeSBjoern A. Zeeb u32 preamble;
3412dd4f32aeSBjoern A. Zeeb u16 hw_value;
3413dd4f32aeSBjoern A. Zeeb u16 bitrate;
3414dd4f32aeSBjoern A. Zeeb int ret = 0;
3415dd4f32aeSBjoern A. Zeeb u8 rateidx;
341628348caeSBjoern A. Zeeb u32 rate, param;
341728348caeSBjoern A. Zeeb u32 ipv4_cnt;
3418dd4f32aeSBjoern A. Zeeb
3419dd4f32aeSBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
3420dd4f32aeSBjoern A. Zeeb
3421dd4f32aeSBjoern A. Zeeb if (changed & BSS_CHANGED_BEACON_INT) {
3422dd4f32aeSBjoern A. Zeeb arvif->beacon_interval = info->beacon_int;
3423dd4f32aeSBjoern A. Zeeb
3424dd4f32aeSBjoern A. Zeeb param_id = WMI_VDEV_PARAM_BEACON_INTERVAL;
3425dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
3426dd4f32aeSBjoern A. Zeeb param_id,
3427dd4f32aeSBjoern A. Zeeb arvif->beacon_interval);
3428dd4f32aeSBjoern A. Zeeb if (ret)
3429dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "Failed to set beacon interval for VDEV: %d\n",
3430dd4f32aeSBjoern A. Zeeb arvif->vdev_id);
3431dd4f32aeSBjoern A. Zeeb else
3432dd4f32aeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
3433dd4f32aeSBjoern A. Zeeb "Beacon interval: %d set for VDEV: %d\n",
3434dd4f32aeSBjoern A. Zeeb arvif->beacon_interval, arvif->vdev_id);
3435dd4f32aeSBjoern A. Zeeb }
3436dd4f32aeSBjoern A. Zeeb
3437dd4f32aeSBjoern A. Zeeb if (changed & BSS_CHANGED_BEACON) {
3438dd4f32aeSBjoern A. Zeeb param_id = WMI_PDEV_PARAM_BEACON_TX_MODE;
3439dd4f32aeSBjoern A. Zeeb param_value = WMI_BEACON_STAGGERED_MODE;
3440dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_pdev_set_param(ar, param_id,
3441dd4f32aeSBjoern A. Zeeb param_value, ar->pdev->pdev_id);
3442dd4f32aeSBjoern A. Zeeb if (ret)
3443dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "Failed to set beacon mode for VDEV: %d\n",
3444dd4f32aeSBjoern A. Zeeb arvif->vdev_id);
3445dd4f32aeSBjoern A. Zeeb else
3446dd4f32aeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
3447dd4f32aeSBjoern A. Zeeb "Set staggered beacon mode for VDEV: %d\n",
3448dd4f32aeSBjoern A. Zeeb arvif->vdev_id);
3449dd4f32aeSBjoern A. Zeeb
3450dd4f32aeSBjoern A. Zeeb if (!arvif->do_not_send_tmpl || !arvif->bcca_zero_sent) {
3451dd4f32aeSBjoern A. Zeeb ret = ath11k_mac_setup_bcn_tmpl(arvif);
3452dd4f32aeSBjoern A. Zeeb if (ret)
3453dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to update bcn template: %d\n",
3454dd4f32aeSBjoern A. Zeeb ret);
3455dd4f32aeSBjoern A. Zeeb }
3456dd4f32aeSBjoern A. Zeeb
3457dd4f32aeSBjoern A. Zeeb if (arvif->bcca_zero_sent)
3458dd4f32aeSBjoern A. Zeeb arvif->do_not_send_tmpl = true;
3459dd4f32aeSBjoern A. Zeeb else
3460dd4f32aeSBjoern A. Zeeb arvif->do_not_send_tmpl = false;
346128348caeSBjoern A. Zeeb
346228348caeSBjoern A. Zeeb if (vif->bss_conf.he_support) {
346328348caeSBjoern A. Zeeb ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
346428348caeSBjoern A. Zeeb WMI_VDEV_PARAM_BA_MODE,
346528348caeSBjoern A. Zeeb WMI_BA_MODE_BUFFER_SIZE_256);
346628348caeSBjoern A. Zeeb if (ret)
346728348caeSBjoern A. Zeeb ath11k_warn(ar->ab,
346828348caeSBjoern A. Zeeb "failed to set BA BUFFER SIZE 256 for vdev: %d\n",
346928348caeSBjoern A. Zeeb arvif->vdev_id);
347028348caeSBjoern A. Zeeb else
347128348caeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
347228348caeSBjoern A. Zeeb "Set BA BUFFER SIZE 256 for VDEV: %d\n",
347328348caeSBjoern A. Zeeb arvif->vdev_id);
347428348caeSBjoern A. Zeeb }
3475dd4f32aeSBjoern A. Zeeb }
3476dd4f32aeSBjoern A. Zeeb
3477dd4f32aeSBjoern A. Zeeb if (changed & (BSS_CHANGED_BEACON_INFO | BSS_CHANGED_BEACON)) {
3478dd4f32aeSBjoern A. Zeeb arvif->dtim_period = info->dtim_period;
3479dd4f32aeSBjoern A. Zeeb
3480dd4f32aeSBjoern A. Zeeb param_id = WMI_VDEV_PARAM_DTIM_PERIOD;
3481dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
3482dd4f32aeSBjoern A. Zeeb param_id,
3483dd4f32aeSBjoern A. Zeeb arvif->dtim_period);
3484dd4f32aeSBjoern A. Zeeb
3485dd4f32aeSBjoern A. Zeeb if (ret)
3486dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "Failed to set dtim period for VDEV %d: %i\n",
3487dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ret);
3488dd4f32aeSBjoern A. Zeeb else
3489dd4f32aeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
3490dd4f32aeSBjoern A. Zeeb "DTIM period: %d set for VDEV: %d\n",
3491dd4f32aeSBjoern A. Zeeb arvif->dtim_period, arvif->vdev_id);
3492dd4f32aeSBjoern A. Zeeb }
3493dd4f32aeSBjoern A. Zeeb
3494dd4f32aeSBjoern A. Zeeb if (changed & BSS_CHANGED_SSID &&
3495dd4f32aeSBjoern A. Zeeb vif->type == NL80211_IFTYPE_AP) {
349628348caeSBjoern A. Zeeb arvif->u.ap.ssid_len = vif->cfg.ssid_len;
349728348caeSBjoern A. Zeeb if (vif->cfg.ssid_len)
349828348caeSBjoern A. Zeeb memcpy(arvif->u.ap.ssid, vif->cfg.ssid,
349928348caeSBjoern A. Zeeb vif->cfg.ssid_len);
3500dd4f32aeSBjoern A. Zeeb arvif->u.ap.hidden_ssid = info->hidden_ssid;
3501dd4f32aeSBjoern A. Zeeb }
3502dd4f32aeSBjoern A. Zeeb
3503dd4f32aeSBjoern A. Zeeb if (changed & BSS_CHANGED_BSSID && !is_zero_ether_addr(info->bssid))
3504dd4f32aeSBjoern A. Zeeb ether_addr_copy(arvif->bssid, info->bssid);
3505dd4f32aeSBjoern A. Zeeb
3506dd4f32aeSBjoern A. Zeeb if (changed & BSS_CHANGED_BEACON_ENABLED) {
350728348caeSBjoern A. Zeeb if (info->enable_beacon)
350828348caeSBjoern A. Zeeb ath11k_mac_set_he_txbf_conf(arvif);
3509dd4f32aeSBjoern A. Zeeb ath11k_control_beaconing(arvif, info);
3510dd4f32aeSBjoern A. Zeeb
3511dd4f32aeSBjoern A. Zeeb if (arvif->is_up && vif->bss_conf.he_support &&
3512dd4f32aeSBjoern A. Zeeb vif->bss_conf.he_oper.params) {
3513dd4f32aeSBjoern A. Zeeb param_id = WMI_VDEV_PARAM_HEOPS_0_31;
3514dd4f32aeSBjoern A. Zeeb param_value = vif->bss_conf.he_oper.params;
3515dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
3516dd4f32aeSBjoern A. Zeeb param_id, param_value);
3517dd4f32aeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
3518dd4f32aeSBjoern A. Zeeb "he oper param: %x set for VDEV: %d\n",
3519dd4f32aeSBjoern A. Zeeb param_value, arvif->vdev_id);
3520dd4f32aeSBjoern A. Zeeb
3521dd4f32aeSBjoern A. Zeeb if (ret)
3522dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "Failed to set he oper params %x for VDEV %d: %i\n",
3523dd4f32aeSBjoern A. Zeeb param_value, arvif->vdev_id, ret);
3524dd4f32aeSBjoern A. Zeeb }
3525dd4f32aeSBjoern A. Zeeb }
3526dd4f32aeSBjoern A. Zeeb
3527dd4f32aeSBjoern A. Zeeb if (changed & BSS_CHANGED_ERP_CTS_PROT) {
3528dd4f32aeSBjoern A. Zeeb u32 cts_prot;
3529dd4f32aeSBjoern A. Zeeb
3530dd4f32aeSBjoern A. Zeeb cts_prot = !!(info->use_cts_prot);
3531dd4f32aeSBjoern A. Zeeb param_id = WMI_VDEV_PARAM_PROTECTION_MODE;
3532dd4f32aeSBjoern A. Zeeb
3533dd4f32aeSBjoern A. Zeeb if (arvif->is_started) {
3534dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
3535dd4f32aeSBjoern A. Zeeb param_id, cts_prot);
3536dd4f32aeSBjoern A. Zeeb if (ret)
3537dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "Failed to set CTS prot for VDEV: %d\n",
3538dd4f32aeSBjoern A. Zeeb arvif->vdev_id);
3539dd4f32aeSBjoern A. Zeeb else
3540dd4f32aeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "Set CTS prot: %d for VDEV: %d\n",
3541dd4f32aeSBjoern A. Zeeb cts_prot, arvif->vdev_id);
3542dd4f32aeSBjoern A. Zeeb } else {
3543dd4f32aeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "defer protection mode setup, vdev is not ready yet\n");
3544dd4f32aeSBjoern A. Zeeb }
3545dd4f32aeSBjoern A. Zeeb }
3546dd4f32aeSBjoern A. Zeeb
3547dd4f32aeSBjoern A. Zeeb if (changed & BSS_CHANGED_ERP_SLOT) {
3548dd4f32aeSBjoern A. Zeeb u32 slottime;
3549dd4f32aeSBjoern A. Zeeb
3550dd4f32aeSBjoern A. Zeeb if (info->use_short_slot)
3551dd4f32aeSBjoern A. Zeeb slottime = WMI_VDEV_SLOT_TIME_SHORT; /* 9us */
3552dd4f32aeSBjoern A. Zeeb
3553dd4f32aeSBjoern A. Zeeb else
3554dd4f32aeSBjoern A. Zeeb slottime = WMI_VDEV_SLOT_TIME_LONG; /* 20us */
3555dd4f32aeSBjoern A. Zeeb
3556dd4f32aeSBjoern A. Zeeb param_id = WMI_VDEV_PARAM_SLOT_TIME;
3557dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
3558dd4f32aeSBjoern A. Zeeb param_id, slottime);
3559dd4f32aeSBjoern A. Zeeb if (ret)
3560dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "Failed to set erp slot for VDEV: %d\n",
3561dd4f32aeSBjoern A. Zeeb arvif->vdev_id);
3562dd4f32aeSBjoern A. Zeeb else
3563dd4f32aeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
3564dd4f32aeSBjoern A. Zeeb "Set slottime: %d for VDEV: %d\n",
3565dd4f32aeSBjoern A. Zeeb slottime, arvif->vdev_id);
3566dd4f32aeSBjoern A. Zeeb }
3567dd4f32aeSBjoern A. Zeeb
3568dd4f32aeSBjoern A. Zeeb if (changed & BSS_CHANGED_ERP_PREAMBLE) {
3569dd4f32aeSBjoern A. Zeeb u32 preamble;
3570dd4f32aeSBjoern A. Zeeb
3571dd4f32aeSBjoern A. Zeeb if (info->use_short_preamble)
3572dd4f32aeSBjoern A. Zeeb preamble = WMI_VDEV_PREAMBLE_SHORT;
3573dd4f32aeSBjoern A. Zeeb else
3574dd4f32aeSBjoern A. Zeeb preamble = WMI_VDEV_PREAMBLE_LONG;
3575dd4f32aeSBjoern A. Zeeb
3576dd4f32aeSBjoern A. Zeeb param_id = WMI_VDEV_PARAM_PREAMBLE;
3577dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
3578dd4f32aeSBjoern A. Zeeb param_id, preamble);
3579dd4f32aeSBjoern A. Zeeb if (ret)
3580dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "Failed to set preamble for VDEV: %d\n",
3581dd4f32aeSBjoern A. Zeeb arvif->vdev_id);
3582dd4f32aeSBjoern A. Zeeb else
3583dd4f32aeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
3584dd4f32aeSBjoern A. Zeeb "Set preamble: %d for VDEV: %d\n",
3585dd4f32aeSBjoern A. Zeeb preamble, arvif->vdev_id);
3586dd4f32aeSBjoern A. Zeeb }
3587dd4f32aeSBjoern A. Zeeb
3588dd4f32aeSBjoern A. Zeeb if (changed & BSS_CHANGED_ASSOC) {
358928348caeSBjoern A. Zeeb if (vif->cfg.assoc)
3590dd4f32aeSBjoern A. Zeeb ath11k_bss_assoc(hw, vif, info);
3591dd4f32aeSBjoern A. Zeeb else
3592dd4f32aeSBjoern A. Zeeb ath11k_bss_disassoc(hw, vif);
3593dd4f32aeSBjoern A. Zeeb }
3594dd4f32aeSBjoern A. Zeeb
3595dd4f32aeSBjoern A. Zeeb if (changed & BSS_CHANGED_TXPOWER) {
359628348caeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev_id %i txpower %d\n",
3597dd4f32aeSBjoern A. Zeeb arvif->vdev_id, info->txpower);
3598dd4f32aeSBjoern A. Zeeb
3599dd4f32aeSBjoern A. Zeeb arvif->txpower = info->txpower;
3600dd4f32aeSBjoern A. Zeeb ath11k_mac_txpower_recalc(ar);
3601dd4f32aeSBjoern A. Zeeb }
3602dd4f32aeSBjoern A. Zeeb
3603dd4f32aeSBjoern A. Zeeb if (changed & BSS_CHANGED_PS &&
3604dd4f32aeSBjoern A. Zeeb ar->ab->hw_params.supports_sta_ps) {
360528348caeSBjoern A. Zeeb arvif->ps = vif->cfg.ps;
3606dd4f32aeSBjoern A. Zeeb
3607dd4f32aeSBjoern A. Zeeb ret = ath11k_mac_config_ps(ar);
3608dd4f32aeSBjoern A. Zeeb if (ret)
3609dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to setup ps on vdev %i: %d\n",
3610dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ret);
3611dd4f32aeSBjoern A. Zeeb }
3612dd4f32aeSBjoern A. Zeeb
3613dd4f32aeSBjoern A. Zeeb if (changed & BSS_CHANGED_MCAST_RATE &&
3614dd4f32aeSBjoern A. Zeeb !ath11k_mac_vif_chan(arvif->vif, &def)) {
3615dd4f32aeSBjoern A. Zeeb band = def.chan->band;
3616dd4f32aeSBjoern A. Zeeb mcast_rate = vif->bss_conf.mcast_rate[band];
3617dd4f32aeSBjoern A. Zeeb
3618dd4f32aeSBjoern A. Zeeb if (mcast_rate > 0)
3619dd4f32aeSBjoern A. Zeeb rateidx = mcast_rate - 1;
3620dd4f32aeSBjoern A. Zeeb else
3621dd4f32aeSBjoern A. Zeeb rateidx = ffs(vif->bss_conf.basic_rates) - 1;
3622dd4f32aeSBjoern A. Zeeb
3623dd4f32aeSBjoern A. Zeeb if (ar->pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP)
3624dd4f32aeSBjoern A. Zeeb rateidx += ATH11K_MAC_FIRST_OFDM_RATE_IDX;
3625dd4f32aeSBjoern A. Zeeb
3626dd4f32aeSBjoern A. Zeeb bitrate = ath11k_legacy_rates[rateidx].bitrate;
3627dd4f32aeSBjoern A. Zeeb hw_value = ath11k_legacy_rates[rateidx].hw_value;
3628dd4f32aeSBjoern A. Zeeb
3629dd4f32aeSBjoern A. Zeeb if (ath11k_mac_bitrate_is_cck(bitrate))
3630dd4f32aeSBjoern A. Zeeb preamble = WMI_RATE_PREAMBLE_CCK;
3631dd4f32aeSBjoern A. Zeeb else
3632dd4f32aeSBjoern A. Zeeb preamble = WMI_RATE_PREAMBLE_OFDM;
3633dd4f32aeSBjoern A. Zeeb
3634dd4f32aeSBjoern A. Zeeb rate = ATH11K_HW_RATE_CODE(hw_value, 0, preamble);
3635dd4f32aeSBjoern A. Zeeb
3636dd4f32aeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
363728348caeSBjoern A. Zeeb "vdev %d mcast_rate %x\n",
3638dd4f32aeSBjoern A. Zeeb arvif->vdev_id, rate);
3639dd4f32aeSBjoern A. Zeeb
3640dd4f32aeSBjoern A. Zeeb vdev_param = WMI_VDEV_PARAM_MCAST_DATA_RATE;
3641dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
3642dd4f32aeSBjoern A. Zeeb vdev_param, rate);
3643dd4f32aeSBjoern A. Zeeb if (ret)
3644dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab,
3645dd4f32aeSBjoern A. Zeeb "failed to set mcast rate on vdev %i: %d\n",
3646dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ret);
3647dd4f32aeSBjoern A. Zeeb
3648dd4f32aeSBjoern A. Zeeb vdev_param = WMI_VDEV_PARAM_BCAST_DATA_RATE;
3649dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
3650dd4f32aeSBjoern A. Zeeb vdev_param, rate);
3651dd4f32aeSBjoern A. Zeeb if (ret)
3652dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab,
3653dd4f32aeSBjoern A. Zeeb "failed to set bcast rate on vdev %i: %d\n",
3654dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ret);
3655dd4f32aeSBjoern A. Zeeb }
3656dd4f32aeSBjoern A. Zeeb
3657dd4f32aeSBjoern A. Zeeb if (changed & BSS_CHANGED_BASIC_RATES &&
3658dd4f32aeSBjoern A. Zeeb !ath11k_mac_vif_chan(arvif->vif, &def))
3659dd4f32aeSBjoern A. Zeeb ath11k_recalculate_mgmt_rate(ar, vif, &def);
3660dd4f32aeSBjoern A. Zeeb
3661dd4f32aeSBjoern A. Zeeb if (changed & BSS_CHANGED_TWT) {
366228348caeSBjoern A. Zeeb struct wmi_twt_enable_params twt_params = {0};
366328348caeSBjoern A. Zeeb
366428348caeSBjoern A. Zeeb if (info->twt_requester || info->twt_responder) {
366528348caeSBjoern A. Zeeb ath11k_wmi_fill_default_twt_params(&twt_params);
366628348caeSBjoern A. Zeeb ath11k_wmi_send_twt_enable_cmd(ar, ar->pdev->pdev_id,
366728348caeSBjoern A. Zeeb &twt_params);
366828348caeSBjoern A. Zeeb } else {
3669dd4f32aeSBjoern A. Zeeb ath11k_wmi_send_twt_disable_cmd(ar, ar->pdev->pdev_id);
3670dd4f32aeSBjoern A. Zeeb }
367128348caeSBjoern A. Zeeb }
3672dd4f32aeSBjoern A. Zeeb
3673dd4f32aeSBjoern A. Zeeb if (changed & BSS_CHANGED_HE_OBSS_PD)
3674dd4f32aeSBjoern A. Zeeb ath11k_mac_config_obss_pd(ar, &info->he_obss_pd);
3675dd4f32aeSBjoern A. Zeeb
3676dd4f32aeSBjoern A. Zeeb if (changed & BSS_CHANGED_HE_BSS_COLOR) {
3677dd4f32aeSBjoern A. Zeeb if (vif->type == NL80211_IFTYPE_AP) {
3678dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_send_obss_color_collision_cfg_cmd(
3679dd4f32aeSBjoern A. Zeeb ar, arvif->vdev_id, info->he_bss_color.color,
3680dd4f32aeSBjoern A. Zeeb ATH11K_BSS_COLOR_COLLISION_DETECTION_AP_PERIOD_MS,
3681dd4f32aeSBjoern A. Zeeb info->he_bss_color.enabled);
3682dd4f32aeSBjoern A. Zeeb if (ret)
3683dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to set bss color collision on vdev %i: %d\n",
3684dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ret);
3685dd4f32aeSBjoern A. Zeeb
3686dd4f32aeSBjoern A. Zeeb param_id = WMI_VDEV_PARAM_BSS_COLOR;
3687dd4f32aeSBjoern A. Zeeb if (info->he_bss_color.enabled)
3688dd4f32aeSBjoern A. Zeeb param_value = info->he_bss_color.color <<
3689dd4f32aeSBjoern A. Zeeb IEEE80211_HE_OPERATION_BSS_COLOR_OFFSET;
3690dd4f32aeSBjoern A. Zeeb else
3691dd4f32aeSBjoern A. Zeeb param_value = IEEE80211_HE_OPERATION_BSS_COLOR_DISABLED;
3692dd4f32aeSBjoern A. Zeeb
3693dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
3694dd4f32aeSBjoern A. Zeeb param_id,
3695dd4f32aeSBjoern A. Zeeb param_value);
3696dd4f32aeSBjoern A. Zeeb if (ret)
3697dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab,
3698dd4f32aeSBjoern A. Zeeb "failed to set bss color param on vdev %i: %d\n",
3699dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ret);
3700dd4f32aeSBjoern A. Zeeb
3701dd4f32aeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
3702dd4f32aeSBjoern A. Zeeb "bss color param 0x%x set on vdev %i\n",
3703dd4f32aeSBjoern A. Zeeb param_value, arvif->vdev_id);
3704dd4f32aeSBjoern A. Zeeb } else if (vif->type == NL80211_IFTYPE_STATION) {
3705dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_send_bss_color_change_enable_cmd(ar,
3706dd4f32aeSBjoern A. Zeeb arvif->vdev_id,
3707dd4f32aeSBjoern A. Zeeb 1);
3708dd4f32aeSBjoern A. Zeeb if (ret)
3709dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to enable bss color change on vdev %i: %d\n",
3710dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ret);
3711dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_send_obss_color_collision_cfg_cmd(
3712dd4f32aeSBjoern A. Zeeb ar, arvif->vdev_id, 0,
3713dd4f32aeSBjoern A. Zeeb ATH11K_BSS_COLOR_COLLISION_DETECTION_STA_PERIOD_MS, 1);
3714dd4f32aeSBjoern A. Zeeb if (ret)
3715dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to set bss color collision on vdev %i: %d\n",
3716dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ret);
3717dd4f32aeSBjoern A. Zeeb }
3718dd4f32aeSBjoern A. Zeeb }
3719dd4f32aeSBjoern A. Zeeb
372028348caeSBjoern A. Zeeb if (changed & BSS_CHANGED_FTM_RESPONDER &&
372128348caeSBjoern A. Zeeb arvif->ftm_responder != info->ftm_responder &&
372228348caeSBjoern A. Zeeb test_bit(WMI_TLV_SERVICE_RTT, ar->ab->wmi_ab.svc_map) &&
372328348caeSBjoern A. Zeeb (vif->type == NL80211_IFTYPE_AP ||
372428348caeSBjoern A. Zeeb vif->type == NL80211_IFTYPE_MESH_POINT)) {
372528348caeSBjoern A. Zeeb arvif->ftm_responder = info->ftm_responder;
372628348caeSBjoern A. Zeeb param = WMI_VDEV_PARAM_ENABLE_DISABLE_RTT_RESPONDER_ROLE;
372728348caeSBjoern A. Zeeb ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, param,
372828348caeSBjoern A. Zeeb arvif->ftm_responder);
372928348caeSBjoern A. Zeeb if (ret)
373028348caeSBjoern A. Zeeb ath11k_warn(ar->ab, "Failed to set ftm responder %i: %d\n",
373128348caeSBjoern A. Zeeb arvif->vdev_id, ret);
373228348caeSBjoern A. Zeeb }
373328348caeSBjoern A. Zeeb
3734dd4f32aeSBjoern A. Zeeb if (changed & BSS_CHANGED_FILS_DISCOVERY ||
3735dd4f32aeSBjoern A. Zeeb changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP)
3736dd4f32aeSBjoern A. Zeeb ath11k_mac_fils_discovery(arvif, info);
3737dd4f32aeSBjoern A. Zeeb
373828348caeSBjoern A. Zeeb if (changed & BSS_CHANGED_ARP_FILTER) {
373928348caeSBjoern A. Zeeb ipv4_cnt = min(vif->cfg.arp_addr_cnt, ATH11K_IPV4_MAX_COUNT);
374028348caeSBjoern A. Zeeb memcpy(arvif->arp_ns_offload.ipv4_addr,
374128348caeSBjoern A. Zeeb vif->cfg.arp_addr_list,
374228348caeSBjoern A. Zeeb ipv4_cnt * sizeof(u32));
374328348caeSBjoern A. Zeeb memcpy(arvif->arp_ns_offload.mac_addr, vif->addr, ETH_ALEN);
374428348caeSBjoern A. Zeeb arvif->arp_ns_offload.ipv4_count = ipv4_cnt;
374528348caeSBjoern A. Zeeb
374628348caeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "arp_addr_cnt %d vif->addr %pM, offload_addr %pI4\n",
374728348caeSBjoern A. Zeeb vif->cfg.arp_addr_cnt,
374828348caeSBjoern A. Zeeb vif->addr, arvif->arp_ns_offload.ipv4_addr);
374928348caeSBjoern A. Zeeb }
375028348caeSBjoern A. Zeeb
3751dd4f32aeSBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
3752dd4f32aeSBjoern A. Zeeb }
3753dd4f32aeSBjoern A. Zeeb
__ath11k_mac_scan_finish(struct ath11k * ar)3754dd4f32aeSBjoern A. Zeeb void __ath11k_mac_scan_finish(struct ath11k *ar)
3755dd4f32aeSBjoern A. Zeeb {
3756dd4f32aeSBjoern A. Zeeb lockdep_assert_held(&ar->data_lock);
3757dd4f32aeSBjoern A. Zeeb
3758dd4f32aeSBjoern A. Zeeb switch (ar->scan.state) {
3759dd4f32aeSBjoern A. Zeeb case ATH11K_SCAN_IDLE:
3760dd4f32aeSBjoern A. Zeeb break;
3761dd4f32aeSBjoern A. Zeeb case ATH11K_SCAN_RUNNING:
3762dd4f32aeSBjoern A. Zeeb case ATH11K_SCAN_ABORTING:
3763dd4f32aeSBjoern A. Zeeb if (ar->scan.is_roc && ar->scan.roc_notify)
3764dd4f32aeSBjoern A. Zeeb ieee80211_remain_on_channel_expired(ar->hw);
3765dd4f32aeSBjoern A. Zeeb fallthrough;
3766dd4f32aeSBjoern A. Zeeb case ATH11K_SCAN_STARTING:
3767dd4f32aeSBjoern A. Zeeb if (!ar->scan.is_roc) {
3768dd4f32aeSBjoern A. Zeeb struct cfg80211_scan_info info = {
3769dd4f32aeSBjoern A. Zeeb .aborted = ((ar->scan.state ==
3770dd4f32aeSBjoern A. Zeeb ATH11K_SCAN_ABORTING) ||
3771dd4f32aeSBjoern A. Zeeb (ar->scan.state ==
3772dd4f32aeSBjoern A. Zeeb ATH11K_SCAN_STARTING)),
3773dd4f32aeSBjoern A. Zeeb };
3774dd4f32aeSBjoern A. Zeeb
3775dd4f32aeSBjoern A. Zeeb ieee80211_scan_completed(ar->hw, &info);
3776dd4f32aeSBjoern A. Zeeb }
3777dd4f32aeSBjoern A. Zeeb
3778dd4f32aeSBjoern A. Zeeb ar->scan.state = ATH11K_SCAN_IDLE;
3779dd4f32aeSBjoern A. Zeeb ar->scan_channel = NULL;
3780dd4f32aeSBjoern A. Zeeb ar->scan.roc_freq = 0;
3781dd4f32aeSBjoern A. Zeeb cancel_delayed_work(&ar->scan.timeout);
378228348caeSBjoern A. Zeeb complete_all(&ar->scan.completed);
3783dd4f32aeSBjoern A. Zeeb break;
3784dd4f32aeSBjoern A. Zeeb }
3785dd4f32aeSBjoern A. Zeeb }
3786dd4f32aeSBjoern A. Zeeb
ath11k_mac_scan_finish(struct ath11k * ar)3787dd4f32aeSBjoern A. Zeeb void ath11k_mac_scan_finish(struct ath11k *ar)
3788dd4f32aeSBjoern A. Zeeb {
3789dd4f32aeSBjoern A. Zeeb spin_lock_bh(&ar->data_lock);
3790dd4f32aeSBjoern A. Zeeb __ath11k_mac_scan_finish(ar);
3791dd4f32aeSBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
3792dd4f32aeSBjoern A. Zeeb }
3793dd4f32aeSBjoern A. Zeeb
ath11k_scan_stop(struct ath11k * ar)3794dd4f32aeSBjoern A. Zeeb static int ath11k_scan_stop(struct ath11k *ar)
3795dd4f32aeSBjoern A. Zeeb {
3796dd4f32aeSBjoern A. Zeeb struct scan_cancel_param arg = {
3797dd4f32aeSBjoern A. Zeeb .req_type = WLAN_SCAN_CANCEL_SINGLE,
3798dd4f32aeSBjoern A. Zeeb .scan_id = ATH11K_SCAN_ID,
3799dd4f32aeSBjoern A. Zeeb };
3800dd4f32aeSBjoern A. Zeeb int ret;
3801dd4f32aeSBjoern A. Zeeb
3802dd4f32aeSBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
3803dd4f32aeSBjoern A. Zeeb
3804dd4f32aeSBjoern A. Zeeb /* TODO: Fill other STOP Params */
3805dd4f32aeSBjoern A. Zeeb arg.pdev_id = ar->pdev->pdev_id;
3806dd4f32aeSBjoern A. Zeeb
3807dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_send_scan_stop_cmd(ar, &arg);
3808dd4f32aeSBjoern A. Zeeb if (ret) {
3809dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to stop wmi scan: %d\n", ret);
3810dd4f32aeSBjoern A. Zeeb goto out;
3811dd4f32aeSBjoern A. Zeeb }
3812dd4f32aeSBjoern A. Zeeb
3813dd4f32aeSBjoern A. Zeeb ret = wait_for_completion_timeout(&ar->scan.completed, 3 * HZ);
3814dd4f32aeSBjoern A. Zeeb if (ret == 0) {
3815dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab,
3816dd4f32aeSBjoern A. Zeeb "failed to receive scan abort comple: timed out\n");
3817dd4f32aeSBjoern A. Zeeb ret = -ETIMEDOUT;
3818dd4f32aeSBjoern A. Zeeb } else if (ret > 0) {
3819dd4f32aeSBjoern A. Zeeb ret = 0;
3820dd4f32aeSBjoern A. Zeeb }
3821dd4f32aeSBjoern A. Zeeb
3822dd4f32aeSBjoern A. Zeeb out:
3823dd4f32aeSBjoern A. Zeeb /* Scan state should be updated upon scan completion but in case
3824dd4f32aeSBjoern A. Zeeb * firmware fails to deliver the event (for whatever reason) it is
3825dd4f32aeSBjoern A. Zeeb * desired to clean up scan state anyway. Firmware may have just
3826dd4f32aeSBjoern A. Zeeb * dropped the scan completion event delivery due to transport pipe
3827dd4f32aeSBjoern A. Zeeb * being overflown with data and/or it can recover on its own before
3828dd4f32aeSBjoern A. Zeeb * next scan request is submitted.
3829dd4f32aeSBjoern A. Zeeb */
3830dd4f32aeSBjoern A. Zeeb spin_lock_bh(&ar->data_lock);
3831dd4f32aeSBjoern A. Zeeb if (ar->scan.state != ATH11K_SCAN_IDLE)
3832dd4f32aeSBjoern A. Zeeb __ath11k_mac_scan_finish(ar);
3833dd4f32aeSBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
3834dd4f32aeSBjoern A. Zeeb
3835dd4f32aeSBjoern A. Zeeb return ret;
3836dd4f32aeSBjoern A. Zeeb }
3837dd4f32aeSBjoern A. Zeeb
ath11k_scan_abort(struct ath11k * ar)3838dd4f32aeSBjoern A. Zeeb static void ath11k_scan_abort(struct ath11k *ar)
3839dd4f32aeSBjoern A. Zeeb {
3840dd4f32aeSBjoern A. Zeeb int ret;
3841dd4f32aeSBjoern A. Zeeb
3842dd4f32aeSBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
3843dd4f32aeSBjoern A. Zeeb
3844dd4f32aeSBjoern A. Zeeb spin_lock_bh(&ar->data_lock);
3845dd4f32aeSBjoern A. Zeeb
3846dd4f32aeSBjoern A. Zeeb switch (ar->scan.state) {
3847dd4f32aeSBjoern A. Zeeb case ATH11K_SCAN_IDLE:
3848dd4f32aeSBjoern A. Zeeb /* This can happen if timeout worker kicked in and called
3849dd4f32aeSBjoern A. Zeeb * abortion while scan completion was being processed.
3850dd4f32aeSBjoern A. Zeeb */
3851dd4f32aeSBjoern A. Zeeb break;
3852dd4f32aeSBjoern A. Zeeb case ATH11K_SCAN_STARTING:
3853dd4f32aeSBjoern A. Zeeb case ATH11K_SCAN_ABORTING:
3854dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "refusing scan abortion due to invalid scan state: %d\n",
3855dd4f32aeSBjoern A. Zeeb ar->scan.state);
3856dd4f32aeSBjoern A. Zeeb break;
3857dd4f32aeSBjoern A. Zeeb case ATH11K_SCAN_RUNNING:
3858dd4f32aeSBjoern A. Zeeb ar->scan.state = ATH11K_SCAN_ABORTING;
3859dd4f32aeSBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
3860dd4f32aeSBjoern A. Zeeb
3861dd4f32aeSBjoern A. Zeeb ret = ath11k_scan_stop(ar);
3862dd4f32aeSBjoern A. Zeeb if (ret)
3863dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to abort scan: %d\n", ret);
3864dd4f32aeSBjoern A. Zeeb
3865dd4f32aeSBjoern A. Zeeb spin_lock_bh(&ar->data_lock);
3866dd4f32aeSBjoern A. Zeeb break;
3867dd4f32aeSBjoern A. Zeeb }
3868dd4f32aeSBjoern A. Zeeb
3869dd4f32aeSBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
3870dd4f32aeSBjoern A. Zeeb }
3871dd4f32aeSBjoern A. Zeeb
ath11k_scan_timeout_work(struct work_struct * work)3872dd4f32aeSBjoern A. Zeeb static void ath11k_scan_timeout_work(struct work_struct *work)
3873dd4f32aeSBjoern A. Zeeb {
3874dd4f32aeSBjoern A. Zeeb struct ath11k *ar = container_of(work, struct ath11k,
3875dd4f32aeSBjoern A. Zeeb scan.timeout.work);
3876dd4f32aeSBjoern A. Zeeb
3877dd4f32aeSBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
3878dd4f32aeSBjoern A. Zeeb ath11k_scan_abort(ar);
3879dd4f32aeSBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
3880dd4f32aeSBjoern A. Zeeb }
3881dd4f32aeSBjoern A. Zeeb
ath11k_start_scan(struct ath11k * ar,struct scan_req_params * arg)3882dd4f32aeSBjoern A. Zeeb static int ath11k_start_scan(struct ath11k *ar,
3883dd4f32aeSBjoern A. Zeeb struct scan_req_params *arg)
3884dd4f32aeSBjoern A. Zeeb {
3885dd4f32aeSBjoern A. Zeeb int ret;
3886dd4f32aeSBjoern A. Zeeb unsigned long timeout = 1 * HZ;
3887dd4f32aeSBjoern A. Zeeb
3888dd4f32aeSBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
3889dd4f32aeSBjoern A. Zeeb
3890dd4f32aeSBjoern A. Zeeb if (ath11k_spectral_get_mode(ar) == ATH11K_SPECTRAL_BACKGROUND)
3891dd4f32aeSBjoern A. Zeeb ath11k_spectral_reset_buffer(ar);
3892dd4f32aeSBjoern A. Zeeb
3893dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_send_scan_start_cmd(ar, arg);
3894dd4f32aeSBjoern A. Zeeb if (ret)
3895dd4f32aeSBjoern A. Zeeb return ret;
3896dd4f32aeSBjoern A. Zeeb
3897dd4f32aeSBjoern A. Zeeb if (test_bit(WMI_TLV_SERVICE_11D_OFFLOAD, ar->ab->wmi_ab.svc_map)) {
3898dd4f32aeSBjoern A. Zeeb timeout = 5 * HZ;
3899dd4f32aeSBjoern A. Zeeb
3900dd4f32aeSBjoern A. Zeeb if (ar->supports_6ghz)
3901dd4f32aeSBjoern A. Zeeb timeout += 5 * HZ;
3902dd4f32aeSBjoern A. Zeeb }
3903dd4f32aeSBjoern A. Zeeb
3904dd4f32aeSBjoern A. Zeeb ret = wait_for_completion_timeout(&ar->scan.started, timeout);
3905dd4f32aeSBjoern A. Zeeb if (ret == 0) {
3906dd4f32aeSBjoern A. Zeeb ret = ath11k_scan_stop(ar);
3907dd4f32aeSBjoern A. Zeeb if (ret)
3908dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to stop scan: %d\n", ret);
3909dd4f32aeSBjoern A. Zeeb
3910dd4f32aeSBjoern A. Zeeb return -ETIMEDOUT;
3911dd4f32aeSBjoern A. Zeeb }
3912dd4f32aeSBjoern A. Zeeb
3913dd4f32aeSBjoern A. Zeeb /* If we failed to start the scan, return error code at
3914dd4f32aeSBjoern A. Zeeb * this point. This is probably due to some issue in the
3915dd4f32aeSBjoern A. Zeeb * firmware, but no need to wedge the driver due to that...
3916dd4f32aeSBjoern A. Zeeb */
3917dd4f32aeSBjoern A. Zeeb spin_lock_bh(&ar->data_lock);
3918dd4f32aeSBjoern A. Zeeb if (ar->scan.state == ATH11K_SCAN_IDLE) {
3919dd4f32aeSBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
3920dd4f32aeSBjoern A. Zeeb return -EINVAL;
3921dd4f32aeSBjoern A. Zeeb }
3922dd4f32aeSBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
3923dd4f32aeSBjoern A. Zeeb
3924dd4f32aeSBjoern A. Zeeb return 0;
3925dd4f32aeSBjoern A. Zeeb }
3926dd4f32aeSBjoern A. Zeeb
ath11k_mac_op_hw_scan(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_scan_request * hw_req)3927dd4f32aeSBjoern A. Zeeb static int ath11k_mac_op_hw_scan(struct ieee80211_hw *hw,
3928dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif,
3929dd4f32aeSBjoern A. Zeeb struct ieee80211_scan_request *hw_req)
3930dd4f32aeSBjoern A. Zeeb {
3931dd4f32aeSBjoern A. Zeeb struct ath11k *ar = hw->priv;
3932dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
3933dd4f32aeSBjoern A. Zeeb struct cfg80211_scan_request *req = &hw_req->req;
393428348caeSBjoern A. Zeeb struct scan_req_params *arg = NULL;
3935dd4f32aeSBjoern A. Zeeb int ret = 0;
3936dd4f32aeSBjoern A. Zeeb int i;
393728348caeSBjoern A. Zeeb u32 scan_timeout;
393828348caeSBjoern A. Zeeb
393928348caeSBjoern A. Zeeb /* Firmwares advertising the support of triggering 11D algorithm
394028348caeSBjoern A. Zeeb * on the scan results of a regular scan expects driver to send
394128348caeSBjoern A. Zeeb * WMI_11D_SCAN_START_CMDID before sending WMI_START_SCAN_CMDID.
394228348caeSBjoern A. Zeeb * With this feature, separate 11D scan can be avoided since
394328348caeSBjoern A. Zeeb * regdomain can be determined with the scan results of the
394428348caeSBjoern A. Zeeb * regular scan.
394528348caeSBjoern A. Zeeb */
394628348caeSBjoern A. Zeeb if (ar->state_11d == ATH11K_11D_PREPARING &&
394728348caeSBjoern A. Zeeb test_bit(WMI_TLV_SERVICE_SUPPORT_11D_FOR_HOST_SCAN,
394828348caeSBjoern A. Zeeb ar->ab->wmi_ab.svc_map))
394928348caeSBjoern A. Zeeb ath11k_mac_11d_scan_start(ar, arvif->vdev_id);
3950dd4f32aeSBjoern A. Zeeb
3951dd4f32aeSBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
3952dd4f32aeSBjoern A. Zeeb
3953dd4f32aeSBjoern A. Zeeb spin_lock_bh(&ar->data_lock);
3954dd4f32aeSBjoern A. Zeeb switch (ar->scan.state) {
3955dd4f32aeSBjoern A. Zeeb case ATH11K_SCAN_IDLE:
3956dd4f32aeSBjoern A. Zeeb reinit_completion(&ar->scan.started);
3957dd4f32aeSBjoern A. Zeeb reinit_completion(&ar->scan.completed);
3958dd4f32aeSBjoern A. Zeeb ar->scan.state = ATH11K_SCAN_STARTING;
3959dd4f32aeSBjoern A. Zeeb ar->scan.is_roc = false;
3960dd4f32aeSBjoern A. Zeeb ar->scan.vdev_id = arvif->vdev_id;
3961dd4f32aeSBjoern A. Zeeb ret = 0;
3962dd4f32aeSBjoern A. Zeeb break;
3963dd4f32aeSBjoern A. Zeeb case ATH11K_SCAN_STARTING:
3964dd4f32aeSBjoern A. Zeeb case ATH11K_SCAN_RUNNING:
3965dd4f32aeSBjoern A. Zeeb case ATH11K_SCAN_ABORTING:
3966dd4f32aeSBjoern A. Zeeb ret = -EBUSY;
3967dd4f32aeSBjoern A. Zeeb break;
3968dd4f32aeSBjoern A. Zeeb }
3969dd4f32aeSBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
3970dd4f32aeSBjoern A. Zeeb
3971dd4f32aeSBjoern A. Zeeb if (ret)
3972dd4f32aeSBjoern A. Zeeb goto exit;
3973dd4f32aeSBjoern A. Zeeb
397428348caeSBjoern A. Zeeb arg = kzalloc(sizeof(*arg), GFP_KERNEL);
3975dd4f32aeSBjoern A. Zeeb
397628348caeSBjoern A. Zeeb if (!arg) {
3977dd4f32aeSBjoern A. Zeeb ret = -ENOMEM;
3978dd4f32aeSBjoern A. Zeeb goto exit;
3979dd4f32aeSBjoern A. Zeeb }
398028348caeSBjoern A. Zeeb
398128348caeSBjoern A. Zeeb ath11k_wmi_start_scan_init(ar, arg);
398228348caeSBjoern A. Zeeb arg->vdev_id = arvif->vdev_id;
398328348caeSBjoern A. Zeeb arg->scan_id = ATH11K_SCAN_ID;
398428348caeSBjoern A. Zeeb
398528348caeSBjoern A. Zeeb if (req->ie_len) {
398628348caeSBjoern A. Zeeb arg->extraie.ptr = kmemdup(req->ie, req->ie_len, GFP_KERNEL);
398728348caeSBjoern A. Zeeb if (!arg->extraie.ptr) {
398828348caeSBjoern A. Zeeb ret = -ENOMEM;
398928348caeSBjoern A. Zeeb goto exit;
399028348caeSBjoern A. Zeeb }
399128348caeSBjoern A. Zeeb arg->extraie.len = req->ie_len;
3992dd4f32aeSBjoern A. Zeeb }
3993dd4f32aeSBjoern A. Zeeb
3994dd4f32aeSBjoern A. Zeeb if (req->n_ssids) {
399528348caeSBjoern A. Zeeb arg->num_ssids = req->n_ssids;
399628348caeSBjoern A. Zeeb for (i = 0; i < arg->num_ssids; i++) {
399728348caeSBjoern A. Zeeb arg->ssid[i].length = req->ssids[i].ssid_len;
399828348caeSBjoern A. Zeeb memcpy(&arg->ssid[i].ssid, req->ssids[i].ssid,
3999dd4f32aeSBjoern A. Zeeb req->ssids[i].ssid_len);
4000dd4f32aeSBjoern A. Zeeb }
4001dd4f32aeSBjoern A. Zeeb } else {
400228348caeSBjoern A. Zeeb arg->scan_flags |= WMI_SCAN_FLAG_PASSIVE;
4003dd4f32aeSBjoern A. Zeeb }
4004dd4f32aeSBjoern A. Zeeb
4005dd4f32aeSBjoern A. Zeeb if (req->n_channels) {
400628348caeSBjoern A. Zeeb arg->num_chan = req->n_channels;
400728348caeSBjoern A. Zeeb arg->chan_list = kcalloc(arg->num_chan, sizeof(*arg->chan_list),
4008dd4f32aeSBjoern A. Zeeb GFP_KERNEL);
4009dd4f32aeSBjoern A. Zeeb
401028348caeSBjoern A. Zeeb if (!arg->chan_list) {
4011dd4f32aeSBjoern A. Zeeb ret = -ENOMEM;
4012dd4f32aeSBjoern A. Zeeb goto exit;
4013dd4f32aeSBjoern A. Zeeb }
4014dd4f32aeSBjoern A. Zeeb
401528348caeSBjoern A. Zeeb for (i = 0; i < arg->num_chan; i++) {
401628348caeSBjoern A. Zeeb if (test_bit(WMI_TLV_SERVICE_SCAN_CONFIG_PER_CHANNEL,
401728348caeSBjoern A. Zeeb ar->ab->wmi_ab.svc_map)) {
401828348caeSBjoern A. Zeeb arg->chan_list[i] =
401928348caeSBjoern A. Zeeb u32_encode_bits(req->channels[i]->center_freq,
402028348caeSBjoern A. Zeeb WMI_SCAN_CONFIG_PER_CHANNEL_MASK);
402128348caeSBjoern A. Zeeb
402228348caeSBjoern A. Zeeb /* If NL80211_SCAN_FLAG_COLOCATED_6GHZ is set in scan
402328348caeSBjoern A. Zeeb * flags, then scan all PSC channels in 6 GHz band and
402428348caeSBjoern A. Zeeb * those non-PSC channels where RNR IE is found during
402528348caeSBjoern A. Zeeb * the legacy 2.4/5 GHz scan.
402628348caeSBjoern A. Zeeb * If NL80211_SCAN_FLAG_COLOCATED_6GHZ is not set,
402728348caeSBjoern A. Zeeb * then all channels in 6 GHz will be scanned.
402828348caeSBjoern A. Zeeb */
402928348caeSBjoern A. Zeeb if (req->channels[i]->band == NL80211_BAND_6GHZ &&
403028348caeSBjoern A. Zeeb req->flags & NL80211_SCAN_FLAG_COLOCATED_6GHZ &&
403128348caeSBjoern A. Zeeb !cfg80211_channel_is_psc(req->channels[i]))
403228348caeSBjoern A. Zeeb arg->chan_list[i] |=
403328348caeSBjoern A. Zeeb WMI_SCAN_CH_FLAG_SCAN_ONLY_IF_RNR_FOUND;
403428348caeSBjoern A. Zeeb } else {
403528348caeSBjoern A. Zeeb arg->chan_list[i] = req->channels[i]->center_freq;
403628348caeSBjoern A. Zeeb }
403728348caeSBjoern A. Zeeb }
4038dd4f32aeSBjoern A. Zeeb }
4039dd4f32aeSBjoern A. Zeeb
4040dd4f32aeSBjoern A. Zeeb if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
404128348caeSBjoern A. Zeeb arg->scan_f_add_spoofed_mac_in_probe = 1;
404228348caeSBjoern A. Zeeb ether_addr_copy(arg->mac_addr.addr, req->mac_addr);
404328348caeSBjoern A. Zeeb ether_addr_copy(arg->mac_mask.addr, req->mac_addr_mask);
4044dd4f32aeSBjoern A. Zeeb }
4045dd4f32aeSBjoern A. Zeeb
404628348caeSBjoern A. Zeeb /* if duration is set, default dwell times will be overwritten */
404728348caeSBjoern A. Zeeb if (req->duration) {
404828348caeSBjoern A. Zeeb arg->dwell_time_active = req->duration;
404928348caeSBjoern A. Zeeb arg->dwell_time_active_2g = req->duration;
405028348caeSBjoern A. Zeeb arg->dwell_time_active_6g = req->duration;
405128348caeSBjoern A. Zeeb arg->dwell_time_passive = req->duration;
405228348caeSBjoern A. Zeeb arg->dwell_time_passive_6g = req->duration;
405328348caeSBjoern A. Zeeb arg->burst_duration = req->duration;
405428348caeSBjoern A. Zeeb
405528348caeSBjoern A. Zeeb scan_timeout = min_t(u32, arg->max_rest_time *
405628348caeSBjoern A. Zeeb (arg->num_chan - 1) + (req->duration +
405728348caeSBjoern A. Zeeb ATH11K_SCAN_CHANNEL_SWITCH_WMI_EVT_OVERHEAD) *
405828348caeSBjoern A. Zeeb arg->num_chan, arg->max_scan_time);
405928348caeSBjoern A. Zeeb } else {
406028348caeSBjoern A. Zeeb scan_timeout = arg->max_scan_time;
406128348caeSBjoern A. Zeeb }
406228348caeSBjoern A. Zeeb
406328348caeSBjoern A. Zeeb /* Add a margin to account for event/command processing */
406428348caeSBjoern A. Zeeb scan_timeout += ATH11K_MAC_SCAN_CMD_EVT_OVERHEAD;
406528348caeSBjoern A. Zeeb
406628348caeSBjoern A. Zeeb ret = ath11k_start_scan(ar, arg);
4067dd4f32aeSBjoern A. Zeeb if (ret) {
4068dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to start hw scan: %d\n", ret);
4069dd4f32aeSBjoern A. Zeeb spin_lock_bh(&ar->data_lock);
4070dd4f32aeSBjoern A. Zeeb ar->scan.state = ATH11K_SCAN_IDLE;
4071dd4f32aeSBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
4072dd4f32aeSBjoern A. Zeeb }
4073dd4f32aeSBjoern A. Zeeb
4074dd4f32aeSBjoern A. Zeeb ieee80211_queue_delayed_work(ar->hw, &ar->scan.timeout,
407528348caeSBjoern A. Zeeb msecs_to_jiffies(scan_timeout));
4076dd4f32aeSBjoern A. Zeeb
4077dd4f32aeSBjoern A. Zeeb exit:
407828348caeSBjoern A. Zeeb if (arg) {
407928348caeSBjoern A. Zeeb kfree(arg->chan_list);
408028348caeSBjoern A. Zeeb kfree(arg->extraie.ptr);
408128348caeSBjoern A. Zeeb kfree(arg);
408228348caeSBjoern A. Zeeb }
4083dd4f32aeSBjoern A. Zeeb
4084dd4f32aeSBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
408528348caeSBjoern A. Zeeb
408628348caeSBjoern A. Zeeb if (ar->state_11d == ATH11K_11D_PREPARING)
408728348caeSBjoern A. Zeeb ath11k_mac_11d_scan_start(ar, arvif->vdev_id);
408828348caeSBjoern A. Zeeb
4089dd4f32aeSBjoern A. Zeeb return ret;
4090dd4f32aeSBjoern A. Zeeb }
4091dd4f32aeSBjoern A. Zeeb
ath11k_mac_op_cancel_hw_scan(struct ieee80211_hw * hw,struct ieee80211_vif * vif)4092dd4f32aeSBjoern A. Zeeb static void ath11k_mac_op_cancel_hw_scan(struct ieee80211_hw *hw,
4093dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif)
4094dd4f32aeSBjoern A. Zeeb {
4095dd4f32aeSBjoern A. Zeeb struct ath11k *ar = hw->priv;
4096dd4f32aeSBjoern A. Zeeb
4097dd4f32aeSBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
4098dd4f32aeSBjoern A. Zeeb ath11k_scan_abort(ar);
4099dd4f32aeSBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
4100dd4f32aeSBjoern A. Zeeb
4101dd4f32aeSBjoern A. Zeeb cancel_delayed_work_sync(&ar->scan.timeout);
4102dd4f32aeSBjoern A. Zeeb }
4103dd4f32aeSBjoern A. Zeeb
ath11k_install_key(struct ath11k_vif * arvif,struct ieee80211_key_conf * key,enum set_key_cmd cmd,const u8 * macaddr,u32 flags)4104dd4f32aeSBjoern A. Zeeb static int ath11k_install_key(struct ath11k_vif *arvif,
4105dd4f32aeSBjoern A. Zeeb struct ieee80211_key_conf *key,
4106dd4f32aeSBjoern A. Zeeb enum set_key_cmd cmd,
4107dd4f32aeSBjoern A. Zeeb const u8 *macaddr, u32 flags)
4108dd4f32aeSBjoern A. Zeeb {
4109dd4f32aeSBjoern A. Zeeb int ret;
4110dd4f32aeSBjoern A. Zeeb struct ath11k *ar = arvif->ar;
4111dd4f32aeSBjoern A. Zeeb struct wmi_vdev_install_key_arg arg = {
4112dd4f32aeSBjoern A. Zeeb .vdev_id = arvif->vdev_id,
4113dd4f32aeSBjoern A. Zeeb .key_idx = key->keyidx,
4114dd4f32aeSBjoern A. Zeeb .key_len = key->keylen,
4115dd4f32aeSBjoern A. Zeeb .key_data = key->key,
4116dd4f32aeSBjoern A. Zeeb .key_flags = flags,
4117dd4f32aeSBjoern A. Zeeb .macaddr = macaddr,
4118dd4f32aeSBjoern A. Zeeb };
4119dd4f32aeSBjoern A. Zeeb
4120dd4f32aeSBjoern A. Zeeb lockdep_assert_held(&arvif->ar->conf_mutex);
4121dd4f32aeSBjoern A. Zeeb
4122dd4f32aeSBjoern A. Zeeb reinit_completion(&ar->install_key_done);
4123dd4f32aeSBjoern A. Zeeb
4124dd4f32aeSBjoern A. Zeeb if (test_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags))
4125dd4f32aeSBjoern A. Zeeb return 0;
4126dd4f32aeSBjoern A. Zeeb
4127dd4f32aeSBjoern A. Zeeb if (cmd == DISABLE_KEY) {
4128dd4f32aeSBjoern A. Zeeb arg.key_cipher = WMI_CIPHER_NONE;
4129dd4f32aeSBjoern A. Zeeb arg.key_data = NULL;
4130dd4f32aeSBjoern A. Zeeb goto install;
4131dd4f32aeSBjoern A. Zeeb }
4132dd4f32aeSBjoern A. Zeeb
4133dd4f32aeSBjoern A. Zeeb switch (key->cipher) {
4134dd4f32aeSBjoern A. Zeeb case WLAN_CIPHER_SUITE_CCMP:
4135dd4f32aeSBjoern A. Zeeb arg.key_cipher = WMI_CIPHER_AES_CCM;
4136dd4f32aeSBjoern A. Zeeb /* TODO: Re-check if flag is valid */
4137dd4f32aeSBjoern A. Zeeb key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV_MGMT;
4138dd4f32aeSBjoern A. Zeeb break;
4139dd4f32aeSBjoern A. Zeeb case WLAN_CIPHER_SUITE_TKIP:
4140dd4f32aeSBjoern A. Zeeb arg.key_cipher = WMI_CIPHER_TKIP;
4141dd4f32aeSBjoern A. Zeeb arg.key_txmic_len = 8;
4142dd4f32aeSBjoern A. Zeeb arg.key_rxmic_len = 8;
4143dd4f32aeSBjoern A. Zeeb break;
4144dd4f32aeSBjoern A. Zeeb case WLAN_CIPHER_SUITE_CCMP_256:
4145dd4f32aeSBjoern A. Zeeb arg.key_cipher = WMI_CIPHER_AES_CCM;
4146dd4f32aeSBjoern A. Zeeb break;
4147dd4f32aeSBjoern A. Zeeb case WLAN_CIPHER_SUITE_GCMP:
4148dd4f32aeSBjoern A. Zeeb case WLAN_CIPHER_SUITE_GCMP_256:
4149dd4f32aeSBjoern A. Zeeb arg.key_cipher = WMI_CIPHER_AES_GCM;
4150dd4f32aeSBjoern A. Zeeb break;
4151dd4f32aeSBjoern A. Zeeb default:
4152dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "cipher %d is not supported\n", key->cipher);
4153dd4f32aeSBjoern A. Zeeb return -EOPNOTSUPP;
4154dd4f32aeSBjoern A. Zeeb }
4155dd4f32aeSBjoern A. Zeeb
4156dd4f32aeSBjoern A. Zeeb if (test_bit(ATH11K_FLAG_RAW_MODE, &ar->ab->dev_flags))
4157dd4f32aeSBjoern A. Zeeb key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV |
4158dd4f32aeSBjoern A. Zeeb IEEE80211_KEY_FLAG_RESERVE_TAILROOM;
4159dd4f32aeSBjoern A. Zeeb
4160dd4f32aeSBjoern A. Zeeb install:
4161dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_vdev_install_key(arvif->ar, &arg);
4162dd4f32aeSBjoern A. Zeeb
4163dd4f32aeSBjoern A. Zeeb if (ret)
4164dd4f32aeSBjoern A. Zeeb return ret;
4165dd4f32aeSBjoern A. Zeeb
4166dd4f32aeSBjoern A. Zeeb if (!wait_for_completion_timeout(&ar->install_key_done, 1 * HZ))
4167dd4f32aeSBjoern A. Zeeb return -ETIMEDOUT;
4168dd4f32aeSBjoern A. Zeeb
4169dd4f32aeSBjoern A. Zeeb return ar->install_key_status ? -EINVAL : 0;
4170dd4f32aeSBjoern A. Zeeb }
4171dd4f32aeSBjoern A. Zeeb
ath11k_clear_peer_keys(struct ath11k_vif * arvif,const u8 * addr)4172dd4f32aeSBjoern A. Zeeb static int ath11k_clear_peer_keys(struct ath11k_vif *arvif,
4173dd4f32aeSBjoern A. Zeeb const u8 *addr)
4174dd4f32aeSBjoern A. Zeeb {
4175dd4f32aeSBjoern A. Zeeb struct ath11k *ar = arvif->ar;
4176dd4f32aeSBjoern A. Zeeb struct ath11k_base *ab = ar->ab;
4177dd4f32aeSBjoern A. Zeeb struct ath11k_peer *peer;
4178dd4f32aeSBjoern A. Zeeb int first_errno = 0;
4179dd4f32aeSBjoern A. Zeeb int ret;
4180dd4f32aeSBjoern A. Zeeb int i;
4181dd4f32aeSBjoern A. Zeeb u32 flags = 0;
4182dd4f32aeSBjoern A. Zeeb
4183dd4f32aeSBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
4184dd4f32aeSBjoern A. Zeeb
4185dd4f32aeSBjoern A. Zeeb spin_lock_bh(&ab->base_lock);
4186dd4f32aeSBjoern A. Zeeb peer = ath11k_peer_find(ab, arvif->vdev_id, addr);
4187dd4f32aeSBjoern A. Zeeb spin_unlock_bh(&ab->base_lock);
4188dd4f32aeSBjoern A. Zeeb
4189dd4f32aeSBjoern A. Zeeb if (!peer)
4190dd4f32aeSBjoern A. Zeeb return -ENOENT;
4191dd4f32aeSBjoern A. Zeeb
4192dd4f32aeSBjoern A. Zeeb for (i = 0; i < ARRAY_SIZE(peer->keys); i++) {
4193dd4f32aeSBjoern A. Zeeb if (!peer->keys[i])
4194dd4f32aeSBjoern A. Zeeb continue;
4195dd4f32aeSBjoern A. Zeeb
4196dd4f32aeSBjoern A. Zeeb /* key flags are not required to delete the key */
4197dd4f32aeSBjoern A. Zeeb ret = ath11k_install_key(arvif, peer->keys[i],
4198dd4f32aeSBjoern A. Zeeb DISABLE_KEY, addr, flags);
4199dd4f32aeSBjoern A. Zeeb if (ret < 0 && first_errno == 0)
4200dd4f32aeSBjoern A. Zeeb first_errno = ret;
4201dd4f32aeSBjoern A. Zeeb
4202dd4f32aeSBjoern A. Zeeb if (ret < 0)
4203dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, "failed to remove peer key %d: %d\n",
4204dd4f32aeSBjoern A. Zeeb i, ret);
4205dd4f32aeSBjoern A. Zeeb
4206dd4f32aeSBjoern A. Zeeb spin_lock_bh(&ab->base_lock);
4207dd4f32aeSBjoern A. Zeeb peer->keys[i] = NULL;
4208dd4f32aeSBjoern A. Zeeb spin_unlock_bh(&ab->base_lock);
4209dd4f32aeSBjoern A. Zeeb }
4210dd4f32aeSBjoern A. Zeeb
4211dd4f32aeSBjoern A. Zeeb return first_errno;
4212dd4f32aeSBjoern A. Zeeb }
4213dd4f32aeSBjoern A. Zeeb
ath11k_mac_op_set_key(struct ieee80211_hw * hw,enum set_key_cmd cmd,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct ieee80211_key_conf * key)4214dd4f32aeSBjoern A. Zeeb static int ath11k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
4215dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif, struct ieee80211_sta *sta,
4216dd4f32aeSBjoern A. Zeeb struct ieee80211_key_conf *key)
4217dd4f32aeSBjoern A. Zeeb {
4218dd4f32aeSBjoern A. Zeeb struct ath11k *ar = hw->priv;
4219dd4f32aeSBjoern A. Zeeb struct ath11k_base *ab = ar->ab;
4220dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
4221dd4f32aeSBjoern A. Zeeb struct ath11k_peer *peer;
4222dd4f32aeSBjoern A. Zeeb struct ath11k_sta *arsta;
4223dd4f32aeSBjoern A. Zeeb const u8 *peer_addr;
4224dd4f32aeSBjoern A. Zeeb int ret = 0;
4225dd4f32aeSBjoern A. Zeeb u32 flags = 0;
4226dd4f32aeSBjoern A. Zeeb
4227dd4f32aeSBjoern A. Zeeb /* BIP needs to be done in software */
4228dd4f32aeSBjoern A. Zeeb if (key->cipher == WLAN_CIPHER_SUITE_AES_CMAC ||
4229dd4f32aeSBjoern A. Zeeb key->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 ||
4230dd4f32aeSBjoern A. Zeeb key->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256 ||
4231dd4f32aeSBjoern A. Zeeb key->cipher == WLAN_CIPHER_SUITE_BIP_CMAC_256)
4232dd4f32aeSBjoern A. Zeeb return 1;
4233dd4f32aeSBjoern A. Zeeb
4234dd4f32aeSBjoern A. Zeeb if (test_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags))
4235dd4f32aeSBjoern A. Zeeb return 1;
4236dd4f32aeSBjoern A. Zeeb
4237dd4f32aeSBjoern A. Zeeb if (key->keyidx > WMI_MAX_KEY_INDEX)
4238dd4f32aeSBjoern A. Zeeb return -ENOSPC;
4239dd4f32aeSBjoern A. Zeeb
4240dd4f32aeSBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
4241dd4f32aeSBjoern A. Zeeb
4242dd4f32aeSBjoern A. Zeeb if (sta)
4243dd4f32aeSBjoern A. Zeeb peer_addr = sta->addr;
4244dd4f32aeSBjoern A. Zeeb else if (arvif->vdev_type == WMI_VDEV_TYPE_STA)
4245dd4f32aeSBjoern A. Zeeb peer_addr = vif->bss_conf.bssid;
4246dd4f32aeSBjoern A. Zeeb else
4247dd4f32aeSBjoern A. Zeeb peer_addr = vif->addr;
4248dd4f32aeSBjoern A. Zeeb
4249dd4f32aeSBjoern A. Zeeb key->hw_key_idx = key->keyidx;
4250dd4f32aeSBjoern A. Zeeb
4251dd4f32aeSBjoern A. Zeeb /* the peer should not disappear in mid-way (unless FW goes awry) since
4252dd4f32aeSBjoern A. Zeeb * we already hold conf_mutex. we just make sure its there now.
4253dd4f32aeSBjoern A. Zeeb */
4254dd4f32aeSBjoern A. Zeeb spin_lock_bh(&ab->base_lock);
4255dd4f32aeSBjoern A. Zeeb peer = ath11k_peer_find(ab, arvif->vdev_id, peer_addr);
4256dd4f32aeSBjoern A. Zeeb
4257dd4f32aeSBjoern A. Zeeb /* flush the fragments cache during key (re)install to
4258dd4f32aeSBjoern A. Zeeb * ensure all frags in the new frag list belong to the same key.
4259dd4f32aeSBjoern A. Zeeb */
4260dd4f32aeSBjoern A. Zeeb if (peer && sta && cmd == SET_KEY)
4261dd4f32aeSBjoern A. Zeeb ath11k_peer_frags_flush(ar, peer);
4262dd4f32aeSBjoern A. Zeeb spin_unlock_bh(&ab->base_lock);
4263dd4f32aeSBjoern A. Zeeb
4264dd4f32aeSBjoern A. Zeeb if (!peer) {
4265dd4f32aeSBjoern A. Zeeb if (cmd == SET_KEY) {
4266dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, "cannot install key for non-existent peer %pM\n",
4267dd4f32aeSBjoern A. Zeeb peer_addr);
4268dd4f32aeSBjoern A. Zeeb ret = -EOPNOTSUPP;
4269dd4f32aeSBjoern A. Zeeb goto exit;
4270dd4f32aeSBjoern A. Zeeb } else {
4271dd4f32aeSBjoern A. Zeeb /* if the peer doesn't exist there is no key to disable
4272dd4f32aeSBjoern A. Zeeb * anymore
4273dd4f32aeSBjoern A. Zeeb */
4274dd4f32aeSBjoern A. Zeeb goto exit;
4275dd4f32aeSBjoern A. Zeeb }
4276dd4f32aeSBjoern A. Zeeb }
4277dd4f32aeSBjoern A. Zeeb
4278dd4f32aeSBjoern A. Zeeb if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
4279dd4f32aeSBjoern A. Zeeb flags |= WMI_KEY_PAIRWISE;
4280dd4f32aeSBjoern A. Zeeb else
4281dd4f32aeSBjoern A. Zeeb flags |= WMI_KEY_GROUP;
4282dd4f32aeSBjoern A. Zeeb
4283dd4f32aeSBjoern A. Zeeb ret = ath11k_install_key(arvif, key, cmd, peer_addr, flags);
4284dd4f32aeSBjoern A. Zeeb if (ret) {
4285dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, "ath11k_install_key failed (%d)\n", ret);
4286dd4f32aeSBjoern A. Zeeb goto exit;
4287dd4f32aeSBjoern A. Zeeb }
4288dd4f32aeSBjoern A. Zeeb
4289dd4f32aeSBjoern A. Zeeb ret = ath11k_dp_peer_rx_pn_replay_config(arvif, peer_addr, cmd, key);
4290dd4f32aeSBjoern A. Zeeb if (ret) {
4291dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, "failed to offload PN replay detection %d\n", ret);
4292dd4f32aeSBjoern A. Zeeb goto exit;
4293dd4f32aeSBjoern A. Zeeb }
4294dd4f32aeSBjoern A. Zeeb
4295dd4f32aeSBjoern A. Zeeb spin_lock_bh(&ab->base_lock);
4296dd4f32aeSBjoern A. Zeeb peer = ath11k_peer_find(ab, arvif->vdev_id, peer_addr);
4297dd4f32aeSBjoern A. Zeeb if (peer && cmd == SET_KEY) {
4298dd4f32aeSBjoern A. Zeeb peer->keys[key->keyidx] = key;
4299dd4f32aeSBjoern A. Zeeb if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
4300dd4f32aeSBjoern A. Zeeb peer->ucast_keyidx = key->keyidx;
4301dd4f32aeSBjoern A. Zeeb peer->sec_type = ath11k_dp_tx_get_encrypt_type(key->cipher);
4302dd4f32aeSBjoern A. Zeeb } else {
4303dd4f32aeSBjoern A. Zeeb peer->mcast_keyidx = key->keyidx;
4304dd4f32aeSBjoern A. Zeeb peer->sec_type_grp = ath11k_dp_tx_get_encrypt_type(key->cipher);
4305dd4f32aeSBjoern A. Zeeb }
4306dd4f32aeSBjoern A. Zeeb } else if (peer && cmd == DISABLE_KEY) {
4307dd4f32aeSBjoern A. Zeeb peer->keys[key->keyidx] = NULL;
4308dd4f32aeSBjoern A. Zeeb if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
4309dd4f32aeSBjoern A. Zeeb peer->ucast_keyidx = 0;
4310dd4f32aeSBjoern A. Zeeb else
4311dd4f32aeSBjoern A. Zeeb peer->mcast_keyidx = 0;
4312dd4f32aeSBjoern A. Zeeb } else if (!peer)
4313dd4f32aeSBjoern A. Zeeb /* impossible unless FW goes crazy */
4314dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, "peer %pM disappeared!\n", peer_addr);
4315dd4f32aeSBjoern A. Zeeb
4316dd4f32aeSBjoern A. Zeeb if (sta) {
4317dd4f32aeSBjoern A. Zeeb arsta = (struct ath11k_sta *)sta->drv_priv;
4318dd4f32aeSBjoern A. Zeeb
4319dd4f32aeSBjoern A. Zeeb switch (key->cipher) {
4320dd4f32aeSBjoern A. Zeeb case WLAN_CIPHER_SUITE_TKIP:
4321dd4f32aeSBjoern A. Zeeb case WLAN_CIPHER_SUITE_CCMP:
4322dd4f32aeSBjoern A. Zeeb case WLAN_CIPHER_SUITE_CCMP_256:
4323dd4f32aeSBjoern A. Zeeb case WLAN_CIPHER_SUITE_GCMP:
4324dd4f32aeSBjoern A. Zeeb case WLAN_CIPHER_SUITE_GCMP_256:
4325dd4f32aeSBjoern A. Zeeb if (cmd == SET_KEY)
4326dd4f32aeSBjoern A. Zeeb arsta->pn_type = HAL_PN_TYPE_WPA;
4327dd4f32aeSBjoern A. Zeeb else
4328dd4f32aeSBjoern A. Zeeb arsta->pn_type = HAL_PN_TYPE_NONE;
4329dd4f32aeSBjoern A. Zeeb break;
4330dd4f32aeSBjoern A. Zeeb default:
4331dd4f32aeSBjoern A. Zeeb arsta->pn_type = HAL_PN_TYPE_NONE;
4332dd4f32aeSBjoern A. Zeeb break;
4333dd4f32aeSBjoern A. Zeeb }
4334dd4f32aeSBjoern A. Zeeb }
4335dd4f32aeSBjoern A. Zeeb
4336dd4f32aeSBjoern A. Zeeb spin_unlock_bh(&ab->base_lock);
4337dd4f32aeSBjoern A. Zeeb
4338dd4f32aeSBjoern A. Zeeb exit:
4339dd4f32aeSBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
4340dd4f32aeSBjoern A. Zeeb return ret;
4341dd4f32aeSBjoern A. Zeeb }
4342dd4f32aeSBjoern A. Zeeb
4343dd4f32aeSBjoern A. Zeeb static int
ath11k_mac_bitrate_mask_num_ht_rates(struct ath11k * ar,enum nl80211_band band,const struct cfg80211_bitrate_mask * mask)434428348caeSBjoern A. Zeeb ath11k_mac_bitrate_mask_num_ht_rates(struct ath11k *ar,
434528348caeSBjoern A. Zeeb enum nl80211_band band,
434628348caeSBjoern A. Zeeb const struct cfg80211_bitrate_mask *mask)
434728348caeSBjoern A. Zeeb {
434828348caeSBjoern A. Zeeb int num_rates = 0;
434928348caeSBjoern A. Zeeb int i;
435028348caeSBjoern A. Zeeb
435128348caeSBjoern A. Zeeb for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++)
435228348caeSBjoern A. Zeeb num_rates += hweight8(mask->control[band].ht_mcs[i]);
435328348caeSBjoern A. Zeeb
435428348caeSBjoern A. Zeeb return num_rates;
435528348caeSBjoern A. Zeeb }
435628348caeSBjoern A. Zeeb
435728348caeSBjoern A. Zeeb static int
ath11k_mac_bitrate_mask_num_vht_rates(struct ath11k * ar,enum nl80211_band band,const struct cfg80211_bitrate_mask * mask)4358dd4f32aeSBjoern A. Zeeb ath11k_mac_bitrate_mask_num_vht_rates(struct ath11k *ar,
4359dd4f32aeSBjoern A. Zeeb enum nl80211_band band,
4360dd4f32aeSBjoern A. Zeeb const struct cfg80211_bitrate_mask *mask)
4361dd4f32aeSBjoern A. Zeeb {
4362dd4f32aeSBjoern A. Zeeb int num_rates = 0;
4363dd4f32aeSBjoern A. Zeeb int i;
4364dd4f32aeSBjoern A. Zeeb
4365dd4f32aeSBjoern A. Zeeb for (i = 0; i < ARRAY_SIZE(mask->control[band].vht_mcs); i++)
4366dd4f32aeSBjoern A. Zeeb num_rates += hweight16(mask->control[band].vht_mcs[i]);
4367dd4f32aeSBjoern A. Zeeb
4368dd4f32aeSBjoern A. Zeeb return num_rates;
4369dd4f32aeSBjoern A. Zeeb }
4370dd4f32aeSBjoern A. Zeeb
4371dd4f32aeSBjoern A. Zeeb static int
ath11k_mac_bitrate_mask_num_he_rates(struct ath11k * ar,enum nl80211_band band,const struct cfg80211_bitrate_mask * mask)4372dd4f32aeSBjoern A. Zeeb ath11k_mac_bitrate_mask_num_he_rates(struct ath11k *ar,
4373dd4f32aeSBjoern A. Zeeb enum nl80211_band band,
4374dd4f32aeSBjoern A. Zeeb const struct cfg80211_bitrate_mask *mask)
4375dd4f32aeSBjoern A. Zeeb {
4376dd4f32aeSBjoern A. Zeeb int num_rates = 0;
4377dd4f32aeSBjoern A. Zeeb int i;
4378dd4f32aeSBjoern A. Zeeb
4379dd4f32aeSBjoern A. Zeeb for (i = 0; i < ARRAY_SIZE(mask->control[band].he_mcs); i++)
4380dd4f32aeSBjoern A. Zeeb num_rates += hweight16(mask->control[band].he_mcs[i]);
4381dd4f32aeSBjoern A. Zeeb
4382dd4f32aeSBjoern A. Zeeb return num_rates;
4383dd4f32aeSBjoern A. Zeeb }
4384dd4f32aeSBjoern A. Zeeb
4385dd4f32aeSBjoern A. Zeeb static int
ath11k_mac_set_peer_vht_fixed_rate(struct ath11k_vif * arvif,struct ieee80211_sta * sta,const struct cfg80211_bitrate_mask * mask,enum nl80211_band band)4386dd4f32aeSBjoern A. Zeeb ath11k_mac_set_peer_vht_fixed_rate(struct ath11k_vif *arvif,
4387dd4f32aeSBjoern A. Zeeb struct ieee80211_sta *sta,
4388dd4f32aeSBjoern A. Zeeb const struct cfg80211_bitrate_mask *mask,
4389dd4f32aeSBjoern A. Zeeb enum nl80211_band band)
4390dd4f32aeSBjoern A. Zeeb {
4391dd4f32aeSBjoern A. Zeeb struct ath11k *ar = arvif->ar;
4392dd4f32aeSBjoern A. Zeeb u8 vht_rate, nss;
4393dd4f32aeSBjoern A. Zeeb u32 rate_code;
4394dd4f32aeSBjoern A. Zeeb int ret, i;
4395dd4f32aeSBjoern A. Zeeb
4396dd4f32aeSBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
4397dd4f32aeSBjoern A. Zeeb
4398dd4f32aeSBjoern A. Zeeb nss = 0;
4399dd4f32aeSBjoern A. Zeeb
4400dd4f32aeSBjoern A. Zeeb for (i = 0; i < ARRAY_SIZE(mask->control[band].vht_mcs); i++) {
4401dd4f32aeSBjoern A. Zeeb if (hweight16(mask->control[band].vht_mcs[i]) == 1) {
4402dd4f32aeSBjoern A. Zeeb nss = i + 1;
4403dd4f32aeSBjoern A. Zeeb vht_rate = ffs(mask->control[band].vht_mcs[i]) - 1;
4404dd4f32aeSBjoern A. Zeeb }
4405dd4f32aeSBjoern A. Zeeb }
4406dd4f32aeSBjoern A. Zeeb
4407dd4f32aeSBjoern A. Zeeb if (!nss) {
4408dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "No single VHT Fixed rate found to set for %pM",
4409dd4f32aeSBjoern A. Zeeb sta->addr);
4410dd4f32aeSBjoern A. Zeeb return -EINVAL;
4411dd4f32aeSBjoern A. Zeeb }
4412dd4f32aeSBjoern A. Zeeb
4413dd4f32aeSBjoern A. Zeeb /* Avoid updating invalid nss as fixed rate*/
4414dd4f32aeSBjoern A. Zeeb if (nss > sta->deflink.rx_nss)
4415dd4f32aeSBjoern A. Zeeb return -EINVAL;
4416dd4f32aeSBjoern A. Zeeb
4417dd4f32aeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
4418dd4f32aeSBjoern A. Zeeb "Setting Fixed VHT Rate for peer %pM. Device will not switch to any other selected rates",
4419dd4f32aeSBjoern A. Zeeb sta->addr);
4420dd4f32aeSBjoern A. Zeeb
4421dd4f32aeSBjoern A. Zeeb rate_code = ATH11K_HW_RATE_CODE(vht_rate, nss - 1,
4422dd4f32aeSBjoern A. Zeeb WMI_RATE_PREAMBLE_VHT);
4423dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_set_peer_param(ar, sta->addr,
4424dd4f32aeSBjoern A. Zeeb arvif->vdev_id,
4425dd4f32aeSBjoern A. Zeeb WMI_PEER_PARAM_FIXED_RATE,
4426dd4f32aeSBjoern A. Zeeb rate_code);
4427dd4f32aeSBjoern A. Zeeb if (ret)
4428dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab,
4429dd4f32aeSBjoern A. Zeeb "failed to update STA %pM Fixed Rate %d: %d\n",
4430dd4f32aeSBjoern A. Zeeb sta->addr, rate_code, ret);
4431dd4f32aeSBjoern A. Zeeb
4432dd4f32aeSBjoern A. Zeeb return ret;
4433dd4f32aeSBjoern A. Zeeb }
4434dd4f32aeSBjoern A. Zeeb
4435dd4f32aeSBjoern A. Zeeb static int
ath11k_mac_set_peer_he_fixed_rate(struct ath11k_vif * arvif,struct ieee80211_sta * sta,const struct cfg80211_bitrate_mask * mask,enum nl80211_band band)4436dd4f32aeSBjoern A. Zeeb ath11k_mac_set_peer_he_fixed_rate(struct ath11k_vif *arvif,
4437dd4f32aeSBjoern A. Zeeb struct ieee80211_sta *sta,
4438dd4f32aeSBjoern A. Zeeb const struct cfg80211_bitrate_mask *mask,
4439dd4f32aeSBjoern A. Zeeb enum nl80211_band band)
4440dd4f32aeSBjoern A. Zeeb {
4441dd4f32aeSBjoern A. Zeeb struct ath11k *ar = arvif->ar;
4442dd4f32aeSBjoern A. Zeeb u8 he_rate, nss;
4443dd4f32aeSBjoern A. Zeeb u32 rate_code;
4444dd4f32aeSBjoern A. Zeeb int ret, i;
4445dd4f32aeSBjoern A. Zeeb
4446dd4f32aeSBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
4447dd4f32aeSBjoern A. Zeeb
4448dd4f32aeSBjoern A. Zeeb nss = 0;
4449dd4f32aeSBjoern A. Zeeb
4450dd4f32aeSBjoern A. Zeeb for (i = 0; i < ARRAY_SIZE(mask->control[band].he_mcs); i++) {
4451dd4f32aeSBjoern A. Zeeb if (hweight16(mask->control[band].he_mcs[i]) == 1) {
4452dd4f32aeSBjoern A. Zeeb nss = i + 1;
4453dd4f32aeSBjoern A. Zeeb he_rate = ffs(mask->control[band].he_mcs[i]) - 1;
4454dd4f32aeSBjoern A. Zeeb }
4455dd4f32aeSBjoern A. Zeeb }
4456dd4f32aeSBjoern A. Zeeb
4457dd4f32aeSBjoern A. Zeeb if (!nss) {
4458dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "No single he fixed rate found to set for %pM",
4459dd4f32aeSBjoern A. Zeeb sta->addr);
4460dd4f32aeSBjoern A. Zeeb return -EINVAL;
4461dd4f32aeSBjoern A. Zeeb }
4462dd4f32aeSBjoern A. Zeeb
4463dd4f32aeSBjoern A. Zeeb /* Avoid updating invalid nss as fixed rate */
4464dd4f32aeSBjoern A. Zeeb if (nss > sta->deflink.rx_nss)
4465dd4f32aeSBjoern A. Zeeb return -EINVAL;
4466dd4f32aeSBjoern A. Zeeb
4467dd4f32aeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
446828348caeSBjoern A. Zeeb "setting fixed he rate for peer %pM, device will not switch to any other selected rates",
4469dd4f32aeSBjoern A. Zeeb sta->addr);
4470dd4f32aeSBjoern A. Zeeb
4471dd4f32aeSBjoern A. Zeeb rate_code = ATH11K_HW_RATE_CODE(he_rate, nss - 1,
4472dd4f32aeSBjoern A. Zeeb WMI_RATE_PREAMBLE_HE);
4473dd4f32aeSBjoern A. Zeeb
4474dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_set_peer_param(ar, sta->addr,
4475dd4f32aeSBjoern A. Zeeb arvif->vdev_id,
4476dd4f32aeSBjoern A. Zeeb WMI_PEER_PARAM_FIXED_RATE,
4477dd4f32aeSBjoern A. Zeeb rate_code);
4478dd4f32aeSBjoern A. Zeeb if (ret)
4479dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab,
4480dd4f32aeSBjoern A. Zeeb "failed to update sta %pM fixed rate %d: %d\n",
4481dd4f32aeSBjoern A. Zeeb sta->addr, rate_code, ret);
4482dd4f32aeSBjoern A. Zeeb
4483dd4f32aeSBjoern A. Zeeb return ret;
4484dd4f32aeSBjoern A. Zeeb }
4485dd4f32aeSBjoern A. Zeeb
448628348caeSBjoern A. Zeeb static int
ath11k_mac_set_peer_ht_fixed_rate(struct ath11k_vif * arvif,struct ieee80211_sta * sta,const struct cfg80211_bitrate_mask * mask,enum nl80211_band band)448728348caeSBjoern A. Zeeb ath11k_mac_set_peer_ht_fixed_rate(struct ath11k_vif *arvif,
448828348caeSBjoern A. Zeeb struct ieee80211_sta *sta,
448928348caeSBjoern A. Zeeb const struct cfg80211_bitrate_mask *mask,
449028348caeSBjoern A. Zeeb enum nl80211_band band)
449128348caeSBjoern A. Zeeb {
449228348caeSBjoern A. Zeeb struct ath11k *ar = arvif->ar;
449328348caeSBjoern A. Zeeb u8 ht_rate, nss = 0;
449428348caeSBjoern A. Zeeb u32 rate_code;
449528348caeSBjoern A. Zeeb int ret, i;
449628348caeSBjoern A. Zeeb
449728348caeSBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
449828348caeSBjoern A. Zeeb
449928348caeSBjoern A. Zeeb for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++) {
450028348caeSBjoern A. Zeeb if (hweight8(mask->control[band].ht_mcs[i]) == 1) {
450128348caeSBjoern A. Zeeb nss = i + 1;
450228348caeSBjoern A. Zeeb ht_rate = ffs(mask->control[band].ht_mcs[i]) - 1;
450328348caeSBjoern A. Zeeb }
450428348caeSBjoern A. Zeeb }
450528348caeSBjoern A. Zeeb
450628348caeSBjoern A. Zeeb if (!nss) {
450728348caeSBjoern A. Zeeb ath11k_warn(ar->ab, "No single HT Fixed rate found to set for %pM",
450828348caeSBjoern A. Zeeb sta->addr);
450928348caeSBjoern A. Zeeb return -EINVAL;
451028348caeSBjoern A. Zeeb }
451128348caeSBjoern A. Zeeb
451228348caeSBjoern A. Zeeb /* Avoid updating invalid nss as fixed rate*/
451328348caeSBjoern A. Zeeb if (nss > sta->deflink.rx_nss)
451428348caeSBjoern A. Zeeb return -EINVAL;
451528348caeSBjoern A. Zeeb
451628348caeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
451728348caeSBjoern A. Zeeb "Setting Fixed HT Rate for peer %pM. Device will not switch to any other selected rates",
451828348caeSBjoern A. Zeeb sta->addr);
451928348caeSBjoern A. Zeeb
452028348caeSBjoern A. Zeeb rate_code = ATH11K_HW_RATE_CODE(ht_rate, nss - 1,
452128348caeSBjoern A. Zeeb WMI_RATE_PREAMBLE_HT);
452228348caeSBjoern A. Zeeb ret = ath11k_wmi_set_peer_param(ar, sta->addr,
452328348caeSBjoern A. Zeeb arvif->vdev_id,
452428348caeSBjoern A. Zeeb WMI_PEER_PARAM_FIXED_RATE,
452528348caeSBjoern A. Zeeb rate_code);
452628348caeSBjoern A. Zeeb if (ret)
452728348caeSBjoern A. Zeeb ath11k_warn(ar->ab,
452828348caeSBjoern A. Zeeb "failed to update STA %pM HT Fixed Rate %d: %d\n",
452928348caeSBjoern A. Zeeb sta->addr, rate_code, ret);
453028348caeSBjoern A. Zeeb
453128348caeSBjoern A. Zeeb return ret;
453228348caeSBjoern A. Zeeb }
453328348caeSBjoern A. Zeeb
ath11k_station_assoc(struct ath11k * ar,struct ieee80211_vif * vif,struct ieee80211_sta * sta,bool reassoc)4534dd4f32aeSBjoern A. Zeeb static int ath11k_station_assoc(struct ath11k *ar,
4535dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif,
4536dd4f32aeSBjoern A. Zeeb struct ieee80211_sta *sta,
4537dd4f32aeSBjoern A. Zeeb bool reassoc)
4538dd4f32aeSBjoern A. Zeeb {
4539dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
4540dd4f32aeSBjoern A. Zeeb struct peer_assoc_params peer_arg;
4541dd4f32aeSBjoern A. Zeeb int ret = 0;
4542dd4f32aeSBjoern A. Zeeb struct cfg80211_chan_def def;
4543dd4f32aeSBjoern A. Zeeb enum nl80211_band band;
4544dd4f32aeSBjoern A. Zeeb struct cfg80211_bitrate_mask *mask;
454528348caeSBjoern A. Zeeb u8 num_ht_rates, num_vht_rates, num_he_rates;
4546dd4f32aeSBjoern A. Zeeb
4547dd4f32aeSBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
4548dd4f32aeSBjoern A. Zeeb
4549dd4f32aeSBjoern A. Zeeb if (WARN_ON(ath11k_mac_vif_chan(vif, &def)))
4550dd4f32aeSBjoern A. Zeeb return -EPERM;
4551dd4f32aeSBjoern A. Zeeb
4552dd4f32aeSBjoern A. Zeeb band = def.chan->band;
4553dd4f32aeSBjoern A. Zeeb mask = &arvif->bitrate_mask;
4554dd4f32aeSBjoern A. Zeeb
4555dd4f32aeSBjoern A. Zeeb ath11k_peer_assoc_prepare(ar, vif, sta, &peer_arg, reassoc);
4556dd4f32aeSBjoern A. Zeeb
4557dd4f32aeSBjoern A. Zeeb peer_arg.is_assoc = true;
4558dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_send_peer_assoc_cmd(ar, &peer_arg);
4559dd4f32aeSBjoern A. Zeeb if (ret) {
4560dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to run peer assoc for STA %pM vdev %i: %d\n",
4561dd4f32aeSBjoern A. Zeeb sta->addr, arvif->vdev_id, ret);
4562dd4f32aeSBjoern A. Zeeb return ret;
4563dd4f32aeSBjoern A. Zeeb }
4564dd4f32aeSBjoern A. Zeeb
4565dd4f32aeSBjoern A. Zeeb if (!wait_for_completion_timeout(&ar->peer_assoc_done, 1 * HZ)) {
4566dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to get peer assoc conf event for %pM vdev %i\n",
4567dd4f32aeSBjoern A. Zeeb sta->addr, arvif->vdev_id);
4568dd4f32aeSBjoern A. Zeeb return -ETIMEDOUT;
4569dd4f32aeSBjoern A. Zeeb }
4570dd4f32aeSBjoern A. Zeeb
4571dd4f32aeSBjoern A. Zeeb num_vht_rates = ath11k_mac_bitrate_mask_num_vht_rates(ar, band, mask);
4572dd4f32aeSBjoern A. Zeeb num_he_rates = ath11k_mac_bitrate_mask_num_he_rates(ar, band, mask);
457328348caeSBjoern A. Zeeb num_ht_rates = ath11k_mac_bitrate_mask_num_ht_rates(ar, band, mask);
4574dd4f32aeSBjoern A. Zeeb
4575dd4f32aeSBjoern A. Zeeb /* If single VHT/HE rate is configured (by set_bitrate_mask()),
4576dd4f32aeSBjoern A. Zeeb * peer_assoc will disable VHT/HE. This is now enabled by a peer specific
4577dd4f32aeSBjoern A. Zeeb * fixed param.
4578dd4f32aeSBjoern A. Zeeb * Note that all other rates and NSS will be disabled for this peer.
4579dd4f32aeSBjoern A. Zeeb */
4580dd4f32aeSBjoern A. Zeeb if (sta->deflink.vht_cap.vht_supported && num_vht_rates == 1) {
4581dd4f32aeSBjoern A. Zeeb ret = ath11k_mac_set_peer_vht_fixed_rate(arvif, sta, mask,
4582dd4f32aeSBjoern A. Zeeb band);
4583dd4f32aeSBjoern A. Zeeb if (ret)
4584dd4f32aeSBjoern A. Zeeb return ret;
4585dd4f32aeSBjoern A. Zeeb } else if (sta->deflink.he_cap.has_he && num_he_rates == 1) {
4586dd4f32aeSBjoern A. Zeeb ret = ath11k_mac_set_peer_he_fixed_rate(arvif, sta, mask,
4587dd4f32aeSBjoern A. Zeeb band);
4588dd4f32aeSBjoern A. Zeeb if (ret)
4589dd4f32aeSBjoern A. Zeeb return ret;
459028348caeSBjoern A. Zeeb } else if (sta->deflink.ht_cap.ht_supported && num_ht_rates == 1) {
459128348caeSBjoern A. Zeeb ret = ath11k_mac_set_peer_ht_fixed_rate(arvif, sta, mask,
459228348caeSBjoern A. Zeeb band);
459328348caeSBjoern A. Zeeb if (ret)
459428348caeSBjoern A. Zeeb return ret;
4595dd4f32aeSBjoern A. Zeeb }
4596dd4f32aeSBjoern A. Zeeb
4597dd4f32aeSBjoern A. Zeeb /* Re-assoc is run only to update supported rates for given station. It
4598dd4f32aeSBjoern A. Zeeb * doesn't make much sense to reconfigure the peer completely.
4599dd4f32aeSBjoern A. Zeeb */
4600dd4f32aeSBjoern A. Zeeb if (reassoc)
4601dd4f32aeSBjoern A. Zeeb return 0;
4602dd4f32aeSBjoern A. Zeeb
4603dd4f32aeSBjoern A. Zeeb ret = ath11k_setup_peer_smps(ar, arvif, sta->addr,
4604dd4f32aeSBjoern A. Zeeb &sta->deflink.ht_cap,
4605dd4f32aeSBjoern A. Zeeb le16_to_cpu(sta->deflink.he_6ghz_capa.capa));
4606dd4f32aeSBjoern A. Zeeb if (ret) {
4607dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to setup peer SMPS for vdev %d: %d\n",
4608dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ret);
4609dd4f32aeSBjoern A. Zeeb return ret;
4610dd4f32aeSBjoern A. Zeeb }
4611dd4f32aeSBjoern A. Zeeb
4612dd4f32aeSBjoern A. Zeeb if (!sta->wme) {
4613dd4f32aeSBjoern A. Zeeb arvif->num_legacy_stations++;
4614dd4f32aeSBjoern A. Zeeb ret = ath11k_recalc_rtscts_prot(arvif);
4615dd4f32aeSBjoern A. Zeeb if (ret)
4616dd4f32aeSBjoern A. Zeeb return ret;
4617dd4f32aeSBjoern A. Zeeb }
4618dd4f32aeSBjoern A. Zeeb
4619dd4f32aeSBjoern A. Zeeb if (sta->wme && sta->uapsd_queues) {
4620dd4f32aeSBjoern A. Zeeb ret = ath11k_peer_assoc_qos_ap(ar, arvif, sta);
4621dd4f32aeSBjoern A. Zeeb if (ret) {
4622dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to set qos params for STA %pM for vdev %i: %d\n",
4623dd4f32aeSBjoern A. Zeeb sta->addr, arvif->vdev_id, ret);
4624dd4f32aeSBjoern A. Zeeb return ret;
4625dd4f32aeSBjoern A. Zeeb }
4626dd4f32aeSBjoern A. Zeeb }
4627dd4f32aeSBjoern A. Zeeb
4628dd4f32aeSBjoern A. Zeeb return 0;
4629dd4f32aeSBjoern A. Zeeb }
4630dd4f32aeSBjoern A. Zeeb
ath11k_station_disassoc(struct ath11k * ar,struct ieee80211_vif * vif,struct ieee80211_sta * sta)4631dd4f32aeSBjoern A. Zeeb static int ath11k_station_disassoc(struct ath11k *ar,
4632dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif,
4633dd4f32aeSBjoern A. Zeeb struct ieee80211_sta *sta)
4634dd4f32aeSBjoern A. Zeeb {
4635dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif = (void *)vif->drv_priv;
4636dd4f32aeSBjoern A. Zeeb int ret = 0;
4637dd4f32aeSBjoern A. Zeeb
4638dd4f32aeSBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
4639dd4f32aeSBjoern A. Zeeb
4640dd4f32aeSBjoern A. Zeeb if (!sta->wme) {
4641dd4f32aeSBjoern A. Zeeb arvif->num_legacy_stations--;
4642dd4f32aeSBjoern A. Zeeb ret = ath11k_recalc_rtscts_prot(arvif);
4643dd4f32aeSBjoern A. Zeeb if (ret)
4644dd4f32aeSBjoern A. Zeeb return ret;
4645dd4f32aeSBjoern A. Zeeb }
4646dd4f32aeSBjoern A. Zeeb
4647dd4f32aeSBjoern A. Zeeb ret = ath11k_clear_peer_keys(arvif, sta->addr);
4648dd4f32aeSBjoern A. Zeeb if (ret) {
4649dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to clear all peer keys for vdev %i: %d\n",
4650dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ret);
4651dd4f32aeSBjoern A. Zeeb return ret;
4652dd4f32aeSBjoern A. Zeeb }
4653dd4f32aeSBjoern A. Zeeb return 0;
4654dd4f32aeSBjoern A. Zeeb }
4655dd4f32aeSBjoern A. Zeeb
ath11k_sta_rc_update_wk(struct work_struct * wk)4656dd4f32aeSBjoern A. Zeeb static void ath11k_sta_rc_update_wk(struct work_struct *wk)
4657dd4f32aeSBjoern A. Zeeb {
4658dd4f32aeSBjoern A. Zeeb struct ath11k *ar;
4659dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif;
4660dd4f32aeSBjoern A. Zeeb struct ath11k_sta *arsta;
4661dd4f32aeSBjoern A. Zeeb struct ieee80211_sta *sta;
4662dd4f32aeSBjoern A. Zeeb struct cfg80211_chan_def def;
4663dd4f32aeSBjoern A. Zeeb enum nl80211_band band;
4664dd4f32aeSBjoern A. Zeeb const u8 *ht_mcs_mask;
4665dd4f32aeSBjoern A. Zeeb const u16 *vht_mcs_mask;
4666dd4f32aeSBjoern A. Zeeb const u16 *he_mcs_mask;
466728348caeSBjoern A. Zeeb u32 changed, bw, nss, smps, bw_prev;
466828348caeSBjoern A. Zeeb int err, num_ht_rates, num_vht_rates, num_he_rates;
4669dd4f32aeSBjoern A. Zeeb const struct cfg80211_bitrate_mask *mask;
4670dd4f32aeSBjoern A. Zeeb struct peer_assoc_params peer_arg;
467128348caeSBjoern A. Zeeb enum wmi_phy_mode peer_phymode;
4672dd4f32aeSBjoern A. Zeeb
4673dd4f32aeSBjoern A. Zeeb arsta = container_of(wk, struct ath11k_sta, update_wk);
4674dd4f32aeSBjoern A. Zeeb sta = container_of((void *)arsta, struct ieee80211_sta, drv_priv);
4675dd4f32aeSBjoern A. Zeeb arvif = arsta->arvif;
4676dd4f32aeSBjoern A. Zeeb ar = arvif->ar;
4677dd4f32aeSBjoern A. Zeeb
4678dd4f32aeSBjoern A. Zeeb if (WARN_ON(ath11k_mac_vif_chan(arvif->vif, &def)))
4679dd4f32aeSBjoern A. Zeeb return;
4680dd4f32aeSBjoern A. Zeeb
4681dd4f32aeSBjoern A. Zeeb band = def.chan->band;
4682dd4f32aeSBjoern A. Zeeb ht_mcs_mask = arvif->bitrate_mask.control[band].ht_mcs;
4683dd4f32aeSBjoern A. Zeeb vht_mcs_mask = arvif->bitrate_mask.control[band].vht_mcs;
4684dd4f32aeSBjoern A. Zeeb he_mcs_mask = arvif->bitrate_mask.control[band].he_mcs;
4685dd4f32aeSBjoern A. Zeeb
4686dd4f32aeSBjoern A. Zeeb spin_lock_bh(&ar->data_lock);
4687dd4f32aeSBjoern A. Zeeb
4688dd4f32aeSBjoern A. Zeeb changed = arsta->changed;
4689dd4f32aeSBjoern A. Zeeb arsta->changed = 0;
4690dd4f32aeSBjoern A. Zeeb
4691dd4f32aeSBjoern A. Zeeb bw = arsta->bw;
469228348caeSBjoern A. Zeeb bw_prev = arsta->bw_prev;
4693dd4f32aeSBjoern A. Zeeb nss = arsta->nss;
4694dd4f32aeSBjoern A. Zeeb smps = arsta->smps;
4695dd4f32aeSBjoern A. Zeeb
4696dd4f32aeSBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
4697dd4f32aeSBjoern A. Zeeb
4698dd4f32aeSBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
4699dd4f32aeSBjoern A. Zeeb
4700dd4f32aeSBjoern A. Zeeb nss = max_t(u32, 1, nss);
4701dd4f32aeSBjoern A. Zeeb nss = min(nss, max(max(ath11k_mac_max_ht_nss(ht_mcs_mask),
4702dd4f32aeSBjoern A. Zeeb ath11k_mac_max_vht_nss(vht_mcs_mask)),
4703dd4f32aeSBjoern A. Zeeb ath11k_mac_max_he_nss(he_mcs_mask)));
4704dd4f32aeSBjoern A. Zeeb
4705dd4f32aeSBjoern A. Zeeb if (changed & IEEE80211_RC_BW_CHANGED) {
470628348caeSBjoern A. Zeeb /* Get the peer phymode */
470728348caeSBjoern A. Zeeb ath11k_peer_assoc_h_phymode(ar, arvif->vif, sta, &peer_arg);
470828348caeSBjoern A. Zeeb peer_phymode = peer_arg.peer_phymode;
4709dd4f32aeSBjoern A. Zeeb
471028348caeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "update sta %pM peer bw %d phymode %d\n",
471128348caeSBjoern A. Zeeb sta->addr, bw, peer_phymode);
471228348caeSBjoern A. Zeeb
471328348caeSBjoern A. Zeeb if (bw > bw_prev) {
471428348caeSBjoern A. Zeeb /* BW is upgraded. In this case we send WMI_PEER_PHYMODE
471528348caeSBjoern A. Zeeb * followed by WMI_PEER_CHWIDTH
471628348caeSBjoern A. Zeeb */
471728348caeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "BW upgrade for sta %pM new BW %d, old BW %d\n",
471828348caeSBjoern A. Zeeb sta->addr, bw, bw_prev);
471928348caeSBjoern A. Zeeb
472028348caeSBjoern A. Zeeb err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,
472128348caeSBjoern A. Zeeb WMI_PEER_PHYMODE, peer_phymode);
472228348caeSBjoern A. Zeeb
4723dd4f32aeSBjoern A. Zeeb if (err) {
472428348caeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to update STA %pM peer phymode %d: %d\n",
472528348caeSBjoern A. Zeeb sta->addr, peer_phymode, err);
472628348caeSBjoern A. Zeeb goto err_rc_bw_changed;
472728348caeSBjoern A. Zeeb }
472828348caeSBjoern A. Zeeb
4729dd4f32aeSBjoern A. Zeeb err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,
4730dd4f32aeSBjoern A. Zeeb WMI_PEER_CHWIDTH, bw);
473128348caeSBjoern A. Zeeb
4732dd4f32aeSBjoern A. Zeeb if (err)
4733dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to update STA %pM peer bw %d: %d\n",
4734dd4f32aeSBjoern A. Zeeb sta->addr, bw, err);
4735dd4f32aeSBjoern A. Zeeb } else {
473628348caeSBjoern A. Zeeb /* BW is downgraded. In this case we send WMI_PEER_CHWIDTH
473728348caeSBjoern A. Zeeb * followed by WMI_PEER_PHYMODE
473828348caeSBjoern A. Zeeb */
473928348caeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "BW downgrade for sta %pM new BW %d,old BW %d\n",
474028348caeSBjoern A. Zeeb sta->addr, bw, bw_prev);
474128348caeSBjoern A. Zeeb
474228348caeSBjoern A. Zeeb err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,
474328348caeSBjoern A. Zeeb WMI_PEER_CHWIDTH, bw);
474428348caeSBjoern A. Zeeb
474528348caeSBjoern A. Zeeb if (err) {
474628348caeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to update STA %pM peer bw %d: %d\n",
474728348caeSBjoern A. Zeeb sta->addr, bw, err);
474828348caeSBjoern A. Zeeb goto err_rc_bw_changed;
474928348caeSBjoern A. Zeeb }
475028348caeSBjoern A. Zeeb
475128348caeSBjoern A. Zeeb err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,
475228348caeSBjoern A. Zeeb WMI_PEER_PHYMODE, peer_phymode);
475328348caeSBjoern A. Zeeb
475428348caeSBjoern A. Zeeb if (err)
475528348caeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to update STA %pM peer phymode %d: %d\n",
475628348caeSBjoern A. Zeeb sta->addr, peer_phymode, err);
4757dd4f32aeSBjoern A. Zeeb }
4758dd4f32aeSBjoern A. Zeeb }
4759dd4f32aeSBjoern A. Zeeb
4760dd4f32aeSBjoern A. Zeeb if (changed & IEEE80211_RC_NSS_CHANGED) {
476128348caeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "update sta %pM nss %d\n",
4762dd4f32aeSBjoern A. Zeeb sta->addr, nss);
4763dd4f32aeSBjoern A. Zeeb
4764dd4f32aeSBjoern A. Zeeb err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,
4765dd4f32aeSBjoern A. Zeeb WMI_PEER_NSS, nss);
4766dd4f32aeSBjoern A. Zeeb if (err)
4767dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to update STA %pM nss %d: %d\n",
4768dd4f32aeSBjoern A. Zeeb sta->addr, nss, err);
4769dd4f32aeSBjoern A. Zeeb }
4770dd4f32aeSBjoern A. Zeeb
4771dd4f32aeSBjoern A. Zeeb if (changed & IEEE80211_RC_SMPS_CHANGED) {
477228348caeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "update sta %pM smps %d\n",
4773dd4f32aeSBjoern A. Zeeb sta->addr, smps);
4774dd4f32aeSBjoern A. Zeeb
4775dd4f32aeSBjoern A. Zeeb err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,
4776dd4f32aeSBjoern A. Zeeb WMI_PEER_MIMO_PS_STATE, smps);
4777dd4f32aeSBjoern A. Zeeb if (err)
4778dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to update STA %pM smps %d: %d\n",
4779dd4f32aeSBjoern A. Zeeb sta->addr, smps, err);
4780dd4f32aeSBjoern A. Zeeb }
4781dd4f32aeSBjoern A. Zeeb
4782dd4f32aeSBjoern A. Zeeb if (changed & IEEE80211_RC_SUPP_RATES_CHANGED) {
4783dd4f32aeSBjoern A. Zeeb mask = &arvif->bitrate_mask;
478428348caeSBjoern A. Zeeb num_ht_rates = ath11k_mac_bitrate_mask_num_ht_rates(ar, band,
478528348caeSBjoern A. Zeeb mask);
4786dd4f32aeSBjoern A. Zeeb num_vht_rates = ath11k_mac_bitrate_mask_num_vht_rates(ar, band,
4787dd4f32aeSBjoern A. Zeeb mask);
4788dd4f32aeSBjoern A. Zeeb num_he_rates = ath11k_mac_bitrate_mask_num_he_rates(ar, band,
4789dd4f32aeSBjoern A. Zeeb mask);
4790dd4f32aeSBjoern A. Zeeb
4791dd4f32aeSBjoern A. Zeeb /* Peer_assoc_prepare will reject vht rates in
4792dd4f32aeSBjoern A. Zeeb * bitrate_mask if its not available in range format and
4793dd4f32aeSBjoern A. Zeeb * sets vht tx_rateset as unsupported. So multiple VHT MCS
4794dd4f32aeSBjoern A. Zeeb * setting(eg. MCS 4,5,6) per peer is not supported here.
4795dd4f32aeSBjoern A. Zeeb * But, Single rate in VHT mask can be set as per-peer
4796dd4f32aeSBjoern A. Zeeb * fixed rate. But even if any HT rates are configured in
4797dd4f32aeSBjoern A. Zeeb * the bitrate mask, device will not switch to those rates
4798dd4f32aeSBjoern A. Zeeb * when per-peer Fixed rate is set.
4799dd4f32aeSBjoern A. Zeeb * TODO: Check RATEMASK_CMDID to support auto rates selection
4800dd4f32aeSBjoern A. Zeeb * across HT/VHT and for multiple VHT MCS support.
4801dd4f32aeSBjoern A. Zeeb */
4802dd4f32aeSBjoern A. Zeeb if (sta->deflink.vht_cap.vht_supported && num_vht_rates == 1) {
4803dd4f32aeSBjoern A. Zeeb ath11k_mac_set_peer_vht_fixed_rate(arvif, sta, mask,
4804dd4f32aeSBjoern A. Zeeb band);
4805dd4f32aeSBjoern A. Zeeb } else if (sta->deflink.he_cap.has_he && num_he_rates == 1) {
4806dd4f32aeSBjoern A. Zeeb ath11k_mac_set_peer_he_fixed_rate(arvif, sta, mask,
4807dd4f32aeSBjoern A. Zeeb band);
480828348caeSBjoern A. Zeeb } else if (sta->deflink.ht_cap.ht_supported && num_ht_rates == 1) {
480928348caeSBjoern A. Zeeb ath11k_mac_set_peer_ht_fixed_rate(arvif, sta, mask,
481028348caeSBjoern A. Zeeb band);
4811dd4f32aeSBjoern A. Zeeb } else {
4812dd4f32aeSBjoern A. Zeeb /* If the peer is non-VHT/HE or no fixed VHT/HE rate
4813dd4f32aeSBjoern A. Zeeb * is provided in the new bitrate mask we set the
4814dd4f32aeSBjoern A. Zeeb * other rates using peer_assoc command. Also clear
4815dd4f32aeSBjoern A. Zeeb * the peer fixed rate settings as it has higher proprity
4816dd4f32aeSBjoern A. Zeeb * than peer assoc
4817dd4f32aeSBjoern A. Zeeb */
4818dd4f32aeSBjoern A. Zeeb err = ath11k_wmi_set_peer_param(ar, sta->addr,
4819dd4f32aeSBjoern A. Zeeb arvif->vdev_id,
4820dd4f32aeSBjoern A. Zeeb WMI_PEER_PARAM_FIXED_RATE,
4821dd4f32aeSBjoern A. Zeeb WMI_FIXED_RATE_NONE);
4822dd4f32aeSBjoern A. Zeeb if (err)
4823dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab,
4824dd4f32aeSBjoern A. Zeeb "failed to disable peer fixed rate for sta %pM: %d\n",
4825dd4f32aeSBjoern A. Zeeb sta->addr, err);
4826dd4f32aeSBjoern A. Zeeb
4827dd4f32aeSBjoern A. Zeeb ath11k_peer_assoc_prepare(ar, arvif->vif, sta,
4828dd4f32aeSBjoern A. Zeeb &peer_arg, true);
4829dd4f32aeSBjoern A. Zeeb
4830dd4f32aeSBjoern A. Zeeb peer_arg.is_assoc = false;
4831dd4f32aeSBjoern A. Zeeb err = ath11k_wmi_send_peer_assoc_cmd(ar, &peer_arg);
4832dd4f32aeSBjoern A. Zeeb if (err)
4833dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to run peer assoc for STA %pM vdev %i: %d\n",
4834dd4f32aeSBjoern A. Zeeb sta->addr, arvif->vdev_id, err);
4835dd4f32aeSBjoern A. Zeeb
4836dd4f32aeSBjoern A. Zeeb if (!wait_for_completion_timeout(&ar->peer_assoc_done, 1 * HZ))
4837dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to get peer assoc conf event for %pM vdev %i\n",
4838dd4f32aeSBjoern A. Zeeb sta->addr, arvif->vdev_id);
4839dd4f32aeSBjoern A. Zeeb }
4840dd4f32aeSBjoern A. Zeeb }
4841dd4f32aeSBjoern A. Zeeb
484228348caeSBjoern A. Zeeb err_rc_bw_changed:
4843dd4f32aeSBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
4844dd4f32aeSBjoern A. Zeeb }
4845dd4f32aeSBjoern A. Zeeb
ath11k_sta_set_4addr_wk(struct work_struct * wk)4846dd4f32aeSBjoern A. Zeeb static void ath11k_sta_set_4addr_wk(struct work_struct *wk)
4847dd4f32aeSBjoern A. Zeeb {
4848dd4f32aeSBjoern A. Zeeb struct ath11k *ar;
4849dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif;
4850dd4f32aeSBjoern A. Zeeb struct ath11k_sta *arsta;
4851dd4f32aeSBjoern A. Zeeb struct ieee80211_sta *sta;
4852dd4f32aeSBjoern A. Zeeb int ret = 0;
4853dd4f32aeSBjoern A. Zeeb
4854dd4f32aeSBjoern A. Zeeb arsta = container_of(wk, struct ath11k_sta, set_4addr_wk);
4855dd4f32aeSBjoern A. Zeeb sta = container_of((void *)arsta, struct ieee80211_sta, drv_priv);
4856dd4f32aeSBjoern A. Zeeb arvif = arsta->arvif;
4857dd4f32aeSBjoern A. Zeeb ar = arvif->ar;
4858dd4f32aeSBjoern A. Zeeb
4859dd4f32aeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
4860dd4f32aeSBjoern A. Zeeb "setting USE_4ADDR for peer %pM\n", sta->addr);
4861dd4f32aeSBjoern A. Zeeb
4862dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_set_peer_param(ar, sta->addr,
4863dd4f32aeSBjoern A. Zeeb arvif->vdev_id,
4864dd4f32aeSBjoern A. Zeeb WMI_PEER_USE_4ADDR, 1);
4865dd4f32aeSBjoern A. Zeeb
4866dd4f32aeSBjoern A. Zeeb if (ret)
4867dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to set peer %pM 4addr capability: %d\n",
4868dd4f32aeSBjoern A. Zeeb sta->addr, ret);
4869dd4f32aeSBjoern A. Zeeb }
4870dd4f32aeSBjoern A. Zeeb
ath11k_mac_inc_num_stations(struct ath11k_vif * arvif,struct ieee80211_sta * sta)4871dd4f32aeSBjoern A. Zeeb static int ath11k_mac_inc_num_stations(struct ath11k_vif *arvif,
4872dd4f32aeSBjoern A. Zeeb struct ieee80211_sta *sta)
4873dd4f32aeSBjoern A. Zeeb {
4874dd4f32aeSBjoern A. Zeeb struct ath11k *ar = arvif->ar;
4875dd4f32aeSBjoern A. Zeeb
4876dd4f32aeSBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
4877dd4f32aeSBjoern A. Zeeb
4878dd4f32aeSBjoern A. Zeeb if (arvif->vdev_type == WMI_VDEV_TYPE_STA && !sta->tdls)
4879dd4f32aeSBjoern A. Zeeb return 0;
4880dd4f32aeSBjoern A. Zeeb
4881dd4f32aeSBjoern A. Zeeb if (ar->num_stations >= ar->max_num_stations)
4882dd4f32aeSBjoern A. Zeeb return -ENOBUFS;
4883dd4f32aeSBjoern A. Zeeb
4884dd4f32aeSBjoern A. Zeeb ar->num_stations++;
4885dd4f32aeSBjoern A. Zeeb
4886dd4f32aeSBjoern A. Zeeb return 0;
4887dd4f32aeSBjoern A. Zeeb }
4888dd4f32aeSBjoern A. Zeeb
ath11k_mac_dec_num_stations(struct ath11k_vif * arvif,struct ieee80211_sta * sta)4889dd4f32aeSBjoern A. Zeeb static void ath11k_mac_dec_num_stations(struct ath11k_vif *arvif,
4890dd4f32aeSBjoern A. Zeeb struct ieee80211_sta *sta)
4891dd4f32aeSBjoern A. Zeeb {
4892dd4f32aeSBjoern A. Zeeb struct ath11k *ar = arvif->ar;
4893dd4f32aeSBjoern A. Zeeb
4894dd4f32aeSBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
4895dd4f32aeSBjoern A. Zeeb
4896dd4f32aeSBjoern A. Zeeb if (arvif->vdev_type == WMI_VDEV_TYPE_STA && !sta->tdls)
4897dd4f32aeSBjoern A. Zeeb return;
4898dd4f32aeSBjoern A. Zeeb
4899dd4f32aeSBjoern A. Zeeb ar->num_stations--;
4900dd4f32aeSBjoern A. Zeeb }
4901dd4f32aeSBjoern A. Zeeb
ath11k_mac_station_add(struct ath11k * ar,struct ieee80211_vif * vif,struct ieee80211_sta * sta)4902dd4f32aeSBjoern A. Zeeb static int ath11k_mac_station_add(struct ath11k *ar,
4903dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif,
4904dd4f32aeSBjoern A. Zeeb struct ieee80211_sta *sta)
4905dd4f32aeSBjoern A. Zeeb {
4906dd4f32aeSBjoern A. Zeeb struct ath11k_base *ab = ar->ab;
4907dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
4908dd4f32aeSBjoern A. Zeeb struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
4909dd4f32aeSBjoern A. Zeeb struct peer_create_params peer_param;
4910dd4f32aeSBjoern A. Zeeb int ret;
4911dd4f32aeSBjoern A. Zeeb
4912dd4f32aeSBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
4913dd4f32aeSBjoern A. Zeeb
4914dd4f32aeSBjoern A. Zeeb ret = ath11k_mac_inc_num_stations(arvif, sta);
4915dd4f32aeSBjoern A. Zeeb if (ret) {
4916dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, "refusing to associate station: too many connected already (%d)\n",
4917dd4f32aeSBjoern A. Zeeb ar->max_num_stations);
4918dd4f32aeSBjoern A. Zeeb goto exit;
4919dd4f32aeSBjoern A. Zeeb }
4920dd4f32aeSBjoern A. Zeeb
4921dd4f32aeSBjoern A. Zeeb arsta->rx_stats = kzalloc(sizeof(*arsta->rx_stats), GFP_KERNEL);
4922dd4f32aeSBjoern A. Zeeb if (!arsta->rx_stats) {
4923dd4f32aeSBjoern A. Zeeb ret = -ENOMEM;
4924dd4f32aeSBjoern A. Zeeb goto dec_num_station;
4925dd4f32aeSBjoern A. Zeeb }
4926dd4f32aeSBjoern A. Zeeb
4927dd4f32aeSBjoern A. Zeeb peer_param.vdev_id = arvif->vdev_id;
4928dd4f32aeSBjoern A. Zeeb peer_param.peer_addr = sta->addr;
4929dd4f32aeSBjoern A. Zeeb peer_param.peer_type = WMI_PEER_TYPE_DEFAULT;
4930dd4f32aeSBjoern A. Zeeb
4931dd4f32aeSBjoern A. Zeeb ret = ath11k_peer_create(ar, arvif, sta, &peer_param);
4932dd4f32aeSBjoern A. Zeeb if (ret) {
4933dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, "Failed to add peer: %pM for VDEV: %d\n",
4934dd4f32aeSBjoern A. Zeeb sta->addr, arvif->vdev_id);
4935dd4f32aeSBjoern A. Zeeb goto free_rx_stats;
4936dd4f32aeSBjoern A. Zeeb }
4937dd4f32aeSBjoern A. Zeeb
4938dd4f32aeSBjoern A. Zeeb ath11k_dbg(ab, ATH11K_DBG_MAC, "Added peer: %pM for VDEV: %d\n",
4939dd4f32aeSBjoern A. Zeeb sta->addr, arvif->vdev_id);
4940dd4f32aeSBjoern A. Zeeb
4941dd4f32aeSBjoern A. Zeeb if (ath11k_debugfs_is_extd_tx_stats_enabled(ar)) {
4942dd4f32aeSBjoern A. Zeeb arsta->tx_stats = kzalloc(sizeof(*arsta->tx_stats), GFP_KERNEL);
4943dd4f32aeSBjoern A. Zeeb if (!arsta->tx_stats) {
4944dd4f32aeSBjoern A. Zeeb ret = -ENOMEM;
4945dd4f32aeSBjoern A. Zeeb goto free_peer;
4946dd4f32aeSBjoern A. Zeeb }
4947dd4f32aeSBjoern A. Zeeb }
4948dd4f32aeSBjoern A. Zeeb
4949dd4f32aeSBjoern A. Zeeb if (ieee80211_vif_is_mesh(vif)) {
4950dd4f32aeSBjoern A. Zeeb ath11k_dbg(ab, ATH11K_DBG_MAC,
4951dd4f32aeSBjoern A. Zeeb "setting USE_4ADDR for mesh STA %pM\n", sta->addr);
4952dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_set_peer_param(ar, sta->addr,
4953dd4f32aeSBjoern A. Zeeb arvif->vdev_id,
4954dd4f32aeSBjoern A. Zeeb WMI_PEER_USE_4ADDR, 1);
4955dd4f32aeSBjoern A. Zeeb if (ret) {
4956dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, "failed to set mesh STA %pM 4addr capability: %d\n",
4957dd4f32aeSBjoern A. Zeeb sta->addr, ret);
4958dd4f32aeSBjoern A. Zeeb goto free_tx_stats;
4959dd4f32aeSBjoern A. Zeeb }
4960dd4f32aeSBjoern A. Zeeb }
4961dd4f32aeSBjoern A. Zeeb
4962dd4f32aeSBjoern A. Zeeb ret = ath11k_dp_peer_setup(ar, arvif->vdev_id, sta->addr);
4963dd4f32aeSBjoern A. Zeeb if (ret) {
4964dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, "failed to setup dp for peer %pM on vdev %i (%d)\n",
4965dd4f32aeSBjoern A. Zeeb sta->addr, arvif->vdev_id, ret);
4966dd4f32aeSBjoern A. Zeeb goto free_tx_stats;
4967dd4f32aeSBjoern A. Zeeb }
4968dd4f32aeSBjoern A. Zeeb
4969dd4f32aeSBjoern A. Zeeb if (ab->hw_params.vdev_start_delay &&
4970dd4f32aeSBjoern A. Zeeb !arvif->is_started &&
4971dd4f32aeSBjoern A. Zeeb arvif->vdev_type != WMI_VDEV_TYPE_AP) {
4972dd4f32aeSBjoern A. Zeeb ret = ath11k_start_vdev_delay(ar->hw, vif);
4973dd4f32aeSBjoern A. Zeeb if (ret) {
4974dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, "failed to delay vdev start: %d\n", ret);
4975dd4f32aeSBjoern A. Zeeb goto free_tx_stats;
4976dd4f32aeSBjoern A. Zeeb }
4977dd4f32aeSBjoern A. Zeeb }
4978dd4f32aeSBjoern A. Zeeb
497928348caeSBjoern A. Zeeb ewma_avg_rssi_init(&arsta->avg_rssi);
4980dd4f32aeSBjoern A. Zeeb return 0;
4981dd4f32aeSBjoern A. Zeeb
4982dd4f32aeSBjoern A. Zeeb free_tx_stats:
4983dd4f32aeSBjoern A. Zeeb kfree(arsta->tx_stats);
4984dd4f32aeSBjoern A. Zeeb arsta->tx_stats = NULL;
4985dd4f32aeSBjoern A. Zeeb free_peer:
4986dd4f32aeSBjoern A. Zeeb ath11k_peer_delete(ar, arvif->vdev_id, sta->addr);
4987dd4f32aeSBjoern A. Zeeb free_rx_stats:
4988dd4f32aeSBjoern A. Zeeb kfree(arsta->rx_stats);
4989dd4f32aeSBjoern A. Zeeb arsta->rx_stats = NULL;
4990dd4f32aeSBjoern A. Zeeb dec_num_station:
4991dd4f32aeSBjoern A. Zeeb ath11k_mac_dec_num_stations(arvif, sta);
4992dd4f32aeSBjoern A. Zeeb exit:
4993dd4f32aeSBjoern A. Zeeb return ret;
4994dd4f32aeSBjoern A. Zeeb }
4995dd4f32aeSBjoern A. Zeeb
ath11k_mac_ieee80211_sta_bw_to_wmi(struct ath11k * ar,struct ieee80211_sta * sta)499628348caeSBjoern A. Zeeb static u32 ath11k_mac_ieee80211_sta_bw_to_wmi(struct ath11k *ar,
499728348caeSBjoern A. Zeeb struct ieee80211_sta *sta)
499828348caeSBjoern A. Zeeb {
499928348caeSBjoern A. Zeeb u32 bw = WMI_PEER_CHWIDTH_20MHZ;
500028348caeSBjoern A. Zeeb
500128348caeSBjoern A. Zeeb switch (sta->deflink.bandwidth) {
500228348caeSBjoern A. Zeeb case IEEE80211_STA_RX_BW_20:
500328348caeSBjoern A. Zeeb bw = WMI_PEER_CHWIDTH_20MHZ;
500428348caeSBjoern A. Zeeb break;
500528348caeSBjoern A. Zeeb case IEEE80211_STA_RX_BW_40:
500628348caeSBjoern A. Zeeb bw = WMI_PEER_CHWIDTH_40MHZ;
500728348caeSBjoern A. Zeeb break;
500828348caeSBjoern A. Zeeb case IEEE80211_STA_RX_BW_80:
500928348caeSBjoern A. Zeeb bw = WMI_PEER_CHWIDTH_80MHZ;
501028348caeSBjoern A. Zeeb break;
501128348caeSBjoern A. Zeeb case IEEE80211_STA_RX_BW_160:
501228348caeSBjoern A. Zeeb bw = WMI_PEER_CHWIDTH_160MHZ;
501328348caeSBjoern A. Zeeb break;
501428348caeSBjoern A. Zeeb default:
501528348caeSBjoern A. Zeeb ath11k_warn(ar->ab, "Invalid bandwidth %d for %pM\n",
501628348caeSBjoern A. Zeeb sta->deflink.bandwidth, sta->addr);
501728348caeSBjoern A. Zeeb bw = WMI_PEER_CHWIDTH_20MHZ;
501828348caeSBjoern A. Zeeb break;
501928348caeSBjoern A. Zeeb }
502028348caeSBjoern A. Zeeb
502128348caeSBjoern A. Zeeb return bw;
502228348caeSBjoern A. Zeeb }
502328348caeSBjoern A. Zeeb
ath11k_mac_op_sta_state(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_sta * sta,enum ieee80211_sta_state old_state,enum ieee80211_sta_state new_state)5024dd4f32aeSBjoern A. Zeeb static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw,
5025dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif,
5026dd4f32aeSBjoern A. Zeeb struct ieee80211_sta *sta,
5027dd4f32aeSBjoern A. Zeeb enum ieee80211_sta_state old_state,
5028dd4f32aeSBjoern A. Zeeb enum ieee80211_sta_state new_state)
5029dd4f32aeSBjoern A. Zeeb {
5030dd4f32aeSBjoern A. Zeeb struct ath11k *ar = hw->priv;
5031dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
5032dd4f32aeSBjoern A. Zeeb struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
5033dd4f32aeSBjoern A. Zeeb struct ath11k_peer *peer;
5034dd4f32aeSBjoern A. Zeeb int ret = 0;
5035dd4f32aeSBjoern A. Zeeb
5036dd4f32aeSBjoern A. Zeeb /* cancel must be done outside the mutex to avoid deadlock */
5037dd4f32aeSBjoern A. Zeeb if ((old_state == IEEE80211_STA_NONE &&
5038dd4f32aeSBjoern A. Zeeb new_state == IEEE80211_STA_NOTEXIST)) {
5039dd4f32aeSBjoern A. Zeeb cancel_work_sync(&arsta->update_wk);
5040dd4f32aeSBjoern A. Zeeb cancel_work_sync(&arsta->set_4addr_wk);
5041dd4f32aeSBjoern A. Zeeb }
5042dd4f32aeSBjoern A. Zeeb
5043dd4f32aeSBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
5044dd4f32aeSBjoern A. Zeeb
5045dd4f32aeSBjoern A. Zeeb if (old_state == IEEE80211_STA_NOTEXIST &&
5046dd4f32aeSBjoern A. Zeeb new_state == IEEE80211_STA_NONE) {
5047dd4f32aeSBjoern A. Zeeb memset(arsta, 0, sizeof(*arsta));
5048dd4f32aeSBjoern A. Zeeb arsta->arvif = arvif;
504928348caeSBjoern A. Zeeb arsta->peer_ps_state = WMI_PEER_PS_STATE_DISABLED;
5050dd4f32aeSBjoern A. Zeeb INIT_WORK(&arsta->update_wk, ath11k_sta_rc_update_wk);
5051dd4f32aeSBjoern A. Zeeb INIT_WORK(&arsta->set_4addr_wk, ath11k_sta_set_4addr_wk);
5052dd4f32aeSBjoern A. Zeeb
5053dd4f32aeSBjoern A. Zeeb ret = ath11k_mac_station_add(ar, vif, sta);
5054dd4f32aeSBjoern A. Zeeb if (ret)
5055dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "Failed to add station: %pM for VDEV: %d\n",
5056dd4f32aeSBjoern A. Zeeb sta->addr, arvif->vdev_id);
5057dd4f32aeSBjoern A. Zeeb } else if ((old_state == IEEE80211_STA_NONE &&
5058dd4f32aeSBjoern A. Zeeb new_state == IEEE80211_STA_NOTEXIST)) {
5059dd4f32aeSBjoern A. Zeeb bool skip_peer_delete = ar->ab->hw_params.vdev_start_delay &&
5060dd4f32aeSBjoern A. Zeeb vif->type == NL80211_IFTYPE_STATION;
5061dd4f32aeSBjoern A. Zeeb
5062dd4f32aeSBjoern A. Zeeb ath11k_dp_peer_cleanup(ar, arvif->vdev_id, sta->addr);
5063dd4f32aeSBjoern A. Zeeb
5064dd4f32aeSBjoern A. Zeeb if (!skip_peer_delete) {
5065dd4f32aeSBjoern A. Zeeb ret = ath11k_peer_delete(ar, arvif->vdev_id, sta->addr);
5066dd4f32aeSBjoern A. Zeeb if (ret)
5067dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab,
5068dd4f32aeSBjoern A. Zeeb "Failed to delete peer: %pM for VDEV: %d\n",
5069dd4f32aeSBjoern A. Zeeb sta->addr, arvif->vdev_id);
5070dd4f32aeSBjoern A. Zeeb else
5071dd4f32aeSBjoern A. Zeeb ath11k_dbg(ar->ab,
5072dd4f32aeSBjoern A. Zeeb ATH11K_DBG_MAC,
5073dd4f32aeSBjoern A. Zeeb "Removed peer: %pM for VDEV: %d\n",
5074dd4f32aeSBjoern A. Zeeb sta->addr, arvif->vdev_id);
5075dd4f32aeSBjoern A. Zeeb }
5076dd4f32aeSBjoern A. Zeeb
5077dd4f32aeSBjoern A. Zeeb ath11k_mac_dec_num_stations(arvif, sta);
507828348caeSBjoern A. Zeeb mutex_lock(&ar->ab->tbl_mtx_lock);
5079dd4f32aeSBjoern A. Zeeb spin_lock_bh(&ar->ab->base_lock);
5080dd4f32aeSBjoern A. Zeeb peer = ath11k_peer_find(ar->ab, arvif->vdev_id, sta->addr);
5081dd4f32aeSBjoern A. Zeeb if (skip_peer_delete && peer) {
5082dd4f32aeSBjoern A. Zeeb peer->sta = NULL;
5083dd4f32aeSBjoern A. Zeeb } else if (peer && peer->sta == sta) {
5084dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "Found peer entry %pM n vdev %i after it was supposedly removed\n",
5085dd4f32aeSBjoern A. Zeeb vif->addr, arvif->vdev_id);
508628348caeSBjoern A. Zeeb ath11k_peer_rhash_delete(ar->ab, peer);
5087dd4f32aeSBjoern A. Zeeb peer->sta = NULL;
5088dd4f32aeSBjoern A. Zeeb list_del(&peer->list);
5089dd4f32aeSBjoern A. Zeeb kfree(peer);
5090dd4f32aeSBjoern A. Zeeb ar->num_peers--;
5091dd4f32aeSBjoern A. Zeeb }
5092dd4f32aeSBjoern A. Zeeb spin_unlock_bh(&ar->ab->base_lock);
509328348caeSBjoern A. Zeeb mutex_unlock(&ar->ab->tbl_mtx_lock);
5094dd4f32aeSBjoern A. Zeeb
5095dd4f32aeSBjoern A. Zeeb kfree(arsta->tx_stats);
5096dd4f32aeSBjoern A. Zeeb arsta->tx_stats = NULL;
5097dd4f32aeSBjoern A. Zeeb
5098dd4f32aeSBjoern A. Zeeb kfree(arsta->rx_stats);
5099dd4f32aeSBjoern A. Zeeb arsta->rx_stats = NULL;
5100dd4f32aeSBjoern A. Zeeb } else if (old_state == IEEE80211_STA_AUTH &&
5101dd4f32aeSBjoern A. Zeeb new_state == IEEE80211_STA_ASSOC &&
5102dd4f32aeSBjoern A. Zeeb (vif->type == NL80211_IFTYPE_AP ||
5103dd4f32aeSBjoern A. Zeeb vif->type == NL80211_IFTYPE_MESH_POINT ||
5104dd4f32aeSBjoern A. Zeeb vif->type == NL80211_IFTYPE_ADHOC)) {
5105dd4f32aeSBjoern A. Zeeb ret = ath11k_station_assoc(ar, vif, sta, false);
5106dd4f32aeSBjoern A. Zeeb if (ret)
5107dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "Failed to associate station: %pM\n",
5108dd4f32aeSBjoern A. Zeeb sta->addr);
510928348caeSBjoern A. Zeeb
511028348caeSBjoern A. Zeeb spin_lock_bh(&ar->data_lock);
511128348caeSBjoern A. Zeeb /* Set arsta bw and prev bw */
511228348caeSBjoern A. Zeeb arsta->bw = ath11k_mac_ieee80211_sta_bw_to_wmi(ar, sta);
511328348caeSBjoern A. Zeeb arsta->bw_prev = arsta->bw;
511428348caeSBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
5115dd4f32aeSBjoern A. Zeeb } else if (old_state == IEEE80211_STA_ASSOC &&
5116dd4f32aeSBjoern A. Zeeb new_state == IEEE80211_STA_AUTHORIZED) {
5117dd4f32aeSBjoern A. Zeeb spin_lock_bh(&ar->ab->base_lock);
5118dd4f32aeSBjoern A. Zeeb
5119dd4f32aeSBjoern A. Zeeb peer = ath11k_peer_find(ar->ab, arvif->vdev_id, sta->addr);
5120dd4f32aeSBjoern A. Zeeb if (peer)
5121dd4f32aeSBjoern A. Zeeb peer->is_authorized = true;
5122dd4f32aeSBjoern A. Zeeb
5123dd4f32aeSBjoern A. Zeeb spin_unlock_bh(&ar->ab->base_lock);
5124dd4f32aeSBjoern A. Zeeb
5125dd4f32aeSBjoern A. Zeeb if (vif->type == NL80211_IFTYPE_STATION && arvif->is_up) {
5126dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_set_peer_param(ar, sta->addr,
5127dd4f32aeSBjoern A. Zeeb arvif->vdev_id,
5128dd4f32aeSBjoern A. Zeeb WMI_PEER_AUTHORIZE,
5129dd4f32aeSBjoern A. Zeeb 1);
5130dd4f32aeSBjoern A. Zeeb if (ret)
5131dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "Unable to authorize peer %pM vdev %d: %d\n",
5132dd4f32aeSBjoern A. Zeeb sta->addr, arvif->vdev_id, ret);
5133dd4f32aeSBjoern A. Zeeb }
5134dd4f32aeSBjoern A. Zeeb } else if (old_state == IEEE80211_STA_AUTHORIZED &&
5135dd4f32aeSBjoern A. Zeeb new_state == IEEE80211_STA_ASSOC) {
5136dd4f32aeSBjoern A. Zeeb spin_lock_bh(&ar->ab->base_lock);
5137dd4f32aeSBjoern A. Zeeb
5138dd4f32aeSBjoern A. Zeeb peer = ath11k_peer_find(ar->ab, arvif->vdev_id, sta->addr);
5139dd4f32aeSBjoern A. Zeeb if (peer)
5140dd4f32aeSBjoern A. Zeeb peer->is_authorized = false;
5141dd4f32aeSBjoern A. Zeeb
5142dd4f32aeSBjoern A. Zeeb spin_unlock_bh(&ar->ab->base_lock);
5143dd4f32aeSBjoern A. Zeeb } else if (old_state == IEEE80211_STA_ASSOC &&
5144dd4f32aeSBjoern A. Zeeb new_state == IEEE80211_STA_AUTH &&
5145dd4f32aeSBjoern A. Zeeb (vif->type == NL80211_IFTYPE_AP ||
5146dd4f32aeSBjoern A. Zeeb vif->type == NL80211_IFTYPE_MESH_POINT ||
5147dd4f32aeSBjoern A. Zeeb vif->type == NL80211_IFTYPE_ADHOC)) {
5148dd4f32aeSBjoern A. Zeeb ret = ath11k_station_disassoc(ar, vif, sta);
5149dd4f32aeSBjoern A. Zeeb if (ret)
5150dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "Failed to disassociate station: %pM\n",
5151dd4f32aeSBjoern A. Zeeb sta->addr);
5152dd4f32aeSBjoern A. Zeeb }
5153dd4f32aeSBjoern A. Zeeb
5154dd4f32aeSBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
5155dd4f32aeSBjoern A. Zeeb return ret;
5156dd4f32aeSBjoern A. Zeeb }
5157dd4f32aeSBjoern A. Zeeb
ath11k_mac_op_sta_set_txpwr(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_sta * sta)5158dd4f32aeSBjoern A. Zeeb static int ath11k_mac_op_sta_set_txpwr(struct ieee80211_hw *hw,
5159dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif,
5160dd4f32aeSBjoern A. Zeeb struct ieee80211_sta *sta)
5161dd4f32aeSBjoern A. Zeeb {
5162dd4f32aeSBjoern A. Zeeb struct ath11k *ar = hw->priv;
5163dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif = (void *)vif->drv_priv;
5164dd4f32aeSBjoern A. Zeeb int ret = 0;
5165dd4f32aeSBjoern A. Zeeb s16 txpwr;
5166dd4f32aeSBjoern A. Zeeb
5167dd4f32aeSBjoern A. Zeeb if (sta->deflink.txpwr.type == NL80211_TX_POWER_AUTOMATIC) {
5168dd4f32aeSBjoern A. Zeeb txpwr = 0;
5169dd4f32aeSBjoern A. Zeeb } else {
5170dd4f32aeSBjoern A. Zeeb txpwr = sta->deflink.txpwr.power;
5171dd4f32aeSBjoern A. Zeeb if (!txpwr)
5172dd4f32aeSBjoern A. Zeeb return -EINVAL;
5173dd4f32aeSBjoern A. Zeeb }
5174dd4f32aeSBjoern A. Zeeb
5175dd4f32aeSBjoern A. Zeeb if (txpwr > ATH11K_TX_POWER_MAX_VAL || txpwr < ATH11K_TX_POWER_MIN_VAL)
5176dd4f32aeSBjoern A. Zeeb return -EINVAL;
5177dd4f32aeSBjoern A. Zeeb
5178dd4f32aeSBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
5179dd4f32aeSBjoern A. Zeeb
5180dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,
5181dd4f32aeSBjoern A. Zeeb WMI_PEER_USE_FIXED_PWR, txpwr);
5182dd4f32aeSBjoern A. Zeeb if (ret) {
5183dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to set tx power for station ret: %d\n",
5184dd4f32aeSBjoern A. Zeeb ret);
5185dd4f32aeSBjoern A. Zeeb goto out;
5186dd4f32aeSBjoern A. Zeeb }
5187dd4f32aeSBjoern A. Zeeb
5188dd4f32aeSBjoern A. Zeeb out:
5189dd4f32aeSBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
5190dd4f32aeSBjoern A. Zeeb return ret;
5191dd4f32aeSBjoern A. Zeeb }
5192dd4f32aeSBjoern A. Zeeb
ath11k_mac_op_sta_set_4addr(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_sta * sta,bool enabled)5193dd4f32aeSBjoern A. Zeeb static void ath11k_mac_op_sta_set_4addr(struct ieee80211_hw *hw,
5194dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif,
5195dd4f32aeSBjoern A. Zeeb struct ieee80211_sta *sta, bool enabled)
5196dd4f32aeSBjoern A. Zeeb {
5197dd4f32aeSBjoern A. Zeeb struct ath11k *ar = hw->priv;
5198dd4f32aeSBjoern A. Zeeb struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
5199dd4f32aeSBjoern A. Zeeb
5200dd4f32aeSBjoern A. Zeeb if (enabled && !arsta->use_4addr_set) {
5201dd4f32aeSBjoern A. Zeeb ieee80211_queue_work(ar->hw, &arsta->set_4addr_wk);
5202dd4f32aeSBjoern A. Zeeb arsta->use_4addr_set = true;
5203dd4f32aeSBjoern A. Zeeb }
5204dd4f32aeSBjoern A. Zeeb }
5205dd4f32aeSBjoern A. Zeeb
ath11k_mac_op_sta_rc_update(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_sta * sta,u32 changed)5206dd4f32aeSBjoern A. Zeeb static void ath11k_mac_op_sta_rc_update(struct ieee80211_hw *hw,
5207dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif,
5208dd4f32aeSBjoern A. Zeeb struct ieee80211_sta *sta,
5209dd4f32aeSBjoern A. Zeeb u32 changed)
5210dd4f32aeSBjoern A. Zeeb {
5211dd4f32aeSBjoern A. Zeeb struct ath11k *ar = hw->priv;
5212dd4f32aeSBjoern A. Zeeb struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
5213dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif = (void *)vif->drv_priv;
5214dd4f32aeSBjoern A. Zeeb struct ath11k_peer *peer;
5215dd4f32aeSBjoern A. Zeeb u32 bw, smps;
5216dd4f32aeSBjoern A. Zeeb
5217dd4f32aeSBjoern A. Zeeb spin_lock_bh(&ar->ab->base_lock);
5218dd4f32aeSBjoern A. Zeeb
5219dd4f32aeSBjoern A. Zeeb peer = ath11k_peer_find(ar->ab, arvif->vdev_id, sta->addr);
5220dd4f32aeSBjoern A. Zeeb if (!peer) {
5221dd4f32aeSBjoern A. Zeeb spin_unlock_bh(&ar->ab->base_lock);
5222dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "mac sta rc update failed to find peer %pM on vdev %i\n",
5223dd4f32aeSBjoern A. Zeeb sta->addr, arvif->vdev_id);
5224dd4f32aeSBjoern A. Zeeb return;
5225dd4f32aeSBjoern A. Zeeb }
5226dd4f32aeSBjoern A. Zeeb
5227dd4f32aeSBjoern A. Zeeb spin_unlock_bh(&ar->ab->base_lock);
5228dd4f32aeSBjoern A. Zeeb
5229dd4f32aeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
523028348caeSBjoern A. Zeeb "sta rc update for %pM changed %08x bw %d nss %d smps %d\n",
5231dd4f32aeSBjoern A. Zeeb sta->addr, changed, sta->deflink.bandwidth,
5232dd4f32aeSBjoern A. Zeeb sta->deflink.rx_nss,
523328348caeSBjoern A. Zeeb sta->deflink.smps_mode);
5234dd4f32aeSBjoern A. Zeeb
5235dd4f32aeSBjoern A. Zeeb spin_lock_bh(&ar->data_lock);
5236dd4f32aeSBjoern A. Zeeb
5237dd4f32aeSBjoern A. Zeeb if (changed & IEEE80211_RC_BW_CHANGED) {
523828348caeSBjoern A. Zeeb bw = ath11k_mac_ieee80211_sta_bw_to_wmi(ar, sta);
523928348caeSBjoern A. Zeeb arsta->bw_prev = arsta->bw;
5240dd4f32aeSBjoern A. Zeeb arsta->bw = bw;
5241dd4f32aeSBjoern A. Zeeb }
5242dd4f32aeSBjoern A. Zeeb
5243dd4f32aeSBjoern A. Zeeb if (changed & IEEE80211_RC_NSS_CHANGED)
5244dd4f32aeSBjoern A. Zeeb arsta->nss = sta->deflink.rx_nss;
5245dd4f32aeSBjoern A. Zeeb
5246dd4f32aeSBjoern A. Zeeb if (changed & IEEE80211_RC_SMPS_CHANGED) {
5247dd4f32aeSBjoern A. Zeeb smps = WMI_PEER_SMPS_PS_NONE;
5248dd4f32aeSBjoern A. Zeeb
524928348caeSBjoern A. Zeeb switch (sta->deflink.smps_mode) {
5250dd4f32aeSBjoern A. Zeeb case IEEE80211_SMPS_AUTOMATIC:
5251dd4f32aeSBjoern A. Zeeb case IEEE80211_SMPS_OFF:
5252dd4f32aeSBjoern A. Zeeb smps = WMI_PEER_SMPS_PS_NONE;
5253dd4f32aeSBjoern A. Zeeb break;
5254dd4f32aeSBjoern A. Zeeb case IEEE80211_SMPS_STATIC:
5255dd4f32aeSBjoern A. Zeeb smps = WMI_PEER_SMPS_STATIC;
5256dd4f32aeSBjoern A. Zeeb break;
5257dd4f32aeSBjoern A. Zeeb case IEEE80211_SMPS_DYNAMIC:
5258dd4f32aeSBjoern A. Zeeb smps = WMI_PEER_SMPS_DYNAMIC;
5259dd4f32aeSBjoern A. Zeeb break;
5260dd4f32aeSBjoern A. Zeeb default:
5261dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "Invalid smps %d in sta rc update for %pM\n",
526228348caeSBjoern A. Zeeb sta->deflink.smps_mode, sta->addr);
5263dd4f32aeSBjoern A. Zeeb smps = WMI_PEER_SMPS_PS_NONE;
5264dd4f32aeSBjoern A. Zeeb break;
5265dd4f32aeSBjoern A. Zeeb }
5266dd4f32aeSBjoern A. Zeeb
5267dd4f32aeSBjoern A. Zeeb arsta->smps = smps;
5268dd4f32aeSBjoern A. Zeeb }
5269dd4f32aeSBjoern A. Zeeb
5270dd4f32aeSBjoern A. Zeeb arsta->changed |= changed;
5271dd4f32aeSBjoern A. Zeeb
5272dd4f32aeSBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
5273dd4f32aeSBjoern A. Zeeb
5274dd4f32aeSBjoern A. Zeeb ieee80211_queue_work(hw, &arsta->update_wk);
5275dd4f32aeSBjoern A. Zeeb }
5276dd4f32aeSBjoern A. Zeeb
ath11k_conf_tx_uapsd(struct ath11k * ar,struct ieee80211_vif * vif,u16 ac,bool enable)5277dd4f32aeSBjoern A. Zeeb static int ath11k_conf_tx_uapsd(struct ath11k *ar, struct ieee80211_vif *vif,
5278dd4f32aeSBjoern A. Zeeb u16 ac, bool enable)
5279dd4f32aeSBjoern A. Zeeb {
5280dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
5281dd4f32aeSBjoern A. Zeeb u32 value = 0;
5282dd4f32aeSBjoern A. Zeeb int ret = 0;
5283dd4f32aeSBjoern A. Zeeb
5284dd4f32aeSBjoern A. Zeeb if (arvif->vdev_type != WMI_VDEV_TYPE_STA)
5285dd4f32aeSBjoern A. Zeeb return 0;
5286dd4f32aeSBjoern A. Zeeb
5287dd4f32aeSBjoern A. Zeeb switch (ac) {
5288dd4f32aeSBjoern A. Zeeb case IEEE80211_AC_VO:
5289dd4f32aeSBjoern A. Zeeb value = WMI_STA_PS_UAPSD_AC3_DELIVERY_EN |
5290dd4f32aeSBjoern A. Zeeb WMI_STA_PS_UAPSD_AC3_TRIGGER_EN;
5291dd4f32aeSBjoern A. Zeeb break;
5292dd4f32aeSBjoern A. Zeeb case IEEE80211_AC_VI:
5293dd4f32aeSBjoern A. Zeeb value = WMI_STA_PS_UAPSD_AC2_DELIVERY_EN |
5294dd4f32aeSBjoern A. Zeeb WMI_STA_PS_UAPSD_AC2_TRIGGER_EN;
5295dd4f32aeSBjoern A. Zeeb break;
5296dd4f32aeSBjoern A. Zeeb case IEEE80211_AC_BE:
5297dd4f32aeSBjoern A. Zeeb value = WMI_STA_PS_UAPSD_AC1_DELIVERY_EN |
5298dd4f32aeSBjoern A. Zeeb WMI_STA_PS_UAPSD_AC1_TRIGGER_EN;
5299dd4f32aeSBjoern A. Zeeb break;
5300dd4f32aeSBjoern A. Zeeb case IEEE80211_AC_BK:
5301dd4f32aeSBjoern A. Zeeb value = WMI_STA_PS_UAPSD_AC0_DELIVERY_EN |
5302dd4f32aeSBjoern A. Zeeb WMI_STA_PS_UAPSD_AC0_TRIGGER_EN;
5303dd4f32aeSBjoern A. Zeeb break;
5304dd4f32aeSBjoern A. Zeeb }
5305dd4f32aeSBjoern A. Zeeb
5306dd4f32aeSBjoern A. Zeeb if (enable)
5307dd4f32aeSBjoern A. Zeeb arvif->u.sta.uapsd |= value;
5308dd4f32aeSBjoern A. Zeeb else
5309dd4f32aeSBjoern A. Zeeb arvif->u.sta.uapsd &= ~value;
5310dd4f32aeSBjoern A. Zeeb
5311dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_set_sta_ps_param(ar, arvif->vdev_id,
5312dd4f32aeSBjoern A. Zeeb WMI_STA_PS_PARAM_UAPSD,
5313dd4f32aeSBjoern A. Zeeb arvif->u.sta.uapsd);
5314dd4f32aeSBjoern A. Zeeb if (ret) {
5315dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "could not set uapsd params %d\n", ret);
5316dd4f32aeSBjoern A. Zeeb goto exit;
5317dd4f32aeSBjoern A. Zeeb }
5318dd4f32aeSBjoern A. Zeeb
5319dd4f32aeSBjoern A. Zeeb if (arvif->u.sta.uapsd)
5320dd4f32aeSBjoern A. Zeeb value = WMI_STA_PS_RX_WAKE_POLICY_POLL_UAPSD;
5321dd4f32aeSBjoern A. Zeeb else
5322dd4f32aeSBjoern A. Zeeb value = WMI_STA_PS_RX_WAKE_POLICY_WAKE;
5323dd4f32aeSBjoern A. Zeeb
5324dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_set_sta_ps_param(ar, arvif->vdev_id,
5325dd4f32aeSBjoern A. Zeeb WMI_STA_PS_PARAM_RX_WAKE_POLICY,
5326dd4f32aeSBjoern A. Zeeb value);
5327dd4f32aeSBjoern A. Zeeb if (ret)
5328dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "could not set rx wake param %d\n", ret);
5329dd4f32aeSBjoern A. Zeeb
5330dd4f32aeSBjoern A. Zeeb exit:
5331dd4f32aeSBjoern A. Zeeb return ret;
5332dd4f32aeSBjoern A. Zeeb }
5333dd4f32aeSBjoern A. Zeeb
ath11k_mac_op_conf_tx(struct ieee80211_hw * hw,struct ieee80211_vif * vif,unsigned int link_id,u16 ac,const struct ieee80211_tx_queue_params * params)5334dd4f32aeSBjoern A. Zeeb static int ath11k_mac_op_conf_tx(struct ieee80211_hw *hw,
5335dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif,
5336dd4f32aeSBjoern A. Zeeb unsigned int link_id, u16 ac,
5337dd4f32aeSBjoern A. Zeeb const struct ieee80211_tx_queue_params *params)
5338dd4f32aeSBjoern A. Zeeb {
5339dd4f32aeSBjoern A. Zeeb struct ath11k *ar = hw->priv;
5340dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif = (void *)vif->drv_priv;
5341dd4f32aeSBjoern A. Zeeb struct wmi_wmm_params_arg *p = NULL;
5342dd4f32aeSBjoern A. Zeeb int ret;
5343dd4f32aeSBjoern A. Zeeb
5344dd4f32aeSBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
5345dd4f32aeSBjoern A. Zeeb
5346dd4f32aeSBjoern A. Zeeb switch (ac) {
5347dd4f32aeSBjoern A. Zeeb case IEEE80211_AC_VO:
5348dd4f32aeSBjoern A. Zeeb p = &arvif->wmm_params.ac_vo;
5349dd4f32aeSBjoern A. Zeeb break;
5350dd4f32aeSBjoern A. Zeeb case IEEE80211_AC_VI:
5351dd4f32aeSBjoern A. Zeeb p = &arvif->wmm_params.ac_vi;
5352dd4f32aeSBjoern A. Zeeb break;
5353dd4f32aeSBjoern A. Zeeb case IEEE80211_AC_BE:
5354dd4f32aeSBjoern A. Zeeb p = &arvif->wmm_params.ac_be;
5355dd4f32aeSBjoern A. Zeeb break;
5356dd4f32aeSBjoern A. Zeeb case IEEE80211_AC_BK:
5357dd4f32aeSBjoern A. Zeeb p = &arvif->wmm_params.ac_bk;
5358dd4f32aeSBjoern A. Zeeb break;
5359dd4f32aeSBjoern A. Zeeb }
5360dd4f32aeSBjoern A. Zeeb
5361dd4f32aeSBjoern A. Zeeb if (WARN_ON(!p)) {
5362dd4f32aeSBjoern A. Zeeb ret = -EINVAL;
5363dd4f32aeSBjoern A. Zeeb goto exit;
5364dd4f32aeSBjoern A. Zeeb }
5365dd4f32aeSBjoern A. Zeeb
5366dd4f32aeSBjoern A. Zeeb p->cwmin = params->cw_min;
5367dd4f32aeSBjoern A. Zeeb p->cwmax = params->cw_max;
5368dd4f32aeSBjoern A. Zeeb p->aifs = params->aifs;
5369dd4f32aeSBjoern A. Zeeb p->txop = params->txop;
5370dd4f32aeSBjoern A. Zeeb
5371dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_send_wmm_update_cmd_tlv(ar, arvif->vdev_id,
5372dd4f32aeSBjoern A. Zeeb &arvif->wmm_params);
5373dd4f32aeSBjoern A. Zeeb if (ret) {
5374dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to set wmm params: %d\n", ret);
5375dd4f32aeSBjoern A. Zeeb goto exit;
5376dd4f32aeSBjoern A. Zeeb }
5377dd4f32aeSBjoern A. Zeeb
5378dd4f32aeSBjoern A. Zeeb ret = ath11k_conf_tx_uapsd(ar, vif, ac, params->uapsd);
5379dd4f32aeSBjoern A. Zeeb
5380dd4f32aeSBjoern A. Zeeb if (ret)
5381dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to set sta uapsd: %d\n", ret);
5382dd4f32aeSBjoern A. Zeeb
5383dd4f32aeSBjoern A. Zeeb exit:
5384dd4f32aeSBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
5385dd4f32aeSBjoern A. Zeeb return ret;
5386dd4f32aeSBjoern A. Zeeb }
5387dd4f32aeSBjoern A. Zeeb
5388dd4f32aeSBjoern A. Zeeb static struct ieee80211_sta_ht_cap
ath11k_create_ht_cap(struct ath11k * ar,u32 ar_ht_cap,u32 rate_cap_rx_chainmask)5389dd4f32aeSBjoern A. Zeeb ath11k_create_ht_cap(struct ath11k *ar, u32 ar_ht_cap, u32 rate_cap_rx_chainmask)
5390dd4f32aeSBjoern A. Zeeb {
5391dd4f32aeSBjoern A. Zeeb int i;
5392dd4f32aeSBjoern A. Zeeb struct ieee80211_sta_ht_cap ht_cap = {0};
5393dd4f32aeSBjoern A. Zeeb u32 ar_vht_cap = ar->pdev->cap.vht_cap;
5394dd4f32aeSBjoern A. Zeeb
5395dd4f32aeSBjoern A. Zeeb if (!(ar_ht_cap & WMI_HT_CAP_ENABLED))
5396dd4f32aeSBjoern A. Zeeb return ht_cap;
5397dd4f32aeSBjoern A. Zeeb
5398dd4f32aeSBjoern A. Zeeb ht_cap.ht_supported = 1;
5399dd4f32aeSBjoern A. Zeeb ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
5400dd4f32aeSBjoern A. Zeeb ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE;
5401dd4f32aeSBjoern A. Zeeb ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
5402dd4f32aeSBjoern A. Zeeb ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40;
5403dd4f32aeSBjoern A. Zeeb ht_cap.cap |= WLAN_HT_CAP_SM_PS_STATIC << IEEE80211_HT_CAP_SM_PS_SHIFT;
5404dd4f32aeSBjoern A. Zeeb
5405dd4f32aeSBjoern A. Zeeb if (ar_ht_cap & WMI_HT_CAP_HT20_SGI)
5406dd4f32aeSBjoern A. Zeeb ht_cap.cap |= IEEE80211_HT_CAP_SGI_20;
5407dd4f32aeSBjoern A. Zeeb
5408dd4f32aeSBjoern A. Zeeb if (ar_ht_cap & WMI_HT_CAP_HT40_SGI)
5409dd4f32aeSBjoern A. Zeeb ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
5410dd4f32aeSBjoern A. Zeeb
5411dd4f32aeSBjoern A. Zeeb if (ar_ht_cap & WMI_HT_CAP_DYNAMIC_SMPS) {
5412dd4f32aeSBjoern A. Zeeb u32 smps;
5413dd4f32aeSBjoern A. Zeeb
5414dd4f32aeSBjoern A. Zeeb smps = WLAN_HT_CAP_SM_PS_DYNAMIC;
5415dd4f32aeSBjoern A. Zeeb smps <<= IEEE80211_HT_CAP_SM_PS_SHIFT;
5416dd4f32aeSBjoern A. Zeeb
5417dd4f32aeSBjoern A. Zeeb ht_cap.cap |= smps;
5418dd4f32aeSBjoern A. Zeeb }
5419dd4f32aeSBjoern A. Zeeb
5420dd4f32aeSBjoern A. Zeeb if (ar_ht_cap & WMI_HT_CAP_TX_STBC)
5421dd4f32aeSBjoern A. Zeeb ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC;
5422dd4f32aeSBjoern A. Zeeb
5423dd4f32aeSBjoern A. Zeeb if (ar_ht_cap & WMI_HT_CAP_RX_STBC) {
5424dd4f32aeSBjoern A. Zeeb u32 stbc;
5425dd4f32aeSBjoern A. Zeeb
5426dd4f32aeSBjoern A. Zeeb stbc = ar_ht_cap;
5427dd4f32aeSBjoern A. Zeeb stbc &= WMI_HT_CAP_RX_STBC;
5428dd4f32aeSBjoern A. Zeeb stbc >>= WMI_HT_CAP_RX_STBC_MASK_SHIFT;
5429dd4f32aeSBjoern A. Zeeb stbc <<= IEEE80211_HT_CAP_RX_STBC_SHIFT;
5430dd4f32aeSBjoern A. Zeeb stbc &= IEEE80211_HT_CAP_RX_STBC;
5431dd4f32aeSBjoern A. Zeeb
5432dd4f32aeSBjoern A. Zeeb ht_cap.cap |= stbc;
5433dd4f32aeSBjoern A. Zeeb }
5434dd4f32aeSBjoern A. Zeeb
5435dd4f32aeSBjoern A. Zeeb if (ar_ht_cap & WMI_HT_CAP_RX_LDPC)
5436dd4f32aeSBjoern A. Zeeb ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING;
5437dd4f32aeSBjoern A. Zeeb
5438dd4f32aeSBjoern A. Zeeb if (ar_ht_cap & WMI_HT_CAP_L_SIG_TXOP_PROT)
5439dd4f32aeSBjoern A. Zeeb ht_cap.cap |= IEEE80211_HT_CAP_LSIG_TXOP_PROT;
5440dd4f32aeSBjoern A. Zeeb
5441dd4f32aeSBjoern A. Zeeb if (ar_vht_cap & WMI_VHT_CAP_MAX_MPDU_LEN_MASK)
5442dd4f32aeSBjoern A. Zeeb ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU;
5443dd4f32aeSBjoern A. Zeeb
5444dd4f32aeSBjoern A. Zeeb for (i = 0; i < ar->num_rx_chains; i++) {
5445dd4f32aeSBjoern A. Zeeb if (rate_cap_rx_chainmask & BIT(i))
5446dd4f32aeSBjoern A. Zeeb ht_cap.mcs.rx_mask[i] = 0xFF;
5447dd4f32aeSBjoern A. Zeeb }
5448dd4f32aeSBjoern A. Zeeb
5449dd4f32aeSBjoern A. Zeeb ht_cap.mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
5450dd4f32aeSBjoern A. Zeeb
5451dd4f32aeSBjoern A. Zeeb return ht_cap;
5452dd4f32aeSBjoern A. Zeeb }
5453dd4f32aeSBjoern A. Zeeb
ath11k_mac_set_txbf_conf(struct ath11k_vif * arvif)5454dd4f32aeSBjoern A. Zeeb static int ath11k_mac_set_txbf_conf(struct ath11k_vif *arvif)
5455dd4f32aeSBjoern A. Zeeb {
5456dd4f32aeSBjoern A. Zeeb u32 value = 0;
5457dd4f32aeSBjoern A. Zeeb struct ath11k *ar = arvif->ar;
5458dd4f32aeSBjoern A. Zeeb int nsts;
5459dd4f32aeSBjoern A. Zeeb int sound_dim;
5460dd4f32aeSBjoern A. Zeeb u32 vht_cap = ar->pdev->cap.vht_cap;
5461dd4f32aeSBjoern A. Zeeb u32 vdev_param = WMI_VDEV_PARAM_TXBF;
5462dd4f32aeSBjoern A. Zeeb
5463dd4f32aeSBjoern A. Zeeb if (vht_cap & (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE)) {
5464dd4f32aeSBjoern A. Zeeb nsts = vht_cap & IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK;
5465dd4f32aeSBjoern A. Zeeb nsts >>= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT;
546628348caeSBjoern A. Zeeb if (nsts > (ar->num_rx_chains - 1))
546728348caeSBjoern A. Zeeb nsts = ar->num_rx_chains - 1;
5468dd4f32aeSBjoern A. Zeeb value |= SM(nsts, WMI_TXBF_STS_CAP_OFFSET);
5469dd4f32aeSBjoern A. Zeeb }
5470dd4f32aeSBjoern A. Zeeb
5471dd4f32aeSBjoern A. Zeeb if (vht_cap & (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)) {
5472dd4f32aeSBjoern A. Zeeb sound_dim = vht_cap &
5473dd4f32aeSBjoern A. Zeeb IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK;
5474dd4f32aeSBjoern A. Zeeb sound_dim >>= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT;
5475dd4f32aeSBjoern A. Zeeb if (sound_dim > (ar->num_tx_chains - 1))
5476dd4f32aeSBjoern A. Zeeb sound_dim = ar->num_tx_chains - 1;
5477dd4f32aeSBjoern A. Zeeb value |= SM(sound_dim, WMI_BF_SOUND_DIM_OFFSET);
5478dd4f32aeSBjoern A. Zeeb }
5479dd4f32aeSBjoern A. Zeeb
5480dd4f32aeSBjoern A. Zeeb if (!value)
5481dd4f32aeSBjoern A. Zeeb return 0;
5482dd4f32aeSBjoern A. Zeeb
5483dd4f32aeSBjoern A. Zeeb if (vht_cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE) {
5484dd4f32aeSBjoern A. Zeeb value |= WMI_VDEV_PARAM_TXBF_SU_TX_BFER;
5485dd4f32aeSBjoern A. Zeeb
5486dd4f32aeSBjoern A. Zeeb if ((vht_cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) &&
5487dd4f32aeSBjoern A. Zeeb arvif->vdev_type == WMI_VDEV_TYPE_AP)
5488dd4f32aeSBjoern A. Zeeb value |= WMI_VDEV_PARAM_TXBF_MU_TX_BFER;
5489dd4f32aeSBjoern A. Zeeb }
5490dd4f32aeSBjoern A. Zeeb
5491dd4f32aeSBjoern A. Zeeb /* TODO: SUBFEE not validated in HK, disable here until validated? */
5492dd4f32aeSBjoern A. Zeeb
5493dd4f32aeSBjoern A. Zeeb if (vht_cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE) {
5494dd4f32aeSBjoern A. Zeeb value |= WMI_VDEV_PARAM_TXBF_SU_TX_BFEE;
5495dd4f32aeSBjoern A. Zeeb
5496dd4f32aeSBjoern A. Zeeb if ((vht_cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE) &&
5497dd4f32aeSBjoern A. Zeeb arvif->vdev_type == WMI_VDEV_TYPE_STA)
5498dd4f32aeSBjoern A. Zeeb value |= WMI_VDEV_PARAM_TXBF_MU_TX_BFEE;
5499dd4f32aeSBjoern A. Zeeb }
5500dd4f32aeSBjoern A. Zeeb
5501dd4f32aeSBjoern A. Zeeb return ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
5502dd4f32aeSBjoern A. Zeeb vdev_param, value);
5503dd4f32aeSBjoern A. Zeeb }
5504dd4f32aeSBjoern A. Zeeb
ath11k_set_vht_txbf_cap(struct ath11k * ar,u32 * vht_cap)5505dd4f32aeSBjoern A. Zeeb static void ath11k_set_vht_txbf_cap(struct ath11k *ar, u32 *vht_cap)
5506dd4f32aeSBjoern A. Zeeb {
5507dd4f32aeSBjoern A. Zeeb bool subfer, subfee;
550828348caeSBjoern A. Zeeb int sound_dim = 0, nsts = 0;
5509dd4f32aeSBjoern A. Zeeb
5510dd4f32aeSBjoern A. Zeeb subfer = !!(*vht_cap & (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE));
5511dd4f32aeSBjoern A. Zeeb subfee = !!(*vht_cap & (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE));
5512dd4f32aeSBjoern A. Zeeb
5513dd4f32aeSBjoern A. Zeeb if (ar->num_tx_chains < 2) {
5514dd4f32aeSBjoern A. Zeeb *vht_cap &= ~(IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE);
5515dd4f32aeSBjoern A. Zeeb subfer = false;
5516dd4f32aeSBjoern A. Zeeb }
5517dd4f32aeSBjoern A. Zeeb
551828348caeSBjoern A. Zeeb if (ar->num_rx_chains < 2) {
551928348caeSBjoern A. Zeeb *vht_cap &= ~(IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE);
552028348caeSBjoern A. Zeeb subfee = false;
552128348caeSBjoern A. Zeeb }
552228348caeSBjoern A. Zeeb
5523dd4f32aeSBjoern A. Zeeb /* If SU Beaformer is not set, then disable MU Beamformer Capability */
5524dd4f32aeSBjoern A. Zeeb if (!subfer)
5525dd4f32aeSBjoern A. Zeeb *vht_cap &= ~(IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE);
5526dd4f32aeSBjoern A. Zeeb
5527dd4f32aeSBjoern A. Zeeb /* If SU Beaformee is not set, then disable MU Beamformee Capability */
5528dd4f32aeSBjoern A. Zeeb if (!subfee)
5529dd4f32aeSBjoern A. Zeeb *vht_cap &= ~(IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE);
5530dd4f32aeSBjoern A. Zeeb
5531dd4f32aeSBjoern A. Zeeb sound_dim = (*vht_cap & IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK);
5532dd4f32aeSBjoern A. Zeeb sound_dim >>= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT;
5533dd4f32aeSBjoern A. Zeeb *vht_cap &= ~IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK;
5534dd4f32aeSBjoern A. Zeeb
553528348caeSBjoern A. Zeeb nsts = (*vht_cap & IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK);
553628348caeSBjoern A. Zeeb nsts >>= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT;
553728348caeSBjoern A. Zeeb *vht_cap &= ~IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK;
5538dd4f32aeSBjoern A. Zeeb
5539dd4f32aeSBjoern A. Zeeb /* Enable Sounding Dimension Field only if SU BF is enabled */
5540dd4f32aeSBjoern A. Zeeb if (subfer) {
5541dd4f32aeSBjoern A. Zeeb if (sound_dim > (ar->num_tx_chains - 1))
5542dd4f32aeSBjoern A. Zeeb sound_dim = ar->num_tx_chains - 1;
5543dd4f32aeSBjoern A. Zeeb
5544dd4f32aeSBjoern A. Zeeb sound_dim <<= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT;
5545dd4f32aeSBjoern A. Zeeb sound_dim &= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK;
5546dd4f32aeSBjoern A. Zeeb *vht_cap |= sound_dim;
5547dd4f32aeSBjoern A. Zeeb }
5548dd4f32aeSBjoern A. Zeeb
554928348caeSBjoern A. Zeeb /* Enable Beamformee STS Field only if SU BF is enabled */
555028348caeSBjoern A. Zeeb if (subfee) {
555128348caeSBjoern A. Zeeb if (nsts > (ar->num_rx_chains - 1))
555228348caeSBjoern A. Zeeb nsts = ar->num_rx_chains - 1;
555328348caeSBjoern A. Zeeb
555428348caeSBjoern A. Zeeb nsts <<= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT;
555528348caeSBjoern A. Zeeb nsts &= IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK;
555628348caeSBjoern A. Zeeb *vht_cap |= nsts;
555728348caeSBjoern A. Zeeb }
5558dd4f32aeSBjoern A. Zeeb }
5559dd4f32aeSBjoern A. Zeeb
5560dd4f32aeSBjoern A. Zeeb static struct ieee80211_sta_vht_cap
ath11k_create_vht_cap(struct ath11k * ar,u32 rate_cap_tx_chainmask,u32 rate_cap_rx_chainmask)5561dd4f32aeSBjoern A. Zeeb ath11k_create_vht_cap(struct ath11k *ar, u32 rate_cap_tx_chainmask,
5562dd4f32aeSBjoern A. Zeeb u32 rate_cap_rx_chainmask)
5563dd4f32aeSBjoern A. Zeeb {
5564dd4f32aeSBjoern A. Zeeb struct ieee80211_sta_vht_cap vht_cap = {0};
5565dd4f32aeSBjoern A. Zeeb u16 txmcs_map, rxmcs_map;
5566dd4f32aeSBjoern A. Zeeb int i;
5567dd4f32aeSBjoern A. Zeeb
5568dd4f32aeSBjoern A. Zeeb vht_cap.vht_supported = 1;
5569dd4f32aeSBjoern A. Zeeb vht_cap.cap = ar->pdev->cap.vht_cap;
5570dd4f32aeSBjoern A. Zeeb
5571dd4f32aeSBjoern A. Zeeb if (ar->pdev->cap.nss_ratio_enabled)
5572dd4f32aeSBjoern A. Zeeb vht_cap.vht_mcs.tx_highest |=
5573dd4f32aeSBjoern A. Zeeb cpu_to_le16(IEEE80211_VHT_EXT_NSS_BW_CAPABLE);
5574dd4f32aeSBjoern A. Zeeb
5575dd4f32aeSBjoern A. Zeeb ath11k_set_vht_txbf_cap(ar, &vht_cap.cap);
5576dd4f32aeSBjoern A. Zeeb
5577dd4f32aeSBjoern A. Zeeb rxmcs_map = 0;
5578dd4f32aeSBjoern A. Zeeb txmcs_map = 0;
5579dd4f32aeSBjoern A. Zeeb for (i = 0; i < 8; i++) {
5580dd4f32aeSBjoern A. Zeeb if (i < ar->num_tx_chains && rate_cap_tx_chainmask & BIT(i))
5581dd4f32aeSBjoern A. Zeeb txmcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i * 2);
5582dd4f32aeSBjoern A. Zeeb else
5583dd4f32aeSBjoern A. Zeeb txmcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i * 2);
5584dd4f32aeSBjoern A. Zeeb
5585dd4f32aeSBjoern A. Zeeb if (i < ar->num_rx_chains && rate_cap_rx_chainmask & BIT(i))
5586dd4f32aeSBjoern A. Zeeb rxmcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i * 2);
5587dd4f32aeSBjoern A. Zeeb else
5588dd4f32aeSBjoern A. Zeeb rxmcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i * 2);
5589dd4f32aeSBjoern A. Zeeb }
5590dd4f32aeSBjoern A. Zeeb
5591dd4f32aeSBjoern A. Zeeb if (rate_cap_tx_chainmask <= 1)
5592dd4f32aeSBjoern A. Zeeb vht_cap.cap &= ~IEEE80211_VHT_CAP_TXSTBC;
5593dd4f32aeSBjoern A. Zeeb
5594dd4f32aeSBjoern A. Zeeb vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(rxmcs_map);
5595dd4f32aeSBjoern A. Zeeb vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(txmcs_map);
5596dd4f32aeSBjoern A. Zeeb
5597dd4f32aeSBjoern A. Zeeb return vht_cap;
5598dd4f32aeSBjoern A. Zeeb }
5599dd4f32aeSBjoern A. Zeeb
ath11k_mac_setup_ht_vht_cap(struct ath11k * ar,struct ath11k_pdev_cap * cap,u32 * ht_cap_info)5600dd4f32aeSBjoern A. Zeeb static void ath11k_mac_setup_ht_vht_cap(struct ath11k *ar,
5601dd4f32aeSBjoern A. Zeeb struct ath11k_pdev_cap *cap,
5602dd4f32aeSBjoern A. Zeeb u32 *ht_cap_info)
5603dd4f32aeSBjoern A. Zeeb {
5604dd4f32aeSBjoern A. Zeeb struct ieee80211_supported_band *band;
5605dd4f32aeSBjoern A. Zeeb u32 rate_cap_tx_chainmask;
5606dd4f32aeSBjoern A. Zeeb u32 rate_cap_rx_chainmask;
5607dd4f32aeSBjoern A. Zeeb u32 ht_cap;
5608dd4f32aeSBjoern A. Zeeb
5609dd4f32aeSBjoern A. Zeeb rate_cap_tx_chainmask = ar->cfg_tx_chainmask >> cap->tx_chain_mask_shift;
5610dd4f32aeSBjoern A. Zeeb rate_cap_rx_chainmask = ar->cfg_rx_chainmask >> cap->rx_chain_mask_shift;
5611dd4f32aeSBjoern A. Zeeb
5612dd4f32aeSBjoern A. Zeeb if (cap->supported_bands & WMI_HOST_WLAN_2G_CAP) {
5613dd4f32aeSBjoern A. Zeeb band = &ar->mac.sbands[NL80211_BAND_2GHZ];
5614dd4f32aeSBjoern A. Zeeb ht_cap = cap->band[NL80211_BAND_2GHZ].ht_cap_info;
5615dd4f32aeSBjoern A. Zeeb if (ht_cap_info)
5616dd4f32aeSBjoern A. Zeeb *ht_cap_info = ht_cap;
5617dd4f32aeSBjoern A. Zeeb band->ht_cap = ath11k_create_ht_cap(ar, ht_cap,
5618dd4f32aeSBjoern A. Zeeb rate_cap_rx_chainmask);
5619dd4f32aeSBjoern A. Zeeb }
5620dd4f32aeSBjoern A. Zeeb
5621dd4f32aeSBjoern A. Zeeb if (cap->supported_bands & WMI_HOST_WLAN_5G_CAP &&
5622dd4f32aeSBjoern A. Zeeb (ar->ab->hw_params.single_pdev_only ||
5623dd4f32aeSBjoern A. Zeeb !ar->supports_6ghz)) {
5624dd4f32aeSBjoern A. Zeeb band = &ar->mac.sbands[NL80211_BAND_5GHZ];
5625dd4f32aeSBjoern A. Zeeb ht_cap = cap->band[NL80211_BAND_5GHZ].ht_cap_info;
5626dd4f32aeSBjoern A. Zeeb if (ht_cap_info)
5627dd4f32aeSBjoern A. Zeeb *ht_cap_info = ht_cap;
5628dd4f32aeSBjoern A. Zeeb band->ht_cap = ath11k_create_ht_cap(ar, ht_cap,
5629dd4f32aeSBjoern A. Zeeb rate_cap_rx_chainmask);
5630dd4f32aeSBjoern A. Zeeb band->vht_cap = ath11k_create_vht_cap(ar, rate_cap_tx_chainmask,
5631dd4f32aeSBjoern A. Zeeb rate_cap_rx_chainmask);
5632dd4f32aeSBjoern A. Zeeb }
5633dd4f32aeSBjoern A. Zeeb }
5634dd4f32aeSBjoern A. Zeeb
ath11k_check_chain_mask(struct ath11k * ar,u32 ant,bool is_tx_ant)5635dd4f32aeSBjoern A. Zeeb static int ath11k_check_chain_mask(struct ath11k *ar, u32 ant, bool is_tx_ant)
5636dd4f32aeSBjoern A. Zeeb {
5637dd4f32aeSBjoern A. Zeeb /* TODO: Check the request chainmask against the supported
5638dd4f32aeSBjoern A. Zeeb * chainmask table which is advertised in extented_service_ready event
5639dd4f32aeSBjoern A. Zeeb */
5640dd4f32aeSBjoern A. Zeeb
5641dd4f32aeSBjoern A. Zeeb return 0;
5642dd4f32aeSBjoern A. Zeeb }
5643dd4f32aeSBjoern A. Zeeb
ath11k_gen_ppe_thresh(struct ath11k_ppe_threshold * fw_ppet,u8 * he_ppet)5644dd4f32aeSBjoern A. Zeeb static void ath11k_gen_ppe_thresh(struct ath11k_ppe_threshold *fw_ppet,
5645dd4f32aeSBjoern A. Zeeb u8 *he_ppet)
5646dd4f32aeSBjoern A. Zeeb {
5647dd4f32aeSBjoern A. Zeeb int nss, ru;
5648dd4f32aeSBjoern A. Zeeb u8 bit = 7;
5649dd4f32aeSBjoern A. Zeeb
5650dd4f32aeSBjoern A. Zeeb he_ppet[0] = fw_ppet->numss_m1 & IEEE80211_PPE_THRES_NSS_MASK;
5651dd4f32aeSBjoern A. Zeeb he_ppet[0] |= (fw_ppet->ru_bit_mask <<
5652dd4f32aeSBjoern A. Zeeb IEEE80211_PPE_THRES_RU_INDEX_BITMASK_POS) &
5653dd4f32aeSBjoern A. Zeeb IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK;
5654dd4f32aeSBjoern A. Zeeb for (nss = 0; nss <= fw_ppet->numss_m1; nss++) {
5655dd4f32aeSBjoern A. Zeeb for (ru = 0; ru < 4; ru++) {
5656dd4f32aeSBjoern A. Zeeb u8 val;
5657dd4f32aeSBjoern A. Zeeb int i;
5658dd4f32aeSBjoern A. Zeeb
5659dd4f32aeSBjoern A. Zeeb if ((fw_ppet->ru_bit_mask & BIT(ru)) == 0)
5660dd4f32aeSBjoern A. Zeeb continue;
5661dd4f32aeSBjoern A. Zeeb val = (fw_ppet->ppet16_ppet8_ru3_ru0[nss] >> (ru * 6)) &
5662dd4f32aeSBjoern A. Zeeb 0x3f;
5663dd4f32aeSBjoern A. Zeeb val = ((val >> 3) & 0x7) | ((val & 0x7) << 3);
5664dd4f32aeSBjoern A. Zeeb for (i = 5; i >= 0; i--) {
5665dd4f32aeSBjoern A. Zeeb he_ppet[bit / 8] |=
5666dd4f32aeSBjoern A. Zeeb ((val >> i) & 0x1) << ((bit % 8));
5667dd4f32aeSBjoern A. Zeeb bit++;
5668dd4f32aeSBjoern A. Zeeb }
5669dd4f32aeSBjoern A. Zeeb }
5670dd4f32aeSBjoern A. Zeeb }
5671dd4f32aeSBjoern A. Zeeb }
5672dd4f32aeSBjoern A. Zeeb
5673dd4f32aeSBjoern A. Zeeb static void
ath11k_mac_filter_he_cap_mesh(struct ieee80211_he_cap_elem * he_cap_elem)5674dd4f32aeSBjoern A. Zeeb ath11k_mac_filter_he_cap_mesh(struct ieee80211_he_cap_elem *he_cap_elem)
5675dd4f32aeSBjoern A. Zeeb {
5676dd4f32aeSBjoern A. Zeeb u8 m;
5677dd4f32aeSBjoern A. Zeeb
5678dd4f32aeSBjoern A. Zeeb m = IEEE80211_HE_MAC_CAP0_TWT_RES |
5679dd4f32aeSBjoern A. Zeeb IEEE80211_HE_MAC_CAP0_TWT_REQ;
5680dd4f32aeSBjoern A. Zeeb he_cap_elem->mac_cap_info[0] &= ~m;
5681dd4f32aeSBjoern A. Zeeb
5682dd4f32aeSBjoern A. Zeeb m = IEEE80211_HE_MAC_CAP2_TRS |
5683dd4f32aeSBjoern A. Zeeb IEEE80211_HE_MAC_CAP2_BCAST_TWT |
5684dd4f32aeSBjoern A. Zeeb IEEE80211_HE_MAC_CAP2_MU_CASCADING;
5685dd4f32aeSBjoern A. Zeeb he_cap_elem->mac_cap_info[2] &= ~m;
5686dd4f32aeSBjoern A. Zeeb
5687dd4f32aeSBjoern A. Zeeb m = IEEE80211_HE_MAC_CAP3_FLEX_TWT_SCHED |
5688dd4f32aeSBjoern A. Zeeb IEEE80211_HE_MAC_CAP2_BCAST_TWT |
5689dd4f32aeSBjoern A. Zeeb IEEE80211_HE_MAC_CAP2_MU_CASCADING;
5690dd4f32aeSBjoern A. Zeeb he_cap_elem->mac_cap_info[3] &= ~m;
5691dd4f32aeSBjoern A. Zeeb
5692dd4f32aeSBjoern A. Zeeb m = IEEE80211_HE_MAC_CAP4_BSRP_BQRP_A_MPDU_AGG |
5693dd4f32aeSBjoern A. Zeeb IEEE80211_HE_MAC_CAP4_BQR;
5694dd4f32aeSBjoern A. Zeeb he_cap_elem->mac_cap_info[4] &= ~m;
5695dd4f32aeSBjoern A. Zeeb
5696dd4f32aeSBjoern A. Zeeb m = IEEE80211_HE_MAC_CAP5_SUBCHAN_SELECTIVE_TRANSMISSION |
5697dd4f32aeSBjoern A. Zeeb IEEE80211_HE_MAC_CAP5_UL_2x996_TONE_RU |
5698dd4f32aeSBjoern A. Zeeb IEEE80211_HE_MAC_CAP5_PUNCTURED_SOUNDING |
5699dd4f32aeSBjoern A. Zeeb IEEE80211_HE_MAC_CAP5_HT_VHT_TRIG_FRAME_RX;
5700dd4f32aeSBjoern A. Zeeb he_cap_elem->mac_cap_info[5] &= ~m;
5701dd4f32aeSBjoern A. Zeeb
5702dd4f32aeSBjoern A. Zeeb m = IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO |
5703dd4f32aeSBjoern A. Zeeb IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO;
5704dd4f32aeSBjoern A. Zeeb he_cap_elem->phy_cap_info[2] &= ~m;
5705dd4f32aeSBjoern A. Zeeb
5706dd4f32aeSBjoern A. Zeeb m = IEEE80211_HE_PHY_CAP3_RX_PARTIAL_BW_SU_IN_20MHZ_MU |
5707dd4f32aeSBjoern A. Zeeb IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_MASK |
5708dd4f32aeSBjoern A. Zeeb IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_MASK;
5709dd4f32aeSBjoern A. Zeeb he_cap_elem->phy_cap_info[3] &= ~m;
5710dd4f32aeSBjoern A. Zeeb
5711dd4f32aeSBjoern A. Zeeb m = IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER;
5712dd4f32aeSBjoern A. Zeeb he_cap_elem->phy_cap_info[4] &= ~m;
5713dd4f32aeSBjoern A. Zeeb
5714dd4f32aeSBjoern A. Zeeb m = IEEE80211_HE_PHY_CAP5_NG16_MU_FEEDBACK;
5715dd4f32aeSBjoern A. Zeeb he_cap_elem->phy_cap_info[5] &= ~m;
5716dd4f32aeSBjoern A. Zeeb
5717dd4f32aeSBjoern A. Zeeb m = IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU |
5718dd4f32aeSBjoern A. Zeeb IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMING_PARTIAL_BW_FB |
5719dd4f32aeSBjoern A. Zeeb IEEE80211_HE_PHY_CAP6_TRIG_CQI_FB |
5720dd4f32aeSBjoern A. Zeeb IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO;
5721dd4f32aeSBjoern A. Zeeb he_cap_elem->phy_cap_info[6] &= ~m;
5722dd4f32aeSBjoern A. Zeeb
5723dd4f32aeSBjoern A. Zeeb m = IEEE80211_HE_PHY_CAP7_PSR_BASED_SR |
5724dd4f32aeSBjoern A. Zeeb IEEE80211_HE_PHY_CAP7_POWER_BOOST_FACTOR_SUPP |
5725dd4f32aeSBjoern A. Zeeb IEEE80211_HE_PHY_CAP7_STBC_TX_ABOVE_80MHZ |
5726dd4f32aeSBjoern A. Zeeb IEEE80211_HE_PHY_CAP7_STBC_RX_ABOVE_80MHZ;
5727dd4f32aeSBjoern A. Zeeb he_cap_elem->phy_cap_info[7] &= ~m;
5728dd4f32aeSBjoern A. Zeeb
5729dd4f32aeSBjoern A. Zeeb m = IEEE80211_HE_PHY_CAP8_HE_ER_SU_PPDU_4XLTF_AND_08_US_GI |
5730dd4f32aeSBjoern A. Zeeb IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G |
5731dd4f32aeSBjoern A. Zeeb IEEE80211_HE_PHY_CAP8_20MHZ_IN_160MHZ_HE_PPDU |
5732dd4f32aeSBjoern A. Zeeb IEEE80211_HE_PHY_CAP8_80MHZ_IN_160MHZ_HE_PPDU;
5733dd4f32aeSBjoern A. Zeeb he_cap_elem->phy_cap_info[8] &= ~m;
5734dd4f32aeSBjoern A. Zeeb
5735dd4f32aeSBjoern A. Zeeb m = IEEE80211_HE_PHY_CAP9_LONGER_THAN_16_SIGB_OFDM_SYM |
5736dd4f32aeSBjoern A. Zeeb IEEE80211_HE_PHY_CAP9_NON_TRIGGERED_CQI_FEEDBACK |
5737dd4f32aeSBjoern A. Zeeb IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU |
5738dd4f32aeSBjoern A. Zeeb IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU |
5739dd4f32aeSBjoern A. Zeeb IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB |
5740dd4f32aeSBjoern A. Zeeb IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB;
5741dd4f32aeSBjoern A. Zeeb he_cap_elem->phy_cap_info[9] &= ~m;
5742dd4f32aeSBjoern A. Zeeb }
5743dd4f32aeSBjoern A. Zeeb
ath11k_mac_setup_he_6ghz_cap(struct ath11k_pdev_cap * pcap,struct ath11k_band_cap * bcap)5744dd4f32aeSBjoern A. Zeeb static __le16 ath11k_mac_setup_he_6ghz_cap(struct ath11k_pdev_cap *pcap,
5745dd4f32aeSBjoern A. Zeeb struct ath11k_band_cap *bcap)
5746dd4f32aeSBjoern A. Zeeb {
5747dd4f32aeSBjoern A. Zeeb u8 val;
5748dd4f32aeSBjoern A. Zeeb
5749dd4f32aeSBjoern A. Zeeb bcap->he_6ghz_capa = IEEE80211_HT_MPDU_DENSITY_NONE;
5750dd4f32aeSBjoern A. Zeeb if (bcap->ht_cap_info & WMI_HT_CAP_DYNAMIC_SMPS)
5751dd4f32aeSBjoern A. Zeeb bcap->he_6ghz_capa |=
5752dd4f32aeSBjoern A. Zeeb FIELD_PREP(IEEE80211_HE_6GHZ_CAP_SM_PS,
5753dd4f32aeSBjoern A. Zeeb WLAN_HT_CAP_SM_PS_DYNAMIC);
5754dd4f32aeSBjoern A. Zeeb else
5755dd4f32aeSBjoern A. Zeeb bcap->he_6ghz_capa |=
5756dd4f32aeSBjoern A. Zeeb FIELD_PREP(IEEE80211_HE_6GHZ_CAP_SM_PS,
5757dd4f32aeSBjoern A. Zeeb WLAN_HT_CAP_SM_PS_DISABLED);
5758dd4f32aeSBjoern A. Zeeb val = FIELD_GET(IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK,
5759dd4f32aeSBjoern A. Zeeb pcap->vht_cap);
5760dd4f32aeSBjoern A. Zeeb bcap->he_6ghz_capa |=
5761dd4f32aeSBjoern A. Zeeb FIELD_PREP(IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP, val);
5762dd4f32aeSBjoern A. Zeeb val = FIELD_GET(IEEE80211_VHT_CAP_MAX_MPDU_MASK, pcap->vht_cap);
5763dd4f32aeSBjoern A. Zeeb bcap->he_6ghz_capa |=
5764dd4f32aeSBjoern A. Zeeb FIELD_PREP(IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN, val);
5765dd4f32aeSBjoern A. Zeeb if (pcap->vht_cap & IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN)
5766dd4f32aeSBjoern A. Zeeb bcap->he_6ghz_capa |= IEEE80211_HE_6GHZ_CAP_RX_ANTPAT_CONS;
5767dd4f32aeSBjoern A. Zeeb if (pcap->vht_cap & IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN)
5768dd4f32aeSBjoern A. Zeeb bcap->he_6ghz_capa |= IEEE80211_HE_6GHZ_CAP_TX_ANTPAT_CONS;
5769dd4f32aeSBjoern A. Zeeb
5770dd4f32aeSBjoern A. Zeeb return cpu_to_le16(bcap->he_6ghz_capa);
5771dd4f32aeSBjoern A. Zeeb }
5772dd4f32aeSBjoern A. Zeeb
ath11k_mac_set_hemcsmap(struct ath11k * ar,struct ath11k_pdev_cap * cap,struct ieee80211_sta_he_cap * he_cap,int band)577328348caeSBjoern A. Zeeb static void ath11k_mac_set_hemcsmap(struct ath11k *ar,
577428348caeSBjoern A. Zeeb struct ath11k_pdev_cap *cap,
577528348caeSBjoern A. Zeeb struct ieee80211_sta_he_cap *he_cap,
577628348caeSBjoern A. Zeeb int band)
577728348caeSBjoern A. Zeeb {
577828348caeSBjoern A. Zeeb u16 txmcs_map, rxmcs_map;
577928348caeSBjoern A. Zeeb u32 i;
578028348caeSBjoern A. Zeeb
578128348caeSBjoern A. Zeeb rxmcs_map = 0;
578228348caeSBjoern A. Zeeb txmcs_map = 0;
578328348caeSBjoern A. Zeeb for (i = 0; i < 8; i++) {
578428348caeSBjoern A. Zeeb if (i < ar->num_tx_chains &&
578528348caeSBjoern A. Zeeb (ar->cfg_tx_chainmask >> cap->tx_chain_mask_shift) & BIT(i))
578628348caeSBjoern A. Zeeb txmcs_map |= IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2);
578728348caeSBjoern A. Zeeb else
578828348caeSBjoern A. Zeeb txmcs_map |= IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2);
578928348caeSBjoern A. Zeeb
579028348caeSBjoern A. Zeeb if (i < ar->num_rx_chains &&
579128348caeSBjoern A. Zeeb (ar->cfg_rx_chainmask >> cap->tx_chain_mask_shift) & BIT(i))
579228348caeSBjoern A. Zeeb rxmcs_map |= IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2);
579328348caeSBjoern A. Zeeb else
579428348caeSBjoern A. Zeeb rxmcs_map |= IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2);
579528348caeSBjoern A. Zeeb }
579628348caeSBjoern A. Zeeb he_cap->he_mcs_nss_supp.rx_mcs_80 =
579728348caeSBjoern A. Zeeb cpu_to_le16(rxmcs_map & 0xffff);
579828348caeSBjoern A. Zeeb he_cap->he_mcs_nss_supp.tx_mcs_80 =
579928348caeSBjoern A. Zeeb cpu_to_le16(txmcs_map & 0xffff);
580028348caeSBjoern A. Zeeb he_cap->he_mcs_nss_supp.rx_mcs_160 =
580128348caeSBjoern A. Zeeb cpu_to_le16(rxmcs_map & 0xffff);
580228348caeSBjoern A. Zeeb he_cap->he_mcs_nss_supp.tx_mcs_160 =
580328348caeSBjoern A. Zeeb cpu_to_le16(txmcs_map & 0xffff);
580428348caeSBjoern A. Zeeb he_cap->he_mcs_nss_supp.rx_mcs_80p80 =
580528348caeSBjoern A. Zeeb cpu_to_le16(rxmcs_map & 0xffff);
580628348caeSBjoern A. Zeeb he_cap->he_mcs_nss_supp.tx_mcs_80p80 =
580728348caeSBjoern A. Zeeb cpu_to_le16(txmcs_map & 0xffff);
580828348caeSBjoern A. Zeeb }
580928348caeSBjoern A. Zeeb
ath11k_mac_copy_he_cap(struct ath11k * ar,struct ath11k_pdev_cap * cap,struct ieee80211_sband_iftype_data * data,int band)5810dd4f32aeSBjoern A. Zeeb static int ath11k_mac_copy_he_cap(struct ath11k *ar,
5811dd4f32aeSBjoern A. Zeeb struct ath11k_pdev_cap *cap,
5812dd4f32aeSBjoern A. Zeeb struct ieee80211_sband_iftype_data *data,
5813dd4f32aeSBjoern A. Zeeb int band)
5814dd4f32aeSBjoern A. Zeeb {
5815dd4f32aeSBjoern A. Zeeb int i, idx = 0;
5816dd4f32aeSBjoern A. Zeeb
5817dd4f32aeSBjoern A. Zeeb for (i = 0; i < NUM_NL80211_IFTYPES; i++) {
5818dd4f32aeSBjoern A. Zeeb struct ieee80211_sta_he_cap *he_cap = &data[idx].he_cap;
5819dd4f32aeSBjoern A. Zeeb struct ath11k_band_cap *band_cap = &cap->band[band];
5820dd4f32aeSBjoern A. Zeeb struct ieee80211_he_cap_elem *he_cap_elem =
5821dd4f32aeSBjoern A. Zeeb &he_cap->he_cap_elem;
5822dd4f32aeSBjoern A. Zeeb
5823dd4f32aeSBjoern A. Zeeb switch (i) {
5824dd4f32aeSBjoern A. Zeeb case NL80211_IFTYPE_STATION:
5825dd4f32aeSBjoern A. Zeeb case NL80211_IFTYPE_AP:
5826dd4f32aeSBjoern A. Zeeb case NL80211_IFTYPE_MESH_POINT:
5827dd4f32aeSBjoern A. Zeeb break;
5828dd4f32aeSBjoern A. Zeeb
5829dd4f32aeSBjoern A. Zeeb default:
5830dd4f32aeSBjoern A. Zeeb continue;
5831dd4f32aeSBjoern A. Zeeb }
5832dd4f32aeSBjoern A. Zeeb
5833dd4f32aeSBjoern A. Zeeb data[idx].types_mask = BIT(i);
5834dd4f32aeSBjoern A. Zeeb he_cap->has_he = true;
5835dd4f32aeSBjoern A. Zeeb memcpy(he_cap_elem->mac_cap_info, band_cap->he_cap_info,
5836dd4f32aeSBjoern A. Zeeb sizeof(he_cap_elem->mac_cap_info));
5837dd4f32aeSBjoern A. Zeeb memcpy(he_cap_elem->phy_cap_info, band_cap->he_cap_phy_info,
5838dd4f32aeSBjoern A. Zeeb sizeof(he_cap_elem->phy_cap_info));
5839dd4f32aeSBjoern A. Zeeb
5840dd4f32aeSBjoern A. Zeeb he_cap_elem->mac_cap_info[1] &=
5841dd4f32aeSBjoern A. Zeeb IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_MASK;
5842dd4f32aeSBjoern A. Zeeb
5843dd4f32aeSBjoern A. Zeeb he_cap_elem->phy_cap_info[5] &=
5844dd4f32aeSBjoern A. Zeeb ~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK;
5845dd4f32aeSBjoern A. Zeeb he_cap_elem->phy_cap_info[5] |= ar->num_tx_chains - 1;
5846dd4f32aeSBjoern A. Zeeb
5847dd4f32aeSBjoern A. Zeeb switch (i) {
5848dd4f32aeSBjoern A. Zeeb case NL80211_IFTYPE_AP:
5849dd4f32aeSBjoern A. Zeeb he_cap_elem->phy_cap_info[3] &=
5850dd4f32aeSBjoern A. Zeeb ~IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_MASK;
5851dd4f32aeSBjoern A. Zeeb he_cap_elem->phy_cap_info[9] |=
5852dd4f32aeSBjoern A. Zeeb IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU;
5853dd4f32aeSBjoern A. Zeeb break;
5854dd4f32aeSBjoern A. Zeeb case NL80211_IFTYPE_STATION:
5855dd4f32aeSBjoern A. Zeeb he_cap_elem->mac_cap_info[0] &=
5856dd4f32aeSBjoern A. Zeeb ~IEEE80211_HE_MAC_CAP0_TWT_RES;
5857dd4f32aeSBjoern A. Zeeb he_cap_elem->mac_cap_info[0] |=
5858dd4f32aeSBjoern A. Zeeb IEEE80211_HE_MAC_CAP0_TWT_REQ;
5859dd4f32aeSBjoern A. Zeeb he_cap_elem->phy_cap_info[9] |=
5860dd4f32aeSBjoern A. Zeeb IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU;
5861dd4f32aeSBjoern A. Zeeb break;
5862dd4f32aeSBjoern A. Zeeb case NL80211_IFTYPE_MESH_POINT:
5863dd4f32aeSBjoern A. Zeeb ath11k_mac_filter_he_cap_mesh(he_cap_elem);
5864dd4f32aeSBjoern A. Zeeb break;
5865dd4f32aeSBjoern A. Zeeb }
5866dd4f32aeSBjoern A. Zeeb
586728348caeSBjoern A. Zeeb ath11k_mac_set_hemcsmap(ar, cap, he_cap, band);
5868dd4f32aeSBjoern A. Zeeb
5869dd4f32aeSBjoern A. Zeeb memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres));
5870dd4f32aeSBjoern A. Zeeb if (he_cap_elem->phy_cap_info[6] &
5871dd4f32aeSBjoern A. Zeeb IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT)
5872dd4f32aeSBjoern A. Zeeb ath11k_gen_ppe_thresh(&band_cap->he_ppet,
5873dd4f32aeSBjoern A. Zeeb he_cap->ppe_thres);
5874dd4f32aeSBjoern A. Zeeb
5875dd4f32aeSBjoern A. Zeeb if (band == NL80211_BAND_6GHZ) {
5876dd4f32aeSBjoern A. Zeeb data[idx].he_6ghz_capa.capa =
5877dd4f32aeSBjoern A. Zeeb ath11k_mac_setup_he_6ghz_cap(cap, band_cap);
5878dd4f32aeSBjoern A. Zeeb }
5879dd4f32aeSBjoern A. Zeeb idx++;
5880dd4f32aeSBjoern A. Zeeb }
5881dd4f32aeSBjoern A. Zeeb
5882dd4f32aeSBjoern A. Zeeb return idx;
5883dd4f32aeSBjoern A. Zeeb }
5884dd4f32aeSBjoern A. Zeeb
ath11k_mac_setup_he_cap(struct ath11k * ar,struct ath11k_pdev_cap * cap)5885dd4f32aeSBjoern A. Zeeb static void ath11k_mac_setup_he_cap(struct ath11k *ar,
5886dd4f32aeSBjoern A. Zeeb struct ath11k_pdev_cap *cap)
5887dd4f32aeSBjoern A. Zeeb {
5888dd4f32aeSBjoern A. Zeeb struct ieee80211_supported_band *band;
5889dd4f32aeSBjoern A. Zeeb int count;
5890dd4f32aeSBjoern A. Zeeb
5891dd4f32aeSBjoern A. Zeeb if (cap->supported_bands & WMI_HOST_WLAN_2G_CAP) {
5892dd4f32aeSBjoern A. Zeeb count = ath11k_mac_copy_he_cap(ar, cap,
5893dd4f32aeSBjoern A. Zeeb ar->mac.iftype[NL80211_BAND_2GHZ],
5894dd4f32aeSBjoern A. Zeeb NL80211_BAND_2GHZ);
5895dd4f32aeSBjoern A. Zeeb band = &ar->mac.sbands[NL80211_BAND_2GHZ];
5896dd4f32aeSBjoern A. Zeeb band->iftype_data = ar->mac.iftype[NL80211_BAND_2GHZ];
5897dd4f32aeSBjoern A. Zeeb band->n_iftype_data = count;
5898dd4f32aeSBjoern A. Zeeb }
5899dd4f32aeSBjoern A. Zeeb
5900dd4f32aeSBjoern A. Zeeb if (cap->supported_bands & WMI_HOST_WLAN_5G_CAP) {
5901dd4f32aeSBjoern A. Zeeb count = ath11k_mac_copy_he_cap(ar, cap,
5902dd4f32aeSBjoern A. Zeeb ar->mac.iftype[NL80211_BAND_5GHZ],
5903dd4f32aeSBjoern A. Zeeb NL80211_BAND_5GHZ);
5904dd4f32aeSBjoern A. Zeeb band = &ar->mac.sbands[NL80211_BAND_5GHZ];
5905dd4f32aeSBjoern A. Zeeb band->iftype_data = ar->mac.iftype[NL80211_BAND_5GHZ];
5906dd4f32aeSBjoern A. Zeeb band->n_iftype_data = count;
5907dd4f32aeSBjoern A. Zeeb }
5908dd4f32aeSBjoern A. Zeeb
5909dd4f32aeSBjoern A. Zeeb if (cap->supported_bands & WMI_HOST_WLAN_5G_CAP &&
5910dd4f32aeSBjoern A. Zeeb ar->supports_6ghz) {
5911dd4f32aeSBjoern A. Zeeb count = ath11k_mac_copy_he_cap(ar, cap,
5912dd4f32aeSBjoern A. Zeeb ar->mac.iftype[NL80211_BAND_6GHZ],
5913dd4f32aeSBjoern A. Zeeb NL80211_BAND_6GHZ);
5914dd4f32aeSBjoern A. Zeeb band = &ar->mac.sbands[NL80211_BAND_6GHZ];
5915dd4f32aeSBjoern A. Zeeb band->iftype_data = ar->mac.iftype[NL80211_BAND_6GHZ];
5916dd4f32aeSBjoern A. Zeeb band->n_iftype_data = count;
5917dd4f32aeSBjoern A. Zeeb }
5918dd4f32aeSBjoern A. Zeeb }
5919dd4f32aeSBjoern A. Zeeb
__ath11k_set_antenna(struct ath11k * ar,u32 tx_ant,u32 rx_ant)5920dd4f32aeSBjoern A. Zeeb static int __ath11k_set_antenna(struct ath11k *ar, u32 tx_ant, u32 rx_ant)
5921dd4f32aeSBjoern A. Zeeb {
5922dd4f32aeSBjoern A. Zeeb int ret;
5923dd4f32aeSBjoern A. Zeeb
5924dd4f32aeSBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
5925dd4f32aeSBjoern A. Zeeb
5926dd4f32aeSBjoern A. Zeeb if (ath11k_check_chain_mask(ar, tx_ant, true))
5927dd4f32aeSBjoern A. Zeeb return -EINVAL;
5928dd4f32aeSBjoern A. Zeeb
5929dd4f32aeSBjoern A. Zeeb if (ath11k_check_chain_mask(ar, rx_ant, false))
5930dd4f32aeSBjoern A. Zeeb return -EINVAL;
5931dd4f32aeSBjoern A. Zeeb
5932dd4f32aeSBjoern A. Zeeb ar->cfg_tx_chainmask = tx_ant;
5933dd4f32aeSBjoern A. Zeeb ar->cfg_rx_chainmask = rx_ant;
5934dd4f32aeSBjoern A. Zeeb
5935dd4f32aeSBjoern A. Zeeb if (ar->state != ATH11K_STATE_ON &&
5936dd4f32aeSBjoern A. Zeeb ar->state != ATH11K_STATE_RESTARTED)
5937dd4f32aeSBjoern A. Zeeb return 0;
5938dd4f32aeSBjoern A. Zeeb
5939dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_TX_CHAIN_MASK,
5940dd4f32aeSBjoern A. Zeeb tx_ant, ar->pdev->pdev_id);
5941dd4f32aeSBjoern A. Zeeb if (ret) {
5942dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to set tx-chainmask: %d, req 0x%x\n",
5943dd4f32aeSBjoern A. Zeeb ret, tx_ant);
5944dd4f32aeSBjoern A. Zeeb return ret;
5945dd4f32aeSBjoern A. Zeeb }
5946dd4f32aeSBjoern A. Zeeb
5947dd4f32aeSBjoern A. Zeeb ar->num_tx_chains = get_num_chains(tx_ant);
5948dd4f32aeSBjoern A. Zeeb
5949dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_RX_CHAIN_MASK,
5950dd4f32aeSBjoern A. Zeeb rx_ant, ar->pdev->pdev_id);
5951dd4f32aeSBjoern A. Zeeb if (ret) {
5952dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to set rx-chainmask: %d, req 0x%x\n",
5953dd4f32aeSBjoern A. Zeeb ret, rx_ant);
5954dd4f32aeSBjoern A. Zeeb return ret;
5955dd4f32aeSBjoern A. Zeeb }
5956dd4f32aeSBjoern A. Zeeb
5957dd4f32aeSBjoern A. Zeeb ar->num_rx_chains = get_num_chains(rx_ant);
5958dd4f32aeSBjoern A. Zeeb
5959dd4f32aeSBjoern A. Zeeb /* Reload HT/VHT/HE capability */
5960dd4f32aeSBjoern A. Zeeb ath11k_mac_setup_ht_vht_cap(ar, &ar->pdev->cap, NULL);
5961dd4f32aeSBjoern A. Zeeb ath11k_mac_setup_he_cap(ar, &ar->pdev->cap);
5962dd4f32aeSBjoern A. Zeeb
5963dd4f32aeSBjoern A. Zeeb return 0;
5964dd4f32aeSBjoern A. Zeeb }
5965dd4f32aeSBjoern A. Zeeb
ath11k_mgmt_over_wmi_tx_drop(struct ath11k * ar,struct sk_buff * skb)5966dd4f32aeSBjoern A. Zeeb static void ath11k_mgmt_over_wmi_tx_drop(struct ath11k *ar, struct sk_buff *skb)
5967dd4f32aeSBjoern A. Zeeb {
5968dd4f32aeSBjoern A. Zeeb int num_mgmt;
5969dd4f32aeSBjoern A. Zeeb
5970dd4f32aeSBjoern A. Zeeb ieee80211_free_txskb(ar->hw, skb);
5971dd4f32aeSBjoern A. Zeeb
5972dd4f32aeSBjoern A. Zeeb num_mgmt = atomic_dec_if_positive(&ar->num_pending_mgmt_tx);
5973dd4f32aeSBjoern A. Zeeb
5974dd4f32aeSBjoern A. Zeeb if (num_mgmt < 0)
5975dd4f32aeSBjoern A. Zeeb WARN_ON_ONCE(1);
5976dd4f32aeSBjoern A. Zeeb
5977dd4f32aeSBjoern A. Zeeb if (!num_mgmt)
5978dd4f32aeSBjoern A. Zeeb wake_up(&ar->txmgmt_empty_waitq);
5979dd4f32aeSBjoern A. Zeeb }
5980dd4f32aeSBjoern A. Zeeb
ath11k_mac_tx_mgmt_free(struct ath11k * ar,int buf_id)5981dd4f32aeSBjoern A. Zeeb static void ath11k_mac_tx_mgmt_free(struct ath11k *ar, int buf_id)
5982dd4f32aeSBjoern A. Zeeb {
5983dd4f32aeSBjoern A. Zeeb struct sk_buff *msdu;
5984dd4f32aeSBjoern A. Zeeb struct ieee80211_tx_info *info;
5985dd4f32aeSBjoern A. Zeeb
5986dd4f32aeSBjoern A. Zeeb spin_lock_bh(&ar->txmgmt_idr_lock);
5987dd4f32aeSBjoern A. Zeeb msdu = idr_remove(&ar->txmgmt_idr, buf_id);
5988dd4f32aeSBjoern A. Zeeb spin_unlock_bh(&ar->txmgmt_idr_lock);
5989dd4f32aeSBjoern A. Zeeb
5990dd4f32aeSBjoern A. Zeeb if (!msdu)
5991dd4f32aeSBjoern A. Zeeb return;
5992dd4f32aeSBjoern A. Zeeb
5993dd4f32aeSBjoern A. Zeeb dma_unmap_single(ar->ab->dev, ATH11K_SKB_CB(msdu)->paddr, msdu->len,
5994dd4f32aeSBjoern A. Zeeb DMA_TO_DEVICE);
5995dd4f32aeSBjoern A. Zeeb
5996dd4f32aeSBjoern A. Zeeb info = IEEE80211_SKB_CB(msdu);
5997dd4f32aeSBjoern A. Zeeb memset(&info->status, 0, sizeof(info->status));
5998dd4f32aeSBjoern A. Zeeb
5999dd4f32aeSBjoern A. Zeeb ath11k_mgmt_over_wmi_tx_drop(ar, msdu);
6000dd4f32aeSBjoern A. Zeeb }
6001dd4f32aeSBjoern A. Zeeb
ath11k_mac_tx_mgmt_pending_free(int buf_id,void * skb,void * ctx)6002dd4f32aeSBjoern A. Zeeb int ath11k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx)
6003dd4f32aeSBjoern A. Zeeb {
6004dd4f32aeSBjoern A. Zeeb struct ath11k *ar = ctx;
6005dd4f32aeSBjoern A. Zeeb
6006dd4f32aeSBjoern A. Zeeb ath11k_mac_tx_mgmt_free(ar, buf_id);
6007dd4f32aeSBjoern A. Zeeb
6008dd4f32aeSBjoern A. Zeeb return 0;
6009dd4f32aeSBjoern A. Zeeb }
6010dd4f32aeSBjoern A. Zeeb
ath11k_mac_vif_txmgmt_idr_remove(int buf_id,void * skb,void * ctx)6011dd4f32aeSBjoern A. Zeeb static int ath11k_mac_vif_txmgmt_idr_remove(int buf_id, void *skb, void *ctx)
6012dd4f32aeSBjoern A. Zeeb {
6013dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif = ctx;
6014dd4f32aeSBjoern A. Zeeb struct ath11k_skb_cb *skb_cb = ATH11K_SKB_CB((struct sk_buff *)skb);
6015dd4f32aeSBjoern A. Zeeb struct ath11k *ar = skb_cb->ar;
6016dd4f32aeSBjoern A. Zeeb
6017dd4f32aeSBjoern A. Zeeb if (skb_cb->vif == vif)
6018dd4f32aeSBjoern A. Zeeb ath11k_mac_tx_mgmt_free(ar, buf_id);
6019dd4f32aeSBjoern A. Zeeb
6020dd4f32aeSBjoern A. Zeeb return 0;
6021dd4f32aeSBjoern A. Zeeb }
6022dd4f32aeSBjoern A. Zeeb
ath11k_mac_mgmt_tx_wmi(struct ath11k * ar,struct ath11k_vif * arvif,struct sk_buff * skb)6023dd4f32aeSBjoern A. Zeeb static int ath11k_mac_mgmt_tx_wmi(struct ath11k *ar, struct ath11k_vif *arvif,
6024dd4f32aeSBjoern A. Zeeb struct sk_buff *skb)
6025dd4f32aeSBjoern A. Zeeb {
6026dd4f32aeSBjoern A. Zeeb struct ath11k_base *ab = ar->ab;
6027dd4f32aeSBjoern A. Zeeb struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
6028dd4f32aeSBjoern A. Zeeb struct ieee80211_tx_info *info;
6029dd4f32aeSBjoern A. Zeeb dma_addr_t paddr;
6030dd4f32aeSBjoern A. Zeeb int buf_id;
6031dd4f32aeSBjoern A. Zeeb int ret;
6032dd4f32aeSBjoern A. Zeeb
6033dd4f32aeSBjoern A. Zeeb ATH11K_SKB_CB(skb)->ar = ar;
6034dd4f32aeSBjoern A. Zeeb
6035dd4f32aeSBjoern A. Zeeb spin_lock_bh(&ar->txmgmt_idr_lock);
6036dd4f32aeSBjoern A. Zeeb buf_id = idr_alloc(&ar->txmgmt_idr, skb, 0,
6037dd4f32aeSBjoern A. Zeeb ATH11K_TX_MGMT_NUM_PENDING_MAX, GFP_ATOMIC);
6038dd4f32aeSBjoern A. Zeeb spin_unlock_bh(&ar->txmgmt_idr_lock);
6039dd4f32aeSBjoern A. Zeeb
6040dd4f32aeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
604128348caeSBjoern A. Zeeb "tx mgmt frame, buf id %d\n", buf_id);
6042dd4f32aeSBjoern A. Zeeb
6043dd4f32aeSBjoern A. Zeeb if (buf_id < 0)
6044dd4f32aeSBjoern A. Zeeb return -ENOSPC;
6045dd4f32aeSBjoern A. Zeeb
6046dd4f32aeSBjoern A. Zeeb info = IEEE80211_SKB_CB(skb);
6047dd4f32aeSBjoern A. Zeeb if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP)) {
6048dd4f32aeSBjoern A. Zeeb if ((ieee80211_is_action(hdr->frame_control) ||
6049dd4f32aeSBjoern A. Zeeb ieee80211_is_deauth(hdr->frame_control) ||
6050dd4f32aeSBjoern A. Zeeb ieee80211_is_disassoc(hdr->frame_control)) &&
6051dd4f32aeSBjoern A. Zeeb ieee80211_has_protected(hdr->frame_control)) {
6052dd4f32aeSBjoern A. Zeeb skb_put(skb, IEEE80211_CCMP_MIC_LEN);
6053dd4f32aeSBjoern A. Zeeb }
6054dd4f32aeSBjoern A. Zeeb }
6055dd4f32aeSBjoern A. Zeeb
6056dd4f32aeSBjoern A. Zeeb paddr = dma_map_single(ab->dev, skb->data, skb->len, DMA_TO_DEVICE);
6057dd4f32aeSBjoern A. Zeeb if (dma_mapping_error(ab->dev, paddr)) {
6058dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, "failed to DMA map mgmt Tx buffer\n");
6059dd4f32aeSBjoern A. Zeeb ret = -EIO;
6060dd4f32aeSBjoern A. Zeeb goto err_free_idr;
6061dd4f32aeSBjoern A. Zeeb }
6062dd4f32aeSBjoern A. Zeeb
6063dd4f32aeSBjoern A. Zeeb ATH11K_SKB_CB(skb)->paddr = paddr;
6064dd4f32aeSBjoern A. Zeeb
6065dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_mgmt_send(ar, arvif->vdev_id, buf_id, skb);
6066dd4f32aeSBjoern A. Zeeb if (ret) {
6067dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to send mgmt frame: %d\n", ret);
6068dd4f32aeSBjoern A. Zeeb goto err_unmap_buf;
6069dd4f32aeSBjoern A. Zeeb }
6070dd4f32aeSBjoern A. Zeeb
6071dd4f32aeSBjoern A. Zeeb return 0;
6072dd4f32aeSBjoern A. Zeeb
6073dd4f32aeSBjoern A. Zeeb err_unmap_buf:
6074dd4f32aeSBjoern A. Zeeb dma_unmap_single(ab->dev, ATH11K_SKB_CB(skb)->paddr,
6075dd4f32aeSBjoern A. Zeeb skb->len, DMA_TO_DEVICE);
6076dd4f32aeSBjoern A. Zeeb err_free_idr:
6077dd4f32aeSBjoern A. Zeeb spin_lock_bh(&ar->txmgmt_idr_lock);
6078dd4f32aeSBjoern A. Zeeb idr_remove(&ar->txmgmt_idr, buf_id);
6079dd4f32aeSBjoern A. Zeeb spin_unlock_bh(&ar->txmgmt_idr_lock);
6080dd4f32aeSBjoern A. Zeeb
6081dd4f32aeSBjoern A. Zeeb return ret;
6082dd4f32aeSBjoern A. Zeeb }
6083dd4f32aeSBjoern A. Zeeb
ath11k_mgmt_over_wmi_tx_purge(struct ath11k * ar)6084dd4f32aeSBjoern A. Zeeb static void ath11k_mgmt_over_wmi_tx_purge(struct ath11k *ar)
6085dd4f32aeSBjoern A. Zeeb {
6086dd4f32aeSBjoern A. Zeeb struct sk_buff *skb;
6087dd4f32aeSBjoern A. Zeeb
6088dd4f32aeSBjoern A. Zeeb while ((skb = skb_dequeue(&ar->wmi_mgmt_tx_queue)) != NULL)
6089dd4f32aeSBjoern A. Zeeb ath11k_mgmt_over_wmi_tx_drop(ar, skb);
6090dd4f32aeSBjoern A. Zeeb }
6091dd4f32aeSBjoern A. Zeeb
ath11k_mgmt_over_wmi_tx_work(struct work_struct * work)6092dd4f32aeSBjoern A. Zeeb static void ath11k_mgmt_over_wmi_tx_work(struct work_struct *work)
6093dd4f32aeSBjoern A. Zeeb {
6094dd4f32aeSBjoern A. Zeeb struct ath11k *ar = container_of(work, struct ath11k, wmi_mgmt_tx_work);
6095dd4f32aeSBjoern A. Zeeb struct ath11k_skb_cb *skb_cb;
6096dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif;
6097dd4f32aeSBjoern A. Zeeb struct sk_buff *skb;
6098dd4f32aeSBjoern A. Zeeb int ret;
6099dd4f32aeSBjoern A. Zeeb
6100dd4f32aeSBjoern A. Zeeb while ((skb = skb_dequeue(&ar->wmi_mgmt_tx_queue)) != NULL) {
6101dd4f32aeSBjoern A. Zeeb skb_cb = ATH11K_SKB_CB(skb);
6102dd4f32aeSBjoern A. Zeeb if (!skb_cb->vif) {
6103dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "no vif found for mgmt frame\n");
6104dd4f32aeSBjoern A. Zeeb ath11k_mgmt_over_wmi_tx_drop(ar, skb);
6105dd4f32aeSBjoern A. Zeeb continue;
6106dd4f32aeSBjoern A. Zeeb }
6107dd4f32aeSBjoern A. Zeeb
6108dd4f32aeSBjoern A. Zeeb arvif = ath11k_vif_to_arvif(skb_cb->vif);
610928348caeSBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
611028348caeSBjoern A. Zeeb if (ar->allocated_vdev_map & (1LL << arvif->vdev_id)) {
6111dd4f32aeSBjoern A. Zeeb ret = ath11k_mac_mgmt_tx_wmi(ar, arvif, skb);
6112dd4f32aeSBjoern A. Zeeb if (ret) {
6113dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to tx mgmt frame, vdev_id %d :%d\n",
6114dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ret);
6115dd4f32aeSBjoern A. Zeeb ath11k_mgmt_over_wmi_tx_drop(ar, skb);
6116dd4f32aeSBjoern A. Zeeb } else {
6117dd4f32aeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
611828348caeSBjoern A. Zeeb "tx mgmt frame, vdev_id %d\n",
6119dd4f32aeSBjoern A. Zeeb arvif->vdev_id);
6120dd4f32aeSBjoern A. Zeeb }
6121dd4f32aeSBjoern A. Zeeb } else {
6122dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab,
6123dd4f32aeSBjoern A. Zeeb "dropping mgmt frame for vdev %d, is_started %d\n",
6124dd4f32aeSBjoern A. Zeeb arvif->vdev_id,
6125dd4f32aeSBjoern A. Zeeb arvif->is_started);
6126dd4f32aeSBjoern A. Zeeb ath11k_mgmt_over_wmi_tx_drop(ar, skb);
6127dd4f32aeSBjoern A. Zeeb }
612828348caeSBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
6129dd4f32aeSBjoern A. Zeeb }
6130dd4f32aeSBjoern A. Zeeb }
6131dd4f32aeSBjoern A. Zeeb
ath11k_mac_mgmt_tx(struct ath11k * ar,struct sk_buff * skb,bool is_prb_rsp)6132dd4f32aeSBjoern A. Zeeb static int ath11k_mac_mgmt_tx(struct ath11k *ar, struct sk_buff *skb,
6133dd4f32aeSBjoern A. Zeeb bool is_prb_rsp)
6134dd4f32aeSBjoern A. Zeeb {
6135dd4f32aeSBjoern A. Zeeb struct sk_buff_head *q = &ar->wmi_mgmt_tx_queue;
6136dd4f32aeSBjoern A. Zeeb
6137dd4f32aeSBjoern A. Zeeb if (test_bit(ATH11K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))
6138dd4f32aeSBjoern A. Zeeb return -ESHUTDOWN;
6139dd4f32aeSBjoern A. Zeeb
6140dd4f32aeSBjoern A. Zeeb /* Drop probe response packets when the pending management tx
6141dd4f32aeSBjoern A. Zeeb * count has reached a certain threshold, so as to prioritize
6142dd4f32aeSBjoern A. Zeeb * other mgmt packets like auth and assoc to be sent on time
6143dd4f32aeSBjoern A. Zeeb * for establishing successful connections.
6144dd4f32aeSBjoern A. Zeeb */
6145dd4f32aeSBjoern A. Zeeb if (is_prb_rsp &&
6146dd4f32aeSBjoern A. Zeeb atomic_read(&ar->num_pending_mgmt_tx) > ATH11K_PRB_RSP_DROP_THRESHOLD) {
6147dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab,
6148dd4f32aeSBjoern A. Zeeb "dropping probe response as pending queue is almost full\n");
6149dd4f32aeSBjoern A. Zeeb return -ENOSPC;
6150dd4f32aeSBjoern A. Zeeb }
6151dd4f32aeSBjoern A. Zeeb
6152dd4f32aeSBjoern A. Zeeb if (skb_queue_len_lockless(q) >= ATH11K_TX_MGMT_NUM_PENDING_MAX) {
6153dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "mgmt tx queue is full\n");
6154dd4f32aeSBjoern A. Zeeb return -ENOSPC;
6155dd4f32aeSBjoern A. Zeeb }
6156dd4f32aeSBjoern A. Zeeb
6157dd4f32aeSBjoern A. Zeeb skb_queue_tail(q, skb);
6158dd4f32aeSBjoern A. Zeeb atomic_inc(&ar->num_pending_mgmt_tx);
615928348caeSBjoern A. Zeeb queue_work(ar->ab->workqueue_aux, &ar->wmi_mgmt_tx_work);
6160dd4f32aeSBjoern A. Zeeb
6161dd4f32aeSBjoern A. Zeeb return 0;
6162dd4f32aeSBjoern A. Zeeb }
6163dd4f32aeSBjoern A. Zeeb
ath11k_mac_op_tx(struct ieee80211_hw * hw,struct ieee80211_tx_control * control,struct sk_buff * skb)6164dd4f32aeSBjoern A. Zeeb static void ath11k_mac_op_tx(struct ieee80211_hw *hw,
6165dd4f32aeSBjoern A. Zeeb struct ieee80211_tx_control *control,
6166dd4f32aeSBjoern A. Zeeb struct sk_buff *skb)
6167dd4f32aeSBjoern A. Zeeb {
6168dd4f32aeSBjoern A. Zeeb struct ath11k_skb_cb *skb_cb = ATH11K_SKB_CB(skb);
6169dd4f32aeSBjoern A. Zeeb struct ath11k *ar = hw->priv;
6170dd4f32aeSBjoern A. Zeeb struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
6171dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif = info->control.vif;
6172dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
6173dd4f32aeSBjoern A. Zeeb struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
6174dd4f32aeSBjoern A. Zeeb struct ieee80211_key_conf *key = info->control.hw_key;
6175dd4f32aeSBjoern A. Zeeb struct ath11k_sta *arsta = NULL;
6176dd4f32aeSBjoern A. Zeeb u32 info_flags = info->flags;
6177dd4f32aeSBjoern A. Zeeb bool is_prb_rsp;
6178dd4f32aeSBjoern A. Zeeb int ret;
6179dd4f32aeSBjoern A. Zeeb
6180dd4f32aeSBjoern A. Zeeb memset(skb_cb, 0, sizeof(*skb_cb));
6181dd4f32aeSBjoern A. Zeeb skb_cb->vif = vif;
6182dd4f32aeSBjoern A. Zeeb
6183dd4f32aeSBjoern A. Zeeb if (key) {
6184dd4f32aeSBjoern A. Zeeb skb_cb->cipher = key->cipher;
6185dd4f32aeSBjoern A. Zeeb skb_cb->flags |= ATH11K_SKB_CIPHER_SET;
6186dd4f32aeSBjoern A. Zeeb }
6187dd4f32aeSBjoern A. Zeeb
6188dd4f32aeSBjoern A. Zeeb if (info_flags & IEEE80211_TX_CTL_HW_80211_ENCAP) {
6189dd4f32aeSBjoern A. Zeeb skb_cb->flags |= ATH11K_SKB_HW_80211_ENCAP;
6190dd4f32aeSBjoern A. Zeeb } else if (ieee80211_is_mgmt(hdr->frame_control)) {
6191dd4f32aeSBjoern A. Zeeb is_prb_rsp = ieee80211_is_probe_resp(hdr->frame_control);
6192dd4f32aeSBjoern A. Zeeb ret = ath11k_mac_mgmt_tx(ar, skb, is_prb_rsp);
6193dd4f32aeSBjoern A. Zeeb if (ret) {
6194dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to queue management frame %d\n",
6195dd4f32aeSBjoern A. Zeeb ret);
6196dd4f32aeSBjoern A. Zeeb ieee80211_free_txskb(ar->hw, skb);
6197dd4f32aeSBjoern A. Zeeb }
6198dd4f32aeSBjoern A. Zeeb return;
6199dd4f32aeSBjoern A. Zeeb }
6200dd4f32aeSBjoern A. Zeeb
6201dd4f32aeSBjoern A. Zeeb if (control->sta)
6202dd4f32aeSBjoern A. Zeeb arsta = (struct ath11k_sta *)control->sta->drv_priv;
6203dd4f32aeSBjoern A. Zeeb
6204dd4f32aeSBjoern A. Zeeb ret = ath11k_dp_tx(ar, arvif, arsta, skb);
6205dd4f32aeSBjoern A. Zeeb if (unlikely(ret)) {
6206dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to transmit frame %d\n", ret);
6207dd4f32aeSBjoern A. Zeeb ieee80211_free_txskb(ar->hw, skb);
6208dd4f32aeSBjoern A. Zeeb }
6209dd4f32aeSBjoern A. Zeeb }
6210dd4f32aeSBjoern A. Zeeb
ath11k_mac_drain_tx(struct ath11k * ar)6211dd4f32aeSBjoern A. Zeeb void ath11k_mac_drain_tx(struct ath11k *ar)
6212dd4f32aeSBjoern A. Zeeb {
6213dd4f32aeSBjoern A. Zeeb /* make sure rcu-protected mac80211 tx path itself is drained */
6214dd4f32aeSBjoern A. Zeeb synchronize_net();
6215dd4f32aeSBjoern A. Zeeb
6216dd4f32aeSBjoern A. Zeeb cancel_work_sync(&ar->wmi_mgmt_tx_work);
6217dd4f32aeSBjoern A. Zeeb ath11k_mgmt_over_wmi_tx_purge(ar);
6218dd4f32aeSBjoern A. Zeeb }
6219dd4f32aeSBjoern A. Zeeb
ath11k_mac_config_mon_status_default(struct ath11k * ar,bool enable)6220dd4f32aeSBjoern A. Zeeb static int ath11k_mac_config_mon_status_default(struct ath11k *ar, bool enable)
6221dd4f32aeSBjoern A. Zeeb {
6222dd4f32aeSBjoern A. Zeeb struct htt_rx_ring_tlv_filter tlv_filter = {0};
6223dd4f32aeSBjoern A. Zeeb struct ath11k_base *ab = ar->ab;
6224dd4f32aeSBjoern A. Zeeb int i, ret = 0;
6225dd4f32aeSBjoern A. Zeeb u32 ring_id;
6226dd4f32aeSBjoern A. Zeeb
6227dd4f32aeSBjoern A. Zeeb if (enable) {
6228dd4f32aeSBjoern A. Zeeb tlv_filter = ath11k_mac_mon_status_filter_default;
6229dd4f32aeSBjoern A. Zeeb if (ath11k_debugfs_rx_filter(ar))
6230dd4f32aeSBjoern A. Zeeb tlv_filter.rx_filter = ath11k_debugfs_rx_filter(ar);
6231dd4f32aeSBjoern A. Zeeb }
6232dd4f32aeSBjoern A. Zeeb
6233dd4f32aeSBjoern A. Zeeb for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
6234dd4f32aeSBjoern A. Zeeb ring_id = ar->dp.rx_mon_status_refill_ring[i].refill_buf_ring.ring_id;
6235dd4f32aeSBjoern A. Zeeb ret = ath11k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id,
6236dd4f32aeSBjoern A. Zeeb ar->dp.mac_id + i,
6237dd4f32aeSBjoern A. Zeeb HAL_RXDMA_MONITOR_STATUS,
6238dd4f32aeSBjoern A. Zeeb DP_RX_BUFFER_SIZE,
6239dd4f32aeSBjoern A. Zeeb &tlv_filter);
6240dd4f32aeSBjoern A. Zeeb }
6241dd4f32aeSBjoern A. Zeeb
6242dd4f32aeSBjoern A. Zeeb if (enable && !ar->ab->hw_params.rxdma1_enable)
6243dd4f32aeSBjoern A. Zeeb mod_timer(&ar->ab->mon_reap_timer, jiffies +
6244dd4f32aeSBjoern A. Zeeb msecs_to_jiffies(ATH11K_MON_TIMER_INTERVAL));
6245dd4f32aeSBjoern A. Zeeb
6246dd4f32aeSBjoern A. Zeeb return ret;
6247dd4f32aeSBjoern A. Zeeb }
6248dd4f32aeSBjoern A. Zeeb
ath11k_mac_wait_reconfigure(struct ath11k_base * ab)624928348caeSBjoern A. Zeeb static void ath11k_mac_wait_reconfigure(struct ath11k_base *ab)
625028348caeSBjoern A. Zeeb {
625128348caeSBjoern A. Zeeb int recovery_start_count;
625228348caeSBjoern A. Zeeb
625328348caeSBjoern A. Zeeb if (!ab->is_reset)
625428348caeSBjoern A. Zeeb return;
625528348caeSBjoern A. Zeeb
625628348caeSBjoern A. Zeeb recovery_start_count = atomic_inc_return(&ab->recovery_start_count);
625728348caeSBjoern A. Zeeb ath11k_dbg(ab, ATH11K_DBG_MAC, "recovery start count %d\n", recovery_start_count);
625828348caeSBjoern A. Zeeb
625928348caeSBjoern A. Zeeb if (recovery_start_count == ab->num_radios) {
626028348caeSBjoern A. Zeeb complete(&ab->recovery_start);
626128348caeSBjoern A. Zeeb ath11k_dbg(ab, ATH11K_DBG_MAC, "recovery started success\n");
626228348caeSBjoern A. Zeeb }
626328348caeSBjoern A. Zeeb
626428348caeSBjoern A. Zeeb ath11k_dbg(ab, ATH11K_DBG_MAC, "waiting reconfigure...\n");
626528348caeSBjoern A. Zeeb
626628348caeSBjoern A. Zeeb wait_for_completion_timeout(&ab->reconfigure_complete,
626728348caeSBjoern A. Zeeb ATH11K_RECONFIGURE_TIMEOUT_HZ);
626828348caeSBjoern A. Zeeb }
626928348caeSBjoern A. Zeeb
ath11k_mac_op_start(struct ieee80211_hw * hw)6270dd4f32aeSBjoern A. Zeeb static int ath11k_mac_op_start(struct ieee80211_hw *hw)
6271dd4f32aeSBjoern A. Zeeb {
6272dd4f32aeSBjoern A. Zeeb struct ath11k *ar = hw->priv;
6273dd4f32aeSBjoern A. Zeeb struct ath11k_base *ab = ar->ab;
6274dd4f32aeSBjoern A. Zeeb struct ath11k_pdev *pdev = ar->pdev;
6275dd4f32aeSBjoern A. Zeeb int ret;
6276dd4f32aeSBjoern A. Zeeb
627728348caeSBjoern A. Zeeb if (ath11k_ftm_mode) {
627828348caeSBjoern A. Zeeb ath11k_warn(ab, "mac operations not supported in factory test mode\n");
627928348caeSBjoern A. Zeeb return -EOPNOTSUPP;
628028348caeSBjoern A. Zeeb }
628128348caeSBjoern A. Zeeb
6282dd4f32aeSBjoern A. Zeeb ath11k_mac_drain_tx(ar);
6283dd4f32aeSBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
6284dd4f32aeSBjoern A. Zeeb
6285dd4f32aeSBjoern A. Zeeb switch (ar->state) {
6286dd4f32aeSBjoern A. Zeeb case ATH11K_STATE_OFF:
6287dd4f32aeSBjoern A. Zeeb ar->state = ATH11K_STATE_ON;
6288dd4f32aeSBjoern A. Zeeb break;
6289dd4f32aeSBjoern A. Zeeb case ATH11K_STATE_RESTARTING:
6290dd4f32aeSBjoern A. Zeeb ar->state = ATH11K_STATE_RESTARTED;
629128348caeSBjoern A. Zeeb ath11k_mac_wait_reconfigure(ab);
6292dd4f32aeSBjoern A. Zeeb break;
6293dd4f32aeSBjoern A. Zeeb case ATH11K_STATE_RESTARTED:
6294dd4f32aeSBjoern A. Zeeb case ATH11K_STATE_WEDGED:
6295dd4f32aeSBjoern A. Zeeb case ATH11K_STATE_ON:
629628348caeSBjoern A. Zeeb case ATH11K_STATE_FTM:
6297dd4f32aeSBjoern A. Zeeb WARN_ON(1);
6298dd4f32aeSBjoern A. Zeeb ret = -EINVAL;
6299dd4f32aeSBjoern A. Zeeb goto err;
6300dd4f32aeSBjoern A. Zeeb }
6301dd4f32aeSBjoern A. Zeeb
6302dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_PMF_QOS,
6303dd4f32aeSBjoern A. Zeeb 1, pdev->pdev_id);
6304dd4f32aeSBjoern A. Zeeb
6305dd4f32aeSBjoern A. Zeeb if (ret) {
6306dd4f32aeSBjoern A. Zeeb ath11k_err(ar->ab, "failed to enable PMF QOS: (%d\n", ret);
6307dd4f32aeSBjoern A. Zeeb goto err;
6308dd4f32aeSBjoern A. Zeeb }
6309dd4f32aeSBjoern A. Zeeb
6310dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_DYNAMIC_BW, 1,
6311dd4f32aeSBjoern A. Zeeb pdev->pdev_id);
6312dd4f32aeSBjoern A. Zeeb if (ret) {
6313dd4f32aeSBjoern A. Zeeb ath11k_err(ar->ab, "failed to enable dynamic bw: %d\n", ret);
6314dd4f32aeSBjoern A. Zeeb goto err;
6315dd4f32aeSBjoern A. Zeeb }
6316dd4f32aeSBjoern A. Zeeb
6317dd4f32aeSBjoern A. Zeeb if (test_bit(WMI_TLV_SERVICE_SPOOF_MAC_SUPPORT, ar->wmi->wmi_ab->svc_map)) {
6318dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_scan_prob_req_oui(ar, ar->mac_addr);
6319dd4f32aeSBjoern A. Zeeb if (ret) {
6320dd4f32aeSBjoern A. Zeeb ath11k_err(ab, "failed to set prob req oui: %i\n", ret);
6321dd4f32aeSBjoern A. Zeeb goto err;
6322dd4f32aeSBjoern A. Zeeb }
6323dd4f32aeSBjoern A. Zeeb }
6324dd4f32aeSBjoern A. Zeeb
6325dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_ARP_AC_OVERRIDE,
6326dd4f32aeSBjoern A. Zeeb 0, pdev->pdev_id);
6327dd4f32aeSBjoern A. Zeeb if (ret) {
6328dd4f32aeSBjoern A. Zeeb ath11k_err(ab, "failed to set ac override for ARP: %d\n",
6329dd4f32aeSBjoern A. Zeeb ret);
6330dd4f32aeSBjoern A. Zeeb goto err;
6331dd4f32aeSBjoern A. Zeeb }
6332dd4f32aeSBjoern A. Zeeb
6333dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_send_dfs_phyerr_offload_enable_cmd(ar, pdev->pdev_id);
6334dd4f32aeSBjoern A. Zeeb if (ret) {
6335dd4f32aeSBjoern A. Zeeb ath11k_err(ab, "failed to offload radar detection: %d\n",
6336dd4f32aeSBjoern A. Zeeb ret);
6337dd4f32aeSBjoern A. Zeeb goto err;
6338dd4f32aeSBjoern A. Zeeb }
6339dd4f32aeSBjoern A. Zeeb
6340dd4f32aeSBjoern A. Zeeb ret = ath11k_dp_tx_htt_h2t_ppdu_stats_req(ar,
6341dd4f32aeSBjoern A. Zeeb HTT_PPDU_STATS_TAG_DEFAULT);
6342dd4f32aeSBjoern A. Zeeb if (ret) {
6343dd4f32aeSBjoern A. Zeeb ath11k_err(ab, "failed to req ppdu stats: %d\n", ret);
6344dd4f32aeSBjoern A. Zeeb goto err;
6345dd4f32aeSBjoern A. Zeeb }
6346dd4f32aeSBjoern A. Zeeb
6347dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_MESH_MCAST_ENABLE,
6348dd4f32aeSBjoern A. Zeeb 1, pdev->pdev_id);
6349dd4f32aeSBjoern A. Zeeb
6350dd4f32aeSBjoern A. Zeeb if (ret) {
6351dd4f32aeSBjoern A. Zeeb ath11k_err(ar->ab, "failed to enable MESH MCAST ENABLE: (%d\n", ret);
6352dd4f32aeSBjoern A. Zeeb goto err;
6353dd4f32aeSBjoern A. Zeeb }
6354dd4f32aeSBjoern A. Zeeb
6355dd4f32aeSBjoern A. Zeeb __ath11k_set_antenna(ar, ar->cfg_tx_chainmask, ar->cfg_rx_chainmask);
6356dd4f32aeSBjoern A. Zeeb
6357dd4f32aeSBjoern A. Zeeb /* TODO: Do we need to enable ANI? */
6358dd4f32aeSBjoern A. Zeeb
635928348caeSBjoern A. Zeeb ath11k_reg_update_chan_list(ar, false);
6360dd4f32aeSBjoern A. Zeeb
6361dd4f32aeSBjoern A. Zeeb ar->num_started_vdevs = 0;
6362dd4f32aeSBjoern A. Zeeb ar->num_created_vdevs = 0;
6363dd4f32aeSBjoern A. Zeeb ar->num_peers = 0;
6364dd4f32aeSBjoern A. Zeeb ar->allocated_vdev_map = 0;
6365dd4f32aeSBjoern A. Zeeb
6366dd4f32aeSBjoern A. Zeeb /* Configure monitor status ring with default rx_filter to get rx status
6367dd4f32aeSBjoern A. Zeeb * such as rssi, rx_duration.
6368dd4f32aeSBjoern A. Zeeb */
6369dd4f32aeSBjoern A. Zeeb ret = ath11k_mac_config_mon_status_default(ar, true);
6370dd4f32aeSBjoern A. Zeeb if (ret) {
6371dd4f32aeSBjoern A. Zeeb ath11k_err(ab, "failed to configure monitor status ring with default rx_filter: (%d)\n",
6372dd4f32aeSBjoern A. Zeeb ret);
6373dd4f32aeSBjoern A. Zeeb goto err;
6374dd4f32aeSBjoern A. Zeeb }
6375dd4f32aeSBjoern A. Zeeb
6376dd4f32aeSBjoern A. Zeeb /* Configure the hash seed for hash based reo dest ring selection */
6377dd4f32aeSBjoern A. Zeeb ath11k_wmi_pdev_lro_cfg(ar, ar->pdev->pdev_id);
6378dd4f32aeSBjoern A. Zeeb
6379dd4f32aeSBjoern A. Zeeb /* allow device to enter IMPS */
6380dd4f32aeSBjoern A. Zeeb if (ab->hw_params.idle_ps) {
6381dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_IDLE_PS_CONFIG,
6382dd4f32aeSBjoern A. Zeeb 1, pdev->pdev_id);
6383dd4f32aeSBjoern A. Zeeb if (ret) {
6384dd4f32aeSBjoern A. Zeeb ath11k_err(ab, "failed to enable idle ps: %d\n", ret);
6385dd4f32aeSBjoern A. Zeeb goto err;
6386dd4f32aeSBjoern A. Zeeb }
6387dd4f32aeSBjoern A. Zeeb }
6388dd4f32aeSBjoern A. Zeeb
6389dd4f32aeSBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
6390dd4f32aeSBjoern A. Zeeb
6391dd4f32aeSBjoern A. Zeeb rcu_assign_pointer(ab->pdevs_active[ar->pdev_idx],
6392dd4f32aeSBjoern A. Zeeb &ab->pdevs[ar->pdev_idx]);
6393dd4f32aeSBjoern A. Zeeb
6394dd4f32aeSBjoern A. Zeeb return 0;
6395dd4f32aeSBjoern A. Zeeb
6396dd4f32aeSBjoern A. Zeeb err:
6397dd4f32aeSBjoern A. Zeeb ar->state = ATH11K_STATE_OFF;
6398dd4f32aeSBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
6399dd4f32aeSBjoern A. Zeeb
6400dd4f32aeSBjoern A. Zeeb return ret;
6401dd4f32aeSBjoern A. Zeeb }
6402dd4f32aeSBjoern A. Zeeb
ath11k_mac_op_stop(struct ieee80211_hw * hw)6403dd4f32aeSBjoern A. Zeeb static void ath11k_mac_op_stop(struct ieee80211_hw *hw)
6404dd4f32aeSBjoern A. Zeeb {
6405dd4f32aeSBjoern A. Zeeb struct ath11k *ar = hw->priv;
6406dd4f32aeSBjoern A. Zeeb struct htt_ppdu_stats_info *ppdu_stats, *tmp;
6407dd4f32aeSBjoern A. Zeeb int ret;
6408dd4f32aeSBjoern A. Zeeb
6409dd4f32aeSBjoern A. Zeeb ath11k_mac_drain_tx(ar);
6410dd4f32aeSBjoern A. Zeeb
6411dd4f32aeSBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
6412dd4f32aeSBjoern A. Zeeb ret = ath11k_mac_config_mon_status_default(ar, false);
6413dd4f32aeSBjoern A. Zeeb if (ret)
6414dd4f32aeSBjoern A. Zeeb ath11k_err(ar->ab, "failed to clear rx_filter for monitor status ring: (%d)\n",
6415dd4f32aeSBjoern A. Zeeb ret);
6416dd4f32aeSBjoern A. Zeeb
6417dd4f32aeSBjoern A. Zeeb clear_bit(ATH11K_CAC_RUNNING, &ar->dev_flags);
6418dd4f32aeSBjoern A. Zeeb ar->state = ATH11K_STATE_OFF;
6419dd4f32aeSBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
6420dd4f32aeSBjoern A. Zeeb
6421dd4f32aeSBjoern A. Zeeb cancel_delayed_work_sync(&ar->scan.timeout);
6422dd4f32aeSBjoern A. Zeeb cancel_work_sync(&ar->regd_update_work);
6423dd4f32aeSBjoern A. Zeeb cancel_work_sync(&ar->ab->update_11d_work);
642428348caeSBjoern A. Zeeb
642528348caeSBjoern A. Zeeb if (ar->state_11d == ATH11K_11D_PREPARING) {
642628348caeSBjoern A. Zeeb ar->state_11d = ATH11K_11D_IDLE;
642728348caeSBjoern A. Zeeb complete(&ar->completed_11d_scan);
642828348caeSBjoern A. Zeeb }
6429dd4f32aeSBjoern A. Zeeb
6430dd4f32aeSBjoern A. Zeeb spin_lock_bh(&ar->data_lock);
6431dd4f32aeSBjoern A. Zeeb list_for_each_entry_safe(ppdu_stats, tmp, &ar->ppdu_stats_info, list) {
6432dd4f32aeSBjoern A. Zeeb list_del(&ppdu_stats->list);
6433dd4f32aeSBjoern A. Zeeb kfree(ppdu_stats);
6434dd4f32aeSBjoern A. Zeeb }
6435dd4f32aeSBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
6436dd4f32aeSBjoern A. Zeeb
6437dd4f32aeSBjoern A. Zeeb rcu_assign_pointer(ar->ab->pdevs_active[ar->pdev_idx], NULL);
6438dd4f32aeSBjoern A. Zeeb
6439dd4f32aeSBjoern A. Zeeb synchronize_rcu();
6440dd4f32aeSBjoern A. Zeeb
6441dd4f32aeSBjoern A. Zeeb atomic_set(&ar->num_pending_mgmt_tx, 0);
6442dd4f32aeSBjoern A. Zeeb }
6443dd4f32aeSBjoern A. Zeeb
ath11k_mac_setup_vdev_params_mbssid(struct ath11k_vif * arvif,u32 * flags,u32 * tx_vdev_id)644428348caeSBjoern A. Zeeb static int ath11k_mac_setup_vdev_params_mbssid(struct ath11k_vif *arvif,
644528348caeSBjoern A. Zeeb u32 *flags, u32 *tx_vdev_id)
644628348caeSBjoern A. Zeeb {
644728348caeSBjoern A. Zeeb struct ath11k *ar = arvif->ar;
644828348caeSBjoern A. Zeeb struct ath11k_vif *tx_arvif;
644928348caeSBjoern A. Zeeb struct ieee80211_vif *tx_vif;
645028348caeSBjoern A. Zeeb
645128348caeSBjoern A. Zeeb *tx_vdev_id = 0;
645228348caeSBjoern A. Zeeb tx_vif = arvif->vif->mbssid_tx_vif;
645328348caeSBjoern A. Zeeb if (!tx_vif) {
645428348caeSBjoern A. Zeeb *flags = WMI_HOST_VDEV_FLAGS_NON_MBSSID_AP;
645528348caeSBjoern A. Zeeb return 0;
645628348caeSBjoern A. Zeeb }
645728348caeSBjoern A. Zeeb
645828348caeSBjoern A. Zeeb tx_arvif = (void *)tx_vif->drv_priv;
645928348caeSBjoern A. Zeeb
646028348caeSBjoern A. Zeeb if (arvif->vif->bss_conf.nontransmitted) {
646128348caeSBjoern A. Zeeb if (ar->hw->wiphy != ieee80211_vif_to_wdev(tx_vif)->wiphy)
646228348caeSBjoern A. Zeeb return -EINVAL;
646328348caeSBjoern A. Zeeb
646428348caeSBjoern A. Zeeb *flags = WMI_HOST_VDEV_FLAGS_NON_TRANSMIT_AP;
646528348caeSBjoern A. Zeeb *tx_vdev_id = ath11k_vif_to_arvif(tx_vif)->vdev_id;
646628348caeSBjoern A. Zeeb } else if (tx_arvif == arvif) {
646728348caeSBjoern A. Zeeb *flags = WMI_HOST_VDEV_FLAGS_TRANSMIT_AP;
646828348caeSBjoern A. Zeeb } else {
646928348caeSBjoern A. Zeeb return -EINVAL;
647028348caeSBjoern A. Zeeb }
647128348caeSBjoern A. Zeeb
647228348caeSBjoern A. Zeeb if (arvif->vif->bss_conf.ema_ap)
647328348caeSBjoern A. Zeeb *flags |= WMI_HOST_VDEV_FLAGS_EMA_MODE;
647428348caeSBjoern A. Zeeb
647528348caeSBjoern A. Zeeb return 0;
647628348caeSBjoern A. Zeeb }
647728348caeSBjoern A. Zeeb
ath11k_mac_setup_vdev_create_params(struct ath11k_vif * arvif,struct vdev_create_params * params)647828348caeSBjoern A. Zeeb static int ath11k_mac_setup_vdev_create_params(struct ath11k_vif *arvif,
6479dd4f32aeSBjoern A. Zeeb struct vdev_create_params *params)
6480dd4f32aeSBjoern A. Zeeb {
6481dd4f32aeSBjoern A. Zeeb struct ath11k *ar = arvif->ar;
6482dd4f32aeSBjoern A. Zeeb struct ath11k_pdev *pdev = ar->pdev;
648328348caeSBjoern A. Zeeb int ret;
6484dd4f32aeSBjoern A. Zeeb
6485dd4f32aeSBjoern A. Zeeb params->if_id = arvif->vdev_id;
6486dd4f32aeSBjoern A. Zeeb params->type = arvif->vdev_type;
6487dd4f32aeSBjoern A. Zeeb params->subtype = arvif->vdev_subtype;
6488dd4f32aeSBjoern A. Zeeb params->pdev_id = pdev->pdev_id;
648928348caeSBjoern A. Zeeb params->mbssid_flags = 0;
649028348caeSBjoern A. Zeeb params->mbssid_tx_vdev_id = 0;
649128348caeSBjoern A. Zeeb
649228348caeSBjoern A. Zeeb if (!test_bit(WMI_TLV_SERVICE_MBSS_PARAM_IN_VDEV_START_SUPPORT,
649328348caeSBjoern A. Zeeb ar->ab->wmi_ab.svc_map)) {
649428348caeSBjoern A. Zeeb ret = ath11k_mac_setup_vdev_params_mbssid(arvif,
649528348caeSBjoern A. Zeeb ¶ms->mbssid_flags,
649628348caeSBjoern A. Zeeb ¶ms->mbssid_tx_vdev_id);
649728348caeSBjoern A. Zeeb if (ret)
649828348caeSBjoern A. Zeeb return ret;
649928348caeSBjoern A. Zeeb }
6500dd4f32aeSBjoern A. Zeeb
6501dd4f32aeSBjoern A. Zeeb if (pdev->cap.supported_bands & WMI_HOST_WLAN_2G_CAP) {
6502dd4f32aeSBjoern A. Zeeb params->chains[NL80211_BAND_2GHZ].tx = ar->num_tx_chains;
6503dd4f32aeSBjoern A. Zeeb params->chains[NL80211_BAND_2GHZ].rx = ar->num_rx_chains;
6504dd4f32aeSBjoern A. Zeeb }
6505dd4f32aeSBjoern A. Zeeb if (pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP) {
6506dd4f32aeSBjoern A. Zeeb params->chains[NL80211_BAND_5GHZ].tx = ar->num_tx_chains;
6507dd4f32aeSBjoern A. Zeeb params->chains[NL80211_BAND_5GHZ].rx = ar->num_rx_chains;
6508dd4f32aeSBjoern A. Zeeb }
6509dd4f32aeSBjoern A. Zeeb if (pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP &&
6510dd4f32aeSBjoern A. Zeeb ar->supports_6ghz) {
6511dd4f32aeSBjoern A. Zeeb params->chains[NL80211_BAND_6GHZ].tx = ar->num_tx_chains;
6512dd4f32aeSBjoern A. Zeeb params->chains[NL80211_BAND_6GHZ].rx = ar->num_rx_chains;
6513dd4f32aeSBjoern A. Zeeb }
651428348caeSBjoern A. Zeeb return 0;
6515dd4f32aeSBjoern A. Zeeb }
6516dd4f32aeSBjoern A. Zeeb
ath11k_mac_op_update_vif_offload(struct ieee80211_hw * hw,struct ieee80211_vif * vif)6517dd4f32aeSBjoern A. Zeeb static void ath11k_mac_op_update_vif_offload(struct ieee80211_hw *hw,
6518dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif)
6519dd4f32aeSBjoern A. Zeeb {
6520dd4f32aeSBjoern A. Zeeb struct ath11k *ar = hw->priv;
6521dd4f32aeSBjoern A. Zeeb struct ath11k_base *ab = ar->ab;
6522dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
6523dd4f32aeSBjoern A. Zeeb u32 param_id, param_value;
6524dd4f32aeSBjoern A. Zeeb int ret;
6525dd4f32aeSBjoern A. Zeeb
6526dd4f32aeSBjoern A. Zeeb param_id = WMI_VDEV_PARAM_TX_ENCAP_TYPE;
6527dd4f32aeSBjoern A. Zeeb if (ath11k_frame_mode != ATH11K_HW_TXRX_ETHERNET ||
6528dd4f32aeSBjoern A. Zeeb (vif->type != NL80211_IFTYPE_STATION &&
6529dd4f32aeSBjoern A. Zeeb vif->type != NL80211_IFTYPE_AP))
6530dd4f32aeSBjoern A. Zeeb vif->offload_flags &= ~(IEEE80211_OFFLOAD_ENCAP_ENABLED |
6531dd4f32aeSBjoern A. Zeeb IEEE80211_OFFLOAD_DECAP_ENABLED);
6532dd4f32aeSBjoern A. Zeeb
6533dd4f32aeSBjoern A. Zeeb if (vif->offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED)
6534dd4f32aeSBjoern A. Zeeb param_value = ATH11K_HW_TXRX_ETHERNET;
6535dd4f32aeSBjoern A. Zeeb else if (test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags))
6536dd4f32aeSBjoern A. Zeeb param_value = ATH11K_HW_TXRX_RAW;
6537dd4f32aeSBjoern A. Zeeb else
6538dd4f32aeSBjoern A. Zeeb param_value = ATH11K_HW_TXRX_NATIVE_WIFI;
6539dd4f32aeSBjoern A. Zeeb
6540dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
6541dd4f32aeSBjoern A. Zeeb param_id, param_value);
6542dd4f32aeSBjoern A. Zeeb if (ret) {
6543dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, "failed to set vdev %d tx encap mode: %d\n",
6544dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ret);
6545dd4f32aeSBjoern A. Zeeb vif->offload_flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED;
6546dd4f32aeSBjoern A. Zeeb }
6547dd4f32aeSBjoern A. Zeeb
6548dd4f32aeSBjoern A. Zeeb param_id = WMI_VDEV_PARAM_RX_DECAP_TYPE;
6549dd4f32aeSBjoern A. Zeeb if (vif->offload_flags & IEEE80211_OFFLOAD_DECAP_ENABLED)
6550dd4f32aeSBjoern A. Zeeb param_value = ATH11K_HW_TXRX_ETHERNET;
6551dd4f32aeSBjoern A. Zeeb else if (test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags))
6552dd4f32aeSBjoern A. Zeeb param_value = ATH11K_HW_TXRX_RAW;
6553dd4f32aeSBjoern A. Zeeb else
6554dd4f32aeSBjoern A. Zeeb param_value = ATH11K_HW_TXRX_NATIVE_WIFI;
6555dd4f32aeSBjoern A. Zeeb
6556dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
6557dd4f32aeSBjoern A. Zeeb param_id, param_value);
6558dd4f32aeSBjoern A. Zeeb if (ret) {
6559dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, "failed to set vdev %d rx decap mode: %d\n",
6560dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ret);
6561dd4f32aeSBjoern A. Zeeb vif->offload_flags &= ~IEEE80211_OFFLOAD_DECAP_ENABLED;
6562dd4f32aeSBjoern A. Zeeb }
6563dd4f32aeSBjoern A. Zeeb }
6564dd4f32aeSBjoern A. Zeeb
ath11k_mac_vif_ap_active_any(struct ath11k_base * ab)6565dd4f32aeSBjoern A. Zeeb static bool ath11k_mac_vif_ap_active_any(struct ath11k_base *ab)
6566dd4f32aeSBjoern A. Zeeb {
6567dd4f32aeSBjoern A. Zeeb struct ath11k *ar;
6568dd4f32aeSBjoern A. Zeeb struct ath11k_pdev *pdev;
6569dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif;
6570dd4f32aeSBjoern A. Zeeb int i;
6571dd4f32aeSBjoern A. Zeeb
6572dd4f32aeSBjoern A. Zeeb for (i = 0; i < ab->num_radios; i++) {
6573dd4f32aeSBjoern A. Zeeb pdev = &ab->pdevs[i];
6574dd4f32aeSBjoern A. Zeeb ar = pdev->ar;
6575dd4f32aeSBjoern A. Zeeb list_for_each_entry(arvif, &ar->arvifs, list) {
6576dd4f32aeSBjoern A. Zeeb if (arvif->is_up && arvif->vdev_type == WMI_VDEV_TYPE_AP)
6577dd4f32aeSBjoern A. Zeeb return true;
6578dd4f32aeSBjoern A. Zeeb }
6579dd4f32aeSBjoern A. Zeeb }
6580dd4f32aeSBjoern A. Zeeb return false;
6581dd4f32aeSBjoern A. Zeeb }
6582dd4f32aeSBjoern A. Zeeb
ath11k_mac_11d_scan_start(struct ath11k * ar,u32 vdev_id)658328348caeSBjoern A. Zeeb void ath11k_mac_11d_scan_start(struct ath11k *ar, u32 vdev_id)
6584dd4f32aeSBjoern A. Zeeb {
6585dd4f32aeSBjoern A. Zeeb struct wmi_11d_scan_start_params param;
6586dd4f32aeSBjoern A. Zeeb int ret;
6587dd4f32aeSBjoern A. Zeeb
6588dd4f32aeSBjoern A. Zeeb mutex_lock(&ar->ab->vdev_id_11d_lock);
6589dd4f32aeSBjoern A. Zeeb
659028348caeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev id for 11d scan %d\n",
6591dd4f32aeSBjoern A. Zeeb ar->vdev_id_11d_scan);
6592dd4f32aeSBjoern A. Zeeb
6593dd4f32aeSBjoern A. Zeeb if (ar->regdom_set_by_user)
6594dd4f32aeSBjoern A. Zeeb goto fin;
6595dd4f32aeSBjoern A. Zeeb
6596dd4f32aeSBjoern A. Zeeb if (ar->vdev_id_11d_scan != ATH11K_11D_INVALID_VDEV_ID)
6597dd4f32aeSBjoern A. Zeeb goto fin;
6598dd4f32aeSBjoern A. Zeeb
6599dd4f32aeSBjoern A. Zeeb if (!test_bit(WMI_TLV_SERVICE_11D_OFFLOAD, ar->ab->wmi_ab.svc_map))
6600dd4f32aeSBjoern A. Zeeb goto fin;
6601dd4f32aeSBjoern A. Zeeb
6602dd4f32aeSBjoern A. Zeeb if (ath11k_mac_vif_ap_active_any(ar->ab))
6603dd4f32aeSBjoern A. Zeeb goto fin;
6604dd4f32aeSBjoern A. Zeeb
6605dd4f32aeSBjoern A. Zeeb param.vdev_id = vdev_id;
6606dd4f32aeSBjoern A. Zeeb param.start_interval_msec = 0;
6607dd4f32aeSBjoern A. Zeeb param.scan_period_msec = ATH11K_SCAN_11D_INTERVAL;
6608dd4f32aeSBjoern A. Zeeb
660928348caeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "start 11d scan\n");
6610dd4f32aeSBjoern A. Zeeb
6611dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_send_11d_scan_start_cmd(ar, ¶m);
6612dd4f32aeSBjoern A. Zeeb if (ret) {
6613dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to start 11d scan vdev %d ret: %d\n",
6614dd4f32aeSBjoern A. Zeeb vdev_id, ret);
6615dd4f32aeSBjoern A. Zeeb } else {
6616dd4f32aeSBjoern A. Zeeb ar->vdev_id_11d_scan = vdev_id;
661728348caeSBjoern A. Zeeb if (ar->state_11d == ATH11K_11D_PREPARING)
661828348caeSBjoern A. Zeeb ar->state_11d = ATH11K_11D_RUNNING;
6619dd4f32aeSBjoern A. Zeeb }
6620dd4f32aeSBjoern A. Zeeb
6621dd4f32aeSBjoern A. Zeeb fin:
662228348caeSBjoern A. Zeeb if (ar->state_11d == ATH11K_11D_PREPARING) {
662328348caeSBjoern A. Zeeb ar->state_11d = ATH11K_11D_IDLE;
662428348caeSBjoern A. Zeeb complete(&ar->completed_11d_scan);
662528348caeSBjoern A. Zeeb }
662628348caeSBjoern A. Zeeb
6627dd4f32aeSBjoern A. Zeeb mutex_unlock(&ar->ab->vdev_id_11d_lock);
6628dd4f32aeSBjoern A. Zeeb }
6629dd4f32aeSBjoern A. Zeeb
ath11k_mac_11d_scan_stop(struct ath11k * ar)6630dd4f32aeSBjoern A. Zeeb void ath11k_mac_11d_scan_stop(struct ath11k *ar)
6631dd4f32aeSBjoern A. Zeeb {
6632dd4f32aeSBjoern A. Zeeb int ret;
6633dd4f32aeSBjoern A. Zeeb u32 vdev_id;
6634dd4f32aeSBjoern A. Zeeb
6635dd4f32aeSBjoern A. Zeeb if (!test_bit(WMI_TLV_SERVICE_11D_OFFLOAD, ar->ab->wmi_ab.svc_map))
6636dd4f32aeSBjoern A. Zeeb return;
6637dd4f32aeSBjoern A. Zeeb
663828348caeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "stop 11d scan\n");
6639dd4f32aeSBjoern A. Zeeb
6640dd4f32aeSBjoern A. Zeeb mutex_lock(&ar->ab->vdev_id_11d_lock);
6641dd4f32aeSBjoern A. Zeeb
664228348caeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "stop 11d vdev id %d\n",
6643dd4f32aeSBjoern A. Zeeb ar->vdev_id_11d_scan);
6644dd4f32aeSBjoern A. Zeeb
664528348caeSBjoern A. Zeeb if (ar->state_11d == ATH11K_11D_PREPARING) {
664628348caeSBjoern A. Zeeb ar->state_11d = ATH11K_11D_IDLE;
664728348caeSBjoern A. Zeeb complete(&ar->completed_11d_scan);
664828348caeSBjoern A. Zeeb }
664928348caeSBjoern A. Zeeb
6650dd4f32aeSBjoern A. Zeeb if (ar->vdev_id_11d_scan != ATH11K_11D_INVALID_VDEV_ID) {
6651dd4f32aeSBjoern A. Zeeb vdev_id = ar->vdev_id_11d_scan;
6652dd4f32aeSBjoern A. Zeeb
6653dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_send_11d_scan_stop_cmd(ar, vdev_id);
665428348caeSBjoern A. Zeeb if (ret) {
6655dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab,
6656dd4f32aeSBjoern A. Zeeb "failed to stopt 11d scan vdev %d ret: %d\n",
6657dd4f32aeSBjoern A. Zeeb vdev_id, ret);
665828348caeSBjoern A. Zeeb } else {
6659dd4f32aeSBjoern A. Zeeb ar->vdev_id_11d_scan = ATH11K_11D_INVALID_VDEV_ID;
666028348caeSBjoern A. Zeeb ar->state_11d = ATH11K_11D_IDLE;
666128348caeSBjoern A. Zeeb complete(&ar->completed_11d_scan);
666228348caeSBjoern A. Zeeb }
6663dd4f32aeSBjoern A. Zeeb }
6664dd4f32aeSBjoern A. Zeeb mutex_unlock(&ar->ab->vdev_id_11d_lock);
6665dd4f32aeSBjoern A. Zeeb }
6666dd4f32aeSBjoern A. Zeeb
ath11k_mac_11d_scan_stop_all(struct ath11k_base * ab)6667dd4f32aeSBjoern A. Zeeb void ath11k_mac_11d_scan_stop_all(struct ath11k_base *ab)
6668dd4f32aeSBjoern A. Zeeb {
6669dd4f32aeSBjoern A. Zeeb struct ath11k *ar;
6670dd4f32aeSBjoern A. Zeeb struct ath11k_pdev *pdev;
6671dd4f32aeSBjoern A. Zeeb int i;
6672dd4f32aeSBjoern A. Zeeb
667328348caeSBjoern A. Zeeb ath11k_dbg(ab, ATH11K_DBG_MAC, "stop soc 11d scan\n");
6674dd4f32aeSBjoern A. Zeeb
6675dd4f32aeSBjoern A. Zeeb for (i = 0; i < ab->num_radios; i++) {
6676dd4f32aeSBjoern A. Zeeb pdev = &ab->pdevs[i];
6677dd4f32aeSBjoern A. Zeeb ar = pdev->ar;
6678dd4f32aeSBjoern A. Zeeb
6679dd4f32aeSBjoern A. Zeeb ath11k_mac_11d_scan_stop(ar);
6680dd4f32aeSBjoern A. Zeeb }
6681dd4f32aeSBjoern A. Zeeb }
6682dd4f32aeSBjoern A. Zeeb
ath11k_mac_vdev_delete(struct ath11k * ar,struct ath11k_vif * arvif)668328348caeSBjoern A. Zeeb static int ath11k_mac_vdev_delete(struct ath11k *ar, struct ath11k_vif *arvif)
668428348caeSBjoern A. Zeeb {
668528348caeSBjoern A. Zeeb unsigned long time_left;
668628348caeSBjoern A. Zeeb struct ieee80211_vif *vif = arvif->vif;
668728348caeSBjoern A. Zeeb int ret = 0;
668828348caeSBjoern A. Zeeb
668928348caeSBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
669028348caeSBjoern A. Zeeb
669128348caeSBjoern A. Zeeb reinit_completion(&ar->vdev_delete_done);
669228348caeSBjoern A. Zeeb
669328348caeSBjoern A. Zeeb ret = ath11k_wmi_vdev_delete(ar, arvif->vdev_id);
669428348caeSBjoern A. Zeeb if (ret) {
669528348caeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to delete WMI vdev %d: %d\n",
669628348caeSBjoern A. Zeeb arvif->vdev_id, ret);
669728348caeSBjoern A. Zeeb return ret;
669828348caeSBjoern A. Zeeb }
669928348caeSBjoern A. Zeeb
670028348caeSBjoern A. Zeeb time_left = wait_for_completion_timeout(&ar->vdev_delete_done,
670128348caeSBjoern A. Zeeb ATH11K_VDEV_DELETE_TIMEOUT_HZ);
670228348caeSBjoern A. Zeeb if (time_left == 0) {
670328348caeSBjoern A. Zeeb ath11k_warn(ar->ab, "Timeout in receiving vdev delete response\n");
670428348caeSBjoern A. Zeeb return -ETIMEDOUT;
670528348caeSBjoern A. Zeeb }
670628348caeSBjoern A. Zeeb
670728348caeSBjoern A. Zeeb ar->ab->free_vdev_map |= 1LL << (arvif->vdev_id);
670828348caeSBjoern A. Zeeb ar->allocated_vdev_map &= ~(1LL << arvif->vdev_id);
670928348caeSBjoern A. Zeeb ar->num_created_vdevs--;
671028348caeSBjoern A. Zeeb
671128348caeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev %pM deleted, vdev_id %d\n",
671228348caeSBjoern A. Zeeb vif->addr, arvif->vdev_id);
671328348caeSBjoern A. Zeeb
671428348caeSBjoern A. Zeeb return ret;
671528348caeSBjoern A. Zeeb }
671628348caeSBjoern A. Zeeb
ath11k_mac_op_add_interface(struct ieee80211_hw * hw,struct ieee80211_vif * vif)6717dd4f32aeSBjoern A. Zeeb static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,
6718dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif)
6719dd4f32aeSBjoern A. Zeeb {
6720dd4f32aeSBjoern A. Zeeb struct ath11k *ar = hw->priv;
6721dd4f32aeSBjoern A. Zeeb struct ath11k_base *ab = ar->ab;
6722dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
6723dd4f32aeSBjoern A. Zeeb struct vdev_create_params vdev_param = {0};
6724dd4f32aeSBjoern A. Zeeb struct peer_create_params peer_param;
6725dd4f32aeSBjoern A. Zeeb u32 param_id, param_value;
6726dd4f32aeSBjoern A. Zeeb u16 nss;
6727dd4f32aeSBjoern A. Zeeb int i;
6728dd4f32aeSBjoern A. Zeeb int ret, fbret;
6729dd4f32aeSBjoern A. Zeeb int bit;
6730dd4f32aeSBjoern A. Zeeb
6731dd4f32aeSBjoern A. Zeeb vif->driver_flags |= IEEE80211_VIF_SUPPORTS_UAPSD;
6732dd4f32aeSBjoern A. Zeeb
6733dd4f32aeSBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
6734dd4f32aeSBjoern A. Zeeb
6735dd4f32aeSBjoern A. Zeeb if (vif->type == NL80211_IFTYPE_AP &&
6736dd4f32aeSBjoern A. Zeeb ar->num_peers > (ar->max_num_peers - 1)) {
6737dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, "failed to create vdev due to insufficient peer entry resource in firmware\n");
6738dd4f32aeSBjoern A. Zeeb ret = -ENOBUFS;
6739dd4f32aeSBjoern A. Zeeb goto err;
6740dd4f32aeSBjoern A. Zeeb }
6741dd4f32aeSBjoern A. Zeeb
6742dd4f32aeSBjoern A. Zeeb if (ar->num_created_vdevs > (TARGET_NUM_VDEVS(ab) - 1)) {
6743dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, "failed to create vdev %u, reached max vdev limit %d\n",
6744dd4f32aeSBjoern A. Zeeb ar->num_created_vdevs, TARGET_NUM_VDEVS(ab));
6745dd4f32aeSBjoern A. Zeeb ret = -EBUSY;
6746dd4f32aeSBjoern A. Zeeb goto err;
6747dd4f32aeSBjoern A. Zeeb }
6748dd4f32aeSBjoern A. Zeeb
674928348caeSBjoern A. Zeeb /* In the case of hardware recovery, debugfs files are
675028348caeSBjoern A. Zeeb * not deleted since ieee80211_ops.remove_interface() is
675128348caeSBjoern A. Zeeb * not invoked. In such cases, try to delete the files.
675228348caeSBjoern A. Zeeb * These will be re-created later.
675328348caeSBjoern A. Zeeb */
675428348caeSBjoern A. Zeeb ath11k_debugfs_remove_interface(arvif);
675528348caeSBjoern A. Zeeb
6756dd4f32aeSBjoern A. Zeeb memset(arvif, 0, sizeof(*arvif));
6757dd4f32aeSBjoern A. Zeeb
6758dd4f32aeSBjoern A. Zeeb arvif->ar = ar;
6759dd4f32aeSBjoern A. Zeeb arvif->vif = vif;
6760dd4f32aeSBjoern A. Zeeb
6761dd4f32aeSBjoern A. Zeeb INIT_LIST_HEAD(&arvif->list);
6762dd4f32aeSBjoern A. Zeeb INIT_DELAYED_WORK(&arvif->connection_loss_work,
6763dd4f32aeSBjoern A. Zeeb ath11k_mac_vif_sta_connection_loss_work);
6764dd4f32aeSBjoern A. Zeeb
6765dd4f32aeSBjoern A. Zeeb for (i = 0; i < ARRAY_SIZE(arvif->bitrate_mask.control); i++) {
6766dd4f32aeSBjoern A. Zeeb arvif->bitrate_mask.control[i].legacy = 0xffffffff;
6767dd4f32aeSBjoern A. Zeeb arvif->bitrate_mask.control[i].gi = NL80211_TXRATE_FORCE_SGI;
6768dd4f32aeSBjoern A. Zeeb memset(arvif->bitrate_mask.control[i].ht_mcs, 0xff,
6769dd4f32aeSBjoern A. Zeeb sizeof(arvif->bitrate_mask.control[i].ht_mcs));
6770dd4f32aeSBjoern A. Zeeb memset(arvif->bitrate_mask.control[i].vht_mcs, 0xff,
6771dd4f32aeSBjoern A. Zeeb sizeof(arvif->bitrate_mask.control[i].vht_mcs));
6772dd4f32aeSBjoern A. Zeeb memset(arvif->bitrate_mask.control[i].he_mcs, 0xff,
6773dd4f32aeSBjoern A. Zeeb sizeof(arvif->bitrate_mask.control[i].he_mcs));
6774dd4f32aeSBjoern A. Zeeb }
6775dd4f32aeSBjoern A. Zeeb
6776dd4f32aeSBjoern A. Zeeb bit = __ffs64(ab->free_vdev_map);
6777dd4f32aeSBjoern A. Zeeb
6778dd4f32aeSBjoern A. Zeeb arvif->vdev_id = bit;
6779dd4f32aeSBjoern A. Zeeb arvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE;
6780dd4f32aeSBjoern A. Zeeb
6781dd4f32aeSBjoern A. Zeeb switch (vif->type) {
6782dd4f32aeSBjoern A. Zeeb case NL80211_IFTYPE_UNSPECIFIED:
6783dd4f32aeSBjoern A. Zeeb case NL80211_IFTYPE_STATION:
6784dd4f32aeSBjoern A. Zeeb arvif->vdev_type = WMI_VDEV_TYPE_STA;
6785dd4f32aeSBjoern A. Zeeb break;
6786dd4f32aeSBjoern A. Zeeb case NL80211_IFTYPE_MESH_POINT:
6787dd4f32aeSBjoern A. Zeeb arvif->vdev_subtype = WMI_VDEV_SUBTYPE_MESH_11S;
6788dd4f32aeSBjoern A. Zeeb fallthrough;
6789dd4f32aeSBjoern A. Zeeb case NL80211_IFTYPE_AP:
6790dd4f32aeSBjoern A. Zeeb arvif->vdev_type = WMI_VDEV_TYPE_AP;
6791dd4f32aeSBjoern A. Zeeb break;
6792dd4f32aeSBjoern A. Zeeb case NL80211_IFTYPE_MONITOR:
6793dd4f32aeSBjoern A. Zeeb arvif->vdev_type = WMI_VDEV_TYPE_MONITOR;
6794dd4f32aeSBjoern A. Zeeb ar->monitor_vdev_id = bit;
6795dd4f32aeSBjoern A. Zeeb break;
6796dd4f32aeSBjoern A. Zeeb default:
6797dd4f32aeSBjoern A. Zeeb WARN_ON(1);
6798dd4f32aeSBjoern A. Zeeb break;
6799dd4f32aeSBjoern A. Zeeb }
6800dd4f32aeSBjoern A. Zeeb
680128348caeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "add interface id %d type %d subtype %d map %llx\n",
6802dd4f32aeSBjoern A. Zeeb arvif->vdev_id, arvif->vdev_type, arvif->vdev_subtype,
6803dd4f32aeSBjoern A. Zeeb ab->free_vdev_map);
6804dd4f32aeSBjoern A. Zeeb
6805dd4f32aeSBjoern A. Zeeb vif->cab_queue = arvif->vdev_id % (ATH11K_HW_MAX_QUEUES - 1);
6806dd4f32aeSBjoern A. Zeeb for (i = 0; i < ARRAY_SIZE(vif->hw_queue); i++)
6807dd4f32aeSBjoern A. Zeeb vif->hw_queue[i] = i % (ATH11K_HW_MAX_QUEUES - 1);
6808dd4f32aeSBjoern A. Zeeb
680928348caeSBjoern A. Zeeb ret = ath11k_mac_setup_vdev_create_params(arvif, &vdev_param);
681028348caeSBjoern A. Zeeb if (ret) {
681128348caeSBjoern A. Zeeb ath11k_warn(ab, "failed to create vdev parameters %d: %d\n",
681228348caeSBjoern A. Zeeb arvif->vdev_id, ret);
681328348caeSBjoern A. Zeeb goto err;
681428348caeSBjoern A. Zeeb }
6815dd4f32aeSBjoern A. Zeeb
6816dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_vdev_create(ar, vif->addr, &vdev_param);
6817dd4f32aeSBjoern A. Zeeb if (ret) {
6818dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, "failed to create WMI vdev %d: %d\n",
6819dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ret);
6820dd4f32aeSBjoern A. Zeeb goto err;
6821dd4f32aeSBjoern A. Zeeb }
6822dd4f32aeSBjoern A. Zeeb
6823dd4f32aeSBjoern A. Zeeb ar->num_created_vdevs++;
6824dd4f32aeSBjoern A. Zeeb ath11k_dbg(ab, ATH11K_DBG_MAC, "vdev %pM created, vdev_id %d\n",
6825dd4f32aeSBjoern A. Zeeb vif->addr, arvif->vdev_id);
6826dd4f32aeSBjoern A. Zeeb ar->allocated_vdev_map |= 1LL << arvif->vdev_id;
6827dd4f32aeSBjoern A. Zeeb ab->free_vdev_map &= ~(1LL << arvif->vdev_id);
6828dd4f32aeSBjoern A. Zeeb
6829dd4f32aeSBjoern A. Zeeb spin_lock_bh(&ar->data_lock);
6830dd4f32aeSBjoern A. Zeeb list_add(&arvif->list, &ar->arvifs);
6831dd4f32aeSBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
6832dd4f32aeSBjoern A. Zeeb
6833dd4f32aeSBjoern A. Zeeb ath11k_mac_op_update_vif_offload(hw, vif);
6834dd4f32aeSBjoern A. Zeeb
6835dd4f32aeSBjoern A. Zeeb nss = get_num_chains(ar->cfg_tx_chainmask) ? : 1;
6836dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
6837dd4f32aeSBjoern A. Zeeb WMI_VDEV_PARAM_NSS, nss);
6838dd4f32aeSBjoern A. Zeeb if (ret) {
6839dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, "failed to set vdev %d chainmask 0x%x, nss %d :%d\n",
6840dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ar->cfg_tx_chainmask, nss, ret);
6841dd4f32aeSBjoern A. Zeeb goto err_vdev_del;
6842dd4f32aeSBjoern A. Zeeb }
6843dd4f32aeSBjoern A. Zeeb
6844dd4f32aeSBjoern A. Zeeb switch (arvif->vdev_type) {
6845dd4f32aeSBjoern A. Zeeb case WMI_VDEV_TYPE_AP:
6846dd4f32aeSBjoern A. Zeeb peer_param.vdev_id = arvif->vdev_id;
6847dd4f32aeSBjoern A. Zeeb peer_param.peer_addr = vif->addr;
6848dd4f32aeSBjoern A. Zeeb peer_param.peer_type = WMI_PEER_TYPE_DEFAULT;
6849dd4f32aeSBjoern A. Zeeb ret = ath11k_peer_create(ar, arvif, NULL, &peer_param);
6850dd4f32aeSBjoern A. Zeeb if (ret) {
6851dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, "failed to vdev %d create peer for AP: %d\n",
6852dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ret);
6853dd4f32aeSBjoern A. Zeeb goto err_vdev_del;
6854dd4f32aeSBjoern A. Zeeb }
6855dd4f32aeSBjoern A. Zeeb
6856dd4f32aeSBjoern A. Zeeb ret = ath11k_mac_set_kickout(arvif);
6857dd4f32aeSBjoern A. Zeeb if (ret) {
6858dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to set vdev %i kickout parameters: %d\n",
6859dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ret);
6860dd4f32aeSBjoern A. Zeeb goto err_peer_del;
6861dd4f32aeSBjoern A. Zeeb }
6862dd4f32aeSBjoern A. Zeeb
6863dd4f32aeSBjoern A. Zeeb ath11k_mac_11d_scan_stop_all(ar->ab);
6864dd4f32aeSBjoern A. Zeeb break;
6865dd4f32aeSBjoern A. Zeeb case WMI_VDEV_TYPE_STA:
6866dd4f32aeSBjoern A. Zeeb param_id = WMI_STA_PS_PARAM_RX_WAKE_POLICY;
6867dd4f32aeSBjoern A. Zeeb param_value = WMI_STA_PS_RX_WAKE_POLICY_WAKE;
6868dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_set_sta_ps_param(ar, arvif->vdev_id,
6869dd4f32aeSBjoern A. Zeeb param_id, param_value);
6870dd4f32aeSBjoern A. Zeeb if (ret) {
6871dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to set vdev %d RX wake policy: %d\n",
6872dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ret);
6873dd4f32aeSBjoern A. Zeeb goto err_peer_del;
6874dd4f32aeSBjoern A. Zeeb }
6875dd4f32aeSBjoern A. Zeeb
6876dd4f32aeSBjoern A. Zeeb param_id = WMI_STA_PS_PARAM_TX_WAKE_THRESHOLD;
6877dd4f32aeSBjoern A. Zeeb param_value = WMI_STA_PS_TX_WAKE_THRESHOLD_ALWAYS;
6878dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_set_sta_ps_param(ar, arvif->vdev_id,
6879dd4f32aeSBjoern A. Zeeb param_id, param_value);
6880dd4f32aeSBjoern A. Zeeb if (ret) {
6881dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to set vdev %d TX wake threshold: %d\n",
6882dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ret);
6883dd4f32aeSBjoern A. Zeeb goto err_peer_del;
6884dd4f32aeSBjoern A. Zeeb }
6885dd4f32aeSBjoern A. Zeeb
6886dd4f32aeSBjoern A. Zeeb param_id = WMI_STA_PS_PARAM_PSPOLL_COUNT;
6887dd4f32aeSBjoern A. Zeeb param_value = WMI_STA_PS_PSPOLL_COUNT_NO_MAX;
6888dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_set_sta_ps_param(ar, arvif->vdev_id,
6889dd4f32aeSBjoern A. Zeeb param_id, param_value);
6890dd4f32aeSBjoern A. Zeeb if (ret) {
6891dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to set vdev %d pspoll count: %d\n",
6892dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ret);
6893dd4f32aeSBjoern A. Zeeb goto err_peer_del;
6894dd4f32aeSBjoern A. Zeeb }
6895dd4f32aeSBjoern A. Zeeb
6896dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_pdev_set_ps_mode(ar, arvif->vdev_id,
6897dd4f32aeSBjoern A. Zeeb WMI_STA_PS_MODE_DISABLED);
6898dd4f32aeSBjoern A. Zeeb if (ret) {
6899dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to disable vdev %d ps mode: %d\n",
6900dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ret);
6901dd4f32aeSBjoern A. Zeeb goto err_peer_del;
6902dd4f32aeSBjoern A. Zeeb }
6903dd4f32aeSBjoern A. Zeeb
690428348caeSBjoern A. Zeeb if (test_bit(WMI_TLV_SERVICE_11D_OFFLOAD, ab->wmi_ab.svc_map)) {
690528348caeSBjoern A. Zeeb reinit_completion(&ar->completed_11d_scan);
690628348caeSBjoern A. Zeeb ar->state_11d = ATH11K_11D_PREPARING;
690728348caeSBjoern A. Zeeb }
6908dd4f32aeSBjoern A. Zeeb break;
6909dd4f32aeSBjoern A. Zeeb case WMI_VDEV_TYPE_MONITOR:
6910dd4f32aeSBjoern A. Zeeb set_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags);
6911dd4f32aeSBjoern A. Zeeb break;
6912dd4f32aeSBjoern A. Zeeb default:
6913dd4f32aeSBjoern A. Zeeb break;
6914dd4f32aeSBjoern A. Zeeb }
6915dd4f32aeSBjoern A. Zeeb
6916dd4f32aeSBjoern A. Zeeb arvif->txpower = vif->bss_conf.txpower;
6917dd4f32aeSBjoern A. Zeeb ret = ath11k_mac_txpower_recalc(ar);
6918dd4f32aeSBjoern A. Zeeb if (ret)
6919dd4f32aeSBjoern A. Zeeb goto err_peer_del;
6920dd4f32aeSBjoern A. Zeeb
6921dd4f32aeSBjoern A. Zeeb param_id = WMI_VDEV_PARAM_RTS_THRESHOLD;
6922dd4f32aeSBjoern A. Zeeb param_value = ar->hw->wiphy->rts_threshold;
6923dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
6924dd4f32aeSBjoern A. Zeeb param_id, param_value);
6925dd4f32aeSBjoern A. Zeeb if (ret) {
6926dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to set rts threshold for vdev %d: %d\n",
6927dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ret);
6928dd4f32aeSBjoern A. Zeeb }
6929dd4f32aeSBjoern A. Zeeb
6930dd4f32aeSBjoern A. Zeeb ath11k_dp_vdev_tx_attach(ar, arvif);
6931dd4f32aeSBjoern A. Zeeb
693228348caeSBjoern A. Zeeb ath11k_debugfs_add_interface(arvif);
693328348caeSBjoern A. Zeeb
6934dd4f32aeSBjoern A. Zeeb if (vif->type != NL80211_IFTYPE_MONITOR &&
6935dd4f32aeSBjoern A. Zeeb test_bit(ATH11K_FLAG_MONITOR_CONF_ENABLED, &ar->monitor_flags)) {
6936dd4f32aeSBjoern A. Zeeb ret = ath11k_mac_monitor_vdev_create(ar);
693728348caeSBjoern A. Zeeb if (ret)
6938dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to create monitor vdev during add interface: %d",
6939dd4f32aeSBjoern A. Zeeb ret);
6940dd4f32aeSBjoern A. Zeeb }
6941dd4f32aeSBjoern A. Zeeb
6942dd4f32aeSBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
6943dd4f32aeSBjoern A. Zeeb
6944dd4f32aeSBjoern A. Zeeb return 0;
6945dd4f32aeSBjoern A. Zeeb
6946dd4f32aeSBjoern A. Zeeb err_peer_del:
6947dd4f32aeSBjoern A. Zeeb if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
694828348caeSBjoern A. Zeeb fbret = ath11k_peer_delete(ar, arvif->vdev_id, vif->addr);
6949dd4f32aeSBjoern A. Zeeb if (fbret) {
695028348caeSBjoern A. Zeeb ath11k_warn(ar->ab, "fallback fail to delete peer addr %pM vdev_id %d ret %d\n",
695128348caeSBjoern A. Zeeb vif->addr, arvif->vdev_id, fbret);
6952dd4f32aeSBjoern A. Zeeb goto err;
6953dd4f32aeSBjoern A. Zeeb }
6954dd4f32aeSBjoern A. Zeeb }
6955dd4f32aeSBjoern A. Zeeb
6956dd4f32aeSBjoern A. Zeeb err_vdev_del:
695728348caeSBjoern A. Zeeb ath11k_mac_vdev_delete(ar, arvif);
6958dd4f32aeSBjoern A. Zeeb spin_lock_bh(&ar->data_lock);
6959dd4f32aeSBjoern A. Zeeb list_del(&arvif->list);
6960dd4f32aeSBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
6961dd4f32aeSBjoern A. Zeeb
6962dd4f32aeSBjoern A. Zeeb err:
6963dd4f32aeSBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
6964dd4f32aeSBjoern A. Zeeb
6965dd4f32aeSBjoern A. Zeeb return ret;
6966dd4f32aeSBjoern A. Zeeb }
6967dd4f32aeSBjoern A. Zeeb
ath11k_mac_vif_unref(int buf_id,void * skb,void * ctx)6968dd4f32aeSBjoern A. Zeeb static int ath11k_mac_vif_unref(int buf_id, void *skb, void *ctx)
6969dd4f32aeSBjoern A. Zeeb {
6970dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif = (struct ieee80211_vif *)ctx;
6971dd4f32aeSBjoern A. Zeeb struct ath11k_skb_cb *skb_cb = ATH11K_SKB_CB((struct sk_buff *)skb);
6972dd4f32aeSBjoern A. Zeeb
6973dd4f32aeSBjoern A. Zeeb if (skb_cb->vif == vif)
6974dd4f32aeSBjoern A. Zeeb skb_cb->vif = NULL;
6975dd4f32aeSBjoern A. Zeeb
6976dd4f32aeSBjoern A. Zeeb return 0;
6977dd4f32aeSBjoern A. Zeeb }
6978dd4f32aeSBjoern A. Zeeb
ath11k_mac_op_remove_interface(struct ieee80211_hw * hw,struct ieee80211_vif * vif)6979dd4f32aeSBjoern A. Zeeb static void ath11k_mac_op_remove_interface(struct ieee80211_hw *hw,
6980dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif)
6981dd4f32aeSBjoern A. Zeeb {
6982dd4f32aeSBjoern A. Zeeb struct ath11k *ar = hw->priv;
6983dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
6984dd4f32aeSBjoern A. Zeeb struct ath11k_base *ab = ar->ab;
6985dd4f32aeSBjoern A. Zeeb int ret;
6986dd4f32aeSBjoern A. Zeeb int i;
6987dd4f32aeSBjoern A. Zeeb
6988dd4f32aeSBjoern A. Zeeb cancel_delayed_work_sync(&arvif->connection_loss_work);
6989dd4f32aeSBjoern A. Zeeb
6990dd4f32aeSBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
6991dd4f32aeSBjoern A. Zeeb
699228348caeSBjoern A. Zeeb ath11k_dbg(ab, ATH11K_DBG_MAC, "remove interface (vdev %d)\n",
6993dd4f32aeSBjoern A. Zeeb arvif->vdev_id);
6994dd4f32aeSBjoern A. Zeeb
699528348caeSBjoern A. Zeeb ret = ath11k_spectral_vif_stop(arvif);
699628348caeSBjoern A. Zeeb if (ret)
699728348caeSBjoern A. Zeeb ath11k_warn(ab, "failed to stop spectral for vdev %i: %d\n",
699828348caeSBjoern A. Zeeb arvif->vdev_id, ret);
699928348caeSBjoern A. Zeeb
7000dd4f32aeSBjoern A. Zeeb if (arvif->vdev_type == WMI_VDEV_TYPE_STA)
7001dd4f32aeSBjoern A. Zeeb ath11k_mac_11d_scan_stop(ar);
7002dd4f32aeSBjoern A. Zeeb
7003dd4f32aeSBjoern A. Zeeb if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
7004dd4f32aeSBjoern A. Zeeb ret = ath11k_peer_delete(ar, arvif->vdev_id, vif->addr);
7005dd4f32aeSBjoern A. Zeeb if (ret)
7006dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, "failed to submit AP self-peer removal on vdev %d: %d\n",
7007dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ret);
7008dd4f32aeSBjoern A. Zeeb }
7009dd4f32aeSBjoern A. Zeeb
701028348caeSBjoern A. Zeeb ret = ath11k_mac_vdev_delete(ar, arvif);
7011dd4f32aeSBjoern A. Zeeb if (ret) {
701228348caeSBjoern A. Zeeb ath11k_warn(ab, "failed to delete vdev %d: %d\n",
7013dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ret);
7014dd4f32aeSBjoern A. Zeeb goto err_vdev_del;
7015dd4f32aeSBjoern A. Zeeb }
7016dd4f32aeSBjoern A. Zeeb
7017dd4f32aeSBjoern A. Zeeb if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
7018dd4f32aeSBjoern A. Zeeb clear_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags);
7019dd4f32aeSBjoern A. Zeeb ar->monitor_vdev_id = -1;
7020dd4f32aeSBjoern A. Zeeb } else if (test_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags) &&
7021dd4f32aeSBjoern A. Zeeb !test_bit(ATH11K_FLAG_MONITOR_STARTED, &ar->monitor_flags)) {
7022dd4f32aeSBjoern A. Zeeb ret = ath11k_mac_monitor_vdev_delete(ar);
7023dd4f32aeSBjoern A. Zeeb if (ret)
7024dd4f32aeSBjoern A. Zeeb /* continue even if there's an error */
7025dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to delete vdev monitor during remove interface: %d",
7026dd4f32aeSBjoern A. Zeeb ret);
7027dd4f32aeSBjoern A. Zeeb }
7028dd4f32aeSBjoern A. Zeeb
7029dd4f32aeSBjoern A. Zeeb err_vdev_del:
7030dd4f32aeSBjoern A. Zeeb spin_lock_bh(&ar->data_lock);
7031dd4f32aeSBjoern A. Zeeb list_del(&arvif->list);
7032dd4f32aeSBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
7033dd4f32aeSBjoern A. Zeeb
7034dd4f32aeSBjoern A. Zeeb ath11k_peer_cleanup(ar, arvif->vdev_id);
7035dd4f32aeSBjoern A. Zeeb
7036dd4f32aeSBjoern A. Zeeb idr_for_each(&ar->txmgmt_idr,
7037dd4f32aeSBjoern A. Zeeb ath11k_mac_vif_txmgmt_idr_remove, vif);
7038dd4f32aeSBjoern A. Zeeb
7039dd4f32aeSBjoern A. Zeeb for (i = 0; i < ab->hw_params.max_tx_ring; i++) {
7040dd4f32aeSBjoern A. Zeeb spin_lock_bh(&ab->dp.tx_ring[i].tx_idr_lock);
7041dd4f32aeSBjoern A. Zeeb idr_for_each(&ab->dp.tx_ring[i].txbuf_idr,
7042dd4f32aeSBjoern A. Zeeb ath11k_mac_vif_unref, vif);
7043dd4f32aeSBjoern A. Zeeb spin_unlock_bh(&ab->dp.tx_ring[i].tx_idr_lock);
7044dd4f32aeSBjoern A. Zeeb }
7045dd4f32aeSBjoern A. Zeeb
7046dd4f32aeSBjoern A. Zeeb /* Recalc txpower for remaining vdev */
7047dd4f32aeSBjoern A. Zeeb ath11k_mac_txpower_recalc(ar);
7048dd4f32aeSBjoern A. Zeeb
704928348caeSBjoern A. Zeeb ath11k_debugfs_remove_interface(arvif);
705028348caeSBjoern A. Zeeb
7051dd4f32aeSBjoern A. Zeeb /* TODO: recal traffic pause state based on the available vdevs */
7052dd4f32aeSBjoern A. Zeeb
7053dd4f32aeSBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
7054dd4f32aeSBjoern A. Zeeb }
7055dd4f32aeSBjoern A. Zeeb
7056dd4f32aeSBjoern A. Zeeb /* FIXME: Has to be verified. */
7057dd4f32aeSBjoern A. Zeeb #define SUPPORTED_FILTERS \
7058dd4f32aeSBjoern A. Zeeb (FIF_ALLMULTI | \
7059dd4f32aeSBjoern A. Zeeb FIF_CONTROL | \
7060dd4f32aeSBjoern A. Zeeb FIF_PSPOLL | \
7061dd4f32aeSBjoern A. Zeeb FIF_OTHER_BSS | \
7062dd4f32aeSBjoern A. Zeeb FIF_BCN_PRBRESP_PROMISC | \
7063dd4f32aeSBjoern A. Zeeb FIF_PROBE_REQ | \
7064dd4f32aeSBjoern A. Zeeb FIF_FCSFAIL)
7065dd4f32aeSBjoern A. Zeeb
ath11k_mac_op_configure_filter(struct ieee80211_hw * hw,unsigned int changed_flags,unsigned int * total_flags,u64 multicast)7066dd4f32aeSBjoern A. Zeeb static void ath11k_mac_op_configure_filter(struct ieee80211_hw *hw,
7067dd4f32aeSBjoern A. Zeeb unsigned int changed_flags,
7068dd4f32aeSBjoern A. Zeeb unsigned int *total_flags,
7069dd4f32aeSBjoern A. Zeeb u64 multicast)
7070dd4f32aeSBjoern A. Zeeb {
7071dd4f32aeSBjoern A. Zeeb struct ath11k *ar = hw->priv;
7072dd4f32aeSBjoern A. Zeeb
7073dd4f32aeSBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
7074dd4f32aeSBjoern A. Zeeb
7075dd4f32aeSBjoern A. Zeeb *total_flags &= SUPPORTED_FILTERS;
7076dd4f32aeSBjoern A. Zeeb ar->filter_flags = *total_flags;
7077dd4f32aeSBjoern A. Zeeb
7078dd4f32aeSBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
7079dd4f32aeSBjoern A. Zeeb }
7080dd4f32aeSBjoern A. Zeeb
ath11k_mac_op_get_antenna(struct ieee80211_hw * hw,u32 * tx_ant,u32 * rx_ant)7081dd4f32aeSBjoern A. Zeeb static int ath11k_mac_op_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
7082dd4f32aeSBjoern A. Zeeb {
7083dd4f32aeSBjoern A. Zeeb struct ath11k *ar = hw->priv;
7084dd4f32aeSBjoern A. Zeeb
7085dd4f32aeSBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
7086dd4f32aeSBjoern A. Zeeb
7087dd4f32aeSBjoern A. Zeeb *tx_ant = ar->cfg_tx_chainmask;
7088dd4f32aeSBjoern A. Zeeb *rx_ant = ar->cfg_rx_chainmask;
7089dd4f32aeSBjoern A. Zeeb
7090dd4f32aeSBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
7091dd4f32aeSBjoern A. Zeeb
7092dd4f32aeSBjoern A. Zeeb return 0;
7093dd4f32aeSBjoern A. Zeeb }
7094dd4f32aeSBjoern A. Zeeb
ath11k_mac_op_set_antenna(struct ieee80211_hw * hw,u32 tx_ant,u32 rx_ant)7095dd4f32aeSBjoern A. Zeeb static int ath11k_mac_op_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
7096dd4f32aeSBjoern A. Zeeb {
7097dd4f32aeSBjoern A. Zeeb struct ath11k *ar = hw->priv;
7098dd4f32aeSBjoern A. Zeeb int ret;
7099dd4f32aeSBjoern A. Zeeb
7100dd4f32aeSBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
7101dd4f32aeSBjoern A. Zeeb ret = __ath11k_set_antenna(ar, tx_ant, rx_ant);
7102dd4f32aeSBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
7103dd4f32aeSBjoern A. Zeeb
7104dd4f32aeSBjoern A. Zeeb return ret;
7105dd4f32aeSBjoern A. Zeeb }
7106dd4f32aeSBjoern A. Zeeb
ath11k_mac_op_ampdu_action(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_ampdu_params * params)7107dd4f32aeSBjoern A. Zeeb static int ath11k_mac_op_ampdu_action(struct ieee80211_hw *hw,
7108dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif,
7109dd4f32aeSBjoern A. Zeeb struct ieee80211_ampdu_params *params)
7110dd4f32aeSBjoern A. Zeeb {
7111dd4f32aeSBjoern A. Zeeb struct ath11k *ar = hw->priv;
7112dd4f32aeSBjoern A. Zeeb int ret = -EINVAL;
7113dd4f32aeSBjoern A. Zeeb
7114dd4f32aeSBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
7115dd4f32aeSBjoern A. Zeeb
7116dd4f32aeSBjoern A. Zeeb switch (params->action) {
7117dd4f32aeSBjoern A. Zeeb case IEEE80211_AMPDU_RX_START:
7118dd4f32aeSBjoern A. Zeeb ret = ath11k_dp_rx_ampdu_start(ar, params);
7119dd4f32aeSBjoern A. Zeeb break;
7120dd4f32aeSBjoern A. Zeeb case IEEE80211_AMPDU_RX_STOP:
7121dd4f32aeSBjoern A. Zeeb ret = ath11k_dp_rx_ampdu_stop(ar, params);
7122dd4f32aeSBjoern A. Zeeb break;
7123dd4f32aeSBjoern A. Zeeb case IEEE80211_AMPDU_TX_START:
7124dd4f32aeSBjoern A. Zeeb case IEEE80211_AMPDU_TX_STOP_CONT:
7125dd4f32aeSBjoern A. Zeeb case IEEE80211_AMPDU_TX_STOP_FLUSH:
7126dd4f32aeSBjoern A. Zeeb case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
7127dd4f32aeSBjoern A. Zeeb case IEEE80211_AMPDU_TX_OPERATIONAL:
7128dd4f32aeSBjoern A. Zeeb /* Tx A-MPDU aggregation offloaded to hw/fw so deny mac80211
7129dd4f32aeSBjoern A. Zeeb * Tx aggregation requests.
7130dd4f32aeSBjoern A. Zeeb */
7131dd4f32aeSBjoern A. Zeeb ret = -EOPNOTSUPP;
7132dd4f32aeSBjoern A. Zeeb break;
7133dd4f32aeSBjoern A. Zeeb }
7134dd4f32aeSBjoern A. Zeeb
7135dd4f32aeSBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
7136dd4f32aeSBjoern A. Zeeb
7137dd4f32aeSBjoern A. Zeeb return ret;
7138dd4f32aeSBjoern A. Zeeb }
7139dd4f32aeSBjoern A. Zeeb
ath11k_mac_op_add_chanctx(struct ieee80211_hw * hw,struct ieee80211_chanctx_conf * ctx)7140dd4f32aeSBjoern A. Zeeb static int ath11k_mac_op_add_chanctx(struct ieee80211_hw *hw,
7141dd4f32aeSBjoern A. Zeeb struct ieee80211_chanctx_conf *ctx)
7142dd4f32aeSBjoern A. Zeeb {
7143dd4f32aeSBjoern A. Zeeb struct ath11k *ar = hw->priv;
7144dd4f32aeSBjoern A. Zeeb struct ath11k_base *ab = ar->ab;
7145dd4f32aeSBjoern A. Zeeb
7146dd4f32aeSBjoern A. Zeeb ath11k_dbg(ab, ATH11K_DBG_MAC,
714728348caeSBjoern A. Zeeb "chanctx add freq %u width %d ptr %p\n",
7148dd4f32aeSBjoern A. Zeeb ctx->def.chan->center_freq, ctx->def.width, ctx);
7149dd4f32aeSBjoern A. Zeeb
7150dd4f32aeSBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
7151dd4f32aeSBjoern A. Zeeb
7152dd4f32aeSBjoern A. Zeeb spin_lock_bh(&ar->data_lock);
7153dd4f32aeSBjoern A. Zeeb /* TODO: In case of multiple channel context, populate rx_channel from
7154dd4f32aeSBjoern A. Zeeb * Rx PPDU desc information.
7155dd4f32aeSBjoern A. Zeeb */
7156dd4f32aeSBjoern A. Zeeb ar->rx_channel = ctx->def.chan;
7157dd4f32aeSBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
7158dd4f32aeSBjoern A. Zeeb
7159dd4f32aeSBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
7160dd4f32aeSBjoern A. Zeeb
7161dd4f32aeSBjoern A. Zeeb return 0;
7162dd4f32aeSBjoern A. Zeeb }
7163dd4f32aeSBjoern A. Zeeb
ath11k_mac_op_remove_chanctx(struct ieee80211_hw * hw,struct ieee80211_chanctx_conf * ctx)7164dd4f32aeSBjoern A. Zeeb static void ath11k_mac_op_remove_chanctx(struct ieee80211_hw *hw,
7165dd4f32aeSBjoern A. Zeeb struct ieee80211_chanctx_conf *ctx)
7166dd4f32aeSBjoern A. Zeeb {
7167dd4f32aeSBjoern A. Zeeb struct ath11k *ar = hw->priv;
7168dd4f32aeSBjoern A. Zeeb struct ath11k_base *ab = ar->ab;
7169dd4f32aeSBjoern A. Zeeb
7170dd4f32aeSBjoern A. Zeeb ath11k_dbg(ab, ATH11K_DBG_MAC,
717128348caeSBjoern A. Zeeb "chanctx remove freq %u width %d ptr %p\n",
7172dd4f32aeSBjoern A. Zeeb ctx->def.chan->center_freq, ctx->def.width, ctx);
7173dd4f32aeSBjoern A. Zeeb
7174dd4f32aeSBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
7175dd4f32aeSBjoern A. Zeeb
7176dd4f32aeSBjoern A. Zeeb spin_lock_bh(&ar->data_lock);
7177dd4f32aeSBjoern A. Zeeb /* TODO: In case of there is one more channel context left, populate
7178dd4f32aeSBjoern A. Zeeb * rx_channel with the channel of that remaining channel context.
7179dd4f32aeSBjoern A. Zeeb */
7180dd4f32aeSBjoern A. Zeeb ar->rx_channel = NULL;
7181dd4f32aeSBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
7182dd4f32aeSBjoern A. Zeeb
7183dd4f32aeSBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
7184dd4f32aeSBjoern A. Zeeb }
7185dd4f32aeSBjoern A. Zeeb
7186dd4f32aeSBjoern A. Zeeb static int
ath11k_mac_vdev_start_restart(struct ath11k_vif * arvif,struct ieee80211_chanctx_conf * ctx,bool restart)7187dd4f32aeSBjoern A. Zeeb ath11k_mac_vdev_start_restart(struct ath11k_vif *arvif,
718828348caeSBjoern A. Zeeb struct ieee80211_chanctx_conf *ctx,
7189dd4f32aeSBjoern A. Zeeb bool restart)
7190dd4f32aeSBjoern A. Zeeb {
7191dd4f32aeSBjoern A. Zeeb struct ath11k *ar = arvif->ar;
7192dd4f32aeSBjoern A. Zeeb struct ath11k_base *ab = ar->ab;
7193dd4f32aeSBjoern A. Zeeb struct wmi_vdev_start_req_arg arg = {};
719428348caeSBjoern A. Zeeb const struct cfg80211_chan_def *chandef = &ctx->def;
7195dd4f32aeSBjoern A. Zeeb int ret = 0;
7196dd4f32aeSBjoern A. Zeeb
7197dd4f32aeSBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
7198dd4f32aeSBjoern A. Zeeb
7199dd4f32aeSBjoern A. Zeeb reinit_completion(&ar->vdev_setup_done);
7200dd4f32aeSBjoern A. Zeeb
7201dd4f32aeSBjoern A. Zeeb arg.vdev_id = arvif->vdev_id;
7202dd4f32aeSBjoern A. Zeeb arg.dtim_period = arvif->dtim_period;
7203dd4f32aeSBjoern A. Zeeb arg.bcn_intval = arvif->beacon_interval;
7204dd4f32aeSBjoern A. Zeeb
7205dd4f32aeSBjoern A. Zeeb arg.channel.freq = chandef->chan->center_freq;
7206dd4f32aeSBjoern A. Zeeb arg.channel.band_center_freq1 = chandef->center_freq1;
7207dd4f32aeSBjoern A. Zeeb arg.channel.band_center_freq2 = chandef->center_freq2;
7208dd4f32aeSBjoern A. Zeeb arg.channel.mode =
7209dd4f32aeSBjoern A. Zeeb ath11k_phymodes[chandef->chan->band][chandef->width];
7210dd4f32aeSBjoern A. Zeeb
7211dd4f32aeSBjoern A. Zeeb arg.channel.min_power = 0;
7212dd4f32aeSBjoern A. Zeeb arg.channel.max_power = chandef->chan->max_power;
7213dd4f32aeSBjoern A. Zeeb arg.channel.max_reg_power = chandef->chan->max_reg_power;
7214dd4f32aeSBjoern A. Zeeb arg.channel.max_antenna_gain = chandef->chan->max_antenna_gain;
7215dd4f32aeSBjoern A. Zeeb
7216dd4f32aeSBjoern A. Zeeb arg.pref_tx_streams = ar->num_tx_chains;
7217dd4f32aeSBjoern A. Zeeb arg.pref_rx_streams = ar->num_rx_chains;
7218dd4f32aeSBjoern A. Zeeb
721928348caeSBjoern A. Zeeb arg.mbssid_flags = 0;
722028348caeSBjoern A. Zeeb arg.mbssid_tx_vdev_id = 0;
722128348caeSBjoern A. Zeeb if (test_bit(WMI_TLV_SERVICE_MBSS_PARAM_IN_VDEV_START_SUPPORT,
722228348caeSBjoern A. Zeeb ar->ab->wmi_ab.svc_map)) {
722328348caeSBjoern A. Zeeb ret = ath11k_mac_setup_vdev_params_mbssid(arvif,
722428348caeSBjoern A. Zeeb &arg.mbssid_flags,
722528348caeSBjoern A. Zeeb &arg.mbssid_tx_vdev_id);
722628348caeSBjoern A. Zeeb if (ret)
722728348caeSBjoern A. Zeeb return ret;
722828348caeSBjoern A. Zeeb }
722928348caeSBjoern A. Zeeb
7230dd4f32aeSBjoern A. Zeeb if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
7231dd4f32aeSBjoern A. Zeeb arg.ssid = arvif->u.ap.ssid;
7232dd4f32aeSBjoern A. Zeeb arg.ssid_len = arvif->u.ap.ssid_len;
7233dd4f32aeSBjoern A. Zeeb arg.hidden_ssid = arvif->u.ap.hidden_ssid;
7234dd4f32aeSBjoern A. Zeeb
7235dd4f32aeSBjoern A. Zeeb /* For now allow DFS for AP mode */
7236dd4f32aeSBjoern A. Zeeb arg.channel.chan_radar =
7237dd4f32aeSBjoern A. Zeeb !!(chandef->chan->flags & IEEE80211_CHAN_RADAR);
7238dd4f32aeSBjoern A. Zeeb
723928348caeSBjoern A. Zeeb arg.channel.freq2_radar = ctx->radar_enabled;
7240dd4f32aeSBjoern A. Zeeb
7241dd4f32aeSBjoern A. Zeeb arg.channel.passive = arg.channel.chan_radar;
7242dd4f32aeSBjoern A. Zeeb
7243dd4f32aeSBjoern A. Zeeb spin_lock_bh(&ab->base_lock);
7244dd4f32aeSBjoern A. Zeeb arg.regdomain = ar->ab->dfs_region;
7245dd4f32aeSBjoern A. Zeeb spin_unlock_bh(&ab->base_lock);
7246dd4f32aeSBjoern A. Zeeb }
7247dd4f32aeSBjoern A. Zeeb
7248dd4f32aeSBjoern A. Zeeb arg.channel.passive |= !!(chandef->chan->flags & IEEE80211_CHAN_NO_IR);
7249dd4f32aeSBjoern A. Zeeb
7250dd4f32aeSBjoern A. Zeeb ath11k_dbg(ab, ATH11K_DBG_MAC,
725128348caeSBjoern A. Zeeb "vdev %d start center_freq %d phymode %s\n",
7252dd4f32aeSBjoern A. Zeeb arg.vdev_id, arg.channel.freq,
7253dd4f32aeSBjoern A. Zeeb ath11k_wmi_phymode_str(arg.channel.mode));
7254dd4f32aeSBjoern A. Zeeb
7255dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_vdev_start(ar, &arg, restart);
7256dd4f32aeSBjoern A. Zeeb if (ret) {
7257dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to %s WMI vdev %i\n",
7258dd4f32aeSBjoern A. Zeeb restart ? "restart" : "start", arg.vdev_id);
7259dd4f32aeSBjoern A. Zeeb return ret;
7260dd4f32aeSBjoern A. Zeeb }
7261dd4f32aeSBjoern A. Zeeb
7262dd4f32aeSBjoern A. Zeeb ret = ath11k_mac_vdev_setup_sync(ar);
7263dd4f32aeSBjoern A. Zeeb if (ret) {
7264dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, "failed to synchronize setup for vdev %i %s: %d\n",
7265dd4f32aeSBjoern A. Zeeb arg.vdev_id, restart ? "restart" : "start", ret);
7266dd4f32aeSBjoern A. Zeeb return ret;
7267dd4f32aeSBjoern A. Zeeb }
7268dd4f32aeSBjoern A. Zeeb
7269dd4f32aeSBjoern A. Zeeb if (!restart)
7270dd4f32aeSBjoern A. Zeeb ar->num_started_vdevs++;
7271dd4f32aeSBjoern A. Zeeb
7272dd4f32aeSBjoern A. Zeeb ath11k_dbg(ab, ATH11K_DBG_MAC, "vdev %pM started, vdev_id %d\n",
7273dd4f32aeSBjoern A. Zeeb arvif->vif->addr, arvif->vdev_id);
7274dd4f32aeSBjoern A. Zeeb
7275dd4f32aeSBjoern A. Zeeb /* Enable CAC Flag in the driver by checking the channel DFS cac time,
7276dd4f32aeSBjoern A. Zeeb * i.e dfs_cac_ms value which will be valid only for radar channels
7277dd4f32aeSBjoern A. Zeeb * and state as NL80211_DFS_USABLE which indicates CAC needs to be
7278dd4f32aeSBjoern A. Zeeb * done before channel usage. This flags is used to drop rx packets.
7279dd4f32aeSBjoern A. Zeeb * during CAC.
7280dd4f32aeSBjoern A. Zeeb */
7281dd4f32aeSBjoern A. Zeeb /* TODO Set the flag for other interface types as required */
7282dd4f32aeSBjoern A. Zeeb if (arvif->vdev_type == WMI_VDEV_TYPE_AP &&
7283dd4f32aeSBjoern A. Zeeb chandef->chan->dfs_cac_ms &&
7284dd4f32aeSBjoern A. Zeeb chandef->chan->dfs_state == NL80211_DFS_USABLE) {
7285dd4f32aeSBjoern A. Zeeb set_bit(ATH11K_CAC_RUNNING, &ar->dev_flags);
7286dd4f32aeSBjoern A. Zeeb ath11k_dbg(ab, ATH11K_DBG_MAC,
7287dd4f32aeSBjoern A. Zeeb "CAC Started in chan_freq %d for vdev %d\n",
7288dd4f32aeSBjoern A. Zeeb arg.channel.freq, arg.vdev_id);
7289dd4f32aeSBjoern A. Zeeb }
7290dd4f32aeSBjoern A. Zeeb
7291dd4f32aeSBjoern A. Zeeb ret = ath11k_mac_set_txbf_conf(arvif);
7292dd4f32aeSBjoern A. Zeeb if (ret)
7293dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, "failed to set txbf conf for vdev %d: %d\n",
7294dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ret);
7295dd4f32aeSBjoern A. Zeeb
7296dd4f32aeSBjoern A. Zeeb return 0;
7297dd4f32aeSBjoern A. Zeeb }
7298dd4f32aeSBjoern A. Zeeb
ath11k_mac_vdev_stop(struct ath11k_vif * arvif)7299dd4f32aeSBjoern A. Zeeb static int ath11k_mac_vdev_stop(struct ath11k_vif *arvif)
7300dd4f32aeSBjoern A. Zeeb {
7301dd4f32aeSBjoern A. Zeeb struct ath11k *ar = arvif->ar;
7302dd4f32aeSBjoern A. Zeeb int ret;
7303dd4f32aeSBjoern A. Zeeb
7304dd4f32aeSBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
7305dd4f32aeSBjoern A. Zeeb
7306dd4f32aeSBjoern A. Zeeb reinit_completion(&ar->vdev_setup_done);
7307dd4f32aeSBjoern A. Zeeb
7308dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_vdev_stop(ar, arvif->vdev_id);
7309dd4f32aeSBjoern A. Zeeb if (ret) {
7310dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to stop WMI vdev %i: %d\n",
7311dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ret);
7312dd4f32aeSBjoern A. Zeeb goto err;
7313dd4f32aeSBjoern A. Zeeb }
7314dd4f32aeSBjoern A. Zeeb
7315dd4f32aeSBjoern A. Zeeb ret = ath11k_mac_vdev_setup_sync(ar);
7316dd4f32aeSBjoern A. Zeeb if (ret) {
7317dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to synchronize setup for vdev %i: %d\n",
7318dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ret);
7319dd4f32aeSBjoern A. Zeeb goto err;
7320dd4f32aeSBjoern A. Zeeb }
7321dd4f32aeSBjoern A. Zeeb
7322dd4f32aeSBjoern A. Zeeb WARN_ON(ar->num_started_vdevs == 0);
7323dd4f32aeSBjoern A. Zeeb
7324dd4f32aeSBjoern A. Zeeb ar->num_started_vdevs--;
7325dd4f32aeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev %pM stopped, vdev_id %d\n",
7326dd4f32aeSBjoern A. Zeeb arvif->vif->addr, arvif->vdev_id);
7327dd4f32aeSBjoern A. Zeeb
7328dd4f32aeSBjoern A. Zeeb if (test_bit(ATH11K_CAC_RUNNING, &ar->dev_flags)) {
7329dd4f32aeSBjoern A. Zeeb clear_bit(ATH11K_CAC_RUNNING, &ar->dev_flags);
7330dd4f32aeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "CAC Stopped for vdev %d\n",
7331dd4f32aeSBjoern A. Zeeb arvif->vdev_id);
7332dd4f32aeSBjoern A. Zeeb }
7333dd4f32aeSBjoern A. Zeeb
7334dd4f32aeSBjoern A. Zeeb return 0;
7335dd4f32aeSBjoern A. Zeeb err:
7336dd4f32aeSBjoern A. Zeeb return ret;
7337dd4f32aeSBjoern A. Zeeb }
7338dd4f32aeSBjoern A. Zeeb
ath11k_mac_vdev_start(struct ath11k_vif * arvif,struct ieee80211_chanctx_conf * ctx)7339dd4f32aeSBjoern A. Zeeb static int ath11k_mac_vdev_start(struct ath11k_vif *arvif,
734028348caeSBjoern A. Zeeb struct ieee80211_chanctx_conf *ctx)
7341dd4f32aeSBjoern A. Zeeb {
734228348caeSBjoern A. Zeeb return ath11k_mac_vdev_start_restart(arvif, ctx, false);
7343dd4f32aeSBjoern A. Zeeb }
7344dd4f32aeSBjoern A. Zeeb
ath11k_mac_vdev_restart(struct ath11k_vif * arvif,struct ieee80211_chanctx_conf * ctx)7345dd4f32aeSBjoern A. Zeeb static int ath11k_mac_vdev_restart(struct ath11k_vif *arvif,
734628348caeSBjoern A. Zeeb struct ieee80211_chanctx_conf *ctx)
7347dd4f32aeSBjoern A. Zeeb {
734828348caeSBjoern A. Zeeb return ath11k_mac_vdev_start_restart(arvif, ctx, true);
7349dd4f32aeSBjoern A. Zeeb }
7350dd4f32aeSBjoern A. Zeeb
7351dd4f32aeSBjoern A. Zeeb struct ath11k_mac_change_chanctx_arg {
7352dd4f32aeSBjoern A. Zeeb struct ieee80211_chanctx_conf *ctx;
7353dd4f32aeSBjoern A. Zeeb struct ieee80211_vif_chanctx_switch *vifs;
7354dd4f32aeSBjoern A. Zeeb int n_vifs;
7355dd4f32aeSBjoern A. Zeeb int next_vif;
7356dd4f32aeSBjoern A. Zeeb };
7357dd4f32aeSBjoern A. Zeeb
7358dd4f32aeSBjoern A. Zeeb static void
ath11k_mac_change_chanctx_cnt_iter(void * data,u8 * mac,struct ieee80211_vif * vif)7359dd4f32aeSBjoern A. Zeeb ath11k_mac_change_chanctx_cnt_iter(void *data, u8 *mac,
7360dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif)
7361dd4f32aeSBjoern A. Zeeb {
7362dd4f32aeSBjoern A. Zeeb struct ath11k_mac_change_chanctx_arg *arg = data;
7363dd4f32aeSBjoern A. Zeeb
736428348caeSBjoern A. Zeeb if (rcu_access_pointer(vif->bss_conf.chanctx_conf) != arg->ctx)
7365dd4f32aeSBjoern A. Zeeb return;
7366dd4f32aeSBjoern A. Zeeb
7367dd4f32aeSBjoern A. Zeeb arg->n_vifs++;
7368dd4f32aeSBjoern A. Zeeb }
7369dd4f32aeSBjoern A. Zeeb
7370dd4f32aeSBjoern A. Zeeb static void
ath11k_mac_change_chanctx_fill_iter(void * data,u8 * mac,struct ieee80211_vif * vif)7371dd4f32aeSBjoern A. Zeeb ath11k_mac_change_chanctx_fill_iter(void *data, u8 *mac,
7372dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif)
7373dd4f32aeSBjoern A. Zeeb {
7374dd4f32aeSBjoern A. Zeeb struct ath11k_mac_change_chanctx_arg *arg = data;
7375dd4f32aeSBjoern A. Zeeb struct ieee80211_chanctx_conf *ctx;
7376dd4f32aeSBjoern A. Zeeb
737728348caeSBjoern A. Zeeb ctx = rcu_access_pointer(vif->bss_conf.chanctx_conf);
7378dd4f32aeSBjoern A. Zeeb if (ctx != arg->ctx)
7379dd4f32aeSBjoern A. Zeeb return;
7380dd4f32aeSBjoern A. Zeeb
7381dd4f32aeSBjoern A. Zeeb if (WARN_ON(arg->next_vif == arg->n_vifs))
7382dd4f32aeSBjoern A. Zeeb return;
7383dd4f32aeSBjoern A. Zeeb
7384dd4f32aeSBjoern A. Zeeb arg->vifs[arg->next_vif].vif = vif;
7385dd4f32aeSBjoern A. Zeeb arg->vifs[arg->next_vif].old_ctx = ctx;
7386dd4f32aeSBjoern A. Zeeb arg->vifs[arg->next_vif].new_ctx = ctx;
7387dd4f32aeSBjoern A. Zeeb arg->next_vif++;
7388dd4f32aeSBjoern A. Zeeb }
7389dd4f32aeSBjoern A. Zeeb
7390dd4f32aeSBjoern A. Zeeb static void
ath11k_mac_update_vif_chan(struct ath11k * ar,struct ieee80211_vif_chanctx_switch * vifs,int n_vifs)7391dd4f32aeSBjoern A. Zeeb ath11k_mac_update_vif_chan(struct ath11k *ar,
7392dd4f32aeSBjoern A. Zeeb struct ieee80211_vif_chanctx_switch *vifs,
7393dd4f32aeSBjoern A. Zeeb int n_vifs)
7394dd4f32aeSBjoern A. Zeeb {
7395dd4f32aeSBjoern A. Zeeb struct ath11k_base *ab = ar->ab;
739628348caeSBjoern A. Zeeb struct ath11k_vif *arvif, *tx_arvif = NULL;
739728348caeSBjoern A. Zeeb struct ieee80211_vif *mbssid_tx_vif;
7398dd4f32aeSBjoern A. Zeeb int ret;
7399dd4f32aeSBjoern A. Zeeb int i;
7400dd4f32aeSBjoern A. Zeeb bool monitor_vif = false;
7401dd4f32aeSBjoern A. Zeeb
7402dd4f32aeSBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
7403dd4f32aeSBjoern A. Zeeb
7404dd4f32aeSBjoern A. Zeeb /* Associated channel resources of all relevant vdevs
7405dd4f32aeSBjoern A. Zeeb * should be available for the channel switch now.
7406dd4f32aeSBjoern A. Zeeb */
7407dd4f32aeSBjoern A. Zeeb
7408dd4f32aeSBjoern A. Zeeb /* TODO: Update ar->rx_channel */
7409dd4f32aeSBjoern A. Zeeb
7410dd4f32aeSBjoern A. Zeeb for (i = 0; i < n_vifs; i++) {
7411dd4f32aeSBjoern A. Zeeb arvif = (void *)vifs[i].vif->drv_priv;
7412dd4f32aeSBjoern A. Zeeb
7413dd4f32aeSBjoern A. Zeeb if (WARN_ON(!arvif->is_started))
7414dd4f32aeSBjoern A. Zeeb continue;
7415dd4f32aeSBjoern A. Zeeb
741628348caeSBjoern A. Zeeb /* change_chanctx can be called even before vdev_up from
741728348caeSBjoern A. Zeeb * ieee80211_start_ap->ieee80211_vif_use_channel->
741828348caeSBjoern A. Zeeb * ieee80211_recalc_radar_chanctx.
741928348caeSBjoern A. Zeeb *
742028348caeSBjoern A. Zeeb * Firmware expect vdev_restart only if vdev is up.
742128348caeSBjoern A. Zeeb * If vdev is down then it expect vdev_stop->vdev_start.
742228348caeSBjoern A. Zeeb */
742328348caeSBjoern A. Zeeb if (arvif->is_up) {
742428348caeSBjoern A. Zeeb ret = ath11k_mac_vdev_restart(arvif, vifs[i].new_ctx);
7425dd4f32aeSBjoern A. Zeeb if (ret) {
7426dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, "failed to restart vdev %d: %d\n",
7427dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ret);
7428dd4f32aeSBjoern A. Zeeb continue;
7429dd4f32aeSBjoern A. Zeeb }
743028348caeSBjoern A. Zeeb } else {
743128348caeSBjoern A. Zeeb ret = ath11k_mac_vdev_stop(arvif);
743228348caeSBjoern A. Zeeb if (ret) {
743328348caeSBjoern A. Zeeb ath11k_warn(ab, "failed to stop vdev %d: %d\n",
743428348caeSBjoern A. Zeeb arvif->vdev_id, ret);
743528348caeSBjoern A. Zeeb continue;
743628348caeSBjoern A. Zeeb }
743728348caeSBjoern A. Zeeb
743828348caeSBjoern A. Zeeb ret = ath11k_mac_vdev_start(arvif, vifs[i].new_ctx);
743928348caeSBjoern A. Zeeb if (ret)
744028348caeSBjoern A. Zeeb ath11k_warn(ab, "failed to start vdev %d: %d\n",
744128348caeSBjoern A. Zeeb arvif->vdev_id, ret);
744228348caeSBjoern A. Zeeb
744328348caeSBjoern A. Zeeb continue;
744428348caeSBjoern A. Zeeb }
7445dd4f32aeSBjoern A. Zeeb
7446dd4f32aeSBjoern A. Zeeb ret = ath11k_mac_setup_bcn_tmpl(arvif);
7447dd4f32aeSBjoern A. Zeeb if (ret)
7448dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, "failed to update bcn tmpl during csa: %d\n",
7449dd4f32aeSBjoern A. Zeeb ret);
7450dd4f32aeSBjoern A. Zeeb
745128348caeSBjoern A. Zeeb mbssid_tx_vif = arvif->vif->mbssid_tx_vif;
745228348caeSBjoern A. Zeeb if (mbssid_tx_vif)
745328348caeSBjoern A. Zeeb tx_arvif = (struct ath11k_vif *)mbssid_tx_vif->drv_priv;
745428348caeSBjoern A. Zeeb
7455dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid,
745628348caeSBjoern A. Zeeb arvif->bssid,
745728348caeSBjoern A. Zeeb tx_arvif ? tx_arvif->bssid : NULL,
745828348caeSBjoern A. Zeeb arvif->vif->bss_conf.bssid_index,
745928348caeSBjoern A. Zeeb 1 << arvif->vif->bss_conf.bssid_indicator);
7460dd4f32aeSBjoern A. Zeeb if (ret) {
7461dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, "failed to bring vdev up %d: %d\n",
7462dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ret);
7463dd4f32aeSBjoern A. Zeeb continue;
7464dd4f32aeSBjoern A. Zeeb }
7465dd4f32aeSBjoern A. Zeeb }
7466dd4f32aeSBjoern A. Zeeb
7467dd4f32aeSBjoern A. Zeeb /* Restart the internal monitor vdev on new channel */
7468dd4f32aeSBjoern A. Zeeb if (!monitor_vif &&
7469dd4f32aeSBjoern A. Zeeb test_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags)) {
7470dd4f32aeSBjoern A. Zeeb ret = ath11k_mac_monitor_stop(ar);
7471dd4f32aeSBjoern A. Zeeb if (ret) {
7472dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to stop monitor during vif channel update: %d",
7473dd4f32aeSBjoern A. Zeeb ret);
7474dd4f32aeSBjoern A. Zeeb return;
7475dd4f32aeSBjoern A. Zeeb }
7476dd4f32aeSBjoern A. Zeeb
7477dd4f32aeSBjoern A. Zeeb ret = ath11k_mac_monitor_start(ar);
7478dd4f32aeSBjoern A. Zeeb if (ret) {
7479dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to start monitor during vif channel update: %d",
7480dd4f32aeSBjoern A. Zeeb ret);
7481dd4f32aeSBjoern A. Zeeb return;
7482dd4f32aeSBjoern A. Zeeb }
7483dd4f32aeSBjoern A. Zeeb }
7484dd4f32aeSBjoern A. Zeeb }
7485dd4f32aeSBjoern A. Zeeb
7486dd4f32aeSBjoern A. Zeeb static void
ath11k_mac_update_active_vif_chan(struct ath11k * ar,struct ieee80211_chanctx_conf * ctx)7487dd4f32aeSBjoern A. Zeeb ath11k_mac_update_active_vif_chan(struct ath11k *ar,
7488dd4f32aeSBjoern A. Zeeb struct ieee80211_chanctx_conf *ctx)
7489dd4f32aeSBjoern A. Zeeb {
7490dd4f32aeSBjoern A. Zeeb struct ath11k_mac_change_chanctx_arg arg = { .ctx = ctx };
7491dd4f32aeSBjoern A. Zeeb
7492dd4f32aeSBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
7493dd4f32aeSBjoern A. Zeeb
7494dd4f32aeSBjoern A. Zeeb ieee80211_iterate_active_interfaces_atomic(ar->hw,
7495dd4f32aeSBjoern A. Zeeb IEEE80211_IFACE_ITER_NORMAL,
7496dd4f32aeSBjoern A. Zeeb ath11k_mac_change_chanctx_cnt_iter,
7497dd4f32aeSBjoern A. Zeeb &arg);
7498dd4f32aeSBjoern A. Zeeb if (arg.n_vifs == 0)
7499dd4f32aeSBjoern A. Zeeb return;
7500dd4f32aeSBjoern A. Zeeb
7501dd4f32aeSBjoern A. Zeeb arg.vifs = kcalloc(arg.n_vifs, sizeof(arg.vifs[0]), GFP_KERNEL);
7502dd4f32aeSBjoern A. Zeeb if (!arg.vifs)
7503dd4f32aeSBjoern A. Zeeb return;
7504dd4f32aeSBjoern A. Zeeb
7505dd4f32aeSBjoern A. Zeeb ieee80211_iterate_active_interfaces_atomic(ar->hw,
7506dd4f32aeSBjoern A. Zeeb IEEE80211_IFACE_ITER_NORMAL,
7507dd4f32aeSBjoern A. Zeeb ath11k_mac_change_chanctx_fill_iter,
7508dd4f32aeSBjoern A. Zeeb &arg);
7509dd4f32aeSBjoern A. Zeeb
7510dd4f32aeSBjoern A. Zeeb ath11k_mac_update_vif_chan(ar, arg.vifs, arg.n_vifs);
7511dd4f32aeSBjoern A. Zeeb
7512dd4f32aeSBjoern A. Zeeb kfree(arg.vifs);
7513dd4f32aeSBjoern A. Zeeb }
7514dd4f32aeSBjoern A. Zeeb
ath11k_mac_op_change_chanctx(struct ieee80211_hw * hw,struct ieee80211_chanctx_conf * ctx,u32 changed)7515dd4f32aeSBjoern A. Zeeb static void ath11k_mac_op_change_chanctx(struct ieee80211_hw *hw,
7516dd4f32aeSBjoern A. Zeeb struct ieee80211_chanctx_conf *ctx,
7517dd4f32aeSBjoern A. Zeeb u32 changed)
7518dd4f32aeSBjoern A. Zeeb {
7519dd4f32aeSBjoern A. Zeeb struct ath11k *ar = hw->priv;
7520dd4f32aeSBjoern A. Zeeb struct ath11k_base *ab = ar->ab;
7521dd4f32aeSBjoern A. Zeeb
7522dd4f32aeSBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
7523dd4f32aeSBjoern A. Zeeb
7524dd4f32aeSBjoern A. Zeeb ath11k_dbg(ab, ATH11K_DBG_MAC,
752528348caeSBjoern A. Zeeb "chanctx change freq %u width %d ptr %p changed %x\n",
7526dd4f32aeSBjoern A. Zeeb ctx->def.chan->center_freq, ctx->def.width, ctx, changed);
7527dd4f32aeSBjoern A. Zeeb
7528dd4f32aeSBjoern A. Zeeb /* This shouldn't really happen because channel switching should use
7529dd4f32aeSBjoern A. Zeeb * switch_vif_chanctx().
7530dd4f32aeSBjoern A. Zeeb */
7531dd4f32aeSBjoern A. Zeeb if (WARN_ON(changed & IEEE80211_CHANCTX_CHANGE_CHANNEL))
7532dd4f32aeSBjoern A. Zeeb goto unlock;
7533dd4f32aeSBjoern A. Zeeb
753428348caeSBjoern A. Zeeb if (changed & IEEE80211_CHANCTX_CHANGE_WIDTH ||
753528348caeSBjoern A. Zeeb changed & IEEE80211_CHANCTX_CHANGE_RADAR)
7536dd4f32aeSBjoern A. Zeeb ath11k_mac_update_active_vif_chan(ar, ctx);
7537dd4f32aeSBjoern A. Zeeb
7538dd4f32aeSBjoern A. Zeeb /* TODO: Recalc radar detection */
7539dd4f32aeSBjoern A. Zeeb
7540dd4f32aeSBjoern A. Zeeb unlock:
7541dd4f32aeSBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
7542dd4f32aeSBjoern A. Zeeb }
7543dd4f32aeSBjoern A. Zeeb
ath11k_start_vdev_delay(struct ieee80211_hw * hw,struct ieee80211_vif * vif)7544dd4f32aeSBjoern A. Zeeb static int ath11k_start_vdev_delay(struct ieee80211_hw *hw,
7545dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif)
7546dd4f32aeSBjoern A. Zeeb {
7547dd4f32aeSBjoern A. Zeeb struct ath11k *ar = hw->priv;
7548dd4f32aeSBjoern A. Zeeb struct ath11k_base *ab = ar->ab;
7549dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif = (void *)vif->drv_priv;
7550dd4f32aeSBjoern A. Zeeb int ret;
7551dd4f32aeSBjoern A. Zeeb
7552dd4f32aeSBjoern A. Zeeb if (WARN_ON(arvif->is_started))
7553dd4f32aeSBjoern A. Zeeb return -EBUSY;
7554dd4f32aeSBjoern A. Zeeb
755528348caeSBjoern A. Zeeb ret = ath11k_mac_vdev_start(arvif, &arvif->chanctx);
7556dd4f32aeSBjoern A. Zeeb if (ret) {
7557dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, "failed to start vdev %i addr %pM on freq %d: %d\n",
7558dd4f32aeSBjoern A. Zeeb arvif->vdev_id, vif->addr,
7559dd4f32aeSBjoern A. Zeeb arvif->chanctx.def.chan->center_freq, ret);
7560dd4f32aeSBjoern A. Zeeb return ret;
7561dd4f32aeSBjoern A. Zeeb }
7562dd4f32aeSBjoern A. Zeeb
7563dd4f32aeSBjoern A. Zeeb /* Reconfigure hardware rate code since it is cleared by firmware.
7564dd4f32aeSBjoern A. Zeeb */
7565dd4f32aeSBjoern A. Zeeb if (ar->hw_rate_code > 0) {
7566dd4f32aeSBjoern A. Zeeb u32 vdev_param = WMI_VDEV_PARAM_MGMT_RATE;
7567dd4f32aeSBjoern A. Zeeb
7568dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, vdev_param,
7569dd4f32aeSBjoern A. Zeeb ar->hw_rate_code);
7570dd4f32aeSBjoern A. Zeeb if (ret) {
7571dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to set mgmt tx rate %d\n", ret);
7572dd4f32aeSBjoern A. Zeeb return ret;
7573dd4f32aeSBjoern A. Zeeb }
7574dd4f32aeSBjoern A. Zeeb }
7575dd4f32aeSBjoern A. Zeeb
7576dd4f32aeSBjoern A. Zeeb if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
757728348caeSBjoern A. Zeeb ret = ath11k_wmi_vdev_up(ar, arvif->vdev_id, 0, ar->mac_addr,
757828348caeSBjoern A. Zeeb NULL, 0, 0);
7579dd4f32aeSBjoern A. Zeeb if (ret) {
7580dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, "failed put monitor up: %d\n", ret);
7581dd4f32aeSBjoern A. Zeeb return ret;
7582dd4f32aeSBjoern A. Zeeb }
7583dd4f32aeSBjoern A. Zeeb }
7584dd4f32aeSBjoern A. Zeeb
7585dd4f32aeSBjoern A. Zeeb arvif->is_started = true;
7586dd4f32aeSBjoern A. Zeeb
7587dd4f32aeSBjoern A. Zeeb /* TODO: Setup ps and cts/rts protection */
7588dd4f32aeSBjoern A. Zeeb return 0;
7589dd4f32aeSBjoern A. Zeeb }
7590dd4f32aeSBjoern A. Zeeb
7591dd4f32aeSBjoern A. Zeeb static int
ath11k_mac_op_assign_vif_chanctx(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_bss_conf * link_conf,struct ieee80211_chanctx_conf * ctx)7592dd4f32aeSBjoern A. Zeeb ath11k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
7593dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif,
7594dd4f32aeSBjoern A. Zeeb struct ieee80211_bss_conf *link_conf,
7595dd4f32aeSBjoern A. Zeeb struct ieee80211_chanctx_conf *ctx)
7596dd4f32aeSBjoern A. Zeeb {
7597dd4f32aeSBjoern A. Zeeb struct ath11k *ar = hw->priv;
7598dd4f32aeSBjoern A. Zeeb struct ath11k_base *ab = ar->ab;
7599dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif = (void *)vif->drv_priv;
7600dd4f32aeSBjoern A. Zeeb int ret;
7601dd4f32aeSBjoern A. Zeeb struct peer_create_params param;
7602dd4f32aeSBjoern A. Zeeb
7603dd4f32aeSBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
7604dd4f32aeSBjoern A. Zeeb
7605dd4f32aeSBjoern A. Zeeb ath11k_dbg(ab, ATH11K_DBG_MAC,
760628348caeSBjoern A. Zeeb "chanctx assign ptr %p vdev_id %i\n",
7607dd4f32aeSBjoern A. Zeeb ctx, arvif->vdev_id);
7608dd4f32aeSBjoern A. Zeeb
7609dd4f32aeSBjoern A. Zeeb /* for QCA6390 bss peer must be created before vdev_start */
7610dd4f32aeSBjoern A. Zeeb if (ab->hw_params.vdev_start_delay &&
7611dd4f32aeSBjoern A. Zeeb arvif->vdev_type != WMI_VDEV_TYPE_AP &&
7612dd4f32aeSBjoern A. Zeeb arvif->vdev_type != WMI_VDEV_TYPE_MONITOR &&
7613dd4f32aeSBjoern A. Zeeb !ath11k_peer_find_by_vdev_id(ab, arvif->vdev_id)) {
7614dd4f32aeSBjoern A. Zeeb memcpy(&arvif->chanctx, ctx, sizeof(*ctx));
7615dd4f32aeSBjoern A. Zeeb ret = 0;
7616dd4f32aeSBjoern A. Zeeb goto out;
7617dd4f32aeSBjoern A. Zeeb }
7618dd4f32aeSBjoern A. Zeeb
7619dd4f32aeSBjoern A. Zeeb if (WARN_ON(arvif->is_started)) {
7620dd4f32aeSBjoern A. Zeeb ret = -EBUSY;
7621dd4f32aeSBjoern A. Zeeb goto out;
7622dd4f32aeSBjoern A. Zeeb }
7623dd4f32aeSBjoern A. Zeeb
7624dd4f32aeSBjoern A. Zeeb if (ab->hw_params.vdev_start_delay &&
7625dd4f32aeSBjoern A. Zeeb arvif->vdev_type != WMI_VDEV_TYPE_AP &&
7626dd4f32aeSBjoern A. Zeeb arvif->vdev_type != WMI_VDEV_TYPE_MONITOR) {
7627dd4f32aeSBjoern A. Zeeb param.vdev_id = arvif->vdev_id;
7628dd4f32aeSBjoern A. Zeeb param.peer_type = WMI_PEER_TYPE_DEFAULT;
7629dd4f32aeSBjoern A. Zeeb param.peer_addr = ar->mac_addr;
7630dd4f32aeSBjoern A. Zeeb
7631dd4f32aeSBjoern A. Zeeb ret = ath11k_peer_create(ar, arvif, NULL, ¶m);
7632dd4f32aeSBjoern A. Zeeb if (ret) {
7633dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, "failed to create peer after vdev start delay: %d",
7634dd4f32aeSBjoern A. Zeeb ret);
7635dd4f32aeSBjoern A. Zeeb goto out;
7636dd4f32aeSBjoern A. Zeeb }
7637dd4f32aeSBjoern A. Zeeb }
7638dd4f32aeSBjoern A. Zeeb
7639dd4f32aeSBjoern A. Zeeb if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
7640dd4f32aeSBjoern A. Zeeb ret = ath11k_mac_monitor_start(ar);
7641dd4f32aeSBjoern A. Zeeb if (ret) {
7642dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to start monitor during vif channel context assignment: %d",
7643dd4f32aeSBjoern A. Zeeb ret);
7644dd4f32aeSBjoern A. Zeeb goto out;
7645dd4f32aeSBjoern A. Zeeb }
7646dd4f32aeSBjoern A. Zeeb
7647dd4f32aeSBjoern A. Zeeb arvif->is_started = true;
7648dd4f32aeSBjoern A. Zeeb goto out;
7649dd4f32aeSBjoern A. Zeeb }
7650dd4f32aeSBjoern A. Zeeb
765128348caeSBjoern A. Zeeb ret = ath11k_mac_vdev_start(arvif, ctx);
7652dd4f32aeSBjoern A. Zeeb if (ret) {
7653dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, "failed to start vdev %i addr %pM on freq %d: %d\n",
7654dd4f32aeSBjoern A. Zeeb arvif->vdev_id, vif->addr,
7655dd4f32aeSBjoern A. Zeeb ctx->def.chan->center_freq, ret);
7656dd4f32aeSBjoern A. Zeeb goto out;
7657dd4f32aeSBjoern A. Zeeb }
7658dd4f32aeSBjoern A. Zeeb
7659dd4f32aeSBjoern A. Zeeb arvif->is_started = true;
7660dd4f32aeSBjoern A. Zeeb
7661dd4f32aeSBjoern A. Zeeb if (arvif->vdev_type != WMI_VDEV_TYPE_MONITOR &&
7662dd4f32aeSBjoern A. Zeeb test_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags)) {
7663dd4f32aeSBjoern A. Zeeb ret = ath11k_mac_monitor_start(ar);
7664dd4f32aeSBjoern A. Zeeb if (ret) {
7665dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to start monitor during vif channel context assignment: %d",
7666dd4f32aeSBjoern A. Zeeb ret);
7667dd4f32aeSBjoern A. Zeeb goto out;
7668dd4f32aeSBjoern A. Zeeb }
7669dd4f32aeSBjoern A. Zeeb }
7670dd4f32aeSBjoern A. Zeeb
7671dd4f32aeSBjoern A. Zeeb /* TODO: Setup ps and cts/rts protection */
7672dd4f32aeSBjoern A. Zeeb
7673dd4f32aeSBjoern A. Zeeb ret = 0;
7674dd4f32aeSBjoern A. Zeeb
7675dd4f32aeSBjoern A. Zeeb out:
7676dd4f32aeSBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
7677dd4f32aeSBjoern A. Zeeb
7678dd4f32aeSBjoern A. Zeeb return ret;
7679dd4f32aeSBjoern A. Zeeb }
7680dd4f32aeSBjoern A. Zeeb
7681dd4f32aeSBjoern A. Zeeb static void
ath11k_mac_op_unassign_vif_chanctx(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_bss_conf * link_conf,struct ieee80211_chanctx_conf * ctx)7682dd4f32aeSBjoern A. Zeeb ath11k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw,
7683dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif,
7684dd4f32aeSBjoern A. Zeeb struct ieee80211_bss_conf *link_conf,
7685dd4f32aeSBjoern A. Zeeb struct ieee80211_chanctx_conf *ctx)
7686dd4f32aeSBjoern A. Zeeb {
7687dd4f32aeSBjoern A. Zeeb struct ath11k *ar = hw->priv;
7688dd4f32aeSBjoern A. Zeeb struct ath11k_base *ab = ar->ab;
7689dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif = (void *)vif->drv_priv;
769028348caeSBjoern A. Zeeb struct ath11k_peer *peer;
7691dd4f32aeSBjoern A. Zeeb int ret;
7692dd4f32aeSBjoern A. Zeeb
7693dd4f32aeSBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
7694dd4f32aeSBjoern A. Zeeb
7695dd4f32aeSBjoern A. Zeeb ath11k_dbg(ab, ATH11K_DBG_MAC,
769628348caeSBjoern A. Zeeb "chanctx unassign ptr %p vdev_id %i\n",
7697dd4f32aeSBjoern A. Zeeb ctx, arvif->vdev_id);
7698dd4f32aeSBjoern A. Zeeb
7699dd4f32aeSBjoern A. Zeeb WARN_ON(!arvif->is_started);
7700dd4f32aeSBjoern A. Zeeb
7701dd4f32aeSBjoern A. Zeeb if (ab->hw_params.vdev_start_delay &&
770228348caeSBjoern A. Zeeb arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
770328348caeSBjoern A. Zeeb spin_lock_bh(&ab->base_lock);
770428348caeSBjoern A. Zeeb peer = ath11k_peer_find_by_addr(ab, ar->mac_addr);
770528348caeSBjoern A. Zeeb spin_unlock_bh(&ab->base_lock);
770628348caeSBjoern A. Zeeb if (peer)
7707dd4f32aeSBjoern A. Zeeb ath11k_peer_delete(ar, arvif->vdev_id, ar->mac_addr);
770828348caeSBjoern A. Zeeb }
7709dd4f32aeSBjoern A. Zeeb
7710dd4f32aeSBjoern A. Zeeb if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
7711dd4f32aeSBjoern A. Zeeb ret = ath11k_mac_monitor_stop(ar);
7712dd4f32aeSBjoern A. Zeeb if (ret) {
7713dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to stop monitor during vif channel context unassignment: %d",
7714dd4f32aeSBjoern A. Zeeb ret);
7715dd4f32aeSBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
7716dd4f32aeSBjoern A. Zeeb return;
7717dd4f32aeSBjoern A. Zeeb }
7718dd4f32aeSBjoern A. Zeeb
7719dd4f32aeSBjoern A. Zeeb arvif->is_started = false;
7720dd4f32aeSBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
7721dd4f32aeSBjoern A. Zeeb return;
7722dd4f32aeSBjoern A. Zeeb }
7723dd4f32aeSBjoern A. Zeeb
7724dd4f32aeSBjoern A. Zeeb ret = ath11k_mac_vdev_stop(arvif);
7725dd4f32aeSBjoern A. Zeeb if (ret)
7726dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, "failed to stop vdev %i: %d\n",
7727dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ret);
7728dd4f32aeSBjoern A. Zeeb
7729dd4f32aeSBjoern A. Zeeb arvif->is_started = false;
7730dd4f32aeSBjoern A. Zeeb
7731dd4f32aeSBjoern A. Zeeb if (ab->hw_params.vdev_start_delay &&
7732dd4f32aeSBjoern A. Zeeb arvif->vdev_type == WMI_VDEV_TYPE_STA) {
7733dd4f32aeSBjoern A. Zeeb ret = ath11k_peer_delete(ar, arvif->vdev_id, arvif->bssid);
7734dd4f32aeSBjoern A. Zeeb if (ret)
7735dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab,
7736dd4f32aeSBjoern A. Zeeb "failed to delete peer %pM for vdev %d: %d\n",
7737dd4f32aeSBjoern A. Zeeb arvif->bssid, arvif->vdev_id, ret);
7738dd4f32aeSBjoern A. Zeeb else
7739dd4f32aeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
774028348caeSBjoern A. Zeeb "removed peer %pM vdev %d after vdev stop\n",
7741dd4f32aeSBjoern A. Zeeb arvif->bssid, arvif->vdev_id);
7742dd4f32aeSBjoern A. Zeeb }
7743dd4f32aeSBjoern A. Zeeb
7744dd4f32aeSBjoern A. Zeeb if (ab->hw_params.vdev_start_delay &&
7745dd4f32aeSBjoern A. Zeeb arvif->vdev_type == WMI_VDEV_TYPE_MONITOR)
7746dd4f32aeSBjoern A. Zeeb ath11k_wmi_vdev_down(ar, arvif->vdev_id);
7747dd4f32aeSBjoern A. Zeeb
7748dd4f32aeSBjoern A. Zeeb if (arvif->vdev_type != WMI_VDEV_TYPE_MONITOR &&
7749dd4f32aeSBjoern A. Zeeb ar->num_started_vdevs == 1 &&
7750dd4f32aeSBjoern A. Zeeb test_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags)) {
7751dd4f32aeSBjoern A. Zeeb ret = ath11k_mac_monitor_stop(ar);
7752dd4f32aeSBjoern A. Zeeb if (ret)
7753dd4f32aeSBjoern A. Zeeb /* continue even if there's an error */
7754dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to stop monitor during vif channel context unassignment: %d",
7755dd4f32aeSBjoern A. Zeeb ret);
7756dd4f32aeSBjoern A. Zeeb }
7757dd4f32aeSBjoern A. Zeeb
7758dd4f32aeSBjoern A. Zeeb if (arvif->vdev_type == WMI_VDEV_TYPE_STA)
775928348caeSBjoern A. Zeeb ath11k_mac_11d_scan_start(ar, arvif->vdev_id);
7760dd4f32aeSBjoern A. Zeeb
7761dd4f32aeSBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
7762dd4f32aeSBjoern A. Zeeb }
7763dd4f32aeSBjoern A. Zeeb
7764dd4f32aeSBjoern A. Zeeb static int
ath11k_mac_op_switch_vif_chanctx(struct ieee80211_hw * hw,struct ieee80211_vif_chanctx_switch * vifs,int n_vifs,enum ieee80211_chanctx_switch_mode mode)7765dd4f32aeSBjoern A. Zeeb ath11k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw,
7766dd4f32aeSBjoern A. Zeeb struct ieee80211_vif_chanctx_switch *vifs,
7767dd4f32aeSBjoern A. Zeeb int n_vifs,
7768dd4f32aeSBjoern A. Zeeb enum ieee80211_chanctx_switch_mode mode)
7769dd4f32aeSBjoern A. Zeeb {
7770dd4f32aeSBjoern A. Zeeb struct ath11k *ar = hw->priv;
7771dd4f32aeSBjoern A. Zeeb
7772dd4f32aeSBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
7773dd4f32aeSBjoern A. Zeeb
7774dd4f32aeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
777528348caeSBjoern A. Zeeb "chanctx switch n_vifs %d mode %d\n",
7776dd4f32aeSBjoern A. Zeeb n_vifs, mode);
7777dd4f32aeSBjoern A. Zeeb ath11k_mac_update_vif_chan(ar, vifs, n_vifs);
7778dd4f32aeSBjoern A. Zeeb
7779dd4f32aeSBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
7780dd4f32aeSBjoern A. Zeeb
7781dd4f32aeSBjoern A. Zeeb return 0;
7782dd4f32aeSBjoern A. Zeeb }
7783dd4f32aeSBjoern A. Zeeb
7784dd4f32aeSBjoern A. Zeeb static int
ath11k_set_vdev_param_to_all_vifs(struct ath11k * ar,int param,u32 value)7785dd4f32aeSBjoern A. Zeeb ath11k_set_vdev_param_to_all_vifs(struct ath11k *ar, int param, u32 value)
7786dd4f32aeSBjoern A. Zeeb {
7787dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif;
7788dd4f32aeSBjoern A. Zeeb int ret = 0;
7789dd4f32aeSBjoern A. Zeeb
7790dd4f32aeSBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
7791dd4f32aeSBjoern A. Zeeb list_for_each_entry(arvif, &ar->arvifs, list) {
7792dd4f32aeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "setting mac vdev %d param %d value %d\n",
7793dd4f32aeSBjoern A. Zeeb param, arvif->vdev_id, value);
7794dd4f32aeSBjoern A. Zeeb
7795dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
7796dd4f32aeSBjoern A. Zeeb param, value);
7797dd4f32aeSBjoern A. Zeeb if (ret) {
7798dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to set param %d for vdev %d: %d\n",
7799dd4f32aeSBjoern A. Zeeb param, arvif->vdev_id, ret);
7800dd4f32aeSBjoern A. Zeeb break;
7801dd4f32aeSBjoern A. Zeeb }
7802dd4f32aeSBjoern A. Zeeb }
7803dd4f32aeSBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
7804dd4f32aeSBjoern A. Zeeb return ret;
7805dd4f32aeSBjoern A. Zeeb }
7806dd4f32aeSBjoern A. Zeeb
7807dd4f32aeSBjoern A. Zeeb /* mac80211 stores device specific RTS/Fragmentation threshold value,
7808dd4f32aeSBjoern A. Zeeb * this is set interface specific to firmware from ath11k driver
7809dd4f32aeSBjoern A. Zeeb */
ath11k_mac_op_set_rts_threshold(struct ieee80211_hw * hw,u32 value)7810dd4f32aeSBjoern A. Zeeb static int ath11k_mac_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
7811dd4f32aeSBjoern A. Zeeb {
7812dd4f32aeSBjoern A. Zeeb struct ath11k *ar = hw->priv;
7813dd4f32aeSBjoern A. Zeeb int param_id = WMI_VDEV_PARAM_RTS_THRESHOLD;
7814dd4f32aeSBjoern A. Zeeb
7815dd4f32aeSBjoern A. Zeeb return ath11k_set_vdev_param_to_all_vifs(ar, param_id, value);
7816dd4f32aeSBjoern A. Zeeb }
7817dd4f32aeSBjoern A. Zeeb
ath11k_mac_op_set_frag_threshold(struct ieee80211_hw * hw,u32 value)7818dd4f32aeSBjoern A. Zeeb static int ath11k_mac_op_set_frag_threshold(struct ieee80211_hw *hw, u32 value)
7819dd4f32aeSBjoern A. Zeeb {
7820dd4f32aeSBjoern A. Zeeb /* Even though there's a WMI vdev param for fragmentation threshold no
7821dd4f32aeSBjoern A. Zeeb * known firmware actually implements it. Moreover it is not possible to
7822dd4f32aeSBjoern A. Zeeb * rely frame fragmentation to mac80211 because firmware clears the
7823dd4f32aeSBjoern A. Zeeb * "more fragments" bit in frame control making it impossible for remote
7824dd4f32aeSBjoern A. Zeeb * devices to reassemble frames.
7825dd4f32aeSBjoern A. Zeeb *
7826dd4f32aeSBjoern A. Zeeb * Hence implement a dummy callback just to say fragmentation isn't
7827dd4f32aeSBjoern A. Zeeb * supported. This effectively prevents mac80211 from doing frame
7828dd4f32aeSBjoern A. Zeeb * fragmentation in software.
7829dd4f32aeSBjoern A. Zeeb */
7830dd4f32aeSBjoern A. Zeeb return -EOPNOTSUPP;
7831dd4f32aeSBjoern A. Zeeb }
7832dd4f32aeSBjoern A. Zeeb
ath11k_mac_flush_tx_complete(struct ath11k * ar)783328348caeSBjoern A. Zeeb static int ath11k_mac_flush_tx_complete(struct ath11k *ar)
7834dd4f32aeSBjoern A. Zeeb {
7835dd4f32aeSBjoern A. Zeeb long time_left;
783628348caeSBjoern A. Zeeb int ret = 0;
7837dd4f32aeSBjoern A. Zeeb
7838dd4f32aeSBjoern A. Zeeb time_left = wait_event_timeout(ar->dp.tx_empty_waitq,
7839dd4f32aeSBjoern A. Zeeb (atomic_read(&ar->dp.num_tx_pending) == 0),
7840dd4f32aeSBjoern A. Zeeb ATH11K_FLUSH_TIMEOUT);
784128348caeSBjoern A. Zeeb if (time_left == 0) {
784228348caeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to flush transmit queue, data pkts pending %d\n",
784328348caeSBjoern A. Zeeb atomic_read(&ar->dp.num_tx_pending));
784428348caeSBjoern A. Zeeb ret = -ETIMEDOUT;
784528348caeSBjoern A. Zeeb }
7846dd4f32aeSBjoern A. Zeeb
7847dd4f32aeSBjoern A. Zeeb time_left = wait_event_timeout(ar->txmgmt_empty_waitq,
7848dd4f32aeSBjoern A. Zeeb (atomic_read(&ar->num_pending_mgmt_tx) == 0),
7849dd4f32aeSBjoern A. Zeeb ATH11K_FLUSH_TIMEOUT);
785028348caeSBjoern A. Zeeb if (time_left == 0) {
785128348caeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to flush mgmt transmit queue, mgmt pkts pending %d\n",
7852dd4f32aeSBjoern A. Zeeb atomic_read(&ar->num_pending_mgmt_tx));
785328348caeSBjoern A. Zeeb ret = -ETIMEDOUT;
7854dd4f32aeSBjoern A. Zeeb }
7855dd4f32aeSBjoern A. Zeeb
785628348caeSBjoern A. Zeeb return ret;
785728348caeSBjoern A. Zeeb }
785828348caeSBjoern A. Zeeb
ath11k_mac_wait_tx_complete(struct ath11k * ar)785928348caeSBjoern A. Zeeb int ath11k_mac_wait_tx_complete(struct ath11k *ar)
7860dd4f32aeSBjoern A. Zeeb {
786128348caeSBjoern A. Zeeb ath11k_mac_drain_tx(ar);
786228348caeSBjoern A. Zeeb return ath11k_mac_flush_tx_complete(ar);
786328348caeSBjoern A. Zeeb }
7864dd4f32aeSBjoern A. Zeeb
ath11k_mac_op_flush(struct ieee80211_hw * hw,struct ieee80211_vif * vif,u32 queues,bool drop)786528348caeSBjoern A. Zeeb static void ath11k_mac_op_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
786628348caeSBjoern A. Zeeb u32 queues, bool drop)
786728348caeSBjoern A. Zeeb {
786828348caeSBjoern A. Zeeb struct ath11k *ar = hw->priv;
7869dd4f32aeSBjoern A. Zeeb
787028348caeSBjoern A. Zeeb if (drop)
787128348caeSBjoern A. Zeeb return;
787228348caeSBjoern A. Zeeb
787328348caeSBjoern A. Zeeb ath11k_mac_flush_tx_complete(ar);
7874dd4f32aeSBjoern A. Zeeb }
7875dd4f32aeSBjoern A. Zeeb
7876dd4f32aeSBjoern A. Zeeb static bool
ath11k_mac_has_single_legacy_rate(struct ath11k * ar,enum nl80211_band band,const struct cfg80211_bitrate_mask * mask)7877dd4f32aeSBjoern A. Zeeb ath11k_mac_has_single_legacy_rate(struct ath11k *ar,
7878dd4f32aeSBjoern A. Zeeb enum nl80211_band band,
7879dd4f32aeSBjoern A. Zeeb const struct cfg80211_bitrate_mask *mask)
7880dd4f32aeSBjoern A. Zeeb {
7881dd4f32aeSBjoern A. Zeeb int num_rates = 0;
7882dd4f32aeSBjoern A. Zeeb
7883dd4f32aeSBjoern A. Zeeb num_rates = hweight32(mask->control[band].legacy);
7884dd4f32aeSBjoern A. Zeeb
7885dd4f32aeSBjoern A. Zeeb if (ath11k_mac_bitrate_mask_num_ht_rates(ar, band, mask))
7886dd4f32aeSBjoern A. Zeeb return false;
7887dd4f32aeSBjoern A. Zeeb
7888dd4f32aeSBjoern A. Zeeb if (ath11k_mac_bitrate_mask_num_vht_rates(ar, band, mask))
7889dd4f32aeSBjoern A. Zeeb return false;
7890dd4f32aeSBjoern A. Zeeb
7891dd4f32aeSBjoern A. Zeeb if (ath11k_mac_bitrate_mask_num_he_rates(ar, band, mask))
7892dd4f32aeSBjoern A. Zeeb return false;
7893dd4f32aeSBjoern A. Zeeb
7894dd4f32aeSBjoern A. Zeeb return num_rates == 1;
7895dd4f32aeSBjoern A. Zeeb }
7896dd4f32aeSBjoern A. Zeeb
7897dd4f32aeSBjoern A. Zeeb static __le16
ath11k_mac_get_tx_mcs_map(const struct ieee80211_sta_he_cap * he_cap)7898dd4f32aeSBjoern A. Zeeb ath11k_mac_get_tx_mcs_map(const struct ieee80211_sta_he_cap *he_cap)
7899dd4f32aeSBjoern A. Zeeb {
7900dd4f32aeSBjoern A. Zeeb if (he_cap->he_cap_elem.phy_cap_info[0] &
7901dd4f32aeSBjoern A. Zeeb IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)
7902dd4f32aeSBjoern A. Zeeb return he_cap->he_mcs_nss_supp.tx_mcs_80p80;
7903dd4f32aeSBjoern A. Zeeb
7904dd4f32aeSBjoern A. Zeeb if (he_cap->he_cap_elem.phy_cap_info[0] &
7905dd4f32aeSBjoern A. Zeeb IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G)
7906dd4f32aeSBjoern A. Zeeb return he_cap->he_mcs_nss_supp.tx_mcs_160;
7907dd4f32aeSBjoern A. Zeeb
7908dd4f32aeSBjoern A. Zeeb return he_cap->he_mcs_nss_supp.tx_mcs_80;
7909dd4f32aeSBjoern A. Zeeb }
7910dd4f32aeSBjoern A. Zeeb
7911dd4f32aeSBjoern A. Zeeb static bool
ath11k_mac_bitrate_mask_get_single_nss(struct ath11k * ar,enum nl80211_band band,const struct cfg80211_bitrate_mask * mask,int * nss)7912dd4f32aeSBjoern A. Zeeb ath11k_mac_bitrate_mask_get_single_nss(struct ath11k *ar,
7913dd4f32aeSBjoern A. Zeeb enum nl80211_band band,
7914dd4f32aeSBjoern A. Zeeb const struct cfg80211_bitrate_mask *mask,
7915dd4f32aeSBjoern A. Zeeb int *nss)
7916dd4f32aeSBjoern A. Zeeb {
7917dd4f32aeSBjoern A. Zeeb struct ieee80211_supported_band *sband = &ar->mac.sbands[band];
7918dd4f32aeSBjoern A. Zeeb u16 vht_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map);
7919dd4f32aeSBjoern A. Zeeb u16 he_mcs_map = 0;
7920dd4f32aeSBjoern A. Zeeb u8 ht_nss_mask = 0;
7921dd4f32aeSBjoern A. Zeeb u8 vht_nss_mask = 0;
7922dd4f32aeSBjoern A. Zeeb u8 he_nss_mask = 0;
7923dd4f32aeSBjoern A. Zeeb int i;
7924dd4f32aeSBjoern A. Zeeb
7925dd4f32aeSBjoern A. Zeeb /* No need to consider legacy here. Basic rates are always present
7926dd4f32aeSBjoern A. Zeeb * in bitrate mask
7927dd4f32aeSBjoern A. Zeeb */
7928dd4f32aeSBjoern A. Zeeb
7929dd4f32aeSBjoern A. Zeeb for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++) {
7930dd4f32aeSBjoern A. Zeeb if (mask->control[band].ht_mcs[i] == 0)
7931dd4f32aeSBjoern A. Zeeb continue;
7932dd4f32aeSBjoern A. Zeeb else if (mask->control[band].ht_mcs[i] ==
7933dd4f32aeSBjoern A. Zeeb sband->ht_cap.mcs.rx_mask[i])
7934dd4f32aeSBjoern A. Zeeb ht_nss_mask |= BIT(i);
7935dd4f32aeSBjoern A. Zeeb else
7936dd4f32aeSBjoern A. Zeeb return false;
7937dd4f32aeSBjoern A. Zeeb }
7938dd4f32aeSBjoern A. Zeeb
7939dd4f32aeSBjoern A. Zeeb for (i = 0; i < ARRAY_SIZE(mask->control[band].vht_mcs); i++) {
7940dd4f32aeSBjoern A. Zeeb if (mask->control[band].vht_mcs[i] == 0)
7941dd4f32aeSBjoern A. Zeeb continue;
7942dd4f32aeSBjoern A. Zeeb else if (mask->control[band].vht_mcs[i] ==
7943dd4f32aeSBjoern A. Zeeb ath11k_mac_get_max_vht_mcs_map(vht_mcs_map, i))
7944dd4f32aeSBjoern A. Zeeb vht_nss_mask |= BIT(i);
7945dd4f32aeSBjoern A. Zeeb else
7946dd4f32aeSBjoern A. Zeeb return false;
7947dd4f32aeSBjoern A. Zeeb }
7948dd4f32aeSBjoern A. Zeeb
7949dd4f32aeSBjoern A. Zeeb he_mcs_map = le16_to_cpu(ath11k_mac_get_tx_mcs_map(&sband->iftype_data->he_cap));
7950dd4f32aeSBjoern A. Zeeb
7951dd4f32aeSBjoern A. Zeeb for (i = 0; i < ARRAY_SIZE(mask->control[band].he_mcs); i++) {
7952dd4f32aeSBjoern A. Zeeb if (mask->control[band].he_mcs[i] == 0)
7953dd4f32aeSBjoern A. Zeeb continue;
7954dd4f32aeSBjoern A. Zeeb
7955dd4f32aeSBjoern A. Zeeb if (mask->control[band].he_mcs[i] ==
7956dd4f32aeSBjoern A. Zeeb ath11k_mac_get_max_he_mcs_map(he_mcs_map, i))
7957dd4f32aeSBjoern A. Zeeb he_nss_mask |= BIT(i);
7958dd4f32aeSBjoern A. Zeeb else
7959dd4f32aeSBjoern A. Zeeb return false;
7960dd4f32aeSBjoern A. Zeeb }
7961dd4f32aeSBjoern A. Zeeb
7962dd4f32aeSBjoern A. Zeeb if (ht_nss_mask != vht_nss_mask || ht_nss_mask != he_nss_mask)
7963dd4f32aeSBjoern A. Zeeb return false;
7964dd4f32aeSBjoern A. Zeeb
7965dd4f32aeSBjoern A. Zeeb if (ht_nss_mask == 0)
7966dd4f32aeSBjoern A. Zeeb return false;
7967dd4f32aeSBjoern A. Zeeb
7968dd4f32aeSBjoern A. Zeeb if (BIT(fls(ht_nss_mask)) - 1 != ht_nss_mask)
7969dd4f32aeSBjoern A. Zeeb return false;
7970dd4f32aeSBjoern A. Zeeb
7971dd4f32aeSBjoern A. Zeeb *nss = fls(ht_nss_mask);
7972dd4f32aeSBjoern A. Zeeb
7973dd4f32aeSBjoern A. Zeeb return true;
7974dd4f32aeSBjoern A. Zeeb }
7975dd4f32aeSBjoern A. Zeeb
7976dd4f32aeSBjoern A. Zeeb static int
ath11k_mac_get_single_legacy_rate(struct ath11k * ar,enum nl80211_band band,const struct cfg80211_bitrate_mask * mask,u32 * rate,u8 * nss)7977dd4f32aeSBjoern A. Zeeb ath11k_mac_get_single_legacy_rate(struct ath11k *ar,
7978dd4f32aeSBjoern A. Zeeb enum nl80211_band band,
7979dd4f32aeSBjoern A. Zeeb const struct cfg80211_bitrate_mask *mask,
7980dd4f32aeSBjoern A. Zeeb u32 *rate, u8 *nss)
7981dd4f32aeSBjoern A. Zeeb {
7982dd4f32aeSBjoern A. Zeeb int rate_idx;
7983dd4f32aeSBjoern A. Zeeb u16 bitrate;
7984dd4f32aeSBjoern A. Zeeb u8 preamble;
7985dd4f32aeSBjoern A. Zeeb u8 hw_rate;
7986dd4f32aeSBjoern A. Zeeb
7987dd4f32aeSBjoern A. Zeeb if (hweight32(mask->control[band].legacy) != 1)
7988dd4f32aeSBjoern A. Zeeb return -EINVAL;
7989dd4f32aeSBjoern A. Zeeb
7990dd4f32aeSBjoern A. Zeeb rate_idx = ffs(mask->control[band].legacy) - 1;
7991dd4f32aeSBjoern A. Zeeb
7992dd4f32aeSBjoern A. Zeeb if (band == NL80211_BAND_5GHZ || band == NL80211_BAND_6GHZ)
7993dd4f32aeSBjoern A. Zeeb rate_idx += ATH11K_MAC_FIRST_OFDM_RATE_IDX;
7994dd4f32aeSBjoern A. Zeeb
7995dd4f32aeSBjoern A. Zeeb hw_rate = ath11k_legacy_rates[rate_idx].hw_value;
7996dd4f32aeSBjoern A. Zeeb bitrate = ath11k_legacy_rates[rate_idx].bitrate;
7997dd4f32aeSBjoern A. Zeeb
7998dd4f32aeSBjoern A. Zeeb if (ath11k_mac_bitrate_is_cck(bitrate))
7999dd4f32aeSBjoern A. Zeeb preamble = WMI_RATE_PREAMBLE_CCK;
8000dd4f32aeSBjoern A. Zeeb else
8001dd4f32aeSBjoern A. Zeeb preamble = WMI_RATE_PREAMBLE_OFDM;
8002dd4f32aeSBjoern A. Zeeb
8003dd4f32aeSBjoern A. Zeeb *nss = 1;
8004dd4f32aeSBjoern A. Zeeb *rate = ATH11K_HW_RATE_CODE(hw_rate, 0, preamble);
8005dd4f32aeSBjoern A. Zeeb
8006dd4f32aeSBjoern A. Zeeb return 0;
8007dd4f32aeSBjoern A. Zeeb }
8008dd4f32aeSBjoern A. Zeeb
8009dd4f32aeSBjoern A. Zeeb static int
ath11k_mac_set_fixed_rate_gi_ltf(struct ath11k_vif * arvif,u8 he_gi,u8 he_ltf)8010dd4f32aeSBjoern A. Zeeb ath11k_mac_set_fixed_rate_gi_ltf(struct ath11k_vif *arvif, u8 he_gi, u8 he_ltf)
8011dd4f32aeSBjoern A. Zeeb {
8012dd4f32aeSBjoern A. Zeeb struct ath11k *ar = arvif->ar;
8013dd4f32aeSBjoern A. Zeeb int ret;
8014dd4f32aeSBjoern A. Zeeb
8015dd4f32aeSBjoern A. Zeeb /* 0.8 = 0, 1.6 = 2 and 3.2 = 3. */
8016dd4f32aeSBjoern A. Zeeb if (he_gi && he_gi != 0xFF)
8017dd4f32aeSBjoern A. Zeeb he_gi += 1;
8018dd4f32aeSBjoern A. Zeeb
8019dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
8020dd4f32aeSBjoern A. Zeeb WMI_VDEV_PARAM_SGI, he_gi);
8021dd4f32aeSBjoern A. Zeeb if (ret) {
8022dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to set he gi %d: %d\n",
8023dd4f32aeSBjoern A. Zeeb he_gi, ret);
8024dd4f32aeSBjoern A. Zeeb return ret;
8025dd4f32aeSBjoern A. Zeeb }
8026dd4f32aeSBjoern A. Zeeb /* start from 1 */
8027dd4f32aeSBjoern A. Zeeb if (he_ltf != 0xFF)
8028dd4f32aeSBjoern A. Zeeb he_ltf += 1;
8029dd4f32aeSBjoern A. Zeeb
8030dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
8031dd4f32aeSBjoern A. Zeeb WMI_VDEV_PARAM_HE_LTF, he_ltf);
8032dd4f32aeSBjoern A. Zeeb if (ret) {
8033dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to set he ltf %d: %d\n",
8034dd4f32aeSBjoern A. Zeeb he_ltf, ret);
8035dd4f32aeSBjoern A. Zeeb return ret;
8036dd4f32aeSBjoern A. Zeeb }
8037dd4f32aeSBjoern A. Zeeb
8038dd4f32aeSBjoern A. Zeeb return 0;
8039dd4f32aeSBjoern A. Zeeb }
8040dd4f32aeSBjoern A. Zeeb
8041dd4f32aeSBjoern A. Zeeb static int
ath11k_mac_set_auto_rate_gi_ltf(struct ath11k_vif * arvif,u16 he_gi,u8 he_ltf)8042dd4f32aeSBjoern A. Zeeb ath11k_mac_set_auto_rate_gi_ltf(struct ath11k_vif *arvif, u16 he_gi, u8 he_ltf)
8043dd4f32aeSBjoern A. Zeeb {
8044dd4f32aeSBjoern A. Zeeb struct ath11k *ar = arvif->ar;
8045dd4f32aeSBjoern A. Zeeb int ret;
8046dd4f32aeSBjoern A. Zeeb u32 he_ar_gi_ltf;
8047dd4f32aeSBjoern A. Zeeb
8048dd4f32aeSBjoern A. Zeeb if (he_gi != 0xFF) {
8049dd4f32aeSBjoern A. Zeeb switch (he_gi) {
8050dd4f32aeSBjoern A. Zeeb case NL80211_RATE_INFO_HE_GI_0_8:
8051dd4f32aeSBjoern A. Zeeb he_gi = WMI_AUTORATE_800NS_GI;
8052dd4f32aeSBjoern A. Zeeb break;
8053dd4f32aeSBjoern A. Zeeb case NL80211_RATE_INFO_HE_GI_1_6:
8054dd4f32aeSBjoern A. Zeeb he_gi = WMI_AUTORATE_1600NS_GI;
8055dd4f32aeSBjoern A. Zeeb break;
8056dd4f32aeSBjoern A. Zeeb case NL80211_RATE_INFO_HE_GI_3_2:
8057dd4f32aeSBjoern A. Zeeb he_gi = WMI_AUTORATE_3200NS_GI;
8058dd4f32aeSBjoern A. Zeeb break;
8059dd4f32aeSBjoern A. Zeeb default:
8060dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "invalid he gi: %d\n", he_gi);
8061dd4f32aeSBjoern A. Zeeb return -EINVAL;
8062dd4f32aeSBjoern A. Zeeb }
8063dd4f32aeSBjoern A. Zeeb }
8064dd4f32aeSBjoern A. Zeeb
8065dd4f32aeSBjoern A. Zeeb if (he_ltf != 0xFF) {
8066dd4f32aeSBjoern A. Zeeb switch (he_ltf) {
8067dd4f32aeSBjoern A. Zeeb case NL80211_RATE_INFO_HE_1XLTF:
8068dd4f32aeSBjoern A. Zeeb he_ltf = WMI_HE_AUTORATE_LTF_1X;
8069dd4f32aeSBjoern A. Zeeb break;
8070dd4f32aeSBjoern A. Zeeb case NL80211_RATE_INFO_HE_2XLTF:
8071dd4f32aeSBjoern A. Zeeb he_ltf = WMI_HE_AUTORATE_LTF_2X;
8072dd4f32aeSBjoern A. Zeeb break;
8073dd4f32aeSBjoern A. Zeeb case NL80211_RATE_INFO_HE_4XLTF:
8074dd4f32aeSBjoern A. Zeeb he_ltf = WMI_HE_AUTORATE_LTF_4X;
8075dd4f32aeSBjoern A. Zeeb break;
8076dd4f32aeSBjoern A. Zeeb default:
8077dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "invalid he ltf: %d\n", he_ltf);
8078dd4f32aeSBjoern A. Zeeb return -EINVAL;
8079dd4f32aeSBjoern A. Zeeb }
8080dd4f32aeSBjoern A. Zeeb }
8081dd4f32aeSBjoern A. Zeeb
8082dd4f32aeSBjoern A. Zeeb he_ar_gi_ltf = he_gi | he_ltf;
8083dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
8084dd4f32aeSBjoern A. Zeeb WMI_VDEV_PARAM_AUTORATE_MISC_CFG,
8085dd4f32aeSBjoern A. Zeeb he_ar_gi_ltf);
8086dd4f32aeSBjoern A. Zeeb if (ret) {
8087dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab,
8088dd4f32aeSBjoern A. Zeeb "failed to set he autorate gi %u ltf %u: %d\n",
8089dd4f32aeSBjoern A. Zeeb he_gi, he_ltf, ret);
8090dd4f32aeSBjoern A. Zeeb return ret;
8091dd4f32aeSBjoern A. Zeeb }
8092dd4f32aeSBjoern A. Zeeb
8093dd4f32aeSBjoern A. Zeeb return 0;
8094dd4f32aeSBjoern A. Zeeb }
8095dd4f32aeSBjoern A. Zeeb
ath11k_mac_set_rate_params(struct ath11k_vif * arvif,u32 rate,u8 nss,u8 sgi,u8 ldpc,u8 he_gi,u8 he_ltf,bool he_fixed_rate)8096dd4f32aeSBjoern A. Zeeb static int ath11k_mac_set_rate_params(struct ath11k_vif *arvif,
8097dd4f32aeSBjoern A. Zeeb u32 rate, u8 nss, u8 sgi, u8 ldpc,
8098dd4f32aeSBjoern A. Zeeb u8 he_gi, u8 he_ltf, bool he_fixed_rate)
8099dd4f32aeSBjoern A. Zeeb {
8100dd4f32aeSBjoern A. Zeeb struct ath11k *ar = arvif->ar;
8101dd4f32aeSBjoern A. Zeeb u32 vdev_param;
8102dd4f32aeSBjoern A. Zeeb int ret;
8103dd4f32aeSBjoern A. Zeeb
8104dd4f32aeSBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
8105dd4f32aeSBjoern A. Zeeb
8106dd4f32aeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
810728348caeSBjoern A. Zeeb "set rate params vdev %i rate 0x%02x nss 0x%02x sgi 0x%02x ldpc 0x%02x he_gi 0x%02x he_ltf 0x%02x he_fixed_rate %d\n",
8108dd4f32aeSBjoern A. Zeeb arvif->vdev_id, rate, nss, sgi, ldpc, he_gi,
8109dd4f32aeSBjoern A. Zeeb he_ltf, he_fixed_rate);
8110dd4f32aeSBjoern A. Zeeb
8111dd4f32aeSBjoern A. Zeeb if (!arvif->vif->bss_conf.he_support) {
8112dd4f32aeSBjoern A. Zeeb vdev_param = WMI_VDEV_PARAM_FIXED_RATE;
8113dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
8114dd4f32aeSBjoern A. Zeeb vdev_param, rate);
8115dd4f32aeSBjoern A. Zeeb if (ret) {
8116dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to set fixed rate param 0x%02x: %d\n",
8117dd4f32aeSBjoern A. Zeeb rate, ret);
8118dd4f32aeSBjoern A. Zeeb return ret;
8119dd4f32aeSBjoern A. Zeeb }
8120dd4f32aeSBjoern A. Zeeb }
8121dd4f32aeSBjoern A. Zeeb
8122dd4f32aeSBjoern A. Zeeb vdev_param = WMI_VDEV_PARAM_NSS;
8123dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
8124dd4f32aeSBjoern A. Zeeb vdev_param, nss);
8125dd4f32aeSBjoern A. Zeeb if (ret) {
8126dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to set nss param %d: %d\n",
8127dd4f32aeSBjoern A. Zeeb nss, ret);
8128dd4f32aeSBjoern A. Zeeb return ret;
8129dd4f32aeSBjoern A. Zeeb }
8130dd4f32aeSBjoern A. Zeeb
8131dd4f32aeSBjoern A. Zeeb vdev_param = WMI_VDEV_PARAM_LDPC;
8132dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
8133dd4f32aeSBjoern A. Zeeb vdev_param, ldpc);
8134dd4f32aeSBjoern A. Zeeb if (ret) {
8135dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to set ldpc param %d: %d\n",
8136dd4f32aeSBjoern A. Zeeb ldpc, ret);
8137dd4f32aeSBjoern A. Zeeb return ret;
8138dd4f32aeSBjoern A. Zeeb }
8139dd4f32aeSBjoern A. Zeeb
8140dd4f32aeSBjoern A. Zeeb if (arvif->vif->bss_conf.he_support) {
8141dd4f32aeSBjoern A. Zeeb if (he_fixed_rate) {
8142dd4f32aeSBjoern A. Zeeb ret = ath11k_mac_set_fixed_rate_gi_ltf(arvif, he_gi,
8143dd4f32aeSBjoern A. Zeeb he_ltf);
8144dd4f32aeSBjoern A. Zeeb if (ret) {
8145dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to set fixed rate gi ltf: %d\n",
8146dd4f32aeSBjoern A. Zeeb ret);
8147dd4f32aeSBjoern A. Zeeb return ret;
8148dd4f32aeSBjoern A. Zeeb }
8149dd4f32aeSBjoern A. Zeeb } else {
8150dd4f32aeSBjoern A. Zeeb ret = ath11k_mac_set_auto_rate_gi_ltf(arvif, he_gi,
8151dd4f32aeSBjoern A. Zeeb he_ltf);
8152dd4f32aeSBjoern A. Zeeb if (ret) {
8153dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to set auto rate gi ltf: %d\n",
8154dd4f32aeSBjoern A. Zeeb ret);
8155dd4f32aeSBjoern A. Zeeb return ret;
8156dd4f32aeSBjoern A. Zeeb }
8157dd4f32aeSBjoern A. Zeeb }
8158dd4f32aeSBjoern A. Zeeb } else {
8159dd4f32aeSBjoern A. Zeeb vdev_param = WMI_VDEV_PARAM_SGI;
8160dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
8161dd4f32aeSBjoern A. Zeeb vdev_param, sgi);
8162dd4f32aeSBjoern A. Zeeb if (ret) {
8163dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to set sgi param %d: %d\n",
8164dd4f32aeSBjoern A. Zeeb sgi, ret);
8165dd4f32aeSBjoern A. Zeeb return ret;
8166dd4f32aeSBjoern A. Zeeb }
8167dd4f32aeSBjoern A. Zeeb }
8168dd4f32aeSBjoern A. Zeeb
8169dd4f32aeSBjoern A. Zeeb return 0;
8170dd4f32aeSBjoern A. Zeeb }
8171dd4f32aeSBjoern A. Zeeb
8172dd4f32aeSBjoern A. Zeeb static bool
ath11k_mac_vht_mcs_range_present(struct ath11k * ar,enum nl80211_band band,const struct cfg80211_bitrate_mask * mask)8173dd4f32aeSBjoern A. Zeeb ath11k_mac_vht_mcs_range_present(struct ath11k *ar,
8174dd4f32aeSBjoern A. Zeeb enum nl80211_band band,
8175dd4f32aeSBjoern A. Zeeb const struct cfg80211_bitrate_mask *mask)
8176dd4f32aeSBjoern A. Zeeb {
8177dd4f32aeSBjoern A. Zeeb int i;
8178dd4f32aeSBjoern A. Zeeb u16 vht_mcs;
8179dd4f32aeSBjoern A. Zeeb
8180dd4f32aeSBjoern A. Zeeb for (i = 0; i < NL80211_VHT_NSS_MAX; i++) {
8181dd4f32aeSBjoern A. Zeeb vht_mcs = mask->control[band].vht_mcs[i];
8182dd4f32aeSBjoern A. Zeeb
8183dd4f32aeSBjoern A. Zeeb switch (vht_mcs) {
8184dd4f32aeSBjoern A. Zeeb case 0:
8185dd4f32aeSBjoern A. Zeeb case BIT(8) - 1:
8186dd4f32aeSBjoern A. Zeeb case BIT(9) - 1:
8187dd4f32aeSBjoern A. Zeeb case BIT(10) - 1:
8188dd4f32aeSBjoern A. Zeeb break;
8189dd4f32aeSBjoern A. Zeeb default:
8190dd4f32aeSBjoern A. Zeeb return false;
8191dd4f32aeSBjoern A. Zeeb }
8192dd4f32aeSBjoern A. Zeeb }
8193dd4f32aeSBjoern A. Zeeb
8194dd4f32aeSBjoern A. Zeeb return true;
8195dd4f32aeSBjoern A. Zeeb }
8196dd4f32aeSBjoern A. Zeeb
8197dd4f32aeSBjoern A. Zeeb static bool
ath11k_mac_he_mcs_range_present(struct ath11k * ar,enum nl80211_band band,const struct cfg80211_bitrate_mask * mask)8198dd4f32aeSBjoern A. Zeeb ath11k_mac_he_mcs_range_present(struct ath11k *ar,
8199dd4f32aeSBjoern A. Zeeb enum nl80211_band band,
8200dd4f32aeSBjoern A. Zeeb const struct cfg80211_bitrate_mask *mask)
8201dd4f32aeSBjoern A. Zeeb {
8202dd4f32aeSBjoern A. Zeeb int i;
8203dd4f32aeSBjoern A. Zeeb u16 he_mcs;
8204dd4f32aeSBjoern A. Zeeb
8205dd4f32aeSBjoern A. Zeeb for (i = 0; i < NL80211_HE_NSS_MAX; i++) {
8206dd4f32aeSBjoern A. Zeeb he_mcs = mask->control[band].he_mcs[i];
8207dd4f32aeSBjoern A. Zeeb
8208dd4f32aeSBjoern A. Zeeb switch (he_mcs) {
8209dd4f32aeSBjoern A. Zeeb case 0:
8210dd4f32aeSBjoern A. Zeeb case BIT(8) - 1:
8211dd4f32aeSBjoern A. Zeeb case BIT(10) - 1:
8212dd4f32aeSBjoern A. Zeeb case BIT(12) - 1:
8213dd4f32aeSBjoern A. Zeeb break;
8214dd4f32aeSBjoern A. Zeeb default:
8215dd4f32aeSBjoern A. Zeeb return false;
8216dd4f32aeSBjoern A. Zeeb }
8217dd4f32aeSBjoern A. Zeeb }
8218dd4f32aeSBjoern A. Zeeb
8219dd4f32aeSBjoern A. Zeeb return true;
8220dd4f32aeSBjoern A. Zeeb }
8221dd4f32aeSBjoern A. Zeeb
ath11k_mac_set_bitrate_mask_iter(void * data,struct ieee80211_sta * sta)8222dd4f32aeSBjoern A. Zeeb static void ath11k_mac_set_bitrate_mask_iter(void *data,
8223dd4f32aeSBjoern A. Zeeb struct ieee80211_sta *sta)
8224dd4f32aeSBjoern A. Zeeb {
8225dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif = data;
8226dd4f32aeSBjoern A. Zeeb struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
8227dd4f32aeSBjoern A. Zeeb struct ath11k *ar = arvif->ar;
8228dd4f32aeSBjoern A. Zeeb
8229dd4f32aeSBjoern A. Zeeb spin_lock_bh(&ar->data_lock);
8230dd4f32aeSBjoern A. Zeeb arsta->changed |= IEEE80211_RC_SUPP_RATES_CHANGED;
8231dd4f32aeSBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
8232dd4f32aeSBjoern A. Zeeb
8233dd4f32aeSBjoern A. Zeeb ieee80211_queue_work(ar->hw, &arsta->update_wk);
8234dd4f32aeSBjoern A. Zeeb }
8235dd4f32aeSBjoern A. Zeeb
ath11k_mac_disable_peer_fixed_rate(void * data,struct ieee80211_sta * sta)8236dd4f32aeSBjoern A. Zeeb static void ath11k_mac_disable_peer_fixed_rate(void *data,
8237dd4f32aeSBjoern A. Zeeb struct ieee80211_sta *sta)
8238dd4f32aeSBjoern A. Zeeb {
8239dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif = data;
8240dd4f32aeSBjoern A. Zeeb struct ath11k *ar = arvif->ar;
8241dd4f32aeSBjoern A. Zeeb int ret;
8242dd4f32aeSBjoern A. Zeeb
8243dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_set_peer_param(ar, sta->addr,
8244dd4f32aeSBjoern A. Zeeb arvif->vdev_id,
8245dd4f32aeSBjoern A. Zeeb WMI_PEER_PARAM_FIXED_RATE,
8246dd4f32aeSBjoern A. Zeeb WMI_FIXED_RATE_NONE);
8247dd4f32aeSBjoern A. Zeeb if (ret)
8248dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab,
8249dd4f32aeSBjoern A. Zeeb "failed to disable peer fixed rate for STA %pM ret %d\n",
8250dd4f32aeSBjoern A. Zeeb sta->addr, ret);
8251dd4f32aeSBjoern A. Zeeb }
8252dd4f32aeSBjoern A. Zeeb
8253dd4f32aeSBjoern A. Zeeb static bool
ath11k_mac_validate_vht_he_fixed_rate_settings(struct ath11k * ar,enum nl80211_band band,const struct cfg80211_bitrate_mask * mask)8254dd4f32aeSBjoern A. Zeeb ath11k_mac_validate_vht_he_fixed_rate_settings(struct ath11k *ar, enum nl80211_band band,
8255dd4f32aeSBjoern A. Zeeb const struct cfg80211_bitrate_mask *mask)
8256dd4f32aeSBjoern A. Zeeb {
8257dd4f32aeSBjoern A. Zeeb bool he_fixed_rate = false, vht_fixed_rate = false;
825828348caeSBjoern A. Zeeb struct ath11k_peer *peer;
8259dd4f32aeSBjoern A. Zeeb const u16 *vht_mcs_mask, *he_mcs_mask;
826028348caeSBjoern A. Zeeb struct ieee80211_link_sta *deflink;
8261dd4f32aeSBjoern A. Zeeb u8 vht_nss, he_nss;
8262dd4f32aeSBjoern A. Zeeb bool ret = true;
8263dd4f32aeSBjoern A. Zeeb
8264dd4f32aeSBjoern A. Zeeb vht_mcs_mask = mask->control[band].vht_mcs;
8265dd4f32aeSBjoern A. Zeeb he_mcs_mask = mask->control[band].he_mcs;
8266dd4f32aeSBjoern A. Zeeb
8267dd4f32aeSBjoern A. Zeeb if (ath11k_mac_bitrate_mask_num_vht_rates(ar, band, mask) == 1)
8268dd4f32aeSBjoern A. Zeeb vht_fixed_rate = true;
8269dd4f32aeSBjoern A. Zeeb
8270dd4f32aeSBjoern A. Zeeb if (ath11k_mac_bitrate_mask_num_he_rates(ar, band, mask) == 1)
8271dd4f32aeSBjoern A. Zeeb he_fixed_rate = true;
8272dd4f32aeSBjoern A. Zeeb
8273dd4f32aeSBjoern A. Zeeb if (!vht_fixed_rate && !he_fixed_rate)
8274dd4f32aeSBjoern A. Zeeb return true;
8275dd4f32aeSBjoern A. Zeeb
8276dd4f32aeSBjoern A. Zeeb vht_nss = ath11k_mac_max_vht_nss(vht_mcs_mask);
8277dd4f32aeSBjoern A. Zeeb he_nss = ath11k_mac_max_he_nss(he_mcs_mask);
8278dd4f32aeSBjoern A. Zeeb
8279dd4f32aeSBjoern A. Zeeb rcu_read_lock();
8280dd4f32aeSBjoern A. Zeeb spin_lock_bh(&ar->ab->base_lock);
828128348caeSBjoern A. Zeeb list_for_each_entry(peer, &ar->ab->peers, list) {
8282dd4f32aeSBjoern A. Zeeb if (peer->sta) {
828328348caeSBjoern A. Zeeb deflink = &peer->sta->deflink;
828428348caeSBjoern A. Zeeb
828528348caeSBjoern A. Zeeb if (vht_fixed_rate && (!deflink->vht_cap.vht_supported ||
828628348caeSBjoern A. Zeeb deflink->rx_nss < vht_nss)) {
8287dd4f32aeSBjoern A. Zeeb ret = false;
8288dd4f32aeSBjoern A. Zeeb goto out;
8289dd4f32aeSBjoern A. Zeeb }
829028348caeSBjoern A. Zeeb
829128348caeSBjoern A. Zeeb if (he_fixed_rate && (!deflink->he_cap.has_he ||
829228348caeSBjoern A. Zeeb deflink->rx_nss < he_nss)) {
8293dd4f32aeSBjoern A. Zeeb ret = false;
8294dd4f32aeSBjoern A. Zeeb goto out;
8295dd4f32aeSBjoern A. Zeeb }
8296dd4f32aeSBjoern A. Zeeb }
8297dd4f32aeSBjoern A. Zeeb }
8298dd4f32aeSBjoern A. Zeeb
8299dd4f32aeSBjoern A. Zeeb out:
8300dd4f32aeSBjoern A. Zeeb spin_unlock_bh(&ar->ab->base_lock);
8301dd4f32aeSBjoern A. Zeeb rcu_read_unlock();
8302dd4f32aeSBjoern A. Zeeb return ret;
8303dd4f32aeSBjoern A. Zeeb }
8304dd4f32aeSBjoern A. Zeeb
8305dd4f32aeSBjoern A. Zeeb static int
ath11k_mac_op_set_bitrate_mask(struct ieee80211_hw * hw,struct ieee80211_vif * vif,const struct cfg80211_bitrate_mask * mask)8306dd4f32aeSBjoern A. Zeeb ath11k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
8307dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif,
8308dd4f32aeSBjoern A. Zeeb const struct cfg80211_bitrate_mask *mask)
8309dd4f32aeSBjoern A. Zeeb {
8310dd4f32aeSBjoern A. Zeeb struct ath11k_vif *arvif = (void *)vif->drv_priv;
8311dd4f32aeSBjoern A. Zeeb struct cfg80211_chan_def def;
831228348caeSBjoern A. Zeeb struct ath11k_pdev_cap *cap;
8313dd4f32aeSBjoern A. Zeeb struct ath11k *ar = arvif->ar;
8314dd4f32aeSBjoern A. Zeeb enum nl80211_band band;
8315dd4f32aeSBjoern A. Zeeb const u8 *ht_mcs_mask;
8316dd4f32aeSBjoern A. Zeeb const u16 *vht_mcs_mask;
8317dd4f32aeSBjoern A. Zeeb const u16 *he_mcs_mask;
8318dd4f32aeSBjoern A. Zeeb u8 he_ltf = 0;
8319dd4f32aeSBjoern A. Zeeb u8 he_gi = 0;
8320dd4f32aeSBjoern A. Zeeb u32 rate;
8321dd4f32aeSBjoern A. Zeeb u8 nss;
8322dd4f32aeSBjoern A. Zeeb u8 sgi;
8323dd4f32aeSBjoern A. Zeeb u8 ldpc;
8324dd4f32aeSBjoern A. Zeeb int single_nss;
8325dd4f32aeSBjoern A. Zeeb int ret;
8326dd4f32aeSBjoern A. Zeeb int num_rates;
8327dd4f32aeSBjoern A. Zeeb bool he_fixed_rate = false;
8328dd4f32aeSBjoern A. Zeeb
8329dd4f32aeSBjoern A. Zeeb if (ath11k_mac_vif_chan(vif, &def))
8330dd4f32aeSBjoern A. Zeeb return -EPERM;
8331dd4f32aeSBjoern A. Zeeb
8332dd4f32aeSBjoern A. Zeeb band = def.chan->band;
833328348caeSBjoern A. Zeeb cap = &ar->pdev->cap;
8334dd4f32aeSBjoern A. Zeeb ht_mcs_mask = mask->control[band].ht_mcs;
8335dd4f32aeSBjoern A. Zeeb vht_mcs_mask = mask->control[band].vht_mcs;
8336dd4f32aeSBjoern A. Zeeb he_mcs_mask = mask->control[band].he_mcs;
833728348caeSBjoern A. Zeeb ldpc = !!(cap->band[band].ht_cap_info & WMI_HT_CAP_TX_LDPC);
8338dd4f32aeSBjoern A. Zeeb
8339dd4f32aeSBjoern A. Zeeb sgi = mask->control[band].gi;
8340dd4f32aeSBjoern A. Zeeb if (sgi == NL80211_TXRATE_FORCE_LGI)
8341dd4f32aeSBjoern A. Zeeb return -EINVAL;
8342dd4f32aeSBjoern A. Zeeb
8343dd4f32aeSBjoern A. Zeeb he_gi = mask->control[band].he_gi;
8344dd4f32aeSBjoern A. Zeeb he_ltf = mask->control[band].he_ltf;
8345dd4f32aeSBjoern A. Zeeb
8346dd4f32aeSBjoern A. Zeeb /* mac80211 doesn't support sending a fixed HT/VHT MCS alone, rather it
8347dd4f32aeSBjoern A. Zeeb * requires passing at least one of used basic rates along with them.
8348dd4f32aeSBjoern A. Zeeb * Fixed rate setting across different preambles(legacy, HT, VHT) is
8349dd4f32aeSBjoern A. Zeeb * not supported by the FW. Hence use of FIXED_RATE vdev param is not
8350dd4f32aeSBjoern A. Zeeb * suitable for setting single HT/VHT rates.
8351dd4f32aeSBjoern A. Zeeb * But, there could be a single basic rate passed from userspace which
8352dd4f32aeSBjoern A. Zeeb * can be done through the FIXED_RATE param.
8353dd4f32aeSBjoern A. Zeeb */
8354dd4f32aeSBjoern A. Zeeb if (ath11k_mac_has_single_legacy_rate(ar, band, mask)) {
8355dd4f32aeSBjoern A. Zeeb ret = ath11k_mac_get_single_legacy_rate(ar, band, mask, &rate,
8356dd4f32aeSBjoern A. Zeeb &nss);
8357dd4f32aeSBjoern A. Zeeb if (ret) {
8358dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to get single legacy rate for vdev %i: %d\n",
8359dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ret);
8360dd4f32aeSBjoern A. Zeeb return ret;
8361dd4f32aeSBjoern A. Zeeb }
8362dd4f32aeSBjoern A. Zeeb ieee80211_iterate_stations_atomic(ar->hw,
8363dd4f32aeSBjoern A. Zeeb ath11k_mac_disable_peer_fixed_rate,
8364dd4f32aeSBjoern A. Zeeb arvif);
8365dd4f32aeSBjoern A. Zeeb } else if (ath11k_mac_bitrate_mask_get_single_nss(ar, band, mask,
8366dd4f32aeSBjoern A. Zeeb &single_nss)) {
8367dd4f32aeSBjoern A. Zeeb rate = WMI_FIXED_RATE_NONE;
8368dd4f32aeSBjoern A. Zeeb nss = single_nss;
8369dd4f32aeSBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
8370dd4f32aeSBjoern A. Zeeb arvif->bitrate_mask = *mask;
8371dd4f32aeSBjoern A. Zeeb ieee80211_iterate_stations_atomic(ar->hw,
8372dd4f32aeSBjoern A. Zeeb ath11k_mac_set_bitrate_mask_iter,
8373dd4f32aeSBjoern A. Zeeb arvif);
8374dd4f32aeSBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
8375dd4f32aeSBjoern A. Zeeb } else {
8376dd4f32aeSBjoern A. Zeeb rate = WMI_FIXED_RATE_NONE;
8377dd4f32aeSBjoern A. Zeeb
8378dd4f32aeSBjoern A. Zeeb if (!ath11k_mac_validate_vht_he_fixed_rate_settings(ar, band, mask))
8379dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab,
8380dd4f32aeSBjoern A. Zeeb "could not update fixed rate settings to all peers due to mcs/nss incompatibility\n");
8381dd4f32aeSBjoern A. Zeeb nss = min_t(u32, ar->num_tx_chains,
8382dd4f32aeSBjoern A. Zeeb max(max(ath11k_mac_max_ht_nss(ht_mcs_mask),
8383dd4f32aeSBjoern A. Zeeb ath11k_mac_max_vht_nss(vht_mcs_mask)),
8384dd4f32aeSBjoern A. Zeeb ath11k_mac_max_he_nss(he_mcs_mask)));
8385dd4f32aeSBjoern A. Zeeb
8386dd4f32aeSBjoern A. Zeeb /* If multiple rates across different preambles are given
8387dd4f32aeSBjoern A. Zeeb * we can reconfigure this info with all peers using PEER_ASSOC
8388dd4f32aeSBjoern A. Zeeb * command with the below exception cases.
8389dd4f32aeSBjoern A. Zeeb * - Single VHT Rate : peer_assoc command accommodates only MCS
8390dd4f32aeSBjoern A. Zeeb * range values i.e 0-7, 0-8, 0-9 for VHT. Though mac80211
8391dd4f32aeSBjoern A. Zeeb * mandates passing basic rates along with HT/VHT rates, FW
8392dd4f32aeSBjoern A. Zeeb * doesn't allow switching from VHT to Legacy. Hence instead of
8393dd4f32aeSBjoern A. Zeeb * setting legacy and VHT rates using RATEMASK_CMD vdev cmd,
8394dd4f32aeSBjoern A. Zeeb * we could set this VHT rate as peer fixed rate param, which
8395dd4f32aeSBjoern A. Zeeb * will override FIXED rate and FW rate control algorithm.
8396dd4f32aeSBjoern A. Zeeb * If single VHT rate is passed along with HT rates, we select
8397dd4f32aeSBjoern A. Zeeb * the VHT rate as fixed rate for vht peers.
8398dd4f32aeSBjoern A. Zeeb * - Multiple VHT Rates : When Multiple VHT rates are given,this
8399dd4f32aeSBjoern A. Zeeb * can be set using RATEMASK CMD which uses FW rate-ctl alg.
8400dd4f32aeSBjoern A. Zeeb * TODO: Setting multiple VHT MCS and replacing peer_assoc with
8401dd4f32aeSBjoern A. Zeeb * RATEMASK_CMDID can cover all use cases of setting rates
8402dd4f32aeSBjoern A. Zeeb * across multiple preambles and rates within same type.
8403dd4f32aeSBjoern A. Zeeb * But requires more validation of the command at this point.
8404dd4f32aeSBjoern A. Zeeb */
8405dd4f32aeSBjoern A. Zeeb
8406dd4f32aeSBjoern A. Zeeb num_rates = ath11k_mac_bitrate_mask_num_vht_rates(ar, band,
8407dd4f32aeSBjoern A. Zeeb mask);
8408dd4f32aeSBjoern A. Zeeb
8409dd4f32aeSBjoern A. Zeeb if (!ath11k_mac_vht_mcs_range_present(ar, band, mask) &&
8410dd4f32aeSBjoern A. Zeeb num_rates > 1) {
8411dd4f32aeSBjoern A. Zeeb /* TODO: Handle multiple VHT MCS values setting using
8412dd4f32aeSBjoern A. Zeeb * RATEMASK CMD
8413dd4f32aeSBjoern A. Zeeb */
8414dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab,
8415dd4f32aeSBjoern A. Zeeb "setting %d mcs values in bitrate mask not supported\n",
8416dd4f32aeSBjoern A. Zeeb num_rates);
8417dd4f32aeSBjoern A. Zeeb return -EINVAL;
8418dd4f32aeSBjoern A. Zeeb }
8419dd4f32aeSBjoern A. Zeeb
8420dd4f32aeSBjoern A. Zeeb num_rates = ath11k_mac_bitrate_mask_num_he_rates(ar, band,
8421dd4f32aeSBjoern A. Zeeb mask);
8422dd4f32aeSBjoern A. Zeeb if (num_rates == 1)
8423dd4f32aeSBjoern A. Zeeb he_fixed_rate = true;
8424dd4f32aeSBjoern A. Zeeb
8425dd4f32aeSBjoern A. Zeeb if (!ath11k_mac_he_mcs_range_present(ar, band, mask) &&
8426dd4f32aeSBjoern A. Zeeb num_rates > 1) {
8427dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab,
8428dd4f32aeSBjoern A. Zeeb "Setting more than one HE MCS Value in bitrate mask not supported\n");
8429dd4f32aeSBjoern A. Zeeb return -EINVAL;
8430dd4f32aeSBjoern A. Zeeb }
8431dd4f32aeSBjoern A. Zeeb
8432dd4f32aeSBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
8433dd4f32aeSBjoern A. Zeeb ieee80211_iterate_stations_atomic(ar->hw,
8434dd4f32aeSBjoern A. Zeeb ath11k_mac_disable_peer_fixed_rate,
8435dd4f32aeSBjoern A. Zeeb arvif);
8436dd4f32aeSBjoern A. Zeeb
8437dd4f32aeSBjoern A. Zeeb arvif->bitrate_mask = *mask;
8438dd4f32aeSBjoern A. Zeeb ieee80211_iterate_stations_atomic(ar->hw,
8439dd4f32aeSBjoern A. Zeeb ath11k_mac_set_bitrate_mask_iter,
8440dd4f32aeSBjoern A. Zeeb arvif);
8441dd4f32aeSBjoern A. Zeeb
8442dd4f32aeSBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
8443dd4f32aeSBjoern A. Zeeb }
8444dd4f32aeSBjoern A. Zeeb
8445dd4f32aeSBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
8446dd4f32aeSBjoern A. Zeeb
8447dd4f32aeSBjoern A. Zeeb ret = ath11k_mac_set_rate_params(arvif, rate, nss, sgi, ldpc, he_gi,
8448dd4f32aeSBjoern A. Zeeb he_ltf, he_fixed_rate);
8449dd4f32aeSBjoern A. Zeeb if (ret) {
8450dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to set rate params on vdev %i: %d\n",
8451dd4f32aeSBjoern A. Zeeb arvif->vdev_id, ret);
8452dd4f32aeSBjoern A. Zeeb }
8453dd4f32aeSBjoern A. Zeeb
8454dd4f32aeSBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
8455dd4f32aeSBjoern A. Zeeb
8456dd4f32aeSBjoern A. Zeeb return ret;
8457dd4f32aeSBjoern A. Zeeb }
8458dd4f32aeSBjoern A. Zeeb
8459dd4f32aeSBjoern A. Zeeb static void
ath11k_mac_op_reconfig_complete(struct ieee80211_hw * hw,enum ieee80211_reconfig_type reconfig_type)8460dd4f32aeSBjoern A. Zeeb ath11k_mac_op_reconfig_complete(struct ieee80211_hw *hw,
8461dd4f32aeSBjoern A. Zeeb enum ieee80211_reconfig_type reconfig_type)
8462dd4f32aeSBjoern A. Zeeb {
8463dd4f32aeSBjoern A. Zeeb struct ath11k *ar = hw->priv;
846428348caeSBjoern A. Zeeb struct ath11k_base *ab = ar->ab;
846528348caeSBjoern A. Zeeb int recovery_count;
846628348caeSBjoern A. Zeeb struct ath11k_vif *arvif;
8467dd4f32aeSBjoern A. Zeeb
8468dd4f32aeSBjoern A. Zeeb if (reconfig_type != IEEE80211_RECONFIG_TYPE_RESTART)
8469dd4f32aeSBjoern A. Zeeb return;
8470dd4f32aeSBjoern A. Zeeb
8471dd4f32aeSBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
8472dd4f32aeSBjoern A. Zeeb
8473dd4f32aeSBjoern A. Zeeb if (ar->state == ATH11K_STATE_RESTARTED) {
8474dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "pdev %d successfully recovered\n",
8475dd4f32aeSBjoern A. Zeeb ar->pdev->pdev_id);
8476dd4f32aeSBjoern A. Zeeb ar->state = ATH11K_STATE_ON;
8477dd4f32aeSBjoern A. Zeeb ieee80211_wake_queues(ar->hw);
847828348caeSBjoern A. Zeeb
847928348caeSBjoern A. Zeeb if (ar->ab->hw_params.current_cc_support &&
848028348caeSBjoern A. Zeeb ar->alpha2[0] != 0 && ar->alpha2[1] != 0) {
848128348caeSBjoern A. Zeeb struct wmi_set_current_country_params set_current_param = {};
848228348caeSBjoern A. Zeeb
848328348caeSBjoern A. Zeeb memcpy(&set_current_param.alpha2, ar->alpha2, 2);
848428348caeSBjoern A. Zeeb ath11k_wmi_send_set_current_country_cmd(ar, &set_current_param);
848528348caeSBjoern A. Zeeb }
848628348caeSBjoern A. Zeeb
848728348caeSBjoern A. Zeeb if (ab->is_reset) {
848828348caeSBjoern A. Zeeb recovery_count = atomic_inc_return(&ab->recovery_count);
848928348caeSBjoern A. Zeeb ath11k_dbg(ab, ATH11K_DBG_BOOT,
849028348caeSBjoern A. Zeeb "recovery count %d\n", recovery_count);
849128348caeSBjoern A. Zeeb /* When there are multiple radios in an SOC,
849228348caeSBjoern A. Zeeb * the recovery has to be done for each radio
849328348caeSBjoern A. Zeeb */
849428348caeSBjoern A. Zeeb if (recovery_count == ab->num_radios) {
849528348caeSBjoern A. Zeeb atomic_dec(&ab->reset_count);
849628348caeSBjoern A. Zeeb complete(&ab->reset_complete);
849728348caeSBjoern A. Zeeb ab->is_reset = false;
849828348caeSBjoern A. Zeeb atomic_set(&ab->fail_cont_count, 0);
849928348caeSBjoern A. Zeeb ath11k_dbg(ab, ATH11K_DBG_BOOT, "reset success\n");
850028348caeSBjoern A. Zeeb }
850128348caeSBjoern A. Zeeb }
850228348caeSBjoern A. Zeeb if (ar->ab->hw_params.support_fw_mac_sequence) {
850328348caeSBjoern A. Zeeb list_for_each_entry(arvif, &ar->arvifs, list) {
850428348caeSBjoern A. Zeeb if (arvif->is_up && arvif->vdev_type == WMI_VDEV_TYPE_STA)
850528348caeSBjoern A. Zeeb ieee80211_hw_restart_disconnect(arvif->vif);
850628348caeSBjoern A. Zeeb }
850728348caeSBjoern A. Zeeb }
8508dd4f32aeSBjoern A. Zeeb }
8509dd4f32aeSBjoern A. Zeeb
8510dd4f32aeSBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
8511dd4f32aeSBjoern A. Zeeb }
8512dd4f32aeSBjoern A. Zeeb
8513dd4f32aeSBjoern A. Zeeb static void
ath11k_mac_update_bss_chan_survey(struct ath11k * ar,struct ieee80211_channel * channel)8514dd4f32aeSBjoern A. Zeeb ath11k_mac_update_bss_chan_survey(struct ath11k *ar,
8515dd4f32aeSBjoern A. Zeeb struct ieee80211_channel *channel)
8516dd4f32aeSBjoern A. Zeeb {
8517dd4f32aeSBjoern A. Zeeb int ret;
8518dd4f32aeSBjoern A. Zeeb enum wmi_bss_chan_info_req_type type = WMI_BSS_SURVEY_REQ_TYPE_READ;
8519dd4f32aeSBjoern A. Zeeb
8520dd4f32aeSBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
8521dd4f32aeSBjoern A. Zeeb
8522dd4f32aeSBjoern A. Zeeb if (!test_bit(WMI_TLV_SERVICE_BSS_CHANNEL_INFO_64, ar->ab->wmi_ab.svc_map) ||
8523dd4f32aeSBjoern A. Zeeb ar->rx_channel != channel)
8524dd4f32aeSBjoern A. Zeeb return;
8525dd4f32aeSBjoern A. Zeeb
8526dd4f32aeSBjoern A. Zeeb if (ar->scan.state != ATH11K_SCAN_IDLE) {
8527dd4f32aeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
8528dd4f32aeSBjoern A. Zeeb "ignoring bss chan info req while scanning..\n");
8529dd4f32aeSBjoern A. Zeeb return;
8530dd4f32aeSBjoern A. Zeeb }
8531dd4f32aeSBjoern A. Zeeb
8532dd4f32aeSBjoern A. Zeeb reinit_completion(&ar->bss_survey_done);
8533dd4f32aeSBjoern A. Zeeb
8534dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_pdev_bss_chan_info_request(ar, type);
8535dd4f32aeSBjoern A. Zeeb if (ret) {
8536dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to send pdev bss chan info request\n");
8537dd4f32aeSBjoern A. Zeeb return;
8538dd4f32aeSBjoern A. Zeeb }
8539dd4f32aeSBjoern A. Zeeb
8540dd4f32aeSBjoern A. Zeeb ret = wait_for_completion_timeout(&ar->bss_survey_done, 3 * HZ);
8541dd4f32aeSBjoern A. Zeeb if (ret == 0)
8542dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "bss channel survey timed out\n");
8543dd4f32aeSBjoern A. Zeeb }
8544dd4f32aeSBjoern A. Zeeb
ath11k_mac_op_get_survey(struct ieee80211_hw * hw,int idx,struct survey_info * survey)8545dd4f32aeSBjoern A. Zeeb static int ath11k_mac_op_get_survey(struct ieee80211_hw *hw, int idx,
8546dd4f32aeSBjoern A. Zeeb struct survey_info *survey)
8547dd4f32aeSBjoern A. Zeeb {
8548dd4f32aeSBjoern A. Zeeb struct ath11k *ar = hw->priv;
8549dd4f32aeSBjoern A. Zeeb struct ieee80211_supported_band *sband;
8550dd4f32aeSBjoern A. Zeeb struct survey_info *ar_survey;
8551dd4f32aeSBjoern A. Zeeb int ret = 0;
8552dd4f32aeSBjoern A. Zeeb
8553dd4f32aeSBjoern A. Zeeb if (idx >= ATH11K_NUM_CHANS)
8554dd4f32aeSBjoern A. Zeeb return -ENOENT;
8555dd4f32aeSBjoern A. Zeeb
8556dd4f32aeSBjoern A. Zeeb ar_survey = &ar->survey[idx];
8557dd4f32aeSBjoern A. Zeeb
8558dd4f32aeSBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
8559dd4f32aeSBjoern A. Zeeb
8560dd4f32aeSBjoern A. Zeeb sband = hw->wiphy->bands[NL80211_BAND_2GHZ];
8561dd4f32aeSBjoern A. Zeeb if (sband && idx >= sband->n_channels) {
8562dd4f32aeSBjoern A. Zeeb idx -= sband->n_channels;
8563dd4f32aeSBjoern A. Zeeb sband = NULL;
8564dd4f32aeSBjoern A. Zeeb }
8565dd4f32aeSBjoern A. Zeeb
8566dd4f32aeSBjoern A. Zeeb if (!sband)
8567dd4f32aeSBjoern A. Zeeb sband = hw->wiphy->bands[NL80211_BAND_5GHZ];
8568dd4f32aeSBjoern A. Zeeb if (sband && idx >= sband->n_channels) {
8569dd4f32aeSBjoern A. Zeeb idx -= sband->n_channels;
8570dd4f32aeSBjoern A. Zeeb sband = NULL;
8571dd4f32aeSBjoern A. Zeeb }
8572dd4f32aeSBjoern A. Zeeb
8573dd4f32aeSBjoern A. Zeeb if (!sband)
8574dd4f32aeSBjoern A. Zeeb sband = hw->wiphy->bands[NL80211_BAND_6GHZ];
8575dd4f32aeSBjoern A. Zeeb if (!sband || idx >= sband->n_channels) {
8576dd4f32aeSBjoern A. Zeeb ret = -ENOENT;
8577dd4f32aeSBjoern A. Zeeb goto exit;
8578dd4f32aeSBjoern A. Zeeb }
8579dd4f32aeSBjoern A. Zeeb
8580dd4f32aeSBjoern A. Zeeb ath11k_mac_update_bss_chan_survey(ar, &sband->channels[idx]);
8581dd4f32aeSBjoern A. Zeeb
8582dd4f32aeSBjoern A. Zeeb spin_lock_bh(&ar->data_lock);
8583dd4f32aeSBjoern A. Zeeb memcpy(survey, ar_survey, sizeof(*survey));
8584dd4f32aeSBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
8585dd4f32aeSBjoern A. Zeeb
8586dd4f32aeSBjoern A. Zeeb survey->channel = &sband->channels[idx];
8587dd4f32aeSBjoern A. Zeeb
8588dd4f32aeSBjoern A. Zeeb if (ar->rx_channel == survey->channel)
8589dd4f32aeSBjoern A. Zeeb survey->filled |= SURVEY_INFO_IN_USE;
8590dd4f32aeSBjoern A. Zeeb
8591dd4f32aeSBjoern A. Zeeb exit:
8592dd4f32aeSBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
8593dd4f32aeSBjoern A. Zeeb return ret;
8594dd4f32aeSBjoern A. Zeeb }
8595dd4f32aeSBjoern A. Zeeb
ath11k_mac_put_chain_rssi(struct station_info * sinfo,struct ath11k_sta * arsta,char * pre,bool clear)8596dd4f32aeSBjoern A. Zeeb static void ath11k_mac_put_chain_rssi(struct station_info *sinfo,
8597dd4f32aeSBjoern A. Zeeb struct ath11k_sta *arsta,
8598dd4f32aeSBjoern A. Zeeb char *pre,
8599dd4f32aeSBjoern A. Zeeb bool clear)
8600dd4f32aeSBjoern A. Zeeb {
8601dd4f32aeSBjoern A. Zeeb struct ath11k *ar = arsta->arvif->ar;
8602dd4f32aeSBjoern A. Zeeb int i;
8603dd4f32aeSBjoern A. Zeeb s8 rssi;
8604dd4f32aeSBjoern A. Zeeb
8605dd4f32aeSBjoern A. Zeeb for (i = 0; i < ARRAY_SIZE(sinfo->chain_signal); i++) {
8606dd4f32aeSBjoern A. Zeeb sinfo->chains &= ~BIT(i);
8607dd4f32aeSBjoern A. Zeeb rssi = arsta->chain_signal[i];
8608dd4f32aeSBjoern A. Zeeb if (clear)
8609dd4f32aeSBjoern A. Zeeb arsta->chain_signal[i] = ATH11K_INVALID_RSSI_FULL;
8610dd4f32aeSBjoern A. Zeeb
8611dd4f32aeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
861228348caeSBjoern A. Zeeb "sta statistics %s rssi[%d] %d\n", pre, i, rssi);
8613dd4f32aeSBjoern A. Zeeb
8614dd4f32aeSBjoern A. Zeeb if (rssi != ATH11K_DEFAULT_NOISE_FLOOR &&
8615dd4f32aeSBjoern A. Zeeb rssi != ATH11K_INVALID_RSSI_FULL &&
8616dd4f32aeSBjoern A. Zeeb rssi != ATH11K_INVALID_RSSI_EMPTY &&
8617dd4f32aeSBjoern A. Zeeb rssi != 0) {
8618dd4f32aeSBjoern A. Zeeb sinfo->chain_signal[i] = rssi;
8619dd4f32aeSBjoern A. Zeeb sinfo->chains |= BIT(i);
8620dd4f32aeSBjoern A. Zeeb sinfo->filled |= BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL);
8621dd4f32aeSBjoern A. Zeeb }
8622dd4f32aeSBjoern A. Zeeb }
8623dd4f32aeSBjoern A. Zeeb }
8624dd4f32aeSBjoern A. Zeeb
ath11k_mac_op_sta_statistics(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct station_info * sinfo)8625dd4f32aeSBjoern A. Zeeb static void ath11k_mac_op_sta_statistics(struct ieee80211_hw *hw,
8626dd4f32aeSBjoern A. Zeeb struct ieee80211_vif *vif,
8627dd4f32aeSBjoern A. Zeeb struct ieee80211_sta *sta,
8628dd4f32aeSBjoern A. Zeeb struct station_info *sinfo)
8629dd4f32aeSBjoern A. Zeeb {
8630dd4f32aeSBjoern A. Zeeb struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
8631dd4f32aeSBjoern A. Zeeb struct ath11k *ar = arsta->arvif->ar;
8632dd4f32aeSBjoern A. Zeeb s8 signal;
8633dd4f32aeSBjoern A. Zeeb bool db2dbm = test_bit(WMI_TLV_SERVICE_HW_DB2DBM_CONVERSION_SUPPORT,
8634dd4f32aeSBjoern A. Zeeb ar->ab->wmi_ab.svc_map);
8635dd4f32aeSBjoern A. Zeeb
8636dd4f32aeSBjoern A. Zeeb sinfo->rx_duration = arsta->rx_duration;
8637dd4f32aeSBjoern A. Zeeb sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_DURATION);
8638dd4f32aeSBjoern A. Zeeb
8639dd4f32aeSBjoern A. Zeeb sinfo->tx_duration = arsta->tx_duration;
8640dd4f32aeSBjoern A. Zeeb sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_DURATION);
8641dd4f32aeSBjoern A. Zeeb
8642dd4f32aeSBjoern A. Zeeb if (arsta->txrate.legacy || arsta->txrate.nss) {
8643dd4f32aeSBjoern A. Zeeb if (arsta->txrate.legacy) {
8644dd4f32aeSBjoern A. Zeeb sinfo->txrate.legacy = arsta->txrate.legacy;
8645dd4f32aeSBjoern A. Zeeb } else {
8646dd4f32aeSBjoern A. Zeeb sinfo->txrate.mcs = arsta->txrate.mcs;
8647dd4f32aeSBjoern A. Zeeb sinfo->txrate.nss = arsta->txrate.nss;
8648dd4f32aeSBjoern A. Zeeb sinfo->txrate.bw = arsta->txrate.bw;
8649dd4f32aeSBjoern A. Zeeb sinfo->txrate.he_gi = arsta->txrate.he_gi;
8650dd4f32aeSBjoern A. Zeeb sinfo->txrate.he_dcm = arsta->txrate.he_dcm;
8651dd4f32aeSBjoern A. Zeeb sinfo->txrate.he_ru_alloc = arsta->txrate.he_ru_alloc;
8652dd4f32aeSBjoern A. Zeeb }
8653dd4f32aeSBjoern A. Zeeb sinfo->txrate.flags = arsta->txrate.flags;
8654dd4f32aeSBjoern A. Zeeb sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
8655dd4f32aeSBjoern A. Zeeb }
8656dd4f32aeSBjoern A. Zeeb
8657dd4f32aeSBjoern A. Zeeb ath11k_mac_put_chain_rssi(sinfo, arsta, "ppdu", false);
8658dd4f32aeSBjoern A. Zeeb
8659dd4f32aeSBjoern A. Zeeb if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL)) &&
8660dd4f32aeSBjoern A. Zeeb arsta->arvif->vdev_type == WMI_VDEV_TYPE_STA &&
8661dd4f32aeSBjoern A. Zeeb ar->ab->hw_params.supports_rssi_stats &&
8662dd4f32aeSBjoern A. Zeeb !ath11k_debugfs_get_fw_stats(ar, ar->pdev->pdev_id, 0,
8663dd4f32aeSBjoern A. Zeeb WMI_REQUEST_RSSI_PER_CHAIN_STAT)) {
8664dd4f32aeSBjoern A. Zeeb ath11k_mac_put_chain_rssi(sinfo, arsta, "fw stats", true);
8665dd4f32aeSBjoern A. Zeeb }
8666dd4f32aeSBjoern A. Zeeb
8667dd4f32aeSBjoern A. Zeeb signal = arsta->rssi_comb;
8668dd4f32aeSBjoern A. Zeeb if (!signal &&
8669dd4f32aeSBjoern A. Zeeb arsta->arvif->vdev_type == WMI_VDEV_TYPE_STA &&
8670dd4f32aeSBjoern A. Zeeb ar->ab->hw_params.supports_rssi_stats &&
8671dd4f32aeSBjoern A. Zeeb !(ath11k_debugfs_get_fw_stats(ar, ar->pdev->pdev_id, 0,
8672dd4f32aeSBjoern A. Zeeb WMI_REQUEST_VDEV_STAT)))
8673dd4f32aeSBjoern A. Zeeb signal = arsta->rssi_beacon;
8674dd4f32aeSBjoern A. Zeeb
8675dd4f32aeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
867628348caeSBjoern A. Zeeb "sta statistics db2dbm %u rssi comb %d rssi beacon %d\n",
8677dd4f32aeSBjoern A. Zeeb db2dbm, arsta->rssi_comb, arsta->rssi_beacon);
8678dd4f32aeSBjoern A. Zeeb
8679dd4f32aeSBjoern A. Zeeb if (signal) {
8680dd4f32aeSBjoern A. Zeeb sinfo->signal = db2dbm ? signal : signal + ATH11K_DEFAULT_NOISE_FLOOR;
8681dd4f32aeSBjoern A. Zeeb sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL);
8682dd4f32aeSBjoern A. Zeeb }
868328348caeSBjoern A. Zeeb
868428348caeSBjoern A. Zeeb sinfo->signal_avg = ewma_avg_rssi_read(&arsta->avg_rssi) +
868528348caeSBjoern A. Zeeb ATH11K_DEFAULT_NOISE_FLOOR;
868628348caeSBjoern A. Zeeb sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG);
868728348caeSBjoern A. Zeeb }
868828348caeSBjoern A. Zeeb
868928348caeSBjoern A. Zeeb #if IS_ENABLED(CONFIG_IPV6)
ath11k_generate_ns_mc_addr(struct ath11k * ar,struct ath11k_arp_ns_offload * offload)869028348caeSBjoern A. Zeeb static void ath11k_generate_ns_mc_addr(struct ath11k *ar,
869128348caeSBjoern A. Zeeb struct ath11k_arp_ns_offload *offload)
869228348caeSBjoern A. Zeeb {
869328348caeSBjoern A. Zeeb int i;
869428348caeSBjoern A. Zeeb
869528348caeSBjoern A. Zeeb for (i = 0; i < offload->ipv6_count; i++) {
869628348caeSBjoern A. Zeeb offload->self_ipv6_addr[i][0] = 0xff;
869728348caeSBjoern A. Zeeb offload->self_ipv6_addr[i][1] = 0x02;
869828348caeSBjoern A. Zeeb offload->self_ipv6_addr[i][11] = 0x01;
869928348caeSBjoern A. Zeeb offload->self_ipv6_addr[i][12] = 0xff;
870028348caeSBjoern A. Zeeb offload->self_ipv6_addr[i][13] =
870128348caeSBjoern A. Zeeb offload->ipv6_addr[i][13];
870228348caeSBjoern A. Zeeb offload->self_ipv6_addr[i][14] =
870328348caeSBjoern A. Zeeb offload->ipv6_addr[i][14];
870428348caeSBjoern A. Zeeb offload->self_ipv6_addr[i][15] =
870528348caeSBjoern A. Zeeb offload->ipv6_addr[i][15];
870628348caeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "NS solicited addr %pI6\n",
870728348caeSBjoern A. Zeeb offload->self_ipv6_addr[i]);
870828348caeSBjoern A. Zeeb }
870928348caeSBjoern A. Zeeb }
871028348caeSBjoern A. Zeeb
ath11k_mac_op_ipv6_changed(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct inet6_dev * idev)871128348caeSBjoern A. Zeeb static void ath11k_mac_op_ipv6_changed(struct ieee80211_hw *hw,
871228348caeSBjoern A. Zeeb struct ieee80211_vif *vif,
871328348caeSBjoern A. Zeeb struct inet6_dev *idev)
871428348caeSBjoern A. Zeeb {
871528348caeSBjoern A. Zeeb struct ath11k *ar = hw->priv;
871628348caeSBjoern A. Zeeb struct ath11k_arp_ns_offload *offload;
871728348caeSBjoern A. Zeeb struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
871828348caeSBjoern A. Zeeb struct inet6_ifaddr *ifa6;
871928348caeSBjoern A. Zeeb struct ifacaddr6 *ifaca6;
872028348caeSBjoern A. Zeeb struct list_head *p;
872128348caeSBjoern A. Zeeb u32 count, scope;
872228348caeSBjoern A. Zeeb
872328348caeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "op ipv6 changed\n");
872428348caeSBjoern A. Zeeb
872528348caeSBjoern A. Zeeb offload = &arvif->arp_ns_offload;
872628348caeSBjoern A. Zeeb count = 0;
872728348caeSBjoern A. Zeeb
872828348caeSBjoern A. Zeeb read_lock_bh(&idev->lock);
872928348caeSBjoern A. Zeeb
873028348caeSBjoern A. Zeeb memset(offload->ipv6_addr, 0, sizeof(offload->ipv6_addr));
873128348caeSBjoern A. Zeeb memset(offload->self_ipv6_addr, 0, sizeof(offload->self_ipv6_addr));
873228348caeSBjoern A. Zeeb memcpy(offload->mac_addr, vif->addr, ETH_ALEN);
873328348caeSBjoern A. Zeeb
873428348caeSBjoern A. Zeeb /* get unicast address */
873528348caeSBjoern A. Zeeb list_for_each(p, &idev->addr_list) {
873628348caeSBjoern A. Zeeb if (count >= ATH11K_IPV6_MAX_COUNT)
873728348caeSBjoern A. Zeeb goto generate;
873828348caeSBjoern A. Zeeb
873928348caeSBjoern A. Zeeb ifa6 = list_entry(p, struct inet6_ifaddr, if_list);
874028348caeSBjoern A. Zeeb if (ifa6->flags & IFA_F_DADFAILED)
874128348caeSBjoern A. Zeeb continue;
874228348caeSBjoern A. Zeeb scope = ipv6_addr_src_scope(&ifa6->addr);
874328348caeSBjoern A. Zeeb if (scope == IPV6_ADDR_SCOPE_LINKLOCAL ||
874428348caeSBjoern A. Zeeb scope == IPV6_ADDR_SCOPE_GLOBAL) {
874528348caeSBjoern A. Zeeb memcpy(offload->ipv6_addr[count], &ifa6->addr.s6_addr,
874628348caeSBjoern A. Zeeb sizeof(ifa6->addr.s6_addr));
874728348caeSBjoern A. Zeeb offload->ipv6_type[count] = ATH11K_IPV6_UC_TYPE;
874828348caeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "count %d ipv6 uc %pI6 scope %d\n",
874928348caeSBjoern A. Zeeb count, offload->ipv6_addr[count],
875028348caeSBjoern A. Zeeb scope);
875128348caeSBjoern A. Zeeb count++;
875228348caeSBjoern A. Zeeb } else {
875328348caeSBjoern A. Zeeb ath11k_warn(ar->ab, "Unsupported ipv6 scope: %d\n", scope);
875428348caeSBjoern A. Zeeb }
875528348caeSBjoern A. Zeeb }
875628348caeSBjoern A. Zeeb
875728348caeSBjoern A. Zeeb /* get anycast address */
875828348caeSBjoern A. Zeeb for (ifaca6 = idev->ac_list; ifaca6; ifaca6 = ifaca6->aca_next) {
875928348caeSBjoern A. Zeeb if (count >= ATH11K_IPV6_MAX_COUNT)
876028348caeSBjoern A. Zeeb goto generate;
876128348caeSBjoern A. Zeeb
876228348caeSBjoern A. Zeeb scope = ipv6_addr_src_scope(&ifaca6->aca_addr);
876328348caeSBjoern A. Zeeb if (scope == IPV6_ADDR_SCOPE_LINKLOCAL ||
876428348caeSBjoern A. Zeeb scope == IPV6_ADDR_SCOPE_GLOBAL) {
876528348caeSBjoern A. Zeeb memcpy(offload->ipv6_addr[count], &ifaca6->aca_addr,
876628348caeSBjoern A. Zeeb sizeof(ifaca6->aca_addr));
876728348caeSBjoern A. Zeeb offload->ipv6_type[count] = ATH11K_IPV6_AC_TYPE;
876828348caeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "count %d ipv6 ac %pI6 scope %d\n",
876928348caeSBjoern A. Zeeb count, offload->ipv6_addr[count],
877028348caeSBjoern A. Zeeb scope);
877128348caeSBjoern A. Zeeb count++;
877228348caeSBjoern A. Zeeb } else {
877328348caeSBjoern A. Zeeb ath11k_warn(ar->ab, "Unsupported ipv scope: %d\n", scope);
877428348caeSBjoern A. Zeeb }
877528348caeSBjoern A. Zeeb }
877628348caeSBjoern A. Zeeb
877728348caeSBjoern A. Zeeb generate:
877828348caeSBjoern A. Zeeb offload->ipv6_count = count;
877928348caeSBjoern A. Zeeb read_unlock_bh(&idev->lock);
878028348caeSBjoern A. Zeeb
878128348caeSBjoern A. Zeeb /* generate ns multicast address */
878228348caeSBjoern A. Zeeb ath11k_generate_ns_mc_addr(ar, offload);
878328348caeSBjoern A. Zeeb }
878428348caeSBjoern A. Zeeb #endif
878528348caeSBjoern A. Zeeb
ath11k_mac_op_set_rekey_data(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct cfg80211_gtk_rekey_data * data)878628348caeSBjoern A. Zeeb static void ath11k_mac_op_set_rekey_data(struct ieee80211_hw *hw,
878728348caeSBjoern A. Zeeb struct ieee80211_vif *vif,
878828348caeSBjoern A. Zeeb struct cfg80211_gtk_rekey_data *data)
878928348caeSBjoern A. Zeeb {
879028348caeSBjoern A. Zeeb struct ath11k *ar = hw->priv;
879128348caeSBjoern A. Zeeb struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
879228348caeSBjoern A. Zeeb struct ath11k_rekey_data *rekey_data = &arvif->rekey_data;
879328348caeSBjoern A. Zeeb
879428348caeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "set rekey data vdev %d\n",
879528348caeSBjoern A. Zeeb arvif->vdev_id);
879628348caeSBjoern A. Zeeb
879728348caeSBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
879828348caeSBjoern A. Zeeb
879928348caeSBjoern A. Zeeb memcpy(rekey_data->kck, data->kck, NL80211_KCK_LEN);
880028348caeSBjoern A. Zeeb memcpy(rekey_data->kek, data->kek, NL80211_KEK_LEN);
880128348caeSBjoern A. Zeeb
880228348caeSBjoern A. Zeeb /* The supplicant works on big-endian, the firmware expects it on
880328348caeSBjoern A. Zeeb * little endian.
880428348caeSBjoern A. Zeeb */
880528348caeSBjoern A. Zeeb rekey_data->replay_ctr = get_unaligned_be64(data->replay_ctr);
880628348caeSBjoern A. Zeeb
880728348caeSBjoern A. Zeeb arvif->rekey_data.enable_offload = true;
880828348caeSBjoern A. Zeeb
880928348caeSBjoern A. Zeeb ath11k_dbg_dump(ar->ab, ATH11K_DBG_MAC, "kck", NULL,
881028348caeSBjoern A. Zeeb rekey_data->kck, NL80211_KCK_LEN);
881128348caeSBjoern A. Zeeb ath11k_dbg_dump(ar->ab, ATH11K_DBG_MAC, "kek", NULL,
881228348caeSBjoern A. Zeeb rekey_data->kck, NL80211_KEK_LEN);
881328348caeSBjoern A. Zeeb ath11k_dbg_dump(ar->ab, ATH11K_DBG_MAC, "replay ctr", NULL,
881428348caeSBjoern A. Zeeb &rekey_data->replay_ctr, sizeof(rekey_data->replay_ctr));
881528348caeSBjoern A. Zeeb
881628348caeSBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
881728348caeSBjoern A. Zeeb }
881828348caeSBjoern A. Zeeb
ath11k_mac_op_set_bios_sar_specs(struct ieee80211_hw * hw,const struct cfg80211_sar_specs * sar)881928348caeSBjoern A. Zeeb static int ath11k_mac_op_set_bios_sar_specs(struct ieee80211_hw *hw,
882028348caeSBjoern A. Zeeb const struct cfg80211_sar_specs *sar)
882128348caeSBjoern A. Zeeb {
882228348caeSBjoern A. Zeeb struct ath11k *ar = hw->priv;
882328348caeSBjoern A. Zeeb const struct cfg80211_sar_sub_specs *sspec;
882428348caeSBjoern A. Zeeb int ret, index;
882528348caeSBjoern A. Zeeb u8 *sar_tbl;
882628348caeSBjoern A. Zeeb u32 i;
882728348caeSBjoern A. Zeeb
882828348caeSBjoern A. Zeeb if (!sar || sar->type != NL80211_SAR_TYPE_POWER ||
882928348caeSBjoern A. Zeeb sar->num_sub_specs == 0)
883028348caeSBjoern A. Zeeb return -EINVAL;
883128348caeSBjoern A. Zeeb
883228348caeSBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
883328348caeSBjoern A. Zeeb
883428348caeSBjoern A. Zeeb if (!test_bit(WMI_TLV_SERVICE_BIOS_SAR_SUPPORT, ar->ab->wmi_ab.svc_map) ||
883528348caeSBjoern A. Zeeb !ar->ab->hw_params.bios_sar_capa) {
883628348caeSBjoern A. Zeeb ret = -EOPNOTSUPP;
883728348caeSBjoern A. Zeeb goto exit;
883828348caeSBjoern A. Zeeb }
883928348caeSBjoern A. Zeeb
884028348caeSBjoern A. Zeeb ret = ath11k_wmi_pdev_set_bios_geo_table_param(ar);
884128348caeSBjoern A. Zeeb if (ret) {
884228348caeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to set geo table: %d\n", ret);
884328348caeSBjoern A. Zeeb goto exit;
884428348caeSBjoern A. Zeeb }
884528348caeSBjoern A. Zeeb
884628348caeSBjoern A. Zeeb sar_tbl = kzalloc(BIOS_SAR_TABLE_LEN, GFP_KERNEL);
884728348caeSBjoern A. Zeeb if (!sar_tbl) {
884828348caeSBjoern A. Zeeb ret = -ENOMEM;
884928348caeSBjoern A. Zeeb goto exit;
885028348caeSBjoern A. Zeeb }
885128348caeSBjoern A. Zeeb
885228348caeSBjoern A. Zeeb sspec = sar->sub_specs;
885328348caeSBjoern A. Zeeb for (i = 0; i < sar->num_sub_specs; i++) {
885428348caeSBjoern A. Zeeb if (sspec->freq_range_index >= (BIOS_SAR_TABLE_LEN >> 1)) {
885528348caeSBjoern A. Zeeb ath11k_warn(ar->ab, "Ignore bad frequency index %u, max allowed %u\n",
885628348caeSBjoern A. Zeeb sspec->freq_range_index, BIOS_SAR_TABLE_LEN >> 1);
885728348caeSBjoern A. Zeeb continue;
885828348caeSBjoern A. Zeeb }
885928348caeSBjoern A. Zeeb
886028348caeSBjoern A. Zeeb /* chain0 and chain1 share same power setting */
886128348caeSBjoern A. Zeeb sar_tbl[sspec->freq_range_index] = sspec->power;
886228348caeSBjoern A. Zeeb index = sspec->freq_range_index + (BIOS_SAR_TABLE_LEN >> 1);
886328348caeSBjoern A. Zeeb sar_tbl[index] = sspec->power;
886428348caeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "sar tbl[%d] = %d\n",
886528348caeSBjoern A. Zeeb sspec->freq_range_index, sar_tbl[sspec->freq_range_index]);
886628348caeSBjoern A. Zeeb sspec++;
886728348caeSBjoern A. Zeeb }
886828348caeSBjoern A. Zeeb
886928348caeSBjoern A. Zeeb ret = ath11k_wmi_pdev_set_bios_sar_table_param(ar, sar_tbl);
887028348caeSBjoern A. Zeeb if (ret)
887128348caeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to set sar power: %d", ret);
887228348caeSBjoern A. Zeeb
887328348caeSBjoern A. Zeeb kfree(sar_tbl);
887428348caeSBjoern A. Zeeb exit:
887528348caeSBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
887628348caeSBjoern A. Zeeb
887728348caeSBjoern A. Zeeb return ret;
887828348caeSBjoern A. Zeeb }
887928348caeSBjoern A. Zeeb
ath11k_mac_op_cancel_remain_on_channel(struct ieee80211_hw * hw,struct ieee80211_vif * vif)888028348caeSBjoern A. Zeeb static int ath11k_mac_op_cancel_remain_on_channel(struct ieee80211_hw *hw,
888128348caeSBjoern A. Zeeb struct ieee80211_vif *vif)
888228348caeSBjoern A. Zeeb {
888328348caeSBjoern A. Zeeb struct ath11k *ar = hw->priv;
888428348caeSBjoern A. Zeeb
888528348caeSBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
888628348caeSBjoern A. Zeeb
888728348caeSBjoern A. Zeeb spin_lock_bh(&ar->data_lock);
888828348caeSBjoern A. Zeeb ar->scan.roc_notify = false;
888928348caeSBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
889028348caeSBjoern A. Zeeb
889128348caeSBjoern A. Zeeb ath11k_scan_abort(ar);
889228348caeSBjoern A. Zeeb
889328348caeSBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
889428348caeSBjoern A. Zeeb
889528348caeSBjoern A. Zeeb cancel_delayed_work_sync(&ar->scan.timeout);
889628348caeSBjoern A. Zeeb
889728348caeSBjoern A. Zeeb return 0;
889828348caeSBjoern A. Zeeb }
889928348caeSBjoern A. Zeeb
ath11k_mac_op_remain_on_channel(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_channel * chan,int duration,enum ieee80211_roc_type type)890028348caeSBjoern A. Zeeb static int ath11k_mac_op_remain_on_channel(struct ieee80211_hw *hw,
890128348caeSBjoern A. Zeeb struct ieee80211_vif *vif,
890228348caeSBjoern A. Zeeb struct ieee80211_channel *chan,
890328348caeSBjoern A. Zeeb int duration,
890428348caeSBjoern A. Zeeb enum ieee80211_roc_type type)
890528348caeSBjoern A. Zeeb {
890628348caeSBjoern A. Zeeb struct ath11k *ar = hw->priv;
890728348caeSBjoern A. Zeeb struct ath11k_vif *arvif = (void *)vif->drv_priv;
890828348caeSBjoern A. Zeeb struct scan_req_params arg;
890928348caeSBjoern A. Zeeb int ret;
891028348caeSBjoern A. Zeeb u32 scan_time_msec;
891128348caeSBjoern A. Zeeb
891228348caeSBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
891328348caeSBjoern A. Zeeb
891428348caeSBjoern A. Zeeb spin_lock_bh(&ar->data_lock);
891528348caeSBjoern A. Zeeb switch (ar->scan.state) {
891628348caeSBjoern A. Zeeb case ATH11K_SCAN_IDLE:
891728348caeSBjoern A. Zeeb reinit_completion(&ar->scan.started);
891828348caeSBjoern A. Zeeb reinit_completion(&ar->scan.completed);
891928348caeSBjoern A. Zeeb reinit_completion(&ar->scan.on_channel);
892028348caeSBjoern A. Zeeb ar->scan.state = ATH11K_SCAN_STARTING;
892128348caeSBjoern A. Zeeb ar->scan.is_roc = true;
892228348caeSBjoern A. Zeeb ar->scan.vdev_id = arvif->vdev_id;
892328348caeSBjoern A. Zeeb ar->scan.roc_freq = chan->center_freq;
892428348caeSBjoern A. Zeeb ar->scan.roc_notify = true;
892528348caeSBjoern A. Zeeb ret = 0;
892628348caeSBjoern A. Zeeb break;
892728348caeSBjoern A. Zeeb case ATH11K_SCAN_STARTING:
892828348caeSBjoern A. Zeeb case ATH11K_SCAN_RUNNING:
892928348caeSBjoern A. Zeeb case ATH11K_SCAN_ABORTING:
893028348caeSBjoern A. Zeeb ret = -EBUSY;
893128348caeSBjoern A. Zeeb break;
893228348caeSBjoern A. Zeeb }
893328348caeSBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
893428348caeSBjoern A. Zeeb
893528348caeSBjoern A. Zeeb if (ret)
893628348caeSBjoern A. Zeeb goto exit;
893728348caeSBjoern A. Zeeb
893828348caeSBjoern A. Zeeb scan_time_msec = ar->hw->wiphy->max_remain_on_channel_duration * 2;
893928348caeSBjoern A. Zeeb
894028348caeSBjoern A. Zeeb memset(&arg, 0, sizeof(arg));
894128348caeSBjoern A. Zeeb ath11k_wmi_start_scan_init(ar, &arg);
894228348caeSBjoern A. Zeeb arg.num_chan = 1;
894328348caeSBjoern A. Zeeb arg.chan_list = kcalloc(arg.num_chan, sizeof(*arg.chan_list),
894428348caeSBjoern A. Zeeb GFP_KERNEL);
894528348caeSBjoern A. Zeeb if (!arg.chan_list) {
894628348caeSBjoern A. Zeeb ret = -ENOMEM;
894728348caeSBjoern A. Zeeb goto exit;
894828348caeSBjoern A. Zeeb }
894928348caeSBjoern A. Zeeb
895028348caeSBjoern A. Zeeb arg.vdev_id = arvif->vdev_id;
895128348caeSBjoern A. Zeeb arg.scan_id = ATH11K_SCAN_ID;
895228348caeSBjoern A. Zeeb arg.chan_list[0] = chan->center_freq;
895328348caeSBjoern A. Zeeb arg.dwell_time_active = scan_time_msec;
895428348caeSBjoern A. Zeeb arg.dwell_time_passive = scan_time_msec;
895528348caeSBjoern A. Zeeb arg.max_scan_time = scan_time_msec;
895628348caeSBjoern A. Zeeb arg.scan_flags |= WMI_SCAN_FLAG_PASSIVE;
895728348caeSBjoern A. Zeeb arg.scan_flags |= WMI_SCAN_FILTER_PROBE_REQ;
895828348caeSBjoern A. Zeeb arg.burst_duration = duration;
895928348caeSBjoern A. Zeeb
896028348caeSBjoern A. Zeeb ret = ath11k_start_scan(ar, &arg);
896128348caeSBjoern A. Zeeb if (ret) {
896228348caeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to start roc scan: %d\n", ret);
896328348caeSBjoern A. Zeeb
896428348caeSBjoern A. Zeeb spin_lock_bh(&ar->data_lock);
896528348caeSBjoern A. Zeeb ar->scan.state = ATH11K_SCAN_IDLE;
896628348caeSBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
896728348caeSBjoern A. Zeeb goto free_chan_list;
896828348caeSBjoern A. Zeeb }
896928348caeSBjoern A. Zeeb
897028348caeSBjoern A. Zeeb ret = wait_for_completion_timeout(&ar->scan.on_channel, 3 * HZ);
897128348caeSBjoern A. Zeeb if (ret == 0) {
897228348caeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to switch to channel for roc scan\n");
897328348caeSBjoern A. Zeeb ret = ath11k_scan_stop(ar);
897428348caeSBjoern A. Zeeb if (ret)
897528348caeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to stop scan: %d\n", ret);
897628348caeSBjoern A. Zeeb ret = -ETIMEDOUT;
897728348caeSBjoern A. Zeeb goto free_chan_list;
897828348caeSBjoern A. Zeeb }
897928348caeSBjoern A. Zeeb
898028348caeSBjoern A. Zeeb ieee80211_queue_delayed_work(ar->hw, &ar->scan.timeout,
898128348caeSBjoern A. Zeeb msecs_to_jiffies(duration));
898228348caeSBjoern A. Zeeb
898328348caeSBjoern A. Zeeb ret = 0;
898428348caeSBjoern A. Zeeb
898528348caeSBjoern A. Zeeb free_chan_list:
898628348caeSBjoern A. Zeeb kfree(arg.chan_list);
898728348caeSBjoern A. Zeeb exit:
898828348caeSBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
898928348caeSBjoern A. Zeeb return ret;
899028348caeSBjoern A. Zeeb }
899128348caeSBjoern A. Zeeb
ath11k_fw_stats_request(struct ath11k * ar,struct stats_request_params * req_param)899228348caeSBjoern A. Zeeb static int ath11k_fw_stats_request(struct ath11k *ar,
899328348caeSBjoern A. Zeeb struct stats_request_params *req_param)
899428348caeSBjoern A. Zeeb {
899528348caeSBjoern A. Zeeb struct ath11k_base *ab = ar->ab;
899628348caeSBjoern A. Zeeb unsigned long time_left;
899728348caeSBjoern A. Zeeb int ret;
899828348caeSBjoern A. Zeeb
899928348caeSBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
900028348caeSBjoern A. Zeeb
900128348caeSBjoern A. Zeeb spin_lock_bh(&ar->data_lock);
900228348caeSBjoern A. Zeeb ar->fw_stats_done = false;
900328348caeSBjoern A. Zeeb ath11k_fw_stats_pdevs_free(&ar->fw_stats.pdevs);
900428348caeSBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
900528348caeSBjoern A. Zeeb
900628348caeSBjoern A. Zeeb reinit_completion(&ar->fw_stats_complete);
900728348caeSBjoern A. Zeeb
900828348caeSBjoern A. Zeeb ret = ath11k_wmi_send_stats_request_cmd(ar, req_param);
900928348caeSBjoern A. Zeeb if (ret) {
901028348caeSBjoern A. Zeeb ath11k_warn(ab, "could not request fw stats (%d)\n",
901128348caeSBjoern A. Zeeb ret);
901228348caeSBjoern A. Zeeb return ret;
901328348caeSBjoern A. Zeeb }
901428348caeSBjoern A. Zeeb
901528348caeSBjoern A. Zeeb time_left = wait_for_completion_timeout(&ar->fw_stats_complete,
901628348caeSBjoern A. Zeeb 1 * HZ);
901728348caeSBjoern A. Zeeb
901828348caeSBjoern A. Zeeb if (!time_left)
901928348caeSBjoern A. Zeeb return -ETIMEDOUT;
902028348caeSBjoern A. Zeeb
902128348caeSBjoern A. Zeeb return 0;
902228348caeSBjoern A. Zeeb }
902328348caeSBjoern A. Zeeb
ath11k_mac_op_get_txpower(struct ieee80211_hw * hw,struct ieee80211_vif * vif,int * dbm)902428348caeSBjoern A. Zeeb static int ath11k_mac_op_get_txpower(struct ieee80211_hw *hw,
902528348caeSBjoern A. Zeeb struct ieee80211_vif *vif,
902628348caeSBjoern A. Zeeb int *dbm)
902728348caeSBjoern A. Zeeb {
902828348caeSBjoern A. Zeeb struct ath11k *ar = hw->priv;
902928348caeSBjoern A. Zeeb struct ath11k_base *ab = ar->ab;
903028348caeSBjoern A. Zeeb struct stats_request_params req_param = {0};
903128348caeSBjoern A. Zeeb struct ath11k_fw_stats_pdev *pdev;
903228348caeSBjoern A. Zeeb int ret;
903328348caeSBjoern A. Zeeb
903428348caeSBjoern A. Zeeb /* Final Tx power is minimum of Target Power, CTL power, Regulatory
903528348caeSBjoern A. Zeeb * Power, PSD EIRP Power. We just know the Regulatory power from the
903628348caeSBjoern A. Zeeb * regulatory rules obtained. FW knows all these power and sets the min
903728348caeSBjoern A. Zeeb * of these. Hence, we request the FW pdev stats in which FW reports
903828348caeSBjoern A. Zeeb * the minimum of all vdev's channel Tx power.
903928348caeSBjoern A. Zeeb */
904028348caeSBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
904128348caeSBjoern A. Zeeb
904228348caeSBjoern A. Zeeb if (ar->state != ATH11K_STATE_ON)
904328348caeSBjoern A. Zeeb goto err_fallback;
904428348caeSBjoern A. Zeeb
904528348caeSBjoern A. Zeeb req_param.pdev_id = ar->pdev->pdev_id;
904628348caeSBjoern A. Zeeb req_param.stats_id = WMI_REQUEST_PDEV_STAT;
904728348caeSBjoern A. Zeeb
904828348caeSBjoern A. Zeeb ret = ath11k_fw_stats_request(ar, &req_param);
904928348caeSBjoern A. Zeeb if (ret) {
905028348caeSBjoern A. Zeeb ath11k_warn(ab, "failed to request fw pdev stats: %d\n", ret);
905128348caeSBjoern A. Zeeb goto err_fallback;
905228348caeSBjoern A. Zeeb }
905328348caeSBjoern A. Zeeb
905428348caeSBjoern A. Zeeb spin_lock_bh(&ar->data_lock);
905528348caeSBjoern A. Zeeb pdev = list_first_entry_or_null(&ar->fw_stats.pdevs,
905628348caeSBjoern A. Zeeb struct ath11k_fw_stats_pdev, list);
905728348caeSBjoern A. Zeeb if (!pdev) {
905828348caeSBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
905928348caeSBjoern A. Zeeb goto err_fallback;
906028348caeSBjoern A. Zeeb }
906128348caeSBjoern A. Zeeb
906228348caeSBjoern A. Zeeb /* tx power is set as 2 units per dBm in FW. */
906328348caeSBjoern A. Zeeb *dbm = pdev->chan_tx_power / 2;
906428348caeSBjoern A. Zeeb
906528348caeSBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
906628348caeSBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
906728348caeSBjoern A. Zeeb
906828348caeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "txpower from firmware %d, reported %d dBm\n",
906928348caeSBjoern A. Zeeb pdev->chan_tx_power, *dbm);
907028348caeSBjoern A. Zeeb return 0;
907128348caeSBjoern A. Zeeb
907228348caeSBjoern A. Zeeb err_fallback:
907328348caeSBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
907428348caeSBjoern A. Zeeb /* We didn't get txpower from FW. Hence, relying on vif->bss_conf.txpower */
907528348caeSBjoern A. Zeeb *dbm = vif->bss_conf.txpower;
907628348caeSBjoern A. Zeeb ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "txpower from firmware NaN, reported %d dBm\n",
907728348caeSBjoern A. Zeeb *dbm);
907828348caeSBjoern A. Zeeb return 0;
9079dd4f32aeSBjoern A. Zeeb }
9080dd4f32aeSBjoern A. Zeeb
9081dd4f32aeSBjoern A. Zeeb static const struct ieee80211_ops ath11k_ops = {
9082dd4f32aeSBjoern A. Zeeb .tx = ath11k_mac_op_tx,
908328348caeSBjoern A. Zeeb .wake_tx_queue = ieee80211_handle_wake_tx_queue,
9084dd4f32aeSBjoern A. Zeeb .start = ath11k_mac_op_start,
9085dd4f32aeSBjoern A. Zeeb .stop = ath11k_mac_op_stop,
9086dd4f32aeSBjoern A. Zeeb .reconfig_complete = ath11k_mac_op_reconfig_complete,
9087dd4f32aeSBjoern A. Zeeb .add_interface = ath11k_mac_op_add_interface,
9088dd4f32aeSBjoern A. Zeeb .remove_interface = ath11k_mac_op_remove_interface,
9089dd4f32aeSBjoern A. Zeeb .update_vif_offload = ath11k_mac_op_update_vif_offload,
9090dd4f32aeSBjoern A. Zeeb .config = ath11k_mac_op_config,
9091dd4f32aeSBjoern A. Zeeb .bss_info_changed = ath11k_mac_op_bss_info_changed,
9092dd4f32aeSBjoern A. Zeeb .configure_filter = ath11k_mac_op_configure_filter,
9093dd4f32aeSBjoern A. Zeeb .hw_scan = ath11k_mac_op_hw_scan,
9094dd4f32aeSBjoern A. Zeeb .cancel_hw_scan = ath11k_mac_op_cancel_hw_scan,
9095dd4f32aeSBjoern A. Zeeb .set_key = ath11k_mac_op_set_key,
909628348caeSBjoern A. Zeeb .set_rekey_data = ath11k_mac_op_set_rekey_data,
9097dd4f32aeSBjoern A. Zeeb .sta_state = ath11k_mac_op_sta_state,
9098dd4f32aeSBjoern A. Zeeb .sta_set_4addr = ath11k_mac_op_sta_set_4addr,
9099dd4f32aeSBjoern A. Zeeb .sta_set_txpwr = ath11k_mac_op_sta_set_txpwr,
9100dd4f32aeSBjoern A. Zeeb .sta_rc_update = ath11k_mac_op_sta_rc_update,
9101dd4f32aeSBjoern A. Zeeb .conf_tx = ath11k_mac_op_conf_tx,
9102dd4f32aeSBjoern A. Zeeb .set_antenna = ath11k_mac_op_set_antenna,
9103dd4f32aeSBjoern A. Zeeb .get_antenna = ath11k_mac_op_get_antenna,
9104dd4f32aeSBjoern A. Zeeb .ampdu_action = ath11k_mac_op_ampdu_action,
9105dd4f32aeSBjoern A. Zeeb .add_chanctx = ath11k_mac_op_add_chanctx,
9106dd4f32aeSBjoern A. Zeeb .remove_chanctx = ath11k_mac_op_remove_chanctx,
9107dd4f32aeSBjoern A. Zeeb .change_chanctx = ath11k_mac_op_change_chanctx,
9108dd4f32aeSBjoern A. Zeeb .assign_vif_chanctx = ath11k_mac_op_assign_vif_chanctx,
9109dd4f32aeSBjoern A. Zeeb .unassign_vif_chanctx = ath11k_mac_op_unassign_vif_chanctx,
9110dd4f32aeSBjoern A. Zeeb .switch_vif_chanctx = ath11k_mac_op_switch_vif_chanctx,
9111dd4f32aeSBjoern A. Zeeb .set_rts_threshold = ath11k_mac_op_set_rts_threshold,
9112dd4f32aeSBjoern A. Zeeb .set_frag_threshold = ath11k_mac_op_set_frag_threshold,
9113dd4f32aeSBjoern A. Zeeb .set_bitrate_mask = ath11k_mac_op_set_bitrate_mask,
9114dd4f32aeSBjoern A. Zeeb .get_survey = ath11k_mac_op_get_survey,
9115dd4f32aeSBjoern A. Zeeb .flush = ath11k_mac_op_flush,
9116dd4f32aeSBjoern A. Zeeb .sta_statistics = ath11k_mac_op_sta_statistics,
9117dd4f32aeSBjoern A. Zeeb CFG80211_TESTMODE_CMD(ath11k_tm_cmd)
911828348caeSBjoern A. Zeeb
911928348caeSBjoern A. Zeeb #ifdef CONFIG_PM
912028348caeSBjoern A. Zeeb .suspend = ath11k_wow_op_suspend,
912128348caeSBjoern A. Zeeb .resume = ath11k_wow_op_resume,
912228348caeSBjoern A. Zeeb .set_wakeup = ath11k_wow_op_set_wakeup,
912328348caeSBjoern A. Zeeb #endif
912428348caeSBjoern A. Zeeb
9125dd4f32aeSBjoern A. Zeeb #ifdef CONFIG_ATH11K_DEBUGFS
9126dd4f32aeSBjoern A. Zeeb .sta_add_debugfs = ath11k_debugfs_sta_op_add,
9127dd4f32aeSBjoern A. Zeeb #endif
912828348caeSBjoern A. Zeeb
912928348caeSBjoern A. Zeeb #if IS_ENABLED(CONFIG_IPV6)
913028348caeSBjoern A. Zeeb .ipv6_addr_change = ath11k_mac_op_ipv6_changed,
913128348caeSBjoern A. Zeeb #endif
913228348caeSBjoern A. Zeeb .get_txpower = ath11k_mac_op_get_txpower,
913328348caeSBjoern A. Zeeb
913428348caeSBjoern A. Zeeb .set_sar_specs = ath11k_mac_op_set_bios_sar_specs,
913528348caeSBjoern A. Zeeb .remain_on_channel = ath11k_mac_op_remain_on_channel,
913628348caeSBjoern A. Zeeb .cancel_remain_on_channel = ath11k_mac_op_cancel_remain_on_channel,
9137dd4f32aeSBjoern A. Zeeb };
9138dd4f32aeSBjoern A. Zeeb
ath11k_mac_update_ch_list(struct ath11k * ar,struct ieee80211_supported_band * band,u32 freq_low,u32 freq_high)9139dd4f32aeSBjoern A. Zeeb static void ath11k_mac_update_ch_list(struct ath11k *ar,
9140dd4f32aeSBjoern A. Zeeb struct ieee80211_supported_band *band,
9141dd4f32aeSBjoern A. Zeeb u32 freq_low, u32 freq_high)
9142dd4f32aeSBjoern A. Zeeb {
9143dd4f32aeSBjoern A. Zeeb int i;
9144dd4f32aeSBjoern A. Zeeb
9145dd4f32aeSBjoern A. Zeeb if (!(freq_low && freq_high))
9146dd4f32aeSBjoern A. Zeeb return;
9147dd4f32aeSBjoern A. Zeeb
9148dd4f32aeSBjoern A. Zeeb for (i = 0; i < band->n_channels; i++) {
9149dd4f32aeSBjoern A. Zeeb if (band->channels[i].center_freq < freq_low ||
9150dd4f32aeSBjoern A. Zeeb band->channels[i].center_freq > freq_high)
9151dd4f32aeSBjoern A. Zeeb band->channels[i].flags |= IEEE80211_CHAN_DISABLED;
9152dd4f32aeSBjoern A. Zeeb }
9153dd4f32aeSBjoern A. Zeeb }
9154dd4f32aeSBjoern A. Zeeb
ath11k_get_phy_id(struct ath11k * ar,u32 band)9155dd4f32aeSBjoern A. Zeeb static u32 ath11k_get_phy_id(struct ath11k *ar, u32 band)
9156dd4f32aeSBjoern A. Zeeb {
9157dd4f32aeSBjoern A. Zeeb struct ath11k_pdev *pdev = ar->pdev;
9158dd4f32aeSBjoern A. Zeeb struct ath11k_pdev_cap *pdev_cap = &pdev->cap;
9159dd4f32aeSBjoern A. Zeeb
9160dd4f32aeSBjoern A. Zeeb if (band == WMI_HOST_WLAN_2G_CAP)
9161dd4f32aeSBjoern A. Zeeb return pdev_cap->band[NL80211_BAND_2GHZ].phy_id;
9162dd4f32aeSBjoern A. Zeeb
9163dd4f32aeSBjoern A. Zeeb if (band == WMI_HOST_WLAN_5G_CAP)
9164dd4f32aeSBjoern A. Zeeb return pdev_cap->band[NL80211_BAND_5GHZ].phy_id;
9165dd4f32aeSBjoern A. Zeeb
9166dd4f32aeSBjoern A. Zeeb ath11k_warn(ar->ab, "unsupported phy cap:%d\n", band);
9167dd4f32aeSBjoern A. Zeeb
9168dd4f32aeSBjoern A. Zeeb return 0;
9169dd4f32aeSBjoern A. Zeeb }
9170dd4f32aeSBjoern A. Zeeb
ath11k_mac_setup_channels_rates(struct ath11k * ar,u32 supported_bands)9171dd4f32aeSBjoern A. Zeeb static int ath11k_mac_setup_channels_rates(struct ath11k *ar,
9172dd4f32aeSBjoern A. Zeeb u32 supported_bands)
9173dd4f32aeSBjoern A. Zeeb {
9174dd4f32aeSBjoern A. Zeeb struct ieee80211_supported_band *band;
9175dd4f32aeSBjoern A. Zeeb struct ath11k_hal_reg_capabilities_ext *reg_cap, *temp_reg_cap;
9176dd4f32aeSBjoern A. Zeeb void *channels;
9177dd4f32aeSBjoern A. Zeeb u32 phy_id;
9178dd4f32aeSBjoern A. Zeeb
9179dd4f32aeSBjoern A. Zeeb BUILD_BUG_ON((ARRAY_SIZE(ath11k_2ghz_channels) +
9180dd4f32aeSBjoern A. Zeeb ARRAY_SIZE(ath11k_5ghz_channels) +
9181dd4f32aeSBjoern A. Zeeb ARRAY_SIZE(ath11k_6ghz_channels)) !=
9182dd4f32aeSBjoern A. Zeeb ATH11K_NUM_CHANS);
9183dd4f32aeSBjoern A. Zeeb
9184dd4f32aeSBjoern A. Zeeb reg_cap = &ar->ab->hal_reg_cap[ar->pdev_idx];
9185dd4f32aeSBjoern A. Zeeb temp_reg_cap = reg_cap;
9186dd4f32aeSBjoern A. Zeeb
9187dd4f32aeSBjoern A. Zeeb if (supported_bands & WMI_HOST_WLAN_2G_CAP) {
9188dd4f32aeSBjoern A. Zeeb channels = kmemdup(ath11k_2ghz_channels,
9189dd4f32aeSBjoern A. Zeeb sizeof(ath11k_2ghz_channels),
9190dd4f32aeSBjoern A. Zeeb GFP_KERNEL);
9191dd4f32aeSBjoern A. Zeeb if (!channels)
9192dd4f32aeSBjoern A. Zeeb return -ENOMEM;
9193dd4f32aeSBjoern A. Zeeb
9194dd4f32aeSBjoern A. Zeeb band = &ar->mac.sbands[NL80211_BAND_2GHZ];
9195dd4f32aeSBjoern A. Zeeb band->band = NL80211_BAND_2GHZ;
9196dd4f32aeSBjoern A. Zeeb band->n_channels = ARRAY_SIZE(ath11k_2ghz_channels);
9197dd4f32aeSBjoern A. Zeeb band->channels = channels;
9198dd4f32aeSBjoern A. Zeeb band->n_bitrates = ath11k_g_rates_size;
9199dd4f32aeSBjoern A. Zeeb band->bitrates = ath11k_g_rates;
9200dd4f32aeSBjoern A. Zeeb ar->hw->wiphy->bands[NL80211_BAND_2GHZ] = band;
9201dd4f32aeSBjoern A. Zeeb
9202dd4f32aeSBjoern A. Zeeb if (ar->ab->hw_params.single_pdev_only) {
9203dd4f32aeSBjoern A. Zeeb phy_id = ath11k_get_phy_id(ar, WMI_HOST_WLAN_2G_CAP);
9204dd4f32aeSBjoern A. Zeeb temp_reg_cap = &ar->ab->hal_reg_cap[phy_id];
9205dd4f32aeSBjoern A. Zeeb }
9206dd4f32aeSBjoern A. Zeeb ath11k_mac_update_ch_list(ar, band,
9207dd4f32aeSBjoern A. Zeeb temp_reg_cap->low_2ghz_chan,
9208dd4f32aeSBjoern A. Zeeb temp_reg_cap->high_2ghz_chan);
9209dd4f32aeSBjoern A. Zeeb }
9210dd4f32aeSBjoern A. Zeeb
9211dd4f32aeSBjoern A. Zeeb if (supported_bands & WMI_HOST_WLAN_5G_CAP) {
921228348caeSBjoern A. Zeeb if (reg_cap->high_5ghz_chan >= ATH11K_MIN_6G_FREQ) {
9213dd4f32aeSBjoern A. Zeeb channels = kmemdup(ath11k_6ghz_channels,
9214dd4f32aeSBjoern A. Zeeb sizeof(ath11k_6ghz_channels), GFP_KERNEL);
9215dd4f32aeSBjoern A. Zeeb if (!channels) {
9216dd4f32aeSBjoern A. Zeeb kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels);
9217dd4f32aeSBjoern A. Zeeb return -ENOMEM;
9218dd4f32aeSBjoern A. Zeeb }
9219dd4f32aeSBjoern A. Zeeb
9220dd4f32aeSBjoern A. Zeeb ar->supports_6ghz = true;
9221dd4f32aeSBjoern A. Zeeb band = &ar->mac.sbands[NL80211_BAND_6GHZ];
9222dd4f32aeSBjoern A. Zeeb band->band = NL80211_BAND_6GHZ;
9223dd4f32aeSBjoern A. Zeeb band->n_channels = ARRAY_SIZE(ath11k_6ghz_channels);
9224dd4f32aeSBjoern A. Zeeb band->channels = channels;
9225dd4f32aeSBjoern A. Zeeb band->n_bitrates = ath11k_a_rates_size;
9226dd4f32aeSBjoern A. Zeeb band->bitrates = ath11k_a_rates;
9227dd4f32aeSBjoern A. Zeeb ar->hw->wiphy->bands[NL80211_BAND_6GHZ] = band;
9228dd4f32aeSBjoern A. Zeeb
9229dd4f32aeSBjoern A. Zeeb if (ar->ab->hw_params.single_pdev_only) {
9230dd4f32aeSBjoern A. Zeeb phy_id = ath11k_get_phy_id(ar, WMI_HOST_WLAN_5G_CAP);
9231dd4f32aeSBjoern A. Zeeb temp_reg_cap = &ar->ab->hal_reg_cap[phy_id];
9232dd4f32aeSBjoern A. Zeeb }
9233dd4f32aeSBjoern A. Zeeb
9234dd4f32aeSBjoern A. Zeeb ath11k_mac_update_ch_list(ar, band,
9235dd4f32aeSBjoern A. Zeeb temp_reg_cap->low_5ghz_chan,
9236dd4f32aeSBjoern A. Zeeb temp_reg_cap->high_5ghz_chan);
9237dd4f32aeSBjoern A. Zeeb }
9238dd4f32aeSBjoern A. Zeeb
9239dd4f32aeSBjoern A. Zeeb if (reg_cap->low_5ghz_chan < ATH11K_MIN_6G_FREQ) {
9240dd4f32aeSBjoern A. Zeeb channels = kmemdup(ath11k_5ghz_channels,
9241dd4f32aeSBjoern A. Zeeb sizeof(ath11k_5ghz_channels),
9242dd4f32aeSBjoern A. Zeeb GFP_KERNEL);
9243dd4f32aeSBjoern A. Zeeb if (!channels) {
9244dd4f32aeSBjoern A. Zeeb kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels);
9245dd4f32aeSBjoern A. Zeeb kfree(ar->mac.sbands[NL80211_BAND_6GHZ].channels);
9246dd4f32aeSBjoern A. Zeeb return -ENOMEM;
9247dd4f32aeSBjoern A. Zeeb }
9248dd4f32aeSBjoern A. Zeeb
9249dd4f32aeSBjoern A. Zeeb band = &ar->mac.sbands[NL80211_BAND_5GHZ];
9250dd4f32aeSBjoern A. Zeeb band->band = NL80211_BAND_5GHZ;
9251dd4f32aeSBjoern A. Zeeb band->n_channels = ARRAY_SIZE(ath11k_5ghz_channels);
9252dd4f32aeSBjoern A. Zeeb band->channels = channels;
9253dd4f32aeSBjoern A. Zeeb band->n_bitrates = ath11k_a_rates_size;
9254dd4f32aeSBjoern A. Zeeb band->bitrates = ath11k_a_rates;
9255dd4f32aeSBjoern A. Zeeb ar->hw->wiphy->bands[NL80211_BAND_5GHZ] = band;
9256dd4f32aeSBjoern A. Zeeb
9257dd4f32aeSBjoern A. Zeeb if (ar->ab->hw_params.single_pdev_only) {
9258dd4f32aeSBjoern A. Zeeb phy_id = ath11k_get_phy_id(ar, WMI_HOST_WLAN_5G_CAP);
9259dd4f32aeSBjoern A. Zeeb temp_reg_cap = &ar->ab->hal_reg_cap[phy_id];
9260dd4f32aeSBjoern A. Zeeb }
9261dd4f32aeSBjoern A. Zeeb
9262dd4f32aeSBjoern A. Zeeb ath11k_mac_update_ch_list(ar, band,
9263dd4f32aeSBjoern A. Zeeb temp_reg_cap->low_5ghz_chan,
9264dd4f32aeSBjoern A. Zeeb temp_reg_cap->high_5ghz_chan);
9265dd4f32aeSBjoern A. Zeeb }
9266dd4f32aeSBjoern A. Zeeb }
9267dd4f32aeSBjoern A. Zeeb
9268dd4f32aeSBjoern A. Zeeb return 0;
9269dd4f32aeSBjoern A. Zeeb }
9270dd4f32aeSBjoern A. Zeeb
ath11k_mac_setup_iface_combinations(struct ath11k * ar)9271dd4f32aeSBjoern A. Zeeb static int ath11k_mac_setup_iface_combinations(struct ath11k *ar)
9272dd4f32aeSBjoern A. Zeeb {
9273dd4f32aeSBjoern A. Zeeb struct ath11k_base *ab = ar->ab;
9274dd4f32aeSBjoern A. Zeeb struct ieee80211_iface_combination *combinations;
9275dd4f32aeSBjoern A. Zeeb struct ieee80211_iface_limit *limits;
9276dd4f32aeSBjoern A. Zeeb int n_limits;
9277dd4f32aeSBjoern A. Zeeb
9278dd4f32aeSBjoern A. Zeeb combinations = kzalloc(sizeof(*combinations), GFP_KERNEL);
9279dd4f32aeSBjoern A. Zeeb if (!combinations)
9280dd4f32aeSBjoern A. Zeeb return -ENOMEM;
9281dd4f32aeSBjoern A. Zeeb
9282dd4f32aeSBjoern A. Zeeb n_limits = 2;
9283dd4f32aeSBjoern A. Zeeb
9284dd4f32aeSBjoern A. Zeeb limits = kcalloc(n_limits, sizeof(*limits), GFP_KERNEL);
9285dd4f32aeSBjoern A. Zeeb if (!limits) {
9286dd4f32aeSBjoern A. Zeeb kfree(combinations);
9287dd4f32aeSBjoern A. Zeeb return -ENOMEM;
9288dd4f32aeSBjoern A. Zeeb }
9289dd4f32aeSBjoern A. Zeeb
9290dd4f32aeSBjoern A. Zeeb limits[0].max = 1;
9291dd4f32aeSBjoern A. Zeeb limits[0].types |= BIT(NL80211_IFTYPE_STATION);
9292dd4f32aeSBjoern A. Zeeb
9293dd4f32aeSBjoern A. Zeeb limits[1].max = 16;
9294dd4f32aeSBjoern A. Zeeb limits[1].types |= BIT(NL80211_IFTYPE_AP);
9295dd4f32aeSBjoern A. Zeeb
9296dd4f32aeSBjoern A. Zeeb if (IS_ENABLED(CONFIG_MAC80211_MESH) &&
9297dd4f32aeSBjoern A. Zeeb ab->hw_params.interface_modes & BIT(NL80211_IFTYPE_MESH_POINT))
9298dd4f32aeSBjoern A. Zeeb limits[1].types |= BIT(NL80211_IFTYPE_MESH_POINT);
9299dd4f32aeSBjoern A. Zeeb
9300dd4f32aeSBjoern A. Zeeb combinations[0].limits = limits;
9301dd4f32aeSBjoern A. Zeeb combinations[0].n_limits = n_limits;
9302dd4f32aeSBjoern A. Zeeb combinations[0].max_interfaces = 16;
9303dd4f32aeSBjoern A. Zeeb combinations[0].num_different_channels = 1;
9304dd4f32aeSBjoern A. Zeeb combinations[0].beacon_int_infra_match = true;
9305dd4f32aeSBjoern A. Zeeb combinations[0].beacon_int_min_gcd = 100;
9306dd4f32aeSBjoern A. Zeeb combinations[0].radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |
9307dd4f32aeSBjoern A. Zeeb BIT(NL80211_CHAN_WIDTH_20) |
9308dd4f32aeSBjoern A. Zeeb BIT(NL80211_CHAN_WIDTH_40) |
9309dd4f32aeSBjoern A. Zeeb BIT(NL80211_CHAN_WIDTH_80) |
9310dd4f32aeSBjoern A. Zeeb BIT(NL80211_CHAN_WIDTH_80P80) |
9311dd4f32aeSBjoern A. Zeeb BIT(NL80211_CHAN_WIDTH_160);
9312dd4f32aeSBjoern A. Zeeb
9313dd4f32aeSBjoern A. Zeeb ar->hw->wiphy->iface_combinations = combinations;
9314dd4f32aeSBjoern A. Zeeb ar->hw->wiphy->n_iface_combinations = 1;
9315dd4f32aeSBjoern A. Zeeb
9316dd4f32aeSBjoern A. Zeeb return 0;
9317dd4f32aeSBjoern A. Zeeb }
9318dd4f32aeSBjoern A. Zeeb
9319dd4f32aeSBjoern A. Zeeb static const u8 ath11k_if_types_ext_capa[] = {
9320dd4f32aeSBjoern A. Zeeb [0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
932128348caeSBjoern A. Zeeb [2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT,
9322dd4f32aeSBjoern A. Zeeb [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
9323dd4f32aeSBjoern A. Zeeb };
9324dd4f32aeSBjoern A. Zeeb
9325dd4f32aeSBjoern A. Zeeb static const u8 ath11k_if_types_ext_capa_sta[] = {
9326dd4f32aeSBjoern A. Zeeb [0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
932728348caeSBjoern A. Zeeb [2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT,
9328dd4f32aeSBjoern A. Zeeb [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
9329dd4f32aeSBjoern A. Zeeb [9] = WLAN_EXT_CAPA10_TWT_REQUESTER_SUPPORT,
9330dd4f32aeSBjoern A. Zeeb };
9331dd4f32aeSBjoern A. Zeeb
9332dd4f32aeSBjoern A. Zeeb static const u8 ath11k_if_types_ext_capa_ap[] = {
9333dd4f32aeSBjoern A. Zeeb [0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
933428348caeSBjoern A. Zeeb [2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT,
9335dd4f32aeSBjoern A. Zeeb [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
9336dd4f32aeSBjoern A. Zeeb [9] = WLAN_EXT_CAPA10_TWT_RESPONDER_SUPPORT,
933728348caeSBjoern A. Zeeb [10] = WLAN_EXT_CAPA11_EMA_SUPPORT,
9338dd4f32aeSBjoern A. Zeeb };
9339dd4f32aeSBjoern A. Zeeb
9340dd4f32aeSBjoern A. Zeeb static const struct wiphy_iftype_ext_capab ath11k_iftypes_ext_capa[] = {
9341dd4f32aeSBjoern A. Zeeb {
9342dd4f32aeSBjoern A. Zeeb .extended_capabilities = ath11k_if_types_ext_capa,
9343dd4f32aeSBjoern A. Zeeb .extended_capabilities_mask = ath11k_if_types_ext_capa,
9344dd4f32aeSBjoern A. Zeeb .extended_capabilities_len = sizeof(ath11k_if_types_ext_capa),
9345dd4f32aeSBjoern A. Zeeb }, {
9346dd4f32aeSBjoern A. Zeeb .iftype = NL80211_IFTYPE_STATION,
9347dd4f32aeSBjoern A. Zeeb .extended_capabilities = ath11k_if_types_ext_capa_sta,
9348dd4f32aeSBjoern A. Zeeb .extended_capabilities_mask = ath11k_if_types_ext_capa_sta,
9349dd4f32aeSBjoern A. Zeeb .extended_capabilities_len =
9350dd4f32aeSBjoern A. Zeeb sizeof(ath11k_if_types_ext_capa_sta),
9351dd4f32aeSBjoern A. Zeeb }, {
9352dd4f32aeSBjoern A. Zeeb .iftype = NL80211_IFTYPE_AP,
9353dd4f32aeSBjoern A. Zeeb .extended_capabilities = ath11k_if_types_ext_capa_ap,
9354dd4f32aeSBjoern A. Zeeb .extended_capabilities_mask = ath11k_if_types_ext_capa_ap,
9355dd4f32aeSBjoern A. Zeeb .extended_capabilities_len =
9356dd4f32aeSBjoern A. Zeeb sizeof(ath11k_if_types_ext_capa_ap),
9357dd4f32aeSBjoern A. Zeeb },
9358dd4f32aeSBjoern A. Zeeb };
9359dd4f32aeSBjoern A. Zeeb
__ath11k_mac_unregister(struct ath11k * ar)9360dd4f32aeSBjoern A. Zeeb static void __ath11k_mac_unregister(struct ath11k *ar)
9361dd4f32aeSBjoern A. Zeeb {
9362dd4f32aeSBjoern A. Zeeb cancel_work_sync(&ar->regd_update_work);
9363dd4f32aeSBjoern A. Zeeb
9364dd4f32aeSBjoern A. Zeeb ieee80211_unregister_hw(ar->hw);
9365dd4f32aeSBjoern A. Zeeb
9366dd4f32aeSBjoern A. Zeeb idr_for_each(&ar->txmgmt_idr, ath11k_mac_tx_mgmt_pending_free, ar);
9367dd4f32aeSBjoern A. Zeeb idr_destroy(&ar->txmgmt_idr);
9368dd4f32aeSBjoern A. Zeeb
9369dd4f32aeSBjoern A. Zeeb kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels);
9370dd4f32aeSBjoern A. Zeeb kfree(ar->mac.sbands[NL80211_BAND_5GHZ].channels);
9371dd4f32aeSBjoern A. Zeeb kfree(ar->mac.sbands[NL80211_BAND_6GHZ].channels);
9372dd4f32aeSBjoern A. Zeeb
9373dd4f32aeSBjoern A. Zeeb kfree(ar->hw->wiphy->iface_combinations[0].limits);
9374dd4f32aeSBjoern A. Zeeb kfree(ar->hw->wiphy->iface_combinations);
9375dd4f32aeSBjoern A. Zeeb
9376dd4f32aeSBjoern A. Zeeb SET_IEEE80211_DEV(ar->hw, NULL);
9377dd4f32aeSBjoern A. Zeeb }
9378dd4f32aeSBjoern A. Zeeb
ath11k_mac_unregister(struct ath11k_base * ab)9379dd4f32aeSBjoern A. Zeeb void ath11k_mac_unregister(struct ath11k_base *ab)
9380dd4f32aeSBjoern A. Zeeb {
9381dd4f32aeSBjoern A. Zeeb struct ath11k *ar;
9382dd4f32aeSBjoern A. Zeeb struct ath11k_pdev *pdev;
9383dd4f32aeSBjoern A. Zeeb int i;
9384dd4f32aeSBjoern A. Zeeb
9385dd4f32aeSBjoern A. Zeeb for (i = 0; i < ab->num_radios; i++) {
9386dd4f32aeSBjoern A. Zeeb pdev = &ab->pdevs[i];
9387dd4f32aeSBjoern A. Zeeb ar = pdev->ar;
9388dd4f32aeSBjoern A. Zeeb if (!ar)
9389dd4f32aeSBjoern A. Zeeb continue;
9390dd4f32aeSBjoern A. Zeeb
9391dd4f32aeSBjoern A. Zeeb __ath11k_mac_unregister(ar);
9392dd4f32aeSBjoern A. Zeeb }
939328348caeSBjoern A. Zeeb
939428348caeSBjoern A. Zeeb ath11k_peer_rhash_tbl_destroy(ab);
9395dd4f32aeSBjoern A. Zeeb }
9396dd4f32aeSBjoern A. Zeeb
__ath11k_mac_register(struct ath11k * ar)9397dd4f32aeSBjoern A. Zeeb static int __ath11k_mac_register(struct ath11k *ar)
9398dd4f32aeSBjoern A. Zeeb {
9399dd4f32aeSBjoern A. Zeeb struct ath11k_base *ab = ar->ab;
9400dd4f32aeSBjoern A. Zeeb struct ath11k_pdev_cap *cap = &ar->pdev->cap;
9401dd4f32aeSBjoern A. Zeeb static const u32 cipher_suites[] = {
9402dd4f32aeSBjoern A. Zeeb WLAN_CIPHER_SUITE_TKIP,
9403dd4f32aeSBjoern A. Zeeb WLAN_CIPHER_SUITE_CCMP,
9404dd4f32aeSBjoern A. Zeeb WLAN_CIPHER_SUITE_AES_CMAC,
9405dd4f32aeSBjoern A. Zeeb WLAN_CIPHER_SUITE_BIP_CMAC_256,
9406dd4f32aeSBjoern A. Zeeb WLAN_CIPHER_SUITE_BIP_GMAC_128,
9407dd4f32aeSBjoern A. Zeeb WLAN_CIPHER_SUITE_BIP_GMAC_256,
9408dd4f32aeSBjoern A. Zeeb WLAN_CIPHER_SUITE_GCMP,
9409dd4f32aeSBjoern A. Zeeb WLAN_CIPHER_SUITE_GCMP_256,
9410dd4f32aeSBjoern A. Zeeb WLAN_CIPHER_SUITE_CCMP_256,
9411dd4f32aeSBjoern A. Zeeb };
9412dd4f32aeSBjoern A. Zeeb int ret;
9413dd4f32aeSBjoern A. Zeeb u32 ht_cap = 0;
9414dd4f32aeSBjoern A. Zeeb
9415dd4f32aeSBjoern A. Zeeb ath11k_pdev_caps_update(ar);
9416dd4f32aeSBjoern A. Zeeb
9417dd4f32aeSBjoern A. Zeeb SET_IEEE80211_PERM_ADDR(ar->hw, ar->mac_addr);
9418dd4f32aeSBjoern A. Zeeb
9419dd4f32aeSBjoern A. Zeeb SET_IEEE80211_DEV(ar->hw, ab->dev);
9420dd4f32aeSBjoern A. Zeeb
9421dd4f32aeSBjoern A. Zeeb ret = ath11k_mac_setup_channels_rates(ar,
9422dd4f32aeSBjoern A. Zeeb cap->supported_bands);
9423dd4f32aeSBjoern A. Zeeb if (ret)
9424dd4f32aeSBjoern A. Zeeb goto err;
9425dd4f32aeSBjoern A. Zeeb
9426dd4f32aeSBjoern A. Zeeb ath11k_mac_setup_ht_vht_cap(ar, cap, &ht_cap);
9427dd4f32aeSBjoern A. Zeeb ath11k_mac_setup_he_cap(ar, cap);
9428dd4f32aeSBjoern A. Zeeb
9429dd4f32aeSBjoern A. Zeeb ret = ath11k_mac_setup_iface_combinations(ar);
9430dd4f32aeSBjoern A. Zeeb if (ret) {
9431dd4f32aeSBjoern A. Zeeb ath11k_err(ar->ab, "failed to setup interface combinations: %d\n", ret);
9432dd4f32aeSBjoern A. Zeeb goto err_free_channels;
9433dd4f32aeSBjoern A. Zeeb }
9434dd4f32aeSBjoern A. Zeeb
9435dd4f32aeSBjoern A. Zeeb ar->hw->wiphy->available_antennas_rx = cap->rx_chain_mask;
9436dd4f32aeSBjoern A. Zeeb ar->hw->wiphy->available_antennas_tx = cap->tx_chain_mask;
9437dd4f32aeSBjoern A. Zeeb
9438dd4f32aeSBjoern A. Zeeb ar->hw->wiphy->interface_modes = ab->hw_params.interface_modes;
9439dd4f32aeSBjoern A. Zeeb
9440dd4f32aeSBjoern A. Zeeb if (ab->hw_params.single_pdev_only && ar->supports_6ghz)
9441dd4f32aeSBjoern A. Zeeb ieee80211_hw_set(ar->hw, SINGLE_SCAN_ON_ALL_BANDS);
9442dd4f32aeSBjoern A. Zeeb
944328348caeSBjoern A. Zeeb if (ab->hw_params.supports_multi_bssid) {
944428348caeSBjoern A. Zeeb ieee80211_hw_set(ar->hw, SUPPORTS_MULTI_BSSID);
944528348caeSBjoern A. Zeeb ieee80211_hw_set(ar->hw, SUPPORTS_ONLY_HE_MULTI_BSSID);
944628348caeSBjoern A. Zeeb }
944728348caeSBjoern A. Zeeb
9448dd4f32aeSBjoern A. Zeeb ieee80211_hw_set(ar->hw, SIGNAL_DBM);
9449dd4f32aeSBjoern A. Zeeb ieee80211_hw_set(ar->hw, SUPPORTS_PS);
9450dd4f32aeSBjoern A. Zeeb ieee80211_hw_set(ar->hw, SUPPORTS_DYNAMIC_PS);
9451dd4f32aeSBjoern A. Zeeb ieee80211_hw_set(ar->hw, MFP_CAPABLE);
9452dd4f32aeSBjoern A. Zeeb ieee80211_hw_set(ar->hw, REPORTS_TX_ACK_STATUS);
9453dd4f32aeSBjoern A. Zeeb ieee80211_hw_set(ar->hw, HAS_RATE_CONTROL);
9454dd4f32aeSBjoern A. Zeeb ieee80211_hw_set(ar->hw, AP_LINK_PS);
9455dd4f32aeSBjoern A. Zeeb ieee80211_hw_set(ar->hw, SPECTRUM_MGMT);
9456dd4f32aeSBjoern A. Zeeb ieee80211_hw_set(ar->hw, CONNECTION_MONITOR);
9457dd4f32aeSBjoern A. Zeeb ieee80211_hw_set(ar->hw, SUPPORTS_PER_STA_GTK);
9458dd4f32aeSBjoern A. Zeeb ieee80211_hw_set(ar->hw, WANT_MONITOR_VIF);
9459dd4f32aeSBjoern A. Zeeb ieee80211_hw_set(ar->hw, CHANCTX_STA_CSA);
9460dd4f32aeSBjoern A. Zeeb ieee80211_hw_set(ar->hw, QUEUE_CONTROL);
9461dd4f32aeSBjoern A. Zeeb ieee80211_hw_set(ar->hw, SUPPORTS_TX_FRAG);
9462dd4f32aeSBjoern A. Zeeb ieee80211_hw_set(ar->hw, REPORTS_LOW_ACK);
9463dd4f32aeSBjoern A. Zeeb
9464dd4f32aeSBjoern A. Zeeb if (ath11k_frame_mode == ATH11K_HW_TXRX_ETHERNET) {
9465dd4f32aeSBjoern A. Zeeb ieee80211_hw_set(ar->hw, SUPPORTS_TX_ENCAP_OFFLOAD);
9466dd4f32aeSBjoern A. Zeeb ieee80211_hw_set(ar->hw, SUPPORTS_RX_DECAP_OFFLOAD);
9467dd4f32aeSBjoern A. Zeeb }
9468dd4f32aeSBjoern A. Zeeb
9469dd4f32aeSBjoern A. Zeeb if (cap->nss_ratio_enabled)
9470dd4f32aeSBjoern A. Zeeb ieee80211_hw_set(ar->hw, SUPPORTS_VHT_EXT_NSS_BW);
9471dd4f32aeSBjoern A. Zeeb
9472dd4f32aeSBjoern A. Zeeb if ((ht_cap & WMI_HT_CAP_ENABLED) || ar->supports_6ghz) {
9473dd4f32aeSBjoern A. Zeeb ieee80211_hw_set(ar->hw, AMPDU_AGGREGATION);
9474dd4f32aeSBjoern A. Zeeb ieee80211_hw_set(ar->hw, TX_AMPDU_SETUP_IN_HW);
9475dd4f32aeSBjoern A. Zeeb ieee80211_hw_set(ar->hw, SUPPORTS_REORDERING_BUFFER);
9476dd4f32aeSBjoern A. Zeeb ieee80211_hw_set(ar->hw, SUPPORTS_AMSDU_IN_AMPDU);
9477dd4f32aeSBjoern A. Zeeb ieee80211_hw_set(ar->hw, USES_RSS);
9478dd4f32aeSBjoern A. Zeeb }
9479dd4f32aeSBjoern A. Zeeb
9480dd4f32aeSBjoern A. Zeeb ar->hw->wiphy->features |= NL80211_FEATURE_STATIC_SMPS;
9481dd4f32aeSBjoern A. Zeeb ar->hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
9482dd4f32aeSBjoern A. Zeeb
9483dd4f32aeSBjoern A. Zeeb /* TODO: Check if HT capability advertised from firmware is different
9484dd4f32aeSBjoern A. Zeeb * for each band for a dual band capable radio. It will be tricky to
9485dd4f32aeSBjoern A. Zeeb * handle it when the ht capability different for each band.
9486dd4f32aeSBjoern A. Zeeb */
9487dd4f32aeSBjoern A. Zeeb if (ht_cap & WMI_HT_CAP_DYNAMIC_SMPS ||
9488dd4f32aeSBjoern A. Zeeb (ar->supports_6ghz && ab->hw_params.supports_dynamic_smps_6ghz))
9489dd4f32aeSBjoern A. Zeeb ar->hw->wiphy->features |= NL80211_FEATURE_DYNAMIC_SMPS;
9490dd4f32aeSBjoern A. Zeeb
9491dd4f32aeSBjoern A. Zeeb ar->hw->wiphy->max_scan_ssids = WLAN_SCAN_PARAMS_MAX_SSID;
9492dd4f32aeSBjoern A. Zeeb ar->hw->wiphy->max_scan_ie_len = WLAN_SCAN_PARAMS_MAX_IE_LEN;
9493dd4f32aeSBjoern A. Zeeb
9494dd4f32aeSBjoern A. Zeeb ar->hw->max_listen_interval = ATH11K_MAX_HW_LISTEN_INTERVAL;
9495dd4f32aeSBjoern A. Zeeb
9496dd4f32aeSBjoern A. Zeeb ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
9497dd4f32aeSBjoern A. Zeeb ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
9498dd4f32aeSBjoern A. Zeeb ar->hw->wiphy->max_remain_on_channel_duration = 5000;
9499dd4f32aeSBjoern A. Zeeb
9500dd4f32aeSBjoern A. Zeeb ar->hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
9501dd4f32aeSBjoern A. Zeeb ar->hw->wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE |
9502dd4f32aeSBjoern A. Zeeb NL80211_FEATURE_AP_SCAN;
9503dd4f32aeSBjoern A. Zeeb
9504dd4f32aeSBjoern A. Zeeb ar->max_num_stations = TARGET_NUM_STATIONS(ab);
9505dd4f32aeSBjoern A. Zeeb ar->max_num_peers = TARGET_NUM_PEERS_PDEV(ab);
9506dd4f32aeSBjoern A. Zeeb
9507dd4f32aeSBjoern A. Zeeb ar->hw->wiphy->max_ap_assoc_sta = ar->max_num_stations;
9508dd4f32aeSBjoern A. Zeeb
9509dd4f32aeSBjoern A. Zeeb if (test_bit(WMI_TLV_SERVICE_SPOOF_MAC_SUPPORT, ar->wmi->wmi_ab->svc_map)) {
9510dd4f32aeSBjoern A. Zeeb ar->hw->wiphy->features |=
9511dd4f32aeSBjoern A. Zeeb NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
9512dd4f32aeSBjoern A. Zeeb }
9513dd4f32aeSBjoern A. Zeeb
951428348caeSBjoern A. Zeeb if (test_bit(WMI_TLV_SERVICE_NLO, ar->wmi->wmi_ab->svc_map)) {
951528348caeSBjoern A. Zeeb ar->hw->wiphy->max_sched_scan_ssids = WMI_PNO_MAX_SUPP_NETWORKS;
951628348caeSBjoern A. Zeeb ar->hw->wiphy->max_match_sets = WMI_PNO_MAX_SUPP_NETWORKS;
951728348caeSBjoern A. Zeeb ar->hw->wiphy->max_sched_scan_ie_len = WMI_PNO_MAX_IE_LENGTH;
951828348caeSBjoern A. Zeeb ar->hw->wiphy->max_sched_scan_plans = WMI_PNO_MAX_SCHED_SCAN_PLANS;
951928348caeSBjoern A. Zeeb ar->hw->wiphy->max_sched_scan_plan_interval =
952028348caeSBjoern A. Zeeb WMI_PNO_MAX_SCHED_SCAN_PLAN_INT;
952128348caeSBjoern A. Zeeb ar->hw->wiphy->max_sched_scan_plan_iterations =
952228348caeSBjoern A. Zeeb WMI_PNO_MAX_SCHED_SCAN_PLAN_ITRNS;
952328348caeSBjoern A. Zeeb ar->hw->wiphy->features |= NL80211_FEATURE_ND_RANDOM_MAC_ADDR;
952428348caeSBjoern A. Zeeb }
952528348caeSBjoern A. Zeeb
952628348caeSBjoern A. Zeeb ret = ath11k_wow_init(ar);
952728348caeSBjoern A. Zeeb if (ret) {
952828348caeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to init wow: %d\n", ret);
952928348caeSBjoern A. Zeeb goto err_free_if_combs;
953028348caeSBjoern A. Zeeb }
953128348caeSBjoern A. Zeeb
953228348caeSBjoern A. Zeeb if (test_bit(WMI_TLV_SERVICE_TX_DATA_MGMT_ACK_RSSI,
953328348caeSBjoern A. Zeeb ar->ab->wmi_ab.svc_map))
953428348caeSBjoern A. Zeeb wiphy_ext_feature_set(ar->hw->wiphy,
953528348caeSBjoern A. Zeeb NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT);
953628348caeSBjoern A. Zeeb
9537dd4f32aeSBjoern A. Zeeb ar->hw->queues = ATH11K_HW_MAX_QUEUES;
9538dd4f32aeSBjoern A. Zeeb ar->hw->wiphy->tx_queue_len = ATH11K_QUEUE_LEN;
9539dd4f32aeSBjoern A. Zeeb ar->hw->offchannel_tx_hw_queue = ATH11K_HW_MAX_QUEUES - 1;
954028348caeSBjoern A. Zeeb ar->hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE;
9541dd4f32aeSBjoern A. Zeeb
9542dd4f32aeSBjoern A. Zeeb ar->hw->vif_data_size = sizeof(struct ath11k_vif);
9543dd4f32aeSBjoern A. Zeeb ar->hw->sta_data_size = sizeof(struct ath11k_sta);
9544dd4f32aeSBjoern A. Zeeb
9545dd4f32aeSBjoern A. Zeeb wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
9546dd4f32aeSBjoern A. Zeeb wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_STA_TX_PWR);
954728348caeSBjoern A. Zeeb if (test_bit(WMI_TLV_SERVICE_BSS_COLOR_OFFLOAD,
954828348caeSBjoern A. Zeeb ar->ab->wmi_ab.svc_map)) {
9549dd4f32aeSBjoern A. Zeeb wiphy_ext_feature_set(ar->hw->wiphy,
9550dd4f32aeSBjoern A. Zeeb NL80211_EXT_FEATURE_BSS_COLOR);
955128348caeSBjoern A. Zeeb ieee80211_hw_set(ar->hw, DETECTS_COLOR_COLLISION);
955228348caeSBjoern A. Zeeb }
9553dd4f32aeSBjoern A. Zeeb
9554dd4f32aeSBjoern A. Zeeb ar->hw->wiphy->cipher_suites = cipher_suites;
9555dd4f32aeSBjoern A. Zeeb ar->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
9556dd4f32aeSBjoern A. Zeeb
9557dd4f32aeSBjoern A. Zeeb ar->hw->wiphy->iftype_ext_capab = ath11k_iftypes_ext_capa;
9558dd4f32aeSBjoern A. Zeeb ar->hw->wiphy->num_iftype_ext_capab =
9559dd4f32aeSBjoern A. Zeeb ARRAY_SIZE(ath11k_iftypes_ext_capa);
9560dd4f32aeSBjoern A. Zeeb
9561dd4f32aeSBjoern A. Zeeb if (ar->supports_6ghz) {
9562dd4f32aeSBjoern A. Zeeb wiphy_ext_feature_set(ar->hw->wiphy,
9563dd4f32aeSBjoern A. Zeeb NL80211_EXT_FEATURE_FILS_DISCOVERY);
9564dd4f32aeSBjoern A. Zeeb wiphy_ext_feature_set(ar->hw->wiphy,
9565dd4f32aeSBjoern A. Zeeb NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP);
9566dd4f32aeSBjoern A. Zeeb }
9567dd4f32aeSBjoern A. Zeeb
956828348caeSBjoern A. Zeeb wiphy_ext_feature_set(ar->hw->wiphy,
956928348caeSBjoern A. Zeeb NL80211_EXT_FEATURE_SET_SCAN_DWELL);
957028348caeSBjoern A. Zeeb
957128348caeSBjoern A. Zeeb if (test_bit(WMI_TLV_SERVICE_RTT, ar->ab->wmi_ab.svc_map))
957228348caeSBjoern A. Zeeb wiphy_ext_feature_set(ar->hw->wiphy,
957328348caeSBjoern A. Zeeb NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER);
957428348caeSBjoern A. Zeeb
957528348caeSBjoern A. Zeeb ar->hw->wiphy->mbssid_max_interfaces = TARGET_NUM_VDEVS(ab);
957628348caeSBjoern A. Zeeb ar->hw->wiphy->ema_max_profile_periodicity = TARGET_EMA_MAX_PROFILE_PERIOD;
957728348caeSBjoern A. Zeeb
9578dd4f32aeSBjoern A. Zeeb ath11k_reg_init(ar);
9579dd4f32aeSBjoern A. Zeeb
9580dd4f32aeSBjoern A. Zeeb if (!test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags)) {
9581dd4f32aeSBjoern A. Zeeb ar->hw->netdev_features = NETIF_F_HW_CSUM;
9582dd4f32aeSBjoern A. Zeeb ieee80211_hw_set(ar->hw, SW_CRYPTO_CONTROL);
9583dd4f32aeSBjoern A. Zeeb ieee80211_hw_set(ar->hw, SUPPORT_FAST_XMIT);
9584dd4f32aeSBjoern A. Zeeb }
9585dd4f32aeSBjoern A. Zeeb
958628348caeSBjoern A. Zeeb if (test_bit(WMI_TLV_SERVICE_BIOS_SAR_SUPPORT, ar->ab->wmi_ab.svc_map) &&
958728348caeSBjoern A. Zeeb ab->hw_params.bios_sar_capa)
958828348caeSBjoern A. Zeeb ar->hw->wiphy->sar_capa = ab->hw_params.bios_sar_capa;
958928348caeSBjoern A. Zeeb
9590dd4f32aeSBjoern A. Zeeb ret = ieee80211_register_hw(ar->hw);
9591dd4f32aeSBjoern A. Zeeb if (ret) {
9592dd4f32aeSBjoern A. Zeeb ath11k_err(ar->ab, "ieee80211 registration failed: %d\n", ret);
9593dd4f32aeSBjoern A. Zeeb goto err_free_if_combs;
9594dd4f32aeSBjoern A. Zeeb }
9595dd4f32aeSBjoern A. Zeeb
9596dd4f32aeSBjoern A. Zeeb if (!ab->hw_params.supports_monitor)
9597dd4f32aeSBjoern A. Zeeb /* There's a race between calling ieee80211_register_hw()
9598dd4f32aeSBjoern A. Zeeb * and here where the monitor mode is enabled for a little
9599dd4f32aeSBjoern A. Zeeb * while. But that time is so short and in practise it make
9600dd4f32aeSBjoern A. Zeeb * a difference in real life.
9601dd4f32aeSBjoern A. Zeeb */
9602dd4f32aeSBjoern A. Zeeb ar->hw->wiphy->interface_modes &= ~BIT(NL80211_IFTYPE_MONITOR);
9603dd4f32aeSBjoern A. Zeeb
9604dd4f32aeSBjoern A. Zeeb /* Apply the regd received during initialization */
9605dd4f32aeSBjoern A. Zeeb ret = ath11k_regd_update(ar);
9606dd4f32aeSBjoern A. Zeeb if (ret) {
9607dd4f32aeSBjoern A. Zeeb ath11k_err(ar->ab, "ath11k regd update failed: %d\n", ret);
9608dd4f32aeSBjoern A. Zeeb goto err_unregister_hw;
9609dd4f32aeSBjoern A. Zeeb }
9610dd4f32aeSBjoern A. Zeeb
961128348caeSBjoern A. Zeeb if (ab->hw_params.current_cc_support && ab->new_alpha2[0]) {
961228348caeSBjoern A. Zeeb struct wmi_set_current_country_params set_current_param = {};
961328348caeSBjoern A. Zeeb
961428348caeSBjoern A. Zeeb memcpy(&set_current_param.alpha2, ab->new_alpha2, 2);
961528348caeSBjoern A. Zeeb memcpy(&ar->alpha2, ab->new_alpha2, 2);
961628348caeSBjoern A. Zeeb ret = ath11k_wmi_send_set_current_country_cmd(ar, &set_current_param);
961728348caeSBjoern A. Zeeb if (ret)
961828348caeSBjoern A. Zeeb ath11k_warn(ar->ab,
961928348caeSBjoern A. Zeeb "failed set cc code for mac register: %d\n", ret);
962028348caeSBjoern A. Zeeb }
962128348caeSBjoern A. Zeeb
9622dd4f32aeSBjoern A. Zeeb ret = ath11k_debugfs_register(ar);
9623dd4f32aeSBjoern A. Zeeb if (ret) {
9624dd4f32aeSBjoern A. Zeeb ath11k_err(ar->ab, "debugfs registration failed: %d\n", ret);
9625dd4f32aeSBjoern A. Zeeb goto err_unregister_hw;
9626dd4f32aeSBjoern A. Zeeb }
9627dd4f32aeSBjoern A. Zeeb
9628dd4f32aeSBjoern A. Zeeb return 0;
9629dd4f32aeSBjoern A. Zeeb
9630dd4f32aeSBjoern A. Zeeb err_unregister_hw:
9631dd4f32aeSBjoern A. Zeeb ieee80211_unregister_hw(ar->hw);
9632dd4f32aeSBjoern A. Zeeb
9633dd4f32aeSBjoern A. Zeeb err_free_if_combs:
9634dd4f32aeSBjoern A. Zeeb kfree(ar->hw->wiphy->iface_combinations[0].limits);
9635dd4f32aeSBjoern A. Zeeb kfree(ar->hw->wiphy->iface_combinations);
9636dd4f32aeSBjoern A. Zeeb
9637dd4f32aeSBjoern A. Zeeb err_free_channels:
9638dd4f32aeSBjoern A. Zeeb kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels);
9639dd4f32aeSBjoern A. Zeeb kfree(ar->mac.sbands[NL80211_BAND_5GHZ].channels);
9640dd4f32aeSBjoern A. Zeeb kfree(ar->mac.sbands[NL80211_BAND_6GHZ].channels);
9641dd4f32aeSBjoern A. Zeeb
9642dd4f32aeSBjoern A. Zeeb err:
9643dd4f32aeSBjoern A. Zeeb SET_IEEE80211_DEV(ar->hw, NULL);
9644dd4f32aeSBjoern A. Zeeb return ret;
9645dd4f32aeSBjoern A. Zeeb }
9646dd4f32aeSBjoern A. Zeeb
ath11k_mac_register(struct ath11k_base * ab)9647dd4f32aeSBjoern A. Zeeb int ath11k_mac_register(struct ath11k_base *ab)
9648dd4f32aeSBjoern A. Zeeb {
9649dd4f32aeSBjoern A. Zeeb struct ath11k *ar;
9650dd4f32aeSBjoern A. Zeeb struct ath11k_pdev *pdev;
9651dd4f32aeSBjoern A. Zeeb int i;
9652dd4f32aeSBjoern A. Zeeb int ret;
965328348caeSBjoern A. Zeeb u8 mac_addr[ETH_ALEN] = {0};
9654dd4f32aeSBjoern A. Zeeb
9655dd4f32aeSBjoern A. Zeeb if (test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags))
9656dd4f32aeSBjoern A. Zeeb return 0;
9657dd4f32aeSBjoern A. Zeeb
9658dd4f32aeSBjoern A. Zeeb /* Initialize channel counters frequency value in hertz */
9659dd4f32aeSBjoern A. Zeeb ab->cc_freq_hz = IPQ8074_CC_FREQ_HERTZ;
9660dd4f32aeSBjoern A. Zeeb ab->free_vdev_map = (1LL << (ab->num_radios * TARGET_NUM_VDEVS(ab))) - 1;
9661dd4f32aeSBjoern A. Zeeb
966228348caeSBjoern A. Zeeb ret = ath11k_peer_rhash_tbl_init(ab);
966328348caeSBjoern A. Zeeb if (ret)
966428348caeSBjoern A. Zeeb return ret;
966528348caeSBjoern A. Zeeb
966628348caeSBjoern A. Zeeb device_get_mac_address(ab->dev, mac_addr);
966728348caeSBjoern A. Zeeb
9668dd4f32aeSBjoern A. Zeeb for (i = 0; i < ab->num_radios; i++) {
9669dd4f32aeSBjoern A. Zeeb pdev = &ab->pdevs[i];
9670dd4f32aeSBjoern A. Zeeb ar = pdev->ar;
9671dd4f32aeSBjoern A. Zeeb if (ab->pdevs_macaddr_valid) {
9672dd4f32aeSBjoern A. Zeeb ether_addr_copy(ar->mac_addr, pdev->mac_addr);
9673dd4f32aeSBjoern A. Zeeb } else {
967428348caeSBjoern A. Zeeb if (is_zero_ether_addr(mac_addr))
9675dd4f32aeSBjoern A. Zeeb ether_addr_copy(ar->mac_addr, ab->mac_addr);
967628348caeSBjoern A. Zeeb else
967728348caeSBjoern A. Zeeb ether_addr_copy(ar->mac_addr, mac_addr);
9678dd4f32aeSBjoern A. Zeeb ar->mac_addr[4] += i;
9679dd4f32aeSBjoern A. Zeeb }
9680dd4f32aeSBjoern A. Zeeb
9681dd4f32aeSBjoern A. Zeeb idr_init(&ar->txmgmt_idr);
9682dd4f32aeSBjoern A. Zeeb spin_lock_init(&ar->txmgmt_idr_lock);
9683dd4f32aeSBjoern A. Zeeb
9684dd4f32aeSBjoern A. Zeeb ret = __ath11k_mac_register(ar);
9685dd4f32aeSBjoern A. Zeeb if (ret)
9686dd4f32aeSBjoern A. Zeeb goto err_cleanup;
9687dd4f32aeSBjoern A. Zeeb
9688dd4f32aeSBjoern A. Zeeb init_waitqueue_head(&ar->txmgmt_empty_waitq);
9689dd4f32aeSBjoern A. Zeeb }
9690dd4f32aeSBjoern A. Zeeb
9691dd4f32aeSBjoern A. Zeeb return 0;
9692dd4f32aeSBjoern A. Zeeb
9693dd4f32aeSBjoern A. Zeeb err_cleanup:
9694dd4f32aeSBjoern A. Zeeb for (i = i - 1; i >= 0; i--) {
9695dd4f32aeSBjoern A. Zeeb pdev = &ab->pdevs[i];
9696dd4f32aeSBjoern A. Zeeb ar = pdev->ar;
9697dd4f32aeSBjoern A. Zeeb __ath11k_mac_unregister(ar);
9698dd4f32aeSBjoern A. Zeeb }
9699dd4f32aeSBjoern A. Zeeb
970028348caeSBjoern A. Zeeb ath11k_peer_rhash_tbl_destroy(ab);
970128348caeSBjoern A. Zeeb
9702dd4f32aeSBjoern A. Zeeb return ret;
9703dd4f32aeSBjoern A. Zeeb }
9704dd4f32aeSBjoern A. Zeeb
ath11k_mac_allocate(struct ath11k_base * ab)9705dd4f32aeSBjoern A. Zeeb int ath11k_mac_allocate(struct ath11k_base *ab)
9706dd4f32aeSBjoern A. Zeeb {
9707dd4f32aeSBjoern A. Zeeb struct ieee80211_hw *hw;
9708dd4f32aeSBjoern A. Zeeb struct ath11k *ar;
9709dd4f32aeSBjoern A. Zeeb struct ath11k_pdev *pdev;
9710dd4f32aeSBjoern A. Zeeb int ret;
9711dd4f32aeSBjoern A. Zeeb int i;
9712dd4f32aeSBjoern A. Zeeb
9713dd4f32aeSBjoern A. Zeeb if (test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags))
9714dd4f32aeSBjoern A. Zeeb return 0;
9715dd4f32aeSBjoern A. Zeeb
9716dd4f32aeSBjoern A. Zeeb for (i = 0; i < ab->num_radios; i++) {
9717dd4f32aeSBjoern A. Zeeb pdev = &ab->pdevs[i];
9718dd4f32aeSBjoern A. Zeeb hw = ieee80211_alloc_hw(sizeof(struct ath11k), &ath11k_ops);
9719dd4f32aeSBjoern A. Zeeb if (!hw) {
9720dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, "failed to allocate mac80211 hw device\n");
9721dd4f32aeSBjoern A. Zeeb ret = -ENOMEM;
9722dd4f32aeSBjoern A. Zeeb goto err_free_mac;
9723dd4f32aeSBjoern A. Zeeb }
9724dd4f32aeSBjoern A. Zeeb
9725dd4f32aeSBjoern A. Zeeb ar = hw->priv;
9726dd4f32aeSBjoern A. Zeeb ar->hw = hw;
9727dd4f32aeSBjoern A. Zeeb ar->ab = ab;
9728dd4f32aeSBjoern A. Zeeb ar->pdev = pdev;
9729dd4f32aeSBjoern A. Zeeb ar->pdev_idx = i;
9730dd4f32aeSBjoern A. Zeeb ar->lmac_id = ath11k_hw_get_mac_from_pdev_id(&ab->hw_params, i);
9731dd4f32aeSBjoern A. Zeeb
9732dd4f32aeSBjoern A. Zeeb ar->wmi = &ab->wmi_ab.wmi[i];
9733dd4f32aeSBjoern A. Zeeb /* FIXME wmi[0] is already initialized during attach,
9734dd4f32aeSBjoern A. Zeeb * Should we do this again?
9735dd4f32aeSBjoern A. Zeeb */
9736dd4f32aeSBjoern A. Zeeb ath11k_wmi_pdev_attach(ab, i);
9737dd4f32aeSBjoern A. Zeeb
9738dd4f32aeSBjoern A. Zeeb ar->cfg_tx_chainmask = pdev->cap.tx_chain_mask;
9739dd4f32aeSBjoern A. Zeeb ar->cfg_rx_chainmask = pdev->cap.rx_chain_mask;
9740dd4f32aeSBjoern A. Zeeb ar->num_tx_chains = get_num_chains(pdev->cap.tx_chain_mask);
9741dd4f32aeSBjoern A. Zeeb ar->num_rx_chains = get_num_chains(pdev->cap.rx_chain_mask);
9742dd4f32aeSBjoern A. Zeeb
9743dd4f32aeSBjoern A. Zeeb pdev->ar = ar;
9744dd4f32aeSBjoern A. Zeeb spin_lock_init(&ar->data_lock);
9745dd4f32aeSBjoern A. Zeeb INIT_LIST_HEAD(&ar->arvifs);
9746dd4f32aeSBjoern A. Zeeb INIT_LIST_HEAD(&ar->ppdu_stats_info);
9747dd4f32aeSBjoern A. Zeeb mutex_init(&ar->conf_mutex);
9748dd4f32aeSBjoern A. Zeeb init_completion(&ar->vdev_setup_done);
9749dd4f32aeSBjoern A. Zeeb init_completion(&ar->vdev_delete_done);
9750dd4f32aeSBjoern A. Zeeb init_completion(&ar->peer_assoc_done);
9751dd4f32aeSBjoern A. Zeeb init_completion(&ar->peer_delete_done);
9752dd4f32aeSBjoern A. Zeeb init_completion(&ar->install_key_done);
9753dd4f32aeSBjoern A. Zeeb init_completion(&ar->bss_survey_done);
9754dd4f32aeSBjoern A. Zeeb init_completion(&ar->scan.started);
9755dd4f32aeSBjoern A. Zeeb init_completion(&ar->scan.completed);
975628348caeSBjoern A. Zeeb init_completion(&ar->scan.on_channel);
9757dd4f32aeSBjoern A. Zeeb init_completion(&ar->thermal.wmi_sync);
9758dd4f32aeSBjoern A. Zeeb
9759dd4f32aeSBjoern A. Zeeb INIT_DELAYED_WORK(&ar->scan.timeout, ath11k_scan_timeout_work);
9760dd4f32aeSBjoern A. Zeeb INIT_WORK(&ar->regd_update_work, ath11k_regd_update_work);
9761dd4f32aeSBjoern A. Zeeb
9762dd4f32aeSBjoern A. Zeeb INIT_WORK(&ar->wmi_mgmt_tx_work, ath11k_mgmt_over_wmi_tx_work);
9763dd4f32aeSBjoern A. Zeeb skb_queue_head_init(&ar->wmi_mgmt_tx_queue);
9764dd4f32aeSBjoern A. Zeeb
9765dd4f32aeSBjoern A. Zeeb clear_bit(ATH11K_FLAG_MONITOR_STARTED, &ar->monitor_flags);
9766dd4f32aeSBjoern A. Zeeb
9767dd4f32aeSBjoern A. Zeeb ar->monitor_vdev_id = -1;
9768dd4f32aeSBjoern A. Zeeb clear_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags);
9769dd4f32aeSBjoern A. Zeeb ar->vdev_id_11d_scan = ATH11K_11D_INVALID_VDEV_ID;
977028348caeSBjoern A. Zeeb init_completion(&ar->completed_11d_scan);
977128348caeSBjoern A. Zeeb
977228348caeSBjoern A. Zeeb ath11k_fw_stats_init(ar);
9773dd4f32aeSBjoern A. Zeeb }
9774dd4f32aeSBjoern A. Zeeb
9775dd4f32aeSBjoern A. Zeeb return 0;
9776dd4f32aeSBjoern A. Zeeb
9777dd4f32aeSBjoern A. Zeeb err_free_mac:
9778dd4f32aeSBjoern A. Zeeb ath11k_mac_destroy(ab);
9779dd4f32aeSBjoern A. Zeeb
9780dd4f32aeSBjoern A. Zeeb return ret;
9781dd4f32aeSBjoern A. Zeeb }
9782dd4f32aeSBjoern A. Zeeb
ath11k_mac_destroy(struct ath11k_base * ab)9783dd4f32aeSBjoern A. Zeeb void ath11k_mac_destroy(struct ath11k_base *ab)
9784dd4f32aeSBjoern A. Zeeb {
9785dd4f32aeSBjoern A. Zeeb struct ath11k *ar;
9786dd4f32aeSBjoern A. Zeeb struct ath11k_pdev *pdev;
9787dd4f32aeSBjoern A. Zeeb int i;
9788dd4f32aeSBjoern A. Zeeb
9789dd4f32aeSBjoern A. Zeeb for (i = 0; i < ab->num_radios; i++) {
9790dd4f32aeSBjoern A. Zeeb pdev = &ab->pdevs[i];
9791dd4f32aeSBjoern A. Zeeb ar = pdev->ar;
9792dd4f32aeSBjoern A. Zeeb if (!ar)
9793dd4f32aeSBjoern A. Zeeb continue;
9794dd4f32aeSBjoern A. Zeeb
979528348caeSBjoern A. Zeeb ath11k_fw_stats_free(&ar->fw_stats);
9796dd4f32aeSBjoern A. Zeeb ieee80211_free_hw(ar->hw);
9797dd4f32aeSBjoern A. Zeeb pdev->ar = NULL;
9798dd4f32aeSBjoern A. Zeeb }
9799dd4f32aeSBjoern A. Zeeb }
980028348caeSBjoern A. Zeeb
ath11k_mac_vif_set_keepalive(struct ath11k_vif * arvif,enum wmi_sta_keepalive_method method,u32 interval)980128348caeSBjoern A. Zeeb int ath11k_mac_vif_set_keepalive(struct ath11k_vif *arvif,
980228348caeSBjoern A. Zeeb enum wmi_sta_keepalive_method method,
980328348caeSBjoern A. Zeeb u32 interval)
980428348caeSBjoern A. Zeeb {
980528348caeSBjoern A. Zeeb struct ath11k *ar = arvif->ar;
980628348caeSBjoern A. Zeeb struct wmi_sta_keepalive_arg arg = {};
980728348caeSBjoern A. Zeeb int ret;
980828348caeSBjoern A. Zeeb
980928348caeSBjoern A. Zeeb lockdep_assert_held(&ar->conf_mutex);
981028348caeSBjoern A. Zeeb
981128348caeSBjoern A. Zeeb if (arvif->vdev_type != WMI_VDEV_TYPE_STA)
981228348caeSBjoern A. Zeeb return 0;
981328348caeSBjoern A. Zeeb
981428348caeSBjoern A. Zeeb if (!test_bit(WMI_TLV_SERVICE_STA_KEEP_ALIVE, ar->ab->wmi_ab.svc_map))
981528348caeSBjoern A. Zeeb return 0;
981628348caeSBjoern A. Zeeb
981728348caeSBjoern A. Zeeb arg.vdev_id = arvif->vdev_id;
981828348caeSBjoern A. Zeeb arg.enabled = 1;
981928348caeSBjoern A. Zeeb arg.method = method;
982028348caeSBjoern A. Zeeb arg.interval = interval;
982128348caeSBjoern A. Zeeb
982228348caeSBjoern A. Zeeb ret = ath11k_wmi_sta_keepalive(ar, &arg);
982328348caeSBjoern A. Zeeb if (ret) {
982428348caeSBjoern A. Zeeb ath11k_warn(ar->ab, "failed to set keepalive on vdev %i: %d\n",
982528348caeSBjoern A. Zeeb arvif->vdev_id, ret);
982628348caeSBjoern A. Zeeb return ret;
982728348caeSBjoern A. Zeeb }
982828348caeSBjoern A. Zeeb
982928348caeSBjoern A. Zeeb return 0;
983028348caeSBjoern A. Zeeb }
9831