1*4882a593Smuzhiyun /** @file mlan_wmm.c
2*4882a593Smuzhiyun *
3*4882a593Smuzhiyun * @brief This file contains functions for WMM.
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * Copyright 2008-2021 NXP
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * This software file (the File) is distributed by NXP
9*4882a593Smuzhiyun * under the terms of the GNU General Public License Version 2, June 1991
10*4882a593Smuzhiyun * (the License). You may use, redistribute and/or modify the File in
11*4882a593Smuzhiyun * accordance with the terms and conditions of the License, a copy of which
12*4882a593Smuzhiyun * is available by writing to the Free Software Foundation, Inc.,
13*4882a593Smuzhiyun * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
14*4882a593Smuzhiyun * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
15*4882a593Smuzhiyun *
16*4882a593Smuzhiyun * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
17*4882a593Smuzhiyun * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
18*4882a593Smuzhiyun * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
19*4882a593Smuzhiyun * this warranty disclaimer.
20*4882a593Smuzhiyun *
21*4882a593Smuzhiyun */
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun /********************************************************
24*4882a593Smuzhiyun Change log:
25*4882a593Smuzhiyun 10/24/2008: initial version
26*4882a593Smuzhiyun ********************************************************/
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun #include "mlan.h"
29*4882a593Smuzhiyun #ifdef STA_SUPPORT
30*4882a593Smuzhiyun #include "mlan_join.h"
31*4882a593Smuzhiyun #endif
32*4882a593Smuzhiyun #include "mlan_util.h"
33*4882a593Smuzhiyun #include "mlan_fw.h"
34*4882a593Smuzhiyun #include "mlan_main.h"
35*4882a593Smuzhiyun #include "mlan_wmm.h"
36*4882a593Smuzhiyun #include "mlan_11n.h"
37*4882a593Smuzhiyun #include "mlan_11ax.h"
38*4882a593Smuzhiyun #ifdef SDIO
39*4882a593Smuzhiyun #include "mlan_sdio.h"
40*4882a593Smuzhiyun #endif /* SDIO */
41*4882a593Smuzhiyun #ifdef PCIE
42*4882a593Smuzhiyun #include "mlan_pcie.h"
43*4882a593Smuzhiyun #endif /* PCIE */
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun /********************************************************
46*4882a593Smuzhiyun Local Variables
47*4882a593Smuzhiyun ********************************************************/
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun /** WMM information IE */
50*4882a593Smuzhiyun static const t_u8 wmm_info_ie[] = {WMM_IE, 0x07, 0x00, 0x50, 0xf2,
51*4882a593Smuzhiyun 0x02, 0x00, 0x01, 0x00};
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun /** Type enumeration of WMM AC_QUEUES */
54*4882a593Smuzhiyun typedef MLAN_PACK_START enum _wmm_ac_e {
55*4882a593Smuzhiyun AC_BE,
56*4882a593Smuzhiyun AC_BK,
57*4882a593Smuzhiyun AC_VI,
58*4882a593Smuzhiyun AC_VO
59*4882a593Smuzhiyun } MLAN_PACK_END wmm_ac_e;
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun /**
62*4882a593Smuzhiyun * AC Priorities go from AC_BK to AC_VO. The ACI enumeration for AC_BK (1)
63*4882a593Smuzhiyun * is higher than the enumeration for AC_BE (0); hence the needed
64*4882a593Smuzhiyun * mapping conversion for wmm AC to priority Queue Index
65*4882a593Smuzhiyun */
66*4882a593Smuzhiyun static const t_u8 wmm_aci_to_qidx_map[] = {WMM_AC_BE, WMM_AC_BK, WMM_AC_VI,
67*4882a593Smuzhiyun WMM_AC_VO};
68*4882a593Smuzhiyun /**
69*4882a593Smuzhiyun * This table will be used to store the tid values based on ACs.
70*4882a593Smuzhiyun * It is initialized to default values per TID.
71*4882a593Smuzhiyun */
72*4882a593Smuzhiyun static t_u8 tos_to_tid[] = {
73*4882a593Smuzhiyun /* TID DSCP_P2 DSCP_P1 DSCP_P0 WMM_AC */
74*4882a593Smuzhiyun 0x01, /* 0 1 0 AC_BK */
75*4882a593Smuzhiyun 0x02, /* 0 0 0 AC_BK */
76*4882a593Smuzhiyun 0x00, /* 0 0 1 AC_BE */
77*4882a593Smuzhiyun 0x03, /* 0 1 1 AC_BE */
78*4882a593Smuzhiyun 0x04, /* 1 0 0 AC_VI */
79*4882a593Smuzhiyun 0x05, /* 1 0 1 AC_VI */
80*4882a593Smuzhiyun 0x06, /* 1 1 0 AC_VO */
81*4882a593Smuzhiyun 0x07 /* 1 1 1 AC_VO */
82*4882a593Smuzhiyun };
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun /**
85*4882a593Smuzhiyun * This table inverses the tos_to_tid operation to get a priority
86*4882a593Smuzhiyun * which is in sequential order, and can be compared.
87*4882a593Smuzhiyun * Use this to compare the priority of two different TIDs.
88*4882a593Smuzhiyun */
89*4882a593Smuzhiyun t_u8 tos_to_tid_inv[] = {0x02, /* from tos_to_tid[2] = 0 */
90*4882a593Smuzhiyun 0x00, /* from tos_to_tid[0] = 1 */
91*4882a593Smuzhiyun 0x01, /* from tos_to_tid[1] = 2 */
92*4882a593Smuzhiyun 0x03, 0x04, 0x05, 0x06, 0x07};
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun /**
95*4882a593Smuzhiyun * This table will provide the tid value for given ac. This table does not
96*4882a593Smuzhiyun * change and will be used to copy back the default values to tos_to_tid in
97*4882a593Smuzhiyun * case of disconnect.
98*4882a593Smuzhiyun */
99*4882a593Smuzhiyun t_u8 ac_to_tid[4][2] = {{1, 2}, {0, 3}, {4, 5}, {6, 7}};
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun /* Map of TOS UP values to WMM AC */
102*4882a593Smuzhiyun static const mlan_wmm_ac_e tos_to_ac[] = {WMM_AC_BE, WMM_AC_BK, WMM_AC_BK,
103*4882a593Smuzhiyun WMM_AC_BE, WMM_AC_VI, WMM_AC_VI,
104*4882a593Smuzhiyun WMM_AC_VO, WMM_AC_VO};
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun raListTbl *wlan_wmm_get_ralist_node(pmlan_private priv, t_u8 tid,
107*4882a593Smuzhiyun t_u8 *ra_addr);
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun /********************************************************
110*4882a593Smuzhiyun Local Functions
111*4882a593Smuzhiyun ********************************************************/
112*4882a593Smuzhiyun #ifdef DEBUG_LEVEL2
113*4882a593Smuzhiyun /**
114*4882a593Smuzhiyun * @brief Debug print function to display the priority parameters for a WMM AC
115*4882a593Smuzhiyun *
116*4882a593Smuzhiyun * @param pac_param Pointer to the AC parameters to display
117*4882a593Smuzhiyun *
118*4882a593Smuzhiyun * @return N/A
119*4882a593Smuzhiyun */
120*4882a593Smuzhiyun static void
wlan_wmm_ac_debug_print(const IEEEtypes_WmmAcParameters_t * pac_param)121*4882a593Smuzhiyun wlan_wmm_ac_debug_print(const IEEEtypes_WmmAcParameters_t *pac_param)
122*4882a593Smuzhiyun {
123*4882a593Smuzhiyun const char *ac_str[] = {"BK", "BE", "VI", "VO"};
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun ENTER();
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun PRINTM(MINFO,
128*4882a593Smuzhiyun "WMM AC_%s: ACI=%d, ACM=%d, Aifsn=%d, "
129*4882a593Smuzhiyun "EcwMin=%d, EcwMax=%d, TxopLimit=%d\n",
130*4882a593Smuzhiyun ac_str[wmm_aci_to_qidx_map[pac_param->aci_aifsn.aci]],
131*4882a593Smuzhiyun pac_param->aci_aifsn.aci, pac_param->aci_aifsn.acm,
132*4882a593Smuzhiyun pac_param->aci_aifsn.aifsn, pac_param->ecw.ecw_min,
133*4882a593Smuzhiyun pac_param->ecw.ecw_max,
134*4882a593Smuzhiyun wlan_le16_to_cpu(pac_param->tx_op_limit));
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun LEAVE();
137*4882a593Smuzhiyun }
138*4882a593Smuzhiyun /** Print the WMM AC for debug purpose */
139*4882a593Smuzhiyun #define PRINTM_AC(pac_param) wlan_wmm_ac_debug_print(pac_param)
140*4882a593Smuzhiyun #else
141*4882a593Smuzhiyun /** Print the WMM AC for debug purpose */
142*4882a593Smuzhiyun #define PRINTM_AC(pac_param)
143*4882a593Smuzhiyun #endif
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun /**
146*4882a593Smuzhiyun * @brief Allocate route address
147*4882a593Smuzhiyun *
148*4882a593Smuzhiyun * @param pmadapter Pointer to the mlan_adapter structure
149*4882a593Smuzhiyun * @param ra Pointer to the route address
150*4882a593Smuzhiyun *
151*4882a593Smuzhiyun * @return ra_list
152*4882a593Smuzhiyun */
wlan_wmm_allocate_ralist_node(pmlan_adapter pmadapter,t_u8 * ra)153*4882a593Smuzhiyun static raListTbl *wlan_wmm_allocate_ralist_node(pmlan_adapter pmadapter,
154*4882a593Smuzhiyun t_u8 *ra)
155*4882a593Smuzhiyun {
156*4882a593Smuzhiyun raListTbl *ra_list = MNULL;
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun ENTER();
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun if (pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
161*4882a593Smuzhiyun sizeof(raListTbl), MLAN_MEM_DEF,
162*4882a593Smuzhiyun (t_u8 **)&ra_list)) {
163*4882a593Smuzhiyun PRINTM(MERROR, "Fail to allocate ra_list\n");
164*4882a593Smuzhiyun goto done;
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun util_init_list((pmlan_linked_list)ra_list);
167*4882a593Smuzhiyun util_init_list_head((t_void *)pmadapter->pmoal_handle,
168*4882a593Smuzhiyun &ra_list->buf_head, MFALSE,
169*4882a593Smuzhiyun pmadapter->callbacks.moal_init_lock);
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun memcpy_ext(pmadapter, ra_list->ra, ra, MLAN_MAC_ADDR_LENGTH,
172*4882a593Smuzhiyun MLAN_MAC_ADDR_LENGTH);
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun ra_list->del_ba_count = 0;
175*4882a593Smuzhiyun ra_list->total_pkts = 0;
176*4882a593Smuzhiyun ra_list->tx_pause = 0;
177*4882a593Smuzhiyun PRINTM(MINFO, "RAList: Allocating buffers for TID %p\n", ra_list);
178*4882a593Smuzhiyun done:
179*4882a593Smuzhiyun LEAVE();
180*4882a593Smuzhiyun return ra_list;
181*4882a593Smuzhiyun }
182*4882a593Smuzhiyun
183*4882a593Smuzhiyun /**
184*4882a593Smuzhiyun * @brief Add packet to TDLS pending TX queue
185*4882a593Smuzhiyun *
186*4882a593Smuzhiyun * @param priv A pointer to mlan_private
187*4882a593Smuzhiyun * @param pmbuf Pointer to the mlan_buffer data struct
188*4882a593Smuzhiyun *
189*4882a593Smuzhiyun * @return N/A
190*4882a593Smuzhiyun */
wlan_add_buf_tdls_txqueue(pmlan_private priv,pmlan_buffer pmbuf)191*4882a593Smuzhiyun static t_void wlan_add_buf_tdls_txqueue(pmlan_private priv, pmlan_buffer pmbuf)
192*4882a593Smuzhiyun {
193*4882a593Smuzhiyun mlan_adapter *pmadapter = priv->adapter;
194*4882a593Smuzhiyun ENTER();
195*4882a593Smuzhiyun util_enqueue_list_tail(pmadapter->pmoal_handle, &priv->tdls_pending_txq,
196*4882a593Smuzhiyun (pmlan_linked_list)pmbuf,
197*4882a593Smuzhiyun pmadapter->callbacks.moal_spin_lock,
198*4882a593Smuzhiyun pmadapter->callbacks.moal_spin_unlock);
199*4882a593Smuzhiyun LEAVE();
200*4882a593Smuzhiyun }
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun /**
203*4882a593Smuzhiyun * @brief Clean up the tdls pending TX queue
204*4882a593Smuzhiyun *
205*4882a593Smuzhiyun * @param priv A pointer to mlan_private
206*4882a593Smuzhiyun *
207*4882a593Smuzhiyun * @return N/A
208*4882a593Smuzhiyun */
wlan_cleanup_tdls_txq(pmlan_private priv)209*4882a593Smuzhiyun static t_void wlan_cleanup_tdls_txq(pmlan_private priv)
210*4882a593Smuzhiyun {
211*4882a593Smuzhiyun pmlan_buffer pmbuf;
212*4882a593Smuzhiyun mlan_adapter *pmadapter = priv->adapter;
213*4882a593Smuzhiyun ENTER();
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
216*4882a593Smuzhiyun priv->tdls_pending_txq.plock);
217*4882a593Smuzhiyun while ((pmbuf = (pmlan_buffer)util_peek_list(pmadapter->pmoal_handle,
218*4882a593Smuzhiyun &priv->tdls_pending_txq,
219*4882a593Smuzhiyun MNULL, MNULL))) {
220*4882a593Smuzhiyun util_unlink_list(pmadapter->pmoal_handle,
221*4882a593Smuzhiyun &priv->tdls_pending_txq,
222*4882a593Smuzhiyun (pmlan_linked_list)pmbuf, MNULL, MNULL);
223*4882a593Smuzhiyun wlan_write_data_complete(pmadapter, pmbuf, MLAN_STATUS_FAILURE);
224*4882a593Smuzhiyun }
225*4882a593Smuzhiyun pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
226*4882a593Smuzhiyun priv->tdls_pending_txq.plock);
227*4882a593Smuzhiyun LEAVE();
228*4882a593Smuzhiyun }
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun /**
231*4882a593Smuzhiyun * @brief Map ACs to TID
232*4882a593Smuzhiyun *
233*4882a593Smuzhiyun * @param priv Pointer to the mlan_private driver data struct
234*4882a593Smuzhiyun * @param queue_priority Queue_priority structure
235*4882a593Smuzhiyun *
236*4882a593Smuzhiyun * @return N/A
237*4882a593Smuzhiyun */
wlan_wmm_queue_priorities_tid(pmlan_private priv,t_u8 queue_priority[])238*4882a593Smuzhiyun static void wlan_wmm_queue_priorities_tid(pmlan_private priv,
239*4882a593Smuzhiyun t_u8 queue_priority[])
240*4882a593Smuzhiyun {
241*4882a593Smuzhiyun int i;
242*4882a593Smuzhiyun
243*4882a593Smuzhiyun ENTER();
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun for (i = 0; i < 4; ++i) {
246*4882a593Smuzhiyun tos_to_tid[7 - (i * 2)] = ac_to_tid[queue_priority[i]][1];
247*4882a593Smuzhiyun tos_to_tid[6 - (i * 2)] = ac_to_tid[queue_priority[i]][0];
248*4882a593Smuzhiyun }
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun for (i = 0; i < MAX_NUM_TID; i++)
251*4882a593Smuzhiyun tos_to_tid_inv[tos_to_tid[i]] = (t_u8)i;
252*4882a593Smuzhiyun
253*4882a593Smuzhiyun /* in case priorities have changed, force highest priority so
254*4882a593Smuzhiyun * next packet will check from top to re-establish the highest
255*4882a593Smuzhiyun */
256*4882a593Smuzhiyun util_scalar_write(priv->adapter->pmoal_handle,
257*4882a593Smuzhiyun &priv->wmm.highest_queued_prio, HIGH_PRIO_TID,
258*4882a593Smuzhiyun priv->adapter->callbacks.moal_spin_lock,
259*4882a593Smuzhiyun priv->adapter->callbacks.moal_spin_unlock);
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun LEAVE();
262*4882a593Smuzhiyun }
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun /**
265*4882a593Smuzhiyun * @brief Evaluate whether or not an AC is to be downgraded
266*4882a593Smuzhiyun *
267*4882a593Smuzhiyun * @param priv Pointer to the mlan_private driver data struct
268*4882a593Smuzhiyun * @param eval_ac AC to evaluate for downgrading
269*4882a593Smuzhiyun *
270*4882a593Smuzhiyun * @return WMM AC The eval_ac traffic is to be sent on.
271*4882a593Smuzhiyun */
wlan_wmm_eval_downgrade_ac(pmlan_private priv,mlan_wmm_ac_e eval_ac)272*4882a593Smuzhiyun static mlan_wmm_ac_e wlan_wmm_eval_downgrade_ac(pmlan_private priv,
273*4882a593Smuzhiyun mlan_wmm_ac_e eval_ac)
274*4882a593Smuzhiyun {
275*4882a593Smuzhiyun int down_ac;
276*4882a593Smuzhiyun mlan_wmm_ac_e ret_ac;
277*4882a593Smuzhiyun WmmAcStatus_t *pac_status;
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun ENTER();
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun pac_status = &priv->wmm.ac_status[eval_ac];
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun if (pac_status->disabled == MFALSE) {
284*4882a593Smuzhiyun LEAVE();
285*4882a593Smuzhiyun /* Okay to use this AC, its enabled */
286*4882a593Smuzhiyun return eval_ac;
287*4882a593Smuzhiyun }
288*4882a593Smuzhiyun
289*4882a593Smuzhiyun /* Setup a default return value of the lowest priority */
290*4882a593Smuzhiyun ret_ac = WMM_AC_BK;
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun /*
293*4882a593Smuzhiyun * Find the highest AC that is enabled and does not require admission
294*4882a593Smuzhiyun * control. The spec disallows downgrading to an AC, which is enabled
295*4882a593Smuzhiyun * due to a completed admission control. Unadmitted traffic is not
296*4882a593Smuzhiyun * to be sent on an AC with admitted traffic.
297*4882a593Smuzhiyun */
298*4882a593Smuzhiyun for (down_ac = WMM_AC_BK; down_ac < eval_ac; down_ac++) {
299*4882a593Smuzhiyun pac_status = &priv->wmm.ac_status[down_ac];
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun if ((pac_status->disabled == MFALSE) &&
302*4882a593Smuzhiyun (pac_status->flow_required == MFALSE))
303*4882a593Smuzhiyun /* AC is enabled and does not require admission control
304*4882a593Smuzhiyun */
305*4882a593Smuzhiyun ret_ac = (mlan_wmm_ac_e)down_ac;
306*4882a593Smuzhiyun }
307*4882a593Smuzhiyun
308*4882a593Smuzhiyun LEAVE();
309*4882a593Smuzhiyun return ret_ac;
310*4882a593Smuzhiyun }
311*4882a593Smuzhiyun
312*4882a593Smuzhiyun /**
313*4882a593Smuzhiyun * @brief Convert the IP TOS field to an WMM AC Queue assignment
314*4882a593Smuzhiyun *
315*4882a593Smuzhiyun * @param pmadapter A pointer to mlan_adapter structure
316*4882a593Smuzhiyun * @param tos IP TOS field
317*4882a593Smuzhiyun *
318*4882a593Smuzhiyun * @return WMM AC Queue mapping of the IP TOS field
319*4882a593Smuzhiyun */
wlan_wmm_convert_tos_to_ac(pmlan_adapter pmadapter,t_u32 tos)320*4882a593Smuzhiyun static INLINE mlan_wmm_ac_e wlan_wmm_convert_tos_to_ac(pmlan_adapter pmadapter,
321*4882a593Smuzhiyun t_u32 tos)
322*4882a593Smuzhiyun {
323*4882a593Smuzhiyun ENTER();
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun if (tos >= NELEMENTS(tos_to_ac)) {
326*4882a593Smuzhiyun LEAVE();
327*4882a593Smuzhiyun return WMM_AC_BE;
328*4882a593Smuzhiyun }
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun LEAVE();
331*4882a593Smuzhiyun return tos_to_ac[tos];
332*4882a593Smuzhiyun }
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun /**
335*4882a593Smuzhiyun * @brief Evaluate a given TID and downgrade it to a lower TID if the
336*4882a593Smuzhiyun * WMM Parameter IE received from the AP indicates that the AP
337*4882a593Smuzhiyun * is disabled (due to call admission control (ACM bit). Mapping
338*4882a593Smuzhiyun * of TID to AC is taken care internally
339*4882a593Smuzhiyun *
340*4882a593Smuzhiyun * @param priv Pointer to the mlan_private data struct
341*4882a593Smuzhiyun * @param tid tid to evaluate for downgrading
342*4882a593Smuzhiyun *
343*4882a593Smuzhiyun * @return Same tid as input if downgrading not required or
344*4882a593Smuzhiyun * the tid the traffic for the given tid should be downgraded to
345*4882a593Smuzhiyun */
wlan_wmm_downgrade_tid(pmlan_private priv,t_u32 tid)346*4882a593Smuzhiyun static INLINE t_u8 wlan_wmm_downgrade_tid(pmlan_private priv, t_u32 tid)
347*4882a593Smuzhiyun {
348*4882a593Smuzhiyun mlan_wmm_ac_e ac_down;
349*4882a593Smuzhiyun pmlan_adapter pmadapter = priv->adapter;
350*4882a593Smuzhiyun
351*4882a593Smuzhiyun ENTER();
352*4882a593Smuzhiyun
353*4882a593Smuzhiyun ac_down = priv->wmm.ac_down_graded_vals[wlan_wmm_convert_tos_to_ac(
354*4882a593Smuzhiyun pmadapter, tid)];
355*4882a593Smuzhiyun LEAVE();
356*4882a593Smuzhiyun /*
357*4882a593Smuzhiyun * Send the index to tid array, picking from the array will be
358*4882a593Smuzhiyun * taken care by dequeuing function
359*4882a593Smuzhiyun */
360*4882a593Smuzhiyun if (tid == 1 || tid == 2)
361*4882a593Smuzhiyun return ac_to_tid[ac_down][(tid + 1) % 2];
362*4882a593Smuzhiyun else if (tid >= MAX_NUM_TID)
363*4882a593Smuzhiyun return ac_to_tid[ac_down][0];
364*4882a593Smuzhiyun else
365*4882a593Smuzhiyun return ac_to_tid[ac_down][tid % 2];
366*4882a593Smuzhiyun }
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun /**
369*4882a593Smuzhiyun * @brief Delete packets in RA node
370*4882a593Smuzhiyun *
371*4882a593Smuzhiyun * @param priv Pointer to the mlan_private driver data struct
372*4882a593Smuzhiyun * @param ra_list Pointer to raListTbl
373*4882a593Smuzhiyun *
374*4882a593Smuzhiyun * @return N/A
375*4882a593Smuzhiyun */
wlan_wmm_del_pkts_in_ralist_node(pmlan_private priv,raListTbl * ra_list)376*4882a593Smuzhiyun static INLINE void wlan_wmm_del_pkts_in_ralist_node(pmlan_private priv,
377*4882a593Smuzhiyun raListTbl *ra_list)
378*4882a593Smuzhiyun {
379*4882a593Smuzhiyun pmlan_buffer pmbuf;
380*4882a593Smuzhiyun pmlan_adapter pmadapter = priv->adapter;
381*4882a593Smuzhiyun
382*4882a593Smuzhiyun ENTER();
383*4882a593Smuzhiyun while ((pmbuf = (pmlan_buffer)util_peek_list(pmadapter->pmoal_handle,
384*4882a593Smuzhiyun &ra_list->buf_head, MNULL,
385*4882a593Smuzhiyun MNULL))) {
386*4882a593Smuzhiyun util_unlink_list(pmadapter->pmoal_handle, &ra_list->buf_head,
387*4882a593Smuzhiyun (pmlan_linked_list)pmbuf, MNULL, MNULL);
388*4882a593Smuzhiyun wlan_write_data_complete(pmadapter, pmbuf, MLAN_STATUS_FAILURE);
389*4882a593Smuzhiyun }
390*4882a593Smuzhiyun util_free_list_head((t_void *)pmadapter->pmoal_handle,
391*4882a593Smuzhiyun &ra_list->buf_head,
392*4882a593Smuzhiyun pmadapter->callbacks.moal_free_lock);
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun LEAVE();
395*4882a593Smuzhiyun }
396*4882a593Smuzhiyun
397*4882a593Smuzhiyun /**
398*4882a593Smuzhiyun * @brief Delete packets in RA list
399*4882a593Smuzhiyun *
400*4882a593Smuzhiyun * @param priv Pointer to the mlan_private driver data struct
401*4882a593Smuzhiyun * @param ra_list_head ra list header
402*4882a593Smuzhiyun *
403*4882a593Smuzhiyun * @return N/A
404*4882a593Smuzhiyun */
wlan_wmm_del_pkts_in_ralist(pmlan_private priv,mlan_list_head * ra_list_head)405*4882a593Smuzhiyun static INLINE void wlan_wmm_del_pkts_in_ralist(pmlan_private priv,
406*4882a593Smuzhiyun mlan_list_head *ra_list_head)
407*4882a593Smuzhiyun {
408*4882a593Smuzhiyun raListTbl *ra_list;
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun ENTER();
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun ra_list = (raListTbl *)util_peek_list(priv->adapter->pmoal_handle,
413*4882a593Smuzhiyun ra_list_head, MNULL, MNULL);
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun while (ra_list && ra_list != (raListTbl *)ra_list_head) {
416*4882a593Smuzhiyun wlan_wmm_del_pkts_in_ralist_node(priv, ra_list);
417*4882a593Smuzhiyun
418*4882a593Smuzhiyun ra_list = ra_list->pnext;
419*4882a593Smuzhiyun }
420*4882a593Smuzhiyun
421*4882a593Smuzhiyun LEAVE();
422*4882a593Smuzhiyun }
423*4882a593Smuzhiyun
424*4882a593Smuzhiyun /**
425*4882a593Smuzhiyun * @brief Clean up the wmm queue
426*4882a593Smuzhiyun *
427*4882a593Smuzhiyun * @param priv Pointer to the mlan_private driver data struct
428*4882a593Smuzhiyun *
429*4882a593Smuzhiyun * @return N/A
430*4882a593Smuzhiyun */
wlan_wmm_cleanup_queues(pmlan_private priv)431*4882a593Smuzhiyun static void wlan_wmm_cleanup_queues(pmlan_private priv)
432*4882a593Smuzhiyun {
433*4882a593Smuzhiyun int i;
434*4882a593Smuzhiyun
435*4882a593Smuzhiyun ENTER();
436*4882a593Smuzhiyun
437*4882a593Smuzhiyun for (i = 0; i < MAX_NUM_TID; i++) {
438*4882a593Smuzhiyun wlan_wmm_del_pkts_in_ralist(priv,
439*4882a593Smuzhiyun &priv->wmm.tid_tbl_ptr[i].ra_list);
440*4882a593Smuzhiyun priv->wmm.pkts_queued[i] = 0;
441*4882a593Smuzhiyun priv->wmm.pkts_paused[i] = 0;
442*4882a593Smuzhiyun }
443*4882a593Smuzhiyun util_scalar_write(priv->adapter->pmoal_handle,
444*4882a593Smuzhiyun &priv->wmm.tx_pkts_queued, 0, MNULL, MNULL);
445*4882a593Smuzhiyun util_scalar_write(priv->adapter->pmoal_handle,
446*4882a593Smuzhiyun &priv->wmm.highest_queued_prio, HIGH_PRIO_TID, MNULL,
447*4882a593Smuzhiyun MNULL);
448*4882a593Smuzhiyun
449*4882a593Smuzhiyun LEAVE();
450*4882a593Smuzhiyun }
451*4882a593Smuzhiyun
452*4882a593Smuzhiyun /**
453*4882a593Smuzhiyun * @brief Delete all route address from RA list
454*4882a593Smuzhiyun *
455*4882a593Smuzhiyun * @param priv Pointer to the mlan_private driver data struct
456*4882a593Smuzhiyun *
457*4882a593Smuzhiyun * @return N/A
458*4882a593Smuzhiyun */
wlan_wmm_delete_all_ralist(pmlan_private priv)459*4882a593Smuzhiyun static void wlan_wmm_delete_all_ralist(pmlan_private priv)
460*4882a593Smuzhiyun {
461*4882a593Smuzhiyun raListTbl *ra_list;
462*4882a593Smuzhiyun int i;
463*4882a593Smuzhiyun pmlan_adapter pmadapter = priv->adapter;
464*4882a593Smuzhiyun
465*4882a593Smuzhiyun ENTER();
466*4882a593Smuzhiyun
467*4882a593Smuzhiyun for (i = 0; i < MAX_NUM_TID; ++i) {
468*4882a593Smuzhiyun PRINTM(MINFO, "RAList: Freeing buffers for TID %d\n", i);
469*4882a593Smuzhiyun while ((ra_list = (raListTbl *)util_peek_list(
470*4882a593Smuzhiyun pmadapter->pmoal_handle,
471*4882a593Smuzhiyun &priv->wmm.tid_tbl_ptr[i].ra_list, MNULL,
472*4882a593Smuzhiyun MNULL))) {
473*4882a593Smuzhiyun util_unlink_list(pmadapter->pmoal_handle,
474*4882a593Smuzhiyun &priv->wmm.tid_tbl_ptr[i].ra_list,
475*4882a593Smuzhiyun (pmlan_linked_list)ra_list, MNULL,
476*4882a593Smuzhiyun MNULL);
477*4882a593Smuzhiyun
478*4882a593Smuzhiyun pmadapter->callbacks.moal_mfree(pmadapter->pmoal_handle,
479*4882a593Smuzhiyun (t_u8 *)ra_list);
480*4882a593Smuzhiyun }
481*4882a593Smuzhiyun
482*4882a593Smuzhiyun util_init_list(
483*4882a593Smuzhiyun (pmlan_linked_list)&priv->wmm.tid_tbl_ptr[i].ra_list);
484*4882a593Smuzhiyun priv->wmm.tid_tbl_ptr[i].ra_list_curr = MNULL;
485*4882a593Smuzhiyun }
486*4882a593Smuzhiyun
487*4882a593Smuzhiyun LEAVE();
488*4882a593Smuzhiyun }
489*4882a593Smuzhiyun
490*4882a593Smuzhiyun /**
491*4882a593Smuzhiyun * @brief Get queue RA pointer
492*4882a593Smuzhiyun *
493*4882a593Smuzhiyun * @param priv Pointer to the mlan_private driver data struct
494*4882a593Smuzhiyun * @param tid TID
495*4882a593Smuzhiyun * @param ra_addr Pointer to the route address
496*4882a593Smuzhiyun *
497*4882a593Smuzhiyun * @return ra_list
498*4882a593Smuzhiyun */
wlan_wmm_get_queue_raptr(pmlan_private priv,t_u8 tid,t_u8 * ra_addr)499*4882a593Smuzhiyun static raListTbl *wlan_wmm_get_queue_raptr(pmlan_private priv, t_u8 tid,
500*4882a593Smuzhiyun t_u8 *ra_addr)
501*4882a593Smuzhiyun {
502*4882a593Smuzhiyun raListTbl *ra_list;
503*4882a593Smuzhiyun #ifdef UAP_SUPPORT
504*4882a593Smuzhiyun t_u8 bcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
505*4882a593Smuzhiyun #endif
506*4882a593Smuzhiyun
507*4882a593Smuzhiyun ENTER();
508*4882a593Smuzhiyun ra_list = wlan_wmm_get_ralist_node(priv, tid, ra_addr);
509*4882a593Smuzhiyun if (ra_list) {
510*4882a593Smuzhiyun LEAVE();
511*4882a593Smuzhiyun return ra_list;
512*4882a593Smuzhiyun }
513*4882a593Smuzhiyun #ifdef UAP_SUPPORT
514*4882a593Smuzhiyun if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) &&
515*4882a593Smuzhiyun (0 !=
516*4882a593Smuzhiyun memcmp(priv->adapter, ra_addr, bcast_addr, sizeof(bcast_addr)))) {
517*4882a593Smuzhiyun if (MNULL == wlan_get_station_entry(priv, ra_addr)) {
518*4882a593Smuzhiyun PRINTM_NETINTF(MERROR, priv);
519*4882a593Smuzhiyun PRINTM(MERROR,
520*4882a593Smuzhiyun "Drop packets to unknow station " MACSTR "\n",
521*4882a593Smuzhiyun MAC2STR(ra_addr));
522*4882a593Smuzhiyun LEAVE();
523*4882a593Smuzhiyun return MNULL;
524*4882a593Smuzhiyun }
525*4882a593Smuzhiyun }
526*4882a593Smuzhiyun #endif
527*4882a593Smuzhiyun wlan_ralist_add(priv, ra_addr);
528*4882a593Smuzhiyun
529*4882a593Smuzhiyun ra_list = wlan_wmm_get_ralist_node(priv, tid, ra_addr);
530*4882a593Smuzhiyun LEAVE();
531*4882a593Smuzhiyun return ra_list;
532*4882a593Smuzhiyun }
533*4882a593Smuzhiyun
534*4882a593Smuzhiyun #ifdef STA_SUPPORT
535*4882a593Smuzhiyun /**
536*4882a593Smuzhiyun * @brief Sends wmmac host event
537*4882a593Smuzhiyun *
538*4882a593Smuzhiyun * @param priv Pointer to the mlan_private driver data struct
539*4882a593Smuzhiyun * @param type_str Type of host event
540*4882a593Smuzhiyun * @param src_addr Pointer to the source Address
541*4882a593Smuzhiyun * @param tid TID
542*4882a593Smuzhiyun * @param up User priority
543*4882a593Smuzhiyun * @param status Status code or Reason code
544*4882a593Smuzhiyun *
545*4882a593Smuzhiyun * @return N/A
546*4882a593Smuzhiyun */
wlan_send_wmmac_host_event(pmlan_private priv,char * type_str,t_u8 * src_addr,t_u8 tid,t_u8 up,t_u8 status)547*4882a593Smuzhiyun static void wlan_send_wmmac_host_event(pmlan_private priv, char *type_str,
548*4882a593Smuzhiyun t_u8 *src_addr, t_u8 tid, t_u8 up,
549*4882a593Smuzhiyun t_u8 status)
550*4882a593Smuzhiyun {
551*4882a593Smuzhiyun t_u8 event_buf[100];
552*4882a593Smuzhiyun mlan_event *pevent;
553*4882a593Smuzhiyun t_u8 *pout_buf;
554*4882a593Smuzhiyun
555*4882a593Smuzhiyun ENTER();
556*4882a593Smuzhiyun
557*4882a593Smuzhiyun /* Format one of the following two output strings:
558*4882a593Smuzhiyun ** - TSPEC:ADDTS_RSP:[<status code>]:TID=X:UP=Y
559*4882a593Smuzhiyun ** - TSPEC:DELTS_RX:[<reason code>]:TID=X:UP=Y
560*4882a593Smuzhiyun */
561*4882a593Smuzhiyun pevent = (mlan_event *)event_buf;
562*4882a593Smuzhiyun pout_buf = pevent->event_buf;
563*4882a593Smuzhiyun
564*4882a593Smuzhiyun memcpy_ext(priv->adapter, pout_buf, (t_u8 *)"TSPEC:", 6, 6);
565*4882a593Smuzhiyun pout_buf += 6;
566*4882a593Smuzhiyun
567*4882a593Smuzhiyun memcpy_ext(priv->adapter, pout_buf, (t_u8 *)type_str,
568*4882a593Smuzhiyun wlan_strlen(type_str), wlan_strlen(type_str));
569*4882a593Smuzhiyun pout_buf += wlan_strlen(type_str);
570*4882a593Smuzhiyun
571*4882a593Smuzhiyun *pout_buf++ = ':';
572*4882a593Smuzhiyun *pout_buf++ = '[';
573*4882a593Smuzhiyun
574*4882a593Smuzhiyun if (status >= 100) {
575*4882a593Smuzhiyun *pout_buf++ = (status / 100) + '0';
576*4882a593Smuzhiyun status = (status % 100);
577*4882a593Smuzhiyun }
578*4882a593Smuzhiyun
579*4882a593Smuzhiyun if (status >= 10) {
580*4882a593Smuzhiyun *pout_buf++ = (status / 10) + '0';
581*4882a593Smuzhiyun status = (status % 10);
582*4882a593Smuzhiyun }
583*4882a593Smuzhiyun
584*4882a593Smuzhiyun *pout_buf++ = status + '0';
585*4882a593Smuzhiyun
586*4882a593Smuzhiyun memcpy_ext(priv->adapter, pout_buf, (t_u8 *)"]:TID", 5, 5);
587*4882a593Smuzhiyun pout_buf += 5;
588*4882a593Smuzhiyun *pout_buf++ = tid + '0';
589*4882a593Smuzhiyun
590*4882a593Smuzhiyun memcpy_ext(priv->adapter, pout_buf, (t_u8 *)":UP", 3, 3);
591*4882a593Smuzhiyun pout_buf += 3;
592*4882a593Smuzhiyun *pout_buf++ = up + '0';
593*4882a593Smuzhiyun
594*4882a593Smuzhiyun *pout_buf = '\0';
595*4882a593Smuzhiyun
596*4882a593Smuzhiyun pevent->bss_index = priv->bss_index;
597*4882a593Smuzhiyun pevent->event_id = MLAN_EVENT_ID_DRV_REPORT_STRING;
598*4882a593Smuzhiyun pevent->event_len = wlan_strlen((const char *)(pevent->event_buf));
599*4882a593Smuzhiyun
600*4882a593Smuzhiyun wlan_recv_event(priv, MLAN_EVENT_ID_DRV_REPORT_STRING, pevent);
601*4882a593Smuzhiyun LEAVE();
602*4882a593Smuzhiyun }
603*4882a593Smuzhiyun #endif /* STA_SUPPORT */
604*4882a593Smuzhiyun
605*4882a593Smuzhiyun /**
606*4882a593Smuzhiyun * @brief This function gets the highest priority list pointer
607*4882a593Smuzhiyun *
608*4882a593Smuzhiyun * @param pmadapter A pointer to mlan_adapter
609*4882a593Smuzhiyun * @param priv A pointer to mlan_private
610*4882a593Smuzhiyun * @param tid A pointer to return tid
611*4882a593Smuzhiyun *
612*4882a593Smuzhiyun * @return raListTbl
613*4882a593Smuzhiyun */
wlan_wmm_get_highest_priolist_ptr(pmlan_adapter pmadapter,pmlan_private * priv,int * tid)614*4882a593Smuzhiyun static raListTbl *wlan_wmm_get_highest_priolist_ptr(pmlan_adapter pmadapter,
615*4882a593Smuzhiyun pmlan_private *priv,
616*4882a593Smuzhiyun int *tid)
617*4882a593Smuzhiyun {
618*4882a593Smuzhiyun pmlan_private priv_tmp;
619*4882a593Smuzhiyun raListTbl *ptr, *head;
620*4882a593Smuzhiyun mlan_bssprio_node *bssprio_node, *bssprio_head;
621*4882a593Smuzhiyun tid_tbl_t *tid_ptr;
622*4882a593Smuzhiyun int i, j;
623*4882a593Smuzhiyun int next_prio = 0;
624*4882a593Smuzhiyun int next_tid = 0;
625*4882a593Smuzhiyun ENTER();
626*4882a593Smuzhiyun
627*4882a593Smuzhiyun PRINTM(MDAT_D, "POP\n");
628*4882a593Smuzhiyun for (j = pmadapter->priv_num - 1; j >= 0; --j) {
629*4882a593Smuzhiyun if (!(util_peek_list(pmadapter->pmoal_handle,
630*4882a593Smuzhiyun &pmadapter->bssprio_tbl[j].bssprio_head,
631*4882a593Smuzhiyun MNULL, MNULL)))
632*4882a593Smuzhiyun continue;
633*4882a593Smuzhiyun
634*4882a593Smuzhiyun if (pmadapter->bssprio_tbl[j].bssprio_cur ==
635*4882a593Smuzhiyun (mlan_bssprio_node *)&pmadapter->bssprio_tbl[j]
636*4882a593Smuzhiyun .bssprio_head) {
637*4882a593Smuzhiyun pmadapter->bssprio_tbl[j].bssprio_cur =
638*4882a593Smuzhiyun pmadapter->bssprio_tbl[j].bssprio_cur->pnext;
639*4882a593Smuzhiyun }
640*4882a593Smuzhiyun
641*4882a593Smuzhiyun bssprio_head = bssprio_node =
642*4882a593Smuzhiyun pmadapter->bssprio_tbl[j].bssprio_cur;
643*4882a593Smuzhiyun
644*4882a593Smuzhiyun do {
645*4882a593Smuzhiyun priv_tmp = bssprio_node->priv;
646*4882a593Smuzhiyun if ((priv_tmp->port_ctrl_mode == MTRUE) &&
647*4882a593Smuzhiyun (priv_tmp->port_open == MFALSE)) {
648*4882a593Smuzhiyun PRINTM(MINFO,
649*4882a593Smuzhiyun "get_highest_prio_ptr(): "
650*4882a593Smuzhiyun "PORT_CLOSED Ignore pkts from BSS%d\n",
651*4882a593Smuzhiyun priv_tmp->bss_index);
652*4882a593Smuzhiyun /* Ignore data pkts from a BSS if port is closed
653*4882a593Smuzhiyun */
654*4882a593Smuzhiyun goto next_intf;
655*4882a593Smuzhiyun }
656*4882a593Smuzhiyun if (priv_tmp->tx_pause == MTRUE) {
657*4882a593Smuzhiyun PRINTM(MINFO,
658*4882a593Smuzhiyun "get_highest_prio_ptr(): "
659*4882a593Smuzhiyun "TX PASUE Ignore pkts from BSS%d\n",
660*4882a593Smuzhiyun priv_tmp->bss_index);
661*4882a593Smuzhiyun /* Ignore data pkts from a BSS if tx pause */
662*4882a593Smuzhiyun goto next_intf;
663*4882a593Smuzhiyun }
664*4882a593Smuzhiyun
665*4882a593Smuzhiyun pmadapter->callbacks.moal_spin_lock(
666*4882a593Smuzhiyun pmadapter->pmoal_handle,
667*4882a593Smuzhiyun priv_tmp->wmm.ra_list_spinlock);
668*4882a593Smuzhiyun
669*4882a593Smuzhiyun for (i = util_scalar_read(
670*4882a593Smuzhiyun pmadapter->pmoal_handle,
671*4882a593Smuzhiyun &priv_tmp->wmm.highest_queued_prio, MNULL,
672*4882a593Smuzhiyun MNULL);
673*4882a593Smuzhiyun i >= LOW_PRIO_TID; --i) {
674*4882a593Smuzhiyun tid_ptr = &(priv_tmp)
675*4882a593Smuzhiyun ->wmm
676*4882a593Smuzhiyun .tid_tbl_ptr[tos_to_tid[i]];
677*4882a593Smuzhiyun if (!util_peek_list(pmadapter->pmoal_handle,
678*4882a593Smuzhiyun &tid_ptr->ra_list, MNULL,
679*4882a593Smuzhiyun MNULL))
680*4882a593Smuzhiyun continue;
681*4882a593Smuzhiyun
682*4882a593Smuzhiyun /*
683*4882a593Smuzhiyun * Always choose the next ra we transmitted
684*4882a593Smuzhiyun * last time, this way we pick the ra's in
685*4882a593Smuzhiyun * round robin fashion.
686*4882a593Smuzhiyun */
687*4882a593Smuzhiyun head = ptr = tid_ptr->ra_list_curr->pnext;
688*4882a593Smuzhiyun if (ptr == (raListTbl *)&tid_ptr->ra_list)
689*4882a593Smuzhiyun head = ptr = ptr->pnext;
690*4882a593Smuzhiyun
691*4882a593Smuzhiyun do {
692*4882a593Smuzhiyun if (!ptr->tx_pause &&
693*4882a593Smuzhiyun util_peek_list(
694*4882a593Smuzhiyun pmadapter->pmoal_handle,
695*4882a593Smuzhiyun &ptr->buf_head, MNULL,
696*4882a593Smuzhiyun MNULL)) {
697*4882a593Smuzhiyun /* Because WMM only support
698*4882a593Smuzhiyun * BK/BE/VI/VO, we have 8 tid
699*4882a593Smuzhiyun * We should balance the traffic
700*4882a593Smuzhiyun * of the same AC */
701*4882a593Smuzhiyun if (i % 2)
702*4882a593Smuzhiyun next_prio = i - 1;
703*4882a593Smuzhiyun else
704*4882a593Smuzhiyun next_prio = i + 1;
705*4882a593Smuzhiyun next_tid =
706*4882a593Smuzhiyun tos_to_tid[next_prio];
707*4882a593Smuzhiyun if (priv_tmp->wmm.pkts_queued
708*4882a593Smuzhiyun [next_tid] &&
709*4882a593Smuzhiyun (priv_tmp->wmm.pkts_queued
710*4882a593Smuzhiyun [next_tid] >
711*4882a593Smuzhiyun priv_tmp->wmm.pkts_paused
712*4882a593Smuzhiyun [next_tid]))
713*4882a593Smuzhiyun util_scalar_write(
714*4882a593Smuzhiyun pmadapter->pmoal_handle,
715*4882a593Smuzhiyun &priv_tmp->wmm
716*4882a593Smuzhiyun .highest_queued_prio,
717*4882a593Smuzhiyun next_prio,
718*4882a593Smuzhiyun MNULL, MNULL);
719*4882a593Smuzhiyun else
720*4882a593Smuzhiyun /* if
721*4882a593Smuzhiyun * highest_queued_prio >
722*4882a593Smuzhiyun * i, set it to i */
723*4882a593Smuzhiyun util_scalar_conditional_write(
724*4882a593Smuzhiyun pmadapter->pmoal_handle,
725*4882a593Smuzhiyun &priv_tmp->wmm
726*4882a593Smuzhiyun .highest_queued_prio,
727*4882a593Smuzhiyun MLAN_SCALAR_COND_GREATER_THAN,
728*4882a593Smuzhiyun i, i, MNULL,
729*4882a593Smuzhiyun MNULL);
730*4882a593Smuzhiyun *priv = priv_tmp;
731*4882a593Smuzhiyun *tid = tos_to_tid[i];
732*4882a593Smuzhiyun /* hold priv->ra_list_spinlock
733*4882a593Smuzhiyun * to maintain ptr */
734*4882a593Smuzhiyun PRINTM(MDAT_D,
735*4882a593Smuzhiyun "get highest prio ptr %p, tid %d\n",
736*4882a593Smuzhiyun ptr, *tid);
737*4882a593Smuzhiyun LEAVE();
738*4882a593Smuzhiyun return ptr;
739*4882a593Smuzhiyun }
740*4882a593Smuzhiyun
741*4882a593Smuzhiyun ptr = ptr->pnext;
742*4882a593Smuzhiyun if (ptr ==
743*4882a593Smuzhiyun (raListTbl *)&tid_ptr->ra_list)
744*4882a593Smuzhiyun ptr = ptr->pnext;
745*4882a593Smuzhiyun } while (ptr != head);
746*4882a593Smuzhiyun }
747*4882a593Smuzhiyun
748*4882a593Smuzhiyun /* If priv still has packets queued, reset to
749*4882a593Smuzhiyun * HIGH_PRIO_TID */
750*4882a593Smuzhiyun if (util_scalar_read(pmadapter->pmoal_handle,
751*4882a593Smuzhiyun &priv_tmp->wmm.tx_pkts_queued,
752*4882a593Smuzhiyun MNULL, MNULL))
753*4882a593Smuzhiyun util_scalar_write(
754*4882a593Smuzhiyun pmadapter->pmoal_handle,
755*4882a593Smuzhiyun &priv_tmp->wmm.highest_queued_prio,
756*4882a593Smuzhiyun HIGH_PRIO_TID, MNULL, MNULL);
757*4882a593Smuzhiyun else
758*4882a593Smuzhiyun /* No packet at any TID for this priv. Mark as
759*4882a593Smuzhiyun * such to skip checking TIDs for this priv
760*4882a593Smuzhiyun * (until pkt is added). */
761*4882a593Smuzhiyun util_scalar_write(
762*4882a593Smuzhiyun pmadapter->pmoal_handle,
763*4882a593Smuzhiyun &priv_tmp->wmm.highest_queued_prio,
764*4882a593Smuzhiyun NO_PKT_PRIO_TID, MNULL, MNULL);
765*4882a593Smuzhiyun
766*4882a593Smuzhiyun pmadapter->callbacks.moal_spin_unlock(
767*4882a593Smuzhiyun pmadapter->pmoal_handle,
768*4882a593Smuzhiyun priv_tmp->wmm.ra_list_spinlock);
769*4882a593Smuzhiyun
770*4882a593Smuzhiyun next_intf:
771*4882a593Smuzhiyun bssprio_node = bssprio_node->pnext;
772*4882a593Smuzhiyun if (bssprio_node ==
773*4882a593Smuzhiyun (mlan_bssprio_node *)&pmadapter->bssprio_tbl[j]
774*4882a593Smuzhiyun .bssprio_head)
775*4882a593Smuzhiyun bssprio_node = bssprio_node->pnext;
776*4882a593Smuzhiyun pmadapter->bssprio_tbl[j].bssprio_cur = bssprio_node;
777*4882a593Smuzhiyun } while (bssprio_node != bssprio_head);
778*4882a593Smuzhiyun }
779*4882a593Smuzhiyun
780*4882a593Smuzhiyun LEAVE();
781*4882a593Smuzhiyun return MNULL;
782*4882a593Smuzhiyun }
783*4882a593Smuzhiyun
784*4882a593Smuzhiyun /**
785*4882a593Smuzhiyun * @brief This function gets the number of packets in the Tx queue
786*4882a593Smuzhiyun *
787*4882a593Smuzhiyun * @param priv A pointer to mlan_private
788*4882a593Smuzhiyun * @param ptr A pointer to RA list table
789*4882a593Smuzhiyun * @param max_buf_size Maximum buffer size
790*4882a593Smuzhiyun *
791*4882a593Smuzhiyun * @return Packet count
792*4882a593Smuzhiyun */
wlan_num_pkts_in_txq(mlan_private * priv,raListTbl * ptr,int max_buf_size)793*4882a593Smuzhiyun static int wlan_num_pkts_in_txq(mlan_private *priv, raListTbl *ptr,
794*4882a593Smuzhiyun int max_buf_size)
795*4882a593Smuzhiyun {
796*4882a593Smuzhiyun int count = 0, total_size = 0;
797*4882a593Smuzhiyun pmlan_buffer pmbuf;
798*4882a593Smuzhiyun
799*4882a593Smuzhiyun ENTER();
800*4882a593Smuzhiyun
801*4882a593Smuzhiyun for (pmbuf = (pmlan_buffer)ptr->buf_head.pnext;
802*4882a593Smuzhiyun pmbuf != (pmlan_buffer)(&ptr->buf_head); pmbuf = pmbuf->pnext) {
803*4882a593Smuzhiyun total_size += pmbuf->data_len;
804*4882a593Smuzhiyun if (total_size < max_buf_size)
805*4882a593Smuzhiyun ++count;
806*4882a593Smuzhiyun else
807*4882a593Smuzhiyun break;
808*4882a593Smuzhiyun }
809*4882a593Smuzhiyun
810*4882a593Smuzhiyun LEAVE();
811*4882a593Smuzhiyun return count;
812*4882a593Smuzhiyun }
813*4882a593Smuzhiyun
814*4882a593Smuzhiyun /**
815*4882a593Smuzhiyun * @brief This function sends a single packet
816*4882a593Smuzhiyun *
817*4882a593Smuzhiyun * @param priv A pointer to mlan_private
818*4882a593Smuzhiyun * @param ptr A pointer to RA list table
819*4882a593Smuzhiyun * @param ptrindex ptr's TID index
820*4882a593Smuzhiyun *
821*4882a593Smuzhiyun * @return N/A
822*4882a593Smuzhiyun */
wlan_send_single_packet(pmlan_private priv,raListTbl * ptr,int ptrindex)823*4882a593Smuzhiyun static INLINE void wlan_send_single_packet(pmlan_private priv, raListTbl *ptr,
824*4882a593Smuzhiyun int ptrindex)
825*4882a593Smuzhiyun {
826*4882a593Smuzhiyun pmlan_buffer pmbuf;
827*4882a593Smuzhiyun pmlan_buffer pmbuf_next;
828*4882a593Smuzhiyun mlan_tx_param tx_param;
829*4882a593Smuzhiyun pmlan_adapter pmadapter = priv->adapter;
830*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
831*4882a593Smuzhiyun
832*4882a593Smuzhiyun ENTER();
833*4882a593Smuzhiyun
834*4882a593Smuzhiyun pmbuf = (pmlan_buffer)util_dequeue_list(pmadapter->pmoal_handle,
835*4882a593Smuzhiyun &ptr->buf_head, MNULL, MNULL);
836*4882a593Smuzhiyun if (pmbuf) {
837*4882a593Smuzhiyun PRINTM(MINFO, "Dequeuing the packet %p %p\n", ptr, pmbuf);
838*4882a593Smuzhiyun priv->wmm.pkts_queued[ptrindex]--;
839*4882a593Smuzhiyun util_scalar_decrement(pmadapter->pmoal_handle,
840*4882a593Smuzhiyun &priv->wmm.tx_pkts_queued, MNULL, MNULL);
841*4882a593Smuzhiyun ptr->total_pkts--;
842*4882a593Smuzhiyun pmbuf_next = (pmlan_buffer)util_peek_list(
843*4882a593Smuzhiyun pmadapter->pmoal_handle, &ptr->buf_head, MNULL, MNULL);
844*4882a593Smuzhiyun pmadapter->callbacks.moal_spin_unlock(
845*4882a593Smuzhiyun pmadapter->pmoal_handle, priv->wmm.ra_list_spinlock);
846*4882a593Smuzhiyun
847*4882a593Smuzhiyun tx_param.next_pkt_len =
848*4882a593Smuzhiyun ((pmbuf_next) ? pmbuf_next->data_len + sizeof(TxPD) :
849*4882a593Smuzhiyun 0);
850*4882a593Smuzhiyun status = wlan_process_tx(priv, pmbuf, &tx_param);
851*4882a593Smuzhiyun
852*4882a593Smuzhiyun if (status == MLAN_STATUS_RESOURCE) {
853*4882a593Smuzhiyun /** Queue the packet back at the head */
854*4882a593Smuzhiyun PRINTM(MDAT_D, "Queuing pkt back to raList %p %p\n",
855*4882a593Smuzhiyun ptr, pmbuf);
856*4882a593Smuzhiyun pmadapter->callbacks.moal_spin_lock(
857*4882a593Smuzhiyun pmadapter->pmoal_handle,
858*4882a593Smuzhiyun priv->wmm.ra_list_spinlock);
859*4882a593Smuzhiyun
860*4882a593Smuzhiyun if (!wlan_is_ralist_valid(priv, ptr, ptrindex)) {
861*4882a593Smuzhiyun pmadapter->callbacks.moal_spin_unlock(
862*4882a593Smuzhiyun pmadapter->pmoal_handle,
863*4882a593Smuzhiyun priv->wmm.ra_list_spinlock);
864*4882a593Smuzhiyun wlan_write_data_complete(pmadapter, pmbuf,
865*4882a593Smuzhiyun MLAN_STATUS_FAILURE);
866*4882a593Smuzhiyun LEAVE();
867*4882a593Smuzhiyun return;
868*4882a593Smuzhiyun }
869*4882a593Smuzhiyun priv->wmm.pkts_queued[ptrindex]++;
870*4882a593Smuzhiyun util_scalar_increment(pmadapter->pmoal_handle,
871*4882a593Smuzhiyun &priv->wmm.tx_pkts_queued, MNULL,
872*4882a593Smuzhiyun MNULL);
873*4882a593Smuzhiyun util_enqueue_list_head(pmadapter->pmoal_handle,
874*4882a593Smuzhiyun &ptr->buf_head,
875*4882a593Smuzhiyun (pmlan_linked_list)pmbuf, MNULL,
876*4882a593Smuzhiyun MNULL);
877*4882a593Smuzhiyun
878*4882a593Smuzhiyun ptr->total_pkts++;
879*4882a593Smuzhiyun pmbuf->flags |= MLAN_BUF_FLAG_REQUEUED_PKT;
880*4882a593Smuzhiyun pmadapter->callbacks.moal_spin_unlock(
881*4882a593Smuzhiyun pmadapter->pmoal_handle,
882*4882a593Smuzhiyun priv->wmm.ra_list_spinlock);
883*4882a593Smuzhiyun } else {
884*4882a593Smuzhiyun pmadapter->callbacks.moal_spin_lock(
885*4882a593Smuzhiyun pmadapter->pmoal_handle,
886*4882a593Smuzhiyun priv->wmm.ra_list_spinlock);
887*4882a593Smuzhiyun if (wlan_is_ralist_valid(priv, ptr, ptrindex)) {
888*4882a593Smuzhiyun priv->wmm.packets_out[ptrindex]++;
889*4882a593Smuzhiyun priv->wmm.tid_tbl_ptr[ptrindex].ra_list_curr =
890*4882a593Smuzhiyun ptr;
891*4882a593Smuzhiyun }
892*4882a593Smuzhiyun pmadapter->bssprio_tbl[priv->bss_priority].bssprio_cur =
893*4882a593Smuzhiyun pmadapter->bssprio_tbl[priv->bss_priority]
894*4882a593Smuzhiyun .bssprio_cur->pnext;
895*4882a593Smuzhiyun pmadapter->callbacks.moal_spin_unlock(
896*4882a593Smuzhiyun pmadapter->pmoal_handle,
897*4882a593Smuzhiyun priv->wmm.ra_list_spinlock);
898*4882a593Smuzhiyun }
899*4882a593Smuzhiyun } else {
900*4882a593Smuzhiyun pmadapter->callbacks.moal_spin_unlock(
901*4882a593Smuzhiyun pmadapter->pmoal_handle, priv->wmm.ra_list_spinlock);
902*4882a593Smuzhiyun PRINTM(MINFO, "Nothing to send\n");
903*4882a593Smuzhiyun }
904*4882a593Smuzhiyun
905*4882a593Smuzhiyun LEAVE();
906*4882a593Smuzhiyun }
907*4882a593Smuzhiyun
908*4882a593Smuzhiyun /**
909*4882a593Smuzhiyun * @brief This function checks if this mlan_buffer is already processed.
910*4882a593Smuzhiyun *
911*4882a593Smuzhiyun * @param priv A pointer to mlan_private
912*4882a593Smuzhiyun * @param ptr A pointer to RA list table
913*4882a593Smuzhiyun *
914*4882a593Smuzhiyun * @return MTRUE or MFALSE
915*4882a593Smuzhiyun */
wlan_is_ptr_processed(mlan_private * priv,raListTbl * ptr)916*4882a593Smuzhiyun static INLINE int wlan_is_ptr_processed(mlan_private *priv, raListTbl *ptr)
917*4882a593Smuzhiyun {
918*4882a593Smuzhiyun pmlan_buffer pmbuf;
919*4882a593Smuzhiyun
920*4882a593Smuzhiyun pmbuf = (pmlan_buffer)util_peek_list(priv->adapter->pmoal_handle,
921*4882a593Smuzhiyun &ptr->buf_head, MNULL, MNULL);
922*4882a593Smuzhiyun if (pmbuf && (pmbuf->flags & MLAN_BUF_FLAG_REQUEUED_PKT))
923*4882a593Smuzhiyun return MTRUE;
924*4882a593Smuzhiyun
925*4882a593Smuzhiyun return MFALSE;
926*4882a593Smuzhiyun }
927*4882a593Smuzhiyun
928*4882a593Smuzhiyun /**
929*4882a593Smuzhiyun * @brief This function sends a single packet that has been processed
930*4882a593Smuzhiyun *
931*4882a593Smuzhiyun * @param priv A pointer to mlan_private
932*4882a593Smuzhiyun * @param ptr A pointer to RA list table
933*4882a593Smuzhiyun * @param ptrindex ptr's TID index
934*4882a593Smuzhiyun *
935*4882a593Smuzhiyun * @return N/A
936*4882a593Smuzhiyun */
wlan_send_processed_packet(pmlan_private priv,raListTbl * ptr,int ptrindex)937*4882a593Smuzhiyun static INLINE void wlan_send_processed_packet(pmlan_private priv,
938*4882a593Smuzhiyun raListTbl *ptr, int ptrindex)
939*4882a593Smuzhiyun {
940*4882a593Smuzhiyun pmlan_buffer pmbuf_next = MNULL;
941*4882a593Smuzhiyun mlan_tx_param tx_param;
942*4882a593Smuzhiyun pmlan_buffer pmbuf;
943*4882a593Smuzhiyun pmlan_adapter pmadapter = priv->adapter;
944*4882a593Smuzhiyun mlan_status ret = MLAN_STATUS_FAILURE;
945*4882a593Smuzhiyun
946*4882a593Smuzhiyun pmbuf = (pmlan_buffer)util_dequeue_list(pmadapter->pmoal_handle,
947*4882a593Smuzhiyun &ptr->buf_head, MNULL, MNULL);
948*4882a593Smuzhiyun if (pmbuf) {
949*4882a593Smuzhiyun pmbuf_next = (pmlan_buffer)util_peek_list(
950*4882a593Smuzhiyun pmadapter->pmoal_handle, &ptr->buf_head, MNULL, MNULL);
951*4882a593Smuzhiyun pmadapter->callbacks.moal_spin_unlock(
952*4882a593Smuzhiyun pmadapter->pmoal_handle, priv->wmm.ra_list_spinlock);
953*4882a593Smuzhiyun tx_param.next_pkt_len =
954*4882a593Smuzhiyun ((pmbuf_next) ? pmbuf_next->data_len + sizeof(TxPD) :
955*4882a593Smuzhiyun 0);
956*4882a593Smuzhiyun
957*4882a593Smuzhiyun ret = pmadapter->ops.host_to_card(priv, MLAN_TYPE_DATA, pmbuf,
958*4882a593Smuzhiyun &tx_param);
959*4882a593Smuzhiyun switch (ret) {
960*4882a593Smuzhiyun #ifdef USB
961*4882a593Smuzhiyun case MLAN_STATUS_PRESOURCE:
962*4882a593Smuzhiyun PRINTM(MINFO, "MLAN_STATUS_PRESOURCE is returned\n");
963*4882a593Smuzhiyun break;
964*4882a593Smuzhiyun #endif
965*4882a593Smuzhiyun case MLAN_STATUS_RESOURCE:
966*4882a593Smuzhiyun PRINTM(MINFO, "MLAN_STATUS_RESOURCE is returned\n");
967*4882a593Smuzhiyun pmadapter->callbacks.moal_spin_lock(
968*4882a593Smuzhiyun pmadapter->pmoal_handle,
969*4882a593Smuzhiyun priv->wmm.ra_list_spinlock);
970*4882a593Smuzhiyun
971*4882a593Smuzhiyun if (!wlan_is_ralist_valid(priv, ptr, ptrindex)) {
972*4882a593Smuzhiyun pmadapter->callbacks.moal_spin_unlock(
973*4882a593Smuzhiyun pmadapter->pmoal_handle,
974*4882a593Smuzhiyun priv->wmm.ra_list_spinlock);
975*4882a593Smuzhiyun wlan_write_data_complete(pmadapter, pmbuf,
976*4882a593Smuzhiyun MLAN_STATUS_FAILURE);
977*4882a593Smuzhiyun LEAVE();
978*4882a593Smuzhiyun return;
979*4882a593Smuzhiyun }
980*4882a593Smuzhiyun util_enqueue_list_head(pmadapter->pmoal_handle,
981*4882a593Smuzhiyun &ptr->buf_head,
982*4882a593Smuzhiyun (pmlan_linked_list)pmbuf, MNULL,
983*4882a593Smuzhiyun MNULL);
984*4882a593Smuzhiyun
985*4882a593Smuzhiyun pmbuf->flags |= MLAN_BUF_FLAG_REQUEUED_PKT;
986*4882a593Smuzhiyun pmadapter->callbacks.moal_spin_unlock(
987*4882a593Smuzhiyun pmadapter->pmoal_handle,
988*4882a593Smuzhiyun priv->wmm.ra_list_spinlock);
989*4882a593Smuzhiyun break;
990*4882a593Smuzhiyun case MLAN_STATUS_FAILURE:
991*4882a593Smuzhiyun PRINTM(MERROR, "Error: Failed to write data\n");
992*4882a593Smuzhiyun pmadapter->dbg.num_tx_host_to_card_failure++;
993*4882a593Smuzhiyun pmbuf->status_code = MLAN_ERROR_DATA_TX_FAIL;
994*4882a593Smuzhiyun wlan_write_data_complete(pmadapter, pmbuf, ret);
995*4882a593Smuzhiyun break;
996*4882a593Smuzhiyun case MLAN_STATUS_PENDING:
997*4882a593Smuzhiyun break;
998*4882a593Smuzhiyun case MLAN_STATUS_SUCCESS:
999*4882a593Smuzhiyun DBG_HEXDUMP(MDAT_D, "Tx",
1000*4882a593Smuzhiyun pmbuf->pbuf + pmbuf->data_offset,
1001*4882a593Smuzhiyun MIN(pmbuf->data_len + sizeof(TxPD),
1002*4882a593Smuzhiyun MAX_DATA_DUMP_LEN));
1003*4882a593Smuzhiyun wlan_write_data_complete(pmadapter, pmbuf, ret);
1004*4882a593Smuzhiyun break;
1005*4882a593Smuzhiyun default:
1006*4882a593Smuzhiyun break;
1007*4882a593Smuzhiyun }
1008*4882a593Smuzhiyun if (ret != MLAN_STATUS_RESOURCE) {
1009*4882a593Smuzhiyun pmadapter->callbacks.moal_spin_lock(
1010*4882a593Smuzhiyun pmadapter->pmoal_handle,
1011*4882a593Smuzhiyun priv->wmm.ra_list_spinlock);
1012*4882a593Smuzhiyun if (wlan_is_ralist_valid(priv, ptr, ptrindex)) {
1013*4882a593Smuzhiyun priv->wmm.packets_out[ptrindex]++;
1014*4882a593Smuzhiyun priv->wmm.tid_tbl_ptr[ptrindex].ra_list_curr =
1015*4882a593Smuzhiyun ptr;
1016*4882a593Smuzhiyun ptr->total_pkts--;
1017*4882a593Smuzhiyun }
1018*4882a593Smuzhiyun pmadapter->bssprio_tbl[priv->bss_priority].bssprio_cur =
1019*4882a593Smuzhiyun pmadapter->bssprio_tbl[priv->bss_priority]
1020*4882a593Smuzhiyun .bssprio_cur->pnext;
1021*4882a593Smuzhiyun priv->wmm.pkts_queued[ptrindex]--;
1022*4882a593Smuzhiyun util_scalar_decrement(pmadapter->pmoal_handle,
1023*4882a593Smuzhiyun &priv->wmm.tx_pkts_queued, MNULL,
1024*4882a593Smuzhiyun MNULL);
1025*4882a593Smuzhiyun pmadapter->callbacks.moal_spin_unlock(
1026*4882a593Smuzhiyun pmadapter->pmoal_handle,
1027*4882a593Smuzhiyun priv->wmm.ra_list_spinlock);
1028*4882a593Smuzhiyun }
1029*4882a593Smuzhiyun } else {
1030*4882a593Smuzhiyun pmadapter->callbacks.moal_spin_unlock(
1031*4882a593Smuzhiyun pmadapter->pmoal_handle, priv->wmm.ra_list_spinlock);
1032*4882a593Smuzhiyun }
1033*4882a593Smuzhiyun }
1034*4882a593Smuzhiyun
1035*4882a593Smuzhiyun /**
1036*4882a593Smuzhiyun * @brief This function dequeues a packet
1037*4882a593Smuzhiyun *
1038*4882a593Smuzhiyun * @param pmadapter A pointer to mlan_adapter
1039*4882a593Smuzhiyun *
1040*4882a593Smuzhiyun * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1041*4882a593Smuzhiyun */
wlan_dequeue_tx_packet(pmlan_adapter pmadapter)1042*4882a593Smuzhiyun static int wlan_dequeue_tx_packet(pmlan_adapter pmadapter)
1043*4882a593Smuzhiyun {
1044*4882a593Smuzhiyun raListTbl *ptr;
1045*4882a593Smuzhiyun pmlan_private priv = MNULL;
1046*4882a593Smuzhiyun int ptrindex = 0;
1047*4882a593Smuzhiyun t_u8 ra[MLAN_MAC_ADDR_LENGTH];
1048*4882a593Smuzhiyun int tid_del = 0;
1049*4882a593Smuzhiyun int tid = 0;
1050*4882a593Smuzhiyun mlan_buffer *pmbuf = MNULL;
1051*4882a593Smuzhiyun
1052*4882a593Smuzhiyun ENTER();
1053*4882a593Smuzhiyun
1054*4882a593Smuzhiyun ptr = wlan_wmm_get_highest_priolist_ptr(pmadapter, &priv, &ptrindex);
1055*4882a593Smuzhiyun if (!ptr) {
1056*4882a593Smuzhiyun LEAVE();
1057*4882a593Smuzhiyun return MLAN_STATUS_FAILURE;
1058*4882a593Smuzhiyun }
1059*4882a593Smuzhiyun
1060*4882a593Smuzhiyun /* Note:- Spinlock is locked in wlan_wmm_get_highest_priolist_ptr
1061*4882a593Smuzhiyun * when it returns a pointer (for the priv it returns),
1062*4882a593Smuzhiyun * and is unlocked in wlan_send_processed_packet,
1063*4882a593Smuzhiyun * wlan_send_single_packet or wlan_11n_aggregate_pkt.
1064*4882a593Smuzhiyun * The spinlock would be required for some parts of both of function.
1065*4882a593Smuzhiyun * But, the the bulk of these function will execute w/o spinlock.
1066*4882a593Smuzhiyun * Unlocking the spinlock inside these function will help us avoid
1067*4882a593Smuzhiyun * taking the spinlock again, check to see if the ptr is still
1068*4882a593Smuzhiyun * valid and then proceed. This is done purely to increase
1069*4882a593Smuzhiyun * execution time. */
1070*4882a593Smuzhiyun
1071*4882a593Smuzhiyun /* Note:- Also, anybody adding code which does not get into
1072*4882a593Smuzhiyun * wlan_send_processed_packet, wlan_send_single_packet, or
1073*4882a593Smuzhiyun * wlan_11n_aggregate_pkt should make sure ra_list_spinlock
1074*4882a593Smuzhiyun * is freed. Otherwise there would be a lock up. */
1075*4882a593Smuzhiyun
1076*4882a593Smuzhiyun tid = wlan_get_tid(priv->adapter, ptr);
1077*4882a593Smuzhiyun if (tid >= MAX_NUM_TID)
1078*4882a593Smuzhiyun tid = wlan_wmm_downgrade_tid(priv, tid);
1079*4882a593Smuzhiyun
1080*4882a593Smuzhiyun if (wlan_is_ptr_processed(priv, ptr)) {
1081*4882a593Smuzhiyun wlan_send_processed_packet(priv, ptr, ptrindex);
1082*4882a593Smuzhiyun LEAVE();
1083*4882a593Smuzhiyun return MLAN_STATUS_SUCCESS;
1084*4882a593Smuzhiyun }
1085*4882a593Smuzhiyun if (ptr->del_ba_count >= DEL_BA_THRESHOLD)
1086*4882a593Smuzhiyun wlan_update_del_ba_count(priv, ptr);
1087*4882a593Smuzhiyun if (pmadapter->tp_state_on) {
1088*4882a593Smuzhiyun pmbuf = (pmlan_buffer)util_peek_list(
1089*4882a593Smuzhiyun pmadapter->pmoal_handle, &ptr->buf_head, MNULL, MNULL);
1090*4882a593Smuzhiyun if (pmbuf) {
1091*4882a593Smuzhiyun pmadapter->callbacks.moal_tp_accounting(
1092*4882a593Smuzhiyun pmadapter->pmoal_handle, pmbuf->pdesc, 3);
1093*4882a593Smuzhiyun if (pmadapter->tp_state_drop_point == 3) {
1094*4882a593Smuzhiyun pmbuf = (pmlan_buffer)util_dequeue_list(
1095*4882a593Smuzhiyun pmadapter->pmoal_handle, &ptr->buf_head,
1096*4882a593Smuzhiyun MNULL, MNULL);
1097*4882a593Smuzhiyun PRINTM(MERROR, "Dequeuing the packet %p %p\n",
1098*4882a593Smuzhiyun ptr, pmbuf);
1099*4882a593Smuzhiyun priv->wmm.pkts_queued[ptrindex]--;
1100*4882a593Smuzhiyun util_scalar_decrement(pmadapter->pmoal_handle,
1101*4882a593Smuzhiyun &priv->wmm.tx_pkts_queued,
1102*4882a593Smuzhiyun MNULL, MNULL);
1103*4882a593Smuzhiyun ptr->total_pkts--;
1104*4882a593Smuzhiyun pmadapter->callbacks.moal_spin_unlock(
1105*4882a593Smuzhiyun pmadapter->pmoal_handle,
1106*4882a593Smuzhiyun priv->wmm.ra_list_spinlock);
1107*4882a593Smuzhiyun wlan_write_data_complete(pmadapter, pmbuf,
1108*4882a593Smuzhiyun MLAN_STATUS_SUCCESS);
1109*4882a593Smuzhiyun LEAVE();
1110*4882a593Smuzhiyun return MLAN_STATUS_SUCCESS;
1111*4882a593Smuzhiyun }
1112*4882a593Smuzhiyun }
1113*4882a593Smuzhiyun }
1114*4882a593Smuzhiyun if (!ptr->is_wmm_enabled ||
1115*4882a593Smuzhiyun (ptr->ba_status || ptr->del_ba_count >= DEL_BA_THRESHOLD)
1116*4882a593Smuzhiyun #ifdef STA_SUPPORT
1117*4882a593Smuzhiyun || priv->wps.session_enable
1118*4882a593Smuzhiyun #endif /* STA_SUPPORT */
1119*4882a593Smuzhiyun ) {
1120*4882a593Smuzhiyun if (ptr->is_wmm_enabled && ptr->ba_status &&
1121*4882a593Smuzhiyun ptr->amsdu_in_ampdu &&
1122*4882a593Smuzhiyun wlan_is_amsdu_allowed(priv, ptr, tid) &&
1123*4882a593Smuzhiyun (wlan_num_pkts_in_txq(priv, ptr, pmadapter->tx_buf_size) >=
1124*4882a593Smuzhiyun MIN_NUM_AMSDU)) {
1125*4882a593Smuzhiyun wlan_11n_aggregate_pkt(priv, ptr, priv->intf_hr_len,
1126*4882a593Smuzhiyun ptrindex);
1127*4882a593Smuzhiyun } else
1128*4882a593Smuzhiyun wlan_send_single_packet(priv, ptr, ptrindex);
1129*4882a593Smuzhiyun } else {
1130*4882a593Smuzhiyun if (wlan_is_ampdu_allowed(priv, ptr, tid) &&
1131*4882a593Smuzhiyun (ptr->packet_count > ptr->ba_packet_threshold)) {
1132*4882a593Smuzhiyun if (wlan_is_bastream_avail(priv)) {
1133*4882a593Smuzhiyun PRINTM(MINFO,
1134*4882a593Smuzhiyun "BA setup threshold %d reached. tid=%d\n",
1135*4882a593Smuzhiyun ptr->packet_count, tid);
1136*4882a593Smuzhiyun if (!wlan_11n_get_txbastream_tbl(
1137*4882a593Smuzhiyun priv, tid, ptr->ra, MFALSE)) {
1138*4882a593Smuzhiyun wlan_11n_create_txbastream_tbl(
1139*4882a593Smuzhiyun priv, ptr->ra, tid,
1140*4882a593Smuzhiyun BA_STREAM_SETUP_INPROGRESS);
1141*4882a593Smuzhiyun wlan_send_addba(priv, tid, ptr->ra);
1142*4882a593Smuzhiyun }
1143*4882a593Smuzhiyun } else if (wlan_find_stream_to_delete(priv, ptr, tid,
1144*4882a593Smuzhiyun &tid_del, ra)) {
1145*4882a593Smuzhiyun PRINTM(MDAT_D, "tid_del=%d tid=%d\n", tid_del,
1146*4882a593Smuzhiyun tid);
1147*4882a593Smuzhiyun if (!wlan_11n_get_txbastream_tbl(
1148*4882a593Smuzhiyun priv, tid, ptr->ra, MFALSE)) {
1149*4882a593Smuzhiyun wlan_11n_create_txbastream_tbl(
1150*4882a593Smuzhiyun priv, ptr->ra, tid,
1151*4882a593Smuzhiyun BA_STREAM_SETUP_INPROGRESS);
1152*4882a593Smuzhiyun wlan_send_delba(priv, MNULL, tid_del,
1153*4882a593Smuzhiyun ra, 1);
1154*4882a593Smuzhiyun }
1155*4882a593Smuzhiyun }
1156*4882a593Smuzhiyun }
1157*4882a593Smuzhiyun if (wlan_is_amsdu_allowed(priv, ptr, tid) &&
1158*4882a593Smuzhiyun (wlan_num_pkts_in_txq(priv, ptr, pmadapter->tx_buf_size) >=
1159*4882a593Smuzhiyun MIN_NUM_AMSDU)) {
1160*4882a593Smuzhiyun wlan_11n_aggregate_pkt(priv, ptr, priv->intf_hr_len,
1161*4882a593Smuzhiyun ptrindex);
1162*4882a593Smuzhiyun } else {
1163*4882a593Smuzhiyun wlan_send_single_packet(priv, ptr, ptrindex);
1164*4882a593Smuzhiyun }
1165*4882a593Smuzhiyun }
1166*4882a593Smuzhiyun
1167*4882a593Smuzhiyun LEAVE();
1168*4882a593Smuzhiyun return MLAN_STATUS_SUCCESS;
1169*4882a593Smuzhiyun }
1170*4882a593Smuzhiyun
1171*4882a593Smuzhiyun /**
1172*4882a593Smuzhiyun * @brief update tx_pause flag in ra_list
1173*4882a593Smuzhiyun *
1174*4882a593Smuzhiyun * @param priv A pointer to mlan_private
1175*4882a593Smuzhiyun * @param mac peer mac address
1176*4882a593Smuzhiyun * @param tx_pause tx_pause flag (0/1)
1177*4882a593Smuzhiyun *
1178*4882a593Smuzhiyun *
1179*4882a593Smuzhiyun * @return packets queued for this mac
1180*4882a593Smuzhiyun */
wlan_update_ralist_tx_pause(pmlan_private priv,t_u8 * mac,t_u8 tx_pause)1181*4882a593Smuzhiyun t_u16 wlan_update_ralist_tx_pause(pmlan_private priv, t_u8 *mac, t_u8 tx_pause)
1182*4882a593Smuzhiyun {
1183*4882a593Smuzhiyun raListTbl *ra_list;
1184*4882a593Smuzhiyun int i;
1185*4882a593Smuzhiyun pmlan_adapter pmadapter = priv->adapter;
1186*4882a593Smuzhiyun t_u32 pkt_cnt = 0;
1187*4882a593Smuzhiyun t_u32 tx_pkts_queued = 0;
1188*4882a593Smuzhiyun ENTER();
1189*4882a593Smuzhiyun
1190*4882a593Smuzhiyun pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
1191*4882a593Smuzhiyun priv->wmm.ra_list_spinlock);
1192*4882a593Smuzhiyun for (i = 0; i < MAX_NUM_TID; ++i) {
1193*4882a593Smuzhiyun ra_list = wlan_wmm_get_ralist_node(priv, i, mac);
1194*4882a593Smuzhiyun if (ra_list && ra_list->tx_pause != tx_pause) {
1195*4882a593Smuzhiyun pkt_cnt += ra_list->total_pkts;
1196*4882a593Smuzhiyun ra_list->tx_pause = tx_pause;
1197*4882a593Smuzhiyun if (tx_pause)
1198*4882a593Smuzhiyun priv->wmm.pkts_paused[i] += ra_list->total_pkts;
1199*4882a593Smuzhiyun else
1200*4882a593Smuzhiyun priv->wmm.pkts_paused[i] -= ra_list->total_pkts;
1201*4882a593Smuzhiyun }
1202*4882a593Smuzhiyun }
1203*4882a593Smuzhiyun if (pkt_cnt) {
1204*4882a593Smuzhiyun tx_pkts_queued = util_scalar_read(pmadapter->pmoal_handle,
1205*4882a593Smuzhiyun &priv->wmm.tx_pkts_queued,
1206*4882a593Smuzhiyun MNULL, MNULL);
1207*4882a593Smuzhiyun if (tx_pause)
1208*4882a593Smuzhiyun tx_pkts_queued -= pkt_cnt;
1209*4882a593Smuzhiyun else
1210*4882a593Smuzhiyun tx_pkts_queued += pkt_cnt;
1211*4882a593Smuzhiyun util_scalar_write(priv->adapter->pmoal_handle,
1212*4882a593Smuzhiyun &priv->wmm.tx_pkts_queued, tx_pkts_queued,
1213*4882a593Smuzhiyun MNULL, MNULL);
1214*4882a593Smuzhiyun util_scalar_write(priv->adapter->pmoal_handle,
1215*4882a593Smuzhiyun &priv->wmm.highest_queued_prio, HIGH_PRIO_TID,
1216*4882a593Smuzhiyun MNULL, MNULL);
1217*4882a593Smuzhiyun }
1218*4882a593Smuzhiyun pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
1219*4882a593Smuzhiyun priv->wmm.ra_list_spinlock);
1220*4882a593Smuzhiyun LEAVE();
1221*4882a593Smuzhiyun return pkt_cnt;
1222*4882a593Smuzhiyun }
1223*4882a593Smuzhiyun
1224*4882a593Smuzhiyun #ifdef STA_SUPPORT
1225*4882a593Smuzhiyun /**
1226*4882a593Smuzhiyun * @brief update tx_pause flag in none tdls ra_list
1227*4882a593Smuzhiyun *
1228*4882a593Smuzhiyun * @param priv A pointer to mlan_private
1229*4882a593Smuzhiyun * @param mac peer mac address
1230*4882a593Smuzhiyun * @param tx_pause tx_pause flag (0/1)
1231*4882a593Smuzhiyun *
1232*4882a593Smuzhiyun * @return N/A
1233*4882a593Smuzhiyun */
wlan_update_non_tdls_ralist(mlan_private * priv,t_u8 * mac,t_u8 tx_pause)1234*4882a593Smuzhiyun t_void wlan_update_non_tdls_ralist(mlan_private *priv, t_u8 *mac, t_u8 tx_pause)
1235*4882a593Smuzhiyun {
1236*4882a593Smuzhiyun raListTbl *ra_list;
1237*4882a593Smuzhiyun int i;
1238*4882a593Smuzhiyun pmlan_adapter pmadapter = priv->adapter;
1239*4882a593Smuzhiyun t_u32 pkt_cnt = 0;
1240*4882a593Smuzhiyun t_u32 tx_pkts_queued = 0;
1241*4882a593Smuzhiyun ENTER();
1242*4882a593Smuzhiyun
1243*4882a593Smuzhiyun pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
1244*4882a593Smuzhiyun priv->wmm.ra_list_spinlock);
1245*4882a593Smuzhiyun for (i = 0; i < MAX_NUM_TID; ++i) {
1246*4882a593Smuzhiyun ra_list = (raListTbl *)util_peek_list(
1247*4882a593Smuzhiyun priv->adapter->pmoal_handle,
1248*4882a593Smuzhiyun &priv->wmm.tid_tbl_ptr[i].ra_list, MNULL, MNULL);
1249*4882a593Smuzhiyun while (ra_list &&
1250*4882a593Smuzhiyun (ra_list !=
1251*4882a593Smuzhiyun (raListTbl *)&priv->wmm.tid_tbl_ptr[i].ra_list)) {
1252*4882a593Smuzhiyun if (memcmp(priv->adapter, ra_list->ra, mac,
1253*4882a593Smuzhiyun MLAN_MAC_ADDR_LENGTH) &&
1254*4882a593Smuzhiyun ra_list->tx_pause != tx_pause) {
1255*4882a593Smuzhiyun pkt_cnt += ra_list->total_pkts;
1256*4882a593Smuzhiyun ra_list->tx_pause = tx_pause;
1257*4882a593Smuzhiyun if (tx_pause)
1258*4882a593Smuzhiyun priv->wmm.pkts_paused[i] +=
1259*4882a593Smuzhiyun ra_list->total_pkts;
1260*4882a593Smuzhiyun else
1261*4882a593Smuzhiyun priv->wmm.pkts_paused[i] -=
1262*4882a593Smuzhiyun ra_list->total_pkts;
1263*4882a593Smuzhiyun }
1264*4882a593Smuzhiyun ra_list = ra_list->pnext;
1265*4882a593Smuzhiyun }
1266*4882a593Smuzhiyun }
1267*4882a593Smuzhiyun if (pkt_cnt) {
1268*4882a593Smuzhiyun tx_pkts_queued = util_scalar_read(pmadapter->pmoal_handle,
1269*4882a593Smuzhiyun &priv->wmm.tx_pkts_queued,
1270*4882a593Smuzhiyun MNULL, MNULL);
1271*4882a593Smuzhiyun if (tx_pause)
1272*4882a593Smuzhiyun tx_pkts_queued -= pkt_cnt;
1273*4882a593Smuzhiyun else
1274*4882a593Smuzhiyun tx_pkts_queued += pkt_cnt;
1275*4882a593Smuzhiyun util_scalar_write(priv->adapter->pmoal_handle,
1276*4882a593Smuzhiyun &priv->wmm.tx_pkts_queued, tx_pkts_queued,
1277*4882a593Smuzhiyun MNULL, MNULL);
1278*4882a593Smuzhiyun util_scalar_write(priv->adapter->pmoal_handle,
1279*4882a593Smuzhiyun &priv->wmm.highest_queued_prio, HIGH_PRIO_TID,
1280*4882a593Smuzhiyun MNULL, MNULL);
1281*4882a593Smuzhiyun }
1282*4882a593Smuzhiyun pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
1283*4882a593Smuzhiyun priv->wmm.ra_list_spinlock);
1284*4882a593Smuzhiyun LEAVE();
1285*4882a593Smuzhiyun return;
1286*4882a593Smuzhiyun }
1287*4882a593Smuzhiyun
1288*4882a593Smuzhiyun /**
1289*4882a593Smuzhiyun * @brief find tdls buffer from ralist
1290*4882a593Smuzhiyun *
1291*4882a593Smuzhiyun * @param priv A pointer to mlan_private
1292*4882a593Smuzhiyun * @param ralist A pointer to ralistTbl
1293*4882a593Smuzhiyun * @param mac TDLS peer mac address
1294*4882a593Smuzhiyun *
1295*4882a593Smuzhiyun * @return pmlan_buffer or MNULL
1296*4882a593Smuzhiyun */
wlan_find_tdls_packets(mlan_private * priv,raListTbl * ra_list,t_u8 * mac)1297*4882a593Smuzhiyun static pmlan_buffer wlan_find_tdls_packets(mlan_private *priv,
1298*4882a593Smuzhiyun raListTbl *ra_list, t_u8 *mac)
1299*4882a593Smuzhiyun {
1300*4882a593Smuzhiyun pmlan_buffer pmbuf = MNULL;
1301*4882a593Smuzhiyun mlan_adapter *pmadapter = priv->adapter;
1302*4882a593Smuzhiyun t_u8 ra[MLAN_MAC_ADDR_LENGTH];
1303*4882a593Smuzhiyun ENTER();
1304*4882a593Smuzhiyun pmbuf = (pmlan_buffer)util_peek_list(priv->adapter->pmoal_handle,
1305*4882a593Smuzhiyun &ra_list->buf_head, MNULL, MNULL);
1306*4882a593Smuzhiyun if (!pmbuf) {
1307*4882a593Smuzhiyun LEAVE();
1308*4882a593Smuzhiyun return MNULL;
1309*4882a593Smuzhiyun }
1310*4882a593Smuzhiyun while (pmbuf != (pmlan_buffer)&ra_list->buf_head) {
1311*4882a593Smuzhiyun memcpy_ext(pmadapter, ra, pmbuf->pbuf + pmbuf->data_offset,
1312*4882a593Smuzhiyun MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
1313*4882a593Smuzhiyun if (!memcmp(priv->adapter, ra, mac, MLAN_MAC_ADDR_LENGTH)) {
1314*4882a593Smuzhiyun LEAVE();
1315*4882a593Smuzhiyun return pmbuf;
1316*4882a593Smuzhiyun }
1317*4882a593Smuzhiyun pmbuf = pmbuf->pnext;
1318*4882a593Smuzhiyun }
1319*4882a593Smuzhiyun LEAVE();
1320*4882a593Smuzhiyun return MNULL;
1321*4882a593Smuzhiyun }
1322*4882a593Smuzhiyun
1323*4882a593Smuzhiyun /**
1324*4882a593Smuzhiyun * @brief find tdls buffer from tdls pending queue
1325*4882a593Smuzhiyun *
1326*4882a593Smuzhiyun * @param priv A pointer to mlan_private
1327*4882a593Smuzhiyun * @param mac TDLS peer mac address
1328*4882a593Smuzhiyun *
1329*4882a593Smuzhiyun * @return pmlan_buffer or MNULL
1330*4882a593Smuzhiyun */
wlan_find_packets_tdls_txq(mlan_private * priv,t_u8 * mac)1331*4882a593Smuzhiyun static pmlan_buffer wlan_find_packets_tdls_txq(mlan_private *priv, t_u8 *mac)
1332*4882a593Smuzhiyun {
1333*4882a593Smuzhiyun pmlan_buffer pmbuf = MNULL;
1334*4882a593Smuzhiyun mlan_adapter *pmadapter = priv->adapter;
1335*4882a593Smuzhiyun t_u8 ra[MLAN_MAC_ADDR_LENGTH];
1336*4882a593Smuzhiyun ENTER();
1337*4882a593Smuzhiyun pmbuf = (pmlan_buffer)util_peek_list(priv->adapter->pmoal_handle,
1338*4882a593Smuzhiyun &priv->tdls_pending_txq, MNULL,
1339*4882a593Smuzhiyun MNULL);
1340*4882a593Smuzhiyun if (!pmbuf) {
1341*4882a593Smuzhiyun LEAVE();
1342*4882a593Smuzhiyun return MNULL;
1343*4882a593Smuzhiyun }
1344*4882a593Smuzhiyun while (pmbuf != (pmlan_buffer)&priv->tdls_pending_txq) {
1345*4882a593Smuzhiyun memcpy_ext(pmadapter, ra, pmbuf->pbuf + pmbuf->data_offset,
1346*4882a593Smuzhiyun MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
1347*4882a593Smuzhiyun if (!memcmp(priv->adapter, ra, mac, MLAN_MAC_ADDR_LENGTH)) {
1348*4882a593Smuzhiyun LEAVE();
1349*4882a593Smuzhiyun return pmbuf;
1350*4882a593Smuzhiyun }
1351*4882a593Smuzhiyun pmbuf = pmbuf->pnext;
1352*4882a593Smuzhiyun }
1353*4882a593Smuzhiyun LEAVE();
1354*4882a593Smuzhiyun return MNULL;
1355*4882a593Smuzhiyun }
1356*4882a593Smuzhiyun
1357*4882a593Smuzhiyun /**
1358*4882a593Smuzhiyun * @brief Remove TDLS ralist and move packets to AP's ralist
1359*4882a593Smuzhiyun *
1360*4882a593Smuzhiyun * @param priv A pointer to mlan_private
1361*4882a593Smuzhiyun * @param mac TDLS peer mac address
1362*4882a593Smuzhiyun *
1363*4882a593Smuzhiyun * @return N/A
1364*4882a593Smuzhiyun */
wlan_wmm_delete_tdls_ralist(pmlan_private priv,t_u8 * mac)1365*4882a593Smuzhiyun static t_void wlan_wmm_delete_tdls_ralist(pmlan_private priv, t_u8 *mac)
1366*4882a593Smuzhiyun {
1367*4882a593Smuzhiyun raListTbl *ra_list;
1368*4882a593Smuzhiyun raListTbl *ra_list_ap = MNULL;
1369*4882a593Smuzhiyun int i;
1370*4882a593Smuzhiyun pmlan_adapter pmadapter = priv->adapter;
1371*4882a593Smuzhiyun pmlan_buffer pmbuf;
1372*4882a593Smuzhiyun ENTER();
1373*4882a593Smuzhiyun
1374*4882a593Smuzhiyun for (i = 0; i < MAX_NUM_TID; ++i) {
1375*4882a593Smuzhiyun ra_list = wlan_wmm_get_ralist_node(priv, i, mac);
1376*4882a593Smuzhiyun if (ra_list) {
1377*4882a593Smuzhiyun PRINTM(MDATA, "delete TDLS ralist %p\n", ra_list);
1378*4882a593Smuzhiyun ra_list_ap = (raListTbl *)util_peek_list(
1379*4882a593Smuzhiyun pmadapter->pmoal_handle,
1380*4882a593Smuzhiyun &priv->wmm.tid_tbl_ptr[i].ra_list, MNULL,
1381*4882a593Smuzhiyun MNULL);
1382*4882a593Smuzhiyun if (!ra_list_ap) {
1383*4882a593Smuzhiyun LEAVE();
1384*4882a593Smuzhiyun return;
1385*4882a593Smuzhiyun }
1386*4882a593Smuzhiyun while ((pmbuf = (pmlan_buffer)util_peek_list(
1387*4882a593Smuzhiyun pmadapter->pmoal_handle,
1388*4882a593Smuzhiyun &ra_list->buf_head, MNULL, MNULL))) {
1389*4882a593Smuzhiyun util_unlink_list(pmadapter->pmoal_handle,
1390*4882a593Smuzhiyun &ra_list->buf_head,
1391*4882a593Smuzhiyun (pmlan_linked_list)pmbuf,
1392*4882a593Smuzhiyun MNULL, MNULL);
1393*4882a593Smuzhiyun util_enqueue_list_tail(pmadapter->pmoal_handle,
1394*4882a593Smuzhiyun &ra_list_ap->buf_head,
1395*4882a593Smuzhiyun (pmlan_linked_list)pmbuf,
1396*4882a593Smuzhiyun MNULL, MNULL);
1397*4882a593Smuzhiyun ra_list_ap->total_pkts++;
1398*4882a593Smuzhiyun ra_list_ap->packet_count++;
1399*4882a593Smuzhiyun }
1400*4882a593Smuzhiyun util_free_list_head(
1401*4882a593Smuzhiyun (t_void *)pmadapter->pmoal_handle,
1402*4882a593Smuzhiyun &ra_list->buf_head,
1403*4882a593Smuzhiyun pmadapter->callbacks.moal_free_lock);
1404*4882a593Smuzhiyun
1405*4882a593Smuzhiyun util_unlink_list(pmadapter->pmoal_handle,
1406*4882a593Smuzhiyun &priv->wmm.tid_tbl_ptr[i].ra_list,
1407*4882a593Smuzhiyun (pmlan_linked_list)ra_list, MNULL,
1408*4882a593Smuzhiyun MNULL);
1409*4882a593Smuzhiyun pmadapter->callbacks.moal_mfree(pmadapter->pmoal_handle,
1410*4882a593Smuzhiyun (t_u8 *)ra_list);
1411*4882a593Smuzhiyun if (priv->wmm.tid_tbl_ptr[i].ra_list_curr == ra_list)
1412*4882a593Smuzhiyun priv->wmm.tid_tbl_ptr[i].ra_list_curr =
1413*4882a593Smuzhiyun ra_list_ap;
1414*4882a593Smuzhiyun }
1415*4882a593Smuzhiyun }
1416*4882a593Smuzhiyun
1417*4882a593Smuzhiyun LEAVE();
1418*4882a593Smuzhiyun }
1419*4882a593Smuzhiyun #endif /* STA_SUPPORT */
1420*4882a593Smuzhiyun /********************************************************
1421*4882a593Smuzhiyun Global Functions
1422*4882a593Smuzhiyun ********************************************************/
1423*4882a593Smuzhiyun
1424*4882a593Smuzhiyun /**
1425*4882a593Smuzhiyun * @brief Get the threshold value for BA setup using system time.
1426*4882a593Smuzhiyun *
1427*4882a593Smuzhiyun * @param pmadapter Pointer to the mlan_adapter structure
1428*4882a593Smuzhiyun *
1429*4882a593Smuzhiyun * @return threshold value.
1430*4882a593Smuzhiyun */
wlan_get_random_ba_threshold(pmlan_adapter pmadapter)1431*4882a593Smuzhiyun t_u8 wlan_get_random_ba_threshold(pmlan_adapter pmadapter)
1432*4882a593Smuzhiyun {
1433*4882a593Smuzhiyun t_u32 sec, usec;
1434*4882a593Smuzhiyun t_u8 ba_threshold = 0;
1435*4882a593Smuzhiyun
1436*4882a593Smuzhiyun ENTER();
1437*4882a593Smuzhiyun
1438*4882a593Smuzhiyun /* setup ba_packet_threshold here random number between
1439*4882a593Smuzhiyun [BA_SETUP_PACKET_OFFSET,
1440*4882a593Smuzhiyun BA_SETUP_PACKET_OFFSET+BA_SETUP_MAX_PACKET_THRESHOLD-1] */
1441*4882a593Smuzhiyun
1442*4882a593Smuzhiyun #define BA_SETUP_MAX_PACKET_THRESHOLD 16
1443*4882a593Smuzhiyun
1444*4882a593Smuzhiyun pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle, &sec,
1445*4882a593Smuzhiyun &usec);
1446*4882a593Smuzhiyun sec = (sec & 0xFFFF) + (sec >> 16);
1447*4882a593Smuzhiyun usec = (usec & 0xFFFF) + (usec >> 16);
1448*4882a593Smuzhiyun
1449*4882a593Smuzhiyun ba_threshold = (((sec << 16) + usec) % BA_SETUP_MAX_PACKET_THRESHOLD) +
1450*4882a593Smuzhiyun pmadapter->min_ba_threshold;
1451*4882a593Smuzhiyun PRINTM(MINFO, "pmadapter->min_ba_threshold = %d\n",
1452*4882a593Smuzhiyun pmadapter->min_ba_threshold);
1453*4882a593Smuzhiyun PRINTM(MINFO, "setup BA after %d packets\n", ba_threshold);
1454*4882a593Smuzhiyun
1455*4882a593Smuzhiyun LEAVE();
1456*4882a593Smuzhiyun return ba_threshold;
1457*4882a593Smuzhiyun }
1458*4882a593Smuzhiyun
1459*4882a593Smuzhiyun /**
1460*4882a593Smuzhiyun * @brief This function cleans Tx/Rx queues
1461*4882a593Smuzhiyun *
1462*4882a593Smuzhiyun * @param priv A pointer to mlan_private
1463*4882a593Smuzhiyun *
1464*4882a593Smuzhiyun * @return N/A
1465*4882a593Smuzhiyun */
wlan_clean_txrx(pmlan_private priv)1466*4882a593Smuzhiyun t_void wlan_clean_txrx(pmlan_private priv)
1467*4882a593Smuzhiyun {
1468*4882a593Smuzhiyun mlan_adapter *pmadapter = priv->adapter;
1469*4882a593Smuzhiyun t_u8 i = 0;
1470*4882a593Smuzhiyun
1471*4882a593Smuzhiyun ENTER();
1472*4882a593Smuzhiyun wlan_cleanup_bypass_txq(priv);
1473*4882a593Smuzhiyun if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) {
1474*4882a593Smuzhiyun wlan_cleanup_tdls_txq(priv);
1475*4882a593Smuzhiyun }
1476*4882a593Smuzhiyun wlan_11n_cleanup_reorder_tbl(priv);
1477*4882a593Smuzhiyun wlan_11n_deleteall_txbastream_tbl(priv);
1478*4882a593Smuzhiyun #if defined(USB)
1479*4882a593Smuzhiyun if (IS_USB(pmadapter->card_type))
1480*4882a593Smuzhiyun wlan_reset_usb_tx_aggr(priv->adapter);
1481*4882a593Smuzhiyun #endif
1482*4882a593Smuzhiyun #ifdef PCIE
1483*4882a593Smuzhiyun if (IS_PCIE(pmadapter->card_type))
1484*4882a593Smuzhiyun wlan_clean_pcie_ring_buf(priv->adapter);
1485*4882a593Smuzhiyun #endif
1486*4882a593Smuzhiyun pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
1487*4882a593Smuzhiyun priv->wmm.ra_list_spinlock);
1488*4882a593Smuzhiyun wlan_wmm_cleanup_queues(priv);
1489*4882a593Smuzhiyun wlan_wmm_delete_all_ralist(priv);
1490*4882a593Smuzhiyun memcpy_ext(pmadapter, tos_to_tid, ac_to_tid, sizeof(tos_to_tid),
1491*4882a593Smuzhiyun sizeof(tos_to_tid));
1492*4882a593Smuzhiyun for (i = 0; i < MAX_NUM_TID; i++)
1493*4882a593Smuzhiyun tos_to_tid_inv[tos_to_tid[i]] = (t_u8)i;
1494*4882a593Smuzhiyun #ifdef UAP_SUPPORT
1495*4882a593Smuzhiyun priv->num_drop_pkts = 0;
1496*4882a593Smuzhiyun #endif
1497*4882a593Smuzhiyun #ifdef SDIO
1498*4882a593Smuzhiyun if (IS_SD(pmadapter->card_type)) {
1499*4882a593Smuzhiyun memset(pmadapter, pmadapter->pcard_sd->mpa_tx_count, 0,
1500*4882a593Smuzhiyun sizeof(pmadapter->pcard_sd->mpa_tx_count));
1501*4882a593Smuzhiyun pmadapter->pcard_sd->mpa_sent_no_ports = 0;
1502*4882a593Smuzhiyun pmadapter->pcard_sd->mpa_sent_last_pkt = 0;
1503*4882a593Smuzhiyun memset(pmadapter, pmadapter->pcard_sd->mpa_rx_count, 0,
1504*4882a593Smuzhiyun sizeof(pmadapter->pcard_sd->mpa_rx_count));
1505*4882a593Smuzhiyun }
1506*4882a593Smuzhiyun #endif
1507*4882a593Smuzhiyun pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
1508*4882a593Smuzhiyun priv->wmm.ra_list_spinlock);
1509*4882a593Smuzhiyun
1510*4882a593Smuzhiyun LEAVE();
1511*4882a593Smuzhiyun }
1512*4882a593Smuzhiyun
1513*4882a593Smuzhiyun /**
1514*4882a593Smuzhiyun * @brief Set the WMM queue priorities to their default values
1515*4882a593Smuzhiyun *
1516*4882a593Smuzhiyun * @param priv Pointer to the mlan_private driver data struct
1517*4882a593Smuzhiyun *
1518*4882a593Smuzhiyun * @return N/A
1519*4882a593Smuzhiyun */
wlan_wmm_default_queue_priorities(pmlan_private priv)1520*4882a593Smuzhiyun void wlan_wmm_default_queue_priorities(pmlan_private priv)
1521*4882a593Smuzhiyun {
1522*4882a593Smuzhiyun ENTER();
1523*4882a593Smuzhiyun
1524*4882a593Smuzhiyun /* Default queue priorities: VO->VI->BE->BK */
1525*4882a593Smuzhiyun priv->wmm.queue_priority[0] = WMM_AC_VO;
1526*4882a593Smuzhiyun priv->wmm.queue_priority[1] = WMM_AC_VI;
1527*4882a593Smuzhiyun priv->wmm.queue_priority[2] = WMM_AC_BE;
1528*4882a593Smuzhiyun priv->wmm.queue_priority[3] = WMM_AC_BK;
1529*4882a593Smuzhiyun
1530*4882a593Smuzhiyun LEAVE();
1531*4882a593Smuzhiyun }
1532*4882a593Smuzhiyun
1533*4882a593Smuzhiyun /**
1534*4882a593Smuzhiyun * @brief Initialize WMM priority queues
1535*4882a593Smuzhiyun *
1536*4882a593Smuzhiyun * @param priv Pointer to the mlan_private driver data struct
1537*4882a593Smuzhiyun * @param pwmm_ie Pointer to the IEEEtypes_WmmParameter_t data struct
1538*4882a593Smuzhiyun *
1539*4882a593Smuzhiyun * @return N/A
1540*4882a593Smuzhiyun */
wlan_wmm_setup_queue_priorities(pmlan_private priv,IEEEtypes_WmmParameter_t * pwmm_ie)1541*4882a593Smuzhiyun void wlan_wmm_setup_queue_priorities(pmlan_private priv,
1542*4882a593Smuzhiyun IEEEtypes_WmmParameter_t *pwmm_ie)
1543*4882a593Smuzhiyun {
1544*4882a593Smuzhiyun t_u16 cw_min, avg_back_off, tmp[4];
1545*4882a593Smuzhiyun t_u32 i, j, num_ac;
1546*4882a593Smuzhiyun t_u8 ac_idx;
1547*4882a593Smuzhiyun
1548*4882a593Smuzhiyun ENTER();
1549*4882a593Smuzhiyun
1550*4882a593Smuzhiyun if (!pwmm_ie || priv->wmm_enabled == MFALSE) {
1551*4882a593Smuzhiyun /* WMM is not enabled, just set the defaults and return */
1552*4882a593Smuzhiyun wlan_wmm_default_queue_priorities(priv);
1553*4882a593Smuzhiyun LEAVE();
1554*4882a593Smuzhiyun return;
1555*4882a593Smuzhiyun }
1556*4882a593Smuzhiyun memset(priv->adapter, tmp, 0, sizeof(tmp));
1557*4882a593Smuzhiyun
1558*4882a593Smuzhiyun HEXDUMP("WMM: setup_queue_priorities: param IE", (t_u8 *)pwmm_ie,
1559*4882a593Smuzhiyun sizeof(IEEEtypes_WmmParameter_t));
1560*4882a593Smuzhiyun
1561*4882a593Smuzhiyun PRINTM(MINFO,
1562*4882a593Smuzhiyun "WMM Parameter IE: version=%d, "
1563*4882a593Smuzhiyun "qos_info Parameter Set Count=%d, Reserved=%#x\n",
1564*4882a593Smuzhiyun pwmm_ie->vend_hdr.version, pwmm_ie->qos_info.para_set_count,
1565*4882a593Smuzhiyun pwmm_ie->reserved);
1566*4882a593Smuzhiyun
1567*4882a593Smuzhiyun for (num_ac = 0; num_ac < NELEMENTS(pwmm_ie->ac_params); num_ac++) {
1568*4882a593Smuzhiyun cw_min = (1 << pwmm_ie->ac_params[num_ac].ecw.ecw_min) - 1;
1569*4882a593Smuzhiyun avg_back_off = (cw_min >> 1) +
1570*4882a593Smuzhiyun pwmm_ie->ac_params[num_ac].aci_aifsn.aifsn;
1571*4882a593Smuzhiyun
1572*4882a593Smuzhiyun ac_idx = wmm_aci_to_qidx_map[pwmm_ie->ac_params[num_ac]
1573*4882a593Smuzhiyun .aci_aifsn.aci];
1574*4882a593Smuzhiyun priv->wmm.queue_priority[ac_idx] = ac_idx;
1575*4882a593Smuzhiyun tmp[ac_idx] = avg_back_off;
1576*4882a593Smuzhiyun
1577*4882a593Smuzhiyun PRINTM(MCMND, "WMM: CWmax=%d CWmin=%d Avg Back-off=%d\n",
1578*4882a593Smuzhiyun (1 << pwmm_ie->ac_params[num_ac].ecw.ecw_max) - 1,
1579*4882a593Smuzhiyun cw_min, avg_back_off);
1580*4882a593Smuzhiyun PRINTM_AC(&pwmm_ie->ac_params[num_ac]);
1581*4882a593Smuzhiyun }
1582*4882a593Smuzhiyun
1583*4882a593Smuzhiyun HEXDUMP("WMM: avg_back_off", (t_u8 *)tmp, sizeof(tmp));
1584*4882a593Smuzhiyun HEXDUMP("WMM: queue_priority", priv->wmm.queue_priority,
1585*4882a593Smuzhiyun sizeof(priv->wmm.queue_priority));
1586*4882a593Smuzhiyun
1587*4882a593Smuzhiyun /* Bubble sort */
1588*4882a593Smuzhiyun for (i = 0; i < num_ac; i++) {
1589*4882a593Smuzhiyun for (j = 1; j < num_ac - i; j++) {
1590*4882a593Smuzhiyun if (tmp[j - 1] > tmp[j]) {
1591*4882a593Smuzhiyun SWAP_U16(tmp[j - 1], tmp[j]);
1592*4882a593Smuzhiyun SWAP_U8(priv->wmm.queue_priority[j - 1],
1593*4882a593Smuzhiyun priv->wmm.queue_priority[j]);
1594*4882a593Smuzhiyun } else if (tmp[j - 1] == tmp[j]) {
1595*4882a593Smuzhiyun if (priv->wmm.queue_priority[j - 1] <
1596*4882a593Smuzhiyun priv->wmm.queue_priority[j]) {
1597*4882a593Smuzhiyun SWAP_U8(priv->wmm.queue_priority[j - 1],
1598*4882a593Smuzhiyun priv->wmm.queue_priority[j]);
1599*4882a593Smuzhiyun }
1600*4882a593Smuzhiyun }
1601*4882a593Smuzhiyun }
1602*4882a593Smuzhiyun }
1603*4882a593Smuzhiyun
1604*4882a593Smuzhiyun wlan_wmm_queue_priorities_tid(priv, priv->wmm.queue_priority);
1605*4882a593Smuzhiyun
1606*4882a593Smuzhiyun HEXDUMP("WMM: avg_back_off, sort", (t_u8 *)tmp, sizeof(tmp));
1607*4882a593Smuzhiyun DBG_HEXDUMP(MCMD_D, "WMM: queue_priority, sort",
1608*4882a593Smuzhiyun priv->wmm.queue_priority, sizeof(priv->wmm.queue_priority));
1609*4882a593Smuzhiyun LEAVE();
1610*4882a593Smuzhiyun }
1611*4882a593Smuzhiyun
1612*4882a593Smuzhiyun /**
1613*4882a593Smuzhiyun * @brief Downgrade WMM priority queue
1614*4882a593Smuzhiyun *
1615*4882a593Smuzhiyun * @param priv Pointer to the mlan_private driver data struct
1616*4882a593Smuzhiyun *
1617*4882a593Smuzhiyun * @return N/A
1618*4882a593Smuzhiyun */
wlan_wmm_setup_ac_downgrade(pmlan_private priv)1619*4882a593Smuzhiyun void wlan_wmm_setup_ac_downgrade(pmlan_private priv)
1620*4882a593Smuzhiyun {
1621*4882a593Smuzhiyun int ac_val;
1622*4882a593Smuzhiyun
1623*4882a593Smuzhiyun ENTER();
1624*4882a593Smuzhiyun
1625*4882a593Smuzhiyun PRINTM(MINFO, "WMM: AC Priorities: BK(0), BE(1), VI(2), VO(3)\n");
1626*4882a593Smuzhiyun
1627*4882a593Smuzhiyun if (priv->wmm_enabled == MFALSE) {
1628*4882a593Smuzhiyun /* WMM is not enabled, default priorities */
1629*4882a593Smuzhiyun for (ac_val = WMM_AC_BK; ac_val <= WMM_AC_VO; ac_val++) {
1630*4882a593Smuzhiyun priv->wmm.ac_down_graded_vals[ac_val] =
1631*4882a593Smuzhiyun (mlan_wmm_ac_e)ac_val;
1632*4882a593Smuzhiyun }
1633*4882a593Smuzhiyun } else {
1634*4882a593Smuzhiyun for (ac_val = WMM_AC_BK; ac_val <= WMM_AC_VO; ac_val++) {
1635*4882a593Smuzhiyun priv->wmm.ac_down_graded_vals[ac_val] =
1636*4882a593Smuzhiyun wlan_wmm_eval_downgrade_ac(
1637*4882a593Smuzhiyun priv, (mlan_wmm_ac_e)ac_val);
1638*4882a593Smuzhiyun PRINTM(MINFO, "WMM: AC PRIO %d maps to %d\n", ac_val,
1639*4882a593Smuzhiyun priv->wmm.ac_down_graded_vals[ac_val]);
1640*4882a593Smuzhiyun }
1641*4882a593Smuzhiyun }
1642*4882a593Smuzhiyun
1643*4882a593Smuzhiyun LEAVE();
1644*4882a593Smuzhiyun }
1645*4882a593Smuzhiyun
1646*4882a593Smuzhiyun /**
1647*4882a593Smuzhiyun * @brief This function checks whether a station has WMM enabled or not
1648*4882a593Smuzhiyun *
1649*4882a593Smuzhiyun * @param priv A pointer to mlan_private
1650*4882a593Smuzhiyun * @param mac station mac address
1651*4882a593Smuzhiyun * @return MTRUE or MFALSE
1652*4882a593Smuzhiyun */
is_station_wmm_enabled(mlan_private * priv,t_u8 * mac)1653*4882a593Smuzhiyun static t_u8 is_station_wmm_enabled(mlan_private *priv, t_u8 *mac)
1654*4882a593Smuzhiyun {
1655*4882a593Smuzhiyun sta_node *sta_ptr = MNULL;
1656*4882a593Smuzhiyun sta_ptr = wlan_get_station_entry(priv, mac);
1657*4882a593Smuzhiyun if (sta_ptr) {
1658*4882a593Smuzhiyun if (sta_ptr->is_11n_enabled || sta_ptr->is_11ax_enabled)
1659*4882a593Smuzhiyun return MTRUE;
1660*4882a593Smuzhiyun }
1661*4882a593Smuzhiyun return MFALSE;
1662*4882a593Smuzhiyun }
1663*4882a593Smuzhiyun
1664*4882a593Smuzhiyun /**
1665*4882a593Smuzhiyun * @brief This function checks whether wmm is supported
1666*4882a593Smuzhiyun *
1667*4882a593Smuzhiyun * @param priv A pointer to mlan_private
1668*4882a593Smuzhiyun * @param ra Address of the receiver STA
1669*4882a593Smuzhiyun *
1670*4882a593Smuzhiyun * @return MTRUE or MFALSE
1671*4882a593Smuzhiyun */
wlan_is_wmm_enabled(mlan_private * priv,t_u8 * ra)1672*4882a593Smuzhiyun static int wlan_is_wmm_enabled(mlan_private *priv, t_u8 *ra)
1673*4882a593Smuzhiyun {
1674*4882a593Smuzhiyun int ret = MFALSE;
1675*4882a593Smuzhiyun ENTER();
1676*4882a593Smuzhiyun #ifdef UAP_SUPPORT
1677*4882a593Smuzhiyun if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
1678*4882a593Smuzhiyun if ((!(ra[0] & 0x01)) &&
1679*4882a593Smuzhiyun (priv->is_11n_enabled || priv->is_11ax_enabled))
1680*4882a593Smuzhiyun ret = is_station_wmm_enabled(priv, ra);
1681*4882a593Smuzhiyun }
1682*4882a593Smuzhiyun #endif /* UAP_SUPPORT */
1683*4882a593Smuzhiyun LEAVE();
1684*4882a593Smuzhiyun return ret;
1685*4882a593Smuzhiyun }
1686*4882a593Smuzhiyun
1687*4882a593Smuzhiyun /**
1688*4882a593Smuzhiyun * @brief Allocate and add a RA list for all TIDs with the given RA
1689*4882a593Smuzhiyun *
1690*4882a593Smuzhiyun * @param priv Pointer to the mlan_private driver data struct
1691*4882a593Smuzhiyun * @param ra Address of the receiver STA (AP in case of infra)
1692*4882a593Smuzhiyun *
1693*4882a593Smuzhiyun * @return N/A
1694*4882a593Smuzhiyun */
wlan_ralist_add(mlan_private * priv,t_u8 * ra)1695*4882a593Smuzhiyun void wlan_ralist_add(mlan_private *priv, t_u8 *ra)
1696*4882a593Smuzhiyun {
1697*4882a593Smuzhiyun int i;
1698*4882a593Smuzhiyun raListTbl *ra_list;
1699*4882a593Smuzhiyun pmlan_adapter pmadapter = priv->adapter;
1700*4882a593Smuzhiyun tdlsStatus_e status;
1701*4882a593Smuzhiyun
1702*4882a593Smuzhiyun ENTER();
1703*4882a593Smuzhiyun
1704*4882a593Smuzhiyun for (i = 0; i < MAX_NUM_TID; ++i) {
1705*4882a593Smuzhiyun ra_list = wlan_wmm_allocate_ralist_node(pmadapter, ra);
1706*4882a593Smuzhiyun PRINTM(MINFO, "Creating RA List %p for tid %d\n", ra_list, i);
1707*4882a593Smuzhiyun if (!ra_list)
1708*4882a593Smuzhiyun break;
1709*4882a593Smuzhiyun ra_list->max_amsdu = 0;
1710*4882a593Smuzhiyun ra_list->ba_status = BA_STREAM_NOT_SETUP;
1711*4882a593Smuzhiyun ra_list->amsdu_in_ampdu = MFALSE;
1712*4882a593Smuzhiyun if (queuing_ra_based(priv)) {
1713*4882a593Smuzhiyun ra_list->is_wmm_enabled = wlan_is_wmm_enabled(priv, ra);
1714*4882a593Smuzhiyun if (ra_list->is_wmm_enabled)
1715*4882a593Smuzhiyun ra_list->max_amsdu =
1716*4882a593Smuzhiyun get_station_max_amsdu_size(priv, ra);
1717*4882a593Smuzhiyun ra_list->tx_pause = wlan_is_tx_pause(priv, ra);
1718*4882a593Smuzhiyun } else {
1719*4882a593Smuzhiyun ra_list->is_tdls_link = MFALSE;
1720*4882a593Smuzhiyun ra_list->tx_pause = MFALSE;
1721*4882a593Smuzhiyun status = wlan_get_tdls_link_status(priv, ra);
1722*4882a593Smuzhiyun if (MTRUE == wlan_is_tdls_link_setup(status)) {
1723*4882a593Smuzhiyun ra_list->is_wmm_enabled =
1724*4882a593Smuzhiyun is_station_wmm_enabled(priv, ra);
1725*4882a593Smuzhiyun if (ra_list->is_wmm_enabled)
1726*4882a593Smuzhiyun ra_list->max_amsdu =
1727*4882a593Smuzhiyun get_station_max_amsdu_size(priv,
1728*4882a593Smuzhiyun ra);
1729*4882a593Smuzhiyun ra_list->is_tdls_link = MTRUE;
1730*4882a593Smuzhiyun } else {
1731*4882a593Smuzhiyun ra_list->is_wmm_enabled = IS_11N_ENABLED(priv);
1732*4882a593Smuzhiyun if (ra_list->is_wmm_enabled)
1733*4882a593Smuzhiyun ra_list->max_amsdu = priv->max_amsdu;
1734*4882a593Smuzhiyun }
1735*4882a593Smuzhiyun }
1736*4882a593Smuzhiyun
1737*4882a593Smuzhiyun PRINTM_NETINTF(MDATA, priv);
1738*4882a593Smuzhiyun PRINTM(MDATA, "ralist %p: is_wmm_enabled=%d max_amsdu=%d\n",
1739*4882a593Smuzhiyun ra_list, ra_list->is_wmm_enabled, ra_list->max_amsdu);
1740*4882a593Smuzhiyun
1741*4882a593Smuzhiyun if (ra_list->is_wmm_enabled) {
1742*4882a593Smuzhiyun ra_list->packet_count = 0;
1743*4882a593Smuzhiyun ra_list->ba_packet_threshold =
1744*4882a593Smuzhiyun wlan_get_random_ba_threshold(pmadapter);
1745*4882a593Smuzhiyun }
1746*4882a593Smuzhiyun
1747*4882a593Smuzhiyun util_enqueue_list_tail(pmadapter->pmoal_handle,
1748*4882a593Smuzhiyun &priv->wmm.tid_tbl_ptr[i].ra_list,
1749*4882a593Smuzhiyun (pmlan_linked_list)ra_list, MNULL,
1750*4882a593Smuzhiyun MNULL);
1751*4882a593Smuzhiyun
1752*4882a593Smuzhiyun if (!priv->wmm.tid_tbl_ptr[i].ra_list_curr)
1753*4882a593Smuzhiyun priv->wmm.tid_tbl_ptr[i].ra_list_curr = ra_list;
1754*4882a593Smuzhiyun }
1755*4882a593Smuzhiyun
1756*4882a593Smuzhiyun LEAVE();
1757*4882a593Smuzhiyun }
1758*4882a593Smuzhiyun
1759*4882a593Smuzhiyun /**
1760*4882a593Smuzhiyun * @brief Initialize the WMM parameter.
1761*4882a593Smuzhiyun *
1762*4882a593Smuzhiyun * @param pmadapter Pointer to the mlan_adapter data structure
1763*4882a593Smuzhiyun *
1764*4882a593Smuzhiyun * @return N/A
1765*4882a593Smuzhiyun */
wlan_init_wmm_param(pmlan_adapter pmadapter)1766*4882a593Smuzhiyun t_void wlan_init_wmm_param(pmlan_adapter pmadapter)
1767*4882a593Smuzhiyun {
1768*4882a593Smuzhiyun /* Reuse the same structure of WmmAcParameters_t for configuration
1769*4882a593Smuzhiyun * purpose here. the definition of acm bit is changed to ucm (user
1770*4882a593Smuzhiyun * configuration mode) FW will take the setting of
1771*4882a593Smuzhiyun * aifsn,ecw_max,ecw_min, tx_op_limit only when ucm is set to 1.
1772*4882a593Smuzhiyun * othewise the default setting/behavoir in firmware will be used.
1773*4882a593Smuzhiyun */
1774*4882a593Smuzhiyun pmadapter->ac_params[AC_BE].aci_aifsn.acm = 0;
1775*4882a593Smuzhiyun pmadapter->ac_params[AC_BE].aci_aifsn.aci = AC_BE;
1776*4882a593Smuzhiyun pmadapter->ac_params[AC_BE].aci_aifsn.aifsn = 3;
1777*4882a593Smuzhiyun pmadapter->ac_params[AC_BE].ecw.ecw_max = 10;
1778*4882a593Smuzhiyun pmadapter->ac_params[AC_BE].ecw.ecw_min = 4;
1779*4882a593Smuzhiyun pmadapter->ac_params[AC_BE].tx_op_limit = 0;
1780*4882a593Smuzhiyun
1781*4882a593Smuzhiyun pmadapter->ac_params[AC_BK].aci_aifsn.acm = 0;
1782*4882a593Smuzhiyun pmadapter->ac_params[AC_BK].aci_aifsn.aci = AC_BK;
1783*4882a593Smuzhiyun pmadapter->ac_params[AC_BK].aci_aifsn.aifsn = 7;
1784*4882a593Smuzhiyun pmadapter->ac_params[AC_BK].ecw.ecw_max = 10;
1785*4882a593Smuzhiyun pmadapter->ac_params[AC_BK].ecw.ecw_min = 4;
1786*4882a593Smuzhiyun pmadapter->ac_params[AC_BK].tx_op_limit = 0;
1787*4882a593Smuzhiyun
1788*4882a593Smuzhiyun pmadapter->ac_params[AC_VI].aci_aifsn.acm = 0;
1789*4882a593Smuzhiyun pmadapter->ac_params[AC_VI].aci_aifsn.aci = AC_VI;
1790*4882a593Smuzhiyun pmadapter->ac_params[AC_VI].aci_aifsn.aifsn = 2;
1791*4882a593Smuzhiyun pmadapter->ac_params[AC_VI].ecw.ecw_max = 4;
1792*4882a593Smuzhiyun pmadapter->ac_params[AC_VI].ecw.ecw_min = 3;
1793*4882a593Smuzhiyun pmadapter->ac_params[AC_VI].tx_op_limit = 188;
1794*4882a593Smuzhiyun
1795*4882a593Smuzhiyun pmadapter->ac_params[AC_VO].aci_aifsn.acm = 0;
1796*4882a593Smuzhiyun pmadapter->ac_params[AC_VO].aci_aifsn.aci = AC_VO;
1797*4882a593Smuzhiyun pmadapter->ac_params[AC_VO].aci_aifsn.aifsn = 2;
1798*4882a593Smuzhiyun pmadapter->ac_params[AC_VO].ecw.ecw_max = 3;
1799*4882a593Smuzhiyun pmadapter->ac_params[AC_VO].ecw.ecw_min = 2;
1800*4882a593Smuzhiyun pmadapter->ac_params[AC_VO].tx_op_limit = 102;
1801*4882a593Smuzhiyun }
1802*4882a593Smuzhiyun
1803*4882a593Smuzhiyun /**
1804*4882a593Smuzhiyun * @brief Initialize the WMM state information and the WMM data path queues.
1805*4882a593Smuzhiyun *
1806*4882a593Smuzhiyun * @param pmadapter Pointer to the mlan_adapter data structure
1807*4882a593Smuzhiyun *
1808*4882a593Smuzhiyun * @return N/A
1809*4882a593Smuzhiyun */
wlan_wmm_init(pmlan_adapter pmadapter)1810*4882a593Smuzhiyun t_void wlan_wmm_init(pmlan_adapter pmadapter)
1811*4882a593Smuzhiyun {
1812*4882a593Smuzhiyun int i, j;
1813*4882a593Smuzhiyun pmlan_private priv;
1814*4882a593Smuzhiyun
1815*4882a593Smuzhiyun ENTER();
1816*4882a593Smuzhiyun
1817*4882a593Smuzhiyun for (j = 0; j < pmadapter->priv_num; ++j) {
1818*4882a593Smuzhiyun priv = pmadapter->priv[j];
1819*4882a593Smuzhiyun if (priv) {
1820*4882a593Smuzhiyun for (i = 0; i < MAX_NUM_TID; ++i) {
1821*4882a593Smuzhiyun priv->aggr_prio_tbl[i].amsdu =
1822*4882a593Smuzhiyun tos_to_tid_inv[i];
1823*4882a593Smuzhiyun priv->aggr_prio_tbl[i].ampdu_ap =
1824*4882a593Smuzhiyun priv->aggr_prio_tbl[i].ampdu_user =
1825*4882a593Smuzhiyun tos_to_tid_inv[i];
1826*4882a593Smuzhiyun priv->ibss_ampdu[i] =
1827*4882a593Smuzhiyun priv->aggr_prio_tbl[i].ampdu_user;
1828*4882a593Smuzhiyun priv->wmm.pkts_queued[i] = 0;
1829*4882a593Smuzhiyun priv->wmm.pkts_paused[i] = 0;
1830*4882a593Smuzhiyun priv->wmm.tid_tbl_ptr[i].ra_list_curr = MNULL;
1831*4882a593Smuzhiyun }
1832*4882a593Smuzhiyun priv->wmm.drv_pkt_delay_max = WMM_DRV_DELAY_MAX;
1833*4882a593Smuzhiyun
1834*4882a593Smuzhiyun priv->aggr_prio_tbl[6].amsdu = BA_STREAM_NOT_ALLOWED;
1835*4882a593Smuzhiyun priv->aggr_prio_tbl[7].amsdu = BA_STREAM_NOT_ALLOWED;
1836*4882a593Smuzhiyun priv->aggr_prio_tbl[6].ampdu_ap =
1837*4882a593Smuzhiyun priv->aggr_prio_tbl[6].ampdu_user =
1838*4882a593Smuzhiyun BA_STREAM_NOT_ALLOWED;
1839*4882a593Smuzhiyun priv->ibss_ampdu[6] = BA_STREAM_NOT_ALLOWED;
1840*4882a593Smuzhiyun
1841*4882a593Smuzhiyun priv->aggr_prio_tbl[7].ampdu_ap =
1842*4882a593Smuzhiyun priv->aggr_prio_tbl[7].ampdu_user =
1843*4882a593Smuzhiyun BA_STREAM_NOT_ALLOWED;
1844*4882a593Smuzhiyun priv->ibss_ampdu[7] = BA_STREAM_NOT_ALLOWED;
1845*4882a593Smuzhiyun
1846*4882a593Smuzhiyun priv->add_ba_param.timeout =
1847*4882a593Smuzhiyun MLAN_DEFAULT_BLOCK_ACK_TIMEOUT;
1848*4882a593Smuzhiyun #ifdef STA_SUPPORT
1849*4882a593Smuzhiyun if (priv->bss_type == MLAN_BSS_TYPE_STA) {
1850*4882a593Smuzhiyun priv->add_ba_param.tx_win_size =
1851*4882a593Smuzhiyun MLAN_STA_AMPDU_DEF_TXWINSIZE;
1852*4882a593Smuzhiyun priv->add_ba_param.rx_win_size =
1853*4882a593Smuzhiyun MLAN_STA_AMPDU_DEF_RXWINSIZE;
1854*4882a593Smuzhiyun }
1855*4882a593Smuzhiyun #endif
1856*4882a593Smuzhiyun #ifdef WIFI_DIRECT_SUPPORT
1857*4882a593Smuzhiyun if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT) {
1858*4882a593Smuzhiyun priv->add_ba_param.tx_win_size =
1859*4882a593Smuzhiyun MLAN_WFD_AMPDU_DEF_TXRXWINSIZE;
1860*4882a593Smuzhiyun priv->add_ba_param.rx_win_size =
1861*4882a593Smuzhiyun MLAN_WFD_AMPDU_DEF_TXRXWINSIZE;
1862*4882a593Smuzhiyun }
1863*4882a593Smuzhiyun #endif
1864*4882a593Smuzhiyun #ifdef UAP_SUPPORT
1865*4882a593Smuzhiyun if (priv->bss_type == MLAN_BSS_TYPE_UAP) {
1866*4882a593Smuzhiyun priv->add_ba_param.tx_win_size =
1867*4882a593Smuzhiyun MLAN_UAP_AMPDU_DEF_TXWINSIZE;
1868*4882a593Smuzhiyun priv->add_ba_param.rx_win_size =
1869*4882a593Smuzhiyun MLAN_UAP_AMPDU_DEF_RXWINSIZE;
1870*4882a593Smuzhiyun }
1871*4882a593Smuzhiyun #endif
1872*4882a593Smuzhiyun priv->user_rxwinsize = priv->add_ba_param.rx_win_size;
1873*4882a593Smuzhiyun priv->add_ba_param.tx_amsdu = MTRUE;
1874*4882a593Smuzhiyun priv->add_ba_param.rx_amsdu = MTRUE;
1875*4882a593Smuzhiyun memset(priv->adapter, priv->rx_seq, 0xff,
1876*4882a593Smuzhiyun sizeof(priv->rx_seq));
1877*4882a593Smuzhiyun wlan_wmm_default_queue_priorities(priv);
1878*4882a593Smuzhiyun }
1879*4882a593Smuzhiyun }
1880*4882a593Smuzhiyun
1881*4882a593Smuzhiyun LEAVE();
1882*4882a593Smuzhiyun }
1883*4882a593Smuzhiyun
1884*4882a593Smuzhiyun /**
1885*4882a593Smuzhiyun * @brief Setup the queue priorities and downgrade any queues as required
1886*4882a593Smuzhiyun * by the WMM info. Setups default values if WMM is not active
1887*4882a593Smuzhiyun * for this association.
1888*4882a593Smuzhiyun *
1889*4882a593Smuzhiyun * @param priv Pointer to the mlan_private driver data struct
1890*4882a593Smuzhiyun *
1891*4882a593Smuzhiyun * @return N/A
1892*4882a593Smuzhiyun */
wlan_wmm_setup_queues(pmlan_private priv)1893*4882a593Smuzhiyun void wlan_wmm_setup_queues(pmlan_private priv)
1894*4882a593Smuzhiyun {
1895*4882a593Smuzhiyun ENTER();
1896*4882a593Smuzhiyun wlan_wmm_setup_queue_priorities(priv, MNULL);
1897*4882a593Smuzhiyun wlan_wmm_setup_ac_downgrade(priv);
1898*4882a593Smuzhiyun LEAVE();
1899*4882a593Smuzhiyun }
1900*4882a593Smuzhiyun
1901*4882a593Smuzhiyun #ifdef STA_SUPPORT
1902*4882a593Smuzhiyun /**
1903*4882a593Smuzhiyun * @brief Send a command to firmware to retrieve the current WMM status
1904*4882a593Smuzhiyun *
1905*4882a593Smuzhiyun * @param priv Pointer to the mlan_private driver data struct
1906*4882a593Smuzhiyun *
1907*4882a593Smuzhiyun * @return MLAN_STATUS_SUCCESS; MLAN_STATUS_FAILURE
1908*4882a593Smuzhiyun */
wlan_cmd_wmm_status_change(pmlan_private priv)1909*4882a593Smuzhiyun mlan_status wlan_cmd_wmm_status_change(pmlan_private priv)
1910*4882a593Smuzhiyun {
1911*4882a593Smuzhiyun mlan_status ret = MLAN_STATUS_SUCCESS;
1912*4882a593Smuzhiyun
1913*4882a593Smuzhiyun ENTER();
1914*4882a593Smuzhiyun
1915*4882a593Smuzhiyun ret = wlan_prepare_cmd(priv, HostCmd_CMD_WMM_GET_STATUS, 0, 0, MNULL,
1916*4882a593Smuzhiyun MNULL);
1917*4882a593Smuzhiyun LEAVE();
1918*4882a593Smuzhiyun return ret;
1919*4882a593Smuzhiyun }
1920*4882a593Smuzhiyun #endif
1921*4882a593Smuzhiyun
1922*4882a593Smuzhiyun /**
1923*4882a593Smuzhiyun * @brief Check if wmm TX queue is empty
1924*4882a593Smuzhiyun *
1925*4882a593Smuzhiyun * @param pmadapter Pointer to the mlan_adapter driver data struct
1926*4882a593Smuzhiyun *
1927*4882a593Smuzhiyun * @return MFALSE if not empty; MTRUE if empty
1928*4882a593Smuzhiyun */
wlan_wmm_lists_empty(pmlan_adapter pmadapter)1929*4882a593Smuzhiyun int wlan_wmm_lists_empty(pmlan_adapter pmadapter)
1930*4882a593Smuzhiyun {
1931*4882a593Smuzhiyun int j;
1932*4882a593Smuzhiyun pmlan_private priv;
1933*4882a593Smuzhiyun
1934*4882a593Smuzhiyun ENTER();
1935*4882a593Smuzhiyun
1936*4882a593Smuzhiyun for (j = 0; j < pmadapter->priv_num; ++j) {
1937*4882a593Smuzhiyun priv = pmadapter->priv[j];
1938*4882a593Smuzhiyun if (priv) {
1939*4882a593Smuzhiyun if ((priv->port_ctrl_mode == MTRUE) &&
1940*4882a593Smuzhiyun (priv->port_open == MFALSE)) {
1941*4882a593Smuzhiyun PRINTM(MINFO,
1942*4882a593Smuzhiyun "wmm_lists_empty: PORT_CLOSED Ignore pkts from BSS%d\n",
1943*4882a593Smuzhiyun j);
1944*4882a593Smuzhiyun continue;
1945*4882a593Smuzhiyun }
1946*4882a593Smuzhiyun if (priv->tx_pause)
1947*4882a593Smuzhiyun continue;
1948*4882a593Smuzhiyun
1949*4882a593Smuzhiyun if (util_scalar_read(
1950*4882a593Smuzhiyun pmadapter->pmoal_handle,
1951*4882a593Smuzhiyun &priv->wmm.tx_pkts_queued,
1952*4882a593Smuzhiyun pmadapter->callbacks.moal_spin_lock,
1953*4882a593Smuzhiyun pmadapter->callbacks.moal_spin_unlock)) {
1954*4882a593Smuzhiyun LEAVE();
1955*4882a593Smuzhiyun return MFALSE;
1956*4882a593Smuzhiyun }
1957*4882a593Smuzhiyun }
1958*4882a593Smuzhiyun }
1959*4882a593Smuzhiyun
1960*4882a593Smuzhiyun LEAVE();
1961*4882a593Smuzhiyun return MTRUE;
1962*4882a593Smuzhiyun }
1963*4882a593Smuzhiyun
1964*4882a593Smuzhiyun /**
1965*4882a593Smuzhiyun * @brief Get ralist node
1966*4882a593Smuzhiyun *
1967*4882a593Smuzhiyun * @param priv Pointer to the mlan_private driver data struct
1968*4882a593Smuzhiyun * @param tid TID
1969*4882a593Smuzhiyun * @param ra_addr Pointer to the route address
1970*4882a593Smuzhiyun *
1971*4882a593Smuzhiyun * @return ra_list or MNULL
1972*4882a593Smuzhiyun */
wlan_wmm_get_ralist_node(pmlan_private priv,t_u8 tid,t_u8 * ra_addr)1973*4882a593Smuzhiyun raListTbl *wlan_wmm_get_ralist_node(pmlan_private priv, t_u8 tid, t_u8 *ra_addr)
1974*4882a593Smuzhiyun {
1975*4882a593Smuzhiyun raListTbl *ra_list;
1976*4882a593Smuzhiyun ENTER();
1977*4882a593Smuzhiyun ra_list =
1978*4882a593Smuzhiyun (raListTbl *)util_peek_list(priv->adapter->pmoal_handle,
1979*4882a593Smuzhiyun &priv->wmm.tid_tbl_ptr[tid].ra_list,
1980*4882a593Smuzhiyun MNULL, MNULL);
1981*4882a593Smuzhiyun while (ra_list &&
1982*4882a593Smuzhiyun (ra_list != (raListTbl *)&priv->wmm.tid_tbl_ptr[tid].ra_list)) {
1983*4882a593Smuzhiyun if (!memcmp(priv->adapter, ra_list->ra, ra_addr,
1984*4882a593Smuzhiyun MLAN_MAC_ADDR_LENGTH)) {
1985*4882a593Smuzhiyun LEAVE();
1986*4882a593Smuzhiyun return ra_list;
1987*4882a593Smuzhiyun }
1988*4882a593Smuzhiyun ra_list = ra_list->pnext;
1989*4882a593Smuzhiyun }
1990*4882a593Smuzhiyun LEAVE();
1991*4882a593Smuzhiyun return MNULL;
1992*4882a593Smuzhiyun }
1993*4882a593Smuzhiyun
1994*4882a593Smuzhiyun /**
1995*4882a593Smuzhiyun * @brief Check if RA list is valid or not
1996*4882a593Smuzhiyun *
1997*4882a593Smuzhiyun * @param priv Pointer to the mlan_private driver data struct
1998*4882a593Smuzhiyun * @param ra_list Pointer to raListTbl
1999*4882a593Smuzhiyun * @param ptrindex TID pointer index
2000*4882a593Smuzhiyun *
2001*4882a593Smuzhiyun * @return MTRUE- valid. MFALSE- invalid.
2002*4882a593Smuzhiyun */
wlan_is_ralist_valid(mlan_private * priv,raListTbl * ra_list,int ptrindex)2003*4882a593Smuzhiyun int wlan_is_ralist_valid(mlan_private *priv, raListTbl *ra_list, int ptrindex)
2004*4882a593Smuzhiyun {
2005*4882a593Smuzhiyun raListTbl *rlist;
2006*4882a593Smuzhiyun
2007*4882a593Smuzhiyun ENTER();
2008*4882a593Smuzhiyun
2009*4882a593Smuzhiyun rlist = (raListTbl *)util_peek_list(
2010*4882a593Smuzhiyun priv->adapter->pmoal_handle,
2011*4882a593Smuzhiyun &priv->wmm.tid_tbl_ptr[ptrindex].ra_list, MNULL, MNULL);
2012*4882a593Smuzhiyun
2013*4882a593Smuzhiyun while (rlist &&
2014*4882a593Smuzhiyun (rlist !=
2015*4882a593Smuzhiyun (raListTbl *)&priv->wmm.tid_tbl_ptr[ptrindex].ra_list)) {
2016*4882a593Smuzhiyun if (rlist == ra_list) {
2017*4882a593Smuzhiyun LEAVE();
2018*4882a593Smuzhiyun return MTRUE;
2019*4882a593Smuzhiyun }
2020*4882a593Smuzhiyun
2021*4882a593Smuzhiyun rlist = rlist->pnext;
2022*4882a593Smuzhiyun }
2023*4882a593Smuzhiyun LEAVE();
2024*4882a593Smuzhiyun return MFALSE;
2025*4882a593Smuzhiyun }
2026*4882a593Smuzhiyun
2027*4882a593Smuzhiyun /**
2028*4882a593Smuzhiyun * @brief Update an existing raList with a new RA and 11n capability
2029*4882a593Smuzhiyun *
2030*4882a593Smuzhiyun * @param priv Pointer to the mlan_private driver data struct
2031*4882a593Smuzhiyun * @param old_ra Old receiver address
2032*4882a593Smuzhiyun * @param new_ra New receiver address
2033*4882a593Smuzhiyun *
2034*4882a593Smuzhiyun * @return integer count of updated nodes
2035*4882a593Smuzhiyun */
wlan_ralist_update(mlan_private * priv,t_u8 * old_ra,t_u8 * new_ra)2036*4882a593Smuzhiyun int wlan_ralist_update(mlan_private *priv, t_u8 *old_ra, t_u8 *new_ra)
2037*4882a593Smuzhiyun {
2038*4882a593Smuzhiyun t_u8 tid;
2039*4882a593Smuzhiyun int update_count;
2040*4882a593Smuzhiyun raListTbl *ra_list;
2041*4882a593Smuzhiyun
2042*4882a593Smuzhiyun ENTER();
2043*4882a593Smuzhiyun
2044*4882a593Smuzhiyun update_count = 0;
2045*4882a593Smuzhiyun
2046*4882a593Smuzhiyun for (tid = 0; tid < MAX_NUM_TID; ++tid) {
2047*4882a593Smuzhiyun ra_list = wlan_wmm_get_ralist_node(priv, tid, old_ra);
2048*4882a593Smuzhiyun
2049*4882a593Smuzhiyun if (ra_list) {
2050*4882a593Smuzhiyun update_count++;
2051*4882a593Smuzhiyun
2052*4882a593Smuzhiyun if (queuing_ra_based(priv)) {
2053*4882a593Smuzhiyun ra_list->is_wmm_enabled =
2054*4882a593Smuzhiyun wlan_is_wmm_enabled(priv, new_ra);
2055*4882a593Smuzhiyun if (ra_list->is_wmm_enabled)
2056*4882a593Smuzhiyun ra_list->max_amsdu =
2057*4882a593Smuzhiyun get_station_max_amsdu_size(
2058*4882a593Smuzhiyun priv, new_ra);
2059*4882a593Smuzhiyun } else {
2060*4882a593Smuzhiyun ra_list->is_wmm_enabled = IS_11N_ENABLED(priv);
2061*4882a593Smuzhiyun if (ra_list->is_wmm_enabled)
2062*4882a593Smuzhiyun ra_list->max_amsdu = priv->max_amsdu;
2063*4882a593Smuzhiyun }
2064*4882a593Smuzhiyun
2065*4882a593Smuzhiyun ra_list->tx_pause = MFALSE;
2066*4882a593Smuzhiyun ra_list->packet_count = 0;
2067*4882a593Smuzhiyun ra_list->ba_packet_threshold =
2068*4882a593Smuzhiyun wlan_get_random_ba_threshold(priv->adapter);
2069*4882a593Smuzhiyun ra_list->amsdu_in_ampdu = MFALSE;
2070*4882a593Smuzhiyun ra_list->ba_status = BA_STREAM_NOT_SETUP;
2071*4882a593Smuzhiyun PRINTM(MINFO,
2072*4882a593Smuzhiyun "ralist_update: %p, %d, " MACSTR "-->" MACSTR
2073*4882a593Smuzhiyun "\n",
2074*4882a593Smuzhiyun ra_list, ra_list->is_wmm_enabled,
2075*4882a593Smuzhiyun MAC2STR(ra_list->ra), MAC2STR(new_ra));
2076*4882a593Smuzhiyun
2077*4882a593Smuzhiyun memcpy_ext(priv->adapter, ra_list->ra, new_ra,
2078*4882a593Smuzhiyun MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
2079*4882a593Smuzhiyun }
2080*4882a593Smuzhiyun }
2081*4882a593Smuzhiyun
2082*4882a593Smuzhiyun LEAVE();
2083*4882a593Smuzhiyun return update_count;
2084*4882a593Smuzhiyun }
2085*4882a593Smuzhiyun
2086*4882a593Smuzhiyun /**
2087*4882a593Smuzhiyun * @brief Add packet to WMM queue
2088*4882a593Smuzhiyun *
2089*4882a593Smuzhiyun * @param pmadapter Pointer to the mlan_adapter driver data struct
2090*4882a593Smuzhiyun * @param pmbuf Pointer to the mlan_buffer data struct
2091*4882a593Smuzhiyun *
2092*4882a593Smuzhiyun * @return N/A
2093*4882a593Smuzhiyun */
wlan_wmm_add_buf_txqueue(pmlan_adapter pmadapter,pmlan_buffer pmbuf)2094*4882a593Smuzhiyun t_void wlan_wmm_add_buf_txqueue(pmlan_adapter pmadapter, pmlan_buffer pmbuf)
2095*4882a593Smuzhiyun {
2096*4882a593Smuzhiyun pmlan_private priv = pmadapter->priv[pmbuf->bss_index];
2097*4882a593Smuzhiyun t_u32 tid;
2098*4882a593Smuzhiyun raListTbl *ra_list;
2099*4882a593Smuzhiyun t_u8 ra[MLAN_MAC_ADDR_LENGTH], tid_down;
2100*4882a593Smuzhiyun tdlsStatus_e status;
2101*4882a593Smuzhiyun #ifdef UAP_SUPPORT
2102*4882a593Smuzhiyun psta_node sta_ptr = MNULL;
2103*4882a593Smuzhiyun #endif
2104*4882a593Smuzhiyun
2105*4882a593Smuzhiyun ENTER();
2106*4882a593Smuzhiyun
2107*4882a593Smuzhiyun pmbuf->buf_type = MLAN_BUF_TYPE_DATA;
2108*4882a593Smuzhiyun if (!priv->media_connected) {
2109*4882a593Smuzhiyun PRINTM_NETINTF(MWARN, priv);
2110*4882a593Smuzhiyun PRINTM(MWARN, "Drop packet %p in disconnect state\n", pmbuf);
2111*4882a593Smuzhiyun wlan_write_data_complete(pmadapter, pmbuf, MLAN_STATUS_FAILURE);
2112*4882a593Smuzhiyun LEAVE();
2113*4882a593Smuzhiyun return;
2114*4882a593Smuzhiyun }
2115*4882a593Smuzhiyun tid = pmbuf->priority;
2116*4882a593Smuzhiyun pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
2117*4882a593Smuzhiyun priv->wmm.ra_list_spinlock);
2118*4882a593Smuzhiyun tid_down = wlan_wmm_downgrade_tid(priv, tid);
2119*4882a593Smuzhiyun
2120*4882a593Smuzhiyun /* In case of infra as we have already created the list during
2121*4882a593Smuzhiyun association we just don't have to call get_queue_raptr, we will have
2122*4882a593Smuzhiyun only 1 raptr for a tid in case of infra */
2123*4882a593Smuzhiyun if (!queuing_ra_based(priv)) {
2124*4882a593Smuzhiyun memcpy_ext(pmadapter, ra, pmbuf->pbuf + pmbuf->data_offset,
2125*4882a593Smuzhiyun MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
2126*4882a593Smuzhiyun status = wlan_get_tdls_link_status(priv, ra);
2127*4882a593Smuzhiyun if (MTRUE == wlan_is_tdls_link_setup(status)) {
2128*4882a593Smuzhiyun ra_list = wlan_wmm_get_queue_raptr(priv, tid_down, ra);
2129*4882a593Smuzhiyun pmbuf->flags |= MLAN_BUF_FLAG_TDLS;
2130*4882a593Smuzhiyun } else if (status == TDLS_SETUP_INPROGRESS) {
2131*4882a593Smuzhiyun wlan_add_buf_tdls_txqueue(priv, pmbuf);
2132*4882a593Smuzhiyun pmadapter->callbacks.moal_spin_unlock(
2133*4882a593Smuzhiyun pmadapter->pmoal_handle,
2134*4882a593Smuzhiyun priv->wmm.ra_list_spinlock);
2135*4882a593Smuzhiyun LEAVE();
2136*4882a593Smuzhiyun return;
2137*4882a593Smuzhiyun } else
2138*4882a593Smuzhiyun ra_list = (raListTbl *)util_peek_list(
2139*4882a593Smuzhiyun pmadapter->pmoal_handle,
2140*4882a593Smuzhiyun &priv->wmm.tid_tbl_ptr[tid_down].ra_list, MNULL,
2141*4882a593Smuzhiyun MNULL);
2142*4882a593Smuzhiyun } else {
2143*4882a593Smuzhiyun memcpy_ext(pmadapter, ra, pmbuf->pbuf + pmbuf->data_offset,
2144*4882a593Smuzhiyun MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
2145*4882a593Smuzhiyun /** put multicast/broadcast packet in the same ralist */
2146*4882a593Smuzhiyun if (ra[0] & 0x01)
2147*4882a593Smuzhiyun memset(pmadapter, ra, 0xff, sizeof(ra));
2148*4882a593Smuzhiyun #ifdef UAP_SUPPORT
2149*4882a593Smuzhiyun else if (priv->bss_type == MLAN_BSS_TYPE_UAP) {
2150*4882a593Smuzhiyun sta_ptr = wlan_get_station_entry(priv, ra);
2151*4882a593Smuzhiyun if (sta_ptr) {
2152*4882a593Smuzhiyun sta_ptr->stats.tx_bytes += pmbuf->data_len;
2153*4882a593Smuzhiyun sta_ptr->stats.tx_packets++;
2154*4882a593Smuzhiyun if (!sta_ptr->is_wmm_enabled &&
2155*4882a593Smuzhiyun !priv->is_11ac_enabled) {
2156*4882a593Smuzhiyun tid_down = wlan_wmm_downgrade_tid(priv,
2157*4882a593Smuzhiyun 0xff);
2158*4882a593Smuzhiyun }
2159*4882a593Smuzhiyun }
2160*4882a593Smuzhiyun }
2161*4882a593Smuzhiyun #endif
2162*4882a593Smuzhiyun ra_list = wlan_wmm_get_queue_raptr(priv, tid_down, ra);
2163*4882a593Smuzhiyun }
2164*4882a593Smuzhiyun
2165*4882a593Smuzhiyun if (!ra_list) {
2166*4882a593Smuzhiyun PRINTM_NETINTF(MWARN, priv);
2167*4882a593Smuzhiyun PRINTM(MWARN,
2168*4882a593Smuzhiyun "Drop packet %p, ra_list=%p, media_connected=%d\n",
2169*4882a593Smuzhiyun pmbuf, ra_list, priv->media_connected);
2170*4882a593Smuzhiyun pmadapter->callbacks.moal_spin_unlock(
2171*4882a593Smuzhiyun pmadapter->pmoal_handle, priv->wmm.ra_list_spinlock);
2172*4882a593Smuzhiyun wlan_write_data_complete(pmadapter, pmbuf, MLAN_STATUS_FAILURE);
2173*4882a593Smuzhiyun LEAVE();
2174*4882a593Smuzhiyun return;
2175*4882a593Smuzhiyun }
2176*4882a593Smuzhiyun
2177*4882a593Smuzhiyun PRINTM_NETINTF(MDATA, priv);
2178*4882a593Smuzhiyun PRINTM(MDATA,
2179*4882a593Smuzhiyun "Adding pkt %p (priority=%d, tid_down=%d) to ra_list %p\n",
2180*4882a593Smuzhiyun pmbuf, pmbuf->priority, tid_down, ra_list);
2181*4882a593Smuzhiyun util_enqueue_list_tail(pmadapter->pmoal_handle, &ra_list->buf_head,
2182*4882a593Smuzhiyun (pmlan_linked_list)pmbuf, MNULL, MNULL);
2183*4882a593Smuzhiyun
2184*4882a593Smuzhiyun ra_list->total_pkts++;
2185*4882a593Smuzhiyun ra_list->packet_count++;
2186*4882a593Smuzhiyun
2187*4882a593Smuzhiyun priv->wmm.pkts_queued[tid_down]++;
2188*4882a593Smuzhiyun if (ra_list->tx_pause) {
2189*4882a593Smuzhiyun priv->wmm.pkts_paused[tid_down]++;
2190*4882a593Smuzhiyun } else {
2191*4882a593Smuzhiyun util_scalar_increment(pmadapter->pmoal_handle,
2192*4882a593Smuzhiyun &priv->wmm.tx_pkts_queued, MNULL, MNULL);
2193*4882a593Smuzhiyun /* if highest_queued_prio < prio(tid_down), set it to
2194*4882a593Smuzhiyun * prio(tid_down) */
2195*4882a593Smuzhiyun util_scalar_conditional_write(
2196*4882a593Smuzhiyun pmadapter->pmoal_handle, &priv->wmm.highest_queued_prio,
2197*4882a593Smuzhiyun MLAN_SCALAR_COND_LESS_THAN, tos_to_tid_inv[tid_down],
2198*4882a593Smuzhiyun tos_to_tid_inv[tid_down], MNULL, MNULL);
2199*4882a593Smuzhiyun }
2200*4882a593Smuzhiyun /* Record the current time the packet was queued; used to determine
2201*4882a593Smuzhiyun * the amount of time the packet was queued in the driver before it
2202*4882a593Smuzhiyun * was sent to the firmware. The delay is then sent along with the
2203*4882a593Smuzhiyun * packet to the firmware for aggregate delay calculation for stats
2204*4882a593Smuzhiyun * and MSDU lifetime expiry.
2205*4882a593Smuzhiyun */
2206*4882a593Smuzhiyun pmadapter->callbacks.moal_get_system_time(
2207*4882a593Smuzhiyun pmadapter->pmoal_handle, &pmbuf->in_ts_sec, &pmbuf->in_ts_usec);
2208*4882a593Smuzhiyun pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
2209*4882a593Smuzhiyun priv->wmm.ra_list_spinlock);
2210*4882a593Smuzhiyun
2211*4882a593Smuzhiyun LEAVE();
2212*4882a593Smuzhiyun }
2213*4882a593Smuzhiyun
2214*4882a593Smuzhiyun #ifdef STA_SUPPORT
2215*4882a593Smuzhiyun /**
2216*4882a593Smuzhiyun * @brief Process the GET_WMM_STATUS command response from firmware
2217*4882a593Smuzhiyun *
2218*4882a593Smuzhiyun * The GET_WMM_STATUS response may contain multiple TLVs for:
2219*4882a593Smuzhiyun * - AC Queue status TLVs
2220*4882a593Smuzhiyun * - Current WMM Parameter IE TLV
2221*4882a593Smuzhiyun * - Admission Control action frame TLVs
2222*4882a593Smuzhiyun *
2223*4882a593Smuzhiyun * This function parses the TLVs and then calls further functions
2224*4882a593Smuzhiyun * to process any changes in the queue prioritize or state.
2225*4882a593Smuzhiyun *
2226*4882a593Smuzhiyun * @param priv Pointer to the mlan_private driver data struct
2227*4882a593Smuzhiyun * @param ptlv Pointer to the tlv block returned in the response.
2228*4882a593Smuzhiyun * @param resp_len Length of TLV block
2229*4882a593Smuzhiyun *
2230*4882a593Smuzhiyun * @return MLAN_STATUS_SUCCESS
2231*4882a593Smuzhiyun */
wlan_ret_wmm_get_status(pmlan_private priv,t_u8 * ptlv,int resp_len)2232*4882a593Smuzhiyun mlan_status wlan_ret_wmm_get_status(pmlan_private priv, t_u8 *ptlv,
2233*4882a593Smuzhiyun int resp_len)
2234*4882a593Smuzhiyun {
2235*4882a593Smuzhiyun t_u8 *pcurrent = ptlv;
2236*4882a593Smuzhiyun t_u32 tlv_len;
2237*4882a593Smuzhiyun t_u8 send_wmm_event;
2238*4882a593Smuzhiyun MrvlIEtypes_Data_t *ptlv_hdr;
2239*4882a593Smuzhiyun MrvlIEtypes_WmmQueueStatus_t *ptlv_wmm_q_status;
2240*4882a593Smuzhiyun IEEEtypes_WmmParameter_t *pwmm_param_ie = MNULL;
2241*4882a593Smuzhiyun WmmAcStatus_t *pac_status;
2242*4882a593Smuzhiyun
2243*4882a593Smuzhiyun MrvlIETypes_ActionFrame_t *ptlv_action;
2244*4882a593Smuzhiyun IEEEtypes_Action_WMM_AddTsRsp_t *padd_ts_rsp;
2245*4882a593Smuzhiyun IEEEtypes_Action_WMM_DelTs_t *pdel_ts;
2246*4882a593Smuzhiyun
2247*4882a593Smuzhiyun ENTER();
2248*4882a593Smuzhiyun
2249*4882a593Smuzhiyun send_wmm_event = MFALSE;
2250*4882a593Smuzhiyun
2251*4882a593Smuzhiyun PRINTM(MINFO, "WMM: WMM_GET_STATUS cmdresp received: %d\n", resp_len);
2252*4882a593Smuzhiyun HEXDUMP("CMD_RESP: WMM_GET_STATUS", pcurrent, resp_len);
2253*4882a593Smuzhiyun
2254*4882a593Smuzhiyun while (resp_len >= (int)sizeof(ptlv_hdr->header)) {
2255*4882a593Smuzhiyun ptlv_hdr = (MrvlIEtypes_Data_t *)pcurrent;
2256*4882a593Smuzhiyun tlv_len = wlan_le16_to_cpu(ptlv_hdr->header.len);
2257*4882a593Smuzhiyun if ((int)(tlv_len + sizeof(ptlv_hdr->header)) > resp_len) {
2258*4882a593Smuzhiyun PRINTM(MERROR,
2259*4882a593Smuzhiyun "WMM get status: Error in processing TLV buffer\n");
2260*4882a593Smuzhiyun resp_len = 0;
2261*4882a593Smuzhiyun continue;
2262*4882a593Smuzhiyun }
2263*4882a593Smuzhiyun
2264*4882a593Smuzhiyun switch (wlan_le16_to_cpu(ptlv_hdr->header.type)) {
2265*4882a593Smuzhiyun case TLV_TYPE_WMMQSTATUS:
2266*4882a593Smuzhiyun ptlv_wmm_q_status =
2267*4882a593Smuzhiyun (MrvlIEtypes_WmmQueueStatus_t *)ptlv_hdr;
2268*4882a593Smuzhiyun PRINTM(MEVENT, "WMM_STATUS: QSTATUS TLV: %d\n",
2269*4882a593Smuzhiyun ptlv_wmm_q_status->queue_index);
2270*4882a593Smuzhiyun
2271*4882a593Smuzhiyun PRINTM(MINFO,
2272*4882a593Smuzhiyun "CMD_RESP: WMM_GET_STATUS: QSTATUS TLV: %d, %d, %d\n",
2273*4882a593Smuzhiyun ptlv_wmm_q_status->queue_index,
2274*4882a593Smuzhiyun ptlv_wmm_q_status->flow_required,
2275*4882a593Smuzhiyun ptlv_wmm_q_status->disabled);
2276*4882a593Smuzhiyun
2277*4882a593Smuzhiyun /* Pick the minimum among these to avoid array out of
2278*4882a593Smuzhiyun * bounds */
2279*4882a593Smuzhiyun ptlv_wmm_q_status->queue_index = MIN(
2280*4882a593Smuzhiyun ptlv_wmm_q_status->queue_index, MAX_AC_QUEUES);
2281*4882a593Smuzhiyun
2282*4882a593Smuzhiyun pac_status =
2283*4882a593Smuzhiyun &priv->wmm.ac_status[ptlv_wmm_q_status
2284*4882a593Smuzhiyun ->queue_index];
2285*4882a593Smuzhiyun pac_status->disabled = ptlv_wmm_q_status->disabled;
2286*4882a593Smuzhiyun pac_status->flow_required =
2287*4882a593Smuzhiyun ptlv_wmm_q_status->flow_required;
2288*4882a593Smuzhiyun pac_status->flow_created =
2289*4882a593Smuzhiyun ptlv_wmm_q_status->flow_created;
2290*4882a593Smuzhiyun break;
2291*4882a593Smuzhiyun
2292*4882a593Smuzhiyun case TLV_TYPE_VENDOR_SPECIFIC_IE: /* WMM_IE */
2293*4882a593Smuzhiyun /*
2294*4882a593Smuzhiyun * Point the regular IEEE IE 2 bytes into the NXP IE
2295*4882a593Smuzhiyun * and setup the IEEE IE type and length byte fields
2296*4882a593Smuzhiyun */
2297*4882a593Smuzhiyun
2298*4882a593Smuzhiyun PRINTM(MEVENT, "WMM STATUS: WMM IE\n");
2299*4882a593Smuzhiyun
2300*4882a593Smuzhiyun HEXDUMP("WMM: WMM TLV:", (t_u8 *)ptlv_hdr, tlv_len + 4);
2301*4882a593Smuzhiyun
2302*4882a593Smuzhiyun pwmm_param_ie =
2303*4882a593Smuzhiyun (IEEEtypes_WmmParameter_t *)(pcurrent + 2);
2304*4882a593Smuzhiyun pwmm_param_ie->vend_hdr.len = (t_u8)tlv_len;
2305*4882a593Smuzhiyun pwmm_param_ie->vend_hdr.element_id = WMM_IE;
2306*4882a593Smuzhiyun
2307*4882a593Smuzhiyun PRINTM(MINFO,
2308*4882a593Smuzhiyun "CMD_RESP: WMM_GET_STATUS: WMM Parameter Set: %d\n",
2309*4882a593Smuzhiyun pwmm_param_ie->qos_info.para_set_count);
2310*4882a593Smuzhiyun
2311*4882a593Smuzhiyun memcpy_ext(priv->adapter,
2312*4882a593Smuzhiyun (t_u8 *)&priv->curr_bss_params.bss_descriptor
2313*4882a593Smuzhiyun .wmm_ie,
2314*4882a593Smuzhiyun pwmm_param_ie,
2315*4882a593Smuzhiyun (pwmm_param_ie->vend_hdr.len + 2),
2316*4882a593Smuzhiyun sizeof(IEEEtypes_WmmParameter_t));
2317*4882a593Smuzhiyun send_wmm_event = MTRUE;
2318*4882a593Smuzhiyun break;
2319*4882a593Smuzhiyun
2320*4882a593Smuzhiyun case TLV_TYPE_IEEE_ACTION_FRAME:
2321*4882a593Smuzhiyun PRINTM(MEVENT, "WMM_STATUS: IEEE Action Frame\n");
2322*4882a593Smuzhiyun ptlv_action = (MrvlIETypes_ActionFrame_t *)pcurrent;
2323*4882a593Smuzhiyun
2324*4882a593Smuzhiyun ptlv_action->actionFrame.wmmAc.tspecAct.category =
2325*4882a593Smuzhiyun wlan_le32_to_cpu(ptlv_action->actionFrame.wmmAc
2326*4882a593Smuzhiyun .tspecAct.category);
2327*4882a593Smuzhiyun if (ptlv_action->actionFrame.wmmAc.tspecAct.category ==
2328*4882a593Smuzhiyun IEEE_MGMT_ACTION_CATEGORY_WMM_TSPEC) {
2329*4882a593Smuzhiyun ptlv_action->actionFrame.wmmAc.tspecAct.action =
2330*4882a593Smuzhiyun wlan_le32_to_cpu(
2331*4882a593Smuzhiyun ptlv_action->actionFrame.wmmAc
2332*4882a593Smuzhiyun .tspecAct.action);
2333*4882a593Smuzhiyun switch (ptlv_action->actionFrame.wmmAc.tspecAct
2334*4882a593Smuzhiyun .action) {
2335*4882a593Smuzhiyun case TSPEC_ACTION_CODE_ADDTS_RSP:
2336*4882a593Smuzhiyun padd_ts_rsp = &ptlv_action->actionFrame
2337*4882a593Smuzhiyun .wmmAc.addTsRsp;
2338*4882a593Smuzhiyun wlan_send_wmmac_host_event(
2339*4882a593Smuzhiyun priv, "ADDTS_RSP",
2340*4882a593Smuzhiyun ptlv_action->srcAddr,
2341*4882a593Smuzhiyun padd_ts_rsp->tspecIE.TspecBody
2342*4882a593Smuzhiyun .TSInfo.TID,
2343*4882a593Smuzhiyun padd_ts_rsp->tspecIE.TspecBody
2344*4882a593Smuzhiyun .TSInfo.UserPri,
2345*4882a593Smuzhiyun padd_ts_rsp->statusCode);
2346*4882a593Smuzhiyun break;
2347*4882a593Smuzhiyun
2348*4882a593Smuzhiyun case TSPEC_ACTION_CODE_DELTS:
2349*4882a593Smuzhiyun pdel_ts = &ptlv_action->actionFrame
2350*4882a593Smuzhiyun .wmmAc.delTs;
2351*4882a593Smuzhiyun wlan_send_wmmac_host_event(
2352*4882a593Smuzhiyun priv, "DELTS_RX",
2353*4882a593Smuzhiyun ptlv_action->srcAddr,
2354*4882a593Smuzhiyun pdel_ts->tspecIE.TspecBody
2355*4882a593Smuzhiyun .TSInfo.TID,
2356*4882a593Smuzhiyun pdel_ts->tspecIE.TspecBody
2357*4882a593Smuzhiyun .TSInfo.UserPri,
2358*4882a593Smuzhiyun pdel_ts->reasonCode);
2359*4882a593Smuzhiyun break;
2360*4882a593Smuzhiyun
2361*4882a593Smuzhiyun case TSPEC_ACTION_CODE_ADDTS_REQ:
2362*4882a593Smuzhiyun default:
2363*4882a593Smuzhiyun break;
2364*4882a593Smuzhiyun }
2365*4882a593Smuzhiyun }
2366*4882a593Smuzhiyun break;
2367*4882a593Smuzhiyun
2368*4882a593Smuzhiyun default:
2369*4882a593Smuzhiyun break;
2370*4882a593Smuzhiyun }
2371*4882a593Smuzhiyun
2372*4882a593Smuzhiyun pcurrent += (tlv_len + sizeof(ptlv_hdr->header));
2373*4882a593Smuzhiyun resp_len -= (tlv_len + sizeof(ptlv_hdr->header));
2374*4882a593Smuzhiyun }
2375*4882a593Smuzhiyun
2376*4882a593Smuzhiyun wlan_wmm_setup_queue_priorities(priv, pwmm_param_ie);
2377*4882a593Smuzhiyun wlan_wmm_setup_ac_downgrade(priv);
2378*4882a593Smuzhiyun
2379*4882a593Smuzhiyun if (send_wmm_event) {
2380*4882a593Smuzhiyun wlan_recv_event(priv, MLAN_EVENT_ID_FW_WMM_CONFIG_CHANGE,
2381*4882a593Smuzhiyun MNULL);
2382*4882a593Smuzhiyun }
2383*4882a593Smuzhiyun
2384*4882a593Smuzhiyun LEAVE();
2385*4882a593Smuzhiyun return MLAN_STATUS_SUCCESS;
2386*4882a593Smuzhiyun }
2387*4882a593Smuzhiyun
2388*4882a593Smuzhiyun /**
2389*4882a593Smuzhiyun * @brief Call back from the command module to allow insertion of a WMM TLV
2390*4882a593Smuzhiyun *
2391*4882a593Smuzhiyun * If the BSS we are associating to supports WMM, add the required WMM
2392*4882a593Smuzhiyun * Information IE to the association request command buffer in the form
2393*4882a593Smuzhiyun * of a NXP extended IEEE IE.
2394*4882a593Smuzhiyun *
2395*4882a593Smuzhiyun * @param priv Pointer to the mlan_private driver data struct
2396*4882a593Smuzhiyun * @param ppassoc_buf Output parameter: Pointer to the TLV output buffer,
2397*4882a593Smuzhiyun * modified on return to point after the appended WMM TLV
2398*4882a593Smuzhiyun * @param pwmm_ie Pointer to the WMM IE for the BSS we are joining
2399*4882a593Smuzhiyun *
2400*4882a593Smuzhiyun * @return Length of data appended to the association tlv buffer
2401*4882a593Smuzhiyun */
wlan_wmm_process_association_req(pmlan_private priv,t_u8 ** ppassoc_buf,IEEEtypes_WmmParameter_t * pwmm_ie)2402*4882a593Smuzhiyun t_u32 wlan_wmm_process_association_req(pmlan_private priv, t_u8 **ppassoc_buf,
2403*4882a593Smuzhiyun IEEEtypes_WmmParameter_t *pwmm_ie)
2404*4882a593Smuzhiyun {
2405*4882a593Smuzhiyun MrvlIEtypes_WmmParamSet_t *pwmm_tlv;
2406*4882a593Smuzhiyun t_u32 ret_len = 0;
2407*4882a593Smuzhiyun
2408*4882a593Smuzhiyun ENTER();
2409*4882a593Smuzhiyun
2410*4882a593Smuzhiyun /* Null checks */
2411*4882a593Smuzhiyun if (!ppassoc_buf) {
2412*4882a593Smuzhiyun LEAVE();
2413*4882a593Smuzhiyun return 0;
2414*4882a593Smuzhiyun }
2415*4882a593Smuzhiyun if (!(*ppassoc_buf)) {
2416*4882a593Smuzhiyun LEAVE();
2417*4882a593Smuzhiyun return 0;
2418*4882a593Smuzhiyun }
2419*4882a593Smuzhiyun
2420*4882a593Smuzhiyun if (!pwmm_ie) {
2421*4882a593Smuzhiyun LEAVE();
2422*4882a593Smuzhiyun return 0;
2423*4882a593Smuzhiyun }
2424*4882a593Smuzhiyun
2425*4882a593Smuzhiyun PRINTM(MINFO, "WMM: process assoc req: bss->wmmIe=0x%x\n",
2426*4882a593Smuzhiyun pwmm_ie->vend_hdr.element_id);
2427*4882a593Smuzhiyun
2428*4882a593Smuzhiyun if (priv->wmm_required && pwmm_ie->vend_hdr.element_id == WMM_IE) {
2429*4882a593Smuzhiyun pwmm_tlv = (MrvlIEtypes_WmmParamSet_t *)*ppassoc_buf;
2430*4882a593Smuzhiyun pwmm_tlv->header.type = (t_u16)wmm_info_ie[0];
2431*4882a593Smuzhiyun pwmm_tlv->header.type = wlan_cpu_to_le16(pwmm_tlv->header.type);
2432*4882a593Smuzhiyun pwmm_tlv->header.len = (t_u16)wmm_info_ie[1];
2433*4882a593Smuzhiyun memcpy_ext(priv->adapter, pwmm_tlv->wmm_ie, &wmm_info_ie[2],
2434*4882a593Smuzhiyun pwmm_tlv->header.len, pwmm_tlv->header.len);
2435*4882a593Smuzhiyun if (pwmm_ie->qos_info.qos_uapsd)
2436*4882a593Smuzhiyun memcpy_ext(priv->adapter,
2437*4882a593Smuzhiyun (t_u8 *)(pwmm_tlv->wmm_ie +
2438*4882a593Smuzhiyun pwmm_tlv->header.len -
2439*4882a593Smuzhiyun sizeof(priv->wmm_qosinfo)),
2440*4882a593Smuzhiyun &priv->wmm_qosinfo,
2441*4882a593Smuzhiyun sizeof(priv->wmm_qosinfo),
2442*4882a593Smuzhiyun sizeof(priv->wmm_qosinfo));
2443*4882a593Smuzhiyun
2444*4882a593Smuzhiyun ret_len = sizeof(pwmm_tlv->header) + pwmm_tlv->header.len;
2445*4882a593Smuzhiyun pwmm_tlv->header.len = wlan_cpu_to_le16(pwmm_tlv->header.len);
2446*4882a593Smuzhiyun
2447*4882a593Smuzhiyun HEXDUMP("ASSOC_CMD: WMM IE", (t_u8 *)pwmm_tlv, ret_len);
2448*4882a593Smuzhiyun *ppassoc_buf += ret_len;
2449*4882a593Smuzhiyun }
2450*4882a593Smuzhiyun
2451*4882a593Smuzhiyun LEAVE();
2452*4882a593Smuzhiyun return ret_len;
2453*4882a593Smuzhiyun }
2454*4882a593Smuzhiyun #endif /* STA_SUPPORT */
2455*4882a593Smuzhiyun
2456*4882a593Smuzhiyun /**
2457*4882a593Smuzhiyun * @brief Compute the time delay in the driver queues for a given packet.
2458*4882a593Smuzhiyun *
2459*4882a593Smuzhiyun * When the packet is received at the OS/Driver interface, the current
2460*4882a593Smuzhiyun * time is set in the packet structure. The difference between the present
2461*4882a593Smuzhiyun * time and that received time is computed in this function and limited
2462*4882a593Smuzhiyun * based on pre-compiled limits in the driver.
2463*4882a593Smuzhiyun *
2464*4882a593Smuzhiyun * @param priv Ptr to the mlan_private driver data struct
2465*4882a593Smuzhiyun * @param pmbuf Ptr to the mlan_buffer which has been previously timestamped
2466*4882a593Smuzhiyun *
2467*4882a593Smuzhiyun * @return Time delay of the packet in 2ms units after having limit applied
2468*4882a593Smuzhiyun */
wlan_wmm_compute_driver_packet_delay(pmlan_private priv,const pmlan_buffer pmbuf)2469*4882a593Smuzhiyun t_u8 wlan_wmm_compute_driver_packet_delay(pmlan_private priv,
2470*4882a593Smuzhiyun const pmlan_buffer pmbuf)
2471*4882a593Smuzhiyun {
2472*4882a593Smuzhiyun t_u8 ret_val = 0;
2473*4882a593Smuzhiyun t_u32 out_ts_sec, out_ts_usec;
2474*4882a593Smuzhiyun t_s32 queue_delay;
2475*4882a593Smuzhiyun
2476*4882a593Smuzhiyun ENTER();
2477*4882a593Smuzhiyun
2478*4882a593Smuzhiyun priv->adapter->callbacks.moal_get_system_time(
2479*4882a593Smuzhiyun priv->adapter->pmoal_handle, &out_ts_sec, &out_ts_usec);
2480*4882a593Smuzhiyun if (priv->adapter->tp_state_on) {
2481*4882a593Smuzhiyun pmbuf->out_ts_sec = out_ts_sec;
2482*4882a593Smuzhiyun pmbuf->out_ts_usec = out_ts_usec;
2483*4882a593Smuzhiyun if (pmbuf->in_ts_sec)
2484*4882a593Smuzhiyun priv->adapter->callbacks.moal_tp_accounting(
2485*4882a593Smuzhiyun priv->adapter->pmoal_handle, pmbuf, 11);
2486*4882a593Smuzhiyun }
2487*4882a593Smuzhiyun queue_delay = (t_s32)(out_ts_sec - pmbuf->in_ts_sec) * 1000;
2488*4882a593Smuzhiyun queue_delay += (t_s32)(out_ts_usec - pmbuf->in_ts_usec) / 1000;
2489*4882a593Smuzhiyun
2490*4882a593Smuzhiyun /*
2491*4882a593Smuzhiyun * Queue delay is passed as a uint8 in units of 2ms (ms shifted
2492*4882a593Smuzhiyun * by 1). Min value (other than 0) is therefore 2ms, max is 510ms.
2493*4882a593Smuzhiyun *
2494*4882a593Smuzhiyun * Pass max value if queue_delay is beyond the uint8 range
2495*4882a593Smuzhiyun */
2496*4882a593Smuzhiyun ret_val = (t_u8)(MIN(queue_delay, (t_s32)priv->wmm.drv_pkt_delay_max) >>
2497*4882a593Smuzhiyun 1);
2498*4882a593Smuzhiyun
2499*4882a593Smuzhiyun PRINTM(MINFO, "WMM: Pkt Delay: %d ms, %d ms sent to FW\n", queue_delay,
2500*4882a593Smuzhiyun ret_val);
2501*4882a593Smuzhiyun
2502*4882a593Smuzhiyun LEAVE();
2503*4882a593Smuzhiyun return ret_val;
2504*4882a593Smuzhiyun }
2505*4882a593Smuzhiyun
2506*4882a593Smuzhiyun /**
2507*4882a593Smuzhiyun * @brief Transmit the highest priority packet awaiting in the WMM Queues
2508*4882a593Smuzhiyun *
2509*4882a593Smuzhiyun * @param pmadapter Pointer to the mlan_adapter driver data struct
2510*4882a593Smuzhiyun *
2511*4882a593Smuzhiyun * @return N/A
2512*4882a593Smuzhiyun */
wlan_wmm_process_tx(pmlan_adapter pmadapter)2513*4882a593Smuzhiyun void wlan_wmm_process_tx(pmlan_adapter pmadapter)
2514*4882a593Smuzhiyun {
2515*4882a593Smuzhiyun ENTER();
2516*4882a593Smuzhiyun
2517*4882a593Smuzhiyun do {
2518*4882a593Smuzhiyun if (wlan_dequeue_tx_packet(pmadapter))
2519*4882a593Smuzhiyun break;
2520*4882a593Smuzhiyun #ifdef SDIO
2521*4882a593Smuzhiyun if (IS_SD(pmadapter->card_type) &&
2522*4882a593Smuzhiyun (pmadapter->ireg & UP_LD_CMD_PORT_HOST_INT_STATUS)) {
2523*4882a593Smuzhiyun wlan_send_mp_aggr_buf(pmadapter);
2524*4882a593Smuzhiyun break;
2525*4882a593Smuzhiyun }
2526*4882a593Smuzhiyun #endif
2527*4882a593Smuzhiyun
2528*4882a593Smuzhiyun #ifdef PCIE
2529*4882a593Smuzhiyun if (IS_PCIE(pmadapter->card_type) &&
2530*4882a593Smuzhiyun (pmadapter->ireg &
2531*4882a593Smuzhiyun pmadapter->pcard_pcie->reg->host_intr_event_rdy))
2532*4882a593Smuzhiyun break;
2533*4882a593Smuzhiyun #endif
2534*4882a593Smuzhiyun #ifdef USB
2535*4882a593Smuzhiyun if (IS_USB(pmadapter->card_type) && pmadapter->event_received)
2536*4882a593Smuzhiyun break;
2537*4882a593Smuzhiyun #endif
2538*4882a593Smuzhiyun /* Check if busy */
2539*4882a593Smuzhiyun } while (!pmadapter->data_sent && !pmadapter->tx_lock_flag &&
2540*4882a593Smuzhiyun !wlan_wmm_lists_empty(pmadapter));
2541*4882a593Smuzhiyun
2542*4882a593Smuzhiyun LEAVE();
2543*4882a593Smuzhiyun return;
2544*4882a593Smuzhiyun }
2545*4882a593Smuzhiyun
2546*4882a593Smuzhiyun /**
2547*4882a593Smuzhiyun * @brief select wmm queue
2548*4882a593Smuzhiyun *
2549*4882a593Smuzhiyun * @param pmpriv A pointer to mlan_private structure
2550*4882a593Smuzhiyun * @param tid TID 0-7
2551*4882a593Smuzhiyun *
2552*4882a593Smuzhiyun * @return wmm_queue priority (0-3)
2553*4882a593Smuzhiyun */
wlan_wmm_select_queue(mlan_private * pmpriv,t_u8 tid)2554*4882a593Smuzhiyun t_u8 wlan_wmm_select_queue(mlan_private *pmpriv, t_u8 tid)
2555*4882a593Smuzhiyun {
2556*4882a593Smuzhiyun pmlan_adapter pmadapter = pmpriv->adapter;
2557*4882a593Smuzhiyun t_u8 i;
2558*4882a593Smuzhiyun mlan_wmm_ac_e ac_down =
2559*4882a593Smuzhiyun pmpriv->wmm.ac_down_graded_vals[wlan_wmm_convert_tos_to_ac(
2560*4882a593Smuzhiyun pmadapter, tid)];
2561*4882a593Smuzhiyun
2562*4882a593Smuzhiyun ENTER();
2563*4882a593Smuzhiyun
2564*4882a593Smuzhiyun for (i = 0; i < 4; i++) {
2565*4882a593Smuzhiyun if (pmpriv->wmm.queue_priority[i] == ac_down) {
2566*4882a593Smuzhiyun LEAVE();
2567*4882a593Smuzhiyun return i;
2568*4882a593Smuzhiyun }
2569*4882a593Smuzhiyun }
2570*4882a593Smuzhiyun LEAVE();
2571*4882a593Smuzhiyun return 0;
2572*4882a593Smuzhiyun }
2573*4882a593Smuzhiyun
2574*4882a593Smuzhiyun /**
2575*4882a593Smuzhiyun * @brief Delete tx packets in RA list
2576*4882a593Smuzhiyun *
2577*4882a593Smuzhiyun * @param priv Pointer to the mlan_private driver data struct
2578*4882a593Smuzhiyun * @param ra_list_head ra list header
2579*4882a593Smuzhiyun * @param tid tid
2580*4882a593Smuzhiyun *
2581*4882a593Smuzhiyun * @return N/A
2582*4882a593Smuzhiyun */
wlan_del_tx_pkts_in_ralist(pmlan_private priv,mlan_list_head * ra_list_head,int tid)2583*4882a593Smuzhiyun static INLINE t_u8 wlan_del_tx_pkts_in_ralist(pmlan_private priv,
2584*4882a593Smuzhiyun mlan_list_head *ra_list_head,
2585*4882a593Smuzhiyun int tid)
2586*4882a593Smuzhiyun {
2587*4882a593Smuzhiyun raListTbl *ra_list = MNULL;
2588*4882a593Smuzhiyun pmlan_adapter pmadapter = priv->adapter;
2589*4882a593Smuzhiyun pmlan_buffer pmbuf = MNULL;
2590*4882a593Smuzhiyun t_u8 ret = MFALSE;
2591*4882a593Smuzhiyun ENTER();
2592*4882a593Smuzhiyun ra_list = (raListTbl *)util_peek_list(priv->adapter->pmoal_handle,
2593*4882a593Smuzhiyun ra_list_head, MNULL, MNULL);
2594*4882a593Smuzhiyun while (ra_list && ra_list != (raListTbl *)ra_list_head) {
2595*4882a593Smuzhiyun if (ra_list->total_pkts &&
2596*4882a593Smuzhiyun (ra_list->tx_pause ||
2597*4882a593Smuzhiyun (ra_list->total_pkts > RX_LOW_THRESHOLD))) {
2598*4882a593Smuzhiyun pmbuf = (pmlan_buffer)util_dequeue_list(
2599*4882a593Smuzhiyun pmadapter->pmoal_handle, &ra_list->buf_head,
2600*4882a593Smuzhiyun MNULL, MNULL);
2601*4882a593Smuzhiyun if (pmbuf) {
2602*4882a593Smuzhiyun PRINTM(MDATA,
2603*4882a593Smuzhiyun "Drop pkts: tid=%d tx_pause=%d pkts=%d " MACSTR
2604*4882a593Smuzhiyun "\n",
2605*4882a593Smuzhiyun tid, ra_list->tx_pause,
2606*4882a593Smuzhiyun ra_list->total_pkts,
2607*4882a593Smuzhiyun MAC2STR(ra_list->ra));
2608*4882a593Smuzhiyun wlan_write_data_complete(pmadapter, pmbuf,
2609*4882a593Smuzhiyun MLAN_STATUS_FAILURE);
2610*4882a593Smuzhiyun priv->wmm.pkts_queued[tid]--;
2611*4882a593Smuzhiyun priv->num_drop_pkts++;
2612*4882a593Smuzhiyun ra_list->total_pkts--;
2613*4882a593Smuzhiyun if (ra_list->tx_pause)
2614*4882a593Smuzhiyun priv->wmm.pkts_paused[tid]--;
2615*4882a593Smuzhiyun else
2616*4882a593Smuzhiyun util_scalar_decrement(
2617*4882a593Smuzhiyun pmadapter->pmoal_handle,
2618*4882a593Smuzhiyun &priv->wmm.tx_pkts_queued,
2619*4882a593Smuzhiyun MNULL, MNULL);
2620*4882a593Smuzhiyun ret = MTRUE;
2621*4882a593Smuzhiyun break;
2622*4882a593Smuzhiyun }
2623*4882a593Smuzhiyun }
2624*4882a593Smuzhiyun ra_list = ra_list->pnext;
2625*4882a593Smuzhiyun }
2626*4882a593Smuzhiyun
2627*4882a593Smuzhiyun LEAVE();
2628*4882a593Smuzhiyun return ret;
2629*4882a593Smuzhiyun }
2630*4882a593Smuzhiyun
2631*4882a593Smuzhiyun /**
2632*4882a593Smuzhiyun * @brief Drop tx pkts
2633*4882a593Smuzhiyun *
2634*4882a593Smuzhiyun * @param priv Pointer to the mlan_private driver data struct
2635*4882a593Smuzhiyun *
2636*4882a593Smuzhiyun * @return N/A
2637*4882a593Smuzhiyun */
wlan_drop_tx_pkts(pmlan_private priv)2638*4882a593Smuzhiyun t_void wlan_drop_tx_pkts(pmlan_private priv)
2639*4882a593Smuzhiyun {
2640*4882a593Smuzhiyun int j;
2641*4882a593Smuzhiyun static int i;
2642*4882a593Smuzhiyun pmlan_adapter pmadapter = priv->adapter;
2643*4882a593Smuzhiyun pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
2644*4882a593Smuzhiyun priv->wmm.ra_list_spinlock);
2645*4882a593Smuzhiyun for (j = 0; j < MAX_NUM_TID; j++, i++) {
2646*4882a593Smuzhiyun if (i == MAX_NUM_TID)
2647*4882a593Smuzhiyun i = 0;
2648*4882a593Smuzhiyun if (wlan_del_tx_pkts_in_ralist(
2649*4882a593Smuzhiyun priv, &priv->wmm.tid_tbl_ptr[i].ra_list, i)) {
2650*4882a593Smuzhiyun i++;
2651*4882a593Smuzhiyun break;
2652*4882a593Smuzhiyun }
2653*4882a593Smuzhiyun }
2654*4882a593Smuzhiyun pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
2655*4882a593Smuzhiyun priv->wmm.ra_list_spinlock);
2656*4882a593Smuzhiyun return;
2657*4882a593Smuzhiyun }
2658*4882a593Smuzhiyun
2659*4882a593Smuzhiyun /**
2660*4882a593Smuzhiyun * @brief Remove peer ralist
2661*4882a593Smuzhiyun *
2662*4882a593Smuzhiyun * @param priv A pointer to mlan_private
2663*4882a593Smuzhiyun * @param mac peer mac address
2664*4882a593Smuzhiyun *
2665*4882a593Smuzhiyun * @return N/A
2666*4882a593Smuzhiyun */
wlan_wmm_delete_peer_ralist(pmlan_private priv,t_u8 * mac)2667*4882a593Smuzhiyun t_void wlan_wmm_delete_peer_ralist(pmlan_private priv, t_u8 *mac)
2668*4882a593Smuzhiyun {
2669*4882a593Smuzhiyun raListTbl *ra_list;
2670*4882a593Smuzhiyun int i;
2671*4882a593Smuzhiyun pmlan_adapter pmadapter = priv->adapter;
2672*4882a593Smuzhiyun t_u32 pkt_cnt = 0;
2673*4882a593Smuzhiyun t_u32 tx_pkts_queued = 0;
2674*4882a593Smuzhiyun
2675*4882a593Smuzhiyun ENTER();
2676*4882a593Smuzhiyun pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
2677*4882a593Smuzhiyun priv->wmm.ra_list_spinlock);
2678*4882a593Smuzhiyun for (i = 0; i < MAX_NUM_TID; ++i) {
2679*4882a593Smuzhiyun ra_list = wlan_wmm_get_ralist_node(priv, i, mac);
2680*4882a593Smuzhiyun if (ra_list) {
2681*4882a593Smuzhiyun PRINTM(MINFO, "delete sta ralist %p\n", ra_list);
2682*4882a593Smuzhiyun priv->wmm.pkts_queued[i] -= ra_list->total_pkts;
2683*4882a593Smuzhiyun if (ra_list->tx_pause)
2684*4882a593Smuzhiyun priv->wmm.pkts_paused[i] -= ra_list->total_pkts;
2685*4882a593Smuzhiyun else
2686*4882a593Smuzhiyun pkt_cnt += ra_list->total_pkts;
2687*4882a593Smuzhiyun wlan_wmm_del_pkts_in_ralist_node(priv, ra_list);
2688*4882a593Smuzhiyun
2689*4882a593Smuzhiyun util_unlink_list(pmadapter->pmoal_handle,
2690*4882a593Smuzhiyun &priv->wmm.tid_tbl_ptr[i].ra_list,
2691*4882a593Smuzhiyun (pmlan_linked_list)ra_list, MNULL,
2692*4882a593Smuzhiyun MNULL);
2693*4882a593Smuzhiyun pmadapter->callbacks.moal_mfree(pmadapter->pmoal_handle,
2694*4882a593Smuzhiyun (t_u8 *)ra_list);
2695*4882a593Smuzhiyun if (priv->wmm.tid_tbl_ptr[i].ra_list_curr == ra_list)
2696*4882a593Smuzhiyun priv->wmm.tid_tbl_ptr[i].ra_list_curr =
2697*4882a593Smuzhiyun (raListTbl *)&priv->wmm.tid_tbl_ptr[i]
2698*4882a593Smuzhiyun .ra_list;
2699*4882a593Smuzhiyun }
2700*4882a593Smuzhiyun }
2701*4882a593Smuzhiyun if (pkt_cnt) {
2702*4882a593Smuzhiyun tx_pkts_queued = util_scalar_read(pmadapter->pmoal_handle,
2703*4882a593Smuzhiyun &priv->wmm.tx_pkts_queued,
2704*4882a593Smuzhiyun MNULL, MNULL);
2705*4882a593Smuzhiyun tx_pkts_queued -= pkt_cnt;
2706*4882a593Smuzhiyun util_scalar_write(priv->adapter->pmoal_handle,
2707*4882a593Smuzhiyun &priv->wmm.tx_pkts_queued, tx_pkts_queued,
2708*4882a593Smuzhiyun MNULL, MNULL);
2709*4882a593Smuzhiyun util_scalar_write(priv->adapter->pmoal_handle,
2710*4882a593Smuzhiyun &priv->wmm.highest_queued_prio, HIGH_PRIO_TID,
2711*4882a593Smuzhiyun MNULL, MNULL);
2712*4882a593Smuzhiyun }
2713*4882a593Smuzhiyun pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
2714*4882a593Smuzhiyun priv->wmm.ra_list_spinlock);
2715*4882a593Smuzhiyun LEAVE();
2716*4882a593Smuzhiyun }
2717*4882a593Smuzhiyun
2718*4882a593Smuzhiyun #ifdef STA_SUPPORT
2719*4882a593Smuzhiyun /**
2720*4882a593Smuzhiyun * @brief Hold TDLS packets to tdls pending queue
2721*4882a593Smuzhiyun *
2722*4882a593Smuzhiyun * @param priv A pointer to mlan_private
2723*4882a593Smuzhiyun * @param mac station mac address
2724*4882a593Smuzhiyun *
2725*4882a593Smuzhiyun * @return N/A
2726*4882a593Smuzhiyun */
wlan_hold_tdls_packets(pmlan_private priv,t_u8 * mac)2727*4882a593Smuzhiyun t_void wlan_hold_tdls_packets(pmlan_private priv, t_u8 *mac)
2728*4882a593Smuzhiyun {
2729*4882a593Smuzhiyun pmlan_buffer pmbuf;
2730*4882a593Smuzhiyun mlan_adapter *pmadapter = priv->adapter;
2731*4882a593Smuzhiyun raListTbl *ra_list = MNULL;
2732*4882a593Smuzhiyun t_u8 i;
2733*4882a593Smuzhiyun
2734*4882a593Smuzhiyun ENTER();
2735*4882a593Smuzhiyun pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
2736*4882a593Smuzhiyun priv->wmm.ra_list_spinlock);
2737*4882a593Smuzhiyun PRINTM(MDATA, "wlan_hold_tdls_packets: " MACSTR "\n", MAC2STR(mac));
2738*4882a593Smuzhiyun for (i = 0; i < MAX_NUM_TID; ++i) {
2739*4882a593Smuzhiyun ra_list = (raListTbl *)util_peek_list(
2740*4882a593Smuzhiyun pmadapter->pmoal_handle,
2741*4882a593Smuzhiyun &priv->wmm.tid_tbl_ptr[i].ra_list, MNULL, MNULL);
2742*4882a593Smuzhiyun if (ra_list) {
2743*4882a593Smuzhiyun while ((pmbuf = wlan_find_tdls_packets(priv, ra_list,
2744*4882a593Smuzhiyun mac))) {
2745*4882a593Smuzhiyun util_unlink_list(pmadapter->pmoal_handle,
2746*4882a593Smuzhiyun &ra_list->buf_head,
2747*4882a593Smuzhiyun (pmlan_linked_list)pmbuf,
2748*4882a593Smuzhiyun MNULL, MNULL);
2749*4882a593Smuzhiyun ra_list->total_pkts--;
2750*4882a593Smuzhiyun priv->wmm.pkts_queued[i]--;
2751*4882a593Smuzhiyun util_scalar_decrement(pmadapter->pmoal_handle,
2752*4882a593Smuzhiyun &priv->wmm.tx_pkts_queued,
2753*4882a593Smuzhiyun MNULL, MNULL);
2754*4882a593Smuzhiyun ra_list->packet_count--;
2755*4882a593Smuzhiyun wlan_add_buf_tdls_txqueue(priv, pmbuf);
2756*4882a593Smuzhiyun PRINTM(MDATA, "hold tdls packet=%p\n", pmbuf);
2757*4882a593Smuzhiyun }
2758*4882a593Smuzhiyun }
2759*4882a593Smuzhiyun }
2760*4882a593Smuzhiyun pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
2761*4882a593Smuzhiyun priv->wmm.ra_list_spinlock);
2762*4882a593Smuzhiyun LEAVE();
2763*4882a593Smuzhiyun }
2764*4882a593Smuzhiyun
2765*4882a593Smuzhiyun /**
2766*4882a593Smuzhiyun * @brief move TDLS packets back to ralist
2767*4882a593Smuzhiyun *
2768*4882a593Smuzhiyun * @param priv A pointer to mlan_private
2769*4882a593Smuzhiyun * @param mac TDLS peer mac address
2770*4882a593Smuzhiyun * @param status tdlsStatus
2771*4882a593Smuzhiyun *
2772*4882a593Smuzhiyun * @return pmlan_buffer or MNULL
2773*4882a593Smuzhiyun */
wlan_restore_tdls_packets(pmlan_private priv,t_u8 * mac,tdlsStatus_e status)2774*4882a593Smuzhiyun t_void wlan_restore_tdls_packets(pmlan_private priv, t_u8 *mac,
2775*4882a593Smuzhiyun tdlsStatus_e status)
2776*4882a593Smuzhiyun {
2777*4882a593Smuzhiyun pmlan_buffer pmbuf;
2778*4882a593Smuzhiyun mlan_adapter *pmadapter = priv->adapter;
2779*4882a593Smuzhiyun raListTbl *ra_list = MNULL;
2780*4882a593Smuzhiyun t_u32 tid;
2781*4882a593Smuzhiyun t_u32 tid_down;
2782*4882a593Smuzhiyun
2783*4882a593Smuzhiyun ENTER();
2784*4882a593Smuzhiyun PRINTM(MDATA, "wlan_restore_tdls_packets: " MACSTR " status=%d\n",
2785*4882a593Smuzhiyun MAC2STR(mac), status);
2786*4882a593Smuzhiyun
2787*4882a593Smuzhiyun pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
2788*4882a593Smuzhiyun priv->wmm.ra_list_spinlock);
2789*4882a593Smuzhiyun
2790*4882a593Smuzhiyun while ((pmbuf = wlan_find_packets_tdls_txq(priv, mac))) {
2791*4882a593Smuzhiyun util_unlink_list(pmadapter->pmoal_handle,
2792*4882a593Smuzhiyun &priv->tdls_pending_txq,
2793*4882a593Smuzhiyun (pmlan_linked_list)pmbuf, MNULL, MNULL);
2794*4882a593Smuzhiyun tid = pmbuf->priority;
2795*4882a593Smuzhiyun tid_down = wlan_wmm_downgrade_tid(priv, tid);
2796*4882a593Smuzhiyun if (status == TDLS_SETUP_COMPLETE) {
2797*4882a593Smuzhiyun ra_list = wlan_wmm_get_queue_raptr(priv, tid_down, mac);
2798*4882a593Smuzhiyun pmbuf->flags |= MLAN_BUF_FLAG_TDLS;
2799*4882a593Smuzhiyun } else {
2800*4882a593Smuzhiyun ra_list = (raListTbl *)util_peek_list(
2801*4882a593Smuzhiyun pmadapter->pmoal_handle,
2802*4882a593Smuzhiyun &priv->wmm.tid_tbl_ptr[tid_down].ra_list, MNULL,
2803*4882a593Smuzhiyun MNULL);
2804*4882a593Smuzhiyun pmbuf->flags &= ~MLAN_BUF_FLAG_TDLS;
2805*4882a593Smuzhiyun }
2806*4882a593Smuzhiyun if (!ra_list) {
2807*4882a593Smuzhiyun PRINTM_NETINTF(MWARN, priv);
2808*4882a593Smuzhiyun PRINTM(MWARN,
2809*4882a593Smuzhiyun "Drop packet %p, ra_list=%p media_connected=%d\n",
2810*4882a593Smuzhiyun pmbuf, ra_list, priv->media_connected);
2811*4882a593Smuzhiyun wlan_write_data_complete(pmadapter, pmbuf,
2812*4882a593Smuzhiyun MLAN_STATUS_FAILURE);
2813*4882a593Smuzhiyun continue;
2814*4882a593Smuzhiyun }
2815*4882a593Smuzhiyun PRINTM_NETINTF(MDATA, priv);
2816*4882a593Smuzhiyun PRINTM(MDATA,
2817*4882a593Smuzhiyun "ADD TDLS pkt %p (priority=%d) back to ra_list %p\n",
2818*4882a593Smuzhiyun pmbuf, pmbuf->priority, ra_list);
2819*4882a593Smuzhiyun util_enqueue_list_tail(pmadapter->pmoal_handle,
2820*4882a593Smuzhiyun &ra_list->buf_head,
2821*4882a593Smuzhiyun (pmlan_linked_list)pmbuf, MNULL, MNULL);
2822*4882a593Smuzhiyun ra_list->total_pkts++;
2823*4882a593Smuzhiyun ra_list->packet_count++;
2824*4882a593Smuzhiyun priv->wmm.pkts_queued[tid_down]++;
2825*4882a593Smuzhiyun util_scalar_increment(pmadapter->pmoal_handle,
2826*4882a593Smuzhiyun &priv->wmm.tx_pkts_queued, MNULL, MNULL);
2827*4882a593Smuzhiyun util_scalar_conditional_write(
2828*4882a593Smuzhiyun pmadapter->pmoal_handle, &priv->wmm.highest_queued_prio,
2829*4882a593Smuzhiyun MLAN_SCALAR_COND_LESS_THAN, tos_to_tid_inv[tid_down],
2830*4882a593Smuzhiyun tos_to_tid_inv[tid_down], MNULL, MNULL);
2831*4882a593Smuzhiyun }
2832*4882a593Smuzhiyun if (status != TDLS_SETUP_COMPLETE)
2833*4882a593Smuzhiyun wlan_wmm_delete_tdls_ralist(priv, mac);
2834*4882a593Smuzhiyun pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
2835*4882a593Smuzhiyun priv->wmm.ra_list_spinlock);
2836*4882a593Smuzhiyun LEAVE();
2837*4882a593Smuzhiyun }
2838*4882a593Smuzhiyun
2839*4882a593Smuzhiyun /**
2840*4882a593Smuzhiyun * @brief This function prepares the command of ADDTS
2841*4882a593Smuzhiyun *
2842*4882a593Smuzhiyun * @param pmpriv A pointer to mlan_private structure
2843*4882a593Smuzhiyun * @param cmd A pointer to HostCmd_DS_COMMAND structure
2844*4882a593Smuzhiyun * @param pdata_buf A pointer to data buffer
2845*4882a593Smuzhiyun * @return MLAN_STATUS_SUCCESS
2846*4882a593Smuzhiyun */
wlan_cmd_wmm_addts_req(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_void * pdata_buf)2847*4882a593Smuzhiyun mlan_status wlan_cmd_wmm_addts_req(pmlan_private pmpriv,
2848*4882a593Smuzhiyun HostCmd_DS_COMMAND *cmd, t_void *pdata_buf)
2849*4882a593Smuzhiyun {
2850*4882a593Smuzhiyun mlan_ds_wmm_addts *paddts = (mlan_ds_wmm_addts *)pdata_buf;
2851*4882a593Smuzhiyun HostCmd_DS_WMM_ADDTS_REQ *pcmd_addts = &cmd->params.add_ts;
2852*4882a593Smuzhiyun
2853*4882a593Smuzhiyun ENTER();
2854*4882a593Smuzhiyun
2855*4882a593Smuzhiyun cmd->command = wlan_cpu_to_le16(HostCmd_CMD_WMM_ADDTS_REQ);
2856*4882a593Smuzhiyun cmd->size = wlan_cpu_to_le16(sizeof(pcmd_addts->dialog_token) +
2857*4882a593Smuzhiyun sizeof(pcmd_addts->timeout_ms) +
2858*4882a593Smuzhiyun sizeof(pcmd_addts->command_result) +
2859*4882a593Smuzhiyun sizeof(pcmd_addts->ieee_status_code) +
2860*4882a593Smuzhiyun paddts->ie_data_len + S_DS_GEN);
2861*4882a593Smuzhiyun cmd->result = 0;
2862*4882a593Smuzhiyun
2863*4882a593Smuzhiyun pcmd_addts->timeout_ms = wlan_cpu_to_le32(paddts->timeout);
2864*4882a593Smuzhiyun pcmd_addts->dialog_token = paddts->dialog_tok;
2865*4882a593Smuzhiyun memcpy_ext(pmpriv->adapter, pcmd_addts->tspec_data, paddts->ie_data,
2866*4882a593Smuzhiyun paddts->ie_data_len, WMM_TSPEC_SIZE);
2867*4882a593Smuzhiyun
2868*4882a593Smuzhiyun LEAVE();
2869*4882a593Smuzhiyun
2870*4882a593Smuzhiyun return MLAN_STATUS_SUCCESS;
2871*4882a593Smuzhiyun }
2872*4882a593Smuzhiyun
2873*4882a593Smuzhiyun /**
2874*4882a593Smuzhiyun * @brief This function handles the command response of ADDTS
2875*4882a593Smuzhiyun *
2876*4882a593Smuzhiyun * @param pmpriv A pointer to mlan_private structure
2877*4882a593Smuzhiyun * @param resp A pointer to HostCmd_DS_COMMAND
2878*4882a593Smuzhiyun * @param pioctl_buf A pointer to mlan_ioctl_req structure
2879*4882a593Smuzhiyun *
2880*4882a593Smuzhiyun * @return MLAN_STATUS_SUCCESS
2881*4882a593Smuzhiyun */
wlan_ret_wmm_addts_req(pmlan_private pmpriv,const HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)2882*4882a593Smuzhiyun mlan_status wlan_ret_wmm_addts_req(pmlan_private pmpriv,
2883*4882a593Smuzhiyun const HostCmd_DS_COMMAND *resp,
2884*4882a593Smuzhiyun mlan_ioctl_req *pioctl_buf)
2885*4882a593Smuzhiyun {
2886*4882a593Smuzhiyun mlan_ds_wmm_cfg *pwmm = MNULL;
2887*4882a593Smuzhiyun mlan_ds_wmm_addts *paddts = MNULL;
2888*4882a593Smuzhiyun const HostCmd_DS_WMM_ADDTS_REQ *presp_addts = &resp->params.add_ts;
2889*4882a593Smuzhiyun
2890*4882a593Smuzhiyun ENTER();
2891*4882a593Smuzhiyun
2892*4882a593Smuzhiyun if (pioctl_buf) {
2893*4882a593Smuzhiyun pwmm = (mlan_ds_wmm_cfg *)pioctl_buf->pbuf;
2894*4882a593Smuzhiyun paddts = (mlan_ds_wmm_addts *)&pwmm->param.addts;
2895*4882a593Smuzhiyun paddts->result = wlan_le32_to_cpu(presp_addts->command_result);
2896*4882a593Smuzhiyun paddts->dialog_tok = presp_addts->dialog_token;
2897*4882a593Smuzhiyun paddts->status_code = (t_u32)presp_addts->ieee_status_code;
2898*4882a593Smuzhiyun
2899*4882a593Smuzhiyun if (paddts->result == MLAN_CMD_RESULT_SUCCESS) {
2900*4882a593Smuzhiyun /* The tspecData field is potentially variable in size
2901*4882a593Smuzhiyun * due to extra IEs that may have been in the ADDTS
2902*4882a593Smuzhiyun * response action frame. Calculate the data length from
2903*4882a593Smuzhiyun * the firmware command response.
2904*4882a593Smuzhiyun */
2905*4882a593Smuzhiyun paddts->ie_data_len =
2906*4882a593Smuzhiyun (t_u8)(resp->size -
2907*4882a593Smuzhiyun sizeof(presp_addts->command_result) -
2908*4882a593Smuzhiyun sizeof(presp_addts->timeout_ms) -
2909*4882a593Smuzhiyun sizeof(presp_addts->dialog_token) -
2910*4882a593Smuzhiyun sizeof(presp_addts->ieee_status_code) -
2911*4882a593Smuzhiyun S_DS_GEN);
2912*4882a593Smuzhiyun
2913*4882a593Smuzhiyun /* Copy the TSPEC data include any extra IEs after the
2914*4882a593Smuzhiyun * TSPEC */
2915*4882a593Smuzhiyun memcpy_ext(pmpriv->adapter, paddts->ie_data,
2916*4882a593Smuzhiyun presp_addts->tspec_data, paddts->ie_data_len,
2917*4882a593Smuzhiyun sizeof(paddts->ie_data));
2918*4882a593Smuzhiyun } else {
2919*4882a593Smuzhiyun paddts->ie_data_len = 0;
2920*4882a593Smuzhiyun }
2921*4882a593Smuzhiyun PRINTM(MINFO, "TSPEC: ADDTS ret = %d,%d sz=%d\n",
2922*4882a593Smuzhiyun paddts->result, paddts->status_code,
2923*4882a593Smuzhiyun paddts->ie_data_len);
2924*4882a593Smuzhiyun
2925*4882a593Smuzhiyun HEXDUMP("TSPEC: ADDTS data", paddts->ie_data,
2926*4882a593Smuzhiyun paddts->ie_data_len);
2927*4882a593Smuzhiyun }
2928*4882a593Smuzhiyun
2929*4882a593Smuzhiyun LEAVE();
2930*4882a593Smuzhiyun return MLAN_STATUS_SUCCESS;
2931*4882a593Smuzhiyun }
2932*4882a593Smuzhiyun
2933*4882a593Smuzhiyun /**
2934*4882a593Smuzhiyun * @brief This function prepares the command of DELTS
2935*4882a593Smuzhiyun *
2936*4882a593Smuzhiyun * @param pmpriv A pointer to mlan_private structure
2937*4882a593Smuzhiyun * @param cmd A pointer to HostCmd_DS_COMMAND structure
2938*4882a593Smuzhiyun * @param pdata_buf A pointer to data buffer
2939*4882a593Smuzhiyun * @return MLAN_STATUS_SUCCESS
2940*4882a593Smuzhiyun */
wlan_cmd_wmm_delts_req(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_void * pdata_buf)2941*4882a593Smuzhiyun mlan_status wlan_cmd_wmm_delts_req(pmlan_private pmpriv,
2942*4882a593Smuzhiyun HostCmd_DS_COMMAND *cmd, t_void *pdata_buf)
2943*4882a593Smuzhiyun {
2944*4882a593Smuzhiyun mlan_ds_wmm_delts *pdelts = (mlan_ds_wmm_delts *)pdata_buf;
2945*4882a593Smuzhiyun HostCmd_DS_WMM_DELTS_REQ *pcmd_delts = &cmd->params.del_ts;
2946*4882a593Smuzhiyun
2947*4882a593Smuzhiyun ENTER();
2948*4882a593Smuzhiyun
2949*4882a593Smuzhiyun cmd->command = wlan_cpu_to_le16(HostCmd_CMD_WMM_DELTS_REQ);
2950*4882a593Smuzhiyun cmd->size = wlan_cpu_to_le16(sizeof(pcmd_delts->dialog_token) +
2951*4882a593Smuzhiyun sizeof(pcmd_delts->command_result) +
2952*4882a593Smuzhiyun sizeof(pcmd_delts->ieee_reason_code) +
2953*4882a593Smuzhiyun pdelts->ie_data_len + S_DS_GEN);
2954*4882a593Smuzhiyun cmd->result = 0;
2955*4882a593Smuzhiyun pcmd_delts->ieee_reason_code = (t_u8)pdelts->status_code;
2956*4882a593Smuzhiyun memcpy_ext(pmpriv->adapter, pcmd_delts->tspec_data, pdelts->ie_data,
2957*4882a593Smuzhiyun pdelts->ie_data_len, WMM_TSPEC_SIZE);
2958*4882a593Smuzhiyun
2959*4882a593Smuzhiyun LEAVE();
2960*4882a593Smuzhiyun
2961*4882a593Smuzhiyun return MLAN_STATUS_SUCCESS;
2962*4882a593Smuzhiyun }
2963*4882a593Smuzhiyun
2964*4882a593Smuzhiyun /**
2965*4882a593Smuzhiyun * @brief This function handles the command response of DELTS
2966*4882a593Smuzhiyun *
2967*4882a593Smuzhiyun * @param pmpriv A pointer to mlan_private structure
2968*4882a593Smuzhiyun * @param resp A pointer to HostCmd_DS_COMMAND
2969*4882a593Smuzhiyun * @param pioctl_buf A pointer to mlan_ioctl_req structure
2970*4882a593Smuzhiyun *
2971*4882a593Smuzhiyun * @return MLAN_STATUS_SUCCESS
2972*4882a593Smuzhiyun */
wlan_ret_wmm_delts_req(pmlan_private pmpriv,const HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)2973*4882a593Smuzhiyun mlan_status wlan_ret_wmm_delts_req(pmlan_private pmpriv,
2974*4882a593Smuzhiyun const HostCmd_DS_COMMAND *resp,
2975*4882a593Smuzhiyun mlan_ioctl_req *pioctl_buf)
2976*4882a593Smuzhiyun {
2977*4882a593Smuzhiyun mlan_ds_wmm_cfg *pwmm;
2978*4882a593Smuzhiyun IEEEtypes_WMM_TSPEC_t *ptspec_ie;
2979*4882a593Smuzhiyun const HostCmd_DS_WMM_DELTS_REQ *presp_delts = &resp->params.del_ts;
2980*4882a593Smuzhiyun
2981*4882a593Smuzhiyun ENTER();
2982*4882a593Smuzhiyun
2983*4882a593Smuzhiyun if (pioctl_buf) {
2984*4882a593Smuzhiyun pwmm = (mlan_ds_wmm_cfg *)pioctl_buf->pbuf;
2985*4882a593Smuzhiyun pwmm->param.delts.result =
2986*4882a593Smuzhiyun wlan_le32_to_cpu(presp_delts->command_result);
2987*4882a593Smuzhiyun
2988*4882a593Smuzhiyun PRINTM(MINFO, "TSPEC: DELTS result = %d\n",
2989*4882a593Smuzhiyun presp_delts->command_result);
2990*4882a593Smuzhiyun
2991*4882a593Smuzhiyun if (pwmm->param.delts.result == 0) {
2992*4882a593Smuzhiyun ptspec_ie = (IEEEtypes_WMM_TSPEC_t *)
2993*4882a593Smuzhiyun presp_delts->tspec_data;
2994*4882a593Smuzhiyun wlan_send_wmmac_host_event(
2995*4882a593Smuzhiyun pmpriv, "DELTS_TX", MNULL,
2996*4882a593Smuzhiyun ptspec_ie->TspecBody.TSInfo.TID,
2997*4882a593Smuzhiyun ptspec_ie->TspecBody.TSInfo.UserPri,
2998*4882a593Smuzhiyun presp_delts->ieee_reason_code);
2999*4882a593Smuzhiyun }
3000*4882a593Smuzhiyun }
3001*4882a593Smuzhiyun
3002*4882a593Smuzhiyun LEAVE();
3003*4882a593Smuzhiyun return MLAN_STATUS_SUCCESS;
3004*4882a593Smuzhiyun }
3005*4882a593Smuzhiyun
3006*4882a593Smuzhiyun /**
3007*4882a593Smuzhiyun * @brief This function prepares the command of WMM_QUEUE_STATS
3008*4882a593Smuzhiyun *
3009*4882a593Smuzhiyun * @param pmpriv A pointer to mlan_private structure
3010*4882a593Smuzhiyun * @param cmd A pointer to HostCmd_DS_COMMAND structure
3011*4882a593Smuzhiyun * @param pdata_buf A pointer to data buffer
3012*4882a593Smuzhiyun * @return MLAN_STATUS_SUCCESS
3013*4882a593Smuzhiyun */
wlan_cmd_wmm_queue_stats(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_void * pdata_buf)3014*4882a593Smuzhiyun mlan_status wlan_cmd_wmm_queue_stats(pmlan_private pmpriv,
3015*4882a593Smuzhiyun HostCmd_DS_COMMAND *cmd, t_void *pdata_buf)
3016*4882a593Smuzhiyun {
3017*4882a593Smuzhiyun mlan_ds_wmm_queue_stats *pqstats = (mlan_ds_wmm_queue_stats *)pdata_buf;
3018*4882a593Smuzhiyun HostCmd_DS_WMM_QUEUE_STATS *pcmd_qstats = &cmd->params.queue_stats;
3019*4882a593Smuzhiyun t_u8 id;
3020*4882a593Smuzhiyun
3021*4882a593Smuzhiyun ENTER();
3022*4882a593Smuzhiyun
3023*4882a593Smuzhiyun cmd->command = wlan_cpu_to_le16(HostCmd_CMD_WMM_QUEUE_STATS);
3024*4882a593Smuzhiyun cmd->size =
3025*4882a593Smuzhiyun wlan_cpu_to_le16(sizeof(HostCmd_DS_WMM_QUEUE_STATS) + S_DS_GEN);
3026*4882a593Smuzhiyun cmd->result = 0;
3027*4882a593Smuzhiyun
3028*4882a593Smuzhiyun pcmd_qstats->action = pqstats->action;
3029*4882a593Smuzhiyun pcmd_qstats->select_is_userpri = 1;
3030*4882a593Smuzhiyun pcmd_qstats->select_bin = pqstats->user_priority;
3031*4882a593Smuzhiyun pcmd_qstats->pkt_count = wlan_cpu_to_le16(pqstats->pkt_count);
3032*4882a593Smuzhiyun pcmd_qstats->pkt_loss = wlan_cpu_to_le16(pqstats->pkt_loss);
3033*4882a593Smuzhiyun pcmd_qstats->avg_queue_delay =
3034*4882a593Smuzhiyun wlan_cpu_to_le32(pqstats->avg_queue_delay);
3035*4882a593Smuzhiyun pcmd_qstats->avg_tx_delay = wlan_cpu_to_le32(pqstats->avg_tx_delay);
3036*4882a593Smuzhiyun pcmd_qstats->used_time = wlan_cpu_to_le16(pqstats->used_time);
3037*4882a593Smuzhiyun pcmd_qstats->policed_time = wlan_cpu_to_le16(pqstats->policed_time);
3038*4882a593Smuzhiyun for (id = 0; id < MLAN_WMM_STATS_PKTS_HIST_BINS; id++) {
3039*4882a593Smuzhiyun pcmd_qstats->delay_histogram[id] =
3040*4882a593Smuzhiyun wlan_cpu_to_le16(pqstats->delay_histogram[id]);
3041*4882a593Smuzhiyun }
3042*4882a593Smuzhiyun
3043*4882a593Smuzhiyun LEAVE();
3044*4882a593Smuzhiyun return MLAN_STATUS_SUCCESS;
3045*4882a593Smuzhiyun }
3046*4882a593Smuzhiyun
3047*4882a593Smuzhiyun /**
3048*4882a593Smuzhiyun * @brief This function handles the command response of WMM_QUEUE_STATS
3049*4882a593Smuzhiyun *
3050*4882a593Smuzhiyun * @param pmpriv A pointer to mlan_private structure
3051*4882a593Smuzhiyun * @param resp A pointer to HostCmd_DS_COMMAND
3052*4882a593Smuzhiyun * @param pioctl_buf A pointer to mlan_ioctl_req structure
3053*4882a593Smuzhiyun *
3054*4882a593Smuzhiyun * @return MLAN_STATUS_SUCCESS
3055*4882a593Smuzhiyun */
wlan_ret_wmm_queue_stats(pmlan_private pmpriv,const HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)3056*4882a593Smuzhiyun mlan_status wlan_ret_wmm_queue_stats(pmlan_private pmpriv,
3057*4882a593Smuzhiyun const HostCmd_DS_COMMAND *resp,
3058*4882a593Smuzhiyun mlan_ioctl_req *pioctl_buf)
3059*4882a593Smuzhiyun {
3060*4882a593Smuzhiyun mlan_ds_wmm_cfg *pwmm = MNULL;
3061*4882a593Smuzhiyun mlan_ds_wmm_queue_stats *pqstats = MNULL;
3062*4882a593Smuzhiyun const HostCmd_DS_WMM_QUEUE_STATS *presp_qstats =
3063*4882a593Smuzhiyun &resp->params.queue_stats;
3064*4882a593Smuzhiyun t_u8 id;
3065*4882a593Smuzhiyun
3066*4882a593Smuzhiyun ENTER();
3067*4882a593Smuzhiyun
3068*4882a593Smuzhiyun if (pioctl_buf) {
3069*4882a593Smuzhiyun pwmm = (mlan_ds_wmm_cfg *)pioctl_buf->pbuf;
3070*4882a593Smuzhiyun pqstats = (mlan_ds_wmm_queue_stats *)&pwmm->param.q_stats;
3071*4882a593Smuzhiyun
3072*4882a593Smuzhiyun pqstats->action = presp_qstats->action;
3073*4882a593Smuzhiyun pqstats->user_priority = presp_qstats->select_bin;
3074*4882a593Smuzhiyun pqstats->pkt_count = wlan_le16_to_cpu(presp_qstats->pkt_count);
3075*4882a593Smuzhiyun pqstats->pkt_loss = wlan_le16_to_cpu(presp_qstats->pkt_loss);
3076*4882a593Smuzhiyun pqstats->avg_queue_delay =
3077*4882a593Smuzhiyun wlan_le32_to_cpu(presp_qstats->avg_queue_delay);
3078*4882a593Smuzhiyun pqstats->avg_tx_delay =
3079*4882a593Smuzhiyun wlan_le32_to_cpu(presp_qstats->avg_tx_delay);
3080*4882a593Smuzhiyun pqstats->used_time = wlan_le16_to_cpu(presp_qstats->used_time);
3081*4882a593Smuzhiyun pqstats->policed_time =
3082*4882a593Smuzhiyun wlan_le16_to_cpu(presp_qstats->policed_time);
3083*4882a593Smuzhiyun for (id = 0; id < MLAN_WMM_STATS_PKTS_HIST_BINS; id++) {
3084*4882a593Smuzhiyun pqstats->delay_histogram[id] = wlan_le16_to_cpu(
3085*4882a593Smuzhiyun presp_qstats->delay_histogram[id]);
3086*4882a593Smuzhiyun }
3087*4882a593Smuzhiyun }
3088*4882a593Smuzhiyun
3089*4882a593Smuzhiyun LEAVE();
3090*4882a593Smuzhiyun return MLAN_STATUS_SUCCESS;
3091*4882a593Smuzhiyun }
3092*4882a593Smuzhiyun
3093*4882a593Smuzhiyun /**
3094*4882a593Smuzhiyun * @brief This function prepares the command of WMM_TS_STATUS
3095*4882a593Smuzhiyun *
3096*4882a593Smuzhiyun * @param pmpriv A pointer to mlan_private structure
3097*4882a593Smuzhiyun * @param cmd A pointer to HostCmd_DS_COMMAND structure
3098*4882a593Smuzhiyun * @param pdata_buf A pointer to data buffer
3099*4882a593Smuzhiyun * @return MLAN_STATUS_SUCCESS
3100*4882a593Smuzhiyun */
wlan_cmd_wmm_ts_status(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_void * pdata_buf)3101*4882a593Smuzhiyun mlan_status wlan_cmd_wmm_ts_status(pmlan_private pmpriv,
3102*4882a593Smuzhiyun HostCmd_DS_COMMAND *cmd, t_void *pdata_buf)
3103*4882a593Smuzhiyun {
3104*4882a593Smuzhiyun mlan_ds_wmm_ts_status *pts_status = (mlan_ds_wmm_ts_status *)pdata_buf;
3105*4882a593Smuzhiyun HostCmd_DS_WMM_TS_STATUS *pcmd_ts_status = &cmd->params.ts_status;
3106*4882a593Smuzhiyun
3107*4882a593Smuzhiyun ENTER();
3108*4882a593Smuzhiyun
3109*4882a593Smuzhiyun cmd->command = wlan_cpu_to_le16(HostCmd_CMD_WMM_TS_STATUS);
3110*4882a593Smuzhiyun cmd->size =
3111*4882a593Smuzhiyun wlan_cpu_to_le16(sizeof(HostCmd_DS_WMM_TS_STATUS) + S_DS_GEN);
3112*4882a593Smuzhiyun cmd->result = 0;
3113*4882a593Smuzhiyun
3114*4882a593Smuzhiyun memcpy_ext(pmpriv->adapter, (t_void *)pcmd_ts_status,
3115*4882a593Smuzhiyun (t_void *)pts_status, sizeof(HostCmd_DS_WMM_TS_STATUS),
3116*4882a593Smuzhiyun sizeof(HostCmd_DS_WMM_TS_STATUS));
3117*4882a593Smuzhiyun
3118*4882a593Smuzhiyun LEAVE();
3119*4882a593Smuzhiyun return MLAN_STATUS_SUCCESS;
3120*4882a593Smuzhiyun }
3121*4882a593Smuzhiyun
3122*4882a593Smuzhiyun /**
3123*4882a593Smuzhiyun * @brief This function handles the command response of WMM_TS_STATUS
3124*4882a593Smuzhiyun *
3125*4882a593Smuzhiyun * @param pmpriv A pointer to mlan_private structure
3126*4882a593Smuzhiyun * @param resp A pointer to HostCmd_DS_COMMAND
3127*4882a593Smuzhiyun * @param pioctl_buf A pointer to mlan_ioctl_req structure
3128*4882a593Smuzhiyun *
3129*4882a593Smuzhiyun * @return MLAN_STATUS_SUCCESS
3130*4882a593Smuzhiyun */
wlan_ret_wmm_ts_status(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)3131*4882a593Smuzhiyun mlan_status wlan_ret_wmm_ts_status(pmlan_private pmpriv,
3132*4882a593Smuzhiyun HostCmd_DS_COMMAND *resp,
3133*4882a593Smuzhiyun mlan_ioctl_req *pioctl_buf)
3134*4882a593Smuzhiyun {
3135*4882a593Smuzhiyun mlan_ds_wmm_cfg *pwmm = MNULL;
3136*4882a593Smuzhiyun HostCmd_DS_WMM_TS_STATUS *presp_ts_status = &resp->params.ts_status;
3137*4882a593Smuzhiyun
3138*4882a593Smuzhiyun ENTER();
3139*4882a593Smuzhiyun
3140*4882a593Smuzhiyun if (pioctl_buf) {
3141*4882a593Smuzhiyun pwmm = (mlan_ds_wmm_cfg *)pioctl_buf->pbuf;
3142*4882a593Smuzhiyun presp_ts_status->medium_time =
3143*4882a593Smuzhiyun wlan_le16_to_cpu(presp_ts_status->medium_time);
3144*4882a593Smuzhiyun memcpy_ext(pmpriv->adapter, (t_void *)&pwmm->param.ts_status,
3145*4882a593Smuzhiyun (t_void *)presp_ts_status,
3146*4882a593Smuzhiyun sizeof(mlan_ds_wmm_ts_status),
3147*4882a593Smuzhiyun sizeof(mlan_ds_wmm_ts_status));
3148*4882a593Smuzhiyun }
3149*4882a593Smuzhiyun
3150*4882a593Smuzhiyun LEAVE();
3151*4882a593Smuzhiyun return MLAN_STATUS_SUCCESS;
3152*4882a593Smuzhiyun }
3153*4882a593Smuzhiyun
3154*4882a593Smuzhiyun /**
3155*4882a593Smuzhiyun * @brief Set/Get WMM status
3156*4882a593Smuzhiyun *
3157*4882a593Smuzhiyun * @param pmadapter A pointer to mlan_adapter structure
3158*4882a593Smuzhiyun * @param pioctl_req A pointer to ioctl request buffer
3159*4882a593Smuzhiyun *
3160*4882a593Smuzhiyun * @return MLAN_STATUS_SUCCESS --success
3161*4882a593Smuzhiyun */
wlan_wmm_ioctl_enable(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3162*4882a593Smuzhiyun static mlan_status wlan_wmm_ioctl_enable(pmlan_adapter pmadapter,
3163*4882a593Smuzhiyun pmlan_ioctl_req pioctl_req)
3164*4882a593Smuzhiyun {
3165*4882a593Smuzhiyun mlan_status ret = MLAN_STATUS_SUCCESS;
3166*4882a593Smuzhiyun mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
3167*4882a593Smuzhiyun mlan_ds_wmm_cfg *wmm = MNULL;
3168*4882a593Smuzhiyun ENTER();
3169*4882a593Smuzhiyun wmm = (mlan_ds_wmm_cfg *)pioctl_req->pbuf;
3170*4882a593Smuzhiyun if (pioctl_req->action == MLAN_ACT_GET)
3171*4882a593Smuzhiyun wmm->param.wmm_enable = (t_u32)pmpriv->wmm_required;
3172*4882a593Smuzhiyun else
3173*4882a593Smuzhiyun pmpriv->wmm_required = (t_u8)wmm->param.wmm_enable;
3174*4882a593Smuzhiyun pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
3175*4882a593Smuzhiyun LEAVE();
3176*4882a593Smuzhiyun return ret;
3177*4882a593Smuzhiyun }
3178*4882a593Smuzhiyun
3179*4882a593Smuzhiyun /**
3180*4882a593Smuzhiyun * @brief Set/Get WMM QoS configuration
3181*4882a593Smuzhiyun *
3182*4882a593Smuzhiyun * @param pmadapter A pointer to mlan_adapter structure
3183*4882a593Smuzhiyun * @param pioctl_req A pointer to ioctl request buffer
3184*4882a593Smuzhiyun *
3185*4882a593Smuzhiyun * @return MLAN_STATUS_SUCCESS --success
3186*4882a593Smuzhiyun */
wlan_wmm_ioctl_qos(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3187*4882a593Smuzhiyun static mlan_status wlan_wmm_ioctl_qos(pmlan_adapter pmadapter,
3188*4882a593Smuzhiyun pmlan_ioctl_req pioctl_req)
3189*4882a593Smuzhiyun {
3190*4882a593Smuzhiyun mlan_status ret = MLAN_STATUS_SUCCESS;
3191*4882a593Smuzhiyun mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
3192*4882a593Smuzhiyun mlan_ds_wmm_cfg *wmm = MNULL;
3193*4882a593Smuzhiyun
3194*4882a593Smuzhiyun ENTER();
3195*4882a593Smuzhiyun
3196*4882a593Smuzhiyun wmm = (mlan_ds_wmm_cfg *)pioctl_req->pbuf;
3197*4882a593Smuzhiyun
3198*4882a593Smuzhiyun if (pioctl_req->action == MLAN_ACT_GET)
3199*4882a593Smuzhiyun wmm->param.qos_cfg = pmpriv->wmm_qosinfo;
3200*4882a593Smuzhiyun else {
3201*4882a593Smuzhiyun pmpriv->wmm_qosinfo = wmm->param.qos_cfg;
3202*4882a593Smuzhiyun pmpriv->saved_wmm_qosinfo = wmm->param.qos_cfg;
3203*4882a593Smuzhiyun }
3204*4882a593Smuzhiyun
3205*4882a593Smuzhiyun pioctl_req->data_read_written = sizeof(t_u8) + MLAN_SUB_COMMAND_SIZE;
3206*4882a593Smuzhiyun
3207*4882a593Smuzhiyun LEAVE();
3208*4882a593Smuzhiyun return ret;
3209*4882a593Smuzhiyun }
3210*4882a593Smuzhiyun
3211*4882a593Smuzhiyun /**
3212*4882a593Smuzhiyun * @brief Request for add a TSPEC
3213*4882a593Smuzhiyun *
3214*4882a593Smuzhiyun * @param pmadapter A pointer to mlan_adapter structure
3215*4882a593Smuzhiyun * @param pioctl_req A pointer to ioctl request buffer
3216*4882a593Smuzhiyun *
3217*4882a593Smuzhiyun * @return MLAN_STATUS_PENDING --success, otherwise fail
3218*4882a593Smuzhiyun */
wlan_wmm_ioctl_addts_req(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3219*4882a593Smuzhiyun static mlan_status wlan_wmm_ioctl_addts_req(pmlan_adapter pmadapter,
3220*4882a593Smuzhiyun pmlan_ioctl_req pioctl_req)
3221*4882a593Smuzhiyun {
3222*4882a593Smuzhiyun mlan_status ret = MLAN_STATUS_SUCCESS;
3223*4882a593Smuzhiyun pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
3224*4882a593Smuzhiyun mlan_ds_wmm_cfg *cfg = MNULL;
3225*4882a593Smuzhiyun
3226*4882a593Smuzhiyun ENTER();
3227*4882a593Smuzhiyun cfg = (mlan_ds_wmm_cfg *)pioctl_req->pbuf;
3228*4882a593Smuzhiyun
3229*4882a593Smuzhiyun /* Send request to firmware */
3230*4882a593Smuzhiyun ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_WMM_ADDTS_REQ, 0, 0,
3231*4882a593Smuzhiyun (t_void *)pioctl_req,
3232*4882a593Smuzhiyun (t_void *)&cfg->param.addts);
3233*4882a593Smuzhiyun
3234*4882a593Smuzhiyun if (ret == MLAN_STATUS_SUCCESS)
3235*4882a593Smuzhiyun ret = MLAN_STATUS_PENDING;
3236*4882a593Smuzhiyun
3237*4882a593Smuzhiyun LEAVE();
3238*4882a593Smuzhiyun return ret;
3239*4882a593Smuzhiyun }
3240*4882a593Smuzhiyun
3241*4882a593Smuzhiyun /**
3242*4882a593Smuzhiyun * @brief Request for delete a TSPEC
3243*4882a593Smuzhiyun *
3244*4882a593Smuzhiyun * @param pmadapter A pointer to mlan_adapter structure
3245*4882a593Smuzhiyun * @param pioctl_req A pointer to ioctl request buffer
3246*4882a593Smuzhiyun *
3247*4882a593Smuzhiyun * @return MLAN_STATUS_PENDING --success, otherwise fail
3248*4882a593Smuzhiyun */
wlan_wmm_ioctl_delts_req(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3249*4882a593Smuzhiyun static mlan_status wlan_wmm_ioctl_delts_req(pmlan_adapter pmadapter,
3250*4882a593Smuzhiyun pmlan_ioctl_req pioctl_req)
3251*4882a593Smuzhiyun {
3252*4882a593Smuzhiyun mlan_status ret = MLAN_STATUS_SUCCESS;
3253*4882a593Smuzhiyun pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
3254*4882a593Smuzhiyun mlan_ds_wmm_cfg *cfg = MNULL;
3255*4882a593Smuzhiyun
3256*4882a593Smuzhiyun ENTER();
3257*4882a593Smuzhiyun cfg = (mlan_ds_wmm_cfg *)pioctl_req->pbuf;
3258*4882a593Smuzhiyun
3259*4882a593Smuzhiyun /* Send request to firmware */
3260*4882a593Smuzhiyun ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_WMM_DELTS_REQ, 0, 0,
3261*4882a593Smuzhiyun (t_void *)pioctl_req,
3262*4882a593Smuzhiyun (t_void *)&cfg->param.delts);
3263*4882a593Smuzhiyun
3264*4882a593Smuzhiyun if (ret == MLAN_STATUS_SUCCESS)
3265*4882a593Smuzhiyun ret = MLAN_STATUS_PENDING;
3266*4882a593Smuzhiyun
3267*4882a593Smuzhiyun LEAVE();
3268*4882a593Smuzhiyun return ret;
3269*4882a593Smuzhiyun }
3270*4882a593Smuzhiyun
3271*4882a593Smuzhiyun /**
3272*4882a593Smuzhiyun * @brief To get and start/stop queue stats on a WMM AC
3273*4882a593Smuzhiyun *
3274*4882a593Smuzhiyun * @param pmadapter A pointer to mlan_adapter structure
3275*4882a593Smuzhiyun * @param pioctl_req A pointer to ioctl request buffer
3276*4882a593Smuzhiyun *
3277*4882a593Smuzhiyun * @return MLAN_STATUS_PENDING --success, otherwise fail
3278*4882a593Smuzhiyun */
wlan_wmm_ioctl_queue_stats(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3279*4882a593Smuzhiyun static mlan_status wlan_wmm_ioctl_queue_stats(pmlan_adapter pmadapter,
3280*4882a593Smuzhiyun pmlan_ioctl_req pioctl_req)
3281*4882a593Smuzhiyun {
3282*4882a593Smuzhiyun mlan_status ret = MLAN_STATUS_SUCCESS;
3283*4882a593Smuzhiyun pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
3284*4882a593Smuzhiyun mlan_ds_wmm_cfg *cfg = MNULL;
3285*4882a593Smuzhiyun
3286*4882a593Smuzhiyun ENTER();
3287*4882a593Smuzhiyun cfg = (mlan_ds_wmm_cfg *)pioctl_req->pbuf;
3288*4882a593Smuzhiyun
3289*4882a593Smuzhiyun /* Send request to firmware */
3290*4882a593Smuzhiyun ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_WMM_QUEUE_STATS, 0, 0,
3291*4882a593Smuzhiyun (t_void *)pioctl_req,
3292*4882a593Smuzhiyun (t_void *)&cfg->param.q_stats);
3293*4882a593Smuzhiyun
3294*4882a593Smuzhiyun if (ret == MLAN_STATUS_SUCCESS)
3295*4882a593Smuzhiyun ret = MLAN_STATUS_PENDING;
3296*4882a593Smuzhiyun
3297*4882a593Smuzhiyun LEAVE();
3298*4882a593Smuzhiyun return ret;
3299*4882a593Smuzhiyun }
3300*4882a593Smuzhiyun
3301*4882a593Smuzhiyun /**
3302*4882a593Smuzhiyun * @brief Get the status of the WMM AC queues
3303*4882a593Smuzhiyun *
3304*4882a593Smuzhiyun * @param pmadapter A pointer to mlan_adapter structure
3305*4882a593Smuzhiyun * @param pioctl_req A pointer to ioctl request buffer
3306*4882a593Smuzhiyun *
3307*4882a593Smuzhiyun * @return MLAN_STATUS_SUCCESS --success
3308*4882a593Smuzhiyun */
wlan_wmm_ioctl_queue_status(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3309*4882a593Smuzhiyun static mlan_status wlan_wmm_ioctl_queue_status(pmlan_adapter pmadapter,
3310*4882a593Smuzhiyun pmlan_ioctl_req pioctl_req)
3311*4882a593Smuzhiyun {
3312*4882a593Smuzhiyun mlan_status ret = MLAN_STATUS_SUCCESS;
3313*4882a593Smuzhiyun pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
3314*4882a593Smuzhiyun mlan_ds_wmm_cfg *cfg = MNULL;
3315*4882a593Smuzhiyun mlan_ds_wmm_queue_status *pqstatus = MNULL;
3316*4882a593Smuzhiyun WmmAcStatus_t *pac_status = MNULL;
3317*4882a593Smuzhiyun mlan_wmm_ac_e ac_idx;
3318*4882a593Smuzhiyun
3319*4882a593Smuzhiyun ENTER();
3320*4882a593Smuzhiyun
3321*4882a593Smuzhiyun cfg = (mlan_ds_wmm_cfg *)pioctl_req->pbuf;
3322*4882a593Smuzhiyun pqstatus = (mlan_ds_wmm_queue_status *)&cfg->param.q_status;
3323*4882a593Smuzhiyun
3324*4882a593Smuzhiyun for (ac_idx = WMM_AC_BK; ac_idx <= WMM_AC_VO; ac_idx++) {
3325*4882a593Smuzhiyun pac_status = &pmpriv->wmm.ac_status[ac_idx];
3326*4882a593Smuzhiyun
3327*4882a593Smuzhiyun /* Firmware status */
3328*4882a593Smuzhiyun pqstatus->ac_status[ac_idx].flow_required =
3329*4882a593Smuzhiyun pac_status->flow_required;
3330*4882a593Smuzhiyun pqstatus->ac_status[ac_idx].flow_created =
3331*4882a593Smuzhiyun pac_status->flow_created;
3332*4882a593Smuzhiyun pqstatus->ac_status[ac_idx].disabled = pac_status->disabled;
3333*4882a593Smuzhiyun
3334*4882a593Smuzhiyun /* ACM bit reflected in firmware status (redundant) */
3335*4882a593Smuzhiyun pqstatus->ac_status[ac_idx].wmm_acm = pac_status->flow_required;
3336*4882a593Smuzhiyun }
3337*4882a593Smuzhiyun
3338*4882a593Smuzhiyun LEAVE();
3339*4882a593Smuzhiyun return ret;
3340*4882a593Smuzhiyun }
3341*4882a593Smuzhiyun
3342*4882a593Smuzhiyun /**
3343*4882a593Smuzhiyun * @brief Get the status of the WMM Traffic Streams
3344*4882a593Smuzhiyun *
3345*4882a593Smuzhiyun * @param pmadapter A pointer to mlan_adapter structure
3346*4882a593Smuzhiyun * @param pioctl_req A pointer to ioctl request buffer
3347*4882a593Smuzhiyun *
3348*4882a593Smuzhiyun * @return MLAN_STATUS_PENDING --success, otherwise fail
3349*4882a593Smuzhiyun */
wlan_wmm_ioctl_ts_status(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3350*4882a593Smuzhiyun static mlan_status wlan_wmm_ioctl_ts_status(pmlan_adapter pmadapter,
3351*4882a593Smuzhiyun pmlan_ioctl_req pioctl_req)
3352*4882a593Smuzhiyun {
3353*4882a593Smuzhiyun mlan_status ret = MLAN_STATUS_SUCCESS;
3354*4882a593Smuzhiyun pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
3355*4882a593Smuzhiyun mlan_ds_wmm_cfg *cfg = MNULL;
3356*4882a593Smuzhiyun
3357*4882a593Smuzhiyun ENTER();
3358*4882a593Smuzhiyun
3359*4882a593Smuzhiyun cfg = (mlan_ds_wmm_cfg *)pioctl_req->pbuf;
3360*4882a593Smuzhiyun
3361*4882a593Smuzhiyun /* Send request to firmware */
3362*4882a593Smuzhiyun ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_WMM_TS_STATUS, 0, 0,
3363*4882a593Smuzhiyun (t_void *)pioctl_req,
3364*4882a593Smuzhiyun (t_void *)&cfg->param.ts_status);
3365*4882a593Smuzhiyun
3366*4882a593Smuzhiyun if (ret == MLAN_STATUS_SUCCESS)
3367*4882a593Smuzhiyun ret = MLAN_STATUS_PENDING;
3368*4882a593Smuzhiyun
3369*4882a593Smuzhiyun LEAVE();
3370*4882a593Smuzhiyun return ret;
3371*4882a593Smuzhiyun }
3372*4882a593Smuzhiyun #endif /* STA_SUPPORT */
3373*4882a593Smuzhiyun
3374*4882a593Smuzhiyun /**
3375*4882a593Smuzhiyun * @brief This function prepares the command of WMM_PARAM_CONFIG
3376*4882a593Smuzhiyun *
3377*4882a593Smuzhiyun * @param pmpriv A pointer to mlan_private structure
3378*4882a593Smuzhiyun * @param cmd A pointer to HostCmd_DS_COMMAND structure
3379*4882a593Smuzhiyun * @param cmd_action cmd action.
3380*4882a593Smuzhiyun * @param pdata_buf A pointer to data buffer
3381*4882a593Smuzhiyun * @return MLAN_STATUS_SUCCESS
3382*4882a593Smuzhiyun */
wlan_cmd_wmm_param_config(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u8 cmd_action,t_void * pdata_buf)3383*4882a593Smuzhiyun mlan_status wlan_cmd_wmm_param_config(pmlan_private pmpriv,
3384*4882a593Smuzhiyun HostCmd_DS_COMMAND *cmd, t_u8 cmd_action,
3385*4882a593Smuzhiyun t_void *pdata_buf)
3386*4882a593Smuzhiyun {
3387*4882a593Smuzhiyun wmm_ac_parameters_t *ac_params = (wmm_ac_parameters_t *)pdata_buf;
3388*4882a593Smuzhiyun HostCmd_DS_WMM_PARAM_CONFIG *pcmd_cfg = &cmd->params.param_config;
3389*4882a593Smuzhiyun t_u8 i = 0;
3390*4882a593Smuzhiyun
3391*4882a593Smuzhiyun ENTER();
3392*4882a593Smuzhiyun
3393*4882a593Smuzhiyun cmd->command = wlan_cpu_to_le16(HostCmd_CMD_WMM_PARAM_CONFIG);
3394*4882a593Smuzhiyun cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_WMM_PARAM_CONFIG) +
3395*4882a593Smuzhiyun S_DS_GEN);
3396*4882a593Smuzhiyun cmd->result = 0;
3397*4882a593Smuzhiyun
3398*4882a593Smuzhiyun pcmd_cfg->action = cmd_action;
3399*4882a593Smuzhiyun if (cmd_action == HostCmd_ACT_GEN_SET) {
3400*4882a593Smuzhiyun memcpy_ext(pmpriv->adapter, pcmd_cfg->ac_params, ac_params,
3401*4882a593Smuzhiyun sizeof(wmm_ac_parameters_t) * MAX_AC_QUEUES,
3402*4882a593Smuzhiyun sizeof(wmm_ac_parameters_t) * MAX_AC_QUEUES);
3403*4882a593Smuzhiyun for (i = 0; i < MAX_AC_QUEUES; i++) {
3404*4882a593Smuzhiyun pcmd_cfg->ac_params[i].tx_op_limit = wlan_cpu_to_le16(
3405*4882a593Smuzhiyun pcmd_cfg->ac_params[i].tx_op_limit);
3406*4882a593Smuzhiyun }
3407*4882a593Smuzhiyun }
3408*4882a593Smuzhiyun LEAVE();
3409*4882a593Smuzhiyun return MLAN_STATUS_SUCCESS;
3410*4882a593Smuzhiyun }
3411*4882a593Smuzhiyun
3412*4882a593Smuzhiyun /**
3413*4882a593Smuzhiyun * @brief This function handles the command response of WMM_PARAM_CONFIG
3414*4882a593Smuzhiyun *
3415*4882a593Smuzhiyun * @param pmpriv A pointer to mlan_private structure
3416*4882a593Smuzhiyun * @param resp A pointer to HostCmd_DS_COMMAND
3417*4882a593Smuzhiyun * @param pioctl_buf A pointer to mlan_ioctl_req structure
3418*4882a593Smuzhiyun *
3419*4882a593Smuzhiyun * @return MLAN_STATUS_SUCCESS
3420*4882a593Smuzhiyun */
wlan_ret_wmm_param_config(pmlan_private pmpriv,const HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)3421*4882a593Smuzhiyun mlan_status wlan_ret_wmm_param_config(pmlan_private pmpriv,
3422*4882a593Smuzhiyun const HostCmd_DS_COMMAND *resp,
3423*4882a593Smuzhiyun mlan_ioctl_req *pioctl_buf)
3424*4882a593Smuzhiyun {
3425*4882a593Smuzhiyun mlan_ds_wmm_cfg *pwmm = MNULL;
3426*4882a593Smuzhiyun HostCmd_DS_WMM_PARAM_CONFIG *pcfg =
3427*4882a593Smuzhiyun (HostCmd_DS_WMM_PARAM_CONFIG *)&resp->params.param_config;
3428*4882a593Smuzhiyun t_u8 i;
3429*4882a593Smuzhiyun
3430*4882a593Smuzhiyun ENTER();
3431*4882a593Smuzhiyun
3432*4882a593Smuzhiyun if (pioctl_buf) {
3433*4882a593Smuzhiyun pwmm = (mlan_ds_wmm_cfg *)pioctl_buf->pbuf;
3434*4882a593Smuzhiyun for (i = 0; i < MAX_AC_QUEUES; i++) {
3435*4882a593Smuzhiyun pcfg->ac_params[i].tx_op_limit = wlan_le16_to_cpu(
3436*4882a593Smuzhiyun pcfg->ac_params[i].tx_op_limit);
3437*4882a593Smuzhiyun }
3438*4882a593Smuzhiyun memcpy_ext(pmpriv->adapter, pwmm->param.ac_params,
3439*4882a593Smuzhiyun pcfg->ac_params,
3440*4882a593Smuzhiyun sizeof(wmm_ac_parameters_t) * MAX_AC_QUEUES,
3441*4882a593Smuzhiyun sizeof(wmm_ac_parameters_t) * MAX_AC_QUEUES);
3442*4882a593Smuzhiyun }
3443*4882a593Smuzhiyun
3444*4882a593Smuzhiyun LEAVE();
3445*4882a593Smuzhiyun return MLAN_STATUS_SUCCESS;
3446*4882a593Smuzhiyun }
3447*4882a593Smuzhiyun
3448*4882a593Smuzhiyun /**
3449*4882a593Smuzhiyun * @brief This function prepares the command of WMM_QUEUE_CONFIG
3450*4882a593Smuzhiyun *
3451*4882a593Smuzhiyun * @param pmpriv A pointer to mlan_private structure
3452*4882a593Smuzhiyun * @param cmd A pointer to HostCmd_DS_COMMAND structure
3453*4882a593Smuzhiyun * @param pdata_buf A pointer to data buffer
3454*4882a593Smuzhiyun * @return MLAN_STATUS_SUCCESS
3455*4882a593Smuzhiyun */
wlan_cmd_wmm_queue_config(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_void * pdata_buf)3456*4882a593Smuzhiyun mlan_status wlan_cmd_wmm_queue_config(pmlan_private pmpriv,
3457*4882a593Smuzhiyun HostCmd_DS_COMMAND *cmd,
3458*4882a593Smuzhiyun t_void *pdata_buf)
3459*4882a593Smuzhiyun {
3460*4882a593Smuzhiyun mlan_ds_wmm_queue_config *pqcfg = (mlan_ds_wmm_queue_config *)pdata_buf;
3461*4882a593Smuzhiyun HostCmd_DS_WMM_QUEUE_CONFIG *pcmd_qcfg = &cmd->params.queue_config;
3462*4882a593Smuzhiyun
3463*4882a593Smuzhiyun ENTER();
3464*4882a593Smuzhiyun
3465*4882a593Smuzhiyun cmd->command = wlan_cpu_to_le16(HostCmd_CMD_WMM_QUEUE_CONFIG);
3466*4882a593Smuzhiyun cmd->size = wlan_cpu_to_le16(
3467*4882a593Smuzhiyun sizeof(pcmd_qcfg->action) + sizeof(pcmd_qcfg->access_category) +
3468*4882a593Smuzhiyun sizeof(pcmd_qcfg->msdu_lifetime_expiry) + S_DS_GEN);
3469*4882a593Smuzhiyun cmd->result = 0;
3470*4882a593Smuzhiyun
3471*4882a593Smuzhiyun pcmd_qcfg->action = pqcfg->action;
3472*4882a593Smuzhiyun pcmd_qcfg->access_category = pqcfg->access_category;
3473*4882a593Smuzhiyun pcmd_qcfg->msdu_lifetime_expiry =
3474*4882a593Smuzhiyun wlan_cpu_to_le16(pqcfg->msdu_lifetime_expiry);
3475*4882a593Smuzhiyun
3476*4882a593Smuzhiyun LEAVE();
3477*4882a593Smuzhiyun return MLAN_STATUS_SUCCESS;
3478*4882a593Smuzhiyun }
3479*4882a593Smuzhiyun
3480*4882a593Smuzhiyun /**
3481*4882a593Smuzhiyun * @brief This function handles the command response of WMM_QUEUE_CONFIG
3482*4882a593Smuzhiyun *
3483*4882a593Smuzhiyun * @param pmpriv A pointer to mlan_private structure
3484*4882a593Smuzhiyun * @param resp A pointer to HostCmd_DS_COMMAND
3485*4882a593Smuzhiyun * @param pioctl_buf A pointer to mlan_ioctl_req structure
3486*4882a593Smuzhiyun *
3487*4882a593Smuzhiyun * @return MLAN_STATUS_SUCCESS
3488*4882a593Smuzhiyun */
wlan_ret_wmm_queue_config(pmlan_private pmpriv,const HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)3489*4882a593Smuzhiyun mlan_status wlan_ret_wmm_queue_config(pmlan_private pmpriv,
3490*4882a593Smuzhiyun const HostCmd_DS_COMMAND *resp,
3491*4882a593Smuzhiyun mlan_ioctl_req *pioctl_buf)
3492*4882a593Smuzhiyun {
3493*4882a593Smuzhiyun mlan_ds_wmm_cfg *pwmm = MNULL;
3494*4882a593Smuzhiyun const HostCmd_DS_WMM_QUEUE_CONFIG *presp_qcfg =
3495*4882a593Smuzhiyun &resp->params.queue_config;
3496*4882a593Smuzhiyun
3497*4882a593Smuzhiyun ENTER();
3498*4882a593Smuzhiyun
3499*4882a593Smuzhiyun if (pioctl_buf) {
3500*4882a593Smuzhiyun pwmm = (mlan_ds_wmm_cfg *)pioctl_buf->pbuf;
3501*4882a593Smuzhiyun pwmm->param.q_cfg.action = wlan_le32_to_cpu(presp_qcfg->action);
3502*4882a593Smuzhiyun pwmm->param.q_cfg.access_category =
3503*4882a593Smuzhiyun wlan_le32_to_cpu(presp_qcfg->access_category);
3504*4882a593Smuzhiyun pwmm->param.q_cfg.msdu_lifetime_expiry =
3505*4882a593Smuzhiyun wlan_le16_to_cpu(presp_qcfg->msdu_lifetime_expiry);
3506*4882a593Smuzhiyun }
3507*4882a593Smuzhiyun
3508*4882a593Smuzhiyun LEAVE();
3509*4882a593Smuzhiyun return MLAN_STATUS_SUCCESS;
3510*4882a593Smuzhiyun }
3511*4882a593Smuzhiyun
3512*4882a593Smuzhiyun /**
3513*4882a593Smuzhiyun * @brief Set/Get a specified AC Queue's parameters
3514*4882a593Smuzhiyun *
3515*4882a593Smuzhiyun * @param pmadapter A pointer to mlan_adapter structure
3516*4882a593Smuzhiyun * @param pioctl_req A pointer to ioctl request buffer
3517*4882a593Smuzhiyun *
3518*4882a593Smuzhiyun * @return MLAN_STATUS_PENDING --success, otherwise fail
3519*4882a593Smuzhiyun */
wlan_wmm_ioctl_queue_config(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3520*4882a593Smuzhiyun static mlan_status wlan_wmm_ioctl_queue_config(pmlan_adapter pmadapter,
3521*4882a593Smuzhiyun pmlan_ioctl_req pioctl_req)
3522*4882a593Smuzhiyun {
3523*4882a593Smuzhiyun mlan_status ret = MLAN_STATUS_SUCCESS;
3524*4882a593Smuzhiyun pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
3525*4882a593Smuzhiyun mlan_ds_wmm_cfg *cfg = MNULL;
3526*4882a593Smuzhiyun
3527*4882a593Smuzhiyun ENTER();
3528*4882a593Smuzhiyun cfg = (mlan_ds_wmm_cfg *)pioctl_req->pbuf;
3529*4882a593Smuzhiyun
3530*4882a593Smuzhiyun /* Send request to firmware */
3531*4882a593Smuzhiyun ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_WMM_QUEUE_CONFIG, 0, 0,
3532*4882a593Smuzhiyun (t_void *)pioctl_req,
3533*4882a593Smuzhiyun (t_void *)&cfg->param.q_cfg);
3534*4882a593Smuzhiyun
3535*4882a593Smuzhiyun if (ret == MLAN_STATUS_SUCCESS)
3536*4882a593Smuzhiyun ret = MLAN_STATUS_PENDING;
3537*4882a593Smuzhiyun
3538*4882a593Smuzhiyun LEAVE();
3539*4882a593Smuzhiyun return ret;
3540*4882a593Smuzhiyun }
3541*4882a593Smuzhiyun
3542*4882a593Smuzhiyun /**
3543*4882a593Smuzhiyun * @brief WMM configuration handler
3544*4882a593Smuzhiyun *
3545*4882a593Smuzhiyun * @param pmadapter A pointer to mlan_adapter structure
3546*4882a593Smuzhiyun * @param pioctl_req A pointer to ioctl request buffer
3547*4882a593Smuzhiyun *
3548*4882a593Smuzhiyun * @return MLAN_STATUS_SUCCESS --success, otherwise fail
3549*4882a593Smuzhiyun */
wlan_wmm_cfg_ioctl(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3550*4882a593Smuzhiyun mlan_status wlan_wmm_cfg_ioctl(pmlan_adapter pmadapter,
3551*4882a593Smuzhiyun pmlan_ioctl_req pioctl_req)
3552*4882a593Smuzhiyun {
3553*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
3554*4882a593Smuzhiyun mlan_ds_wmm_cfg *wmm = MNULL;
3555*4882a593Smuzhiyun
3556*4882a593Smuzhiyun ENTER();
3557*4882a593Smuzhiyun
3558*4882a593Smuzhiyun if (pioctl_req->buf_len < sizeof(mlan_ds_wmm_cfg)) {
3559*4882a593Smuzhiyun PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
3560*4882a593Smuzhiyun pioctl_req->data_read_written = 0;
3561*4882a593Smuzhiyun pioctl_req->buf_len_needed = sizeof(mlan_ds_wmm_cfg);
3562*4882a593Smuzhiyun pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
3563*4882a593Smuzhiyun LEAVE();
3564*4882a593Smuzhiyun return MLAN_STATUS_RESOURCE;
3565*4882a593Smuzhiyun }
3566*4882a593Smuzhiyun wmm = (mlan_ds_wmm_cfg *)pioctl_req->pbuf;
3567*4882a593Smuzhiyun switch (wmm->sub_command) {
3568*4882a593Smuzhiyun #ifdef STA_SUPPORT
3569*4882a593Smuzhiyun case MLAN_OID_WMM_CFG_ENABLE:
3570*4882a593Smuzhiyun status = wlan_wmm_ioctl_enable(pmadapter, pioctl_req);
3571*4882a593Smuzhiyun break;
3572*4882a593Smuzhiyun case MLAN_OID_WMM_CFG_QOS:
3573*4882a593Smuzhiyun status = wlan_wmm_ioctl_qos(pmadapter, pioctl_req);
3574*4882a593Smuzhiyun break;
3575*4882a593Smuzhiyun case MLAN_OID_WMM_CFG_ADDTS:
3576*4882a593Smuzhiyun status = wlan_wmm_ioctl_addts_req(pmadapter, pioctl_req);
3577*4882a593Smuzhiyun break;
3578*4882a593Smuzhiyun case MLAN_OID_WMM_CFG_DELTS:
3579*4882a593Smuzhiyun status = wlan_wmm_ioctl_delts_req(pmadapter, pioctl_req);
3580*4882a593Smuzhiyun break;
3581*4882a593Smuzhiyun case MLAN_OID_WMM_CFG_QUEUE_STATS:
3582*4882a593Smuzhiyun status = wlan_wmm_ioctl_queue_stats(pmadapter, pioctl_req);
3583*4882a593Smuzhiyun break;
3584*4882a593Smuzhiyun case MLAN_OID_WMM_CFG_QUEUE_STATUS:
3585*4882a593Smuzhiyun status = wlan_wmm_ioctl_queue_status(pmadapter, pioctl_req);
3586*4882a593Smuzhiyun break;
3587*4882a593Smuzhiyun case MLAN_OID_WMM_CFG_TS_STATUS:
3588*4882a593Smuzhiyun status = wlan_wmm_ioctl_ts_status(pmadapter, pioctl_req);
3589*4882a593Smuzhiyun break;
3590*4882a593Smuzhiyun #endif
3591*4882a593Smuzhiyun case MLAN_OID_WMM_CFG_QUEUE_CONFIG:
3592*4882a593Smuzhiyun status = wlan_wmm_ioctl_queue_config(pmadapter, pioctl_req);
3593*4882a593Smuzhiyun break;
3594*4882a593Smuzhiyun default:
3595*4882a593Smuzhiyun pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
3596*4882a593Smuzhiyun status = MLAN_STATUS_FAILURE;
3597*4882a593Smuzhiyun break;
3598*4882a593Smuzhiyun }
3599*4882a593Smuzhiyun LEAVE();
3600*4882a593Smuzhiyun return status;
3601*4882a593Smuzhiyun }
3602*4882a593Smuzhiyun
3603*4882a593Smuzhiyun /**
3604*4882a593Smuzhiyun * @brief Get ralist info
3605*4882a593Smuzhiyun *
3606*4882a593Smuzhiyun * @param priv A pointer to mlan_private structure
3607*4882a593Smuzhiyun * @param buf A pointer to ralist_info structure
3608*4882a593Smuzhiyun * @return number of ralist entry
3609*4882a593Smuzhiyun *
3610*4882a593Smuzhiyun */
wlan_get_ralist_info(mlan_private * priv,ralist_info * buf)3611*4882a593Smuzhiyun int wlan_get_ralist_info(mlan_private *priv, ralist_info *buf)
3612*4882a593Smuzhiyun {
3613*4882a593Smuzhiyun ralist_info *plist = buf;
3614*4882a593Smuzhiyun mlan_list_head *ra_list_head = MNULL;
3615*4882a593Smuzhiyun raListTbl *ra_list;
3616*4882a593Smuzhiyun int i;
3617*4882a593Smuzhiyun int count = 0;
3618*4882a593Smuzhiyun for (i = 0; i < MAX_NUM_TID; i++) {
3619*4882a593Smuzhiyun ra_list_head = &priv->wmm.tid_tbl_ptr[i].ra_list;
3620*4882a593Smuzhiyun ra_list =
3621*4882a593Smuzhiyun (raListTbl *)util_peek_list(priv->adapter->pmoal_handle,
3622*4882a593Smuzhiyun ra_list_head, MNULL, MNULL);
3623*4882a593Smuzhiyun while (ra_list && ra_list != (raListTbl *)ra_list_head) {
3624*4882a593Smuzhiyun if (ra_list->total_pkts) {
3625*4882a593Smuzhiyun plist->total_pkts = ra_list->total_pkts;
3626*4882a593Smuzhiyun plist->tid = i;
3627*4882a593Smuzhiyun plist->tx_pause = ra_list->tx_pause;
3628*4882a593Smuzhiyun memcpy_ext(priv->adapter, plist->ra,
3629*4882a593Smuzhiyun ra_list->ra, MLAN_MAC_ADDR_LENGTH,
3630*4882a593Smuzhiyun MLAN_MAC_ADDR_LENGTH);
3631*4882a593Smuzhiyun plist++;
3632*4882a593Smuzhiyun count++;
3633*4882a593Smuzhiyun if (count >= MLAN_MAX_RALIST_NUM)
3634*4882a593Smuzhiyun break;
3635*4882a593Smuzhiyun }
3636*4882a593Smuzhiyun ra_list = ra_list->pnext;
3637*4882a593Smuzhiyun }
3638*4882a593Smuzhiyun }
3639*4882a593Smuzhiyun LEAVE();
3640*4882a593Smuzhiyun return count;
3641*4882a593Smuzhiyun }
3642*4882a593Smuzhiyun
3643*4882a593Smuzhiyun /**
3644*4882a593Smuzhiyun * @brief dump ralist info
3645*4882a593Smuzhiyun *
3646*4882a593Smuzhiyun * @param priv A pointer to mlan_private structure
3647*4882a593Smuzhiyun *
3648*4882a593Smuzhiyun * @return N/A
3649*4882a593Smuzhiyun *
3650*4882a593Smuzhiyun */
wlan_dump_ralist(mlan_private * priv)3651*4882a593Smuzhiyun void wlan_dump_ralist(mlan_private *priv)
3652*4882a593Smuzhiyun {
3653*4882a593Smuzhiyun mlan_list_head *ra_list_head = MNULL;
3654*4882a593Smuzhiyun raListTbl *ra_list;
3655*4882a593Smuzhiyun mlan_adapter *pmadapter = priv->adapter;
3656*4882a593Smuzhiyun int i;
3657*4882a593Smuzhiyun t_u32 tx_pkts_queued;
3658*4882a593Smuzhiyun
3659*4882a593Smuzhiyun tx_pkts_queued =
3660*4882a593Smuzhiyun util_scalar_read(pmadapter->pmoal_handle,
3661*4882a593Smuzhiyun &priv->wmm.tx_pkts_queued, MNULL, MNULL);
3662*4882a593Smuzhiyun PRINTM(MERROR, "bss_index = %d, tx_pkts_queued = %d\n", priv->bss_index,
3663*4882a593Smuzhiyun tx_pkts_queued);
3664*4882a593Smuzhiyun if (!tx_pkts_queued)
3665*4882a593Smuzhiyun return;
3666*4882a593Smuzhiyun for (i = 0; i < MAX_NUM_TID; i++) {
3667*4882a593Smuzhiyun ra_list_head = &priv->wmm.tid_tbl_ptr[i].ra_list;
3668*4882a593Smuzhiyun ra_list =
3669*4882a593Smuzhiyun (raListTbl *)util_peek_list(priv->adapter->pmoal_handle,
3670*4882a593Smuzhiyun ra_list_head, MNULL, MNULL);
3671*4882a593Smuzhiyun while (ra_list && ra_list != (raListTbl *)ra_list_head) {
3672*4882a593Smuzhiyun if (ra_list->total_pkts) {
3673*4882a593Smuzhiyun PRINTM(MERROR,
3674*4882a593Smuzhiyun "ralist ra: %02x:%02x:%02x:%02x:%02x:%02x tid=%d pkts=%d pause=%d\n",
3675*4882a593Smuzhiyun ra_list->ra[0], ra_list->ra[1],
3676*4882a593Smuzhiyun ra_list->ra[2], ra_list->ra[3],
3677*4882a593Smuzhiyun ra_list->ra[4], ra_list->ra[5], i,
3678*4882a593Smuzhiyun ra_list->total_pkts, ra_list->tx_pause);
3679*4882a593Smuzhiyun }
3680*4882a593Smuzhiyun ra_list = ra_list->pnext;
3681*4882a593Smuzhiyun }
3682*4882a593Smuzhiyun }
3683*4882a593Smuzhiyun return;
3684*4882a593Smuzhiyun }
3685*4882a593Smuzhiyun
3686*4882a593Smuzhiyun /**
3687*4882a593Smuzhiyun * @brief get tid down
3688*4882a593Smuzhiyun *
3689*4882a593Smuzhiyun * @param priv A pointer to mlan_private structure
3690*4882a593Smuzhiyun * @param tid tid
3691*4882a593Smuzhiyun *
3692*4882a593Smuzhiyun * @return tid_down
3693*4882a593Smuzhiyun *
3694*4882a593Smuzhiyun */
wlan_get_wmm_tid_down(mlan_private * priv,int tid)3695*4882a593Smuzhiyun int wlan_get_wmm_tid_down(mlan_private *priv, int tid)
3696*4882a593Smuzhiyun {
3697*4882a593Smuzhiyun return wlan_wmm_downgrade_tid(priv, tid);
3698*4882a593Smuzhiyun }
3699