1 /** @file mlan_wmm.c
2 *
3 * @brief This file provides functions for WMM
4 *
5 * Copyright 2008-2024 NXP
6 *
7 * SPDX-License-Identifier: BSD-3-Clause
8 *
9 */
10
11 /********************************************************
12 Change log:
13 10/24/2008: initial version
14 ********************************************************/
15
16 #include <mlan_api.h>
17
18 /* Additional WMSDK header files */
19 #include <wmerrno.h>
20 #include <osa.h>
21 #if CONFIG_TX_RX_ZERO_COPY
22 #include <wm_net.h>
23 #endif
24 /* Always keep this include at the end of all include files */
25 #include <mlan_remap_mem_operations.h>
26 /********************************************************
27 Local Variables
28 ********************************************************/
29
30 /** Maximum value FW can accept for driver delay in packet transmission */
31 #define DRV_PKT_DELAY_TO_FW_MAX 512
32
33 /*
34 * Upper and Lower threshold for packet queuing in the driver
35
36 * - When the number of packets queued reaches the upper limit,
37 * the driver will stop the net queue in the app/kernel space.
38
39 * - When the number of packets drops beneath the lower limit after
40 * having reached the upper limit, the driver will restart the net
41 * queue.
42 */
43
44 /** Lower threshold for packet queuing in the driver.
45 * When the number of packets drops beneath the lower limit after having
46 * reached the upper limit, the driver will restart the net queue.
47 */
48 #define WMM_QUEUED_PACKET_LOWER_LIMIT 180
49
50 /** Upper threshold for packet queuing in the driver.
51 * When the number of packets queued reaches the upper limit, the driver
52 * will stop the net queue in the app/kernel space.
53 */
54 #define WMM_QUEUED_PACKET_UPPER_LIMIT 200
55
56 /** Offset for TOS field in the IP header */
57 #define IPTOS_OFFSET 5
58
59 /** WMM information IE */
60 static const t_u8 wmm_info_ie[] = {(t_u8)WMM_IE, 0x07, 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00};
61
62 /** Type enumeration of WMM AC_QUEUES */
63 typedef MLAN_PACK_START enum _wmm_ac_e { AC_BE, AC_BK, AC_VI, AC_VO } MLAN_PACK_END wmm_ac_e;
64
65 /**
66 * This table will be used to store the tid values based on ACs.
67 * It is initialized to default values per TID.
68 */
69 static t_u8 tos_to_tid[] = {
70 /* TID DSCP_P2 DSCP_P1 DSCP_P0 WMM_AC */
71 0x01, /* 0 1 0 AC_BK */
72 0x02, /* 0 0 0 AC_BK */
73 0x00, /* 0 0 1 AC_BE */
74 0x03, /* 0 1 1 AC_BE */
75 0x04, /* 1 0 0 AC_VI */
76 0x05, /* 1 0 1 AC_VI */
77 0x06, /* 1 1 0 AC_VO */
78 0x07 /* 1 1 1 AC_VO */
79 };
80
81 /**
82 * This table will provide the tid value for given ac. This table does not
83 * change and will be used to copy back the default values to tos_to_tid in
84 * case of disconnect.
85 */
86 static const t_u8 ac_to_tid[4][2] = {{1, 2}, {0, 3}, {4, 5}, {6, 7}};
87 raListTbl *wlan_wmm_get_ralist_node(pmlan_private priv, t_u8 tid, t_u8 *ra_addr);
88 /********************************************************
89 Local Functions
90 ********************************************************/
91 #ifdef DEBUG_LEVEL2
92 /**
93 * @brief Debug print function to display the priority parameters for a WMM AC
94 *
95 * @param pac_param Pointer to the AC parameters to display
96 *
97 * @return N/A
98 */
wlan_wmm_ac_debug_print(const IEEEtypes_WmmAcParameters_t * pac_param)99 static void wlan_wmm_ac_debug_print(const IEEEtypes_WmmAcParameters_t *pac_param)
100 {
101 const char *ac_str[] = {"BK", "BE", "VI", "VO"};
102
103 ENTER();
104
105 PRINTM(MINFO,
106 "WMM AC_%s: ACI=%d, ACM=%d, Aifsn=%d, "
107 "EcwMin=%d, EcwMax=%d, TxopLimit=%d\n",
108 ac_str[wmm_aci_to_qidx_map[pac_param->aci_aifsn.aci]], pac_param->aci_aifsn.aci, pac_param->aci_aifsn.acm,
109 pac_param->aci_aifsn.aifsn, pac_param->ecw.ecw_min, pac_param->ecw.ecw_max,
110 wlan_le16_to_cpu(pac_param->tx_op_limit));
111
112 LEAVE();
113 }
114
115 /** Print the WMM AC for debug purpose */
116 #define PRINTM_AC(pac_param) wlan_wmm_ac_debug_print(pac_param)
117 #else
118 /** Print the WMM AC for debug purpose */
119 #define PRINTM_AC(pac_param)
120 #endif
121
122 /**
123 * @brief This function cleans Tx/Rx queues
124 *
125 * @param priv A pointer to mlan_private
126 *
127 * @return N/A
128 */
wlan_clean_txrx(pmlan_private priv)129 t_void wlan_clean_txrx(pmlan_private priv)
130 {
131 mlan_adapter *pmadapter = priv->adapter;
132
133 ENTER();
134
135 #if CONFIG_WMM
136 wlan_cleanup_bypass_txq(GET_BSS_ROLE(priv));
137 #endif
138
139 wlan_11n_cleanup_reorder_tbl(priv);
140
141 (void)pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle, priv->wmm.ra_list_spinlock);
142 wlan_11n_deleteall_txbastream_tbl(priv);
143 #ifdef SDIO_MULTI_PORT_TX_AGGR
144 MP_TX_AGGR_BUF_RESET(priv->adapter);
145 #endif
146 #ifdef SDIO_MULTI_PORT_RX_AGGR_FOR_REF
147 MP_RX_AGGR_BUF_RESET(priv->adapter);
148 #endif
149 #if CONFIG_WMM
150 wlan_ralist_del_all_enh(priv);
151 #endif /* CONFIG_WMM */
152 (void)__memcpy(pmadapter, tos_to_tid, ac_to_tid, sizeof(tos_to_tid));
153
154 #if defined(UAP_SUPPORT)
155 priv->num_drop_pkts = 0;
156 #endif
157 (void)pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle, priv->wmm.ra_list_spinlock);
158
159 LEAVE();
160 }
161
162 /**
163 * @brief Set the WMM queue priorities to their default values
164 *
165 * @param priv Pointer to the mlan_private driver data struct
166 *
167 * @return N/A
168 */
wlan_wmm_default_queue_priorities(pmlan_private priv)169 void wlan_wmm_default_queue_priorities(pmlan_private priv)
170 {
171 ENTER();
172
173 /* Default queue priorities: VO->VI->BE->BK */
174 priv->wmm.queue_priority[0] = (t_u8)WMM_AC_VO;
175 priv->wmm.queue_priority[1] = (t_u8)WMM_AC_VI;
176 priv->wmm.queue_priority[2] = (t_u8)WMM_AC_BE;
177 priv->wmm.queue_priority[3] = (t_u8)WMM_AC_BK;
178
179 LEAVE();
180 }
181
182 /**
183 * @brief Initialize the WMM parameter.
184 *
185 * @param pmadapter Pointer to the mlan_adapter data structure
186 *
187 * @return N/A
188 */
wlan_init_wmm_param(pmlan_adapter pmadapter)189 t_void wlan_init_wmm_param(pmlan_adapter pmadapter)
190 {
191 /* Reuse the same structure of WmmAcParameters_t for configuration
192 * purpose here. the definition of acm bit is changed to ucm (user
193 * configuration mode) FW will take the setting of
194 * aifsn,ecw_max,ecw_min, tx_op_limit only when ucm is set to 1.
195 * othewise the default setting/behavoir in firmware will be used.
196 */
197 #ifdef RW610
198 pmadapter->ac_params[AC_BE].aci_aifsn.acm = 0;
199 pmadapter->ac_params[AC_BE].aci_aifsn.aci = AC_BE;
200 pmadapter->ac_params[AC_BE].aci_aifsn.aifsn = 5;
201 pmadapter->ac_params[AC_BE].ecw.ecw_max = 6;
202 pmadapter->ac_params[AC_BE].ecw.ecw_min = 4;
203 pmadapter->ac_params[AC_BE].tx_op_limit = 0;
204
205 pmadapter->ac_params[AC_BK].aci_aifsn.acm = 0;
206 pmadapter->ac_params[AC_BK].aci_aifsn.aci = AC_BK;
207 pmadapter->ac_params[AC_BK].aci_aifsn.aifsn = 9;
208 pmadapter->ac_params[AC_BK].ecw.ecw_max = 10;
209 pmadapter->ac_params[AC_BK].ecw.ecw_min = 4;
210 pmadapter->ac_params[AC_BK].tx_op_limit = 0;
211
212 pmadapter->ac_params[AC_VI].aci_aifsn.acm = 0;
213 pmadapter->ac_params[AC_VI].aci_aifsn.aci = AC_VI;
214 pmadapter->ac_params[AC_VI].aci_aifsn.aifsn = 3;
215 pmadapter->ac_params[AC_VI].ecw.ecw_max = 4;
216 pmadapter->ac_params[AC_VI].ecw.ecw_min = 3;
217 pmadapter->ac_params[AC_VI].tx_op_limit = 94;
218
219 pmadapter->ac_params[AC_VO].aci_aifsn.acm = 0;
220 pmadapter->ac_params[AC_VO].aci_aifsn.aci = AC_VO;
221 pmadapter->ac_params[AC_VO].aci_aifsn.aifsn = 3;
222 pmadapter->ac_params[AC_VO].ecw.ecw_max = 3;
223 pmadapter->ac_params[AC_VO].ecw.ecw_min = 2;
224 pmadapter->ac_params[AC_VO].tx_op_limit = 47;
225 #else
226 pmadapter->ac_params[AC_BE].aci_aifsn.acm = 0;
227 pmadapter->ac_params[AC_BE].aci_aifsn.aci = AC_BE;
228 pmadapter->ac_params[AC_BE].aci_aifsn.aifsn = 3;
229 pmadapter->ac_params[AC_BE].ecw.ecw_max = 10;
230 pmadapter->ac_params[AC_BE].ecw.ecw_min = 4;
231 pmadapter->ac_params[AC_BE].tx_op_limit = 0;
232
233 pmadapter->ac_params[AC_BK].aci_aifsn.acm = 0;
234 pmadapter->ac_params[AC_BK].aci_aifsn.aci = AC_BK;
235 pmadapter->ac_params[AC_BK].aci_aifsn.aifsn = 7;
236 pmadapter->ac_params[AC_BK].ecw.ecw_max = 10;
237 pmadapter->ac_params[AC_BK].ecw.ecw_min = 4;
238 pmadapter->ac_params[AC_BK].tx_op_limit = 0;
239
240 pmadapter->ac_params[AC_VI].aci_aifsn.acm = 0;
241 pmadapter->ac_params[AC_VI].aci_aifsn.aci = AC_VI;
242 pmadapter->ac_params[AC_VI].aci_aifsn.aifsn = 2;
243 pmadapter->ac_params[AC_VI].ecw.ecw_max = 4;
244 pmadapter->ac_params[AC_VI].ecw.ecw_min = 3;
245 pmadapter->ac_params[AC_VI].tx_op_limit = 188;
246
247 pmadapter->ac_params[AC_VO].aci_aifsn.acm = 0;
248 pmadapter->ac_params[AC_VO].aci_aifsn.aci = AC_VO;
249 pmadapter->ac_params[AC_VO].aci_aifsn.aifsn = 2;
250 pmadapter->ac_params[AC_VO].ecw.ecw_max = 3;
251 pmadapter->ac_params[AC_VO].ecw.ecw_min = 2;
252 pmadapter->ac_params[AC_VO].tx_op_limit = 102;
253 #endif
254 }
255
256 /**
257 * @brief Initialize the WMM state information and the WMM data path queues.
258 *
259 * @param pmadapter Pointer to the mlan_adapter data structure
260 *
261 * @return N/A
262 */
wlan_wmm_init(pmlan_adapter pmadapter)263 t_void wlan_wmm_init(pmlan_adapter pmadapter)
264 {
265 t_u8 i, j;
266 pmlan_private priv;
267
268 ENTER();
269
270 for (j = 0; j < pmadapter->priv_num; ++j)
271 {
272 priv = pmadapter->priv[j];
273 if (priv != MNULL)
274 {
275 for (i = 0; i < MAX_NUM_TID; ++i)
276 {
277 priv->wmm.pkts_queued[i] = 0;
278 priv->wmm.tid_tbl_ptr[i].ra_list_curr = MNULL;
279 }
280
281 priv->add_ba_param.timeout = MLAN_DEFAULT_BLOCK_ACK_TIMEOUT;
282 #ifdef STA_SUPPORT
283 if (priv->bss_type == MLAN_BSS_TYPE_STA)
284 {
285 priv->add_ba_param.tx_win_size = MLAN_STA_AMPDU_DEF_TXWINSIZE;
286 priv->add_ba_param.rx_win_size = MLAN_STA_AMPDU_DEF_RXWINSIZE;
287 }
288 #endif
289 #ifdef UAP_SUPPORT
290 if (priv->bss_type == MLAN_BSS_TYPE_UAP
291 #ifdef WIFI_DIRECT_SUPPORT
292 || priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT
293 #endif
294 )
295 {
296 priv->add_ba_param.tx_win_size = MLAN_UAP_AMPDU_DEF_TXWINSIZE;
297 priv->add_ba_param.rx_win_size = MLAN_UAP_AMPDU_DEF_RXWINSIZE;
298 }
299 #endif
300 priv->add_ba_param.tx_amsdu = MTRUE;
301 priv->add_ba_param.rx_amsdu = MTRUE;
302 (void)__memset(priv->adapter, priv->rx_seq, 0xff, sizeof(priv->rx_seq));
303 wlan_wmm_default_queue_priorities(priv);
304 }
305 }
306
307 LEAVE();
308 }
309
310 /**
311 * @brief Get ralist node
312 *
313 * @param priv Pointer to the mlan_private driver data struct
314 * @param tid TID
315 * @param ra_addr Pointer to the route address
316 *
317 * @return ra_list or MNULL
318 */
wlan_wmm_get_ralist_node(pmlan_private priv,t_u8 tid,t_u8 * ra_addr)319 raListTbl *wlan_wmm_get_ralist_node(pmlan_private priv, t_u8 tid, t_u8 *ra_addr)
320 {
321 raListTbl *ra_list;
322 ENTER();
323 ra_list =
324 (raListTbl *)util_peek_list(priv->adapter->pmoal_handle, &priv->wmm.tid_tbl_ptr[tid].ra_list, MNULL, MNULL);
325 while (ra_list && (ra_list != (raListTbl *)&priv->wmm.tid_tbl_ptr[tid].ra_list))
326 {
327 if (!__memcmp(priv->adapter, ra_list->ra, ra_addr, MLAN_MAC_ADDR_LENGTH))
328 {
329 LEAVE();
330 return ra_list;
331 }
332 ra_list = ra_list->pnext;
333 }
334 LEAVE();
335 return MNULL;
336 }
337
338 #ifdef STA_SUPPORT
339 /**
340 * @brief Call back from the command module to allow insertion of a WMM TLV
341 *
342 * If the BSS we are associating to supports WMM, add the required WMM
343 * Information IE to the association request command buffer in the form
344 * of a NXP extended IEEE IE.
345 *
346 * @param priv Pointer to the mlan_private driver data struct
347 * @param ppAssocBuf Output parameter: Pointer to the TLV output buffer,
348 * modified on return to point after the appended WMM TLV
349 * @param pWmmIE Pointer to the WMM IE for the BSS we are joining
350 * @param pHTCap Pointer to the HT IE for the BSS we are joining
351 *
352 * @return Length of data appended to the association tlv buffer
353 */
wlan_wmm_process_association_req(pmlan_private priv,t_u8 ** ppAssocBuf,IEEEtypes_WmmParameter_t * pWmmIE,IEEEtypes_HTCap_t * pHTCap)354 t_u32 wlan_wmm_process_association_req(pmlan_private priv,
355 t_u8 **ppAssocBuf,
356 IEEEtypes_WmmParameter_t *pWmmIE,
357 IEEEtypes_HTCap_t *pHTCap)
358 {
359 MrvlIEtypes_WmmParamSet_t *pwmm_tlv;
360 t_u32 ret_len = 0;
361
362 ENTER();
363
364 /* Null checks */
365 if (ppAssocBuf == MNULL)
366 {
367 LEAVE();
368 return 0;
369 }
370 if ((*ppAssocBuf) == MNULL)
371 {
372 LEAVE();
373 return 0;
374 }
375
376 if (pWmmIE == MNULL)
377 {
378 LEAVE();
379 return 0;
380 }
381
382 PRINTM(MINFO, "WMM: process assoc req: bss->wmmIe=0x%x\n", pWmmIE->vend_hdr.element_id);
383
384 if ((priv->wmm_required || ((pHTCap != MNULL) && (pHTCap->ieee_hdr.element_id == HT_CAPABILITY) &&
385 (priv->config_bands & BAND_GN || priv->config_bands & BAND_AN))) &&
386 pWmmIE->vend_hdr.element_id == WMM_IE)
387 {
388 pwmm_tlv = (MrvlIEtypes_WmmParamSet_t *)(void *)*ppAssocBuf;
389 pwmm_tlv->header.type = (t_u16)wmm_info_ie[0];
390 pwmm_tlv->header.type = wlan_cpu_to_le16(pwmm_tlv->header.type);
391 pwmm_tlv->header.len = (t_u16)wmm_info_ie[1];
392 (void)__memcpy(priv->adapter, pwmm_tlv->wmm_ie, &wmm_info_ie[2], pwmm_tlv->header.len);
393 if (pWmmIE->qos_info.qos_uapsd != 0U)
394 {
395 (void)__memcpy(priv->adapter, (t_u8 *)(pwmm_tlv->wmm_ie + pwmm_tlv->header.len - sizeof(priv->wmm_qosinfo)),
396 &priv->wmm_qosinfo, sizeof(priv->wmm_qosinfo));
397 }
398
399 ret_len = sizeof(pwmm_tlv->header) + pwmm_tlv->header.len;
400 pwmm_tlv->header.len = wlan_cpu_to_le16(pwmm_tlv->header.len);
401
402 HEXDUMP("ASSOC_CMD: WMM IE", (t_u8 *)pwmm_tlv, ret_len);
403 *ppAssocBuf += ret_len;
404 }
405
406 LEAVE();
407 return ret_len;
408 }
409 #endif /* STA_SUPPORT */
410
411 #if CONFIG_WMM
412 /**
413 * @brief This function prepares the command of WMM_PARAM_CONFIG
414 *
415 * @param pmpriv A pointer to mlan_private structure
416 * @param cmd A pointer to HostCmd_DS_COMMAND structure
417 * @param cmd_action cmd action.
418 * @param pdata_buf A pointer to data buffer
419 * @return MLAN_STATUS_SUCCESS
420 */
wlan_cmd_wmm_param_config(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u8 cmd_action,t_void * pdata_buf)421 mlan_status wlan_cmd_wmm_param_config(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd, t_u8 cmd_action, t_void *pdata_buf)
422 {
423 wmm_ac_parameters_t *ac_params = (wmm_ac_parameters_t *)pdata_buf;
424 HostCmd_DS_WMM_PARAM_CONFIG *pcmd_cfg = &cmd->params.param_config;
425 t_u8 i = 0;
426
427 ENTER();
428
429 cmd->command = wlan_cpu_to_le16(HostCmd_CMD_WMM_PARAM_CONFIG);
430 cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_WMM_PARAM_CONFIG) + S_DS_GEN);
431 cmd->result = 0;
432
433 pcmd_cfg->action = cmd_action;
434 if (cmd_action == HostCmd_ACT_GEN_SET)
435 {
436 (void)__memcpy(pmpriv->adapter, pcmd_cfg->ac_params, ac_params, sizeof(wmm_ac_parameters_t) * MAX_AC_QUEUES);
437 for (i = 0; i < MAX_AC_QUEUES; i++)
438 {
439 pcmd_cfg->ac_params[i].tx_op_limit = wlan_cpu_to_le16(pcmd_cfg->ac_params[i].tx_op_limit);
440 }
441 }
442 LEAVE();
443 return MLAN_STATUS_SUCCESS;
444 }
445
446 /**
447 * @brief This function handles the command response of WMM_PARAM_CONFIG
448 *
449 * @param pmpriv A pointer to mlan_private structure
450 * @param resp A pointer to HostCmd_DS_COMMAND
451 * @param pioctl_buf A pointer to mlan_ioctl_req structure
452 *
453 * @return MLAN_STATUS_SUCCESS
454 */
wlan_ret_wmm_param_config(pmlan_private pmpriv,const HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)455 mlan_status wlan_ret_wmm_param_config(pmlan_private pmpriv, const HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
456 {
457 mlan_ds_wmm_cfg *pwmm = MNULL;
458 HostCmd_DS_WMM_PARAM_CONFIG *pcfg = (HostCmd_DS_WMM_PARAM_CONFIG *)&resp->params.param_config;
459 t_u8 i;
460
461 ENTER();
462
463 if (pioctl_buf)
464 {
465 pwmm = (mlan_ds_wmm_cfg *)pioctl_buf->pbuf;
466 for (i = 0; i < MAX_AC_QUEUES; i++)
467 {
468 pcfg->ac_params[i].tx_op_limit = wlan_le16_to_cpu(pcfg->ac_params[i].tx_op_limit);
469 }
470 (void)__memcpy(pmpriv->adapter, pwmm->param.ac_params, pcfg->ac_params,
471 sizeof(wmm_ac_parameters_t) * MAX_AC_QUEUES);
472 }
473
474 LEAVE();
475 return MLAN_STATUS_SUCCESS;
476 }
477 #endif
478
479 #if CONFIG_WMM
480 #if CONFIG_WMM_DEBUG
481 #define MAX_HISTORY_RA_LIST_NUM 32
482
wlan_ralist_get_history(mlan_private * priv,t_u8 * ra,t_u8 ac)483 static raListTbl *wlan_ralist_get_history(mlan_private *priv, t_u8 *ra, t_u8 ac)
484 {
485 raListTbl *ra_list = (raListTbl *)util_peek_list(priv->adapter->pmoal_handle, &priv->wmm.hist_ra[ac], MNULL, MNULL);
486
487 if (ra_list == MNULL)
488 return MNULL;
489
490 while (ra_list && ra_list != (raListTbl *)&priv->wmm.hist_ra[ac])
491 {
492 if (!memcmp(priv->adapter, ra, ra_list->ra, MLAN_MAC_ADDR_LENGTH))
493 return ra_list;
494
495 ra_list = ra_list->pnext;
496 }
497 return MNULL;
498 }
499
500 /* restore ralist to history list for debug */
wlan_ralist_restore_history(mlan_private * priv,raListTbl * ra_list,t_u8 ac)501 static void wlan_ralist_restore_history(mlan_private *priv, raListTbl *ra_list, t_u8 ac)
502 {
503 raListTbl *tmp = MNULL;
504
505 /* history lists has same ra, update stats and insert to tail */
506 tmp = wlan_ralist_get_history(priv, ra_list->ra, ac);
507 if (tmp != MNULL)
508 {
509 util_unlink_list(priv->adapter->pmoal_handle, &priv->wmm.hist_ra[ac], (mlan_linked_list *)tmp, MNULL, MNULL);
510 ra_list->drop_count += tmp->drop_count;
511 util_enqueue_list_tail(priv->adapter->pmoal_handle, &priv->wmm.hist_ra[ac], (mlan_linked_list *)ra_list, MNULL,
512 MNULL);
513 goto FREE_TMP;
514 }
515
516 /* history ralist count reaches max, dequeue the earliest ralist */
517 if (priv->wmm.hist_ra_count[ac] >= MAX_HISTORY_RA_LIST_NUM)
518 {
519 tmp = (raListTbl *)util_dequeue_list(priv->adapter->pmoal_handle, &priv->wmm.hist_ra[ac], MNULL, MNULL);
520 if (tmp == MNULL)
521 {
522 wifi_e("%s error history ralist count %hhu", priv->wmm.hist_ra_count[ac]);
523 goto FREE_IN;
524 }
525
526 util_enqueue_list_tail(priv->adapter->pmoal_handle, &priv->wmm.hist_ra[ac], (mlan_linked_list *)ra_list, MNULL,
527 MNULL);
528 goto FREE_TMP;
529 }
530 else
531 {
532 util_enqueue_list_tail(priv->adapter->pmoal_handle, &priv->wmm.hist_ra[ac], (mlan_linked_list *)ra_list, MNULL,
533 MNULL);
534 priv->wmm.hist_ra_count[ac]++;
535 }
536
537 return;
538 FREE_TMP:
539 priv->adapter->callbacks.moal_free_semaphore(priv->adapter->pmoal_handle, &tmp->buf_head.plock);
540 priv->adapter->callbacks.moal_mfree(priv->adapter->pmoal_handle, (t_u8 *)tmp);
541 return;
542 FREE_IN:
543 priv->adapter->callbacks.moal_free_semaphore(priv->adapter->pmoal_handle, &ra_list->buf_head.plock);
544 priv->adapter->callbacks.moal_mfree(priv->adapter->pmoal_handle, (t_u8 *)ra_list);
545 return;
546 }
547 #endif
548
549 /*
550 * transfer destination address to receive address
551 * consider 802.3 DA as RA
552 * for broadcast and multicast, consider RA as broadcast mac address
553 */
wifi_wmm_da_to_ra(uint8_t * da,uint8_t * ra)554 void wifi_wmm_da_to_ra(uint8_t *da, uint8_t *ra)
555 {
556 if ((da[0] & 0x01) == 1)
557 (void)__memset(mlan_adap, ra, 0xff, MLAN_MAC_ADDR_LENGTH);
558 else
559 (void)__memcpy(mlan_adap, ra, da, MLAN_MAC_ADDR_LENGTH);
560 }
561
562 /*
563 * check ra tx_pause status
564 * 1. STA mode: check priv->tx_pause
565 * 2. UAP mode:
566 * a. broadcast/multicast ra: check in ralists
567 * b. unicast ra: check in ampdu_stat_array for quick access
568 */
wifi_wmm_is_tx_pause(const uint8_t interface,mlan_wmm_ac_e queue,uint8_t * ra)569 static uint8_t wifi_wmm_is_tx_pause(const uint8_t interface, mlan_wmm_ac_e queue, uint8_t *ra)
570 {
571 t_u8 is_tx_pause = MFALSE;
572 raListTbl *ra_list = MNULL;
573
574 if (interface == MLAN_BSS_TYPE_STA)
575 {
576 is_tx_pause = mlan_adap->priv[0]->tx_pause;
577 }
578 else if (interface == MLAN_BSS_TYPE_UAP)
579 {
580 if (mlan_adap->priv[1]->tx_pause == MTRUE)
581 {
582 is_tx_pause = MTRUE;
583 }
584 else
585 {
586 mlan_adap->callbacks.moal_semaphore_get(mlan_adap->pmoal_handle,
587 &mlan_adap->priv[interface]->wmm.tid_tbl_ptr[queue].ra_list.plock);
588
589 ra_list = wlan_wmm_get_ralist_node(mlan_adap->priv[interface], queue, ra);
590 if (ra_list != MNULL)
591 is_tx_pause = ra_list->tx_pause;
592
593 mlan_adap->callbacks.moal_semaphore_put(mlan_adap->pmoal_handle,
594 &mlan_adap->priv[interface]->wmm.tid_tbl_ptr[queue].ra_list.plock);
595 }
596 }
597
598 return is_tx_pause;
599 }
600
601 /*
602 * find the alternative buffer paused in txqueue and replace it,
603 * priv->tx_pause 1: replace any ra node's oldest packet
604 * tx_pause 1: replace the same ra node's oldest packet
605 * tx_pause 0: replace any other tx_paused ra node's oldest packet
606 */
wifi_wmm_get_alter_buf_from_txqueue(const uint8_t interface,t_u8 * ra,t_u8 queue,t_u8 tx_pause)607 static outbuf_t *wifi_wmm_get_alter_buf_from_txqueue(const uint8_t interface, t_u8 *ra, t_u8 queue, t_u8 tx_pause)
608 {
609 raListTbl *ra_list_head = MNULL;
610 raListTbl *ra_list = MNULL;
611 outbuf_t *buf = MNULL;
612
613 mlan_adap->callbacks.moal_semaphore_get(mlan_adap->pmoal_handle,
614 &mlan_adap->priv[interface]->wmm.tid_tbl_ptr[queue].ra_list.plock);
615
616 if (mlan_adap->priv[interface]->wmm.pkts_queued[queue] == 0)
617 goto FAIL;
618
619 ra_list_head = (raListTbl *)&mlan_adap->priv[interface]->wmm.tid_tbl_ptr[queue].ra_list;
620 ra_list = (raListTbl *)util_peek_list(mlan_adap->pmoal_handle, (mlan_list_head *)ra_list_head, MNULL, MNULL);
621
622 while (ra_list && ra_list != ra_list_head)
623 {
624 mlan_adap->callbacks.moal_semaphore_get(mlan_adap->pmoal_handle, &ra_list->buf_head.plock);
625 if (__memcmp(mlan_adap, ra, ra_list->ra, MLAN_MAC_ADDR_LENGTH) && ra_list->tx_pause == MTRUE &&
626 ra_list->total_pkts != 0)
627 {
628 buf = (outbuf_t *)util_dequeue_list(mlan_adap->pmoal_handle, &ra_list->buf_head, MNULL, MNULL);
629 if (buf != MNULL)
630 goto SUCC;
631 }
632 mlan_adap->callbacks.moal_semaphore_put(mlan_adap->pmoal_handle, &ra_list->buf_head.plock);
633 ra_list = ra_list->pnext;
634 }
635
636 FAIL:
637 mlan_adap->callbacks.moal_semaphore_put(mlan_adap->pmoal_handle,
638 &mlan_adap->priv[interface]->wmm.tid_tbl_ptr[queue].ra_list.plock);
639 return MNULL;
640 SUCC:
641 mlan_adap->priv[interface]->wmm.pkts_queued[queue]--;
642 ra_list->total_pkts--;
643 ra_list->drop_count++;
644 #if CONFIG_TX_RX_ZERO_COPY
645 /* Before replacement, need free the buffer from stack first */
646 net_stack_buffer_free(buf->buffer);
647 #endif
648
649 mlan_adap->callbacks.moal_semaphore_put(mlan_adap->pmoal_handle, &ra_list->buf_head.plock);
650
651 mlan_adap->callbacks.moal_semaphore_put(mlan_adap->pmoal_handle,
652 &mlan_adap->priv[interface]->wmm.tid_tbl_ptr[queue].ra_list.plock);
653
654 wifi_wmm_drop_pause_replaced(interface);
655 return buf;
656 }
657
658 /* wmm enhance get free buffer */
wifi_wmm_get_outbuf_enh(uint32_t * outbuf_len,mlan_wmm_ac_e queue,const uint8_t interface,uint8_t * ra,bool * is_tx_pause)659 uint8_t *wifi_wmm_get_outbuf_enh(
660 uint32_t *outbuf_len, mlan_wmm_ac_e queue, const uint8_t interface, uint8_t *ra, bool *is_tx_pause)
661 {
662 t_u8 i;
663 outbuf_t *buf = MNULL;
664 t_u8 tx_pause;
665
666 buf = wifi_wmm_buf_get();
667 if (buf != MNULL)
668 goto SUCC;
669
670 /* check tx_pause */
671 tx_pause = wifi_wmm_is_tx_pause(interface, queue, ra);
672 *is_tx_pause = (tx_pause == MTRUE) ? true : false;
673
674 /* loop tid_tbl to find buf to replace in wmm ralists */
675 if (tx_pause == MFALSE)
676 {
677 for (i = 0; i < MAX_AC_QUEUES; i++)
678 {
679 buf = wifi_wmm_get_alter_buf_from_txqueue(interface, ra, i, tx_pause);
680 if (buf != MNULL)
681 goto SUCC;
682 }
683 }
684
685 *outbuf_len = 0;
686 return MNULL;
687 SUCC:
688 *outbuf_len = OUTBUF_WMM_LEN;
689 return (uint8_t *)buf;
690 }
691
692 /*
693 * get RA list for tx enqueue,
694 * check add broadcast RA list,
695 * drop unknown RA packets in UAP mode
696 */
wlan_wmm_get_queue_raptr_enh(pmlan_private priv,t_u8 ac,t_u8 * ra_addr)697 static raListTbl *wlan_wmm_get_queue_raptr_enh(pmlan_private priv, t_u8 ac, t_u8 *ra_addr)
698 {
699 raListTbl *ra_list = MNULL;
700 t_u8 bcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
701
702 ra_list = wlan_wmm_get_ralist_node(priv, ac, ra_addr);
703 if (ra_list != MNULL)
704 return ra_list;
705
706 #if CONFIG_WIFI_NM_WPA_SUPPLICANT
707 if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) &&
708 (0 != memcmp(ra_addr, bcast_addr, sizeof(bcast_addr))))
709 {
710 if (MNULL == wlan_get_station_entry(priv, ra_addr))
711 {
712 PRINTM(MERROR, "Drop packets to unknow station " MACSTR "\n", MAC2STR(ra_addr));
713 LEAVE();
714 return MNULL;
715 }
716 }
717 #else
718 if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP && __memcmp(priv->adapter, ra_addr, bcast_addr, MLAN_MAC_ADDR_LENGTH))
719 return MNULL;
720 #endif
721
722 /* wlan_ralist_add_enh will hold wmm lock, so need to unlock first */
723 priv->adapter->callbacks.moal_semaphore_put(priv->adapter->pmoal_handle, &priv->wmm.tid_tbl_ptr[ac].ra_list.plock);
724
725 wlan_ralist_add_enh(priv, ra_addr);
726
727 priv->adapter->callbacks.moal_semaphore_get(priv->adapter->pmoal_handle, &priv->wmm.tid_tbl_ptr[ac].ra_list.plock);
728
729 ra_list = wlan_wmm_get_ralist_node(priv, ac, ra_addr);
730 return ra_list;
731 }
732
733 /* wmm enhance enqueue tx buffer */
wlan_wmm_add_buf_txqueue_enh(const uint8_t interface,const uint8_t * buffer,const uint16_t len,uint8_t pkt_prio)734 int wlan_wmm_add_buf_txqueue_enh(const uint8_t interface, const uint8_t *buffer, const uint16_t len, uint8_t pkt_prio)
735 {
736 mlan_private *priv = MNULL;
737 t_u8 ra[MLAN_MAC_ADDR_LENGTH] = {0x0};
738 raListTbl *ralist = MNULL;
739
740 if (interface == MLAN_BSS_TYPE_STA)
741 priv = mlan_adap->priv[0];
742 else
743 priv = mlan_adap->priv[1];
744
745 /* refer to low_level_output payload memcpy */
746 #if CONFIG_TX_RX_ZERO_COPY
747 wifi_wmm_da_to_ra(&((outbuf_t *)buffer)->eth_header[0], ra);
748 #else
749 wifi_wmm_da_to_ra(&((outbuf_t *)buffer)->data[0], ra);
750 #endif
751 mlan_adap->callbacks.moal_semaphore_get(mlan_adap->pmoal_handle, &priv->wmm.tid_tbl_ptr[pkt_prio].ra_list.plock);
752
753 ralist = wlan_wmm_get_queue_raptr_enh(priv, pkt_prio, ra);
754 if (ralist == MNULL)
755 {
756 /* drop for unknown ra when enqueue */
757 wifi_wmm_buf_put((outbuf_t *)buffer);
758 mlan_adap->callbacks.moal_semaphore_put(mlan_adap->pmoal_handle,
759 &priv->wmm.tid_tbl_ptr[pkt_prio].ra_list.plock);
760 return MLAN_STATUS_FAILURE;
761 }
762
763 mlan_adap->callbacks.moal_semaphore_get(mlan_adap->pmoal_handle, &ralist->buf_head.plock);
764
765 util_enqueue_list_tail(mlan_adap->pmoal_handle, &ralist->buf_head, (mlan_linked_list *)buffer, MNULL, MNULL);
766 ralist->total_pkts++;
767 priv->wmm.pkts_queued[pkt_prio]++;
768
769 mlan_adap->callbacks.moal_semaphore_put(mlan_adap->pmoal_handle, &ralist->buf_head.plock);
770
771 mlan_adap->callbacks.moal_semaphore_put(mlan_adap->pmoal_handle, &priv->wmm.tid_tbl_ptr[pkt_prio].ra_list.plock);
772
773 return MLAN_STATUS_SUCCESS;
774 }
775
776 /* wmm enhance buffer pool management */
777 /* return NULL if wmm free list is empty */
wifi_wmm_buf_get(void)778 outbuf_t *wifi_wmm_buf_get(void)
779 {
780 outbuf_t *buf = MNULL;
781
782 mlan_adap->callbacks.moal_semaphore_get(mlan_adap->pmoal_handle, &mlan_adap->outbuf_pool.free_list.plock);
783
784 assert(mlan_adap->outbuf_pool.free_cnt >= 0);
785
786 if (mlan_adap->outbuf_pool.free_cnt == 0)
787 {
788 mlan_adap->callbacks.moal_semaphore_put(mlan_adap->pmoal_handle, &mlan_adap->outbuf_pool.free_list.plock);
789 return MNULL;
790 }
791
792 buf = (outbuf_t *)util_dequeue_list(mlan_adap->pmoal_handle, &mlan_adap->outbuf_pool.free_list, MNULL, MNULL);
793 assert(buf != MNULL);
794 mlan_adap->outbuf_pool.free_cnt--;
795
796 mlan_adap->callbacks.moal_semaphore_put(mlan_adap->pmoal_handle, &mlan_adap->outbuf_pool.free_list.plock);
797 return buf;
798 }
799
wifi_wmm_buf_put(outbuf_t * buf)800 void wifi_wmm_buf_put(outbuf_t *buf)
801 {
802 mlan_adap->callbacks.moal_semaphore_get(mlan_adap->pmoal_handle, &mlan_adap->outbuf_pool.free_list.plock);
803
804 assert(mlan_adap->outbuf_pool.free_cnt < MAX_WMM_BUF_NUM);
805
806 #if CONFIG_TX_RX_ZERO_COPY
807 /* Free driver's reference count for network buffer */
808 net_stack_buffer_free(buf->buffer);
809 #endif
810
811 util_enqueue_list_tail(mlan_adap->pmoal_handle, &mlan_adap->outbuf_pool.free_list, &buf->entry, MNULL, MNULL);
812 mlan_adap->outbuf_pool.free_cnt++;
813
814 mlan_adap->callbacks.moal_semaphore_put(mlan_adap->pmoal_handle, &mlan_adap->outbuf_pool.free_list.plock);
815 }
816
817 /* init free list, insert all buffers to free list */
wifi_wmm_buf_pool_init(uint8_t * pool)818 int wifi_wmm_buf_pool_init(uint8_t *pool)
819 {
820 int i;
821 outbuf_t *buf = MNULL;
822
823 __memset(mlan_adap, &mlan_adap->outbuf_pool, 0x00, sizeof(outbuf_pool_t));
824
825 util_init_list_head(mlan_adap->pmoal_handle, &mlan_adap->outbuf_pool.free_list, MFALSE, MNULL);
826
827 if (mlan_adap->callbacks.moal_init_semaphore(mlan_adap->pmoal_handle, "wmm_buf_pool_sem",
828 &mlan_adap->outbuf_pool.free_list.plock) != MLAN_STATUS_SUCCESS)
829 return WM_E_NOMEM;
830
831 for (i = 0; i < MAX_WMM_BUF_NUM; i++)
832 {
833 /* TODO: where to put buffer pool mgmt codes */
834 // buf = (outbuf_t *)&outbuf_arr[i][0];
835 buf = (outbuf_t *)(pool + (i * OUTBUF_WMM_LEN));
836 util_init_list(&buf->entry);
837 util_enqueue_list_tail(mlan_adap->pmoal_handle, &mlan_adap->outbuf_pool.free_list, &buf->entry, MNULL, MNULL);
838 }
839 mlan_adap->outbuf_pool.free_cnt = MAX_WMM_BUF_NUM;
840
841 return WM_SUCCESS;
842 }
843
844 /* deinit free list, should be called after all buffers are put back */
wifi_wmm_buf_pool_deinit(void)845 void wifi_wmm_buf_pool_deinit(void)
846 {
847 mlan_adap->outbuf_pool.free_cnt = 0;
848
849 mlan_adap->callbacks.moal_free_semaphore(mlan_adap->pmoal_handle, &mlan_adap->outbuf_pool.free_list.plock);
850
851 util_free_list_head(mlan_adap->pmoal_handle, &mlan_adap->outbuf_pool.free_list, MNULL);
852
853 __memset(mlan_adap, &mlan_adap->outbuf_pool, 0x00, sizeof(outbuf_pool_t));
854 }
855
856 /* wmm enhance ralist operation */
857 /* should be called inside wmm tid_tbl_ptr ra_list lock */
wlan_ralist_pkts_free_enh(mlan_private * priv,raListTbl * ra_list,t_u8 ac)858 void wlan_ralist_pkts_free_enh(mlan_private *priv, raListTbl *ra_list, t_u8 ac)
859 {
860 outbuf_t *buff = MNULL;
861
862 priv->adapter->callbacks.moal_semaphore_get(priv->adapter->pmoal_handle, &ra_list->buf_head.plock);
863
864 while ((buff = (outbuf_t *)util_peek_list(priv->adapter->pmoal_handle, &ra_list->buf_head, MNULL, MNULL)))
865 {
866 util_unlink_list(priv->adapter->pmoal_handle, &ra_list->buf_head, &buff->entry, MNULL, MNULL);
867 wifi_wmm_buf_put(buff);
868
869 priv->wmm.pkts_queued[ac]--;
870 wifi_wmm_drop_no_media(priv->bss_index);
871 ra_list->drop_count++;
872 }
873 ra_list->total_pkts = 0;
874
875 priv->adapter->callbacks.moal_semaphore_put(priv->adapter->pmoal_handle, &ra_list->buf_head.plock);
876 }
877
878 /* should be called inside wmm tid_tbl_ptr ra_list lock */
wlan_ralist_free_enh(mlan_private * priv,raListTbl * ra_list,t_u8 ac)879 static void wlan_ralist_free_enh(mlan_private *priv, raListTbl *ra_list, t_u8 ac)
880 {
881 #if CONFIG_WMM_DEBUG
882 wlan_ralist_restore_history(priv, ra_list, ac);
883 #else
884 priv->adapter->callbacks.moal_free_semaphore(priv->adapter->pmoal_handle, &ra_list->buf_head.plock);
885 #if !CONFIG_MEM_POOLS
886
887 priv->adapter->callbacks.moal_mfree(priv->adapter->pmoal_handle, (t_u8 *)ra_list);
888 #else
889 OSA_MemoryPoolFree(buf_128_MemoryPool, ra_list);
890 #endif
891 #endif
892 }
893
wlan_ralist_alloc_enh(pmlan_adapter pmadapter,t_u8 * ra)894 static raListTbl *wlan_ralist_alloc_enh(pmlan_adapter pmadapter, t_u8 *ra)
895 {
896 mlan_status ret;
897 raListTbl *ra_list = MNULL;
898
899 #if !CONFIG_MEM_POOLS
900 ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle, sizeof(raListTbl), MLAN_MEM_DEF, (t_u8 **)&ra_list);
901 if (ret != MLAN_STATUS_SUCCESS || ra_list == MNULL)
902 return MNULL;
903 #else
904 ra_list = OSA_MemoryPoolAllocate(buf_128_MemoryPool);
905 if (ra_list == MNULL)
906 {
907 return MNULL;
908 }
909
910 #endif
911
912 util_init_list((pmlan_linked_list)ra_list);
913 util_init_list_head((t_void *)pmadapter->pmoal_handle, &ra_list->buf_head, MFALSE, MNULL);
914
915 ret = pmadapter->callbacks.moal_init_semaphore(pmadapter->pmoal_handle, "buf_head_sem", &ra_list->buf_head.plock);
916 if (ret != MLAN_STATUS_SUCCESS)
917 {
918 pmadapter->callbacks.moal_mfree(pmadapter->pmoal_handle, (t_u8 *)ra_list);
919 return MNULL;
920 }
921
922 (void)__memcpy(pmadapter, ra_list->ra, ra, MLAN_MAC_ADDR_LENGTH);
923
924 ra_list->total_pkts = 0;
925 ra_list->tx_pause = 0;
926 ra_list->drop_count = 0;
927
928 wifi_d("RAList: Allocating buffers for TID %p\n", ra_list);
929
930 return ra_list;
931 }
932
wlan_ralist_add_enh(mlan_private * priv,t_u8 * ra)933 void wlan_ralist_add_enh(mlan_private *priv, t_u8 *ra)
934 {
935 int i;
936 raListTbl *ra_list = MNULL;
937 pmlan_adapter pmadapter = priv->adapter;
938
939 for (i = 0; i < MAX_AC_QUEUES; i++)
940 {
941 if ((ra_list = wlan_wmm_get_ralist_node(priv, i, ra)))
942 continue;
943
944 ra_list = wlan_ralist_alloc_enh(pmadapter, ra);
945 wifi_d("Creating RA List %p for tid %d\n", ra_list, i);
946 if (ra_list == MNULL)
947 {
948 wifi_e("Creating RA List for tid %d fail", i);
949 break;
950 }
951
952 pmadapter->callbacks.moal_semaphore_get(pmadapter->pmoal_handle, &priv->wmm.tid_tbl_ptr[i].ra_list.plock);
953
954 util_enqueue_list_tail(pmadapter->pmoal_handle, &priv->wmm.tid_tbl_ptr[i].ra_list, (pmlan_linked_list)ra_list,
955 MNULL, MNULL);
956
957 if (priv->wmm.tid_tbl_ptr[i].ra_list_curr == MNULL)
958 priv->wmm.tid_tbl_ptr[i].ra_list_curr = ra_list;
959
960 pmadapter->callbacks.moal_semaphore_put(pmadapter->pmoal_handle, &priv->wmm.tid_tbl_ptr[i].ra_list.plock);
961 }
962 }
963
wlan_ralist_update_enh(mlan_private * priv,t_u8 * old_ra,t_u8 * new_ra)964 int wlan_ralist_update_enh(mlan_private *priv, t_u8 *old_ra, t_u8 *new_ra)
965 {
966 int i;
967 int update_count = 0;
968 raListTbl *ra_list = MNULL;
969 #if CONFIG_WMM_DEBUG
970 raListTbl *hist_ra_list = MNULL;
971 #endif
972
973 for (i = 0; i < MAX_AC_QUEUES; i++)
974 {
975 priv->adapter->callbacks.moal_semaphore_get(priv->adapter->pmoal_handle,
976 &priv->wmm.tid_tbl_ptr[i].ra_list.plock);
977
978 ra_list = wlan_wmm_get_ralist_node(priv, i, old_ra);
979 if (ra_list == MNULL)
980 {
981 priv->adapter->callbacks.moal_semaphore_put(priv->adapter->pmoal_handle,
982 &priv->wmm.tid_tbl_ptr[i].ra_list.plock);
983 continue;
984 }
985
986 update_count++;
987
988 wlan_ralist_pkts_free_enh(priv, ra_list, i);
989 ra_list->tx_pause = MFALSE;
990
991 (void)__memcpy(priv->adapter, ra_list->ra, new_ra, MLAN_MAC_ADDR_LENGTH);
992
993 #if CONFIG_WMM_DEBUG
994 hist_ra_list = wlan_ralist_alloc_enh(priv->adapter, old_ra);
995 if (hist_ra_list != MNULL)
996 {
997 hist_ra_list->drop_count = ra_list->drop_count;
998 wlan_ralist_free_enh(priv, hist_ra_list, i);
999 }
1000 #endif
1001
1002 priv->adapter->callbacks.moal_semaphore_put(priv->adapter->pmoal_handle,
1003 &priv->wmm.tid_tbl_ptr[i].ra_list.plock);
1004 }
1005
1006 return update_count;
1007 }
1008
wlan_ralist_del_enh(mlan_private * priv,t_u8 * ra)1009 void wlan_ralist_del_enh(mlan_private *priv, t_u8 *ra)
1010 {
1011 int i;
1012 pmlan_adapter pmadapter = priv->adapter;
1013 raListTbl *ra_list = MNULL;
1014
1015 for (i = 0; i < MAX_AC_QUEUES; i++)
1016 {
1017 pmadapter->callbacks.moal_semaphore_get(pmadapter->pmoal_handle, &priv->wmm.tid_tbl_ptr[i].ra_list.plock);
1018
1019 ra_list = wlan_wmm_get_ralist_node(priv, i, ra);
1020 if (ra_list == MNULL)
1021 {
1022 pmadapter->callbacks.moal_semaphore_put(pmadapter->pmoal_handle, &priv->wmm.tid_tbl_ptr[i].ra_list.plock);
1023 continue;
1024 }
1025
1026 wlan_ralist_pkts_free_enh(priv, ra_list, i);
1027
1028 util_unlink_list(pmadapter->pmoal_handle, &priv->wmm.tid_tbl_ptr[i].ra_list, (pmlan_linked_list)ra_list, MNULL,
1029 MNULL);
1030
1031 if (priv->wmm.tid_tbl_ptr[i].ra_list_curr == ra_list)
1032 priv->wmm.tid_tbl_ptr[i].ra_list_curr = (raListTbl *)&priv->wmm.tid_tbl_ptr[i].ra_list;
1033
1034 wlan_ralist_free_enh(priv, ra_list, i);
1035
1036 pmadapter->callbacks.moal_semaphore_put(pmadapter->pmoal_handle, &priv->wmm.tid_tbl_ptr[i].ra_list.plock);
1037 }
1038 }
1039
wlan_ralist_del_all_enh(mlan_private * priv)1040 void wlan_ralist_del_all_enh(mlan_private *priv)
1041 {
1042 int i;
1043 raListTbl *ra_list = MNULL;
1044 pmlan_adapter pmadapter = priv->adapter;
1045
1046 for (i = 0; i < MAX_AC_QUEUES; i++)
1047 {
1048 priv->adapter->callbacks.moal_semaphore_get(priv->adapter->pmoal_handle,
1049 &priv->wmm.tid_tbl_ptr[i].ra_list.plock);
1050
1051 while ((ra_list = (raListTbl *)util_peek_list(pmadapter->pmoal_handle, &priv->wmm.tid_tbl_ptr[i].ra_list, MNULL,
1052 MNULL)))
1053 {
1054 util_unlink_list(pmadapter->pmoal_handle, &priv->wmm.tid_tbl_ptr[i].ra_list, (pmlan_linked_list)ra_list,
1055 MNULL, MNULL);
1056
1057 wlan_ralist_pkts_free_enh(priv, ra_list, i);
1058
1059 wlan_ralist_free_enh(priv, ra_list, i);
1060 }
1061
1062 /* do not reinit list lock, so use util_init_list instead of util_init_list_head */
1063 util_init_list((pmlan_linked_list)&priv->wmm.tid_tbl_ptr[i].ra_list);
1064 priv->wmm.tid_tbl_ptr[i].ra_list_curr = MNULL;
1065 priv->wmm.pkts_queued[i] = 0;
1066
1067 priv->adapter->callbacks.moal_semaphore_put(priv->adapter->pmoal_handle,
1068 &priv->wmm.tid_tbl_ptr[i].ra_list.plock);
1069 }
1070 }
1071
wlan_ralist_deinit_enh(mlan_private * priv)1072 void wlan_ralist_deinit_enh(mlan_private *priv)
1073 {
1074 int i;
1075
1076 /* already del all ralists in wlan_clean_txrx */
1077 // wlan_ralist_del_all_enh(priv);
1078
1079 for (i = 0; i < MAX_AC_QUEUES; i++)
1080 {
1081 /* free ralist lock */
1082 priv->adapter->callbacks.moal_free_semaphore(priv->adapter->pmoal_handle,
1083 &priv->wmm.tid_tbl_ptr[i].ra_list.plock);
1084
1085 /* deinit ralists table */
1086 util_free_list_head(priv->adapter->pmoal_handle, &priv->wmm.tid_tbl_ptr[i].ra_list, MNULL);
1087 }
1088 }
1089
1090 /* debug statistics */
wifi_wmm_drop_err_mem(const uint8_t interface)1091 void wifi_wmm_drop_err_mem(const uint8_t interface)
1092 {
1093 if (interface == MLAN_BSS_TYPE_STA)
1094 mlan_adap->priv[0]->driver_error_cnt.tx_err_mem++;
1095 else if (interface == MLAN_BSS_TYPE_UAP)
1096 mlan_adap->priv[1]->driver_error_cnt.tx_err_mem++;
1097 }
1098
wifi_wmm_drop_no_media(const uint8_t interface)1099 void wifi_wmm_drop_no_media(const uint8_t interface)
1100 {
1101 if (interface == MLAN_BSS_TYPE_STA)
1102 mlan_adap->priv[0]->driver_error_cnt.tx_no_media++;
1103 else if (interface == MLAN_BSS_TYPE_UAP)
1104 mlan_adap->priv[1]->driver_error_cnt.tx_no_media++;
1105 }
1106
wifi_wmm_drop_retried_drop(const uint8_t interface)1107 void wifi_wmm_drop_retried_drop(const uint8_t interface)
1108 {
1109 if (interface == MLAN_BSS_TYPE_STA)
1110 mlan_adap->priv[0]->driver_error_cnt.tx_wmm_retried_drop++;
1111 else if (interface == MLAN_BSS_TYPE_UAP)
1112 mlan_adap->priv[1]->driver_error_cnt.tx_wmm_retried_drop++;
1113 }
1114
wifi_wmm_drop_pause_drop(const uint8_t interface)1115 void wifi_wmm_drop_pause_drop(const uint8_t interface)
1116 {
1117 if (interface == MLAN_BSS_TYPE_STA)
1118 mlan_adap->priv[0]->driver_error_cnt.tx_wmm_pause_drop++;
1119 else if (interface == MLAN_BSS_TYPE_UAP)
1120 mlan_adap->priv[1]->driver_error_cnt.tx_wmm_pause_drop++;
1121 }
1122
wifi_wmm_drop_pause_replaced(const uint8_t interface)1123 void wifi_wmm_drop_pause_replaced(const uint8_t interface)
1124 {
1125 if (interface == MLAN_BSS_TYPE_STA)
1126 mlan_adap->priv[0]->driver_error_cnt.tx_wmm_pause_replaced++;
1127 else if (interface == MLAN_BSS_TYPE_UAP)
1128 mlan_adap->priv[1]->driver_error_cnt.tx_wmm_pause_replaced++;
1129 }
1130
wlan_get_bypass_lock(uint8_t interface)1131 void wlan_get_bypass_lock(uint8_t interface)
1132 {
1133 pmlan_private priv = mlan_adap->priv[interface];
1134
1135 mlan_adap->callbacks.moal_semaphore_get(mlan_adap->pmoal_handle, &priv->bypass_txq.plock);
1136 }
1137
wlan_put_bypass_lock(uint8_t interface)1138 void wlan_put_bypass_lock(uint8_t interface)
1139 {
1140 pmlan_private priv = mlan_adap->priv[interface];
1141
1142 mlan_adap->callbacks.moal_semaphore_put(mlan_adap->pmoal_handle, &priv->bypass_txq.plock);
1143 }
1144
wlan_add_buf_bypass_txq(const uint8_t * buffer,const uint8_t interface)1145 void wlan_add_buf_bypass_txq(const uint8_t *buffer, const uint8_t interface)
1146 {
1147 pmlan_private priv = mlan_adap->priv[interface];
1148
1149 wlan_get_bypass_lock(interface);
1150
1151 util_enqueue_list_tail(mlan_adap->pmoal_handle, &priv->bypass_txq, (mlan_linked_list *)buffer, MNULL, MNULL);
1152 priv->bypass_txq_cnt++;
1153
1154 wlan_put_bypass_lock(interface);
1155 }
1156
wlan_bypass_txq_empty(uint8_t interface)1157 t_u8 wlan_bypass_txq_empty(uint8_t interface)
1158 {
1159 return (mlan_adap->priv[interface]->bypass_txq_cnt) ? MFALSE : MTRUE;
1160 }
1161
wifi_bypass_txq_init(void)1162 int wifi_bypass_txq_init(void)
1163 {
1164 pmlan_private priv = NULL;
1165 int i;
1166
1167 for (i = 0; i < mlan_adap->priv_num; ++i)
1168 {
1169 priv = mlan_adap->priv[i];
1170 if (priv != MNULL)
1171 {
1172 /* Initialize bypass_txq */
1173 util_init_list_head((t_void *)mlan_adap->pmoal_handle, &priv->bypass_txq, MFALSE, MNULL);
1174 priv->bypass_txq_cnt = 0;
1175
1176 if (mlan_adap->callbacks.moal_init_semaphore(mlan_adap->pmoal_handle, "bypass_txq_sem",
1177 &priv->bypass_txq.plock) != MLAN_STATUS_SUCCESS)
1178 return WM_E_NOMEM;
1179 }
1180 }
1181
1182 return WM_SUCCESS;
1183 }
1184
wlan_cleanup_bypass_txq(uint8_t interface)1185 void wlan_cleanup_bypass_txq(uint8_t interface)
1186 {
1187 bypass_outbuf_t *buf;
1188 pmlan_private priv = mlan_adap->priv[interface];
1189
1190 /*Free hold buff*/
1191 while (!wlan_bypass_txq_empty(interface))
1192 {
1193 wlan_get_bypass_lock(interface);
1194
1195 buf = (bypass_outbuf_t *)util_dequeue_list(mlan_adap->pmoal_handle, &priv->bypass_txq, MNULL, MNULL);
1196 priv->bypass_txq_cnt--;
1197 #if !CONFIG_MEM_POOLS
1198 OSA_MemoryFree(buf);
1199 #else
1200 OSA_MemoryPoolFree(buf_1536_MemoryPool, buf);
1201 #endif
1202
1203 wlan_put_bypass_lock(interface);
1204 }
1205 }
1206
wifi_bypass_txq_deinit(void)1207 void wifi_bypass_txq_deinit(void)
1208 {
1209 pmlan_private priv = NULL;
1210 int i;
1211
1212 for (i = 0; i < mlan_adap->priv_num; ++i)
1213 {
1214 priv = mlan_adap->priv[i];
1215 if (priv != MNULL)
1216 {
1217 wlan_cleanup_bypass_txq(i);
1218
1219 mlan_adap->callbacks.moal_free_semaphore(mlan_adap->pmoal_handle, &priv->bypass_txq.plock);
1220 /* Deinit bypass_txq */
1221 util_free_list_head(mlan_adap->pmoal_handle, &priv->bypass_txq, MNULL);
1222 priv->bypass_txq_cnt = 0;
1223 }
1224 }
1225 }
1226 #endif /* CONFIG_WMM */
1227