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