1*5113495bSYour Name /*
2*5113495bSYour Name * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved.
3*5113495bSYour Name * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
4*5113495bSYour Name *
5*5113495bSYour Name * Permission to use, copy, modify, and/or distribute this software for
6*5113495bSYour Name * any purpose with or without fee is hereby granted, provided that the
7*5113495bSYour Name * above copyright notice and this permission notice appear in all
8*5113495bSYour Name * copies.
9*5113495bSYour Name *
10*5113495bSYour Name * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11*5113495bSYour Name * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12*5113495bSYour Name * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13*5113495bSYour Name * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14*5113495bSYour Name * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15*5113495bSYour Name * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16*5113495bSYour Name * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*5113495bSYour Name * PERFORMANCE OF THIS SOFTWARE.
18*5113495bSYour Name */
19*5113495bSYour Name
20*5113495bSYour Name /**
21*5113495bSYour Name * DOC: wma_data.c
22*5113495bSYour Name * This file contains tx/rx and data path related functions.
23*5113495bSYour Name */
24*5113495bSYour Name
25*5113495bSYour Name /* Header files */
26*5113495bSYour Name
27*5113495bSYour Name #include "wma.h"
28*5113495bSYour Name #include "enet.h"
29*5113495bSYour Name #include "wma_api.h"
30*5113495bSYour Name #include "cds_api.h"
31*5113495bSYour Name #include "wmi_unified_api.h"
32*5113495bSYour Name #include "wlan_qct_sys.h"
33*5113495bSYour Name #include "wni_api.h"
34*5113495bSYour Name #include "ani_global.h"
35*5113495bSYour Name #include "wmi_unified.h"
36*5113495bSYour Name #include "wni_cfg.h"
37*5113495bSYour Name #include <cdp_txrx_tx_throttle.h>
38*5113495bSYour Name #if defined(CONFIG_HL_SUPPORT)
39*5113495bSYour Name #include "wlan_tgt_def_config_hl.h"
40*5113495bSYour Name #else
41*5113495bSYour Name #include "wlan_tgt_def_config.h"
42*5113495bSYour Name #endif
43*5113495bSYour Name #include "qdf_nbuf.h"
44*5113495bSYour Name #include "qdf_types.h"
45*5113495bSYour Name #include "qdf_mem.h"
46*5113495bSYour Name #include "qdf_util.h"
47*5113495bSYour Name
48*5113495bSYour Name #include "wma_types.h"
49*5113495bSYour Name #include "lim_api.h"
50*5113495bSYour Name #include "lim_session_utils.h"
51*5113495bSYour Name
52*5113495bSYour Name #include "cds_utils.h"
53*5113495bSYour Name
54*5113495bSYour Name #if !defined(REMOVE_PKT_LOG)
55*5113495bSYour Name #include "pktlog_ac.h"
56*5113495bSYour Name #endif /* REMOVE_PKT_LOG */
57*5113495bSYour Name
58*5113495bSYour Name #include "dbglog_host.h"
59*5113495bSYour Name #include "csr_api.h"
60*5113495bSYour Name #include "ol_fw.h"
61*5113495bSYour Name
62*5113495bSYour Name #include "wma_internal.h"
63*5113495bSYour Name #include "cdp_txrx_flow_ctrl_legacy.h"
64*5113495bSYour Name #include "cdp_txrx_cmn.h"
65*5113495bSYour Name #include "cdp_txrx_misc.h"
66*5113495bSYour Name #include <cdp_txrx_peer_ops.h>
67*5113495bSYour Name #include <cdp_txrx_cfg.h>
68*5113495bSYour Name #include "cdp_txrx_stats.h"
69*5113495bSYour Name #include <cdp_txrx_misc.h>
70*5113495bSYour Name #include "wlan_mgmt_txrx_utils_api.h"
71*5113495bSYour Name #include "wlan_objmgr_psoc_obj.h"
72*5113495bSYour Name #include "wlan_objmgr_pdev_obj.h"
73*5113495bSYour Name #include "wlan_objmgr_vdev_obj.h"
74*5113495bSYour Name #include "wlan_objmgr_peer_obj.h"
75*5113495bSYour Name #include <cdp_txrx_handle.h>
76*5113495bSYour Name #include "cfg_ucfg_api.h"
77*5113495bSYour Name #include "wlan_policy_mgr_ucfg.h"
78*5113495bSYour Name #include <wlan_pmo_ucfg_api.h>
79*5113495bSYour Name #include "wlan_lmac_if_api.h"
80*5113495bSYour Name #include <wlan_cp_stats_mc_ucfg_api.h>
81*5113495bSYour Name #include <wlan_crypto_global_api.h>
82*5113495bSYour Name #include <wlan_mlme_main.h>
83*5113495bSYour Name #include <wlan_cm_api.h>
84*5113495bSYour Name #include "wlan_pkt_capture_ucfg_api.h"
85*5113495bSYour Name #include "wma_eht.h"
86*5113495bSYour Name #include "wlan_mlo_mgr_sta.h"
87*5113495bSYour Name #include "wlan_fw_offload_main.h"
88*5113495bSYour Name #include "target_if_fwol.h"
89*5113495bSYour Name
90*5113495bSYour Name struct wma_search_rate {
91*5113495bSYour Name int32_t rate;
92*5113495bSYour Name uint8_t flag;
93*5113495bSYour Name };
94*5113495bSYour Name
95*5113495bSYour Name #define WMA_MAX_OFDM_CCK_RATE_TBL_SIZE 12
96*5113495bSYour Name /* In ofdm_cck_rate_tbl->flag, if bit 7 is 1 it's CCK, otherwise it ofdm.
97*5113495bSYour Name * Lower bit carries the ofdm/cck index for encoding the rate
98*5113495bSYour Name */
99*5113495bSYour Name static struct wma_search_rate ofdm_cck_rate_tbl[WMA_MAX_OFDM_CCK_RATE_TBL_SIZE] = {
100*5113495bSYour Name {540, 4}, /* 4: OFDM 54 Mbps */
101*5113495bSYour Name {480, 0}, /* 0: OFDM 48 Mbps */
102*5113495bSYour Name {360, 5}, /* 5: OFDM 36 Mbps */
103*5113495bSYour Name {240, 1}, /* 1: OFDM 24 Mbps */
104*5113495bSYour Name {180, 6}, /* 6: OFDM 18 Mbps */
105*5113495bSYour Name {120, 2}, /* 2: OFDM 12 Mbps */
106*5113495bSYour Name {110, (1 << 7)}, /* 0: CCK 11 Mbps Long */
107*5113495bSYour Name {90, 7}, /* 7: OFDM 9 Mbps */
108*5113495bSYour Name {60, 3}, /* 3: OFDM 6 Mbps */
109*5113495bSYour Name {55, ((1 << 7) | 1)}, /* 1: CCK 5.5 Mbps Long */
110*5113495bSYour Name {20, ((1 << 7) | 2)}, /* 2: CCK 2 Mbps Long */
111*5113495bSYour Name {10, ((1 << 7) | 3)} /* 3: CCK 1 Mbps Long */
112*5113495bSYour Name };
113*5113495bSYour Name
114*5113495bSYour Name #define WMA_MAX_VHT20_RATE_TBL_SIZE 9
115*5113495bSYour Name /* In vht20_400ns_rate_tbl flag carries the mcs index for encoding the rate */
116*5113495bSYour Name static struct wma_search_rate vht20_400ns_rate_tbl[WMA_MAX_VHT20_RATE_TBL_SIZE] = {
117*5113495bSYour Name {867, 8}, /* MCS8 1SS short GI */
118*5113495bSYour Name {722, 7}, /* MCS7 1SS short GI */
119*5113495bSYour Name {650, 6}, /* MCS6 1SS short GI */
120*5113495bSYour Name {578, 5}, /* MCS5 1SS short GI */
121*5113495bSYour Name {433, 4}, /* MCS4 1SS short GI */
122*5113495bSYour Name {289, 3}, /* MCS3 1SS short GI */
123*5113495bSYour Name {217, 2}, /* MCS2 1SS short GI */
124*5113495bSYour Name {144, 1}, /* MCS1 1SS short GI */
125*5113495bSYour Name {72, 0} /* MCS0 1SS short GI */
126*5113495bSYour Name };
127*5113495bSYour Name
128*5113495bSYour Name /* In vht20_800ns_rate_tbl flag carries the mcs index for encoding the rate */
129*5113495bSYour Name static struct wma_search_rate vht20_800ns_rate_tbl[WMA_MAX_VHT20_RATE_TBL_SIZE] = {
130*5113495bSYour Name {780, 8}, /* MCS8 1SS long GI */
131*5113495bSYour Name {650, 7}, /* MCS7 1SS long GI */
132*5113495bSYour Name {585, 6}, /* MCS6 1SS long GI */
133*5113495bSYour Name {520, 5}, /* MCS5 1SS long GI */
134*5113495bSYour Name {390, 4}, /* MCS4 1SS long GI */
135*5113495bSYour Name {260, 3}, /* MCS3 1SS long GI */
136*5113495bSYour Name {195, 2}, /* MCS2 1SS long GI */
137*5113495bSYour Name {130, 1}, /* MCS1 1SS long GI */
138*5113495bSYour Name {65, 0} /* MCS0 1SS long GI */
139*5113495bSYour Name };
140*5113495bSYour Name
141*5113495bSYour Name #define WMA_MAX_VHT40_RATE_TBL_SIZE 10
142*5113495bSYour Name /* In vht40_400ns_rate_tbl flag carries the mcs index for encoding the rate */
143*5113495bSYour Name static struct wma_search_rate vht40_400ns_rate_tbl[WMA_MAX_VHT40_RATE_TBL_SIZE] = {
144*5113495bSYour Name {2000, 9}, /* MCS9 1SS short GI */
145*5113495bSYour Name {1800, 8}, /* MCS8 1SS short GI */
146*5113495bSYour Name {1500, 7}, /* MCS7 1SS short GI */
147*5113495bSYour Name {1350, 6}, /* MCS6 1SS short GI */
148*5113495bSYour Name {1200, 5}, /* MCS5 1SS short GI */
149*5113495bSYour Name {900, 4}, /* MCS4 1SS short GI */
150*5113495bSYour Name {600, 3}, /* MCS3 1SS short GI */
151*5113495bSYour Name {450, 2}, /* MCS2 1SS short GI */
152*5113495bSYour Name {300, 1}, /* MCS1 1SS short GI */
153*5113495bSYour Name {150, 0}, /* MCS0 1SS short GI */
154*5113495bSYour Name };
155*5113495bSYour Name
156*5113495bSYour Name static struct wma_search_rate vht40_800ns_rate_tbl[WMA_MAX_VHT40_RATE_TBL_SIZE] = {
157*5113495bSYour Name {1800, 9}, /* MCS9 1SS long GI */
158*5113495bSYour Name {1620, 8}, /* MCS8 1SS long GI */
159*5113495bSYour Name {1350, 7}, /* MCS7 1SS long GI */
160*5113495bSYour Name {1215, 6}, /* MCS6 1SS long GI */
161*5113495bSYour Name {1080, 5}, /* MCS5 1SS long GI */
162*5113495bSYour Name {810, 4}, /* MCS4 1SS long GI */
163*5113495bSYour Name {540, 3}, /* MCS3 1SS long GI */
164*5113495bSYour Name {405, 2}, /* MCS2 1SS long GI */
165*5113495bSYour Name {270, 1}, /* MCS1 1SS long GI */
166*5113495bSYour Name {135, 0} /* MCS0 1SS long GI */
167*5113495bSYour Name };
168*5113495bSYour Name
169*5113495bSYour Name #define WMA_MAX_VHT80_RATE_TBL_SIZE 10
170*5113495bSYour Name static struct wma_search_rate vht80_400ns_rate_tbl[WMA_MAX_VHT80_RATE_TBL_SIZE] = {
171*5113495bSYour Name {4333, 9}, /* MCS9 1SS short GI */
172*5113495bSYour Name {3900, 8}, /* MCS8 1SS short GI */
173*5113495bSYour Name {3250, 7}, /* MCS7 1SS short GI */
174*5113495bSYour Name {2925, 6}, /* MCS6 1SS short GI */
175*5113495bSYour Name {2600, 5}, /* MCS5 1SS short GI */
176*5113495bSYour Name {1950, 4}, /* MCS4 1SS short GI */
177*5113495bSYour Name {1300, 3}, /* MCS3 1SS short GI */
178*5113495bSYour Name {975, 2}, /* MCS2 1SS short GI */
179*5113495bSYour Name {650, 1}, /* MCS1 1SS short GI */
180*5113495bSYour Name {325, 0} /* MCS0 1SS short GI */
181*5113495bSYour Name };
182*5113495bSYour Name
183*5113495bSYour Name static struct wma_search_rate vht80_800ns_rate_tbl[WMA_MAX_VHT80_RATE_TBL_SIZE] = {
184*5113495bSYour Name {3900, 9}, /* MCS9 1SS long GI */
185*5113495bSYour Name {3510, 8}, /* MCS8 1SS long GI */
186*5113495bSYour Name {2925, 7}, /* MCS7 1SS long GI */
187*5113495bSYour Name {2633, 6}, /* MCS6 1SS long GI */
188*5113495bSYour Name {2340, 5}, /* MCS5 1SS long GI */
189*5113495bSYour Name {1755, 4}, /* MCS4 1SS long GI */
190*5113495bSYour Name {1170, 3}, /* MCS3 1SS long GI */
191*5113495bSYour Name {878, 2}, /* MCS2 1SS long GI */
192*5113495bSYour Name {585, 1}, /* MCS1 1SS long GI */
193*5113495bSYour Name {293, 0} /* MCS0 1SS long GI */
194*5113495bSYour Name };
195*5113495bSYour Name
196*5113495bSYour Name #define WMA_MAX_HT20_RATE_TBL_SIZE 8
197*5113495bSYour Name static struct wma_search_rate ht20_400ns_rate_tbl[WMA_MAX_HT20_RATE_TBL_SIZE] = {
198*5113495bSYour Name {722, 7}, /* MCS7 1SS short GI */
199*5113495bSYour Name {650, 6}, /* MCS6 1SS short GI */
200*5113495bSYour Name {578, 5}, /* MCS5 1SS short GI */
201*5113495bSYour Name {433, 4}, /* MCS4 1SS short GI */
202*5113495bSYour Name {289, 3}, /* MCS3 1SS short GI */
203*5113495bSYour Name {217, 2}, /* MCS2 1SS short GI */
204*5113495bSYour Name {144, 1}, /* MCS1 1SS short GI */
205*5113495bSYour Name {72, 0} /* MCS0 1SS short GI */
206*5113495bSYour Name };
207*5113495bSYour Name
208*5113495bSYour Name static struct wma_search_rate ht20_800ns_rate_tbl[WMA_MAX_HT20_RATE_TBL_SIZE] = {
209*5113495bSYour Name {650, 7}, /* MCS7 1SS long GI */
210*5113495bSYour Name {585, 6}, /* MCS6 1SS long GI */
211*5113495bSYour Name {520, 5}, /* MCS5 1SS long GI */
212*5113495bSYour Name {390, 4}, /* MCS4 1SS long GI */
213*5113495bSYour Name {260, 3}, /* MCS3 1SS long GI */
214*5113495bSYour Name {195, 2}, /* MCS2 1SS long GI */
215*5113495bSYour Name {130, 1}, /* MCS1 1SS long GI */
216*5113495bSYour Name {65, 0} /* MCS0 1SS long GI */
217*5113495bSYour Name };
218*5113495bSYour Name
219*5113495bSYour Name #define WMA_MAX_HT40_RATE_TBL_SIZE 8
220*5113495bSYour Name static struct wma_search_rate ht40_400ns_rate_tbl[WMA_MAX_HT40_RATE_TBL_SIZE] = {
221*5113495bSYour Name {1500, 7}, /* MCS7 1SS short GI */
222*5113495bSYour Name {1350, 6}, /* MCS6 1SS short GI */
223*5113495bSYour Name {1200, 5}, /* MCS5 1SS short GI */
224*5113495bSYour Name {900, 4}, /* MCS4 1SS short GI */
225*5113495bSYour Name {600, 3}, /* MCS3 1SS short GI */
226*5113495bSYour Name {450, 2}, /* MCS2 1SS short GI */
227*5113495bSYour Name {300, 1}, /* MCS1 1SS short GI */
228*5113495bSYour Name {150, 0} /* MCS0 1SS short GI */
229*5113495bSYour Name };
230*5113495bSYour Name
231*5113495bSYour Name static struct wma_search_rate ht40_800ns_rate_tbl[WMA_MAX_HT40_RATE_TBL_SIZE] = {
232*5113495bSYour Name {1350, 7}, /* MCS7 1SS long GI */
233*5113495bSYour Name {1215, 6}, /* MCS6 1SS long GI */
234*5113495bSYour Name {1080, 5}, /* MCS5 1SS long GI */
235*5113495bSYour Name {810, 4}, /* MCS4 1SS long GI */
236*5113495bSYour Name {540, 3}, /* MCS3 1SS long GI */
237*5113495bSYour Name {405, 2}, /* MCS2 1SS long GI */
238*5113495bSYour Name {270, 1}, /* MCS1 1SS long GI */
239*5113495bSYour Name {135, 0} /* MCS0 1SS long GI */
240*5113495bSYour Name };
241*5113495bSYour Name
242*5113495bSYour Name /**
243*5113495bSYour Name * wma_bin_search_rate() - binary search function to find rate
244*5113495bSYour Name * @tbl: rate table
245*5113495bSYour Name * @tbl_size: table size
246*5113495bSYour Name * @mbpsx10_rate: return mbps rate
247*5113495bSYour Name * @ret_flag: return flag
248*5113495bSYour Name *
249*5113495bSYour Name * Return: none
250*5113495bSYour Name */
wma_bin_search_rate(struct wma_search_rate * tbl,int32_t tbl_size,int32_t * mbpsx10_rate,uint8_t * ret_flag)251*5113495bSYour Name static void wma_bin_search_rate(struct wma_search_rate *tbl, int32_t tbl_size,
252*5113495bSYour Name int32_t *mbpsx10_rate, uint8_t *ret_flag)
253*5113495bSYour Name {
254*5113495bSYour Name int32_t upper, lower, mid;
255*5113495bSYour Name
256*5113495bSYour Name /* the table is descenting. index holds the largest value and the
257*5113495bSYour Name * bottom index holds the smallest value
258*5113495bSYour Name */
259*5113495bSYour Name
260*5113495bSYour Name upper = 0; /* index 0 */
261*5113495bSYour Name lower = tbl_size - 1; /* last index */
262*5113495bSYour Name
263*5113495bSYour Name if (*mbpsx10_rate >= tbl[upper].rate) {
264*5113495bSYour Name /* use the largest rate */
265*5113495bSYour Name *mbpsx10_rate = tbl[upper].rate;
266*5113495bSYour Name *ret_flag = tbl[upper].flag;
267*5113495bSYour Name return;
268*5113495bSYour Name } else if (*mbpsx10_rate <= tbl[lower].rate) {
269*5113495bSYour Name /* use the smallest rate */
270*5113495bSYour Name *mbpsx10_rate = tbl[lower].rate;
271*5113495bSYour Name *ret_flag = tbl[lower].flag;
272*5113495bSYour Name return;
273*5113495bSYour Name }
274*5113495bSYour Name /* now we do binery search to get the floor value */
275*5113495bSYour Name while (lower - upper > 1) {
276*5113495bSYour Name mid = (upper + lower) >> 1;
277*5113495bSYour Name if (*mbpsx10_rate == tbl[mid].rate) {
278*5113495bSYour Name /* found the exact match */
279*5113495bSYour Name *mbpsx10_rate = tbl[mid].rate;
280*5113495bSYour Name *ret_flag = tbl[mid].flag;
281*5113495bSYour Name return;
282*5113495bSYour Name }
283*5113495bSYour Name /* not found. if mid's rate is larger than input move
284*5113495bSYour Name * upper to mid. If mid's rate is larger than input
285*5113495bSYour Name * move lower to mid.
286*5113495bSYour Name */
287*5113495bSYour Name if (*mbpsx10_rate > tbl[mid].rate)
288*5113495bSYour Name lower = mid;
289*5113495bSYour Name else
290*5113495bSYour Name upper = mid;
291*5113495bSYour Name }
292*5113495bSYour Name /* after the bin search the index is the ceiling of rate */
293*5113495bSYour Name *mbpsx10_rate = tbl[upper].rate;
294*5113495bSYour Name *ret_flag = tbl[upper].flag;
295*5113495bSYour Name return;
296*5113495bSYour Name }
297*5113495bSYour Name
298*5113495bSYour Name /**
299*5113495bSYour Name * wma_fill_ofdm_cck_mcast_rate() - fill ofdm cck mcast rate
300*5113495bSYour Name * @mbpsx10_rate: mbps rates
301*5113495bSYour Name * @nss: nss
302*5113495bSYour Name * @rate: rate
303*5113495bSYour Name *
304*5113495bSYour Name * Return: QDF status
305*5113495bSYour Name */
wma_fill_ofdm_cck_mcast_rate(int32_t mbpsx10_rate,uint8_t nss,uint8_t * rate)306*5113495bSYour Name static QDF_STATUS wma_fill_ofdm_cck_mcast_rate(int32_t mbpsx10_rate,
307*5113495bSYour Name uint8_t nss, uint8_t *rate)
308*5113495bSYour Name {
309*5113495bSYour Name uint8_t idx = 0;
310*5113495bSYour Name
311*5113495bSYour Name wma_bin_search_rate(ofdm_cck_rate_tbl, WMA_MAX_OFDM_CCK_RATE_TBL_SIZE,
312*5113495bSYour Name &mbpsx10_rate, &idx);
313*5113495bSYour Name
314*5113495bSYour Name /* if bit 7 is set it uses CCK */
315*5113495bSYour Name if (idx & 0x80)
316*5113495bSYour Name *rate |= (1 << 6) | (idx & 0xF); /* set bit 6 to 1 for CCK */
317*5113495bSYour Name else
318*5113495bSYour Name *rate |= (idx & 0xF);
319*5113495bSYour Name return QDF_STATUS_SUCCESS;
320*5113495bSYour Name }
321*5113495bSYour Name
322*5113495bSYour Name /**
323*5113495bSYour Name * wma_set_ht_vht_mcast_rate() - set ht/vht mcast rate
324*5113495bSYour Name * @shortgi: short guard interval
325*5113495bSYour Name * @mbpsx10_rate: mbps rates
326*5113495bSYour Name * @sgi_idx: shortgi index
327*5113495bSYour Name * @sgi_rate: shortgi rate
328*5113495bSYour Name * @lgi_idx: longgi index
329*5113495bSYour Name * @lgi_rate: longgi rate
330*5113495bSYour Name * @premable: preamble
331*5113495bSYour Name * @rate: rate
332*5113495bSYour Name * @streaming_rate: streaming rate
333*5113495bSYour Name *
334*5113495bSYour Name * Return: none
335*5113495bSYour Name */
wma_set_ht_vht_mcast_rate(uint32_t shortgi,int32_t mbpsx10_rate,uint8_t sgi_idx,int32_t sgi_rate,uint8_t lgi_idx,int32_t lgi_rate,uint8_t premable,uint8_t * rate,int32_t * streaming_rate)336*5113495bSYour Name static void wma_set_ht_vht_mcast_rate(uint32_t shortgi, int32_t mbpsx10_rate,
337*5113495bSYour Name uint8_t sgi_idx, int32_t sgi_rate,
338*5113495bSYour Name uint8_t lgi_idx, int32_t lgi_rate,
339*5113495bSYour Name uint8_t premable, uint8_t *rate,
340*5113495bSYour Name int32_t *streaming_rate)
341*5113495bSYour Name {
342*5113495bSYour Name if (shortgi == 0) {
343*5113495bSYour Name *rate |= (premable << 6) | (lgi_idx & 0xF);
344*5113495bSYour Name *streaming_rate = lgi_rate;
345*5113495bSYour Name } else {
346*5113495bSYour Name *rate |= (premable << 6) | (sgi_idx & 0xF);
347*5113495bSYour Name *streaming_rate = sgi_rate;
348*5113495bSYour Name }
349*5113495bSYour Name }
350*5113495bSYour Name
351*5113495bSYour Name /**
352*5113495bSYour Name * wma_fill_ht20_mcast_rate() - fill ht20 mcast rate
353*5113495bSYour Name * @shortgi: short guard interval
354*5113495bSYour Name * @mbpsx10_rate: mbps rates
355*5113495bSYour Name * @nss: nss
356*5113495bSYour Name * @rate: rate
357*5113495bSYour Name * @streaming_rate: streaming rate
358*5113495bSYour Name *
359*5113495bSYour Name * Return: QDF status
360*5113495bSYour Name */
wma_fill_ht20_mcast_rate(uint32_t shortgi,int32_t mbpsx10_rate,uint8_t nss,uint8_t * rate,int32_t * streaming_rate)361*5113495bSYour Name static QDF_STATUS wma_fill_ht20_mcast_rate(uint32_t shortgi,
362*5113495bSYour Name int32_t mbpsx10_rate, uint8_t nss,
363*5113495bSYour Name uint8_t *rate,
364*5113495bSYour Name int32_t *streaming_rate)
365*5113495bSYour Name {
366*5113495bSYour Name uint8_t sgi_idx = 0, lgi_idx = 0;
367*5113495bSYour Name int32_t sgi_rate, lgi_rate;
368*5113495bSYour Name
369*5113495bSYour Name if (nss == 1)
370*5113495bSYour Name mbpsx10_rate = mbpsx10_rate >> 1;
371*5113495bSYour Name
372*5113495bSYour Name sgi_rate = mbpsx10_rate;
373*5113495bSYour Name lgi_rate = mbpsx10_rate;
374*5113495bSYour Name if (shortgi)
375*5113495bSYour Name wma_bin_search_rate(ht20_400ns_rate_tbl,
376*5113495bSYour Name WMA_MAX_HT20_RATE_TBL_SIZE, &sgi_rate,
377*5113495bSYour Name &sgi_idx);
378*5113495bSYour Name else
379*5113495bSYour Name wma_bin_search_rate(ht20_800ns_rate_tbl,
380*5113495bSYour Name WMA_MAX_HT20_RATE_TBL_SIZE, &lgi_rate,
381*5113495bSYour Name &lgi_idx);
382*5113495bSYour Name
383*5113495bSYour Name wma_set_ht_vht_mcast_rate(shortgi, mbpsx10_rate, sgi_idx, sgi_rate,
384*5113495bSYour Name lgi_idx, lgi_rate, 2, rate, streaming_rate);
385*5113495bSYour Name if (nss == 1)
386*5113495bSYour Name *streaming_rate = *streaming_rate << 1;
387*5113495bSYour Name return QDF_STATUS_SUCCESS;
388*5113495bSYour Name }
389*5113495bSYour Name
390*5113495bSYour Name /**
391*5113495bSYour Name * wma_fill_ht40_mcast_rate() - fill ht40 mcast rate
392*5113495bSYour Name * @shortgi: short guard interval
393*5113495bSYour Name * @mbpsx10_rate: mbps rates
394*5113495bSYour Name * @nss: nss
395*5113495bSYour Name * @rate: rate
396*5113495bSYour Name * @streaming_rate: streaming rate
397*5113495bSYour Name *
398*5113495bSYour Name * Return: QDF status
399*5113495bSYour Name */
wma_fill_ht40_mcast_rate(uint32_t shortgi,int32_t mbpsx10_rate,uint8_t nss,uint8_t * rate,int32_t * streaming_rate)400*5113495bSYour Name static QDF_STATUS wma_fill_ht40_mcast_rate(uint32_t shortgi,
401*5113495bSYour Name int32_t mbpsx10_rate, uint8_t nss,
402*5113495bSYour Name uint8_t *rate,
403*5113495bSYour Name int32_t *streaming_rate)
404*5113495bSYour Name {
405*5113495bSYour Name uint8_t sgi_idx = 0, lgi_idx = 0;
406*5113495bSYour Name int32_t sgi_rate, lgi_rate;
407*5113495bSYour Name
408*5113495bSYour Name /* for 2x2 divide the rate by 2 */
409*5113495bSYour Name if (nss == 1)
410*5113495bSYour Name mbpsx10_rate = mbpsx10_rate >> 1;
411*5113495bSYour Name
412*5113495bSYour Name sgi_rate = mbpsx10_rate;
413*5113495bSYour Name lgi_rate = mbpsx10_rate;
414*5113495bSYour Name if (shortgi)
415*5113495bSYour Name wma_bin_search_rate(ht40_400ns_rate_tbl,
416*5113495bSYour Name WMA_MAX_HT40_RATE_TBL_SIZE, &sgi_rate,
417*5113495bSYour Name &sgi_idx);
418*5113495bSYour Name else
419*5113495bSYour Name wma_bin_search_rate(ht40_800ns_rate_tbl,
420*5113495bSYour Name WMA_MAX_HT40_RATE_TBL_SIZE, &lgi_rate,
421*5113495bSYour Name &lgi_idx);
422*5113495bSYour Name
423*5113495bSYour Name wma_set_ht_vht_mcast_rate(shortgi, mbpsx10_rate, sgi_idx, sgi_rate,
424*5113495bSYour Name lgi_idx, lgi_rate, 2, rate, streaming_rate);
425*5113495bSYour Name
426*5113495bSYour Name return QDF_STATUS_SUCCESS;
427*5113495bSYour Name }
428*5113495bSYour Name
429*5113495bSYour Name /**
430*5113495bSYour Name * wma_fill_vht20_mcast_rate() - fill vht20 mcast rate
431*5113495bSYour Name * @shortgi: short guard interval
432*5113495bSYour Name * @mbpsx10_rate: mbps rates
433*5113495bSYour Name * @nss: nss
434*5113495bSYour Name * @rate: rate
435*5113495bSYour Name * @streaming_rate: streaming rate
436*5113495bSYour Name *
437*5113495bSYour Name * Return: QDF status
438*5113495bSYour Name */
wma_fill_vht20_mcast_rate(uint32_t shortgi,int32_t mbpsx10_rate,uint8_t nss,uint8_t * rate,int32_t * streaming_rate)439*5113495bSYour Name static QDF_STATUS wma_fill_vht20_mcast_rate(uint32_t shortgi,
440*5113495bSYour Name int32_t mbpsx10_rate, uint8_t nss,
441*5113495bSYour Name uint8_t *rate,
442*5113495bSYour Name int32_t *streaming_rate)
443*5113495bSYour Name {
444*5113495bSYour Name uint8_t sgi_idx = 0, lgi_idx = 0;
445*5113495bSYour Name int32_t sgi_rate, lgi_rate;
446*5113495bSYour Name
447*5113495bSYour Name /* for 2x2 divide the rate by 2 */
448*5113495bSYour Name if (nss == 1)
449*5113495bSYour Name mbpsx10_rate = mbpsx10_rate >> 1;
450*5113495bSYour Name
451*5113495bSYour Name sgi_rate = mbpsx10_rate;
452*5113495bSYour Name lgi_rate = mbpsx10_rate;
453*5113495bSYour Name if (shortgi)
454*5113495bSYour Name wma_bin_search_rate(vht20_400ns_rate_tbl,
455*5113495bSYour Name WMA_MAX_VHT20_RATE_TBL_SIZE, &sgi_rate,
456*5113495bSYour Name &sgi_idx);
457*5113495bSYour Name else
458*5113495bSYour Name wma_bin_search_rate(vht20_800ns_rate_tbl,
459*5113495bSYour Name WMA_MAX_VHT20_RATE_TBL_SIZE, &lgi_rate,
460*5113495bSYour Name &lgi_idx);
461*5113495bSYour Name
462*5113495bSYour Name wma_set_ht_vht_mcast_rate(shortgi, mbpsx10_rate, sgi_idx, sgi_rate,
463*5113495bSYour Name lgi_idx, lgi_rate, 3, rate, streaming_rate);
464*5113495bSYour Name if (nss == 1)
465*5113495bSYour Name *streaming_rate = *streaming_rate << 1;
466*5113495bSYour Name return QDF_STATUS_SUCCESS;
467*5113495bSYour Name }
468*5113495bSYour Name
469*5113495bSYour Name /**
470*5113495bSYour Name * wma_fill_vht40_mcast_rate() - fill vht40 mcast rate
471*5113495bSYour Name * @shortgi: short guard interval
472*5113495bSYour Name * @mbpsx10_rate: mbps rates
473*5113495bSYour Name * @nss: nss
474*5113495bSYour Name * @rate: rate
475*5113495bSYour Name * @streaming_rate: streaming rate
476*5113495bSYour Name *
477*5113495bSYour Name * Return: QDF status
478*5113495bSYour Name */
wma_fill_vht40_mcast_rate(uint32_t shortgi,int32_t mbpsx10_rate,uint8_t nss,uint8_t * rate,int32_t * streaming_rate)479*5113495bSYour Name static QDF_STATUS wma_fill_vht40_mcast_rate(uint32_t shortgi,
480*5113495bSYour Name int32_t mbpsx10_rate, uint8_t nss,
481*5113495bSYour Name uint8_t *rate,
482*5113495bSYour Name int32_t *streaming_rate)
483*5113495bSYour Name {
484*5113495bSYour Name uint8_t sgi_idx = 0, lgi_idx = 0;
485*5113495bSYour Name int32_t sgi_rate, lgi_rate;
486*5113495bSYour Name
487*5113495bSYour Name /* for 2x2 divide the rate by 2 */
488*5113495bSYour Name if (nss == 1)
489*5113495bSYour Name mbpsx10_rate = mbpsx10_rate >> 1;
490*5113495bSYour Name
491*5113495bSYour Name sgi_rate = mbpsx10_rate;
492*5113495bSYour Name lgi_rate = mbpsx10_rate;
493*5113495bSYour Name if (shortgi)
494*5113495bSYour Name wma_bin_search_rate(vht40_400ns_rate_tbl,
495*5113495bSYour Name WMA_MAX_VHT40_RATE_TBL_SIZE, &sgi_rate,
496*5113495bSYour Name &sgi_idx);
497*5113495bSYour Name else
498*5113495bSYour Name wma_bin_search_rate(vht40_800ns_rate_tbl,
499*5113495bSYour Name WMA_MAX_VHT40_RATE_TBL_SIZE, &lgi_rate,
500*5113495bSYour Name &lgi_idx);
501*5113495bSYour Name
502*5113495bSYour Name wma_set_ht_vht_mcast_rate(shortgi, mbpsx10_rate,
503*5113495bSYour Name sgi_idx, sgi_rate, lgi_idx, lgi_rate,
504*5113495bSYour Name 3, rate, streaming_rate);
505*5113495bSYour Name if (nss == 1)
506*5113495bSYour Name *streaming_rate = *streaming_rate << 1;
507*5113495bSYour Name return QDF_STATUS_SUCCESS;
508*5113495bSYour Name }
509*5113495bSYour Name
510*5113495bSYour Name /**
511*5113495bSYour Name * wma_fill_vht80_mcast_rate() - fill vht80 mcast rate
512*5113495bSYour Name * @shortgi: short guard interval
513*5113495bSYour Name * @mbpsx10_rate: mbps rates
514*5113495bSYour Name * @nss: nss
515*5113495bSYour Name * @rate: rate
516*5113495bSYour Name * @streaming_rate: streaming rate
517*5113495bSYour Name *
518*5113495bSYour Name * Return: QDF status
519*5113495bSYour Name */
wma_fill_vht80_mcast_rate(uint32_t shortgi,int32_t mbpsx10_rate,uint8_t nss,uint8_t * rate,int32_t * streaming_rate)520*5113495bSYour Name static QDF_STATUS wma_fill_vht80_mcast_rate(uint32_t shortgi,
521*5113495bSYour Name int32_t mbpsx10_rate, uint8_t nss,
522*5113495bSYour Name uint8_t *rate,
523*5113495bSYour Name int32_t *streaming_rate)
524*5113495bSYour Name {
525*5113495bSYour Name uint8_t sgi_idx = 0, lgi_idx = 0;
526*5113495bSYour Name int32_t sgi_rate, lgi_rate;
527*5113495bSYour Name
528*5113495bSYour Name /* for 2x2 divide the rate by 2 */
529*5113495bSYour Name if (nss == 1)
530*5113495bSYour Name mbpsx10_rate = mbpsx10_rate >> 1;
531*5113495bSYour Name
532*5113495bSYour Name sgi_rate = mbpsx10_rate;
533*5113495bSYour Name lgi_rate = mbpsx10_rate;
534*5113495bSYour Name if (shortgi)
535*5113495bSYour Name wma_bin_search_rate(vht80_400ns_rate_tbl,
536*5113495bSYour Name WMA_MAX_VHT80_RATE_TBL_SIZE, &sgi_rate,
537*5113495bSYour Name &sgi_idx);
538*5113495bSYour Name else
539*5113495bSYour Name wma_bin_search_rate(vht80_800ns_rate_tbl,
540*5113495bSYour Name WMA_MAX_VHT80_RATE_TBL_SIZE, &lgi_rate,
541*5113495bSYour Name &lgi_idx);
542*5113495bSYour Name
543*5113495bSYour Name wma_set_ht_vht_mcast_rate(shortgi, mbpsx10_rate, sgi_idx, sgi_rate,
544*5113495bSYour Name lgi_idx, lgi_rate, 3, rate, streaming_rate);
545*5113495bSYour Name if (nss == 1)
546*5113495bSYour Name *streaming_rate = *streaming_rate << 1;
547*5113495bSYour Name return QDF_STATUS_SUCCESS;
548*5113495bSYour Name }
549*5113495bSYour Name
550*5113495bSYour Name /**
551*5113495bSYour Name * wma_fill_ht_mcast_rate() - fill ht mcast rate
552*5113495bSYour Name * @shortgi: short guard interval
553*5113495bSYour Name * @chwidth: channel width
554*5113495bSYour Name * @chanmode: channel mode
555*5113495bSYour Name * @mhz: frequency
556*5113495bSYour Name * @mbpsx10_rate: mbps rates
557*5113495bSYour Name * @nss: nss
558*5113495bSYour Name * @rate: rate
559*5113495bSYour Name * @streaming_rate: streaming rate
560*5113495bSYour Name *
561*5113495bSYour Name * Return: QDF status
562*5113495bSYour Name */
wma_fill_ht_mcast_rate(uint32_t shortgi,uint32_t chwidth,int32_t mbpsx10_rate,uint8_t nss,uint8_t * rate,int32_t * streaming_rate)563*5113495bSYour Name static QDF_STATUS wma_fill_ht_mcast_rate(uint32_t shortgi,
564*5113495bSYour Name uint32_t chwidth, int32_t mbpsx10_rate,
565*5113495bSYour Name uint8_t nss, uint8_t *rate,
566*5113495bSYour Name int32_t *streaming_rate)
567*5113495bSYour Name {
568*5113495bSYour Name int32_t ret = 0;
569*5113495bSYour Name
570*5113495bSYour Name *streaming_rate = 0;
571*5113495bSYour Name if (chwidth == 0)
572*5113495bSYour Name ret = wma_fill_ht20_mcast_rate(shortgi, mbpsx10_rate,
573*5113495bSYour Name nss, rate, streaming_rate);
574*5113495bSYour Name else if (chwidth == 1)
575*5113495bSYour Name ret = wma_fill_ht40_mcast_rate(shortgi, mbpsx10_rate,
576*5113495bSYour Name nss, rate, streaming_rate);
577*5113495bSYour Name else
578*5113495bSYour Name wma_err("Error, Invalid chwidth enum %d", chwidth);
579*5113495bSYour Name return (*streaming_rate != 0) ? QDF_STATUS_SUCCESS : QDF_STATUS_E_INVAL;
580*5113495bSYour Name }
581*5113495bSYour Name
582*5113495bSYour Name /**
583*5113495bSYour Name * wma_fill_vht_mcast_rate() - fill vht mcast rate
584*5113495bSYour Name * @shortgi: short guard interval
585*5113495bSYour Name * @chwidth: channel width
586*5113495bSYour Name * @chanmode: channel mode
587*5113495bSYour Name * @mhz: frequency
588*5113495bSYour Name * @mbpsx10_rate: mbps rates
589*5113495bSYour Name * @nss: nss
590*5113495bSYour Name * @rate: rate
591*5113495bSYour Name * @streaming_rate: streaming rate
592*5113495bSYour Name *
593*5113495bSYour Name * Return: QDF status
594*5113495bSYour Name */
wma_fill_vht_mcast_rate(uint32_t shortgi,uint32_t chwidth,int32_t mbpsx10_rate,uint8_t nss,uint8_t * rate,int32_t * streaming_rate)595*5113495bSYour Name static QDF_STATUS wma_fill_vht_mcast_rate(uint32_t shortgi,
596*5113495bSYour Name uint32_t chwidth,
597*5113495bSYour Name int32_t mbpsx10_rate, uint8_t nss,
598*5113495bSYour Name uint8_t *rate,
599*5113495bSYour Name int32_t *streaming_rate)
600*5113495bSYour Name {
601*5113495bSYour Name int32_t ret = 0;
602*5113495bSYour Name
603*5113495bSYour Name *streaming_rate = 0;
604*5113495bSYour Name if (chwidth == 0)
605*5113495bSYour Name ret = wma_fill_vht20_mcast_rate(shortgi, mbpsx10_rate, nss,
606*5113495bSYour Name rate, streaming_rate);
607*5113495bSYour Name else if (chwidth == 1)
608*5113495bSYour Name ret = wma_fill_vht40_mcast_rate(shortgi, mbpsx10_rate, nss,
609*5113495bSYour Name rate, streaming_rate);
610*5113495bSYour Name else if (chwidth == 2)
611*5113495bSYour Name ret = wma_fill_vht80_mcast_rate(shortgi, mbpsx10_rate, nss,
612*5113495bSYour Name rate, streaming_rate);
613*5113495bSYour Name else
614*5113495bSYour Name wma_err("chwidth enum %d not supported", chwidth);
615*5113495bSYour Name return (*streaming_rate != 0) ? QDF_STATUS_SUCCESS : QDF_STATUS_E_INVAL;
616*5113495bSYour Name }
617*5113495bSYour Name
618*5113495bSYour Name #define WMA_MCAST_1X1_CUT_OFF_RATE 2000
619*5113495bSYour Name /**
620*5113495bSYour Name * wma_encode_mc_rate() - fill mc rates
621*5113495bSYour Name * @shortgi: short guard interval
622*5113495bSYour Name * @chwidth: channel width
623*5113495bSYour Name * @chanmode: channel mode
624*5113495bSYour Name * @mhz: frequency
625*5113495bSYour Name * @mbpsx10_rate: mbps rates
626*5113495bSYour Name * @nss: nss
627*5113495bSYour Name * @rate: rate
628*5113495bSYour Name *
629*5113495bSYour Name * Return: QDF status
630*5113495bSYour Name */
wma_encode_mc_rate(uint32_t shortgi,uint32_t chwidth,A_UINT32 mhz,int32_t mbpsx10_rate,uint8_t nss,uint8_t * rate)631*5113495bSYour Name static QDF_STATUS wma_encode_mc_rate(uint32_t shortgi, uint32_t chwidth,
632*5113495bSYour Name A_UINT32 mhz, int32_t mbpsx10_rate, uint8_t nss,
633*5113495bSYour Name uint8_t *rate)
634*5113495bSYour Name {
635*5113495bSYour Name int32_t ret = 0;
636*5113495bSYour Name
637*5113495bSYour Name /* nss input value: 0 - 1x1; 1 - 2x2; 2 - 3x3
638*5113495bSYour Name * the phymode selection is based on following assumption:
639*5113495bSYour Name * (1) if the app specifically requested 1x1 or 2x2 we hornor it
640*5113495bSYour Name * (2) if mbpsx10_rate <= 540: always use BG
641*5113495bSYour Name * (3) 540 < mbpsx10_rate <= 2000: use 1x1 HT/VHT
642*5113495bSYour Name * (4) 2000 < mbpsx10_rate: use 2x2 HT/VHT
643*5113495bSYour Name */
644*5113495bSYour Name wma_debug("Input: nss = %d, mbpsx10 = 0x%x, chwidth = %d, shortgi = %d",
645*5113495bSYour Name nss, mbpsx10_rate, chwidth, shortgi);
646*5113495bSYour Name if ((mbpsx10_rate & 0x40000000) && nss > 0) {
647*5113495bSYour Name /* bit 30 indicates user inputted nss,
648*5113495bSYour Name * bit 28 and 29 used to encode nss
649*5113495bSYour Name */
650*5113495bSYour Name uint8_t user_nss = (mbpsx10_rate & 0x30000000) >> 28;
651*5113495bSYour Name
652*5113495bSYour Name nss = (user_nss < nss) ? user_nss : nss;
653*5113495bSYour Name /* zero out bits 19 - 21 to recover the actual rate */
654*5113495bSYour Name mbpsx10_rate &= ~0x70000000;
655*5113495bSYour Name } else if (mbpsx10_rate <= WMA_MCAST_1X1_CUT_OFF_RATE) {
656*5113495bSYour Name /* if the input rate is less or equal to the
657*5113495bSYour Name * 1x1 cutoff rate we use 1x1 only
658*5113495bSYour Name */
659*5113495bSYour Name nss = 0;
660*5113495bSYour Name }
661*5113495bSYour Name /* encode NSS bits (bit 4, bit 5) */
662*5113495bSYour Name *rate = (nss & 0x3) << 4;
663*5113495bSYour Name /* if mcast input rate exceeds the ofdm/cck max rate 54mpbs
664*5113495bSYour Name * we try to choose best ht/vht mcs rate
665*5113495bSYour Name */
666*5113495bSYour Name if (540 < mbpsx10_rate) {
667*5113495bSYour Name /* cannot use ofdm/cck, choose closest ht/vht mcs rate */
668*5113495bSYour Name uint8_t rate_ht = *rate;
669*5113495bSYour Name uint8_t rate_vht = *rate;
670*5113495bSYour Name int32_t stream_rate_ht = 0;
671*5113495bSYour Name int32_t stream_rate_vht = 0;
672*5113495bSYour Name int32_t stream_rate = 0;
673*5113495bSYour Name
674*5113495bSYour Name ret = wma_fill_ht_mcast_rate(shortgi, chwidth, mbpsx10_rate,
675*5113495bSYour Name nss, &rate_ht,
676*5113495bSYour Name &stream_rate_ht);
677*5113495bSYour Name if (ret != QDF_STATUS_SUCCESS)
678*5113495bSYour Name stream_rate_ht = 0;
679*5113495bSYour Name if (mhz < WMA_2_4_GHZ_MAX_FREQ) {
680*5113495bSYour Name /* not in 5 GHZ frequency */
681*5113495bSYour Name *rate = rate_ht;
682*5113495bSYour Name stream_rate = stream_rate_ht;
683*5113495bSYour Name goto ht_vht_done;
684*5113495bSYour Name }
685*5113495bSYour Name /* capable doing 11AC mcast so that search vht tables */
686*5113495bSYour Name ret = wma_fill_vht_mcast_rate(shortgi, chwidth, mbpsx10_rate,
687*5113495bSYour Name nss, &rate_vht,
688*5113495bSYour Name &stream_rate_vht);
689*5113495bSYour Name if (ret != QDF_STATUS_SUCCESS) {
690*5113495bSYour Name if (stream_rate_ht != 0)
691*5113495bSYour Name ret = QDF_STATUS_SUCCESS;
692*5113495bSYour Name *rate = rate_ht;
693*5113495bSYour Name stream_rate = stream_rate_ht;
694*5113495bSYour Name goto ht_vht_done;
695*5113495bSYour Name }
696*5113495bSYour Name if (stream_rate_ht == 0) {
697*5113495bSYour Name /* only vht rate available */
698*5113495bSYour Name *rate = rate_vht;
699*5113495bSYour Name stream_rate = stream_rate_vht;
700*5113495bSYour Name } else {
701*5113495bSYour Name /* set ht as default first */
702*5113495bSYour Name *rate = rate_ht;
703*5113495bSYour Name stream_rate = stream_rate_ht;
704*5113495bSYour Name if (stream_rate < mbpsx10_rate) {
705*5113495bSYour Name if (mbpsx10_rate <= stream_rate_vht ||
706*5113495bSYour Name stream_rate < stream_rate_vht) {
707*5113495bSYour Name *rate = rate_vht;
708*5113495bSYour Name stream_rate = stream_rate_vht;
709*5113495bSYour Name }
710*5113495bSYour Name } else {
711*5113495bSYour Name if (stream_rate_vht >= mbpsx10_rate &&
712*5113495bSYour Name stream_rate_vht < stream_rate) {
713*5113495bSYour Name *rate = rate_vht;
714*5113495bSYour Name stream_rate = stream_rate_vht;
715*5113495bSYour Name }
716*5113495bSYour Name }
717*5113495bSYour Name }
718*5113495bSYour Name ht_vht_done:
719*5113495bSYour Name wma_debug("NSS = %d, freq = %d", nss, mhz);
720*5113495bSYour Name wma_debug("input_rate = %d, chwidth = %d rate = 0x%x, streaming_rate = %d",
721*5113495bSYour Name mbpsx10_rate, chwidth, *rate, stream_rate);
722*5113495bSYour Name } else {
723*5113495bSYour Name if (mbpsx10_rate > 0)
724*5113495bSYour Name ret = wma_fill_ofdm_cck_mcast_rate(mbpsx10_rate,
725*5113495bSYour Name nss, rate);
726*5113495bSYour Name else
727*5113495bSYour Name *rate = 0xFF;
728*5113495bSYour Name
729*5113495bSYour Name wma_debug("NSS = %d, input_rate = %d, rate = 0x%x",
730*5113495bSYour Name nss, mbpsx10_rate, *rate);
731*5113495bSYour Name }
732*5113495bSYour Name return ret;
733*5113495bSYour Name }
734*5113495bSYour Name
735*5113495bSYour Name /**
736*5113495bSYour Name * wma_cp_stats_set_rate_flag() - set rate flags within cp_stats priv object
737*5113495bSYour Name * @wma: wma handle
738*5113495bSYour Name * @vdev_id: vdev id
739*5113495bSYour Name *
740*5113495bSYour Name * Return: none
741*5113495bSYour Name */
wma_cp_stats_set_rate_flag(tp_wma_handle wma,uint8_t vdev_id)742*5113495bSYour Name static void wma_cp_stats_set_rate_flag(tp_wma_handle wma, uint8_t vdev_id)
743*5113495bSYour Name {
744*5113495bSYour Name struct wlan_objmgr_vdev *vdev;
745*5113495bSYour Name struct wlan_objmgr_psoc *psoc = wma->psoc;
746*5113495bSYour Name struct wma_txrx_node *iface = &wma->interfaces[vdev_id];
747*5113495bSYour Name uint32_t rate_flag;
748*5113495bSYour Name QDF_STATUS status;
749*5113495bSYour Name
750*5113495bSYour Name vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
751*5113495bSYour Name WLAN_LEGACY_WMA_ID);
752*5113495bSYour Name if (!vdev) {
753*5113495bSYour Name wma_err("vdev not found for id: %d", vdev_id);
754*5113495bSYour Name return;
755*5113495bSYour Name }
756*5113495bSYour Name
757*5113495bSYour Name status = wma_get_vdev_rate_flag(iface->vdev, &rate_flag);
758*5113495bSYour Name if (QDF_IS_STATUS_ERROR(status)) {
759*5113495bSYour Name wma_err("vdev not found for id: %d", vdev_id);
760*5113495bSYour Name return;
761*5113495bSYour Name }
762*5113495bSYour Name ucfg_mc_cp_stats_set_rate_flags(vdev, rate_flag);
763*5113495bSYour Name wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_WMA_ID);
764*5113495bSYour Name }
765*5113495bSYour Name
766*5113495bSYour Name #ifdef WLAN_FEATURE_11AX
767*5113495bSYour Name /**
768*5113495bSYour Name * wma_set_bss_rate_flags_he() - set rate flags based on BSS capability
769*5113495bSYour Name * @rate_flags: rate_flags pointer
770*5113495bSYour Name * @add_bss: add_bss params
771*5113495bSYour Name *
772*5113495bSYour Name * Return: QDF_STATUS
773*5113495bSYour Name */
wma_set_bss_rate_flags_he(enum tx_rate_info * rate_flags,struct bss_params * add_bss)774*5113495bSYour Name static QDF_STATUS wma_set_bss_rate_flags_he(enum tx_rate_info *rate_flags,
775*5113495bSYour Name struct bss_params *add_bss)
776*5113495bSYour Name {
777*5113495bSYour Name if (!add_bss->he_capable)
778*5113495bSYour Name return QDF_STATUS_E_NOSUPPORT;
779*5113495bSYour Name
780*5113495bSYour Name *rate_flags |= wma_get_he_rate_flags(add_bss->ch_width);
781*5113495bSYour Name
782*5113495bSYour Name wma_debug("he_capable %d rate_flags 0x%x", add_bss->he_capable,
783*5113495bSYour Name *rate_flags);
784*5113495bSYour Name return QDF_STATUS_SUCCESS;
785*5113495bSYour Name }
786*5113495bSYour Name
wma_get_bss_he_capable(struct bss_params * add_bss)787*5113495bSYour Name static bool wma_get_bss_he_capable(struct bss_params *add_bss)
788*5113495bSYour Name {
789*5113495bSYour Name return add_bss->he_capable;
790*5113495bSYour Name }
791*5113495bSYour Name #else
wma_set_bss_rate_flags_he(enum tx_rate_info * rate_flags,struct bss_params * add_bss)792*5113495bSYour Name static QDF_STATUS wma_set_bss_rate_flags_he(enum tx_rate_info *rate_flags,
793*5113495bSYour Name struct bss_params *add_bss)
794*5113495bSYour Name {
795*5113495bSYour Name return QDF_STATUS_E_NOSUPPORT;
796*5113495bSYour Name }
797*5113495bSYour Name
wma_get_bss_he_capable(struct bss_params * add_bss)798*5113495bSYour Name static bool wma_get_bss_he_capable(struct bss_params *add_bss)
799*5113495bSYour Name {
800*5113495bSYour Name return false;
801*5113495bSYour Name }
802*5113495bSYour Name #endif
803*5113495bSYour Name
wma_get_vht_rate_flags(enum phy_ch_width ch_width)804*5113495bSYour Name enum tx_rate_info wma_get_vht_rate_flags(enum phy_ch_width ch_width)
805*5113495bSYour Name {
806*5113495bSYour Name enum tx_rate_info rate_flags = 0;
807*5113495bSYour Name
808*5113495bSYour Name if (ch_width == CH_WIDTH_80P80MHZ)
809*5113495bSYour Name rate_flags |= TX_RATE_VHT160 | TX_RATE_VHT80 | TX_RATE_VHT40 |
810*5113495bSYour Name TX_RATE_VHT20;
811*5113495bSYour Name if (ch_width == CH_WIDTH_160MHZ)
812*5113495bSYour Name rate_flags |= TX_RATE_VHT160 | TX_RATE_VHT80 | TX_RATE_VHT40 |
813*5113495bSYour Name TX_RATE_VHT20;
814*5113495bSYour Name if (ch_width == CH_WIDTH_80MHZ)
815*5113495bSYour Name rate_flags |= TX_RATE_VHT80 | TX_RATE_VHT40 | TX_RATE_VHT20;
816*5113495bSYour Name else if (ch_width)
817*5113495bSYour Name rate_flags |= TX_RATE_VHT40 | TX_RATE_VHT20;
818*5113495bSYour Name else
819*5113495bSYour Name rate_flags |= TX_RATE_VHT20;
820*5113495bSYour Name return rate_flags;
821*5113495bSYour Name }
822*5113495bSYour Name
wma_get_ht_rate_flags(enum phy_ch_width ch_width)823*5113495bSYour Name enum tx_rate_info wma_get_ht_rate_flags(enum phy_ch_width ch_width)
824*5113495bSYour Name {
825*5113495bSYour Name enum tx_rate_info rate_flags = 0;
826*5113495bSYour Name
827*5113495bSYour Name if (ch_width)
828*5113495bSYour Name rate_flags |= TX_RATE_HT40 | TX_RATE_HT20;
829*5113495bSYour Name else
830*5113495bSYour Name rate_flags |= TX_RATE_HT20;
831*5113495bSYour Name
832*5113495bSYour Name return rate_flags;
833*5113495bSYour Name }
834*5113495bSYour Name
wma_get_he_rate_flags(enum phy_ch_width ch_width)835*5113495bSYour Name enum tx_rate_info wma_get_he_rate_flags(enum phy_ch_width ch_width)
836*5113495bSYour Name {
837*5113495bSYour Name enum tx_rate_info rate_flags = 0;
838*5113495bSYour Name
839*5113495bSYour Name if (ch_width == CH_WIDTH_160MHZ ||
840*5113495bSYour Name ch_width == CH_WIDTH_80P80MHZ)
841*5113495bSYour Name rate_flags |= TX_RATE_HE160 | TX_RATE_HE80 | TX_RATE_HE40 |
842*5113495bSYour Name TX_RATE_HE20;
843*5113495bSYour Name else if (ch_width == CH_WIDTH_80MHZ)
844*5113495bSYour Name rate_flags |= TX_RATE_HE80 | TX_RATE_HE40 | TX_RATE_HE20;
845*5113495bSYour Name else if (ch_width)
846*5113495bSYour Name rate_flags |= TX_RATE_HE40 | TX_RATE_HE20;
847*5113495bSYour Name else
848*5113495bSYour Name rate_flags |= TX_RATE_HE20;
849*5113495bSYour Name
850*5113495bSYour Name return rate_flags;
851*5113495bSYour Name }
852*5113495bSYour Name
wma_set_bss_rate_flags(tp_wma_handle wma,uint8_t vdev_id,struct bss_params * add_bss)853*5113495bSYour Name void wma_set_bss_rate_flags(tp_wma_handle wma, uint8_t vdev_id,
854*5113495bSYour Name struct bss_params *add_bss)
855*5113495bSYour Name {
856*5113495bSYour Name struct wma_txrx_node *iface = &wma->interfaces[vdev_id];
857*5113495bSYour Name struct vdev_mlme_obj *vdev_mlme;
858*5113495bSYour Name enum tx_rate_info *rate_flags;
859*5113495bSYour Name QDF_STATUS qdf_status;
860*5113495bSYour Name
861*5113495bSYour Name vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(iface->vdev);
862*5113495bSYour Name if (!vdev_mlme) {
863*5113495bSYour Name wma_err("Failed to get mlme obj for vdev_%d", vdev_id);
864*5113495bSYour Name return;
865*5113495bSYour Name }
866*5113495bSYour Name rate_flags = &vdev_mlme->mgmt.rate_info.rate_flags;
867*5113495bSYour Name *rate_flags = 0;
868*5113495bSYour Name
869*5113495bSYour Name qdf_status = wma_set_bss_rate_flags_eht(rate_flags, add_bss);
870*5113495bSYour Name if (QDF_IS_STATUS_ERROR(qdf_status)) {
871*5113495bSYour Name if (QDF_STATUS_SUCCESS !=
872*5113495bSYour Name wma_set_bss_rate_flags_he(rate_flags, add_bss)) {
873*5113495bSYour Name if (add_bss->vhtCapable)
874*5113495bSYour Name *rate_flags = wma_get_vht_rate_flags(add_bss->ch_width);
875*5113495bSYour Name /* avoid to conflict with htCapable flag */
876*5113495bSYour Name else if (add_bss->htCapable)
877*5113495bSYour Name *rate_flags |= wma_get_ht_rate_flags(add_bss->ch_width);
878*5113495bSYour Name }
879*5113495bSYour Name }
880*5113495bSYour Name
881*5113495bSYour Name if (add_bss->staContext.fShortGI20Mhz ||
882*5113495bSYour Name add_bss->staContext.fShortGI40Mhz)
883*5113495bSYour Name *rate_flags |= TX_RATE_SGI;
884*5113495bSYour Name
885*5113495bSYour Name if (!add_bss->htCapable && !add_bss->vhtCapable &&
886*5113495bSYour Name !wma_get_bss_he_capable(add_bss) &&
887*5113495bSYour Name !wma_get_bss_eht_capable(add_bss))
888*5113495bSYour Name *rate_flags = TX_RATE_LEGACY;
889*5113495bSYour Name
890*5113495bSYour Name wma_debug("capable: vht %u, ht %u, rate_flags %x, ch_width %d",
891*5113495bSYour Name add_bss->vhtCapable, add_bss->htCapable,
892*5113495bSYour Name *rate_flags, add_bss->ch_width);
893*5113495bSYour Name
894*5113495bSYour Name wma_cp_stats_set_rate_flag(wma, vdev_id);
895*5113495bSYour Name }
896*5113495bSYour Name
wma_set_vht_txbf_cfg(struct mac_context * mac,uint8_t vdev_id)897*5113495bSYour Name void wma_set_vht_txbf_cfg(struct mac_context *mac, uint8_t vdev_id)
898*5113495bSYour Name {
899*5113495bSYour Name wmi_vdev_txbf_en txbf_en = {0};
900*5113495bSYour Name QDF_STATUS status;
901*5113495bSYour Name tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
902*5113495bSYour Name
903*5113495bSYour Name if (!wma)
904*5113495bSYour Name return;
905*5113495bSYour Name
906*5113495bSYour Name txbf_en.sutxbfee = mac->mlme_cfg->vht_caps.vht_cap_info.su_bformee;
907*5113495bSYour Name txbf_en.mutxbfee =
908*5113495bSYour Name mac->mlme_cfg->vht_caps.vht_cap_info.enable_mu_bformee;
909*5113495bSYour Name txbf_en.sutxbfer = mac->mlme_cfg->vht_caps.vht_cap_info.su_bformer;
910*5113495bSYour Name
911*5113495bSYour Name status = wma_vdev_set_param(wma->wmi_handle, vdev_id,
912*5113495bSYour Name wmi_vdev_param_txbf,
913*5113495bSYour Name *((A_UINT8 *)&txbf_en));
914*5113495bSYour Name if (QDF_IS_STATUS_ERROR(status))
915*5113495bSYour Name wma_err("failed to set VHT TXBF(status = %d)", status);
916*5113495bSYour Name }
917*5113495bSYour Name
918*5113495bSYour Name /**
919*5113495bSYour Name * wmi_unified_send_txbf() - set txbf parameter to fw
920*5113495bSYour Name * @wma: wma handle
921*5113495bSYour Name * @params: txbf parameters
922*5113495bSYour Name *
923*5113495bSYour Name * Return: 0 for success or error code
924*5113495bSYour Name */
wmi_unified_send_txbf(tp_wma_handle wma,tpAddStaParams params)925*5113495bSYour Name int32_t wmi_unified_send_txbf(tp_wma_handle wma, tpAddStaParams params)
926*5113495bSYour Name {
927*5113495bSYour Name wmi_vdev_txbf_en txbf_en = {0};
928*5113495bSYour Name
929*5113495bSYour Name /* This is set when Other partner is Bformer
930*5113495bSYour Name * and we are capable bformee(enabled both in ini and fw)
931*5113495bSYour Name */
932*5113495bSYour Name txbf_en.sutxbfee = params->vhtTxBFCapable;
933*5113495bSYour Name txbf_en.mutxbfee = params->vhtTxMUBformeeCapable;
934*5113495bSYour Name txbf_en.sutxbfer = params->enable_su_tx_bformer;
935*5113495bSYour Name
936*5113495bSYour Name /* When MU TxBfee is set, SU TxBfee must be set by default */
937*5113495bSYour Name if (txbf_en.mutxbfee)
938*5113495bSYour Name txbf_en.sutxbfee = txbf_en.mutxbfee;
939*5113495bSYour Name
940*5113495bSYour Name wma_debug("txbf_en.sutxbfee %d txbf_en.mutxbfee %d, sutxbfer %d",
941*5113495bSYour Name txbf_en.sutxbfee, txbf_en.mutxbfee, txbf_en.sutxbfer);
942*5113495bSYour Name
943*5113495bSYour Name return wma_vdev_set_param(wma->wmi_handle,
944*5113495bSYour Name params->smesessionId,
945*5113495bSYour Name wmi_vdev_param_txbf,
946*5113495bSYour Name *((A_UINT8 *) &txbf_en));
947*5113495bSYour Name }
948*5113495bSYour Name
949*5113495bSYour Name /**
950*5113495bSYour Name * wma_data_tx_ack_work_handler() - process data tx ack
951*5113495bSYour Name * @ack_work: work structure
952*5113495bSYour Name *
953*5113495bSYour Name * Return: none
954*5113495bSYour Name */
wma_data_tx_ack_work_handler(void * ack_work)955*5113495bSYour Name static void wma_data_tx_ack_work_handler(void *ack_work)
956*5113495bSYour Name {
957*5113495bSYour Name struct wma_tx_ack_work_ctx *work;
958*5113495bSYour Name tp_wma_handle wma_handle;
959*5113495bSYour Name wma_tx_ota_comp_callback ack_cb;
960*5113495bSYour Name
961*5113495bSYour Name work = (struct wma_tx_ack_work_ctx *)ack_work;
962*5113495bSYour Name
963*5113495bSYour Name wma_handle = work->wma_handle;
964*5113495bSYour Name if (!wma_handle || cds_is_load_or_unload_in_progress()) {
965*5113495bSYour Name wma_err("Driver load/unload in progress");
966*5113495bSYour Name goto free_frame;
967*5113495bSYour Name }
968*5113495bSYour Name
969*5113495bSYour Name wma_debug("Data Tx Ack Cb Status %d", work->status);
970*5113495bSYour Name ack_cb = wma_handle->umac_data_ota_ack_cb;
971*5113495bSYour Name if (!ack_cb) {
972*5113495bSYour Name wma_err("Data Tx Ack Cb is NULL");
973*5113495bSYour Name goto free_frame;
974*5113495bSYour Name }
975*5113495bSYour Name
976*5113495bSYour Name ack_cb(wma_handle->mac_context, work->frame, work->status,
977*5113495bSYour Name NULL);
978*5113495bSYour Name goto end;
979*5113495bSYour Name
980*5113495bSYour Name free_frame:
981*5113495bSYour Name if (work->frame)
982*5113495bSYour Name qdf_nbuf_free(work->frame);
983*5113495bSYour Name
984*5113495bSYour Name end:
985*5113495bSYour Name qdf_mem_free(work);
986*5113495bSYour Name
987*5113495bSYour Name if (wma_handle) {
988*5113495bSYour Name wma_handle->umac_data_ota_ack_cb = NULL;
989*5113495bSYour Name wma_handle->last_umac_data_nbuf = NULL;
990*5113495bSYour Name wma_handle->ack_work_ctx = NULL;
991*5113495bSYour Name }
992*5113495bSYour Name }
993*5113495bSYour Name
994*5113495bSYour Name /**
995*5113495bSYour Name * wma_data_tx_ack_comp_hdlr() - handles tx data ack completion
996*5113495bSYour Name * @context: context with which the handler is registered
997*5113495bSYour Name * @netbuf: tx data nbuf
998*5113495bSYour Name * @err: status of tx completion
999*5113495bSYour Name *
1000*5113495bSYour Name * This is the cb registered with TxRx for
1001*5113495bSYour Name * Ack Complete
1002*5113495bSYour Name *
1003*5113495bSYour Name * Return: none
1004*5113495bSYour Name */
1005*5113495bSYour Name void
wma_data_tx_ack_comp_hdlr(void * wma_context,qdf_nbuf_t netbuf,int32_t status)1006*5113495bSYour Name wma_data_tx_ack_comp_hdlr(void *wma_context, qdf_nbuf_t netbuf, int32_t status)
1007*5113495bSYour Name {
1008*5113495bSYour Name tp_wma_handle wma_handle = (tp_wma_handle) wma_context;
1009*5113495bSYour Name struct wma_tx_ack_work_ctx *ack_work;
1010*5113495bSYour Name QDF_STATUS qdf_status;
1011*5113495bSYour Name
1012*5113495bSYour Name if (wma_validate_handle(wma_handle))
1013*5113495bSYour Name return;
1014*5113495bSYour Name
1015*5113495bSYour Name if (!netbuf) {
1016*5113495bSYour Name wma_debug("netbuf is NULL");
1017*5113495bSYour Name return;
1018*5113495bSYour Name }
1019*5113495bSYour Name
1020*5113495bSYour Name /*
1021*5113495bSYour Name * if netBuf does not match with pending nbuf then just free the
1022*5113495bSYour Name * netbuf and do not call ack cb
1023*5113495bSYour Name */
1024*5113495bSYour Name if (wma_handle->last_umac_data_nbuf != netbuf) {
1025*5113495bSYour Name wma_err("nbuf does not match but umac_data_ota_ack_cb is %s null",
1026*5113495bSYour Name wma_handle->umac_data_ota_ack_cb ? "not" : "");
1027*5113495bSYour Name goto free_nbuf;
1028*5113495bSYour Name }
1029*5113495bSYour Name
1030*5113495bSYour Name if (!wma_handle->umac_data_ota_ack_cb) {
1031*5113495bSYour Name wma_err_rl("ota_ack cb not registered");
1032*5113495bSYour Name goto free_nbuf;
1033*5113495bSYour Name }
1034*5113495bSYour Name
1035*5113495bSYour Name ack_work = qdf_mem_malloc(sizeof(struct wma_tx_ack_work_ctx));
1036*5113495bSYour Name if (ack_work) {
1037*5113495bSYour Name wma_handle->ack_work_ctx = ack_work;
1038*5113495bSYour Name
1039*5113495bSYour Name ack_work->wma_handle = wma_handle;
1040*5113495bSYour Name ack_work->sub_type = 0;
1041*5113495bSYour Name ack_work->status = status;
1042*5113495bSYour Name ack_work->frame = netbuf;
1043*5113495bSYour Name
1044*5113495bSYour Name /*
1045*5113495bSYour Name * free of the netbuf will be done by the scheduled work so
1046*5113495bSYour Name * just do unmap here
1047*5113495bSYour Name */
1048*5113495bSYour Name qdf_nbuf_unmap_single(wma_handle->qdf_dev, netbuf,
1049*5113495bSYour Name QDF_DMA_TO_DEVICE);
1050*5113495bSYour Name
1051*5113495bSYour Name qdf_status = qdf_create_work(0, &ack_work->ack_cmp_work,
1052*5113495bSYour Name wma_data_tx_ack_work_handler,
1053*5113495bSYour Name ack_work);
1054*5113495bSYour Name if (QDF_IS_STATUS_ERROR(qdf_status)) {
1055*5113495bSYour Name qdf_nbuf_free(netbuf);
1056*5113495bSYour Name wma_err("Failed to create TX ack work");
1057*5113495bSYour Name return;
1058*5113495bSYour Name }
1059*5113495bSYour Name
1060*5113495bSYour Name qdf_sched_work(0, &ack_work->ack_cmp_work);
1061*5113495bSYour Name return;
1062*5113495bSYour Name }
1063*5113495bSYour Name
1064*5113495bSYour Name free_nbuf:
1065*5113495bSYour Name /* unmap and freeing the tx buf as txrx is not taking care */
1066*5113495bSYour Name qdf_nbuf_unmap_single(wma_handle->qdf_dev, netbuf, QDF_DMA_TO_DEVICE);
1067*5113495bSYour Name qdf_nbuf_free(netbuf);
1068*5113495bSYour Name }
1069*5113495bSYour Name
1070*5113495bSYour Name /**
1071*5113495bSYour Name * wma_check_txrx_chainmask() - check txrx chainmask
1072*5113495bSYour Name * @num_rf_chains: number of rf chains
1073*5113495bSYour Name * @cmd_value: command value
1074*5113495bSYour Name *
1075*5113495bSYour Name * Return: QDF_STATUS_SUCCESS for success or error code
1076*5113495bSYour Name */
wma_check_txrx_chainmask(int num_rf_chains,int cmd_value)1077*5113495bSYour Name QDF_STATUS wma_check_txrx_chainmask(int num_rf_chains, int cmd_value)
1078*5113495bSYour Name {
1079*5113495bSYour Name if ((cmd_value > WMA_MAX_RF_CHAINS(num_rf_chains)) ||
1080*5113495bSYour Name (cmd_value < WMA_MIN_RF_CHAINS)) {
1081*5113495bSYour Name wma_err("Requested value %d over the range", cmd_value);
1082*5113495bSYour Name return QDF_STATUS_E_INVAL;
1083*5113495bSYour Name }
1084*5113495bSYour Name return QDF_STATUS_SUCCESS;
1085*5113495bSYour Name }
1086*5113495bSYour Name
1087*5113495bSYour Name /**
1088*5113495bSYour Name * wma_set_enable_disable_mcc_adaptive_scheduler() -enable/disable mcc scheduler
1089*5113495bSYour Name * @mcc_adaptive_scheduler: enable/disable
1090*5113495bSYour Name *
1091*5113495bSYour Name * This function enable/disable mcc adaptive scheduler in fw.
1092*5113495bSYour Name *
1093*5113495bSYour Name * Return: QDF_STATUS_SUCCESS for success or error code
1094*5113495bSYour Name */
wma_set_enable_disable_mcc_adaptive_scheduler(uint32_t mcc_adaptive_scheduler)1095*5113495bSYour Name QDF_STATUS wma_set_enable_disable_mcc_adaptive_scheduler(uint32_t
1096*5113495bSYour Name mcc_adaptive_scheduler)
1097*5113495bSYour Name {
1098*5113495bSYour Name tp_wma_handle wma = NULL;
1099*5113495bSYour Name uint32_t pdev_id;
1100*5113495bSYour Name
1101*5113495bSYour Name wma = cds_get_context(QDF_MODULE_ID_WMA);
1102*5113495bSYour Name if (!wma)
1103*5113495bSYour Name return QDF_STATUS_E_FAULT;
1104*5113495bSYour Name
1105*5113495bSYour Name /*
1106*5113495bSYour Name * Since there could be up to two instances of OCS in FW (one per MAC),
1107*5113495bSYour Name * FW provides the option of enabling and disabling MAS on a per MAC
1108*5113495bSYour Name * basis. But, Host does not have enable/disable option for individual
1109*5113495bSYour Name * MACs. So, FW agreed for the Host to send down a 'pdev id' of 0.
1110*5113495bSYour Name * When 'pdev id' of 0 is used, FW treats this as a SOC level command
1111*5113495bSYour Name * and applies the same value to both MACs. Irrespective of the value
1112*5113495bSYour Name * of 'WMI_SERVICE_DEPRECATED_REPLACE', the pdev id needs to be '0'
1113*5113495bSYour Name * (SOC level) for WMI_RESMGR_ADAPTIVE_OCS_ENABLE_DISABLE_CMDID
1114*5113495bSYour Name */
1115*5113495bSYour Name pdev_id = WMI_PDEV_ID_SOC;
1116*5113495bSYour Name
1117*5113495bSYour Name return wmi_unified_set_enable_disable_mcc_adaptive_scheduler_cmd(
1118*5113495bSYour Name wma->wmi_handle, mcc_adaptive_scheduler, pdev_id);
1119*5113495bSYour Name }
1120*5113495bSYour Name
1121*5113495bSYour Name /**
1122*5113495bSYour Name * wma_set_mcc_channel_time_latency() -set MCC channel time latency
1123*5113495bSYour Name * @wma: wma handle
1124*5113495bSYour Name * @mcc_channel: mcc channel
1125*5113495bSYour Name * @mcc_channel_time_latency: MCC channel time latency.
1126*5113495bSYour Name *
1127*5113495bSYour Name * Currently used to set time latency for an MCC vdev/adapter using operating
1128*5113495bSYour Name * channel of it and channel number. The info is provided run time using
1129*5113495bSYour Name * iwpriv command: iwpriv <wlan0 | p2p0> setMccLatency <latency in ms>.
1130*5113495bSYour Name *
1131*5113495bSYour Name * Return: QDF status
1132*5113495bSYour Name */
wma_set_mcc_channel_time_latency(tp_wma_handle wma,uint32_t mcc_channel,uint32_t mcc_channel_time_latency)1133*5113495bSYour Name QDF_STATUS wma_set_mcc_channel_time_latency(tp_wma_handle wma,
1134*5113495bSYour Name uint32_t mcc_channel, uint32_t mcc_channel_time_latency)
1135*5113495bSYour Name {
1136*5113495bSYour Name bool mcc_adapt_sch = false;
1137*5113495bSYour Name struct mac_context *mac = NULL;
1138*5113495bSYour Name uint32_t channel1 = mcc_channel;
1139*5113495bSYour Name uint32_t chan1_freq = cds_chan_to_freq(channel1);
1140*5113495bSYour Name
1141*5113495bSYour Name if (!wma) {
1142*5113495bSYour Name wma_err("NULL wma ptr. Exiting");
1143*5113495bSYour Name QDF_ASSERT(0);
1144*5113495bSYour Name return QDF_STATUS_E_FAILURE;
1145*5113495bSYour Name }
1146*5113495bSYour Name mac = cds_get_context(QDF_MODULE_ID_PE);
1147*5113495bSYour Name if (!mac) {
1148*5113495bSYour Name QDF_ASSERT(0);
1149*5113495bSYour Name return QDF_STATUS_E_FAILURE;
1150*5113495bSYour Name }
1151*5113495bSYour Name
1152*5113495bSYour Name /* First step is to confirm if MCC is active */
1153*5113495bSYour Name if (!lim_is_in_mcc(mac)) {
1154*5113495bSYour Name wma_err("MCC is not active. Exiting");
1155*5113495bSYour Name QDF_ASSERT(0);
1156*5113495bSYour Name return QDF_STATUS_E_FAILURE;
1157*5113495bSYour Name }
1158*5113495bSYour Name /* Confirm MCC adaptive scheduler feature is disabled */
1159*5113495bSYour Name if (policy_mgr_get_dynamic_mcc_adaptive_sch(mac->psoc,
1160*5113495bSYour Name &mcc_adapt_sch) ==
1161*5113495bSYour Name QDF_STATUS_SUCCESS) {
1162*5113495bSYour Name if (mcc_adapt_sch) {
1163*5113495bSYour Name wma_debug("Can't set channel latency while MCC ADAPTIVE SCHED is enabled. Exit");
1164*5113495bSYour Name return QDF_STATUS_SUCCESS;
1165*5113495bSYour Name }
1166*5113495bSYour Name } else {
1167*5113495bSYour Name wma_err("Failed to get value for MCC_ADAPTIVE_SCHED, "
1168*5113495bSYour Name "Exit w/o setting latency");
1169*5113495bSYour Name QDF_ASSERT(0);
1170*5113495bSYour Name return QDF_STATUS_E_FAILURE;
1171*5113495bSYour Name }
1172*5113495bSYour Name
1173*5113495bSYour Name return wmi_unified_set_mcc_channel_time_latency_cmd(wma->wmi_handle,
1174*5113495bSYour Name chan1_freq,
1175*5113495bSYour Name mcc_channel_time_latency);
1176*5113495bSYour Name }
1177*5113495bSYour Name
1178*5113495bSYour Name /**
1179*5113495bSYour Name * wma_set_mcc_channel_time_quota() -set MCC channel time quota
1180*5113495bSYour Name * @wma: wma handle
1181*5113495bSYour Name * @adapter_1_chan_number: adapter 1 channel number
1182*5113495bSYour Name * @adapter_1_quota: adapter 1 quota
1183*5113495bSYour Name * @adapter_2_chan_number: adapter 2 channel number
1184*5113495bSYour Name *
1185*5113495bSYour Name * Currently used to set time quota for 2 MCC vdevs/adapters using (operating
1186*5113495bSYour Name * channel, quota) for each mode . The info is provided run time using
1187*5113495bSYour Name * iwpriv command: iwpriv <wlan0 | p2p0> setMccQuota <quota in ms>.
1188*5113495bSYour Name * Note: the quota provided in command is for the same mode in cmd. HDD
1189*5113495bSYour Name * checks if MCC mode is active, gets the second mode and its operating chan.
1190*5113495bSYour Name * Quota for the 2nd role is calculated as 100 - quota of first mode.
1191*5113495bSYour Name *
1192*5113495bSYour Name * Return: QDF status
1193*5113495bSYour Name */
wma_set_mcc_channel_time_quota(tp_wma_handle wma,uint32_t adapter_1_chan_number,uint32_t adapter_1_quota,uint32_t adapter_2_chan_number)1194*5113495bSYour Name QDF_STATUS wma_set_mcc_channel_time_quota(tp_wma_handle wma,
1195*5113495bSYour Name uint32_t adapter_1_chan_number, uint32_t adapter_1_quota,
1196*5113495bSYour Name uint32_t adapter_2_chan_number)
1197*5113495bSYour Name {
1198*5113495bSYour Name bool mcc_adapt_sch = false;
1199*5113495bSYour Name struct mac_context *mac = NULL;
1200*5113495bSYour Name uint32_t chan1_freq = cds_chan_to_freq(adapter_1_chan_number);
1201*5113495bSYour Name uint32_t chan2_freq = cds_chan_to_freq(adapter_2_chan_number);
1202*5113495bSYour Name
1203*5113495bSYour Name if (!wma) {
1204*5113495bSYour Name wma_err("NULL wma ptr. Exiting");
1205*5113495bSYour Name QDF_ASSERT(0);
1206*5113495bSYour Name return QDF_STATUS_E_FAILURE;
1207*5113495bSYour Name }
1208*5113495bSYour Name mac = cds_get_context(QDF_MODULE_ID_PE);
1209*5113495bSYour Name if (!mac) {
1210*5113495bSYour Name QDF_ASSERT(0);
1211*5113495bSYour Name return QDF_STATUS_E_FAILURE;
1212*5113495bSYour Name }
1213*5113495bSYour Name
1214*5113495bSYour Name /* First step is to confirm if MCC is active */
1215*5113495bSYour Name if (!lim_is_in_mcc(mac)) {
1216*5113495bSYour Name wma_debug("MCC is not active. Exiting");
1217*5113495bSYour Name QDF_ASSERT(0);
1218*5113495bSYour Name return QDF_STATUS_E_FAILURE;
1219*5113495bSYour Name }
1220*5113495bSYour Name
1221*5113495bSYour Name /* Confirm MCC adaptive scheduler feature is disabled */
1222*5113495bSYour Name if (policy_mgr_get_dynamic_mcc_adaptive_sch(mac->psoc,
1223*5113495bSYour Name &mcc_adapt_sch) ==
1224*5113495bSYour Name QDF_STATUS_SUCCESS) {
1225*5113495bSYour Name if (mcc_adapt_sch) {
1226*5113495bSYour Name wma_debug("Can't set channel quota while MCC_ADAPTIVE_SCHED is enabled. Exit");
1227*5113495bSYour Name return QDF_STATUS_SUCCESS;
1228*5113495bSYour Name }
1229*5113495bSYour Name } else {
1230*5113495bSYour Name wma_err("Failed to retrieve WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED. Exit");
1231*5113495bSYour Name QDF_ASSERT(0);
1232*5113495bSYour Name return QDF_STATUS_E_FAILURE;
1233*5113495bSYour Name }
1234*5113495bSYour Name
1235*5113495bSYour Name return wmi_unified_set_mcc_channel_time_quota_cmd(wma->wmi_handle,
1236*5113495bSYour Name chan1_freq,
1237*5113495bSYour Name adapter_1_quota,
1238*5113495bSYour Name chan2_freq);
1239*5113495bSYour Name }
1240*5113495bSYour Name
1241*5113495bSYour Name #define MAX_VDEV_PROCESS_RATE_PARAMS 2
1242*5113495bSYour Name /* params being sent:
1243*5113495bSYour Name * wmi_vdev_param_sgi
1244*5113495bSYour Name * wmi_vdev_param_mcast_data_rate
1245*5113495bSYour Name */
wma_process_rate_update_indicate(tp_wma_handle wma,tSirRateUpdateInd * pRateUpdateParams)1246*5113495bSYour Name QDF_STATUS wma_process_rate_update_indicate(tp_wma_handle wma,
1247*5113495bSYour Name tSirRateUpdateInd *
1248*5113495bSYour Name pRateUpdateParams)
1249*5113495bSYour Name {
1250*5113495bSYour Name int32_t ret = 0;
1251*5113495bSYour Name uint8_t vdev_id = 0;
1252*5113495bSYour Name int32_t mbpsx10_rate = -1;
1253*5113495bSYour Name uint32_t paramid;
1254*5113495bSYour Name uint8_t rate = 0;
1255*5113495bSYour Name uint32_t short_gi, rate_flag;
1256*5113495bSYour Name struct wma_txrx_node *intr = wma->interfaces;
1257*5113495bSYour Name QDF_STATUS status;
1258*5113495bSYour Name struct dev_set_param setparam[MAX_VDEV_PROCESS_RATE_PARAMS] = {};
1259*5113495bSYour Name uint8_t index = 0;
1260*5113495bSYour Name
1261*5113495bSYour Name /* Get the vdev id */
1262*5113495bSYour Name if (wma_find_vdev_id_by_addr(wma, pRateUpdateParams->bssid.bytes,
1263*5113495bSYour Name &vdev_id)) {
1264*5113495bSYour Name wma_err("vdev handle is invalid for "QDF_MAC_ADDR_FMT,
1265*5113495bSYour Name QDF_MAC_ADDR_REF(pRateUpdateParams->bssid.bytes));
1266*5113495bSYour Name qdf_mem_free(pRateUpdateParams);
1267*5113495bSYour Name return QDF_STATUS_E_INVAL;
1268*5113495bSYour Name }
1269*5113495bSYour Name short_gi = intr[vdev_id].config.shortgi;
1270*5113495bSYour Name
1271*5113495bSYour Name status = wma_get_vdev_rate_flag(intr[vdev_id].vdev, &rate_flag);
1272*5113495bSYour Name if (QDF_IS_STATUS_ERROR(status)) {
1273*5113495bSYour Name wma_err("Failed to get rate_flag for VDEV_%d", vdev_id);
1274*5113495bSYour Name qdf_mem_free(pRateUpdateParams);
1275*5113495bSYour Name return QDF_STATUS_E_INVAL;
1276*5113495bSYour Name }
1277*5113495bSYour Name
1278*5113495bSYour Name if (short_gi == 0)
1279*5113495bSYour Name short_gi = (rate_flag & TX_RATE_SGI) ? true : false;
1280*5113495bSYour Name /* first check if reliable TX mcast rate is used. If not check the bcast
1281*5113495bSYour Name * Then is mcast. Mcast rate is saved in mcastDataRate24GHz
1282*5113495bSYour Name */
1283*5113495bSYour Name if (pRateUpdateParams->reliableMcastDataRateTxFlag > 0) {
1284*5113495bSYour Name mbpsx10_rate = pRateUpdateParams->reliableMcastDataRate;
1285*5113495bSYour Name paramid = wmi_vdev_param_mcast_data_rate;
1286*5113495bSYour Name if (pRateUpdateParams->
1287*5113495bSYour Name reliableMcastDataRateTxFlag & TX_RATE_SGI)
1288*5113495bSYour Name short_gi = 1; /* upper layer specified short GI */
1289*5113495bSYour Name } else if (pRateUpdateParams->bcastDataRate > -1) {
1290*5113495bSYour Name mbpsx10_rate = pRateUpdateParams->bcastDataRate;
1291*5113495bSYour Name paramid = wmi_vdev_param_bcast_data_rate;
1292*5113495bSYour Name } else {
1293*5113495bSYour Name mbpsx10_rate = pRateUpdateParams->mcastDataRate24GHz;
1294*5113495bSYour Name paramid = wmi_vdev_param_mcast_data_rate;
1295*5113495bSYour Name if (pRateUpdateParams->
1296*5113495bSYour Name mcastDataRate24GHzTxFlag & TX_RATE_SGI)
1297*5113495bSYour Name short_gi = 1; /* upper layer specified short GI */
1298*5113495bSYour Name }
1299*5113495bSYour Name wma_debug("dev_id = %d, dev_type = %d, dev_mode = %d,",
1300*5113495bSYour Name vdev_id, intr[vdev_id].type,
1301*5113495bSYour Name pRateUpdateParams->dev_mode);
1302*5113495bSYour Name wma_debug("mac = "QDF_MAC_ADDR_FMT", config.shortgi = %d, rate_flags = 0x%x",
1303*5113495bSYour Name QDF_MAC_ADDR_REF(pRateUpdateParams->bssid.bytes),
1304*5113495bSYour Name intr[vdev_id].config.shortgi, rate_flag);
1305*5113495bSYour Name ret = wma_encode_mc_rate(short_gi, intr[vdev_id].config.chwidth,
1306*5113495bSYour Name intr[vdev_id].ch_freq, mbpsx10_rate,
1307*5113495bSYour Name pRateUpdateParams->nss, &rate);
1308*5113495bSYour Name if (ret != QDF_STATUS_SUCCESS) {
1309*5113495bSYour Name wma_err("Error, Invalid input rate value");
1310*5113495bSYour Name qdf_mem_free(pRateUpdateParams);
1311*5113495bSYour Name return ret;
1312*5113495bSYour Name }
1313*5113495bSYour Name
1314*5113495bSYour Name ret = mlme_check_index_setparam(setparam, wmi_vdev_param_sgi, short_gi,
1315*5113495bSYour Name index++, MAX_VDEV_PROCESS_RATE_PARAMS);
1316*5113495bSYour Name if (QDF_IS_STATUS_ERROR(status)) {
1317*5113495bSYour Name wma_debug("failed at wmi_vdev_param_sgi");
1318*5113495bSYour Name goto error;
1319*5113495bSYour Name }
1320*5113495bSYour Name
1321*5113495bSYour Name ret = mlme_check_index_setparam(setparam, paramid, rate, index++,
1322*5113495bSYour Name MAX_VDEV_PROCESS_RATE_PARAMS);
1323*5113495bSYour Name if (QDF_IS_STATUS_ERROR(status)) {
1324*5113495bSYour Name wma_debug("failed at paramid:%d", paramid);
1325*5113495bSYour Name goto error;
1326*5113495bSYour Name }
1327*5113495bSYour Name
1328*5113495bSYour Name ret = wma_send_multi_pdev_vdev_set_params(MLME_VDEV_SETPARAM,
1329*5113495bSYour Name vdev_id, setparam, index);
1330*5113495bSYour Name if (QDF_IS_STATUS_ERROR(ret))
1331*5113495bSYour Name wma_debug("failed to send vdev set params");
1332*5113495bSYour Name error:
1333*5113495bSYour Name qdf_mem_free(pRateUpdateParams);
1334*5113495bSYour Name return ret;
1335*5113495bSYour Name }
1336*5113495bSYour Name
1337*5113495bSYour Name /**
1338*5113495bSYour Name * wma_mgmt_tx_ack_comp_hdlr() - handles tx ack mgmt completion
1339*5113495bSYour Name * @context: context with which the handler is registered
1340*5113495bSYour Name * @netbuf: tx mgmt nbuf
1341*5113495bSYour Name * @status: status of tx completion
1342*5113495bSYour Name *
1343*5113495bSYour Name * This is callback registered with TxRx for
1344*5113495bSYour Name * Ack Complete.
1345*5113495bSYour Name *
1346*5113495bSYour Name * Return: none
1347*5113495bSYour Name */
1348*5113495bSYour Name static void
wma_mgmt_tx_ack_comp_hdlr(void * wma_context,qdf_nbuf_t netbuf,int32_t status)1349*5113495bSYour Name wma_mgmt_tx_ack_comp_hdlr(void *wma_context, qdf_nbuf_t netbuf, int32_t status)
1350*5113495bSYour Name {
1351*5113495bSYour Name tp_wma_handle wma_handle = (tp_wma_handle) wma_context;
1352*5113495bSYour Name struct wlan_objmgr_pdev *pdev = (struct wlan_objmgr_pdev *)
1353*5113495bSYour Name wma_handle->pdev;
1354*5113495bSYour Name struct wmi_mgmt_params mgmt_params = {};
1355*5113495bSYour Name uint16_t desc_id;
1356*5113495bSYour Name uint8_t vdev_id;
1357*5113495bSYour Name
1358*5113495bSYour Name desc_id = QDF_NBUF_CB_MGMT_TXRX_DESC_ID(netbuf);
1359*5113495bSYour Name vdev_id = mgmt_txrx_get_vdev_id(pdev, desc_id);
1360*5113495bSYour Name
1361*5113495bSYour Name mgmt_params.vdev_id = vdev_id;
1362*5113495bSYour Name mgmt_txrx_tx_completion_handler(pdev, desc_id, status, &mgmt_params);
1363*5113495bSYour Name }
1364*5113495bSYour Name
1365*5113495bSYour Name /**
1366*5113495bSYour Name * wma_mgmt_tx_dload_comp_hldr() - handles tx mgmt completion
1367*5113495bSYour Name * @context: context with which the handler is registered
1368*5113495bSYour Name * @netbuf: tx mgmt nbuf
1369*5113495bSYour Name * @status: status of tx completion
1370*5113495bSYour Name *
1371*5113495bSYour Name * This function calls registered download callback while sending mgmt packet.
1372*5113495bSYour Name *
1373*5113495bSYour Name * Return: none
1374*5113495bSYour Name */
1375*5113495bSYour Name static void
wma_mgmt_tx_dload_comp_hldr(void * wma_context,qdf_nbuf_t netbuf,int32_t status)1376*5113495bSYour Name wma_mgmt_tx_dload_comp_hldr(void *wma_context, qdf_nbuf_t netbuf,
1377*5113495bSYour Name int32_t status)
1378*5113495bSYour Name {
1379*5113495bSYour Name QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
1380*5113495bSYour Name
1381*5113495bSYour Name tp_wma_handle wma_handle = (tp_wma_handle) wma_context;
1382*5113495bSYour Name void *mac_context = wma_handle->mac_context;
1383*5113495bSYour Name
1384*5113495bSYour Name wma_debug("Tx Complete Status %d", status);
1385*5113495bSYour Name
1386*5113495bSYour Name if (!wma_handle->tx_frm_download_comp_cb) {
1387*5113495bSYour Name wma_err("Tx Complete Cb not registered by umac");
1388*5113495bSYour Name return;
1389*5113495bSYour Name }
1390*5113495bSYour Name
1391*5113495bSYour Name /* Call Tx Mgmt Complete Callback registered by umac */
1392*5113495bSYour Name wma_handle->tx_frm_download_comp_cb(mac_context, netbuf, 0);
1393*5113495bSYour Name
1394*5113495bSYour Name /* Reset Callback */
1395*5113495bSYour Name wma_handle->tx_frm_download_comp_cb = NULL;
1396*5113495bSYour Name
1397*5113495bSYour Name /* Set the Tx Mgmt Complete Event */
1398*5113495bSYour Name qdf_status = qdf_event_set(&wma_handle->tx_frm_download_comp_event);
1399*5113495bSYour Name if (!QDF_IS_STATUS_SUCCESS(qdf_status))
1400*5113495bSYour Name wma_alert("Event Set failed - tx_frm_comp_event");
1401*5113495bSYour Name }
1402*5113495bSYour Name
1403*5113495bSYour Name /**
1404*5113495bSYour Name * wma_tx_attach() - attach tx related callbacks
1405*5113495bSYour Name * @pwmaCtx: wma context
1406*5113495bSYour Name *
1407*5113495bSYour Name * attaches tx fn with underlying layer.
1408*5113495bSYour Name *
1409*5113495bSYour Name * Return: QDF status
1410*5113495bSYour Name */
wma_tx_attach(tp_wma_handle wma_handle)1411*5113495bSYour Name QDF_STATUS wma_tx_attach(tp_wma_handle wma_handle)
1412*5113495bSYour Name {
1413*5113495bSYour Name /* Get the Vos Context */
1414*5113495bSYour Name struct cds_context *cds_handle =
1415*5113495bSYour Name (struct cds_context *) (wma_handle->cds_context);
1416*5113495bSYour Name
1417*5113495bSYour Name /* Get the txRx Pdev ID */
1418*5113495bSYour Name uint8_t pdev_id = WMI_PDEV_ID_SOC;
1419*5113495bSYour Name void *soc = cds_get_context(QDF_MODULE_ID_SOC);
1420*5113495bSYour Name
1421*5113495bSYour Name /* Register for Tx Management Frames */
1422*5113495bSYour Name cdp_mgmt_tx_cb_set(soc, pdev_id, 0,
1423*5113495bSYour Name wma_mgmt_tx_dload_comp_hldr,
1424*5113495bSYour Name wma_mgmt_tx_ack_comp_hdlr, wma_handle);
1425*5113495bSYour Name
1426*5113495bSYour Name /* Register callback to send PEER_UNMAP_RESPONSE cmd*/
1427*5113495bSYour Name if (cdp_cfg_get_peer_unmap_conf_support(soc))
1428*5113495bSYour Name cdp_peer_unmap_sync_cb_set(soc, pdev_id,
1429*5113495bSYour Name wma_peer_unmap_conf_cb);
1430*5113495bSYour Name
1431*5113495bSYour Name /* Store the Mac Context */
1432*5113495bSYour Name wma_handle->mac_context = cds_handle->mac_context;
1433*5113495bSYour Name
1434*5113495bSYour Name return QDF_STATUS_SUCCESS;
1435*5113495bSYour Name }
1436*5113495bSYour Name
1437*5113495bSYour Name /**
1438*5113495bSYour Name * wma_tx_detach() - detach tx related callbacks
1439*5113495bSYour Name * @tp_wma_handle: wma context
1440*5113495bSYour Name *
1441*5113495bSYour Name * Deregister with TxRx for Tx Mgmt Download and Ack completion.
1442*5113495bSYour Name *
1443*5113495bSYour Name * Return: QDF status
1444*5113495bSYour Name */
wma_tx_detach(tp_wma_handle wma_handle)1445*5113495bSYour Name QDF_STATUS wma_tx_detach(tp_wma_handle wma_handle)
1446*5113495bSYour Name {
1447*5113495bSYour Name void *soc = cds_get_context(QDF_MODULE_ID_SOC);
1448*5113495bSYour Name
1449*5113495bSYour Name /* Get the txRx Pdev ID */
1450*5113495bSYour Name uint8_t pdev_id = WMI_PDEV_ID_SOC;
1451*5113495bSYour Name
1452*5113495bSYour Name if (!soc)
1453*5113495bSYour Name return QDF_STATUS_E_FAILURE;
1454*5113495bSYour Name
1455*5113495bSYour Name if (pdev_id != OL_TXRX_INVALID_PDEV_ID) {
1456*5113495bSYour Name /* Deregister with TxRx for Tx Mgmt completion call back */
1457*5113495bSYour Name cdp_mgmt_tx_cb_set(soc, pdev_id, 0, NULL, NULL, NULL);
1458*5113495bSYour Name }
1459*5113495bSYour Name
1460*5113495bSYour Name /* Reset Tx Frm Callbacks */
1461*5113495bSYour Name wma_handle->tx_frm_download_comp_cb = NULL;
1462*5113495bSYour Name
1463*5113495bSYour Name /* Reset Tx Data Frame Ack Cb */
1464*5113495bSYour Name wma_handle->umac_data_ota_ack_cb = NULL;
1465*5113495bSYour Name
1466*5113495bSYour Name /* Reset last Tx Data Frame nbuf ptr */
1467*5113495bSYour Name wma_handle->last_umac_data_nbuf = NULL;
1468*5113495bSYour Name
1469*5113495bSYour Name return QDF_STATUS_SUCCESS;
1470*5113495bSYour Name }
1471*5113495bSYour Name
1472*5113495bSYour Name #if defined(QCA_LL_LEGACY_TX_FLOW_CONTROL) || \
1473*5113495bSYour Name defined(QCA_LL_TX_FLOW_CONTROL_V2) || defined(CONFIG_HL_SUPPORT)
wma_process_vdev_tx_pause_evt(void * soc,tp_wma_handle wma,wmi_tx_pause_event_fixed_param * event,uint8_t vdev_id)1474*5113495bSYour Name static void wma_process_vdev_tx_pause_evt(void *soc,
1475*5113495bSYour Name tp_wma_handle wma,
1476*5113495bSYour Name wmi_tx_pause_event_fixed_param *event,
1477*5113495bSYour Name uint8_t vdev_id)
1478*5113495bSYour Name {
1479*5113495bSYour Name /* PAUSE action, add bitmap */
1480*5113495bSYour Name if (event->action == ACTION_PAUSE) {
1481*5113495bSYour Name /* Exclude TDLS_OFFCHAN_CHOP from vdev based pauses */
1482*5113495bSYour Name if (event->pause_type == PAUSE_TYPE_CHOP_TDLS_OFFCHAN) {
1483*5113495bSYour Name cdp_fc_vdev_pause(soc, vdev_id,
1484*5113495bSYour Name OL_TXQ_PAUSE_REASON_FW,
1485*5113495bSYour Name event->pause_type);
1486*5113495bSYour Name } else {
1487*5113495bSYour Name /*
1488*5113495bSYour Name * Now only support per-dev pause so it is not
1489*5113495bSYour Name * necessary to pause a paused queue again.
1490*5113495bSYour Name */
1491*5113495bSYour Name if (!wma_vdev_get_pause_bitmap(vdev_id))
1492*5113495bSYour Name cdp_fc_vdev_pause(soc, vdev_id,
1493*5113495bSYour Name OL_TXQ_PAUSE_REASON_FW,
1494*5113495bSYour Name event->pause_type);
1495*5113495bSYour Name
1496*5113495bSYour Name wma_vdev_set_pause_bit(vdev_id,
1497*5113495bSYour Name event->pause_type);
1498*5113495bSYour Name }
1499*5113495bSYour Name }
1500*5113495bSYour Name /* UNPAUSE action, clean bitmap */
1501*5113495bSYour Name else if (event->action == ACTION_UNPAUSE) {
1502*5113495bSYour Name /* Exclude TDLS_OFFCHAN_CHOP from vdev based pauses */
1503*5113495bSYour Name if (event->pause_type == PAUSE_TYPE_CHOP_TDLS_OFFCHAN) {
1504*5113495bSYour Name cdp_fc_vdev_unpause(soc, vdev_id,
1505*5113495bSYour Name OL_TXQ_PAUSE_REASON_FW,
1506*5113495bSYour Name event->pause_type);
1507*5113495bSYour Name } else {
1508*5113495bSYour Name /* Handle unpause only if already paused */
1509*5113495bSYour Name if (wma_vdev_get_pause_bitmap(vdev_id)) {
1510*5113495bSYour Name wma_vdev_clear_pause_bit(vdev_id,
1511*5113495bSYour Name event->pause_type);
1512*5113495bSYour Name
1513*5113495bSYour Name if (wma->interfaces[vdev_id].pause_bitmap)
1514*5113495bSYour Name return;
1515*5113495bSYour Name
1516*5113495bSYour Name /* PAUSE BIT MAP is cleared
1517*5113495bSYour Name * UNPAUSE VDEV
1518*5113495bSYour Name */
1519*5113495bSYour Name cdp_fc_vdev_unpause(soc, vdev_id,
1520*5113495bSYour Name OL_TXQ_PAUSE_REASON_FW,
1521*5113495bSYour Name event->pause_type);
1522*5113495bSYour Name }
1523*5113495bSYour Name }
1524*5113495bSYour Name } else {
1525*5113495bSYour Name wma_err("Not Valid Action Type %d", event->action);
1526*5113495bSYour Name }
1527*5113495bSYour Name }
1528*5113495bSYour Name
wma_mcc_vdev_tx_pause_evt_handler(void * handle,uint8_t * event,uint32_t len)1529*5113495bSYour Name int wma_mcc_vdev_tx_pause_evt_handler(void *handle, uint8_t *event,
1530*5113495bSYour Name uint32_t len)
1531*5113495bSYour Name {
1532*5113495bSYour Name tp_wma_handle wma = (tp_wma_handle) handle;
1533*5113495bSYour Name WMI_TX_PAUSE_EVENTID_param_tlvs *param_buf;
1534*5113495bSYour Name wmi_tx_pause_event_fixed_param *wmi_event;
1535*5113495bSYour Name uint8_t vdev_id;
1536*5113495bSYour Name A_UINT32 vdev_map;
1537*5113495bSYour Name void *soc = cds_get_context(QDF_MODULE_ID_SOC);
1538*5113495bSYour Name
1539*5113495bSYour Name param_buf = (WMI_TX_PAUSE_EVENTID_param_tlvs *) event;
1540*5113495bSYour Name if (!param_buf) {
1541*5113495bSYour Name wma_err("Invalid roam event buffer");
1542*5113495bSYour Name return -EINVAL;
1543*5113495bSYour Name }
1544*5113495bSYour Name
1545*5113495bSYour Name if (ucfg_pmo_get_wow_bus_suspend(wma->psoc)) {
1546*5113495bSYour Name wma_debug("Suspend is in progress: Pause/Unpause Tx is NoOp");
1547*5113495bSYour Name return 0;
1548*5113495bSYour Name }
1549*5113495bSYour Name
1550*5113495bSYour Name if (!soc)
1551*5113495bSYour Name return -EINVAL;
1552*5113495bSYour Name
1553*5113495bSYour Name wmi_event = param_buf->fixed_param;
1554*5113495bSYour Name vdev_map = wmi_event->vdev_map;
1555*5113495bSYour Name /* FW mapped vdev from ID
1556*5113495bSYour Name * vdev_map = (1 << vdev_id)
1557*5113495bSYour Name * So, host should unmap to ID
1558*5113495bSYour Name */
1559*5113495bSYour Name for (vdev_id = 0; vdev_map != 0 && vdev_id < wma->max_bssid;
1560*5113495bSYour Name vdev_id++) {
1561*5113495bSYour Name if (!(vdev_map & 0x1)) {
1562*5113495bSYour Name /* No Vdev */
1563*5113495bSYour Name } else {
1564*5113495bSYour Name if (!wma->interfaces[vdev_id].vdev) {
1565*5113495bSYour Name wma_err("vdev is NULL for %d", vdev_id);
1566*5113495bSYour Name /* Test Next VDEV */
1567*5113495bSYour Name vdev_map >>= 1;
1568*5113495bSYour Name continue;
1569*5113495bSYour Name }
1570*5113495bSYour Name
1571*5113495bSYour Name wma_process_vdev_tx_pause_evt(soc, wma,
1572*5113495bSYour Name wmi_event,
1573*5113495bSYour Name vdev_id);
1574*5113495bSYour Name
1575*5113495bSYour Name wma_debug
1576*5113495bSYour Name ("vdev_id %d, pause_map 0x%x, pause type %d, action %d",
1577*5113495bSYour Name vdev_id, wma_vdev_get_pause_bitmap(vdev_id),
1578*5113495bSYour Name wmi_event->pause_type, wmi_event->action);
1579*5113495bSYour Name }
1580*5113495bSYour Name /* Test Next VDEV */
1581*5113495bSYour Name vdev_map >>= 1;
1582*5113495bSYour Name }
1583*5113495bSYour Name
1584*5113495bSYour Name return 0;
1585*5113495bSYour Name }
1586*5113495bSYour Name
1587*5113495bSYour Name #endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */
1588*5113495bSYour Name
1589*5113495bSYour Name #if defined(CONFIG_HL_SUPPORT) && defined(QCA_BAD_PEER_TX_FLOW_CL)
1590*5113495bSYour Name
1591*5113495bSYour Name /**
1592*5113495bSYour Name * wma_set_peer_rate_report_condition -
1593*5113495bSYour Name * this function set peer rate report
1594*5113495bSYour Name * condition info to firmware.
1595*5113495bSYour Name * @handle: Handle of WMA
1596*5113495bSYour Name * @config: Bad peer configuration from SIR module
1597*5113495bSYour Name *
1598*5113495bSYour Name * It is a wrapper function to sent WMI_PEER_SET_RATE_REPORT_CONDITION_CMDID
1599*5113495bSYour Name * to the firmware\target. If the command sent to firmware failed, free the
1600*5113495bSYour Name * buffer that allocated.
1601*5113495bSYour Name *
1602*5113495bSYour Name * Return: QDF_STATUS based on values sent to firmware
1603*5113495bSYour Name */
1604*5113495bSYour Name static
wma_set_peer_rate_report_condition(WMA_HANDLE handle,struct t_bad_peer_txtcl_config * config)1605*5113495bSYour Name QDF_STATUS wma_set_peer_rate_report_condition(WMA_HANDLE handle,
1606*5113495bSYour Name struct t_bad_peer_txtcl_config *config)
1607*5113495bSYour Name {
1608*5113495bSYour Name tp_wma_handle wma_handle = (tp_wma_handle)handle;
1609*5113495bSYour Name struct wmi_peer_rate_report_params rate_report_params = {0};
1610*5113495bSYour Name u_int32_t i, j;
1611*5113495bSYour Name
1612*5113495bSYour Name rate_report_params.rate_report_enable = config->enable;
1613*5113495bSYour Name rate_report_params.backoff_time = config->tgt_backoff;
1614*5113495bSYour Name rate_report_params.timer_period = config->tgt_report_prd;
1615*5113495bSYour Name for (i = 0; i < WMI_PEER_RATE_REPORT_COND_MAX_NUM; i++) {
1616*5113495bSYour Name rate_report_params.report_per_phy[i].cond_flags =
1617*5113495bSYour Name config->threshold[i].cond;
1618*5113495bSYour Name rate_report_params.report_per_phy[i].delta.delta_min =
1619*5113495bSYour Name config->threshold[i].delta;
1620*5113495bSYour Name rate_report_params.report_per_phy[i].delta.percent =
1621*5113495bSYour Name config->threshold[i].percentage;
1622*5113495bSYour Name for (j = 0; j < WMI_MAX_NUM_OF_RATE_THRESH; j++) {
1623*5113495bSYour Name rate_report_params.report_per_phy[i].
1624*5113495bSYour Name report_rate_threshold[j] =
1625*5113495bSYour Name config->threshold[i].thresh[j];
1626*5113495bSYour Name }
1627*5113495bSYour Name }
1628*5113495bSYour Name
1629*5113495bSYour Name return wmi_unified_peer_rate_report_cmd(wma_handle->wmi_handle,
1630*5113495bSYour Name &rate_report_params);
1631*5113495bSYour Name }
1632*5113495bSYour Name
1633*5113495bSYour Name /**
1634*5113495bSYour Name * wma_process_init_bad_peer_tx_ctl_info -
1635*5113495bSYour Name * this function to initialize peer rate report config info.
1636*5113495bSYour Name * @handle: Handle of WMA
1637*5113495bSYour Name * @config: Bad peer configuration from SIR module
1638*5113495bSYour Name *
1639*5113495bSYour Name * This function initializes the bad peer tx control data structure in WMA,
1640*5113495bSYour Name * sends down the initial configuration to the firmware and configures
1641*5113495bSYour Name * the peer status update setting in the tx_rx module.
1642*5113495bSYour Name *
1643*5113495bSYour Name * Return: QDF_STATUS based on procedure status
1644*5113495bSYour Name */
1645*5113495bSYour Name
wma_process_init_bad_peer_tx_ctl_info(tp_wma_handle wma,struct t_bad_peer_txtcl_config * config)1646*5113495bSYour Name QDF_STATUS wma_process_init_bad_peer_tx_ctl_info(tp_wma_handle wma,
1647*5113495bSYour Name struct t_bad_peer_txtcl_config *config)
1648*5113495bSYour Name {
1649*5113495bSYour Name /* Parameter sanity check */
1650*5113495bSYour Name void *soc = cds_get_context(QDF_MODULE_ID_SOC);
1651*5113495bSYour Name
1652*5113495bSYour Name if (!wma || !config) {
1653*5113495bSYour Name wma_err("Invalid input");
1654*5113495bSYour Name return QDF_STATUS_E_FAILURE;
1655*5113495bSYour Name }
1656*5113495bSYour Name
1657*5113495bSYour Name wma_debug("enable %d period %d txq limit %d\n",
1658*5113495bSYour Name config->enable,
1659*5113495bSYour Name config->period,
1660*5113495bSYour Name config->txq_limit);
1661*5113495bSYour Name
1662*5113495bSYour Name /* Only need to initialize the setting
1663*5113495bSYour Name * when the feature is enabled
1664*5113495bSYour Name */
1665*5113495bSYour Name if (config->enable) {
1666*5113495bSYour Name int i = 0;
1667*5113495bSYour Name
1668*5113495bSYour Name cdp_bad_peer_txctl_set_setting(soc,
1669*5113495bSYour Name WMI_PDEV_ID_SOC,
1670*5113495bSYour Name config->enable,
1671*5113495bSYour Name config->period,
1672*5113495bSYour Name config->txq_limit);
1673*5113495bSYour Name
1674*5113495bSYour Name for (i = 0; i < WLAN_WMA_IEEE80211_MAX_LEVEL; i++) {
1675*5113495bSYour Name u_int32_t threshold, limit;
1676*5113495bSYour Name
1677*5113495bSYour Name threshold = config->threshold[i].thresh[0];
1678*5113495bSYour Name limit = config->threshold[i].txlimit;
1679*5113495bSYour Name cdp_bad_peer_txctl_update_threshold(soc,
1680*5113495bSYour Name WMI_PDEV_ID_SOC,
1681*5113495bSYour Name i,
1682*5113495bSYour Name threshold,
1683*5113495bSYour Name limit);
1684*5113495bSYour Name }
1685*5113495bSYour Name }
1686*5113495bSYour Name
1687*5113495bSYour Name return wma_set_peer_rate_report_condition(wma, config);
1688*5113495bSYour Name }
1689*5113495bSYour Name #endif /* defined(CONFIG_HL_SUPPORT) && defined(QCA_BAD_PEER_TX_FLOW_CL) */
1690*5113495bSYour Name
1691*5113495bSYour Name #ifdef FW_THERMAL_THROTTLE_SUPPORT
1692*5113495bSYour Name /**
1693*5113495bSYour Name * wma_update_thermal_mitigation_to_fw - update thermal mitigation to fw
1694*5113495bSYour Name * @wma: wma handle
1695*5113495bSYour Name * @thermal_level: thermal level
1696*5113495bSYour Name *
1697*5113495bSYour Name * This function sends down thermal mitigation params to the fw
1698*5113495bSYour Name *
1699*5113495bSYour Name * Returns: QDF_STATUS_SUCCESS for success otherwise failure
1700*5113495bSYour Name */
wma_update_thermal_mitigation_to_fw(tp_wma_handle wma,u_int8_t thermal_level)1701*5113495bSYour Name static QDF_STATUS wma_update_thermal_mitigation_to_fw(tp_wma_handle wma,
1702*5113495bSYour Name u_int8_t thermal_level)
1703*5113495bSYour Name {
1704*5113495bSYour Name struct thermal_mitigation_params therm_data = {0};
1705*5113495bSYour Name
1706*5113495bSYour Name /* Check if vdev is in mcc, if in mcc set dc value as 10, else 100 */
1707*5113495bSYour Name therm_data.dc = 100;
1708*5113495bSYour Name therm_data.enable = 1;
1709*5113495bSYour Name therm_data.levelconf[0].dcoffpercent =
1710*5113495bSYour Name wma->thermal_mgmt_info.throttle_duty_cycle_tbl[thermal_level];
1711*5113495bSYour Name therm_data.levelconf[0].priority = 0;
1712*5113495bSYour Name therm_data.num_thermal_conf = 1;
1713*5113495bSYour Name
1714*5113495bSYour Name return wmi_unified_thermal_mitigation_param_cmd_send(wma->wmi_handle,
1715*5113495bSYour Name &therm_data);
1716*5113495bSYour Name }
1717*5113495bSYour Name #else /* FW_THERMAL_THROTTLE_SUPPORT */
1718*5113495bSYour Name /**
1719*5113495bSYour Name * wma_update_thermal_mitigation_to_fw - update thermal mitigation to fw
1720*5113495bSYour Name * @wma: wma handle
1721*5113495bSYour Name * @thermal_level: thermal level
1722*5113495bSYour Name *
1723*5113495bSYour Name * This function sends down thermal mitigation params to the fw
1724*5113495bSYour Name *
1725*5113495bSYour Name * Returns: QDF_STATUS_SUCCESS for success otherwise failure
1726*5113495bSYour Name */
wma_update_thermal_mitigation_to_fw(tp_wma_handle wma,u_int8_t thermal_level)1727*5113495bSYour Name static QDF_STATUS wma_update_thermal_mitigation_to_fw(tp_wma_handle wma,
1728*5113495bSYour Name u_int8_t thermal_level)
1729*5113495bSYour Name {
1730*5113495bSYour Name return QDF_STATUS_SUCCESS;
1731*5113495bSYour Name }
1732*5113495bSYour Name #endif
1733*5113495bSYour Name
1734*5113495bSYour Name /**
1735*5113495bSYour Name * wma_update_thermal_cfg_to_fw() - update thermal configuration to FW
1736*5113495bSYour Name * @wma: Pointer to WMA handle
1737*5113495bSYour Name *
1738*5113495bSYour Name * This function update thermal configuration to FW
1739*5113495bSYour Name *
1740*5113495bSYour Name * Returns: QDF_STATUS_SUCCESS for success otherwise failure
1741*5113495bSYour Name */
wma_update_thermal_cfg_to_fw(tp_wma_handle wma)1742*5113495bSYour Name static QDF_STATUS wma_update_thermal_cfg_to_fw(tp_wma_handle wma)
1743*5113495bSYour Name {
1744*5113495bSYour Name t_thermal_cmd_params thermal_params = {0};
1745*5113495bSYour Name
1746*5113495bSYour Name /* Get the temperature thresholds to set in firmware */
1747*5113495bSYour Name thermal_params.minTemp =
1748*5113495bSYour Name wma->thermal_mgmt_info.thermalLevels[WLAN_WMA_THERMAL_LEVEL_0].
1749*5113495bSYour Name minTempThreshold;
1750*5113495bSYour Name thermal_params.maxTemp =
1751*5113495bSYour Name wma->thermal_mgmt_info.thermalLevels[WLAN_WMA_THERMAL_LEVEL_0].
1752*5113495bSYour Name maxTempThreshold;
1753*5113495bSYour Name thermal_params.thermalEnable =
1754*5113495bSYour Name wma->thermal_mgmt_info.thermalMgmtEnabled;
1755*5113495bSYour Name thermal_params.thermal_action = wma->thermal_mgmt_info.thermal_action;
1756*5113495bSYour Name
1757*5113495bSYour Name wma_debug("TM sending to fw: min_temp %d max_temp %d enable %d act %d",
1758*5113495bSYour Name thermal_params.minTemp, thermal_params.maxTemp,
1759*5113495bSYour Name thermal_params.thermalEnable, thermal_params.thermal_action);
1760*5113495bSYour Name
1761*5113495bSYour Name return wma_set_thermal_mgmt(wma, thermal_params);
1762*5113495bSYour Name }
1763*5113495bSYour Name
1764*5113495bSYour Name /**
1765*5113495bSYour Name * wma_process_init_thermal_info() - initialize thermal info
1766*5113495bSYour Name * @wma: Pointer to WMA handle
1767*5113495bSYour Name * @pThermalParams: Pointer to thermal mitigation parameters
1768*5113495bSYour Name *
1769*5113495bSYour Name * This function initializes the thermal management table in WMA,
1770*5113495bSYour Name * sends down the initial temperature thresholds to the firmware
1771*5113495bSYour Name * and configures the throttle period in the tx rx module
1772*5113495bSYour Name *
1773*5113495bSYour Name * Returns: QDF_STATUS_SUCCESS for success otherwise failure
1774*5113495bSYour Name */
wma_process_init_thermal_info(tp_wma_handle wma,t_thermal_mgmt * pThermalParams)1775*5113495bSYour Name QDF_STATUS wma_process_init_thermal_info(tp_wma_handle wma,
1776*5113495bSYour Name t_thermal_mgmt *pThermalParams)
1777*5113495bSYour Name {
1778*5113495bSYour Name QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
1779*5113495bSYour Name #ifdef FW_THERMAL_THROTTLE_SUPPORT
1780*5113495bSYour Name int i = 0;
1781*5113495bSYour Name #endif /* FW_THERMAL_THROTTLE_SUPPORT */
1782*5113495bSYour Name
1783*5113495bSYour Name if (!wma || !pThermalParams) {
1784*5113495bSYour Name wma_err("TM Invalid input");
1785*5113495bSYour Name return QDF_STATUS_E_FAILURE;
1786*5113495bSYour Name }
1787*5113495bSYour Name
1788*5113495bSYour Name wma_debug("TM enable %d period %d action %d",
1789*5113495bSYour Name pThermalParams->thermalMgmtEnabled,
1790*5113495bSYour Name pThermalParams->throttlePeriod,
1791*5113495bSYour Name pThermalParams->thermal_action);
1792*5113495bSYour Name
1793*5113495bSYour Name wma_nofl_debug("Throttle Duty Cycle Level in percentage:\n"
1794*5113495bSYour Name "0 %d\n"
1795*5113495bSYour Name "1 %d\n"
1796*5113495bSYour Name "2 %d\n"
1797*5113495bSYour Name "3 %d\n"
1798*5113495bSYour Name "4 %d\n"
1799*5113495bSYour Name "5 %d",
1800*5113495bSYour Name pThermalParams->throttle_duty_cycle_tbl[0],
1801*5113495bSYour Name pThermalParams->throttle_duty_cycle_tbl[1],
1802*5113495bSYour Name pThermalParams->throttle_duty_cycle_tbl[2],
1803*5113495bSYour Name pThermalParams->throttle_duty_cycle_tbl[3],
1804*5113495bSYour Name pThermalParams->throttle_duty_cycle_tbl[4],
1805*5113495bSYour Name pThermalParams->throttle_duty_cycle_tbl[5]);
1806*5113495bSYour Name
1807*5113495bSYour Name wma->thermal_mgmt_info.thermalMgmtEnabled =
1808*5113495bSYour Name pThermalParams->thermalMgmtEnabled;
1809*5113495bSYour Name wma->thermal_mgmt_info.thermalLevels[0].minTempThreshold =
1810*5113495bSYour Name pThermalParams->thermalLevels[0].minTempThreshold;
1811*5113495bSYour Name wma->thermal_mgmt_info.thermalLevels[0].maxTempThreshold =
1812*5113495bSYour Name pThermalParams->thermalLevels[0].maxTempThreshold;
1813*5113495bSYour Name wma->thermal_mgmt_info.thermalLevels[1].minTempThreshold =
1814*5113495bSYour Name pThermalParams->thermalLevels[1].minTempThreshold;
1815*5113495bSYour Name wma->thermal_mgmt_info.thermalLevels[1].maxTempThreshold =
1816*5113495bSYour Name pThermalParams->thermalLevels[1].maxTempThreshold;
1817*5113495bSYour Name wma->thermal_mgmt_info.thermalLevels[2].minTempThreshold =
1818*5113495bSYour Name pThermalParams->thermalLevels[2].minTempThreshold;
1819*5113495bSYour Name wma->thermal_mgmt_info.thermalLevels[2].maxTempThreshold =
1820*5113495bSYour Name pThermalParams->thermalLevels[2].maxTempThreshold;
1821*5113495bSYour Name wma->thermal_mgmt_info.thermalLevels[3].minTempThreshold =
1822*5113495bSYour Name pThermalParams->thermalLevels[3].minTempThreshold;
1823*5113495bSYour Name wma->thermal_mgmt_info.thermalLevels[3].maxTempThreshold =
1824*5113495bSYour Name pThermalParams->thermalLevels[3].maxTempThreshold;
1825*5113495bSYour Name wma->thermal_mgmt_info.thermalLevels[4].minTempThreshold =
1826*5113495bSYour Name pThermalParams->thermalLevels[4].minTempThreshold;
1827*5113495bSYour Name wma->thermal_mgmt_info.thermalLevels[4].maxTempThreshold =
1828*5113495bSYour Name pThermalParams->thermalLevels[4].maxTempThreshold;
1829*5113495bSYour Name wma->thermal_mgmt_info.thermalLevels[5].minTempThreshold =
1830*5113495bSYour Name pThermalParams->thermalLevels[5].minTempThreshold;
1831*5113495bSYour Name wma->thermal_mgmt_info.thermalLevels[5].maxTempThreshold =
1832*5113495bSYour Name pThermalParams->thermalLevels[5].maxTempThreshold;
1833*5113495bSYour Name wma->thermal_mgmt_info.thermalCurrLevel = WLAN_WMA_THERMAL_LEVEL_0;
1834*5113495bSYour Name wma->thermal_mgmt_info.thermal_action = pThermalParams->thermal_action;
1835*5113495bSYour Name wma_nofl_debug("TM level min max:\n"
1836*5113495bSYour Name "0 %d %d\n"
1837*5113495bSYour Name "1 %d %d\n"
1838*5113495bSYour Name "2 %d %d\n"
1839*5113495bSYour Name "3 %d %d\n"
1840*5113495bSYour Name "4 %d %d\n"
1841*5113495bSYour Name "5 %d %d",
1842*5113495bSYour Name wma->thermal_mgmt_info.thermalLevels[0].minTempThreshold,
1843*5113495bSYour Name wma->thermal_mgmt_info.thermalLevels[0].maxTempThreshold,
1844*5113495bSYour Name wma->thermal_mgmt_info.thermalLevels[1].minTempThreshold,
1845*5113495bSYour Name wma->thermal_mgmt_info.thermalLevels[1].maxTempThreshold,
1846*5113495bSYour Name wma->thermal_mgmt_info.thermalLevels[2].minTempThreshold,
1847*5113495bSYour Name wma->thermal_mgmt_info.thermalLevels[2].maxTempThreshold,
1848*5113495bSYour Name wma->thermal_mgmt_info.thermalLevels[3].minTempThreshold,
1849*5113495bSYour Name wma->thermal_mgmt_info.thermalLevels[3].maxTempThreshold,
1850*5113495bSYour Name wma->thermal_mgmt_info.thermalLevels[4].minTempThreshold,
1851*5113495bSYour Name wma->thermal_mgmt_info.thermalLevels[4].maxTempThreshold,
1852*5113495bSYour Name wma->thermal_mgmt_info.thermalLevels[5].minTempThreshold,
1853*5113495bSYour Name wma->thermal_mgmt_info.thermalLevels[5].maxTempThreshold);
1854*5113495bSYour Name
1855*5113495bSYour Name #ifdef FW_THERMAL_THROTTLE_SUPPORT
1856*5113495bSYour Name for (i = 0; i < THROTTLE_LEVEL_MAX; i++)
1857*5113495bSYour Name wma->thermal_mgmt_info.throttle_duty_cycle_tbl[i] =
1858*5113495bSYour Name pThermalParams->throttle_duty_cycle_tbl[i];
1859*5113495bSYour Name #endif /* FW_THERMAL_THROTTLE_SUPPORT */
1860*5113495bSYour Name
1861*5113495bSYour Name if (wma->thermal_mgmt_info.thermalMgmtEnabled) {
1862*5113495bSYour Name if (!wma->fw_therm_throt_support) {
1863*5113495bSYour Name cdp_throttle_init_period(
1864*5113495bSYour Name cds_get_context(QDF_MODULE_ID_SOC),
1865*5113495bSYour Name WMI_PDEV_ID_SOC, pThermalParams->throttlePeriod,
1866*5113495bSYour Name &pThermalParams->throttle_duty_cycle_tbl[0]);
1867*5113495bSYour Name } else {
1868*5113495bSYour Name qdf_status = wma_update_thermal_mitigation_to_fw(
1869*5113495bSYour Name wma, WLAN_WMA_THERMAL_LEVEL_0);
1870*5113495bSYour Name if (QDF_STATUS_SUCCESS != qdf_status)
1871*5113495bSYour Name return qdf_status;
1872*5113495bSYour Name }
1873*5113495bSYour Name qdf_status = wma_update_thermal_cfg_to_fw(wma);
1874*5113495bSYour Name }
1875*5113495bSYour Name return qdf_status;
1876*5113495bSYour Name }
1877*5113495bSYour Name
1878*5113495bSYour Name /**
1879*5113495bSYour Name * wma_set_thermal_level_ind() - send SME set thermal level indication message
1880*5113495bSYour Name * @level: thermal level
1881*5113495bSYour Name *
1882*5113495bSYour Name * Send SME SET_THERMAL_LEVEL_IND message
1883*5113495bSYour Name *
1884*5113495bSYour Name * Returns: none
1885*5113495bSYour Name */
wma_set_thermal_level_ind(u_int8_t level)1886*5113495bSYour Name static void wma_set_thermal_level_ind(u_int8_t level)
1887*5113495bSYour Name {
1888*5113495bSYour Name QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
1889*5113495bSYour Name struct scheduler_msg sme_msg = {0};
1890*5113495bSYour Name
1891*5113495bSYour Name wma_info("Thermal level: %d", level);
1892*5113495bSYour Name
1893*5113495bSYour Name sme_msg.type = eWNI_SME_SET_THERMAL_LEVEL_IND;
1894*5113495bSYour Name sme_msg.bodyptr = NULL;
1895*5113495bSYour Name sme_msg.bodyval = level;
1896*5113495bSYour Name
1897*5113495bSYour Name qdf_status = scheduler_post_message(QDF_MODULE_ID_WMA,
1898*5113495bSYour Name QDF_MODULE_ID_SME,
1899*5113495bSYour Name QDF_MODULE_ID_SME, &sme_msg);
1900*5113495bSYour Name if (!QDF_IS_STATUS_SUCCESS(qdf_status))
1901*5113495bSYour Name wma_err("Fail to post set thermal level ind msg");
1902*5113495bSYour Name }
1903*5113495bSYour Name
1904*5113495bSYour Name /**
1905*5113495bSYour Name * wma_process_set_thermal_level() - sets thermal level
1906*5113495bSYour Name * @wma: Pointer to WMA handle
1907*5113495bSYour Name * @thermal_level : Thermal level
1908*5113495bSYour Name *
1909*5113495bSYour Name * This function sets the new thermal throttle level in the
1910*5113495bSYour Name * txrx module and sends down the corresponding temperature
1911*5113495bSYour Name * thresholds to the firmware
1912*5113495bSYour Name *
1913*5113495bSYour Name * Returns: QDF_STATUS_SUCCESS for success otherwise failure
1914*5113495bSYour Name */
wma_process_set_thermal_level(tp_wma_handle wma,uint8_t thermal_level)1915*5113495bSYour Name QDF_STATUS wma_process_set_thermal_level(tp_wma_handle wma,
1916*5113495bSYour Name uint8_t thermal_level)
1917*5113495bSYour Name {
1918*5113495bSYour Name if (!wma) {
1919*5113495bSYour Name wma_err("TM Invalid input");
1920*5113495bSYour Name return QDF_STATUS_E_FAILURE;
1921*5113495bSYour Name }
1922*5113495bSYour Name
1923*5113495bSYour Name wma_debug("TM set level %d", thermal_level);
1924*5113495bSYour Name
1925*5113495bSYour Name /* Check if thermal mitigation is enabled */
1926*5113495bSYour Name if (!wma->thermal_mgmt_info.thermalMgmtEnabled) {
1927*5113495bSYour Name wma_err("Thermal mgmt is not enabled, ignoring set level command");
1928*5113495bSYour Name return QDF_STATUS_E_FAILURE;
1929*5113495bSYour Name }
1930*5113495bSYour Name
1931*5113495bSYour Name if (thermal_level >= WLAN_WMA_MAX_THERMAL_LEVELS) {
1932*5113495bSYour Name wma_err("Invalid thermal level set %d", thermal_level);
1933*5113495bSYour Name return QDF_STATUS_E_FAILURE;
1934*5113495bSYour Name }
1935*5113495bSYour Name
1936*5113495bSYour Name if (thermal_level == wma->thermal_mgmt_info.thermalCurrLevel) {
1937*5113495bSYour Name wma_debug("Current level %d is same as the set level, ignoring",
1938*5113495bSYour Name wma->thermal_mgmt_info.thermalCurrLevel);
1939*5113495bSYour Name return QDF_STATUS_SUCCESS;
1940*5113495bSYour Name }
1941*5113495bSYour Name
1942*5113495bSYour Name wma->thermal_mgmt_info.thermalCurrLevel = thermal_level;
1943*5113495bSYour Name
1944*5113495bSYour Name cdp_throttle_set_level(cds_get_context(QDF_MODULE_ID_SOC),
1945*5113495bSYour Name WMI_PDEV_ID_SOC, thermal_level);
1946*5113495bSYour Name
1947*5113495bSYour Name /* Send SME SET_THERMAL_LEVEL_IND message */
1948*5113495bSYour Name wma_set_thermal_level_ind(thermal_level);
1949*5113495bSYour Name
1950*5113495bSYour Name return QDF_STATUS_SUCCESS;
1951*5113495bSYour Name }
1952*5113495bSYour Name
1953*5113495bSYour Name
1954*5113495bSYour Name /**
1955*5113495bSYour Name * wma_set_thermal_mgmt() - set thermal mgmt command to fw
1956*5113495bSYour Name * @wma_handle: Pointer to WMA handle
1957*5113495bSYour Name * @thermal_info: Thermal command information
1958*5113495bSYour Name *
1959*5113495bSYour Name * This function sends the thermal management command
1960*5113495bSYour Name * to the firmware
1961*5113495bSYour Name *
1962*5113495bSYour Name * Return: QDF_STATUS_SUCCESS for success otherwise failure
1963*5113495bSYour Name */
wma_set_thermal_mgmt(tp_wma_handle wma_handle,t_thermal_cmd_params thermal_info)1964*5113495bSYour Name QDF_STATUS wma_set_thermal_mgmt(tp_wma_handle wma_handle,
1965*5113495bSYour Name t_thermal_cmd_params thermal_info)
1966*5113495bSYour Name {
1967*5113495bSYour Name struct thermal_cmd_params mgmt_thermal_info = {0};
1968*5113495bSYour Name
1969*5113495bSYour Name if (!wma_handle) {
1970*5113495bSYour Name wma_err("Invalid input");
1971*5113495bSYour Name QDF_ASSERT(0);
1972*5113495bSYour Name return QDF_STATUS_E_FAILURE;
1973*5113495bSYour Name }
1974*5113495bSYour Name
1975*5113495bSYour Name mgmt_thermal_info.min_temp = thermal_info.minTemp;
1976*5113495bSYour Name mgmt_thermal_info.max_temp = thermal_info.maxTemp;
1977*5113495bSYour Name mgmt_thermal_info.thermal_enable = thermal_info.thermalEnable;
1978*5113495bSYour Name mgmt_thermal_info.thermal_action = thermal_info.thermal_action;
1979*5113495bSYour Name
1980*5113495bSYour Name return wmi_unified_set_thermal_mgmt_cmd(wma_handle->wmi_handle,
1981*5113495bSYour Name &mgmt_thermal_info);
1982*5113495bSYour Name }
1983*5113495bSYour Name
1984*5113495bSYour Name /**
1985*5113495bSYour Name * wma_thermal_mgmt_get_level() - returns throttle level
1986*5113495bSYour Name * @handle: Pointer to WMA handle
1987*5113495bSYour Name * @temp: temperature
1988*5113495bSYour Name *
1989*5113495bSYour Name * This function returns the thermal(throttle) level
1990*5113495bSYour Name * given the temperature
1991*5113495bSYour Name *
1992*5113495bSYour Name * Return: thermal (throttle) level
1993*5113495bSYour Name */
wma_thermal_mgmt_get_level(void * handle,uint32_t temp)1994*5113495bSYour Name static uint8_t wma_thermal_mgmt_get_level(void *handle, uint32_t temp)
1995*5113495bSYour Name {
1996*5113495bSYour Name tp_wma_handle wma = (tp_wma_handle) handle;
1997*5113495bSYour Name int i;
1998*5113495bSYour Name uint8_t level;
1999*5113495bSYour Name
2000*5113495bSYour Name level = i = wma->thermal_mgmt_info.thermalCurrLevel;
2001*5113495bSYour Name while (temp < wma->thermal_mgmt_info.thermalLevels[i].minTempThreshold
2002*5113495bSYour Name && i > 0) {
2003*5113495bSYour Name i--;
2004*5113495bSYour Name level = i;
2005*5113495bSYour Name }
2006*5113495bSYour Name
2007*5113495bSYour Name i = wma->thermal_mgmt_info.thermalCurrLevel;
2008*5113495bSYour Name while (temp > wma->thermal_mgmt_info.thermalLevels[i].maxTempThreshold
2009*5113495bSYour Name && i < (WLAN_WMA_MAX_THERMAL_LEVELS - 1)) {
2010*5113495bSYour Name i++;
2011*5113495bSYour Name level = i;
2012*5113495bSYour Name }
2013*5113495bSYour Name
2014*5113495bSYour Name wma_warn("Change thermal level from %d -> %d",
2015*5113495bSYour Name wma->thermal_mgmt_info.thermalCurrLevel, level);
2016*5113495bSYour Name
2017*5113495bSYour Name return level;
2018*5113495bSYour Name }
2019*5113495bSYour Name
2020*5113495bSYour Name /**
2021*5113495bSYour Name * wms_thermal_level_to_host() - Convert wma thermal level to host enum
2022*5113495bSYour Name * @level: current thermal throttle level
2023*5113495bSYour Name *
2024*5113495bSYour Name * Return: host thermal throttle level
2025*5113495bSYour Name */
2026*5113495bSYour Name static enum thermal_throttle_level
wma_thermal_level_to_host(uint8_t level)2027*5113495bSYour Name wma_thermal_level_to_host(uint8_t level)
2028*5113495bSYour Name {
2029*5113495bSYour Name switch (level) {
2030*5113495bSYour Name case WLAN_WMA_THERMAL_LEVEL_0:
2031*5113495bSYour Name return THERMAL_FULLPERF;
2032*5113495bSYour Name case WLAN_WMA_THERMAL_LEVEL_1:
2033*5113495bSYour Name case WLAN_WMA_THERMAL_LEVEL_2:
2034*5113495bSYour Name case WLAN_WMA_THERMAL_LEVEL_3:
2035*5113495bSYour Name return THERMAL_MITIGATION;
2036*5113495bSYour Name case WLAN_WMA_THERMAL_LEVEL_4:
2037*5113495bSYour Name return THERMAL_SHUTOFF;
2038*5113495bSYour Name case WLAN_WMA_THERMAL_LEVEL_5:
2039*5113495bSYour Name return THERMAL_SHUTDOWN_TARGET;
2040*5113495bSYour Name default:
2041*5113495bSYour Name return THERMAL_UNKNOWN;
2042*5113495bSYour Name }
2043*5113495bSYour Name }
2044*5113495bSYour Name
2045*5113495bSYour Name /**
2046*5113495bSYour Name * wma_thermal_mgmt_evt_handler() - thermal mgmt event handler
2047*5113495bSYour Name * @wma_handle: Pointer to WMA handle
2048*5113495bSYour Name * @event: Thermal event information
2049*5113495bSYour Name * @len: length of the event
2050*5113495bSYour Name *
2051*5113495bSYour Name * This function handles the thermal mgmt event from the firmware
2052*5113495bSYour Name *
2053*5113495bSYour Name * Return: 0 for success otherwise failure
2054*5113495bSYour Name */
wma_thermal_mgmt_evt_handler(void * handle,uint8_t * event,uint32_t len)2055*5113495bSYour Name int wma_thermal_mgmt_evt_handler(void *handle, uint8_t *event, uint32_t len)
2056*5113495bSYour Name {
2057*5113495bSYour Name tp_wma_handle wma;
2058*5113495bSYour Name wmi_thermal_mgmt_event_fixed_param *tm_event;
2059*5113495bSYour Name uint8_t thermal_level;
2060*5113495bSYour Name t_thermal_cmd_params thermal_params = {0};
2061*5113495bSYour Name WMI_THERMAL_MGMT_EVENTID_param_tlvs *param_buf;
2062*5113495bSYour Name struct wlan_objmgr_psoc *psoc;
2063*5113495bSYour Name struct thermal_throttle_info info = {0};
2064*5113495bSYour Name
2065*5113495bSYour Name if (!event || !handle) {
2066*5113495bSYour Name wma_err("Invalid thermal mitigation event buffer");
2067*5113495bSYour Name return -EINVAL;
2068*5113495bSYour Name }
2069*5113495bSYour Name
2070*5113495bSYour Name wma = (tp_wma_handle) handle;
2071*5113495bSYour Name
2072*5113495bSYour Name if (wma_validate_handle(wma))
2073*5113495bSYour Name return -EINVAL;
2074*5113495bSYour Name
2075*5113495bSYour Name psoc = wma->psoc;
2076*5113495bSYour Name if (!psoc) {
2077*5113495bSYour Name wma_err("NULL psoc");
2078*5113495bSYour Name return -EINVAL;
2079*5113495bSYour Name }
2080*5113495bSYour Name
2081*5113495bSYour Name param_buf = (WMI_THERMAL_MGMT_EVENTID_param_tlvs *) event;
2082*5113495bSYour Name
2083*5113495bSYour Name /* Check if thermal mitigation is enabled */
2084*5113495bSYour Name if (!wma->thermal_mgmt_info.thermalMgmtEnabled) {
2085*5113495bSYour Name wma_err("Thermal mgmt is not enabled, ignoring event");
2086*5113495bSYour Name return -EINVAL;
2087*5113495bSYour Name }
2088*5113495bSYour Name
2089*5113495bSYour Name tm_event = param_buf->fixed_param;
2090*5113495bSYour Name wma_debug("Thermal mgmt event received with temperature %d",
2091*5113495bSYour Name tm_event->temperature_degreeC);
2092*5113495bSYour Name
2093*5113495bSYour Name /* Get the thermal mitigation level for the reported temperature */
2094*5113495bSYour Name thermal_level = wma_thermal_mgmt_get_level(handle,
2095*5113495bSYour Name tm_event->temperature_degreeC);
2096*5113495bSYour Name wma_debug("Thermal mgmt level %d", thermal_level);
2097*5113495bSYour Name
2098*5113495bSYour Name if (thermal_level == wma->thermal_mgmt_info.thermalCurrLevel) {
2099*5113495bSYour Name wma_debug("Current level %d is same as the set level, ignoring",
2100*5113495bSYour Name wma->thermal_mgmt_info.thermalCurrLevel);
2101*5113495bSYour Name return 0;
2102*5113495bSYour Name }
2103*5113495bSYour Name
2104*5113495bSYour Name wma->thermal_mgmt_info.thermalCurrLevel = thermal_level;
2105*5113495bSYour Name info.level = wma_thermal_level_to_host(thermal_level);
2106*5113495bSYour Name target_if_fwol_notify_thermal_throttle(psoc, &info);
2107*5113495bSYour Name
2108*5113495bSYour Name if (!wma->fw_therm_throt_support) {
2109*5113495bSYour Name /* Inform txrx */
2110*5113495bSYour Name cdp_throttle_set_level(cds_get_context(QDF_MODULE_ID_SOC),
2111*5113495bSYour Name WMI_PDEV_ID_SOC, thermal_level);
2112*5113495bSYour Name }
2113*5113495bSYour Name
2114*5113495bSYour Name /* Send SME SET_THERMAL_LEVEL_IND message */
2115*5113495bSYour Name wma_set_thermal_level_ind(thermal_level);
2116*5113495bSYour Name
2117*5113495bSYour Name if (wma->fw_therm_throt_support) {
2118*5113495bSYour Name /* Send duty cycle info to firmware for fw to throttle */
2119*5113495bSYour Name if (QDF_STATUS_SUCCESS !=
2120*5113495bSYour Name wma_update_thermal_mitigation_to_fw(wma, thermal_level))
2121*5113495bSYour Name return QDF_STATUS_E_FAILURE;
2122*5113495bSYour Name }
2123*5113495bSYour Name
2124*5113495bSYour Name /* Get the temperature thresholds to set in firmware */
2125*5113495bSYour Name thermal_params.minTemp =
2126*5113495bSYour Name wma->thermal_mgmt_info.thermalLevels[thermal_level].
2127*5113495bSYour Name minTempThreshold;
2128*5113495bSYour Name thermal_params.maxTemp =
2129*5113495bSYour Name wma->thermal_mgmt_info.thermalLevels[thermal_level].
2130*5113495bSYour Name maxTempThreshold;
2131*5113495bSYour Name thermal_params.thermalEnable =
2132*5113495bSYour Name wma->thermal_mgmt_info.thermalMgmtEnabled;
2133*5113495bSYour Name thermal_params.thermal_action = wma->thermal_mgmt_info.thermal_action;
2134*5113495bSYour Name
2135*5113495bSYour Name if (QDF_STATUS_SUCCESS != wma_set_thermal_mgmt(wma, thermal_params)) {
2136*5113495bSYour Name wma_err("Could not send thermal mgmt command to the firmware!");
2137*5113495bSYour Name return -EINVAL;
2138*5113495bSYour Name }
2139*5113495bSYour Name
2140*5113495bSYour Name return 0;
2141*5113495bSYour Name }
2142*5113495bSYour Name
2143*5113495bSYour Name /**
2144*5113495bSYour Name * wma_decap_to_8023() - Decapsulate to 802.3 format
2145*5113495bSYour Name * @msdu: skb buffer
2146*5113495bSYour Name * @info: decapsulate info
2147*5113495bSYour Name *
2148*5113495bSYour Name * Return: none
2149*5113495bSYour Name */
wma_decap_to_8023(qdf_nbuf_t msdu,struct wma_decap_info_t * info)2150*5113495bSYour Name static void wma_decap_to_8023(qdf_nbuf_t msdu, struct wma_decap_info_t *info)
2151*5113495bSYour Name {
2152*5113495bSYour Name struct llc_snap_hdr_t *llc_hdr;
2153*5113495bSYour Name uint16_t ether_type;
2154*5113495bSYour Name uint16_t l2_hdr_space;
2155*5113495bSYour Name struct ieee80211_qosframe_addr4 *wh;
2156*5113495bSYour Name uint8_t local_buf[ETHERNET_HDR_LEN];
2157*5113495bSYour Name uint8_t *buf;
2158*5113495bSYour Name struct ethernet_hdr_t *ethr_hdr;
2159*5113495bSYour Name
2160*5113495bSYour Name buf = (uint8_t *) qdf_nbuf_data(msdu);
2161*5113495bSYour Name llc_hdr = (struct llc_snap_hdr_t *)buf;
2162*5113495bSYour Name ether_type = (llc_hdr->ethertype[0] << 8) | llc_hdr->ethertype[1];
2163*5113495bSYour Name /* do llc remove if needed */
2164*5113495bSYour Name l2_hdr_space = 0;
2165*5113495bSYour Name if (IS_SNAP(llc_hdr)) {
2166*5113495bSYour Name if (IS_BTEP(llc_hdr)) {
2167*5113495bSYour Name /* remove llc */
2168*5113495bSYour Name l2_hdr_space += sizeof(struct llc_snap_hdr_t);
2169*5113495bSYour Name llc_hdr = NULL;
2170*5113495bSYour Name } else if (IS_RFC1042(llc_hdr)) {
2171*5113495bSYour Name if (!(ether_type == ETHERTYPE_AARP ||
2172*5113495bSYour Name ether_type == ETHERTYPE_IPX)) {
2173*5113495bSYour Name /* remove llc */
2174*5113495bSYour Name l2_hdr_space += sizeof(struct llc_snap_hdr_t);
2175*5113495bSYour Name llc_hdr = NULL;
2176*5113495bSYour Name }
2177*5113495bSYour Name }
2178*5113495bSYour Name }
2179*5113495bSYour Name if (l2_hdr_space > ETHERNET_HDR_LEN)
2180*5113495bSYour Name buf = qdf_nbuf_pull_head(msdu, l2_hdr_space - ETHERNET_HDR_LEN);
2181*5113495bSYour Name else if (l2_hdr_space < ETHERNET_HDR_LEN)
2182*5113495bSYour Name buf = qdf_nbuf_push_head(msdu, ETHERNET_HDR_LEN - l2_hdr_space);
2183*5113495bSYour Name
2184*5113495bSYour Name /* mpdu hdr should be present in info,re-create ethr_hdr based on
2185*5113495bSYour Name * mpdu hdr
2186*5113495bSYour Name */
2187*5113495bSYour Name wh = (struct ieee80211_qosframe_addr4 *)info->hdr;
2188*5113495bSYour Name ethr_hdr = (struct ethernet_hdr_t *)local_buf;
2189*5113495bSYour Name switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {
2190*5113495bSYour Name case IEEE80211_FC1_DIR_NODS:
2191*5113495bSYour Name qdf_mem_copy(ethr_hdr->dest_addr, wh->i_addr1,
2192*5113495bSYour Name QDF_MAC_ADDR_SIZE);
2193*5113495bSYour Name qdf_mem_copy(ethr_hdr->src_addr, wh->i_addr2,
2194*5113495bSYour Name QDF_MAC_ADDR_SIZE);
2195*5113495bSYour Name break;
2196*5113495bSYour Name case IEEE80211_FC1_DIR_TODS:
2197*5113495bSYour Name qdf_mem_copy(ethr_hdr->dest_addr, wh->i_addr3,
2198*5113495bSYour Name QDF_MAC_ADDR_SIZE);
2199*5113495bSYour Name qdf_mem_copy(ethr_hdr->src_addr, wh->i_addr2,
2200*5113495bSYour Name QDF_MAC_ADDR_SIZE);
2201*5113495bSYour Name break;
2202*5113495bSYour Name case IEEE80211_FC1_DIR_FROMDS:
2203*5113495bSYour Name qdf_mem_copy(ethr_hdr->dest_addr, wh->i_addr1,
2204*5113495bSYour Name QDF_MAC_ADDR_SIZE);
2205*5113495bSYour Name qdf_mem_copy(ethr_hdr->src_addr, wh->i_addr3,
2206*5113495bSYour Name QDF_MAC_ADDR_SIZE);
2207*5113495bSYour Name break;
2208*5113495bSYour Name case IEEE80211_FC1_DIR_DSTODS:
2209*5113495bSYour Name qdf_mem_copy(ethr_hdr->dest_addr, wh->i_addr3,
2210*5113495bSYour Name QDF_MAC_ADDR_SIZE);
2211*5113495bSYour Name qdf_mem_copy(ethr_hdr->src_addr, wh->i_addr4,
2212*5113495bSYour Name QDF_MAC_ADDR_SIZE);
2213*5113495bSYour Name break;
2214*5113495bSYour Name }
2215*5113495bSYour Name
2216*5113495bSYour Name if (!llc_hdr) {
2217*5113495bSYour Name ethr_hdr->ethertype[0] = (ether_type >> 8) & 0xff;
2218*5113495bSYour Name ethr_hdr->ethertype[1] = (ether_type) & 0xff;
2219*5113495bSYour Name } else {
2220*5113495bSYour Name uint32_t pktlen =
2221*5113495bSYour Name qdf_nbuf_len(msdu) - sizeof(ethr_hdr->ethertype);
2222*5113495bSYour Name ether_type = (uint16_t) pktlen;
2223*5113495bSYour Name ether_type = qdf_nbuf_len(msdu) - sizeof(struct ethernet_hdr_t);
2224*5113495bSYour Name ethr_hdr->ethertype[0] = (ether_type >> 8) & 0xff;
2225*5113495bSYour Name ethr_hdr->ethertype[1] = (ether_type) & 0xff;
2226*5113495bSYour Name }
2227*5113495bSYour Name qdf_mem_copy(buf, ethr_hdr, ETHERNET_HDR_LEN);
2228*5113495bSYour Name }
2229*5113495bSYour Name
2230*5113495bSYour Name /**
2231*5113495bSYour Name * wma_ieee80211_hdrsize() - get 802.11 header size
2232*5113495bSYour Name * @data: 80211 frame
2233*5113495bSYour Name *
2234*5113495bSYour Name * Return: size of header
2235*5113495bSYour Name */
wma_ieee80211_hdrsize(const void * data)2236*5113495bSYour Name static int32_t wma_ieee80211_hdrsize(const void *data)
2237*5113495bSYour Name {
2238*5113495bSYour Name const struct ieee80211_frame *wh = (const struct ieee80211_frame *)data;
2239*5113495bSYour Name int32_t size = sizeof(struct ieee80211_frame);
2240*5113495bSYour Name
2241*5113495bSYour Name if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS)
2242*5113495bSYour Name size += QDF_MAC_ADDR_SIZE;
2243*5113495bSYour Name if (IEEE80211_QOS_HAS_SEQ(wh))
2244*5113495bSYour Name size += sizeof(uint16_t);
2245*5113495bSYour Name return size;
2246*5113495bSYour Name }
2247*5113495bSYour Name
2248*5113495bSYour Name /**
2249*5113495bSYour Name * rate_pream: Mapping from data rates to preamble.
2250*5113495bSYour Name */
2251*5113495bSYour Name static uint32_t rate_pream[] = {WMI_RATE_PREAMBLE_CCK, WMI_RATE_PREAMBLE_CCK,
2252*5113495bSYour Name WMI_RATE_PREAMBLE_CCK, WMI_RATE_PREAMBLE_CCK,
2253*5113495bSYour Name WMI_RATE_PREAMBLE_OFDM, WMI_RATE_PREAMBLE_OFDM,
2254*5113495bSYour Name WMI_RATE_PREAMBLE_OFDM, WMI_RATE_PREAMBLE_OFDM,
2255*5113495bSYour Name WMI_RATE_PREAMBLE_OFDM, WMI_RATE_PREAMBLE_OFDM,
2256*5113495bSYour Name WMI_RATE_PREAMBLE_OFDM, WMI_RATE_PREAMBLE_OFDM};
2257*5113495bSYour Name
2258*5113495bSYour Name /**
2259*5113495bSYour Name * rate_mcs: Mapping from data rates to MCS (+4 for OFDM to keep the sequence).
2260*5113495bSYour Name */
2261*5113495bSYour Name static uint32_t rate_mcs[] = {WMI_MAX_CCK_TX_RATE_1M, WMI_MAX_CCK_TX_RATE_2M,
2262*5113495bSYour Name WMI_MAX_CCK_TX_RATE_5_5M, WMI_MAX_CCK_TX_RATE_11M,
2263*5113495bSYour Name WMI_MAX_OFDM_TX_RATE_6M + 4,
2264*5113495bSYour Name WMI_MAX_OFDM_TX_RATE_9M + 4,
2265*5113495bSYour Name WMI_MAX_OFDM_TX_RATE_12M + 4,
2266*5113495bSYour Name WMI_MAX_OFDM_TX_RATE_18M + 4,
2267*5113495bSYour Name WMI_MAX_OFDM_TX_RATE_24M + 4,
2268*5113495bSYour Name WMI_MAX_OFDM_TX_RATE_36M + 4,
2269*5113495bSYour Name WMI_MAX_OFDM_TX_RATE_48M + 4,
2270*5113495bSYour Name WMI_MAX_OFDM_TX_RATE_54M + 4};
2271*5113495bSYour Name
2272*5113495bSYour Name #define WMA_TX_SEND_MGMT_TYPE 0
2273*5113495bSYour Name #define WMA_TX_SEND_DATA_TYPE 1
2274*5113495bSYour Name
2275*5113495bSYour Name /**
2276*5113495bSYour Name * wma_update_tx_send_params() - Update tx_send_params TLV info
2277*5113495bSYour Name * @tx_param: Pointer to tx_send_params
2278*5113495bSYour Name * @rid: rate ID passed by PE
2279*5113495bSYour Name *
2280*5113495bSYour Name * Return: None
2281*5113495bSYour Name */
wma_update_tx_send_params(struct tx_send_params * tx_param,enum rateid rid)2282*5113495bSYour Name static void wma_update_tx_send_params(struct tx_send_params *tx_param,
2283*5113495bSYour Name enum rateid rid)
2284*5113495bSYour Name {
2285*5113495bSYour Name uint8_t preamble = 0, nss = 0, rix = 0;
2286*5113495bSYour Name
2287*5113495bSYour Name preamble = rate_pream[rid];
2288*5113495bSYour Name rix = rate_mcs[rid];
2289*5113495bSYour Name
2290*5113495bSYour Name tx_param->mcs_mask = (1 << rix);
2291*5113495bSYour Name tx_param->nss_mask = (1 << nss);
2292*5113495bSYour Name tx_param->preamble_type = (1 << preamble);
2293*5113495bSYour Name tx_param->frame_type = WMA_TX_SEND_MGMT_TYPE;
2294*5113495bSYour Name
2295*5113495bSYour Name wma_debug("rate_id: %d, mcs: %0x, nss: %0x, preamble: %0x",
2296*5113495bSYour Name rid, tx_param->mcs_mask, tx_param->nss_mask,
2297*5113495bSYour Name tx_param->preamble_type);
2298*5113495bSYour Name }
2299*5113495bSYour Name
wma_tx_packet(void * wma_context,void * tx_frame,uint16_t frmLen,eFrameType frmType,eFrameTxDir txDir,uint8_t tid,wma_tx_dwnld_comp_callback tx_frm_download_comp_cb,void * pData,wma_tx_ota_comp_callback tx_frm_ota_comp_cb,uint8_t tx_flag,uint8_t vdev_id,bool tdls_flag,uint16_t channel_freq,enum rateid rid,int8_t peer_rssi,uint16_t action)2300*5113495bSYour Name QDF_STATUS wma_tx_packet(void *wma_context, void *tx_frame, uint16_t frmLen,
2301*5113495bSYour Name eFrameType frmType, eFrameTxDir txDir, uint8_t tid,
2302*5113495bSYour Name wma_tx_dwnld_comp_callback tx_frm_download_comp_cb,
2303*5113495bSYour Name void *pData,
2304*5113495bSYour Name wma_tx_ota_comp_callback tx_frm_ota_comp_cb,
2305*5113495bSYour Name uint8_t tx_flag, uint8_t vdev_id, bool tdls_flag,
2306*5113495bSYour Name uint16_t channel_freq, enum rateid rid,
2307*5113495bSYour Name int8_t peer_rssi, uint16_t action)
2308*5113495bSYour Name {
2309*5113495bSYour Name tp_wma_handle wma_handle = (tp_wma_handle) (wma_context);
2310*5113495bSYour Name int32_t status;
2311*5113495bSYour Name QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
2312*5113495bSYour Name int32_t is_high_latency;
2313*5113495bSYour Name bool is_wmi_mgmt_tx = false;
2314*5113495bSYour Name enum frame_index tx_frm_index = GENERIC_NODOWNLD_NOACK_COMP_INDEX;
2315*5113495bSYour Name tpSirMacFrameCtl pFc = (tpSirMacFrameCtl) (qdf_nbuf_data(tx_frame));
2316*5113495bSYour Name uint8_t use_6mbps = 0;
2317*5113495bSYour Name uint8_t downld_comp_required = 0;
2318*5113495bSYour Name uint16_t chanfreq;
2319*5113495bSYour Name uint8_t *pFrame = NULL;
2320*5113495bSYour Name void *pPacket = NULL;
2321*5113495bSYour Name uint16_t newFrmLen = 0;
2322*5113495bSYour Name struct wma_txrx_node *iface;
2323*5113495bSYour Name struct mac_context *mac;
2324*5113495bSYour Name tpSirMacMgmtHdr mHdr;
2325*5113495bSYour Name struct wmi_mgmt_params mgmt_param = {0};
2326*5113495bSYour Name struct cdp_cfg *ctrl_pdev;
2327*5113495bSYour Name void *soc = cds_get_context(QDF_MODULE_ID_SOC);
2328*5113495bSYour Name struct ieee80211_frame *wh;
2329*5113495bSYour Name struct wlan_objmgr_peer *peer = NULL;
2330*5113495bSYour Name struct wlan_objmgr_psoc *psoc;
2331*5113495bSYour Name struct wlan_objmgr_vdev *vdev = NULL;
2332*5113495bSYour Name void *mac_addr;
2333*5113495bSYour Name uint8_t *mld_addr = NULL;
2334*5113495bSYour Name bool is_5g = false;
2335*5113495bSYour Name uint8_t pdev_id;
2336*5113495bSYour Name bool mlo_link_agnostic;
2337*5113495bSYour Name
2338*5113495bSYour Name if (wma_validate_handle(wma_handle)) {
2339*5113495bSYour Name cds_packet_free((void *)tx_frame);
2340*5113495bSYour Name return QDF_STATUS_E_FAILURE;
2341*5113495bSYour Name }
2342*5113495bSYour Name
2343*5113495bSYour Name if (vdev_id >= wma_handle->max_bssid) {
2344*5113495bSYour Name wma_err("tx packet with invalid vdev_id :%d", vdev_id);
2345*5113495bSYour Name return QDF_STATUS_E_FAILURE;
2346*5113495bSYour Name }
2347*5113495bSYour Name
2348*5113495bSYour Name iface = &wma_handle->interfaces[vdev_id];
2349*5113495bSYour Name
2350*5113495bSYour Name if (!soc) {
2351*5113495bSYour Name cds_packet_free((void *)tx_frame);
2352*5113495bSYour Name return QDF_STATUS_E_FAILURE;
2353*5113495bSYour Name }
2354*5113495bSYour Name
2355*5113495bSYour Name cdp_hl_tdls_flag_reset(soc, vdev_id, false);
2356*5113495bSYour Name
2357*5113495bSYour Name if (frmType >= TXRX_FRM_MAX) {
2358*5113495bSYour Name wma_err("Invalid Frame Type Fail to send Frame");
2359*5113495bSYour Name cds_packet_free((void *)tx_frame);
2360*5113495bSYour Name return QDF_STATUS_E_FAILURE;
2361*5113495bSYour Name }
2362*5113495bSYour Name
2363*5113495bSYour Name mac = cds_get_context(QDF_MODULE_ID_PE);
2364*5113495bSYour Name if (!mac) {
2365*5113495bSYour Name cds_packet_free((void *)tx_frame);
2366*5113495bSYour Name return QDF_STATUS_E_FAILURE;
2367*5113495bSYour Name }
2368*5113495bSYour Name /*
2369*5113495bSYour Name * Currently only support to
2370*5113495bSYour Name * send 80211 Mgmt and 80211 Data are added.
2371*5113495bSYour Name */
2372*5113495bSYour Name if (!((frmType == TXRX_FRM_802_11_MGMT) ||
2373*5113495bSYour Name (frmType == TXRX_FRM_802_11_DATA))) {
2374*5113495bSYour Name wma_err("No Support to send other frames except 802.11 Mgmt/Data");
2375*5113495bSYour Name cds_packet_free((void *)tx_frame);
2376*5113495bSYour Name return QDF_STATUS_E_FAILURE;
2377*5113495bSYour Name }
2378*5113495bSYour Name
2379*5113495bSYour Name if (((iface->rmfEnabled || tx_flag & HAL_USE_PMF)) &&
2380*5113495bSYour Name (frmType == TXRX_FRM_802_11_MGMT) &&
2381*5113495bSYour Name (pFc->subType == SIR_MAC_MGMT_DISASSOC ||
2382*5113495bSYour Name pFc->subType == SIR_MAC_MGMT_DEAUTH ||
2383*5113495bSYour Name pFc->subType == SIR_MAC_MGMT_ACTION)) {
2384*5113495bSYour Name struct ieee80211_frame *wh =
2385*5113495bSYour Name (struct ieee80211_frame *)qdf_nbuf_data(tx_frame);
2386*5113495bSYour Name if (!QDF_IS_ADDR_BROADCAST(wh->i_addr1) &&
2387*5113495bSYour Name !IEEE80211_IS_MULTICAST(wh->i_addr1)) {
2388*5113495bSYour Name if (pFc->wep) {
2389*5113495bSYour Name uint8_t mic_len, hdr_len, pdev_id;
2390*5113495bSYour Name
2391*5113495bSYour Name /* Allocate extra bytes for privacy header and
2392*5113495bSYour Name * trailer
2393*5113495bSYour Name */
2394*5113495bSYour Name if (iface->type == WMI_VDEV_TYPE_NDI &&
2395*5113495bSYour Name (tx_flag & HAL_USE_PMF)) {
2396*5113495bSYour Name hdr_len = IEEE80211_CCMP_HEADERLEN;
2397*5113495bSYour Name mic_len = IEEE80211_CCMP_MICLEN;
2398*5113495bSYour Name } else {
2399*5113495bSYour Name pdev_id = wlan_objmgr_pdev_get_pdev_id(
2400*5113495bSYour Name wma_handle->pdev);
2401*5113495bSYour Name qdf_status = mlme_get_peer_mic_len(
2402*5113495bSYour Name wma_handle->psoc,
2403*5113495bSYour Name pdev_id, wh->i_addr1,
2404*5113495bSYour Name &mic_len, &hdr_len);
2405*5113495bSYour Name
2406*5113495bSYour Name if (QDF_IS_STATUS_ERROR(qdf_status)) {
2407*5113495bSYour Name cds_packet_free(
2408*5113495bSYour Name (void *)tx_frame);
2409*5113495bSYour Name goto error;
2410*5113495bSYour Name }
2411*5113495bSYour Name }
2412*5113495bSYour Name
2413*5113495bSYour Name newFrmLen = frmLen + hdr_len + mic_len;
2414*5113495bSYour Name qdf_status =
2415*5113495bSYour Name cds_packet_alloc((uint16_t) newFrmLen,
2416*5113495bSYour Name (void **)&pFrame,
2417*5113495bSYour Name (void **)&pPacket);
2418*5113495bSYour Name
2419*5113495bSYour Name if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
2420*5113495bSYour Name wma_alert("Failed to allocate %d bytes for RMF status code (%x)",
2421*5113495bSYour Name newFrmLen,
2422*5113495bSYour Name qdf_status);
2423*5113495bSYour Name /* Free the original packet memory */
2424*5113495bSYour Name cds_packet_free((void *)tx_frame);
2425*5113495bSYour Name goto error;
2426*5113495bSYour Name }
2427*5113495bSYour Name
2428*5113495bSYour Name /*
2429*5113495bSYour Name * Initialize the frame with 0's and only fill
2430*5113495bSYour Name * MAC header and data, Keep the CCMP header and
2431*5113495bSYour Name * trailer as 0's, firmware shall fill this
2432*5113495bSYour Name */
2433*5113495bSYour Name qdf_mem_zero(pFrame, newFrmLen);
2434*5113495bSYour Name qdf_mem_copy(pFrame, wh, sizeof(*wh));
2435*5113495bSYour Name qdf_mem_copy(pFrame + sizeof(*wh) +
2436*5113495bSYour Name hdr_len,
2437*5113495bSYour Name pData + sizeof(*wh),
2438*5113495bSYour Name frmLen - sizeof(*wh));
2439*5113495bSYour Name
2440*5113495bSYour Name cds_packet_free((void *)tx_frame);
2441*5113495bSYour Name tx_frame = pPacket;
2442*5113495bSYour Name pData = pFrame;
2443*5113495bSYour Name frmLen = newFrmLen;
2444*5113495bSYour Name pFc = (tpSirMacFrameCtl)
2445*5113495bSYour Name (qdf_nbuf_data(tx_frame));
2446*5113495bSYour Name }
2447*5113495bSYour Name } else {
2448*5113495bSYour Name uint16_t mmie_size;
2449*5113495bSYour Name int32_t mgmtcipherset;
2450*5113495bSYour Name
2451*5113495bSYour Name mgmtcipherset = wlan_crypto_get_param(iface->vdev,
2452*5113495bSYour Name WLAN_CRYPTO_PARAM_MGMT_CIPHER);
2453*5113495bSYour Name if (mgmtcipherset <= 0) {
2454*5113495bSYour Name wma_err("Invalid key cipher %d", mgmtcipherset);
2455*5113495bSYour Name cds_packet_free((void *)tx_frame);
2456*5113495bSYour Name return -EINVAL;
2457*5113495bSYour Name }
2458*5113495bSYour Name
2459*5113495bSYour Name if (mgmtcipherset & (1 << WLAN_CRYPTO_CIPHER_AES_CMAC))
2460*5113495bSYour Name mmie_size = cds_get_mmie_size();
2461*5113495bSYour Name else
2462*5113495bSYour Name mmie_size = cds_get_gmac_mmie_size();
2463*5113495bSYour Name
2464*5113495bSYour Name /* Allocate extra bytes for MMIE */
2465*5113495bSYour Name newFrmLen = frmLen + mmie_size;
2466*5113495bSYour Name qdf_status = cds_packet_alloc((uint16_t) newFrmLen,
2467*5113495bSYour Name (void **)&pFrame,
2468*5113495bSYour Name (void **)&pPacket);
2469*5113495bSYour Name
2470*5113495bSYour Name if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
2471*5113495bSYour Name wma_alert("Failed to allocate %d bytes for RMF status code (%x)",
2472*5113495bSYour Name newFrmLen,
2473*5113495bSYour Name qdf_status);
2474*5113495bSYour Name /* Free the original packet memory */
2475*5113495bSYour Name cds_packet_free((void *)tx_frame);
2476*5113495bSYour Name goto error;
2477*5113495bSYour Name }
2478*5113495bSYour Name /*
2479*5113495bSYour Name * Initialize the frame with 0's and only fill
2480*5113495bSYour Name * MAC header and data. MMIE field will be
2481*5113495bSYour Name * filled by wlan_crypto_add_mmie API
2482*5113495bSYour Name */
2483*5113495bSYour Name qdf_mem_zero(pFrame, newFrmLen);
2484*5113495bSYour Name qdf_mem_copy(pFrame, wh, sizeof(*wh));
2485*5113495bSYour Name qdf_mem_copy(pFrame + sizeof(*wh),
2486*5113495bSYour Name pData + sizeof(*wh), frmLen - sizeof(*wh));
2487*5113495bSYour Name
2488*5113495bSYour Name /* The API expect length without the mmie size */
2489*5113495bSYour Name if (!wlan_crypto_add_mmie(iface->vdev, pFrame,
2490*5113495bSYour Name frmLen)) {
2491*5113495bSYour Name wma_alert("Failed to attach MMIE");
2492*5113495bSYour Name /* Free the original packet memory */
2493*5113495bSYour Name cds_packet_free((void *)tx_frame);
2494*5113495bSYour Name cds_packet_free((void *)pPacket);
2495*5113495bSYour Name goto error;
2496*5113495bSYour Name }
2497*5113495bSYour Name cds_packet_free((void *)tx_frame);
2498*5113495bSYour Name tx_frame = pPacket;
2499*5113495bSYour Name pData = pFrame;
2500*5113495bSYour Name frmLen = newFrmLen;
2501*5113495bSYour Name pFc = (tpSirMacFrameCtl) (qdf_nbuf_data(tx_frame));
2502*5113495bSYour Name }
2503*5113495bSYour Name /*
2504*5113495bSYour Name * Some target which support sending mgmt frame based on htt
2505*5113495bSYour Name * would DMA write this PMF tx frame buffer, it may cause smmu
2506*5113495bSYour Name * check permission fault, set a flag to do bi-direction DMA
2507*5113495bSYour Name * map, normal tx unmap is enough for this case.
2508*5113495bSYour Name */
2509*5113495bSYour Name QDF_NBUF_CB_TX_DMA_BI_MAP((qdf_nbuf_t)tx_frame) = 1;
2510*5113495bSYour Name }
2511*5113495bSYour Name mHdr = (tpSirMacMgmtHdr)qdf_nbuf_data(tx_frame);
2512*5113495bSYour Name if ((frmType == TXRX_FRM_802_11_MGMT) &&
2513*5113495bSYour Name (pFc->subType == SIR_MAC_MGMT_PROBE_RSP)) {
2514*5113495bSYour Name uint64_t adjusted_tsf_le;
2515*5113495bSYour Name struct ieee80211_frame *wh =
2516*5113495bSYour Name (struct ieee80211_frame *)qdf_nbuf_data(tx_frame);
2517*5113495bSYour Name
2518*5113495bSYour Name /* Make the TSF offset negative to match TSF in beacons */
2519*5113495bSYour Name adjusted_tsf_le = cpu_to_le64(0ULL -
2520*5113495bSYour Name wma_handle->interfaces[vdev_id].
2521*5113495bSYour Name tsfadjust);
2522*5113495bSYour Name A_MEMCPY(&wh[1], &adjusted_tsf_le, sizeof(adjusted_tsf_le));
2523*5113495bSYour Name }
2524*5113495bSYour Name if (frmType == TXRX_FRM_802_11_DATA) {
2525*5113495bSYour Name qdf_nbuf_t ret;
2526*5113495bSYour Name qdf_nbuf_t skb = (qdf_nbuf_t) tx_frame;
2527*5113495bSYour Name
2528*5113495bSYour Name struct wma_decap_info_t decap_info;
2529*5113495bSYour Name struct ieee80211_frame *wh =
2530*5113495bSYour Name (struct ieee80211_frame *)qdf_nbuf_data(skb);
2531*5113495bSYour Name unsigned long curr_timestamp = qdf_mc_timer_get_system_ticks();
2532*5113495bSYour Name
2533*5113495bSYour Name /*
2534*5113495bSYour Name * 1) TxRx Module expects data input to be 802.3 format
2535*5113495bSYour Name * So Decapsulation has to be done.
2536*5113495bSYour Name * 2) Only one Outstanding Data pending for Ack is allowed
2537*5113495bSYour Name */
2538*5113495bSYour Name if (tx_frm_ota_comp_cb) {
2539*5113495bSYour Name if (wma_handle->umac_data_ota_ack_cb) {
2540*5113495bSYour Name /*
2541*5113495bSYour Name * If last data frame was sent more than 2 secs
2542*5113495bSYour Name * ago and still we didn't receive ack/nack from
2543*5113495bSYour Name * fw then allow Tx of this data frame
2544*5113495bSYour Name */
2545*5113495bSYour Name if (curr_timestamp >=
2546*5113495bSYour Name wma_handle->last_umac_data_ota_timestamp +
2547*5113495bSYour Name 200) {
2548*5113495bSYour Name wma_err("No Tx Ack for last data frame for more than 2 secs, allow Tx of current data frame");
2549*5113495bSYour Name } else {
2550*5113495bSYour Name wma_err("Already one Data pending for Ack, reject Tx of data frame");
2551*5113495bSYour Name cds_packet_free((void *)tx_frame);
2552*5113495bSYour Name return QDF_STATUS_E_FAILURE;
2553*5113495bSYour Name }
2554*5113495bSYour Name }
2555*5113495bSYour Name } else {
2556*5113495bSYour Name /*
2557*5113495bSYour Name * Data Frames are sent through TxRx Non Standard Data
2558*5113495bSYour Name * path so Ack Complete Cb is must
2559*5113495bSYour Name */
2560*5113495bSYour Name wma_err("No Ack Complete Cb. Don't Allow");
2561*5113495bSYour Name cds_packet_free((void *)tx_frame);
2562*5113495bSYour Name return QDF_STATUS_E_FAILURE;
2563*5113495bSYour Name }
2564*5113495bSYour Name
2565*5113495bSYour Name /* Take out 802.11 header from skb */
2566*5113495bSYour Name decap_info.hdr_len = wma_ieee80211_hdrsize(wh);
2567*5113495bSYour Name qdf_mem_copy(decap_info.hdr, wh, decap_info.hdr_len);
2568*5113495bSYour Name qdf_nbuf_pull_head(skb, decap_info.hdr_len);
2569*5113495bSYour Name
2570*5113495bSYour Name /* Decapsulate to 802.3 format */
2571*5113495bSYour Name wma_decap_to_8023(skb, &decap_info);
2572*5113495bSYour Name
2573*5113495bSYour Name /* Zero out skb's context buffer for the driver to use */
2574*5113495bSYour Name qdf_mem_zero(skb->cb, sizeof(skb->cb));
2575*5113495bSYour Name
2576*5113495bSYour Name /* Terminate the (single-element) list of tx frames */
2577*5113495bSYour Name skb->next = NULL;
2578*5113495bSYour Name
2579*5113495bSYour Name /* Store the Ack Complete Cb */
2580*5113495bSYour Name wma_handle->umac_data_ota_ack_cb = tx_frm_ota_comp_cb;
2581*5113495bSYour Name
2582*5113495bSYour Name /* Store the timestamp and nbuf for this data Tx */
2583*5113495bSYour Name wma_handle->last_umac_data_ota_timestamp = curr_timestamp;
2584*5113495bSYour Name wma_handle->last_umac_data_nbuf = skb;
2585*5113495bSYour Name
2586*5113495bSYour Name /* Send the Data frame to TxRx in Non Standard Path */
2587*5113495bSYour Name cdp_hl_tdls_flag_reset(soc,
2588*5113495bSYour Name vdev_id, tdls_flag);
2589*5113495bSYour Name
2590*5113495bSYour Name ret = cdp_tx_non_std(soc,
2591*5113495bSYour Name vdev_id,
2592*5113495bSYour Name OL_TX_SPEC_NO_FREE, skb);
2593*5113495bSYour Name
2594*5113495bSYour Name cdp_hl_tdls_flag_reset(soc,
2595*5113495bSYour Name vdev_id, false);
2596*5113495bSYour Name
2597*5113495bSYour Name if (ret) {
2598*5113495bSYour Name wma_err("TxRx Rejected. Fail to do Tx");
2599*5113495bSYour Name /* Call Download Cb so that umac can free the buffer */
2600*5113495bSYour Name if (tx_frm_download_comp_cb)
2601*5113495bSYour Name tx_frm_download_comp_cb(wma_handle->mac_context,
2602*5113495bSYour Name tx_frame,
2603*5113495bSYour Name WMA_TX_FRAME_BUFFER_FREE);
2604*5113495bSYour Name wma_handle->umac_data_ota_ack_cb = NULL;
2605*5113495bSYour Name wma_handle->last_umac_data_nbuf = NULL;
2606*5113495bSYour Name return QDF_STATUS_E_FAILURE;
2607*5113495bSYour Name }
2608*5113495bSYour Name
2609*5113495bSYour Name /* Call Download Callback if passed */
2610*5113495bSYour Name if (tx_frm_download_comp_cb)
2611*5113495bSYour Name tx_frm_download_comp_cb(wma_handle->mac_context,
2612*5113495bSYour Name tx_frame,
2613*5113495bSYour Name WMA_TX_FRAME_BUFFER_NO_FREE);
2614*5113495bSYour Name
2615*5113495bSYour Name return QDF_STATUS_SUCCESS;
2616*5113495bSYour Name }
2617*5113495bSYour Name
2618*5113495bSYour Name ctrl_pdev = cdp_get_ctrl_pdev_from_vdev(soc, vdev_id);
2619*5113495bSYour Name if (!ctrl_pdev) {
2620*5113495bSYour Name wma_err("ol_pdev_handle is NULL");
2621*5113495bSYour Name cds_packet_free((void *)tx_frame);
2622*5113495bSYour Name return QDF_STATUS_E_FAILURE;
2623*5113495bSYour Name }
2624*5113495bSYour Name is_high_latency = cdp_cfg_is_high_latency(soc, ctrl_pdev);
2625*5113495bSYour Name is_wmi_mgmt_tx = wmi_service_enabled(wma_handle->wmi_handle,
2626*5113495bSYour Name wmi_service_mgmt_tx_wmi);
2627*5113495bSYour Name
2628*5113495bSYour Name downld_comp_required = tx_frm_download_comp_cb && is_high_latency &&
2629*5113495bSYour Name (!is_wmi_mgmt_tx) && tx_frm_ota_comp_cb;
2630*5113495bSYour Name
2631*5113495bSYour Name /* Fill the frame index to send */
2632*5113495bSYour Name if (pFc->type == SIR_MAC_MGMT_FRAME) {
2633*5113495bSYour Name if (tx_frm_ota_comp_cb) {
2634*5113495bSYour Name if (downld_comp_required)
2635*5113495bSYour Name tx_frm_index =
2636*5113495bSYour Name GENERIC_DOWNLD_COMP_ACK_COMP_INDEX;
2637*5113495bSYour Name else
2638*5113495bSYour Name tx_frm_index = GENERIC_NODOWLOAD_ACK_COMP_INDEX;
2639*5113495bSYour Name
2640*5113495bSYour Name } else {
2641*5113495bSYour Name tx_frm_index =
2642*5113495bSYour Name GENERIC_NODOWNLD_NOACK_COMP_INDEX;
2643*5113495bSYour Name }
2644*5113495bSYour Name
2645*5113495bSYour Name }
2646*5113495bSYour Name
2647*5113495bSYour Name /*
2648*5113495bSYour Name * If Download Complete is required
2649*5113495bSYour Name * Wait for download complete
2650*5113495bSYour Name */
2651*5113495bSYour Name if (downld_comp_required) {
2652*5113495bSYour Name /* Store Tx Comp Cb */
2653*5113495bSYour Name wma_handle->tx_frm_download_comp_cb = tx_frm_download_comp_cb;
2654*5113495bSYour Name
2655*5113495bSYour Name /* Reset the Tx Frame Complete Event */
2656*5113495bSYour Name qdf_status = qdf_event_reset(
2657*5113495bSYour Name &wma_handle->tx_frm_download_comp_event);
2658*5113495bSYour Name
2659*5113495bSYour Name if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
2660*5113495bSYour Name wma_alert("Event Reset failed tx comp event %x",
2661*5113495bSYour Name qdf_status);
2662*5113495bSYour Name cds_packet_free((void *)tx_frame);
2663*5113495bSYour Name goto error;
2664*5113495bSYour Name }
2665*5113495bSYour Name }
2666*5113495bSYour Name
2667*5113495bSYour Name /* If the frame has to be sent at BD Rate2 inform TxRx */
2668*5113495bSYour Name if (tx_flag & HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME)
2669*5113495bSYour Name use_6mbps = 1;
2670*5113495bSYour Name
2671*5113495bSYour Name if (pFc->subType == SIR_MAC_MGMT_PROBE_RSP) {
2672*5113495bSYour Name if (wma_is_vdev_in_ap_mode(wma_handle, vdev_id) &&
2673*5113495bSYour Name wma_handle->interfaces[vdev_id].ch_freq)
2674*5113495bSYour Name chanfreq = wma_handle->interfaces[vdev_id].ch_freq;
2675*5113495bSYour Name else
2676*5113495bSYour Name chanfreq = channel_freq;
2677*5113495bSYour Name wma_debug("Probe response frame on channel %d vdev:%d",
2678*5113495bSYour Name chanfreq, vdev_id);
2679*5113495bSYour Name if (wma_is_vdev_in_ap_mode(wma_handle, vdev_id) && !chanfreq)
2680*5113495bSYour Name wma_err("AP oper chan is zero");
2681*5113495bSYour Name } else if (pFc->subType == SIR_MAC_MGMT_ACTION ||
2682*5113495bSYour Name pFc->subType == SIR_MAC_MGMT_AUTH) {
2683*5113495bSYour Name chanfreq = channel_freq;
2684*5113495bSYour Name } else {
2685*5113495bSYour Name chanfreq = 0;
2686*5113495bSYour Name }
2687*5113495bSYour Name
2688*5113495bSYour Name if (pFc->type == SIR_MAC_MGMT_FRAME) {
2689*5113495bSYour Name if (((mac->mlme_cfg->gen.debug_packet_log &
2690*5113495bSYour Name DEBUG_PKTLOG_TYPE_MGMT) &&
2691*5113495bSYour Name (pFc->subType != SIR_MAC_MGMT_PROBE_REQ) &&
2692*5113495bSYour Name (pFc->subType != SIR_MAC_MGMT_PROBE_RSP) &&
2693*5113495bSYour Name (pFc->subType != SIR_MAC_MGMT_ACTION)) ||
2694*5113495bSYour Name ((mac->mlme_cfg->gen.debug_packet_log &
2695*5113495bSYour Name DEBUG_PKTLOG_TYPE_ACTION) &&
2696*5113495bSYour Name (pFc->subType == SIR_MAC_MGMT_ACTION)))
2697*5113495bSYour Name mgmt_txrx_frame_hex_dump(pData, frmLen, true);
2698*5113495bSYour Name }
2699*5113495bSYour Name if (wlan_reg_is_5ghz_ch_freq(wma_handle->interfaces[vdev_id].ch_freq))
2700*5113495bSYour Name is_5g = true;
2701*5113495bSYour Name
2702*5113495bSYour Name wh = (struct ieee80211_frame *)(qdf_nbuf_data(tx_frame));
2703*5113495bSYour Name
2704*5113495bSYour Name mlo_link_agnostic =
2705*5113495bSYour Name wlan_get_mlo_link_agnostic_flag(iface->vdev, wh->i_addr1);
2706*5113495bSYour Name
2707*5113495bSYour Name mgmt_param.tx_frame = tx_frame;
2708*5113495bSYour Name mgmt_param.frm_len = frmLen;
2709*5113495bSYour Name mgmt_param.vdev_id = vdev_id;
2710*5113495bSYour Name mgmt_param.pdata = pData;
2711*5113495bSYour Name mgmt_param.chanfreq = chanfreq;
2712*5113495bSYour Name mgmt_param.qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
2713*5113495bSYour Name mgmt_param.use_6mbps = use_6mbps;
2714*5113495bSYour Name mgmt_param.tx_type = tx_frm_index;
2715*5113495bSYour Name mgmt_param.peer_rssi = peer_rssi;
2716*5113495bSYour Name if (wlan_vdev_mlme_get_opmode(iface->vdev) == QDF_STA_MODE &&
2717*5113495bSYour Name wlan_vdev_mlme_is_mlo_vdev(iface->vdev) &&
2718*5113495bSYour Name (wlan_vdev_mlme_is_active(iface->vdev) == QDF_STATUS_SUCCESS) &&
2719*5113495bSYour Name frmType == TXRX_FRM_802_11_MGMT &&
2720*5113495bSYour Name pFc->subType != SIR_MAC_MGMT_PROBE_REQ &&
2721*5113495bSYour Name pFc->subType != SIR_MAC_MGMT_AUTH &&
2722*5113495bSYour Name action != (ACTION_CATEGORY_PUBLIC << 8 | TDLS_DISCOVERY_RESPONSE) &&
2723*5113495bSYour Name action != (ACTION_CATEGORY_BACK << 8 | ADDBA_RESPONSE) &&
2724*5113495bSYour Name mlo_link_agnostic)
2725*5113495bSYour Name mgmt_param.mlo_link_agnostic = true;
2726*5113495bSYour Name
2727*5113495bSYour Name if (tx_flag & HAL_USE_INCORRECT_KEY_PMF)
2728*5113495bSYour Name mgmt_param.tx_flags |= MGMT_TX_USE_INCORRECT_KEY;
2729*5113495bSYour Name
2730*5113495bSYour Name /*
2731*5113495bSYour Name * Update the tx_params TLV only for rates
2732*5113495bSYour Name * other than 1Mbps and 6 Mbps
2733*5113495bSYour Name */
2734*5113495bSYour Name if (rid < RATEID_DEFAULT &&
2735*5113495bSYour Name (rid != RATEID_1MBPS && !(rid == RATEID_6MBPS && is_5g))) {
2736*5113495bSYour Name wma_debug("using rate id: %d for Tx", rid);
2737*5113495bSYour Name mgmt_param.tx_params_valid = true;
2738*5113495bSYour Name wma_update_tx_send_params(&mgmt_param.tx_param, rid);
2739*5113495bSYour Name }
2740*5113495bSYour Name
2741*5113495bSYour Name psoc = wma_handle->psoc;
2742*5113495bSYour Name if (!psoc) {
2743*5113495bSYour Name wma_err("psoc ctx is NULL");
2744*5113495bSYour Name cds_packet_free((void *)tx_frame);
2745*5113495bSYour Name goto error;
2746*5113495bSYour Name }
2747*5113495bSYour Name
2748*5113495bSYour Name if (!wma_handle->pdev) {
2749*5113495bSYour Name wma_err("pdev ctx is NULL");
2750*5113495bSYour Name cds_packet_free((void *)tx_frame);
2751*5113495bSYour Name goto error;
2752*5113495bSYour Name }
2753*5113495bSYour Name
2754*5113495bSYour Name pdev_id = wlan_objmgr_pdev_get_pdev_id(wma_handle->pdev);
2755*5113495bSYour Name mac_addr = wh->i_addr1;
2756*5113495bSYour Name peer = wlan_objmgr_get_peer(psoc, pdev_id, mac_addr, WLAN_MGMT_NB_ID);
2757*5113495bSYour Name if (!peer) {
2758*5113495bSYour Name mac_addr = wh->i_addr2;
2759*5113495bSYour Name peer = wlan_objmgr_get_peer(psoc, pdev_id, mac_addr,
2760*5113495bSYour Name WLAN_MGMT_NB_ID);
2761*5113495bSYour Name if (!peer) {
2762*5113495bSYour Name vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
2763*5113495bSYour Name vdev_id,
2764*5113495bSYour Name WLAN_MGMT_NB_ID);
2765*5113495bSYour Name if (!vdev) {
2766*5113495bSYour Name wma_err("vdev is null");
2767*5113495bSYour Name cds_packet_free((void *)tx_frame);
2768*5113495bSYour Name goto error;
2769*5113495bSYour Name }
2770*5113495bSYour Name mld_addr = wlan_vdev_mlme_get_mldaddr(vdev);
2771*5113495bSYour Name wlan_objmgr_vdev_release_ref(vdev, WLAN_MGMT_NB_ID);
2772*5113495bSYour Name if (!mld_addr) {
2773*5113495bSYour Name wma_err("mld addr is null");
2774*5113495bSYour Name cds_packet_free((void *)tx_frame);
2775*5113495bSYour Name goto error;
2776*5113495bSYour Name }
2777*5113495bSYour Name wma_debug("mld mac addr " QDF_MAC_ADDR_FMT,
2778*5113495bSYour Name QDF_MAC_ADDR_REF(mld_addr));
2779*5113495bSYour Name peer = wlan_objmgr_get_peer(psoc, pdev_id,
2780*5113495bSYour Name mld_addr,
2781*5113495bSYour Name WLAN_MGMT_NB_ID);
2782*5113495bSYour Name if (!peer) {
2783*5113495bSYour Name wma_err("peer is null");
2784*5113495bSYour Name cds_packet_free((void *)tx_frame);
2785*5113495bSYour Name goto error;
2786*5113495bSYour Name }
2787*5113495bSYour Name }
2788*5113495bSYour Name }
2789*5113495bSYour Name
2790*5113495bSYour Name if (ucfg_pkt_capture_get_pktcap_mode(psoc) &
2791*5113495bSYour Name PKT_CAPTURE_MODE_MGMT_ONLY) {
2792*5113495bSYour Name ucfg_pkt_capture_mgmt_tx(wma_handle->pdev,
2793*5113495bSYour Name tx_frame,
2794*5113495bSYour Name wma_handle->interfaces[vdev_id].ch_freq,
2795*5113495bSYour Name mgmt_param.tx_param.preamble_type);
2796*5113495bSYour Name }
2797*5113495bSYour Name
2798*5113495bSYour Name status = wlan_mgmt_txrx_mgmt_frame_tx(peer, wma_handle->mac_context,
2799*5113495bSYour Name (qdf_nbuf_t)tx_frame, NULL,
2800*5113495bSYour Name tx_frm_ota_comp_cb,
2801*5113495bSYour Name WLAN_UMAC_COMP_MLME,
2802*5113495bSYour Name &mgmt_param);
2803*5113495bSYour Name
2804*5113495bSYour Name wlan_objmgr_peer_release_ref(peer, WLAN_MGMT_NB_ID);
2805*5113495bSYour Name if (status != QDF_STATUS_SUCCESS) {
2806*5113495bSYour Name wma_err_rl("mgmt tx failed");
2807*5113495bSYour Name qdf_nbuf_free((qdf_nbuf_t)tx_frame);
2808*5113495bSYour Name goto error;
2809*5113495bSYour Name }
2810*5113495bSYour Name
2811*5113495bSYour Name /*
2812*5113495bSYour Name * Failed to send Tx Mgmt Frame
2813*5113495bSYour Name */
2814*5113495bSYour Name if (status) {
2815*5113495bSYour Name /* Call Download Cb so that umac can free the buffer */
2816*5113495bSYour Name uint32_t rem;
2817*5113495bSYour Name
2818*5113495bSYour Name if (tx_frm_download_comp_cb)
2819*5113495bSYour Name tx_frm_download_comp_cb(wma_handle->mac_context,
2820*5113495bSYour Name tx_frame,
2821*5113495bSYour Name WMA_TX_FRAME_BUFFER_FREE);
2822*5113495bSYour Name rem = qdf_do_div_rem(wma_handle->tx_fail_cnt,
2823*5113495bSYour Name MAX_PRINT_FAILURE_CNT);
2824*5113495bSYour Name if (!rem)
2825*5113495bSYour Name wma_err("Failed to send Mgmt Frame");
2826*5113495bSYour Name else
2827*5113495bSYour Name wma_debug("Failed to send Mgmt Frame");
2828*5113495bSYour Name wma_handle->tx_fail_cnt++;
2829*5113495bSYour Name goto error;
2830*5113495bSYour Name }
2831*5113495bSYour Name
2832*5113495bSYour Name if (!tx_frm_download_comp_cb)
2833*5113495bSYour Name return QDF_STATUS_SUCCESS;
2834*5113495bSYour Name
2835*5113495bSYour Name /*
2836*5113495bSYour Name * Wait for Download Complete
2837*5113495bSYour Name * if required
2838*5113495bSYour Name */
2839*5113495bSYour Name if (downld_comp_required) {
2840*5113495bSYour Name /*
2841*5113495bSYour Name * Wait for Download Complete
2842*5113495bSYour Name * @ Integrated : Dxe Complete
2843*5113495bSYour Name * @ Discrete : Target Download Complete
2844*5113495bSYour Name */
2845*5113495bSYour Name qdf_status =
2846*5113495bSYour Name qdf_wait_for_event_completion(&wma_handle->
2847*5113495bSYour Name tx_frm_download_comp_event,
2848*5113495bSYour Name WMA_TX_FRAME_COMPLETE_TIMEOUT);
2849*5113495bSYour Name
2850*5113495bSYour Name if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
2851*5113495bSYour Name wma_nofl_alert("Wait Event failed txfrm_comp_event");
2852*5113495bSYour Name /*
2853*5113495bSYour Name * @Integrated: Something Wrong with Dxe
2854*5113495bSYour Name * TODO: Some Debug Code
2855*5113495bSYour Name * Here We need to trigger SSR since
2856*5113495bSYour Name * since system went into a bad state where
2857*5113495bSYour Name * we didn't get Download Complete for almost
2858*5113495bSYour Name * WMA_TX_FRAME_COMPLETE_TIMEOUT (1 sec)
2859*5113495bSYour Name */
2860*5113495bSYour Name /* display scheduler stats */
2861*5113495bSYour Name return cdp_display_stats(soc, CDP_SCHEDULER_STATS,
2862*5113495bSYour Name QDF_STATS_VERBOSITY_LEVEL_HIGH);
2863*5113495bSYour Name }
2864*5113495bSYour Name }
2865*5113495bSYour Name
2866*5113495bSYour Name return QDF_STATUS_SUCCESS;
2867*5113495bSYour Name
2868*5113495bSYour Name error:
2869*5113495bSYour Name wma_handle->tx_frm_download_comp_cb = NULL;
2870*5113495bSYour Name wma_handle->umac_data_ota_ack_cb = NULL;
2871*5113495bSYour Name return QDF_STATUS_E_FAILURE;
2872*5113495bSYour Name }
2873*5113495bSYour Name
wma_ds_peek_rx_packet_info(cds_pkt_t * pkt,void ** pkt_meta)2874*5113495bSYour Name QDF_STATUS wma_ds_peek_rx_packet_info(cds_pkt_t *pkt, void **pkt_meta)
2875*5113495bSYour Name {
2876*5113495bSYour Name if (!pkt) {
2877*5113495bSYour Name wma_err("wma:Invalid parameter sent on wma_peek_rx_pkt_info");
2878*5113495bSYour Name return QDF_STATUS_E_FAULT;
2879*5113495bSYour Name }
2880*5113495bSYour Name
2881*5113495bSYour Name *pkt_meta = &(pkt->pkt_meta);
2882*5113495bSYour Name
2883*5113495bSYour Name return QDF_STATUS_SUCCESS;
2884*5113495bSYour Name }
2885*5113495bSYour Name
2886*5113495bSYour Name #ifdef HL_RX_AGGREGATION_HOLE_DETECTION
ol_rx_aggregation_hole(uint32_t hole_info)2887*5113495bSYour Name void ol_rx_aggregation_hole(uint32_t hole_info)
2888*5113495bSYour Name {
2889*5113495bSYour Name struct sir_sme_rx_aggr_hole_ind *rx_aggr_hole_event;
2890*5113495bSYour Name uint32_t alloc_len;
2891*5113495bSYour Name cds_msg_t cds_msg = { 0 };
2892*5113495bSYour Name QDF_STATUS status;
2893*5113495bSYour Name
2894*5113495bSYour Name alloc_len = sizeof(*rx_aggr_hole_event) +
2895*5113495bSYour Name sizeof(rx_aggr_hole_event->hole_info_array[0]);
2896*5113495bSYour Name rx_aggr_hole_event = qdf_mem_malloc(alloc_len);
2897*5113495bSYour Name if (!rx_aggr_hole_event)
2898*5113495bSYour Name return;
2899*5113495bSYour Name
2900*5113495bSYour Name rx_aggr_hole_event->hole_cnt = 1;
2901*5113495bSYour Name rx_aggr_hole_event->hole_info_array[0] = hole_info;
2902*5113495bSYour Name
2903*5113495bSYour Name cds_msg.type = eWNI_SME_RX_AGGR_HOLE_IND;
2904*5113495bSYour Name cds_msg.bodyptr = rx_aggr_hole_event;
2905*5113495bSYour Name cds_msg.bodyval = 0;
2906*5113495bSYour Name
2907*5113495bSYour Name status = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg);
2908*5113495bSYour Name if (status != QDF_STATUS_SUCCESS) {
2909*5113495bSYour Name qdf_mem_free(rx_aggr_hole_event);
2910*5113495bSYour Name return;
2911*5113495bSYour Name }
2912*5113495bSYour Name }
2913*5113495bSYour Name #endif
2914*5113495bSYour Name
2915*5113495bSYour Name /**
2916*5113495bSYour Name * ol_rx_err() - ol rx err handler
2917*5113495bSYour Name * @pdev: ol pdev
2918*5113495bSYour Name * @vdev_id: vdev id
2919*5113495bSYour Name * @peer_mac_addr: peer mac address
2920*5113495bSYour Name * @tid: TID
2921*5113495bSYour Name * @tsf32: TSF
2922*5113495bSYour Name * @err_type: error type
2923*5113495bSYour Name * @rx_frame: rx frame
2924*5113495bSYour Name * @pn: PN Number
2925*5113495bSYour Name * @key_id: key id
2926*5113495bSYour Name *
2927*5113495bSYour Name * This function handles rx error and send MIC error failure to LIM
2928*5113495bSYour Name *
2929*5113495bSYour Name * Return: none
2930*5113495bSYour Name */
2931*5113495bSYour Name /*
2932*5113495bSYour Name * Local prototype added to temporarily address warning caused by
2933*5113495bSYour Name * -Wmissing-prototypes. A more correct solution will come later
2934*5113495bSYour Name * as a solution to IR-196435 at which point this prototype will
2935*5113495bSYour Name * be removed.
2936*5113495bSYour Name */
2937*5113495bSYour Name void ol_rx_err(void *pdev, uint8_t vdev_id,
2938*5113495bSYour Name uint8_t *peer_mac_addr, int tid, uint32_t tsf32,
2939*5113495bSYour Name enum ol_rx_err_type err_type, qdf_nbuf_t rx_frame,
2940*5113495bSYour Name uint64_t *pn, uint8_t key_id);
ol_rx_err(void * pdev,uint8_t vdev_id,uint8_t * peer_mac_addr,int tid,uint32_t tsf32,enum ol_rx_err_type err_type,qdf_nbuf_t rx_frame,uint64_t * pn,uint8_t key_id)2941*5113495bSYour Name void ol_rx_err(void *pdev, uint8_t vdev_id,
2942*5113495bSYour Name uint8_t *peer_mac_addr, int tid, uint32_t tsf32,
2943*5113495bSYour Name enum ol_rx_err_type err_type, qdf_nbuf_t rx_frame,
2944*5113495bSYour Name uint64_t *pn, uint8_t key_id)
2945*5113495bSYour Name {
2946*5113495bSYour Name tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
2947*5113495bSYour Name struct mic_failure_ind *mic_err_ind;
2948*5113495bSYour Name qdf_ether_header_t *eth_hdr;
2949*5113495bSYour Name uint8_t *bssid;
2950*5113495bSYour Name struct scheduler_msg cds_msg = {0};
2951*5113495bSYour Name
2952*5113495bSYour Name if (!wma)
2953*5113495bSYour Name return;
2954*5113495bSYour Name
2955*5113495bSYour Name if (err_type != OL_RX_ERR_TKIP_MIC)
2956*5113495bSYour Name return;
2957*5113495bSYour Name
2958*5113495bSYour Name if (qdf_nbuf_len(rx_frame) < sizeof(*eth_hdr))
2959*5113495bSYour Name return;
2960*5113495bSYour Name eth_hdr = (qdf_ether_header_t *)qdf_nbuf_data(rx_frame);
2961*5113495bSYour Name mic_err_ind = qdf_mem_malloc(sizeof(*mic_err_ind));
2962*5113495bSYour Name if (!mic_err_ind)
2963*5113495bSYour Name return;
2964*5113495bSYour Name
2965*5113495bSYour Name mic_err_ind->messageType = eWNI_SME_MIC_FAILURE_IND;
2966*5113495bSYour Name mic_err_ind->length = sizeof(*mic_err_ind);
2967*5113495bSYour Name mic_err_ind->sessionId = vdev_id;
2968*5113495bSYour Name bssid = wma_get_vdev_bssid(wma->interfaces[vdev_id].vdev);
2969*5113495bSYour Name if (!bssid) {
2970*5113495bSYour Name wma_err("Failed to get bssid for vdev_%d", vdev_id);
2971*5113495bSYour Name qdf_mem_free((void *)mic_err_ind);
2972*5113495bSYour Name return;
2973*5113495bSYour Name }
2974*5113495bSYour Name qdf_copy_macaddr(&mic_err_ind->bssId,
2975*5113495bSYour Name (struct qdf_mac_addr *)bssid);
2976*5113495bSYour Name qdf_mem_copy(mic_err_ind->info.taMacAddr,
2977*5113495bSYour Name (struct qdf_mac_addr *) peer_mac_addr,
2978*5113495bSYour Name sizeof(tSirMacAddr));
2979*5113495bSYour Name qdf_mem_copy(mic_err_ind->info.srcMacAddr,
2980*5113495bSYour Name (struct qdf_mac_addr *) eth_hdr->ether_shost,
2981*5113495bSYour Name sizeof(tSirMacAddr));
2982*5113495bSYour Name qdf_mem_copy(mic_err_ind->info.dstMacAddr,
2983*5113495bSYour Name (struct qdf_mac_addr *) eth_hdr->ether_dhost,
2984*5113495bSYour Name sizeof(tSirMacAddr));
2985*5113495bSYour Name mic_err_ind->info.keyId = key_id;
2986*5113495bSYour Name mic_err_ind->info.multicast =
2987*5113495bSYour Name IEEE80211_IS_MULTICAST(eth_hdr->ether_dhost);
2988*5113495bSYour Name qdf_mem_copy(mic_err_ind->info.TSC, pn, SIR_CIPHER_SEQ_CTR_SIZE);
2989*5113495bSYour Name
2990*5113495bSYour Name qdf_mem_zero(&cds_msg, sizeof(struct scheduler_msg));
2991*5113495bSYour Name cds_msg.type = eWNI_SME_MIC_FAILURE_IND;
2992*5113495bSYour Name cds_msg.bodyptr = (void *) mic_err_ind;
2993*5113495bSYour Name
2994*5113495bSYour Name if (QDF_STATUS_SUCCESS !=
2995*5113495bSYour Name scheduler_post_message(QDF_MODULE_ID_TXRX,
2996*5113495bSYour Name QDF_MODULE_ID_SME,
2997*5113495bSYour Name QDF_MODULE_ID_SME,
2998*5113495bSYour Name &cds_msg)) {
2999*5113495bSYour Name wma_err("could not post mic failure indication to SME");
3000*5113495bSYour Name qdf_mem_free((void *)mic_err_ind);
3001*5113495bSYour Name }
3002*5113495bSYour Name }
3003*5113495bSYour Name
wma_tx_abort(uint8_t vdev_id)3004*5113495bSYour Name void wma_tx_abort(uint8_t vdev_id)
3005*5113495bSYour Name {
3006*5113495bSYour Name #define PEER_ALL_TID_BITMASK 0xffffffff
3007*5113495bSYour Name tp_wma_handle wma;
3008*5113495bSYour Name uint32_t peer_tid_bitmap = PEER_ALL_TID_BITMASK;
3009*5113495bSYour Name struct wma_txrx_node *iface;
3010*5113495bSYour Name uint8_t *bssid;
3011*5113495bSYour Name struct peer_flush_params param = {0};
3012*5113495bSYour Name
3013*5113495bSYour Name wma = cds_get_context(QDF_MODULE_ID_WMA);
3014*5113495bSYour Name if (!wma)
3015*5113495bSYour Name return;
3016*5113495bSYour Name
3017*5113495bSYour Name iface = &wma->interfaces[vdev_id];
3018*5113495bSYour Name if (!iface->vdev) {
3019*5113495bSYour Name wma_err("iface->vdev is NULL");
3020*5113495bSYour Name return;
3021*5113495bSYour Name }
3022*5113495bSYour Name
3023*5113495bSYour Name bssid = wma_get_vdev_bssid(iface->vdev);
3024*5113495bSYour Name if (!bssid) {
3025*5113495bSYour Name wma_err("Failed to get bssid for vdev_%d", vdev_id);
3026*5113495bSYour Name return;
3027*5113495bSYour Name }
3028*5113495bSYour Name
3029*5113495bSYour Name wma_debug("vdevid %d bssid "QDF_MAC_ADDR_FMT, vdev_id,
3030*5113495bSYour Name QDF_MAC_ADDR_REF(bssid));
3031*5113495bSYour Name wma_vdev_set_pause_bit(vdev_id, PAUSE_TYPE_HOST);
3032*5113495bSYour Name cdp_fc_vdev_pause(cds_get_context(QDF_MODULE_ID_SOC), vdev_id,
3033*5113495bSYour Name OL_TXQ_PAUSE_REASON_TX_ABORT, 0);
3034*5113495bSYour Name
3035*5113495bSYour Name /* Flush all TIDs except MGMT TID for this peer in Target */
3036*5113495bSYour Name peer_tid_bitmap &= ~(0x1 << WMI_MGMT_TID);
3037*5113495bSYour Name param.peer_tid_bitmap = peer_tid_bitmap;
3038*5113495bSYour Name param.vdev_id = vdev_id;
3039*5113495bSYour Name wmi_unified_peer_flush_tids_send(wma->wmi_handle, bssid,
3040*5113495bSYour Name ¶m);
3041*5113495bSYour Name }
3042*5113495bSYour Name
wma_delete_invalid_peer_entries(uint8_t vdev_id,uint8_t * peer_mac_addr)3043*5113495bSYour Name void wma_delete_invalid_peer_entries(uint8_t vdev_id, uint8_t *peer_mac_addr)
3044*5113495bSYour Name {
3045*5113495bSYour Name tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
3046*5113495bSYour Name uint8_t i;
3047*5113495bSYour Name struct wma_txrx_node *iface;
3048*5113495bSYour Name
3049*5113495bSYour Name if (!wma)
3050*5113495bSYour Name return;
3051*5113495bSYour Name
3052*5113495bSYour Name iface = &wma->interfaces[vdev_id];
3053*5113495bSYour Name
3054*5113495bSYour Name if (peer_mac_addr) {
3055*5113495bSYour Name for (i = 0; i < INVALID_PEER_MAX_NUM; i++) {
3056*5113495bSYour Name if (qdf_mem_cmp
3057*5113495bSYour Name (iface->invalid_peers[i].rx_macaddr,
3058*5113495bSYour Name peer_mac_addr,
3059*5113495bSYour Name QDF_MAC_ADDR_SIZE) == 0) {
3060*5113495bSYour Name qdf_mem_zero(iface->invalid_peers[i].rx_macaddr,
3061*5113495bSYour Name sizeof(QDF_MAC_ADDR_SIZE));
3062*5113495bSYour Name break;
3063*5113495bSYour Name }
3064*5113495bSYour Name }
3065*5113495bSYour Name if (i == INVALID_PEER_MAX_NUM)
3066*5113495bSYour Name wma_debug("peer_mac_addr "QDF_MAC_ADDR_FMT" is not found",
3067*5113495bSYour Name QDF_MAC_ADDR_REF(peer_mac_addr));
3068*5113495bSYour Name } else {
3069*5113495bSYour Name qdf_mem_zero(iface->invalid_peers,
3070*5113495bSYour Name sizeof(iface->invalid_peers));
3071*5113495bSYour Name }
3072*5113495bSYour Name }
3073*5113495bSYour Name
wma_rx_invalid_peer_ind(uint8_t vdev_id,void * wh)3074*5113495bSYour Name uint8_t wma_rx_invalid_peer_ind(uint8_t vdev_id, void *wh)
3075*5113495bSYour Name {
3076*5113495bSYour Name struct ol_rx_inv_peer_params *rx_inv_msg;
3077*5113495bSYour Name struct ieee80211_frame *wh_l = (struct ieee80211_frame *)wh;
3078*5113495bSYour Name tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
3079*5113495bSYour Name uint8_t i, index;
3080*5113495bSYour Name bool invalid_peer_found = false;
3081*5113495bSYour Name struct wma_txrx_node *iface;
3082*5113495bSYour Name
3083*5113495bSYour Name if (!wma)
3084*5113495bSYour Name return -EINVAL;
3085*5113495bSYour Name
3086*5113495bSYour Name iface = &wma->interfaces[vdev_id];
3087*5113495bSYour Name rx_inv_msg = qdf_mem_malloc(sizeof(struct ol_rx_inv_peer_params));
3088*5113495bSYour Name if (!rx_inv_msg)
3089*5113495bSYour Name return -ENOMEM;
3090*5113495bSYour Name
3091*5113495bSYour Name index = iface->invalid_peer_idx;
3092*5113495bSYour Name rx_inv_msg->vdev_id = vdev_id;
3093*5113495bSYour Name qdf_mem_copy(rx_inv_msg->ra, wh_l->i_addr1, QDF_MAC_ADDR_SIZE);
3094*5113495bSYour Name qdf_mem_copy(rx_inv_msg->ta, wh_l->i_addr2, QDF_MAC_ADDR_SIZE);
3095*5113495bSYour Name
3096*5113495bSYour Name
3097*5113495bSYour Name for (i = 0; i < INVALID_PEER_MAX_NUM; i++) {
3098*5113495bSYour Name if (qdf_mem_cmp
3099*5113495bSYour Name (iface->invalid_peers[i].rx_macaddr,
3100*5113495bSYour Name rx_inv_msg->ta,
3101*5113495bSYour Name QDF_MAC_ADDR_SIZE) == 0) {
3102*5113495bSYour Name invalid_peer_found = true;
3103*5113495bSYour Name break;
3104*5113495bSYour Name }
3105*5113495bSYour Name }
3106*5113495bSYour Name
3107*5113495bSYour Name if (!invalid_peer_found) {
3108*5113495bSYour Name qdf_mem_copy(iface->invalid_peers[index].rx_macaddr,
3109*5113495bSYour Name rx_inv_msg->ta,
3110*5113495bSYour Name QDF_MAC_ADDR_SIZE);
3111*5113495bSYour Name
3112*5113495bSYour Name /* reset count if reached max */
3113*5113495bSYour Name iface->invalid_peer_idx =
3114*5113495bSYour Name (index + 1) % INVALID_PEER_MAX_NUM;
3115*5113495bSYour Name
3116*5113495bSYour Name /* send deauth */
3117*5113495bSYour Name wma_debug("vdev_id: %d RA: "QDF_MAC_ADDR_FMT" TA: "QDF_MAC_ADDR_FMT,
3118*5113495bSYour Name vdev_id, QDF_MAC_ADDR_REF(rx_inv_msg->ra),
3119*5113495bSYour Name QDF_MAC_ADDR_REF(rx_inv_msg->ta));
3120*5113495bSYour Name
3121*5113495bSYour Name wma_send_msg(wma,
3122*5113495bSYour Name SIR_LIM_RX_INVALID_PEER,
3123*5113495bSYour Name (void *)rx_inv_msg, 0);
3124*5113495bSYour Name } else {
3125*5113495bSYour Name wma_debug_rl("Ignore invalid peer indication as received more than once "
3126*5113495bSYour Name QDF_MAC_ADDR_FMT,
3127*5113495bSYour Name QDF_MAC_ADDR_REF(rx_inv_msg->ta));
3128*5113495bSYour Name qdf_mem_free(rx_inv_msg);
3129*5113495bSYour Name }
3130*5113495bSYour Name
3131*5113495bSYour Name return 0;
3132*5113495bSYour Name }
3133*5113495bSYour Name
3134*5113495bSYour Name static bool
wma_drop_delba(tp_wma_handle wma,uint8_t vdev_id,enum cdp_delba_rcode cdp_reason_code)3135*5113495bSYour Name wma_drop_delba(tp_wma_handle wma, uint8_t vdev_id,
3136*5113495bSYour Name enum cdp_delba_rcode cdp_reason_code)
3137*5113495bSYour Name {
3138*5113495bSYour Name struct wlan_objmgr_vdev *vdev;
3139*5113495bSYour Name qdf_time_t last_ts, ts = qdf_mc_timer_get_system_time();
3140*5113495bSYour Name bool drop = false;
3141*5113495bSYour Name
3142*5113495bSYour Name vdev = wlan_objmgr_get_vdev_by_id_from_psoc(wma->psoc, vdev_id,
3143*5113495bSYour Name WLAN_MLME_CM_ID);
3144*5113495bSYour Name if (!vdev) {
3145*5113495bSYour Name wma_err("vdev is NULL");
3146*5113495bSYour Name return drop;
3147*5113495bSYour Name }
3148*5113495bSYour Name if (!wlan_mlme_is_ba_2k_jump_iot_ap(vdev))
3149*5113495bSYour Name goto done;
3150*5113495bSYour Name
3151*5113495bSYour Name last_ts = wlan_mlme_get_last_delba_sent_time(vdev);
3152*5113495bSYour Name if ((last_ts && cdp_reason_code == CDP_DELBA_2K_JUMP) &&
3153*5113495bSYour Name (ts - last_ts) < CDP_DELBA_INTERVAL_MS) {
3154*5113495bSYour Name wma_debug("Drop DELBA, last sent ts: %lu current ts: %lu",
3155*5113495bSYour Name last_ts, ts);
3156*5113495bSYour Name drop = true;
3157*5113495bSYour Name }
3158*5113495bSYour Name
3159*5113495bSYour Name wlan_mlme_set_last_delba_sent_time(vdev, ts);
3160*5113495bSYour Name
3161*5113495bSYour Name done:
3162*5113495bSYour Name wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
3163*5113495bSYour Name
3164*5113495bSYour Name return drop;
3165*5113495bSYour Name }
3166*5113495bSYour Name
wma_dp_send_delba_ind(uint8_t vdev_id,uint8_t * peer_macaddr,uint8_t tid,uint8_t reason_code,enum cdp_delba_rcode cdp_reason_code)3167*5113495bSYour Name int wma_dp_send_delba_ind(uint8_t vdev_id, uint8_t *peer_macaddr,
3168*5113495bSYour Name uint8_t tid, uint8_t reason_code,
3169*5113495bSYour Name enum cdp_delba_rcode cdp_reason_code)
3170*5113495bSYour Name {
3171*5113495bSYour Name tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
3172*5113495bSYour Name struct lim_delba_req_info *req;
3173*5113495bSYour Name
3174*5113495bSYour Name if (!wma || !peer_macaddr) {
3175*5113495bSYour Name wma_err("wma handle or mac addr is NULL");
3176*5113495bSYour Name return -EINVAL;
3177*5113495bSYour Name }
3178*5113495bSYour Name
3179*5113495bSYour Name if (wma_drop_delba(wma, vdev_id, cdp_reason_code))
3180*5113495bSYour Name return 0;
3181*5113495bSYour Name
3182*5113495bSYour Name req = qdf_mem_malloc(sizeof(*req));
3183*5113495bSYour Name if (!req)
3184*5113495bSYour Name return -ENOMEM;
3185*5113495bSYour Name req->vdev_id = vdev_id;
3186*5113495bSYour Name qdf_mem_copy(req->peer_macaddr, peer_macaddr, QDF_MAC_ADDR_SIZE);
3187*5113495bSYour Name req->tid = tid;
3188*5113495bSYour Name req->reason_code = reason_code;
3189*5113495bSYour Name wma_debug("req delba_ind vdev %d "QDF_MAC_ADDR_FMT" tid %d reason %d",
3190*5113495bSYour Name vdev_id, QDF_MAC_ADDR_REF(peer_macaddr), tid, reason_code);
3191*5113495bSYour Name wma_send_msg_high_priority(wma, SIR_HAL_REQ_SEND_DELBA_REQ_IND,
3192*5113495bSYour Name (void *)req, 0);
3193*5113495bSYour Name
3194*5113495bSYour Name return 0;
3195*5113495bSYour Name }
3196*5113495bSYour Name
wma_is_roam_in_progress(uint32_t vdev_id)3197*5113495bSYour Name bool wma_is_roam_in_progress(uint32_t vdev_id)
3198*5113495bSYour Name {
3199*5113495bSYour Name tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
3200*5113495bSYour Name enum QDF_OPMODE opmode;
3201*5113495bSYour Name
3202*5113495bSYour Name if (!wma_is_vdev_valid(vdev_id))
3203*5113495bSYour Name return false;
3204*5113495bSYour Name
3205*5113495bSYour Name if (!wma || !wma->interfaces[vdev_id].vdev)
3206*5113495bSYour Name return false;
3207*5113495bSYour Name
3208*5113495bSYour Name opmode = wlan_vdev_mlme_get_opmode(wma->interfaces[vdev_id].vdev);
3209*5113495bSYour Name if (opmode != QDF_STA_MODE && opmode != QDF_P2P_CLIENT_MODE)
3210*5113495bSYour Name return false;
3211*5113495bSYour Name
3212*5113495bSYour Name return wlan_cm_is_vdev_roam_started(wma->interfaces[vdev_id].vdev);
3213*5113495bSYour Name }
3214