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