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