xref: /wlan-driver/qcacld-3.0/core/dp/txrx/ol_tx_hl.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1 /*
2  * Copyright (c) 2011-2020 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include <qdf_atomic.h>         /* qdf_atomic_inc, etc. */
21 #include <qdf_lock.h>           /* qdf_os_spinlock */
22 #include <qdf_time.h>           /* qdf_system_ticks, etc. */
23 #include <qdf_nbuf.h>           /* qdf_nbuf_t */
24 #include <qdf_net_types.h>      /* QDF_NBUF_TX_EXT_TID_INVALID */
25 
26 #include "queue.h"          /* TAILQ */
27 #ifdef QCA_COMPUTE_TX_DELAY
28 #include <enet.h>               /* ethernet_hdr_t, etc. */
29 #include <ipv6_defs.h>          /* ipv6_traffic_class */
30 #endif
31 
32 #include <ol_txrx_api.h>        /* ol_txrx_vdev_handle, etc. */
33 #include <ol_htt_tx_api.h>      /* htt_tx_compl_desc_id */
34 #include <ol_txrx_htt_api.h>    /* htt_tx_status */
35 
36 #include <ol_ctrl_txrx_api.h>
37 #include <cdp_txrx_tx_delay.h>
38 #include <ol_txrx_types.h>      /* ol_txrx_vdev_t, etc */
39 #include <ol_tx_desc.h>         /* ol_tx_desc_find, ol_tx_desc_frame_free */
40 #ifdef QCA_COMPUTE_TX_DELAY
41 #include <ol_tx_classify.h>     /* ol_tx_dest_addr_find */
42 #endif
43 #include <ol_txrx_internal.h>   /* OL_TX_DESC_NO_REFS, etc. */
44 #include <ol_osif_txrx_api.h>
45 #include <ol_tx.h>              /* ol_tx_reinject */
46 #include <ol_tx_send.h>
47 
48 #include <ol_cfg.h>             /* ol_cfg_is_high_latency */
49 #include <ol_tx_sched.h>
50 #ifdef QCA_SUPPORT_SW_TXRX_ENCAP
51 #include <ol_txrx_encap.h>      /* OL_TX_RESTORE_HDR, etc */
52 #endif
53 #include <ol_tx_queue.h>
54 #include <ol_txrx.h>
55 #include <pktlog_ac_fmt.h>
56 #include <cdp_txrx_handle.h>
57 #include <wlan_reg_services_api.h>
58 #include "qdf_hrtimer.h"
59 
60 /* High/Low tx resource count in percentage */
61 /* Set default high threshold to 15% */
62 #ifndef TX_RESOURCE_HIGH_TH_IN_PER
63 #define TX_RESOURCE_HIGH_TH_IN_PER 15
64 #endif
65 
66 /* Set default low threshold to 5% */
67 #ifndef TX_RESOURCE_LOW_TH_IN_PER
68 #define TX_RESOURCE_LOW_TH_IN_PER 5
69 #endif
70 
71 #ifdef QCA_HL_NETDEV_FLOW_CONTROL
72 static u16 ol_txrx_tx_desc_alloc_table[TXRX_FC_MAX] = {
73 	[TXRX_FC_5GH_80M_2x2] = 2000,
74 	[TXRX_FC_2GH_40M_2x2] = 800,
75 };
76 #endif /* QCA_HL_NETDEV_FLOW_CONTROL */
77 
78 /* tx filtering is handled within the target FW */
79 #define TX_FILTER_CHECK(tx_msdu_info) 0 /* don't filter */
80 
81 u_int16_t
ol_tx_desc_pool_size_hl(struct cdp_cfg * ctrl_pdev)82 ol_tx_desc_pool_size_hl(struct cdp_cfg *ctrl_pdev)
83 {
84 	uint16_t desc_pool_size;
85 	uint16_t steady_state_tx_lifetime_ms;
86 	uint16_t safety_factor;
87 
88 	/*
89 	 * Steady-state tx latency:
90 	 *     roughly 1-2 ms flight time
91 	 *   + roughly 1-2 ms prep time,
92 	 *   + roughly 1-2 ms target->host notification time.
93 	 * = roughly 6 ms total
94 	 * Thus, steady state number of frames =
95 	 * steady state max throughput / frame size * tx latency, e.g.
96 	 * 1 Gbps / 1500 bytes * 6 ms = 500
97 	 *
98 	 */
99 	steady_state_tx_lifetime_ms = 6;
100 
101 	safety_factor = 8;
102 
103 	desc_pool_size =
104 		ol_cfg_max_thruput_mbps(ctrl_pdev) *
105 		1000 /* 1e6 bps/mbps / 1e3 ms per sec = 1000 */ /
106 		(8 * OL_TX_AVG_FRM_BYTES) *
107 		steady_state_tx_lifetime_ms *
108 		safety_factor;
109 
110 	/* minimum */
111 	if (desc_pool_size < OL_TX_DESC_POOL_SIZE_MIN_HL)
112 		desc_pool_size = OL_TX_DESC_POOL_SIZE_MIN_HL;
113 
114 	/* maximum */
115 	if (desc_pool_size > OL_TX_DESC_POOL_SIZE_MAX_HL)
116 		desc_pool_size = OL_TX_DESC_POOL_SIZE_MAX_HL;
117 
118 	return desc_pool_size;
119 }
120 
121 #ifdef CONFIG_TX_DESC_HI_PRIO_RESERVE
122 
123 /**
124  * ol_tx_hl_desc_alloc() - Allocate and initialize a tx descriptor
125  *                        for a HL system.
126  * @pdev: the data physical device sending the data
127  * @vdev: the virtual device sending the data
128  * @msdu: the tx frame
129  * @msdu_info: the tx meta data
130  *
131  * Return: the tx descriptor
132  */
133 static inline
ol_tx_hl_desc_alloc(struct ol_txrx_pdev_t * pdev,struct ol_txrx_vdev_t * vdev,qdf_nbuf_t msdu,struct ol_txrx_msdu_info_t * msdu_info)134 struct ol_tx_desc_t *ol_tx_hl_desc_alloc(struct ol_txrx_pdev_t *pdev,
135 					 struct ol_txrx_vdev_t *vdev,
136 					 qdf_nbuf_t msdu,
137 					 struct ol_txrx_msdu_info_t *msdu_info)
138 {
139 	struct ol_tx_desc_t *tx_desc = NULL;
140 
141 	if (qdf_atomic_read(&pdev->tx_queue.rsrc_cnt) >
142 	    TXRX_HL_TX_DESC_HI_PRIO_RESERVED) {
143 		tx_desc = ol_tx_desc_hl(pdev, vdev, msdu, msdu_info);
144 	} else if (qdf_nbuf_is_ipv4_pkt(msdu) == true) {
145 		if ((QDF_NBUF_CB_GET_PACKET_TYPE(msdu) ==
146 		    QDF_NBUF_CB_PACKET_TYPE_DHCP) ||
147 		    (QDF_NBUF_CB_GET_PACKET_TYPE(msdu) ==
148 		    QDF_NBUF_CB_PACKET_TYPE_EAPOL)) {
149 			tx_desc = ol_tx_desc_hl(pdev, vdev, msdu, msdu_info);
150 			ol_txrx_info("Got tx desc from resv pool");
151 		}
152 	}
153 	return tx_desc;
154 }
155 
156 #elif defined(QCA_HL_NETDEV_FLOW_CONTROL)
ol_tx_desc_is_high_prio(qdf_nbuf_t msdu)157 bool ol_tx_desc_is_high_prio(qdf_nbuf_t msdu)
158 {
159 	enum qdf_proto_subtype proto_subtype;
160 	bool high_prio = false;
161 
162 	if (qdf_nbuf_is_ipv4_pkt(msdu) == true) {
163 		if ((QDF_NBUF_CB_GET_PACKET_TYPE(msdu) ==
164 		    QDF_NBUF_CB_PACKET_TYPE_DHCP) ||
165 		    (QDF_NBUF_CB_GET_PACKET_TYPE(msdu) ==
166 		    QDF_NBUF_CB_PACKET_TYPE_EAPOL))
167 			high_prio = true;
168 	} else if (QDF_NBUF_CB_GET_PACKET_TYPE(msdu) ==
169 		   QDF_NBUF_CB_PACKET_TYPE_ARP) {
170 		high_prio = true;
171 	} else if ((QDF_NBUF_CB_GET_PACKET_TYPE(msdu) ==
172 		   QDF_NBUF_CB_PACKET_TYPE_ICMPv6)) {
173 		proto_subtype = qdf_nbuf_get_icmpv6_subtype(msdu);
174 		switch (proto_subtype) {
175 		case QDF_PROTO_ICMPV6_NA:
176 		case QDF_PROTO_ICMPV6_NS:
177 			high_prio = true;
178 		default:
179 			high_prio = false;
180 		}
181 	}
182 	return high_prio;
183 }
184 
185 static inline
ol_tx_hl_desc_alloc(struct ol_txrx_pdev_t * pdev,struct ol_txrx_vdev_t * vdev,qdf_nbuf_t msdu,struct ol_txrx_msdu_info_t * msdu_info)186 struct ol_tx_desc_t *ol_tx_hl_desc_alloc(struct ol_txrx_pdev_t *pdev,
187 					 struct ol_txrx_vdev_t *vdev,
188 					 qdf_nbuf_t msdu,
189 					 struct ol_txrx_msdu_info_t *msdu_info)
190 {
191 	struct ol_tx_desc_t *tx_desc =
192 			ol_tx_desc_hl(pdev, vdev, msdu, msdu_info);
193 
194 	if (!tx_desc)
195 		return NULL;
196 
197 	qdf_spin_lock_bh(&pdev->tx_mutex);
198 	/* return if TX flow control disabled */
199 	if (vdev->tx_desc_limit == 0) {
200 		qdf_spin_unlock_bh(&pdev->tx_mutex);
201 		return tx_desc;
202 	}
203 
204 	if (!qdf_atomic_read(&vdev->os_q_paused) &&
205 	    (qdf_atomic_read(&vdev->tx_desc_count) >= vdev->queue_stop_th)) {
206 		/*
207 		 * Pause normal priority
208 		 * netdev queues if tx desc limit crosses
209 		 */
210 		pdev->pause_cb(vdev->vdev_id,
211 			       WLAN_STOP_NON_PRIORITY_QUEUE,
212 			       WLAN_DATA_FLOW_CONTROL);
213 		qdf_atomic_set(&vdev->os_q_paused, 1);
214 	} else if (ol_tx_desc_is_high_prio(msdu) && !vdev->prio_q_paused &&
215 		   (qdf_atomic_read(&vdev->tx_desc_count)
216 		   == vdev->tx_desc_limit)) {
217 		/* Pause high priority queue */
218 		pdev->pause_cb(vdev->vdev_id,
219 			       WLAN_NETIF_PRIORITY_QUEUE_OFF,
220 			       WLAN_DATA_FLOW_CONTROL_PRIORITY);
221 		vdev->prio_q_paused = 1;
222 	}
223 	qdf_spin_unlock_bh(&pdev->tx_mutex);
224 
225 	return tx_desc;
226 }
227 
228 #else
229 
230 static inline
ol_tx_hl_desc_alloc(struct ol_txrx_pdev_t * pdev,struct ol_txrx_vdev_t * vdev,qdf_nbuf_t msdu,struct ol_txrx_msdu_info_t * msdu_info)231 struct ol_tx_desc_t *ol_tx_hl_desc_alloc(struct ol_txrx_pdev_t *pdev,
232 					 struct ol_txrx_vdev_t *vdev,
233 					 qdf_nbuf_t msdu,
234 					 struct ol_txrx_msdu_info_t *msdu_info)
235 {
236 	struct ol_tx_desc_t *tx_desc = NULL;
237 
238 	tx_desc = ol_tx_desc_hl(pdev, vdev, msdu, msdu_info);
239 	return tx_desc;
240 }
241 #endif
242 
243 static inline uint16_t
ol_txrx_rsrc_threshold_lo(int desc_pool_size)244 ol_txrx_rsrc_threshold_lo(int desc_pool_size)
245 {
246 	int threshold_low;
247 
248 	/* always maintain a 5% margin of unallocated descriptors */
249 	threshold_low = ((TX_RESOURCE_LOW_TH_IN_PER) *
250 			 desc_pool_size) / 100;
251 
252 	return threshold_low;
253 }
254 
255 static inline uint16_t
ol_txrx_rsrc_threshold_hi(int desc_pool_size)256 ol_txrx_rsrc_threshold_hi(int desc_pool_size)
257 {
258 	int threshold_high;
259 	/* when freeing up descriptors, keep going until
260 	 * there's a 15% margin
261 	 */
262 	threshold_high = ((TX_RESOURCE_HIGH_TH_IN_PER) *
263 			  desc_pool_size) / 100;
264 
265 	return threshold_high;
266 }
267 
ol_tx_init_pdev(ol_txrx_pdev_handle pdev)268 void ol_tx_init_pdev(ol_txrx_pdev_handle pdev)
269 {
270 	uint16_t desc_pool_size, i;
271 
272 	desc_pool_size = ol_tx_desc_pool_size_hl(pdev->ctrl_pdev);
273 
274 	qdf_atomic_init(&pdev->tx_queue.rsrc_cnt);
275 	qdf_atomic_add(desc_pool_size, &pdev->tx_queue.rsrc_cnt);
276 
277 	pdev->tx_queue.rsrc_threshold_lo =
278 		ol_txrx_rsrc_threshold_lo(desc_pool_size);
279 	pdev->tx_queue.rsrc_threshold_hi =
280 		ol_txrx_rsrc_threshold_hi(desc_pool_size);
281 
282 	for (i = 0 ; i < OL_TX_MAX_TXQ_GROUPS; i++)
283 		qdf_atomic_init(&pdev->txq_grps[i].credit);
284 
285 	ol_tx_target_credit_init(pdev, desc_pool_size);
286 }
287 
288 #ifdef QCA_SUPPORT_SW_TXRX_ENCAP
ol_tx_encap_wrapper(struct ol_txrx_pdev_t * pdev,ol_txrx_vdev_handle vdev,struct ol_tx_desc_t * tx_desc,qdf_nbuf_t msdu,struct ol_txrx_msdu_info_t * tx_msdu_info)289 static inline int ol_tx_encap_wrapper(struct ol_txrx_pdev_t *pdev,
290 				      ol_txrx_vdev_handle vdev,
291 				      struct ol_tx_desc_t *tx_desc,
292 				      qdf_nbuf_t msdu,
293 				      struct ol_txrx_msdu_info_t *tx_msdu_info)
294 {
295 	if (OL_TX_ENCAP(vdev, tx_desc, msdu, tx_msdu_info) != A_OK) {
296 		qdf_atomic_inc(&pdev->tx_queue.rsrc_cnt);
297 		ol_tx_desc_frame_free_nonstd(pdev, tx_desc, 1);
298 		if (tx_msdu_info->peer) {
299 			/* remove the peer reference added above */
300 			ol_txrx_peer_release_ref(tx_msdu_info->peer,
301 						 PEER_DEBUG_ID_OL_INTERNAL);
302 		}
303 		return -EINVAL;
304 	}
305 
306 	return 0;
307 }
308 #else
ol_tx_encap_wrapper(struct ol_txrx_pdev_t * pdev,ol_txrx_vdev_handle vdev,struct ol_tx_desc_t * tx_desc,qdf_nbuf_t msdu,struct ol_txrx_msdu_info_t * tx_msdu_info)309 static inline int ol_tx_encap_wrapper(struct ol_txrx_pdev_t *pdev,
310 				      ol_txrx_vdev_handle vdev,
311 				      struct ol_tx_desc_t *tx_desc,
312 				      qdf_nbuf_t msdu,
313 				      struct ol_txrx_msdu_info_t *tx_msdu_info)
314 {
315 	/* no-op */
316 	return 0;
317 }
318 #endif
319 
320 /**
321  * parse_ocb_tx_header() - Function to check for OCB
322  * @msdu:   Pointer to OS packet (qdf_nbuf_t)
323  * @tx_ctrl: TX control header on a packet and extract it if present
324  *
325  * Return: true if ocb parsing is successful
326  */
327 #ifdef WLAN_FEATURE_DSRC
328 #define OCB_HEADER_VERSION     1
parse_ocb_tx_header(qdf_nbuf_t msdu,struct ocb_tx_ctrl_hdr_t * tx_ctrl)329 static bool parse_ocb_tx_header(qdf_nbuf_t msdu,
330 				struct ocb_tx_ctrl_hdr_t *tx_ctrl)
331 {
332 	qdf_ether_header_t *eth_hdr_p;
333 	struct ocb_tx_ctrl_hdr_t *tx_ctrl_hdr;
334 
335 	/* Check if TX control header is present */
336 	eth_hdr_p = (qdf_ether_header_t *)qdf_nbuf_data(msdu);
337 	if (eth_hdr_p->ether_type != QDF_SWAP_U16(ETHERTYPE_OCB_TX))
338 		/* TX control header is not present. Nothing to do.. */
339 		return true;
340 
341 	/* Remove the ethernet header */
342 	qdf_nbuf_pull_head(msdu, sizeof(qdf_ether_header_t));
343 
344 	/* Parse the TX control header */
345 	tx_ctrl_hdr = (struct ocb_tx_ctrl_hdr_t *)qdf_nbuf_data(msdu);
346 
347 	if (tx_ctrl_hdr->version == OCB_HEADER_VERSION) {
348 		if (tx_ctrl)
349 			qdf_mem_copy(tx_ctrl, tx_ctrl_hdr,
350 				     sizeof(*tx_ctrl_hdr));
351 	} else {
352 		/* The TX control header is invalid. */
353 		return false;
354 	}
355 
356 	/* Remove the TX control header */
357 	qdf_nbuf_pull_head(msdu, tx_ctrl_hdr->length);
358 	return true;
359 }
360 #else
parse_ocb_tx_header(qdf_nbuf_t msdu,struct ocb_tx_ctrl_hdr_t * tx_ctrl)361 static bool parse_ocb_tx_header(qdf_nbuf_t msdu,
362 				struct ocb_tx_ctrl_hdr_t *tx_ctrl)
363 {
364 	return true;
365 }
366 #endif
367 
368 /**
369  * ol_txrx_mgmt_tx_desc_alloc() - Allocate and initialize a tx descriptor
370  *				 for management frame
371  * @pdev: the data physical device sending the data
372  * @vdev: the virtual device sending the data
373  * @tx_mgmt_frm: the tx management frame
374  * @tx_msdu_info: the tx meta data
375  *
376  * Return: the tx descriptor
377  */
378 struct ol_tx_desc_t *
ol_txrx_mgmt_tx_desc_alloc(struct ol_txrx_pdev_t * pdev,struct ol_txrx_vdev_t * vdev,qdf_nbuf_t tx_mgmt_frm,struct ol_txrx_msdu_info_t * tx_msdu_info)379 ol_txrx_mgmt_tx_desc_alloc(
380 	struct ol_txrx_pdev_t *pdev,
381 	struct ol_txrx_vdev_t *vdev,
382 	qdf_nbuf_t tx_mgmt_frm,
383 	struct ol_txrx_msdu_info_t *tx_msdu_info)
384 {
385 	struct ol_tx_desc_t *tx_desc;
386 
387 	tx_msdu_info->htt.action.tx_comp_req = 1;
388 	tx_desc = ol_tx_desc_hl(pdev, vdev, tx_mgmt_frm, tx_msdu_info);
389 	return tx_desc;
390 }
391 
392 /**
393  * ol_txrx_mgmt_send_frame() - send a management frame
394  * @vdev: virtual device sending the frame
395  * @tx_desc: tx desc
396  * @tx_mgmt_frm: management frame to send
397  * @tx_msdu_info: the tx meta data
398  * @chanfreq: download change frequency
399  *
400  * Return:
401  *      0 -> the frame is accepted for transmission, -OR-
402  *      1 -> the frame was not accepted
403  */
ol_txrx_mgmt_send_frame(struct ol_txrx_vdev_t * vdev,struct ol_tx_desc_t * tx_desc,qdf_nbuf_t tx_mgmt_frm,struct ol_txrx_msdu_info_t * tx_msdu_info,uint16_t chanfreq)404 int ol_txrx_mgmt_send_frame(
405 	struct ol_txrx_vdev_t *vdev,
406 	struct ol_tx_desc_t *tx_desc,
407 	qdf_nbuf_t tx_mgmt_frm,
408 	struct ol_txrx_msdu_info_t *tx_msdu_info,
409 	uint16_t chanfreq)
410 {
411 	struct ol_txrx_pdev_t *pdev = vdev->pdev;
412 	struct ol_tx_frms_queue_t *txq;
413 	int status = 1;
414 
415 	/*
416 	 * 1.  Look up the peer and queue the frame in the peer's mgmt queue.
417 	 * 2.  Invoke the download scheduler.
418 	 */
419 	txq = ol_tx_classify_mgmt(vdev, tx_desc, tx_mgmt_frm, tx_msdu_info);
420 	if (!txq) {
421 		/* TXRX_STATS_MSDU_LIST_INCR(vdev->pdev, tx.dropped.no_txq,
422 		 *			     msdu);
423 		 */
424 		qdf_atomic_inc(&pdev->tx_queue.rsrc_cnt);
425 		ol_tx_desc_frame_free_nonstd(vdev->pdev, tx_desc,
426 					     1 /* error */);
427 		goto out; /* can't accept the tx mgmt frame */
428 	}
429 	/* Initialize the HTT tx desc l2 header offset field.
430 	 * Even though tx encap does not apply to mgmt frames,
431 	 * htt_tx_desc_mpdu_header still needs to be called,
432 	 * to specify that there was no L2 header added by tx encap,
433 	 * so the frame's length does not need to be adjusted to account for
434 	 * an added L2 header.
435 	 */
436 	htt_tx_desc_mpdu_header(tx_desc->htt_tx_desc, 0);
437 	if (qdf_unlikely(htt_tx_desc_init(
438 			pdev->htt_pdev, tx_desc->htt_tx_desc,
439 			tx_desc->htt_tx_desc_paddr,
440 			ol_tx_desc_id(pdev, tx_desc),
441 			tx_mgmt_frm,
442 			&tx_msdu_info->htt, &tx_msdu_info->tso_info, NULL, 0)))
443 		goto out;
444 	htt_tx_desc_display(tx_desc->htt_tx_desc);
445 	htt_tx_desc_set_chanfreq(tx_desc->htt_tx_desc, chanfreq);
446 
447 	ol_tx_enqueue(vdev->pdev, txq, tx_desc, tx_msdu_info);
448 	ol_tx_sched(vdev->pdev);
449 	status = 0;
450 out:
451 	if (tx_msdu_info->peer) {
452 		/* remove the peer reference added above */
453 		ol_txrx_peer_release_ref(tx_msdu_info->peer,
454 					 PEER_DEBUG_ID_OL_INTERNAL);
455 	}
456 
457 	return status;
458 }
459 
460 /**
461  * ol_tx_hl_base() - send tx frames for a HL system.
462  * @vdev: the virtual device sending the data
463  * @tx_spec: indicate what non-standard transmission actions to apply
464  * @msdu_list: the tx frames to send
465  * @tx_comp_req: tx completion req
466  * @call_sched: will schedule the tx if true
467  *
468  * Return: NULL if all MSDUs are accepted
469  */
470 static inline qdf_nbuf_t
ol_tx_hl_base(ol_txrx_vdev_handle vdev,enum ol_tx_spec tx_spec,qdf_nbuf_t msdu_list,int tx_comp_req,bool call_sched)471 ol_tx_hl_base(
472 	ol_txrx_vdev_handle vdev,
473 	enum ol_tx_spec tx_spec,
474 	qdf_nbuf_t msdu_list,
475 	int tx_comp_req,
476 	bool call_sched)
477 {
478 	struct ol_txrx_pdev_t *pdev = vdev->pdev;
479 	qdf_nbuf_t msdu = msdu_list;
480 	struct ol_txrx_msdu_info_t tx_msdu_info;
481 	struct ocb_tx_ctrl_hdr_t tx_ctrl;
482 	htt_pdev_handle htt_pdev = pdev->htt_pdev;
483 
484 	tx_msdu_info.tso_info.is_tso = 0;
485 
486 	/*
487 	 * The msdu_list variable could be used instead of the msdu var,
488 	 * but just to clarify which operations are done on a single MSDU
489 	 * vs. a list of MSDUs, use a distinct variable for single MSDUs
490 	 * within the list.
491 	 */
492 	while (msdu) {
493 		qdf_nbuf_t next;
494 		struct ol_tx_frms_queue_t *txq;
495 		struct ol_tx_desc_t *tx_desc = NULL;
496 
497 		qdf_mem_zero(&tx_ctrl, sizeof(tx_ctrl));
498 		tx_msdu_info.peer = NULL;
499 		/*
500 		 * The netbuf will get stored into a (peer-TID) tx queue list
501 		 * inside the ol_tx_classify_store function or else dropped,
502 		 * so store the next pointer immediately.
503 		 */
504 		next = qdf_nbuf_next(msdu);
505 
506 		tx_desc = ol_tx_hl_desc_alloc(pdev, vdev, msdu, &tx_msdu_info);
507 
508 		if (!tx_desc) {
509 			/*
510 			 * If we're out of tx descs, there's no need to try
511 			 * to allocate tx descs for the remaining MSDUs.
512 			 */
513 			TXRX_STATS_MSDU_LIST_INCR(pdev, tx.dropped.host_reject,
514 						  msdu);
515 			return msdu; /* the list of unaccepted MSDUs */
516 		}
517 
518 		/* OL_TXRX_PROT_AN_LOG(pdev->prot_an_tx_sent, msdu);*/
519 
520 		qdf_dp_trace_log_pkt(vdev->vdev_id, msdu, QDF_TX,
521 				     QDF_TRACE_DEFAULT_PDEV_ID,
522 				     vdev->qdf_opmode);
523 		DPTRACE(qdf_dp_trace_data_pkt(msdu, QDF_TRACE_DEFAULT_PDEV_ID,
524 					      QDF_DP_TRACE_TX_PACKET_RECORD,
525 					      tx_desc->id, QDF_TX));
526 
527 		if (tx_spec != OL_TX_SPEC_STD) {
528 #if defined(FEATURE_WLAN_TDLS)
529 			if (tx_spec & OL_TX_SPEC_NO_FREE) {
530 				tx_desc->pkt_type = OL_TX_FRM_NO_FREE;
531 			} else if (tx_spec & OL_TX_SPEC_TSO) {
532 #else
533 				if (tx_spec & OL_TX_SPEC_TSO) {
534 #endif
535 					tx_desc->pkt_type = OL_TX_FRM_TSO;
536 				}
537 				if (ol_txrx_tx_is_raw(tx_spec)) {
538 					/* CHECK THIS: does this need
539 					 * to happen after htt_tx_desc_init?
540 					 */
541 					/* different types of raw frames */
542 					u_int8_t sub_type =
543 						ol_txrx_tx_raw_subtype(
544 								tx_spec);
545 					htt_tx_desc_type(htt_pdev,
546 							 tx_desc->htt_tx_desc,
547 							 htt_pkt_type_raw,
548 							 sub_type);
549 				}
550 			}
551 
552 			tx_msdu_info.htt.info.ext_tid = qdf_nbuf_get_tid(msdu);
553 			tx_msdu_info.htt.info.vdev_id = vdev->vdev_id;
554 			tx_msdu_info.htt.info.frame_type = htt_frm_type_data;
555 			tx_msdu_info.htt.info.l2_hdr_type = pdev->htt_pkt_type;
556 
557 			if (QDF_NBUF_CB_TX_EXTRA_FRAG_FLAGS_NOTIFY_COMP(msdu)
558 									== 1) {
559 				tx_msdu_info.htt.action.tx_comp_req = 1;
560 				tx_desc->pkt_type = OL_TX_FRM_NO_FREE;
561 			} else {
562 				tx_msdu_info.htt.action.tx_comp_req =
563 								tx_comp_req;
564 			}
565 
566 			/* If the vdev is in OCB mode,
567 			 * parse the tx control header.
568 			 */
569 			if (vdev->opmode == wlan_op_mode_ocb) {
570 				if (!parse_ocb_tx_header(msdu, &tx_ctrl)) {
571 					/* There was an error parsing
572 					 * the header.Skip this packet.
573 					 */
574 					goto MSDU_LOOP_BOTTOM;
575 				}
576 			}
577 
578 			txq = ol_tx_classify(vdev, tx_desc, msdu,
579 					     &tx_msdu_info);
580 
581 			/* initialize the HW tx descriptor */
582 			htt_tx_desc_init(
583 					pdev->htt_pdev, tx_desc->htt_tx_desc,
584 					tx_desc->htt_tx_desc_paddr,
585 					ol_tx_desc_id(pdev, tx_desc),
586 					msdu,
587 					&tx_msdu_info.htt,
588 					&tx_msdu_info.tso_info,
589 					&tx_ctrl,
590 					vdev->opmode == wlan_op_mode_ocb);
591 
592 			if ((!txq) || TX_FILTER_CHECK(&tx_msdu_info)) {
593 				/* drop this frame,
594 				 * but try sending subsequent frames
595 				 */
596 				/* TXRX_STATS_MSDU_LIST_INCR(pdev,
597 				 * tx.dropped.no_txq, msdu);
598 				 */
599 				qdf_atomic_inc(&pdev->tx_queue.rsrc_cnt);
600 				ol_tx_desc_frame_free_nonstd(pdev, tx_desc, 1);
601 				if (tx_msdu_info.peer) {
602 					/* remove the peer reference
603 					 * added above
604 					 */
605 					ol_txrx_peer_release_ref(
606 						tx_msdu_info.peer,
607 						PEER_DEBUG_ID_OL_INTERNAL);
608 				}
609 				goto MSDU_LOOP_BOTTOM;
610 			}
611 
612 			if (tx_msdu_info.peer) {
613 				/*
614 				 * If the state is not associated then drop all
615 				 * the data packets received for that peer
616 				 */
617 				if (tx_msdu_info.peer->state ==
618 						OL_TXRX_PEER_STATE_DISC) {
619 					qdf_atomic_inc(
620 						&pdev->tx_queue.rsrc_cnt);
621 					ol_tx_desc_frame_free_nonstd(pdev,
622 								     tx_desc,
623 								     1);
624 					ol_txrx_peer_release_ref(
625 						tx_msdu_info.peer,
626 						PEER_DEBUG_ID_OL_INTERNAL);
627 					msdu = next;
628 					continue;
629 				} else if (tx_msdu_info.peer->state !=
630 						OL_TXRX_PEER_STATE_AUTH) {
631 					if (tx_msdu_info.htt.info.ethertype !=
632 						ETHERTYPE_PAE &&
633 						tx_msdu_info.htt.info.ethertype
634 							!= ETHERTYPE_WAI) {
635 						qdf_atomic_inc(
636 							&pdev->tx_queue.
637 								rsrc_cnt);
638 						ol_tx_desc_frame_free_nonstd(
639 								pdev,
640 								tx_desc, 1);
641 						ol_txrx_peer_release_ref(
642 						 tx_msdu_info.peer,
643 						 PEER_DEBUG_ID_OL_INTERNAL);
644 						msdu = next;
645 						continue;
646 					}
647 				}
648 			}
649 			/*
650 			 * Initialize the HTT tx desc l2 header offset field.
651 			 * htt_tx_desc_mpdu_header  needs to be called to
652 			 * make sure, the l2 header size is initialized
653 			 * correctly to handle cases where TX ENCAP is disabled
654 			 * or Tx Encap fails to perform Encap
655 			 */
656 			htt_tx_desc_mpdu_header(tx_desc->htt_tx_desc, 0);
657 
658 			/*
659 			 * Note: when the driver is built without support for
660 			 * SW tx encap,the following macro is a no-op.
661 			 * When the driver is built with support for SW tx
662 			 * encap, it performs encap, and if an error is
663 			 * encountered, jumps to the MSDU_LOOP_BOTTOM label.
664 			 */
665 			if (ol_tx_encap_wrapper(pdev, vdev, tx_desc, msdu,
666 						&tx_msdu_info))
667 				goto MSDU_LOOP_BOTTOM;
668 
669 			/*
670 			 * If debug display is enabled, show the meta-data
671 			 * being downloaded to the target via the
672 			 * HTT tx descriptor.
673 			 */
674 			htt_tx_desc_display(tx_desc->htt_tx_desc);
675 
676 			ol_tx_enqueue(pdev, txq, tx_desc, &tx_msdu_info);
677 			if (tx_msdu_info.peer) {
678 				OL_TX_PEER_STATS_UPDATE(tx_msdu_info.peer,
679 							msdu);
680 				/* remove the peer reference added above */
681 				ol_txrx_peer_release_ref
682 						(tx_msdu_info.peer,
683 						 PEER_DEBUG_ID_OL_INTERNAL);
684 			}
685 MSDU_LOOP_BOTTOM:
686 			msdu = next;
687 		}
688 
689 		if (call_sched)
690 			ol_tx_sched(pdev);
691 		return NULL; /* all MSDUs were accepted */
692 }
693 
694 #ifdef QCA_SUPPORT_TXRX_DRIVER_TCP_DEL_ACK
695 
696 /**
697  * ol_tx_pdev_reset_driver_del_ack() - reset driver delayed ack enabled flag
698  * @soc_hdl: soc handle
699  * @pdev_id: datapath pdev identifier
700  *
701  * Return: none
702  */
703 void
704 ol_tx_pdev_reset_driver_del_ack(struct cdp_soc_t *soc_hdl, uint8_t pdev_id)
705 {
706 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
707 	ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
708 	struct ol_txrx_vdev_t *vdev;
709 
710 	if (!pdev)
711 		return;
712 
713 	TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) {
714 		vdev->driver_del_ack_enabled = false;
715 
716 		dp_debug("vdev_id %d driver_del_ack_enabled %d",
717 			 vdev->vdev_id, vdev->driver_del_ack_enabled);
718 	}
719 }
720 
721 /**
722  * ol_tx_vdev_set_driver_del_ack_enable() - set driver delayed ack enabled flag
723  * @soc_hdl: datapath soc handle
724  * @vdev_id: vdev id
725  * @rx_packets: number of rx packets
726  * @time_in_ms: time in ms
727  * @high_th: high threshold
728  * @low_th: low threshold
729  *
730  * Return: none
731  */
732 void
733 ol_tx_vdev_set_driver_del_ack_enable(struct cdp_soc_t *soc_hdl,
734 				     uint8_t vdev_id,
735 				     unsigned long rx_packets,
736 				     uint32_t time_in_ms,
737 				     uint32_t high_th,
738 				     uint32_t low_th)
739 {
740 	struct ol_txrx_vdev_t *vdev =
741 			(struct ol_txrx_vdev_t *)
742 			ol_txrx_get_vdev_from_vdev_id(vdev_id);
743 	bool old_driver_del_ack_enabled;
744 
745 	if ((!vdev) || (low_th > high_th))
746 		return;
747 
748 	old_driver_del_ack_enabled = vdev->driver_del_ack_enabled;
749 	if (rx_packets > high_th)
750 		vdev->driver_del_ack_enabled = true;
751 	else if (rx_packets < low_th)
752 		vdev->driver_del_ack_enabled = false;
753 
754 	if (old_driver_del_ack_enabled != vdev->driver_del_ack_enabled) {
755 		dp_debug("vdev_id %d driver_del_ack_enabled %d rx_packets %ld time_in_ms %d high_th %d low_th %d",
756 			 vdev->vdev_id, vdev->driver_del_ack_enabled,
757 			 rx_packets, time_in_ms, high_th, low_th);
758 	}
759 }
760 
761 /**
762  * ol_tx_hl_send_all_tcp_ack() - send all queued tcp ack packets
763  * @vdev: vdev handle
764  *
765  * Return: none
766  */
767 void ol_tx_hl_send_all_tcp_ack(struct ol_txrx_vdev_t *vdev)
768 {
769 	int i;
770 	struct tcp_stream_node *tcp_node_list;
771 	struct tcp_stream_node *temp;
772 	struct ol_txrx_pdev_t *pdev = vdev->pdev;
773 
774 	for (i = 0; i < OL_TX_HL_DEL_ACK_HASH_SIZE; i++) {
775 		tcp_node_list = NULL;
776 		qdf_spin_lock_bh(&vdev->tcp_ack_hash.node[i].hash_node_lock);
777 		if (vdev->tcp_ack_hash.node[i].no_of_entries)
778 			tcp_node_list = vdev->tcp_ack_hash.node[i].head;
779 
780 		vdev->tcp_ack_hash.node[i].no_of_entries = 0;
781 		vdev->tcp_ack_hash.node[i].head = NULL;
782 		qdf_spin_unlock_bh(&vdev->tcp_ack_hash.node[i].hash_node_lock);
783 
784 		/* Send all packets */
785 		while (tcp_node_list) {
786 			int tx_comp_req = pdev->cfg.default_tx_comp_req ||
787 						pdev->cfg.request_tx_comp;
788 			qdf_nbuf_t msdu_list;
789 
790 			temp = tcp_node_list;
791 			tcp_node_list = temp->next;
792 
793 			msdu_list = ol_tx_hl_base(vdev, OL_TX_SPEC_STD,
794 						  temp->head,
795 						  tx_comp_req, false);
796 			if (msdu_list)
797 				qdf_nbuf_tx_free(msdu_list, 1/*error*/);
798 			ol_txrx_vdev_free_tcp_node(vdev, temp);
799 		}
800 	}
801 	ol_tx_sched(vdev->pdev);
802 }
803 
804 /**
805  * tcp_del_ack_tasklet() - tasklet function to send ack packets
806  * @data: vdev handle
807  *
808  * Return: none
809  */
810 void tcp_del_ack_tasklet(void *data)
811 {
812 	struct ol_txrx_vdev_t *vdev = data;
813 
814 	ol_tx_hl_send_all_tcp_ack(vdev);
815 }
816 
817 /**
818  * ol_tx_get_stream_id() - get stream_id from packet info
819  * @info: packet info
820  *
821  * Return: stream_id
822  */
823 uint16_t ol_tx_get_stream_id(struct packet_info *info)
824 {
825 	return ((info->dst_port + info->dst_ip + info->src_port + info->src_ip)
826 					 & (OL_TX_HL_DEL_ACK_HASH_SIZE - 1));
827 }
828 
829 /**
830  * ol_tx_is_tcp_ack() - check whether the packet is tcp ack frame
831  * @msdu: packet
832  *
833  * Return: true if the packet is tcp ack frame
834  */
835 static bool
836 ol_tx_is_tcp_ack(qdf_nbuf_t msdu)
837 {
838 	uint16_t ether_type;
839 	uint8_t  protocol;
840 	uint8_t  flag, ip_header_len, tcp_header_len;
841 	uint32_t seg_len;
842 	uint8_t  *skb_data;
843 	uint32_t skb_len;
844 	bool tcp_acked = false;
845 	uint32_t tcp_header_off;
846 
847 	qdf_nbuf_peek_header(msdu, &skb_data, &skb_len);
848 	if (skb_len < (QDF_NBUF_TRAC_IPV4_OFFSET +
849 	    QDF_NBUF_TRAC_IPV4_HEADER_SIZE +
850 	    QDF_NBUF_TRAC_TCP_FLAGS_OFFSET))
851 		goto exit;
852 
853 	ether_type = (uint16_t)(*(uint16_t *)
854 			(skb_data + QDF_NBUF_TRAC_ETH_TYPE_OFFSET));
855 	protocol = (uint16_t)(*(uint16_t *)
856 			(skb_data + QDF_NBUF_TRAC_IPV4_PROTO_TYPE_OFFSET));
857 
858 	if ((QDF_SWAP_U16(QDF_NBUF_TRAC_IPV4_ETH_TYPE) == ether_type) &&
859 	    (protocol == QDF_NBUF_TRAC_TCP_TYPE)) {
860 		ip_header_len = ((uint8_t)(*(uint8_t *)
861 				(skb_data + QDF_NBUF_TRAC_IPV4_OFFSET)) &
862 				QDF_NBUF_TRAC_IPV4_HEADER_MASK) << 2;
863 		tcp_header_off = QDF_NBUF_TRAC_IPV4_OFFSET + ip_header_len;
864 
865 		tcp_header_len = ((uint8_t)(*(uint8_t *)
866 			(skb_data + tcp_header_off +
867 			QDF_NBUF_TRAC_TCP_HEADER_LEN_OFFSET))) >> 2;
868 		seg_len = skb_len - tcp_header_len - tcp_header_off;
869 		flag = (uint8_t)(*(uint8_t *)
870 			(skb_data + tcp_header_off +
871 			QDF_NBUF_TRAC_TCP_FLAGS_OFFSET));
872 
873 		if ((flag == QDF_NBUF_TRAC_TCP_ACK_MASK) && (seg_len == 0))
874 			tcp_acked = true;
875 	}
876 
877 exit:
878 
879 	return tcp_acked;
880 }
881 
882 /**
883  * ol_tx_get_packet_info() - update packet info for passed msdu
884  * @msdu: packet
885  * @info: packet info
886  *
887  * Return: none
888  */
889 void ol_tx_get_packet_info(qdf_nbuf_t msdu, struct packet_info *info)
890 {
891 	uint16_t ether_type;
892 	uint8_t  protocol;
893 	uint8_t  flag, ip_header_len, tcp_header_len;
894 	uint32_t seg_len;
895 	uint8_t  *skb_data;
896 	uint32_t skb_len;
897 	uint32_t tcp_header_off;
898 
899 	info->type = NO_TCP_PKT;
900 
901 	qdf_nbuf_peek_header(msdu, &skb_data, &skb_len);
902 	if (skb_len < (QDF_NBUF_TRAC_IPV4_OFFSET +
903 	    QDF_NBUF_TRAC_IPV4_HEADER_SIZE +
904 	    QDF_NBUF_TRAC_TCP_FLAGS_OFFSET))
905 		return;
906 
907 	ether_type = (uint16_t)(*(uint16_t *)
908 			(skb_data + QDF_NBUF_TRAC_ETH_TYPE_OFFSET));
909 	protocol = (uint16_t)(*(uint16_t *)
910 			(skb_data + QDF_NBUF_TRAC_IPV4_PROTO_TYPE_OFFSET));
911 
912 	if ((QDF_SWAP_U16(QDF_NBUF_TRAC_IPV4_ETH_TYPE) == ether_type) &&
913 	    (protocol == QDF_NBUF_TRAC_TCP_TYPE)) {
914 		ip_header_len = ((uint8_t)(*(uint8_t *)
915 				(skb_data + QDF_NBUF_TRAC_IPV4_OFFSET)) &
916 				QDF_NBUF_TRAC_IPV4_HEADER_MASK) << 2;
917 		tcp_header_off = QDF_NBUF_TRAC_IPV4_OFFSET + ip_header_len;
918 
919 		tcp_header_len = ((uint8_t)(*(uint8_t *)
920 			(skb_data + tcp_header_off +
921 			QDF_NBUF_TRAC_TCP_HEADER_LEN_OFFSET))) >> 2;
922 		seg_len = skb_len - tcp_header_len - tcp_header_off;
923 		flag = (uint8_t)(*(uint8_t *)
924 			(skb_data + tcp_header_off +
925 			QDF_NBUF_TRAC_TCP_FLAGS_OFFSET));
926 
927 		info->src_ip = QDF_SWAP_U32((uint32_t)(*(uint32_t *)
928 			(skb_data + QDF_NBUF_TRAC_IPV4_SRC_ADDR_OFFSET)));
929 		info->dst_ip = QDF_SWAP_U32((uint32_t)(*(uint32_t *)
930 			(skb_data + QDF_NBUF_TRAC_IPV4_DEST_ADDR_OFFSET)));
931 		info->src_port = QDF_SWAP_U16((uint16_t)(*(uint16_t *)
932 				(skb_data + tcp_header_off +
933 				QDF_NBUF_TRAC_TCP_SPORT_OFFSET)));
934 		info->dst_port = QDF_SWAP_U16((uint16_t)(*(uint16_t *)
935 				(skb_data + tcp_header_off +
936 				QDF_NBUF_TRAC_TCP_DPORT_OFFSET)));
937 		info->stream_id = ol_tx_get_stream_id(info);
938 
939 		if ((flag == QDF_NBUF_TRAC_TCP_ACK_MASK) && (seg_len == 0)) {
940 			info->type = TCP_PKT_ACK;
941 			info->ack_number = (uint32_t)(*(uint32_t *)
942 				(skb_data + tcp_header_off +
943 				QDF_NBUF_TRAC_TCP_ACK_OFFSET));
944 			info->ack_number = QDF_SWAP_U32(info->ack_number);
945 		} else {
946 			info->type = TCP_PKT_NO_ACK;
947 		}
948 	}
949 }
950 
951 /**
952  * ol_tx_hl_find_and_send_tcp_stream() - find and send tcp stream for passed
953  *                                       stream info
954  * @vdev: vdev handle
955  * @info: packet info
956  *
957  * Return: none
958  */
959 void ol_tx_hl_find_and_send_tcp_stream(struct ol_txrx_vdev_t *vdev,
960 				       struct packet_info *info)
961 {
962 	uint8_t no_of_entries;
963 	struct tcp_stream_node *node_to_be_remove = NULL;
964 	struct ol_txrx_pdev_t *pdev = vdev->pdev;
965 
966 	/* remove tcp node from hash */
967 	qdf_spin_lock_bh(&vdev->tcp_ack_hash.node[info->stream_id].
968 			hash_node_lock);
969 
970 	no_of_entries = vdev->tcp_ack_hash.node[info->stream_id].
971 			no_of_entries;
972 	if (no_of_entries > 1) {
973 		/* collision case */
974 		struct tcp_stream_node *head =
975 			vdev->tcp_ack_hash.node[info->stream_id].head;
976 		struct tcp_stream_node *temp;
977 
978 		if ((head->dst_ip == info->dst_ip) &&
979 		    (head->src_ip == info->src_ip) &&
980 		    (head->src_port == info->src_port) &&
981 		    (head->dst_port == info->dst_port)) {
982 			node_to_be_remove = head;
983 			vdev->tcp_ack_hash.node[info->stream_id].head =
984 				head->next;
985 			vdev->tcp_ack_hash.node[info->stream_id].
986 				no_of_entries--;
987 		} else {
988 			temp = head;
989 			while (temp->next) {
990 				if ((temp->next->dst_ip == info->dst_ip) &&
991 				    (temp->next->src_ip == info->src_ip) &&
992 				    (temp->next->src_port == info->src_port) &&
993 				    (temp->next->dst_port == info->dst_port)) {
994 					node_to_be_remove = temp->next;
995 					temp->next = temp->next->next;
996 					vdev->tcp_ack_hash.
997 						node[info->stream_id].
998 						no_of_entries--;
999 					break;
1000 				}
1001 				temp = temp->next;
1002 			}
1003 		}
1004 	} else if (no_of_entries == 1) {
1005 		/* Only one tcp_node */
1006 		node_to_be_remove =
1007 			 vdev->tcp_ack_hash.node[info->stream_id].head;
1008 		vdev->tcp_ack_hash.node[info->stream_id].head = NULL;
1009 		vdev->tcp_ack_hash.node[info->stream_id].no_of_entries = 0;
1010 	}
1011 	qdf_spin_unlock_bh(&vdev->tcp_ack_hash.
1012 			  node[info->stream_id].hash_node_lock);
1013 
1014 	/* send packets */
1015 	if (node_to_be_remove) {
1016 		int tx_comp_req = pdev->cfg.default_tx_comp_req ||
1017 					pdev->cfg.request_tx_comp;
1018 		qdf_nbuf_t msdu_list;
1019 
1020 		msdu_list = ol_tx_hl_base(vdev, OL_TX_SPEC_STD,
1021 					  node_to_be_remove->head,
1022 					  tx_comp_req, true);
1023 		if (msdu_list)
1024 			qdf_nbuf_tx_free(msdu_list, 1/*error*/);
1025 		ol_txrx_vdev_free_tcp_node(vdev, node_to_be_remove);
1026 	}
1027 }
1028 
1029 static struct tcp_stream_node *
1030 ol_tx_hl_rep_tcp_ack(struct ol_txrx_vdev_t *vdev, qdf_nbuf_t msdu,
1031 		     struct packet_info *info, bool *is_found,
1032 		     bool *start_timer)
1033 {
1034 	struct tcp_stream_node *node_to_be_remove = NULL;
1035 	struct tcp_stream_node *head =
1036 		 vdev->tcp_ack_hash.node[info->stream_id].head;
1037 	struct tcp_stream_node *temp;
1038 
1039 	if ((head->dst_ip == info->dst_ip) &&
1040 	    (head->src_ip == info->src_ip) &&
1041 	    (head->src_port == info->src_port) &&
1042 	    (head->dst_port == info->dst_port)) {
1043 		*is_found = true;
1044 		if ((head->ack_number < info->ack_number) &&
1045 		    (head->no_of_ack_replaced <
1046 		    ol_cfg_get_del_ack_count_value(vdev->pdev->ctrl_pdev))) {
1047 			/* replace ack packet */
1048 			qdf_nbuf_tx_free(head->head, 1);
1049 			head->head = msdu;
1050 			head->ack_number = info->ack_number;
1051 			head->no_of_ack_replaced++;
1052 			*start_timer = true;
1053 
1054 			vdev->no_of_tcpack_replaced++;
1055 
1056 			if (head->no_of_ack_replaced ==
1057 			    ol_cfg_get_del_ack_count_value(
1058 			    vdev->pdev->ctrl_pdev)) {
1059 				node_to_be_remove = head;
1060 				vdev->tcp_ack_hash.node[info->stream_id].head =
1061 					head->next;
1062 				vdev->tcp_ack_hash.node[info->stream_id].
1063 					no_of_entries--;
1064 			}
1065 		} else {
1066 			/* append and send packets */
1067 			head->head->next = msdu;
1068 			node_to_be_remove = head;
1069 			vdev->tcp_ack_hash.node[info->stream_id].head =
1070 				head->next;
1071 			vdev->tcp_ack_hash.node[info->stream_id].
1072 				no_of_entries--;
1073 		}
1074 	} else {
1075 		temp = head;
1076 		while (temp->next) {
1077 			if ((temp->next->dst_ip == info->dst_ip) &&
1078 			    (temp->next->src_ip == info->src_ip) &&
1079 			    (temp->next->src_port == info->src_port) &&
1080 			    (temp->next->dst_port == info->dst_port)) {
1081 				*is_found = true;
1082 				if ((temp->next->ack_number <
1083 					info->ack_number) &&
1084 				    (temp->next->no_of_ack_replaced <
1085 					 ol_cfg_get_del_ack_count_value(
1086 					 vdev->pdev->ctrl_pdev))) {
1087 					/* replace ack packet */
1088 					qdf_nbuf_tx_free(temp->next->head, 1);
1089 					temp->next->head  = msdu;
1090 					temp->next->ack_number =
1091 						info->ack_number;
1092 					temp->next->no_of_ack_replaced++;
1093 					*start_timer = true;
1094 
1095 					vdev->no_of_tcpack_replaced++;
1096 
1097 					if (temp->next->no_of_ack_replaced ==
1098 					   ol_cfg_get_del_ack_count_value(
1099 					   vdev->pdev->ctrl_pdev)) {
1100 						node_to_be_remove = temp->next;
1101 						temp->next = temp->next->next;
1102 						vdev->tcp_ack_hash.
1103 							node[info->stream_id].
1104 							no_of_entries--;
1105 					}
1106 				} else {
1107 					/* append and send packets */
1108 					temp->next->head->next = msdu;
1109 					node_to_be_remove = temp->next;
1110 					temp->next = temp->next->next;
1111 					vdev->tcp_ack_hash.
1112 						node[info->stream_id].
1113 						no_of_entries--;
1114 				}
1115 				break;
1116 			}
1117 			temp = temp->next;
1118 		}
1119 	}
1120 	return node_to_be_remove;
1121 }
1122 
1123 /**
1124  * ol_tx_hl_find_and_replace_tcp_ack() - find and replace tcp ack packet for
1125  *                                       passed packet info
1126  * @vdev: vdev handle
1127  * @msdu: packet
1128  * @info: packet info
1129  *
1130  * Return: none
1131  */
1132 void ol_tx_hl_find_and_replace_tcp_ack(struct ol_txrx_vdev_t *vdev,
1133 				       qdf_nbuf_t msdu,
1134 				       struct packet_info *info)
1135 {
1136 	uint8_t no_of_entries;
1137 	struct tcp_stream_node *node_to_be_remove = NULL;
1138 	bool is_found = false, start_timer = false;
1139 	struct ol_txrx_pdev_t *pdev = vdev->pdev;
1140 
1141 	/* replace ack if required or send packets */
1142 	qdf_spin_lock_bh(&vdev->tcp_ack_hash.node[info->stream_id].
1143 			hash_node_lock);
1144 
1145 	no_of_entries = vdev->tcp_ack_hash.node[info->stream_id].no_of_entries;
1146 	if (no_of_entries > 0) {
1147 		node_to_be_remove = ol_tx_hl_rep_tcp_ack(vdev, msdu, info,
1148 							 &is_found,
1149 							 &start_timer);
1150 	}
1151 
1152 	if (no_of_entries == 0 || !is_found) {
1153 		/* Alloc new tcp node */
1154 		struct tcp_stream_node *new_node;
1155 
1156 		new_node = ol_txrx_vdev_alloc_tcp_node(vdev);
1157 		if (!new_node) {
1158 			qdf_spin_unlock_bh(&vdev->tcp_ack_hash.
1159 					  node[info->stream_id].hash_node_lock);
1160 			dp_alert("Malloc failed");
1161 			return;
1162 		}
1163 		new_node->stream_id = info->stream_id;
1164 		new_node->dst_ip = info->dst_ip;
1165 		new_node->src_ip = info->src_ip;
1166 		new_node->dst_port = info->dst_port;
1167 		new_node->src_port = info->src_port;
1168 		new_node->ack_number = info->ack_number;
1169 		new_node->head = msdu;
1170 		new_node->next = NULL;
1171 		new_node->no_of_ack_replaced = 0;
1172 
1173 		start_timer = true;
1174 		/* insert new_node */
1175 		if (!vdev->tcp_ack_hash.node[info->stream_id].head) {
1176 			vdev->tcp_ack_hash.node[info->stream_id].head =
1177 				new_node;
1178 			vdev->tcp_ack_hash.node[info->stream_id].
1179 				no_of_entries = 1;
1180 		} else {
1181 			struct tcp_stream_node *temp =
1182 				 vdev->tcp_ack_hash.node[info->stream_id].head;
1183 			while (temp->next)
1184 				temp = temp->next;
1185 
1186 			temp->next = new_node;
1187 			vdev->tcp_ack_hash.node[info->stream_id].
1188 				no_of_entries++;
1189 		}
1190 	}
1191 	qdf_spin_unlock_bh(&vdev->tcp_ack_hash.node[info->stream_id].
1192 			  hash_node_lock);
1193 
1194 	/* start timer */
1195 	if (start_timer &&
1196 	    (!qdf_atomic_read(&vdev->tcp_ack_hash.is_timer_running))) {
1197 		qdf_hrtimer_start(&vdev->tcp_ack_hash.timer,
1198 				  qdf_ns_to_ktime((
1199 						ol_cfg_get_del_ack_timer_value(
1200 						vdev->pdev->ctrl_pdev) *
1201 						1000000)),
1202 			__QDF_HRTIMER_MODE_REL);
1203 		qdf_atomic_set(&vdev->tcp_ack_hash.is_timer_running, 1);
1204 	}
1205 
1206 	/* send packets */
1207 	if (node_to_be_remove) {
1208 		int tx_comp_req = pdev->cfg.default_tx_comp_req ||
1209 					pdev->cfg.request_tx_comp;
1210 		qdf_nbuf_t msdu_list = NULL;
1211 
1212 		msdu_list = ol_tx_hl_base(vdev, OL_TX_SPEC_STD,
1213 					  node_to_be_remove->head,
1214 					  tx_comp_req, true);
1215 		if (msdu_list)
1216 			qdf_nbuf_tx_free(msdu_list, 1/*error*/);
1217 		ol_txrx_vdev_free_tcp_node(vdev, node_to_be_remove);
1218 	}
1219 }
1220 
1221 /**
1222  * ol_tx_hl_vdev_tcp_del_ack_timer() - delayed ack timer function
1223  * @timer: timer handle
1224  *
1225  * Return: enum
1226  */
1227 enum qdf_hrtimer_restart_status
1228 ol_tx_hl_vdev_tcp_del_ack_timer(qdf_hrtimer_data_t *timer)
1229 {
1230 	struct ol_txrx_vdev_t *vdev = qdf_container_of(timer,
1231 						       struct ol_txrx_vdev_t,
1232 						       tcp_ack_hash.timer);
1233 	enum qdf_hrtimer_restart_status ret = QDF_HRTIMER_NORESTART;
1234 
1235 	qdf_sched_bh(&vdev->tcp_ack_hash.tcp_del_ack_tq);
1236 	qdf_atomic_set(&vdev->tcp_ack_hash.is_timer_running, 0);
1237 	return ret;
1238 }
1239 
1240 /**
1241  * ol_tx_hl_del_ack_queue_flush_all() - drop all queued packets
1242  * @vdev: vdev handle
1243  *
1244  * Return: none
1245  */
1246 void ol_tx_hl_del_ack_queue_flush_all(struct ol_txrx_vdev_t *vdev)
1247 {
1248 	int i;
1249 	struct tcp_stream_node *tcp_node_list;
1250 	struct tcp_stream_node *temp;
1251 
1252 	qdf_hrtimer_cancel(&vdev->tcp_ack_hash.timer);
1253 	for (i = 0; i < OL_TX_HL_DEL_ACK_HASH_SIZE; i++) {
1254 		tcp_node_list = NULL;
1255 		qdf_spin_lock_bh(&vdev->tcp_ack_hash.node[i].hash_node_lock);
1256 
1257 		if (vdev->tcp_ack_hash.node[i].no_of_entries)
1258 			tcp_node_list = vdev->tcp_ack_hash.node[i].head;
1259 
1260 		vdev->tcp_ack_hash.node[i].no_of_entries = 0;
1261 		vdev->tcp_ack_hash.node[i].head = NULL;
1262 		qdf_spin_unlock_bh(&vdev->tcp_ack_hash.node[i].hash_node_lock);
1263 
1264 		/* free all packets */
1265 		while (tcp_node_list) {
1266 			temp = tcp_node_list;
1267 			tcp_node_list = temp->next;
1268 
1269 			qdf_nbuf_tx_free(temp->head, 1/*error*/);
1270 			ol_txrx_vdev_free_tcp_node(vdev, temp);
1271 		}
1272 	}
1273 	ol_txrx_vdev_deinit_tcp_del_ack(vdev);
1274 }
1275 
1276 /**
1277  * ol_txrx_vdev_init_tcp_del_ack() - initialize tcp delayed ack structure
1278  * @vdev: vdev handle
1279  *
1280  * Return: none
1281  */
1282 void ol_txrx_vdev_init_tcp_del_ack(struct ol_txrx_vdev_t *vdev)
1283 {
1284 	int i;
1285 
1286 	vdev->driver_del_ack_enabled = false;
1287 
1288 	dp_debug("vdev-id=%u, driver_del_ack_enabled=%d",
1289 		 vdev->vdev_id,
1290 		 vdev->driver_del_ack_enabled);
1291 
1292 	vdev->no_of_tcpack = 0;
1293 	vdev->no_of_tcpack_replaced = 0;
1294 
1295 	qdf_hrtimer_init(&vdev->tcp_ack_hash.timer,
1296 			 ol_tx_hl_vdev_tcp_del_ack_timer,
1297 			 __QDF_CLOCK_MONOTONIC,
1298 			 __QDF_HRTIMER_MODE_REL,
1299 			 QDF_CONTEXT_HARDWARE
1300 			 );
1301 	qdf_create_bh(&vdev->tcp_ack_hash.tcp_del_ack_tq,
1302 		      tcp_del_ack_tasklet,
1303 		      vdev);
1304 	qdf_atomic_init(&vdev->tcp_ack_hash.is_timer_running);
1305 	qdf_atomic_init(&vdev->tcp_ack_hash.tcp_node_in_use_count);
1306 	qdf_spinlock_create(&vdev->tcp_ack_hash.tcp_free_list_lock);
1307 	vdev->tcp_ack_hash.tcp_free_list = NULL;
1308 	for (i = 0; i < OL_TX_HL_DEL_ACK_HASH_SIZE; i++) {
1309 		qdf_spinlock_create(&vdev->tcp_ack_hash.node[i].hash_node_lock);
1310 		vdev->tcp_ack_hash.node[i].no_of_entries = 0;
1311 		vdev->tcp_ack_hash.node[i].head = NULL;
1312 	}
1313 }
1314 
1315 /**
1316  * ol_txrx_vdev_deinit_tcp_del_ack() - deinitialize tcp delayed ack structure
1317  * @vdev: vdev handle
1318  *
1319  * Return: none
1320  */
1321 void ol_txrx_vdev_deinit_tcp_del_ack(struct ol_txrx_vdev_t *vdev)
1322 {
1323 	struct tcp_stream_node *temp;
1324 
1325 	qdf_destroy_bh(&vdev->tcp_ack_hash.tcp_del_ack_tq);
1326 
1327 	qdf_spin_lock_bh(&vdev->tcp_ack_hash.tcp_free_list_lock);
1328 	while (vdev->tcp_ack_hash.tcp_free_list) {
1329 		temp = vdev->tcp_ack_hash.tcp_free_list;
1330 		vdev->tcp_ack_hash.tcp_free_list = temp->next;
1331 		qdf_mem_free(temp);
1332 	}
1333 	qdf_spin_unlock_bh(&vdev->tcp_ack_hash.tcp_free_list_lock);
1334 }
1335 
1336 /**
1337  * ol_txrx_vdev_free_tcp_node() - add tcp node in free list
1338  * @vdev: vdev handle
1339  * @node: tcp stream node
1340  *
1341  * Return: none
1342  */
1343 void ol_txrx_vdev_free_tcp_node(struct ol_txrx_vdev_t *vdev,
1344 				struct tcp_stream_node *node)
1345 {
1346 	qdf_atomic_dec(&vdev->tcp_ack_hash.tcp_node_in_use_count);
1347 
1348 	qdf_spin_lock_bh(&vdev->tcp_ack_hash.tcp_free_list_lock);
1349 	if (vdev->tcp_ack_hash.tcp_free_list) {
1350 		node->next = vdev->tcp_ack_hash.tcp_free_list;
1351 		vdev->tcp_ack_hash.tcp_free_list = node;
1352 	} else {
1353 		vdev->tcp_ack_hash.tcp_free_list = node;
1354 		node->next = NULL;
1355 	}
1356 	qdf_spin_unlock_bh(&vdev->tcp_ack_hash.tcp_free_list_lock);
1357 }
1358 
1359 /**
1360  * ol_txrx_vdev_alloc_tcp_node() - allocate tcp node
1361  * @vdev: vdev handle
1362  *
1363  * Return: tcp stream node
1364  */
1365 struct tcp_stream_node *ol_txrx_vdev_alloc_tcp_node(struct ol_txrx_vdev_t *vdev)
1366 {
1367 	struct tcp_stream_node *node = NULL;
1368 
1369 	qdf_spin_lock_bh(&vdev->tcp_ack_hash.tcp_free_list_lock);
1370 	if (vdev->tcp_ack_hash.tcp_free_list) {
1371 		node = vdev->tcp_ack_hash.tcp_free_list;
1372 		vdev->tcp_ack_hash.tcp_free_list = node->next;
1373 	}
1374 	qdf_spin_unlock_bh(&vdev->tcp_ack_hash.tcp_free_list_lock);
1375 
1376 	if (!node) {
1377 		node = qdf_mem_malloc(sizeof(struct ol_txrx_vdev_t));
1378 		if (!node)
1379 			return NULL;
1380 	}
1381 	qdf_atomic_inc(&vdev->tcp_ack_hash.tcp_node_in_use_count);
1382 	return node;
1383 }
1384 
1385 qdf_nbuf_t
1386 ol_tx_hl(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list)
1387 {
1388 	struct ol_txrx_pdev_t *pdev = vdev->pdev;
1389 	int tx_comp_req = pdev->cfg.default_tx_comp_req ||
1390 				pdev->cfg.request_tx_comp;
1391 	struct packet_info pkt_info;
1392 	qdf_nbuf_t temp;
1393 
1394 	if (ol_tx_is_tcp_ack(msdu_list))
1395 		vdev->no_of_tcpack++;
1396 
1397 	/* check Enable through ini */
1398 	if (!ol_cfg_get_del_ack_enable_value(vdev->pdev->ctrl_pdev) ||
1399 	    (!vdev->driver_del_ack_enabled)) {
1400 		if (qdf_atomic_read(&vdev->tcp_ack_hash.tcp_node_in_use_count))
1401 			ol_tx_hl_send_all_tcp_ack(vdev);
1402 
1403 		return ol_tx_hl_base(vdev, OL_TX_SPEC_STD, msdu_list,
1404 				    tx_comp_req, true);
1405 	}
1406 
1407 	ol_tx_get_packet_info(msdu_list, &pkt_info);
1408 
1409 	if (pkt_info.type == TCP_PKT_NO_ACK) {
1410 		ol_tx_hl_find_and_send_tcp_stream(vdev, &pkt_info);
1411 		temp = ol_tx_hl_base(vdev, OL_TX_SPEC_STD, msdu_list,
1412 				     tx_comp_req, true);
1413 		return temp;
1414 	}
1415 
1416 	if (pkt_info.type == TCP_PKT_ACK) {
1417 		ol_tx_hl_find_and_replace_tcp_ack(vdev, msdu_list, &pkt_info);
1418 		return NULL;
1419 	}
1420 
1421 	temp = ol_tx_hl_base(vdev, OL_TX_SPEC_STD, msdu_list,
1422 			     tx_comp_req, true);
1423 	return temp;
1424 }
1425 #else
1426 
1427 #ifdef WLAN_SUPPORT_TXRX_HL_BUNDLE
1428 void
1429 ol_tx_pdev_reset_bundle_require(struct cdp_soc_t *soc_hdl, uint8_t pdev_id)
1430 {
1431 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
1432 	struct ol_txrx_pdev_t *pdev = ol_txrx_get_pdev_from_pdev_id(soc,
1433 								    pdev_id);
1434 	struct ol_txrx_vdev_t *vdev;
1435 
1436 	TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) {
1437 		vdev->bundling_required = false;
1438 		ol_txrx_info("vdev_id %d bundle_require %d",
1439 			     vdev->vdev_id, vdev->bundling_required);
1440 	}
1441 }
1442 
1443 void
1444 ol_tx_vdev_set_bundle_require(uint8_t vdev_id, unsigned long tx_bytes,
1445 			      uint32_t time_in_ms, uint32_t high_th,
1446 			      uint32_t low_th)
1447 {
1448 	struct ol_txrx_vdev_t *vdev = (struct ol_txrx_vdev_t *)
1449 				ol_txrx_get_vdev_from_vdev_id(vdev_id);
1450 	bool old_bundle_required;
1451 
1452 	if ((!vdev) || (low_th > high_th))
1453 		return;
1454 
1455 	old_bundle_required = vdev->bundling_required;
1456 	if (tx_bytes > ((high_th * time_in_ms * 1500) / 1000))
1457 		vdev->bundling_required = true;
1458 	else if (tx_bytes < ((low_th * time_in_ms * 1500) / 1000))
1459 		vdev->bundling_required = false;
1460 
1461 	if (old_bundle_required != vdev->bundling_required)
1462 		ol_txrx_info("vdev_id %d bundle_require %d tx_bytes %ld time_in_ms %d high_th %d low_th %d",
1463 			     vdev->vdev_id, vdev->bundling_required, tx_bytes,
1464 			     time_in_ms, high_th, low_th);
1465 }
1466 
1467 /**
1468  * ol_tx_hl_queue_flush_all() - drop all packets in vdev bundle queue
1469  * @vdev: vdev handle
1470  *
1471  * Return: none
1472  */
1473 void
1474 ol_tx_hl_queue_flush_all(struct ol_txrx_vdev_t *vdev)
1475 {
1476 	qdf_spin_lock_bh(&vdev->bundle_queue.mutex);
1477 	if (vdev->bundle_queue.txq.depth != 0) {
1478 		qdf_timer_stop(&vdev->bundle_queue.timer);
1479 		vdev->pdev->total_bundle_queue_length -=
1480 				vdev->bundle_queue.txq.depth;
1481 		qdf_nbuf_tx_free(vdev->bundle_queue.txq.head, 1/*error*/);
1482 		vdev->bundle_queue.txq.depth = 0;
1483 		vdev->bundle_queue.txq.head = NULL;
1484 		vdev->bundle_queue.txq.tail = NULL;
1485 	}
1486 	qdf_spin_unlock_bh(&vdev->bundle_queue.mutex);
1487 }
1488 
1489 /**
1490  * ol_tx_hl_vdev_queue_append() - append pkt in tx queue
1491  * @vdev: vdev handle
1492  * @msdu_list: msdu list
1493  *
1494  * Return: none
1495  */
1496 static void
1497 ol_tx_hl_vdev_queue_append(struct ol_txrx_vdev_t *vdev, qdf_nbuf_t msdu_list)
1498 {
1499 	qdf_spin_lock_bh(&vdev->bundle_queue.mutex);
1500 
1501 	if (!vdev->bundle_queue.txq.head) {
1502 		qdf_timer_start(
1503 			&vdev->bundle_queue.timer,
1504 			ol_cfg_get_bundle_timer_value(vdev->pdev->ctrl_pdev));
1505 		vdev->bundle_queue.txq.head = msdu_list;
1506 		vdev->bundle_queue.txq.tail = msdu_list;
1507 	} else {
1508 		qdf_nbuf_set_next(vdev->bundle_queue.txq.tail, msdu_list);
1509 	}
1510 
1511 	while (qdf_nbuf_next(msdu_list)) {
1512 		vdev->bundle_queue.txq.depth++;
1513 		vdev->pdev->total_bundle_queue_length++;
1514 		msdu_list = qdf_nbuf_next(msdu_list);
1515 	}
1516 
1517 	vdev->bundle_queue.txq.depth++;
1518 	vdev->pdev->total_bundle_queue_length++;
1519 	vdev->bundle_queue.txq.tail = msdu_list;
1520 	qdf_spin_unlock_bh(&vdev->bundle_queue.mutex);
1521 }
1522 
1523 /**
1524  * ol_tx_hl_vdev_queue_send_all() - send all packets in vdev bundle queue
1525  * @vdev: vdev handle
1526  * @call_sched: invoke scheduler
1527  *
1528  * Return: NULL for success
1529  */
1530 static qdf_nbuf_t
1531 ol_tx_hl_vdev_queue_send_all(struct ol_txrx_vdev_t *vdev, bool call_sched,
1532 			     bool in_timer_context)
1533 {
1534 	qdf_nbuf_t msdu_list = NULL;
1535 	qdf_nbuf_t skb_list_head, skb_list_tail;
1536 	struct ol_txrx_pdev_t *pdev = vdev->pdev;
1537 	int tx_comp_req = pdev->cfg.default_tx_comp_req ||
1538 				pdev->cfg.request_tx_comp;
1539 	int pkt_to_sent;
1540 
1541 	qdf_spin_lock_bh(&vdev->bundle_queue.mutex);
1542 
1543 	if (!vdev->bundle_queue.txq.depth) {
1544 		qdf_spin_unlock_bh(&vdev->bundle_queue.mutex);
1545 		return msdu_list;
1546 	}
1547 
1548 	if (likely((qdf_atomic_read(&vdev->tx_desc_count) +
1549 		    vdev->bundle_queue.txq.depth) <
1550 		    vdev->queue_stop_th)) {
1551 		qdf_timer_stop(&vdev->bundle_queue.timer);
1552 		vdev->pdev->total_bundle_queue_length -=
1553 				vdev->bundle_queue.txq.depth;
1554 		msdu_list = ol_tx_hl_base(vdev, OL_TX_SPEC_STD,
1555 					  vdev->bundle_queue.txq.head,
1556 					  tx_comp_req, call_sched);
1557 		vdev->bundle_queue.txq.depth = 0;
1558 		vdev->bundle_queue.txq.head = NULL;
1559 		vdev->bundle_queue.txq.tail = NULL;
1560 	} else {
1561 		pkt_to_sent = vdev->queue_stop_th -
1562 			qdf_atomic_read(&vdev->tx_desc_count);
1563 
1564 		if (pkt_to_sent) {
1565 			skb_list_head = vdev->bundle_queue.txq.head;
1566 
1567 			while (pkt_to_sent) {
1568 				skb_list_tail =
1569 					vdev->bundle_queue.txq.head;
1570 				vdev->bundle_queue.txq.head =
1571 				    qdf_nbuf_next(vdev->bundle_queue.txq.head);
1572 				vdev->pdev->total_bundle_queue_length--;
1573 				vdev->bundle_queue.txq.depth--;
1574 				pkt_to_sent--;
1575 				if (!vdev->bundle_queue.txq.head) {
1576 					qdf_timer_stop(
1577 						&vdev->bundle_queue.timer);
1578 					break;
1579 				}
1580 			}
1581 
1582 			qdf_nbuf_set_next(skb_list_tail, NULL);
1583 			msdu_list = ol_tx_hl_base(vdev, OL_TX_SPEC_STD,
1584 						  skb_list_head, tx_comp_req,
1585 						  call_sched);
1586 		}
1587 
1588 		if (in_timer_context &&	vdev->bundle_queue.txq.head) {
1589 			qdf_timer_start(
1590 				&vdev->bundle_queue.timer,
1591 				ol_cfg_get_bundle_timer_value(
1592 					vdev->pdev->ctrl_pdev));
1593 		}
1594 	}
1595 	qdf_spin_unlock_bh(&vdev->bundle_queue.mutex);
1596 
1597 	return msdu_list;
1598 }
1599 
1600 /**
1601  * ol_tx_hl_pdev_queue_send_all() - send all packets from all vdev bundle queue
1602  * @pdev: pdev handle
1603  *
1604  * Return: NULL for success
1605  */
1606 qdf_nbuf_t
1607 ol_tx_hl_pdev_queue_send_all(struct ol_txrx_pdev_t *pdev)
1608 {
1609 	struct ol_txrx_vdev_t *vdev;
1610 	qdf_nbuf_t msdu_list;
1611 
1612 	TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) {
1613 		msdu_list = ol_tx_hl_vdev_queue_send_all(vdev, false, false);
1614 		if (msdu_list)
1615 			qdf_nbuf_tx_free(msdu_list, 1/*error*/);
1616 	}
1617 	ol_tx_sched(pdev);
1618 	return NULL; /* all msdus were accepted */
1619 }
1620 
1621 /**
1622  * ol_tx_hl_vdev_bundle_timer() - bundle timer function
1623  * @vdev: vdev handle
1624  *
1625  * Return: none
1626  */
1627 void
1628 ol_tx_hl_vdev_bundle_timer(void *ctx)
1629 {
1630 	qdf_nbuf_t msdu_list;
1631 	struct ol_txrx_vdev_t *vdev = (struct ol_txrx_vdev_t *)ctx;
1632 
1633 	vdev->no_of_bundle_sent_in_timer++;
1634 	msdu_list = ol_tx_hl_vdev_queue_send_all(vdev, true, true);
1635 	if (msdu_list)
1636 		qdf_nbuf_tx_free(msdu_list, 1/*error*/);
1637 }
1638 
1639 qdf_nbuf_t
1640 ol_tx_hl(struct ol_txrx_vdev_t *vdev, qdf_nbuf_t msdu_list)
1641 {
1642 	struct ol_txrx_pdev_t *pdev = vdev->pdev;
1643 	int tx_comp_req = pdev->cfg.default_tx_comp_req ||
1644 				pdev->cfg.request_tx_comp;
1645 
1646 	/* No queuing for high priority packets */
1647 	if (ol_tx_desc_is_high_prio(msdu_list)) {
1648 		vdev->no_of_pkt_not_added_in_queue++;
1649 		return ol_tx_hl_base(vdev, OL_TX_SPEC_STD, msdu_list,
1650 					     tx_comp_req, true);
1651 	} else if (vdev->bundling_required &&
1652 	    (ol_cfg_get_bundle_size(vdev->pdev->ctrl_pdev) > 1)) {
1653 		ol_tx_hl_vdev_queue_append(vdev, msdu_list);
1654 
1655 		if (pdev->total_bundle_queue_length >=
1656 		    ol_cfg_get_bundle_size(vdev->pdev->ctrl_pdev)) {
1657 			vdev->no_of_bundle_sent_after_threshold++;
1658 			return ol_tx_hl_pdev_queue_send_all(pdev);
1659 		}
1660 	} else {
1661 		if (vdev->bundle_queue.txq.depth != 0) {
1662 			ol_tx_hl_vdev_queue_append(vdev, msdu_list);
1663 			return ol_tx_hl_vdev_queue_send_all(vdev, true, false);
1664 		} else {
1665 			vdev->no_of_pkt_not_added_in_queue++;
1666 			return ol_tx_hl_base(vdev, OL_TX_SPEC_STD, msdu_list,
1667 					     tx_comp_req, true);
1668 		}
1669 	}
1670 
1671 	return NULL; /* all msdus were accepted */
1672 }
1673 
1674 #else
1675 
1676 qdf_nbuf_t
1677 ol_tx_hl(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list)
1678 {
1679 	struct ol_txrx_pdev_t *pdev = vdev->pdev;
1680 	int tx_comp_req = pdev->cfg.default_tx_comp_req ||
1681 				pdev->cfg.request_tx_comp;
1682 
1683 	return ol_tx_hl_base(vdev, OL_TX_SPEC_STD,
1684 			     msdu_list, tx_comp_req, true);
1685 }
1686 #endif
1687 #endif
1688 
1689 qdf_nbuf_t ol_tx_non_std_hl(struct ol_txrx_vdev_t *vdev,
1690 			    enum ol_tx_spec tx_spec,
1691 			    qdf_nbuf_t msdu_list)
1692 {
1693 	struct ol_txrx_pdev_t *pdev = vdev->pdev;
1694 	int tx_comp_req = pdev->cfg.default_tx_comp_req ||
1695 				pdev->cfg.request_tx_comp;
1696 
1697 	if (!tx_comp_req) {
1698 		if ((tx_spec == OL_TX_SPEC_NO_FREE) &&
1699 		    (pdev->tx_data_callback.func))
1700 			tx_comp_req = 1;
1701 	}
1702 	return ol_tx_hl_base(vdev, tx_spec, msdu_list, tx_comp_req, true);
1703 }
1704 
1705 #ifdef FEATURE_WLAN_TDLS
1706 void ol_txrx_copy_mac_addr_raw(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
1707 			       uint8_t *bss_addr)
1708 {
1709 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
1710 	ol_txrx_vdev_handle vdev = ol_txrx_get_vdev_from_soc_vdev_id(soc,
1711 								     vdev_id);
1712 
1713 	if (!vdev)
1714 		return;
1715 
1716 	qdf_spin_lock_bh(&vdev->pdev->last_real_peer_mutex);
1717 	if (bss_addr && vdev->last_real_peer &&
1718 	    !qdf_mem_cmp((u8 *)bss_addr,
1719 			     vdev->last_real_peer->mac_addr.raw,
1720 			     QDF_MAC_ADDR_SIZE))
1721 		qdf_mem_copy(vdev->hl_tdls_ap_mac_addr.raw,
1722 			     vdev->last_real_peer->mac_addr.raw,
1723 			     QDF_MAC_ADDR_SIZE);
1724 	qdf_spin_unlock_bh(&vdev->pdev->last_real_peer_mutex);
1725 }
1726 
1727 void
1728 ol_txrx_add_last_real_peer(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
1729 			   uint8_t vdev_id)
1730 {
1731 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
1732 	ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
1733 	ol_txrx_vdev_handle vdev = ol_txrx_get_vdev_from_soc_vdev_id(soc,
1734 								     vdev_id);
1735 	ol_txrx_peer_handle peer;
1736 
1737 	if (!pdev || !vdev)
1738 		return;
1739 
1740 	peer = ol_txrx_find_peer_by_addr(
1741 		(struct cdp_pdev *)pdev,
1742 		vdev->hl_tdls_ap_mac_addr.raw);
1743 
1744 	qdf_spin_lock_bh(&pdev->last_real_peer_mutex);
1745 	if (!vdev->last_real_peer && peer &&
1746 	    (peer->peer_ids[0] != HTT_INVALID_PEER_ID)) {
1747 		vdev->last_real_peer = peer;
1748 		qdf_mem_zero(vdev->hl_tdls_ap_mac_addr.raw,
1749 			     QDF_MAC_ADDR_SIZE);
1750 	}
1751 	qdf_spin_unlock_bh(&pdev->last_real_peer_mutex);
1752 }
1753 
1754 bool is_vdev_restore_last_peer(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
1755 			       uint8_t *peer_mac)
1756 {
1757 	struct ol_txrx_peer_t *peer;
1758 	struct ol_txrx_pdev_t *pdev;
1759 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
1760 	ol_txrx_vdev_handle vdev = ol_txrx_get_vdev_from_soc_vdev_id(soc,
1761 								     vdev_id);
1762 
1763 	if (!vdev)
1764 		return false;
1765 
1766 	pdev = vdev->pdev;
1767 	peer = ol_txrx_find_peer_by_addr((struct cdp_pdev *)pdev, peer_mac);
1768 
1769 	return vdev->last_real_peer && (vdev->last_real_peer == peer);
1770 }
1771 
1772 void ol_txrx_update_last_real_peer(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
1773 				   uint8_t vdev_id, bool restore_last_peer)
1774 {
1775 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
1776 	ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
1777 	ol_txrx_vdev_handle vdev = ol_txrx_get_vdev_from_soc_vdev_id(soc,
1778 								     vdev_id);
1779 	struct ol_txrx_peer_t *peer;
1780 
1781 	if (!restore_last_peer || !pdev || !vdev)
1782 		return;
1783 
1784 	peer = ol_txrx_find_peer_by_addr((struct cdp_pdev *)pdev,
1785 					 vdev->hl_tdls_ap_mac_addr.raw);
1786 
1787 	qdf_spin_lock_bh(&pdev->last_real_peer_mutex);
1788 	if (!vdev->last_real_peer && peer &&
1789 	    (peer->peer_ids[0] != HTT_INVALID_PEER_ID)) {
1790 		vdev->last_real_peer = peer;
1791 		qdf_mem_zero(vdev->hl_tdls_ap_mac_addr.raw,
1792 			     QDF_MAC_ADDR_SIZE);
1793 	}
1794 	qdf_spin_unlock_bh(&pdev->last_real_peer_mutex);
1795 }
1796 
1797 void ol_txrx_set_peer_as_tdls_peer(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
1798 				   uint8_t *peer_mac, bool val)
1799 {
1800 	ol_txrx_peer_handle peer;
1801 	struct ol_txrx_pdev_t *pdev;
1802 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
1803 	ol_txrx_vdev_handle vdev = ol_txrx_get_vdev_from_soc_vdev_id(soc,
1804 								     vdev_id);
1805 
1806 	if (!vdev)
1807 		return;
1808 
1809 	pdev = vdev->pdev;
1810 	peer = ol_txrx_find_peer_by_addr((struct cdp_pdev *)pdev, peer_mac);
1811 
1812 	ol_txrx_info_high("peer %pK, peer->ref_cnt %d",
1813 			  peer, qdf_atomic_read(&peer->ref_cnt));
1814 
1815 	/* Mark peer as tdls */
1816 	if (peer)
1817 		peer->is_tdls_peer = val;
1818 }
1819 
1820 void ol_txrx_set_tdls_offchan_enabled(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
1821 				      uint8_t *peer_mac, bool val)
1822 {
1823 	ol_txrx_peer_handle peer;
1824 	struct ol_txrx_pdev_t *pdev;
1825 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
1826 	ol_txrx_vdev_handle vdev = ol_txrx_get_vdev_from_soc_vdev_id(soc,
1827 								     vdev_id);
1828 
1829 	if (!vdev)
1830 		return;
1831 
1832 	pdev = vdev->pdev;
1833 	peer = ol_txrx_find_peer_by_addr((struct cdp_pdev *)pdev, peer_mac);
1834 
1835 	ol_txrx_info_high("peer %pK, peer->ref_cnt %d",
1836 			  peer, qdf_atomic_read(&peer->ref_cnt));
1837 
1838 	/* Set TDLS Offchan operation enable/disable */
1839 	if (peer && peer->is_tdls_peer)
1840 		peer->tdls_offchan_enabled = val;
1841 }
1842 #endif
1843 
1844 #if defined(CONFIG_HL_SUPPORT) && defined(DEBUG_HL_LOGGING)
1845 /**
1846  * ol_txrx_pdev_txq_log_init() - initialise pdev txq logs
1847  * @pdev: the physical device object
1848  *
1849  * Return: None
1850  */
1851 void ol_txrx_pdev_txq_log_init(struct ol_txrx_pdev_t *pdev)
1852 {
1853 	qdf_spinlock_create(&pdev->txq_log_spinlock);
1854 	pdev->txq_log.size = OL_TXQ_LOG_SIZE;
1855 	pdev->txq_log.oldest_record_offset = 0;
1856 	pdev->txq_log.offset = 0;
1857 	pdev->txq_log.allow_wrap = 1;
1858 	pdev->txq_log.wrapped = 0;
1859 }
1860 
1861 /**
1862  * ol_txrx_pdev_txq_log_destroy() - remove txq log spinlock for pdev
1863  * @pdev: the physical device object
1864  *
1865  * Return: None
1866  */
1867 void ol_txrx_pdev_txq_log_destroy(struct ol_txrx_pdev_t *pdev)
1868 {
1869 	qdf_spinlock_destroy(&pdev->txq_log_spinlock);
1870 }
1871 #endif
1872 
1873 #if defined(DEBUG_HL_LOGGING)
1874 
1875 /**
1876  * ol_txrx_pdev_grp_stats_init() - initialise group stat spinlock for pdev
1877  * @pdev: the physical device object
1878  *
1879  * Return: None
1880  */
1881 void ol_txrx_pdev_grp_stats_init(struct ol_txrx_pdev_t *pdev)
1882 {
1883 	qdf_spinlock_create(&pdev->grp_stat_spinlock);
1884 	pdev->grp_stats.last_valid_index = -1;
1885 	pdev->grp_stats.wrap_around = 0;
1886 }
1887 
1888 /**
1889  * ol_txrx_pdev_grp_stat_destroy() - destroy group stat spinlock for pdev
1890  * @pdev: the physical device object
1891  *
1892  * Return: None
1893  */
1894 void ol_txrx_pdev_grp_stat_destroy(struct ol_txrx_pdev_t *pdev)
1895 {
1896 	qdf_spinlock_destroy(&pdev->grp_stat_spinlock);
1897 }
1898 #endif
1899 
1900 #if defined(CONFIG_HL_SUPPORT) && defined(FEATURE_WLAN_TDLS)
1901 
1902 /**
1903  * ol_txrx_hl_tdls_flag_reset() - reset tdls flag for vdev
1904  * @soc_hdl: Datapath soc handle
1905  * @vdev_id: id of vdev
1906  * @flag: flag
1907  *
1908  * Return: None
1909  */
1910 void
1911 ol_txrx_hl_tdls_flag_reset(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
1912 			   bool flag)
1913 {
1914 	struct ol_txrx_vdev_t *vdev =
1915 		(struct ol_txrx_vdev_t *)ol_txrx_get_vdev_from_vdev_id(vdev_id);
1916 	if (!vdev) {
1917 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1918 			  "%s: Invalid vdev_id %d", __func__, vdev_id);
1919 		return;
1920 	}
1921 
1922 	vdev->hlTdlsFlag = flag;
1923 }
1924 #endif
1925 
1926 /**
1927  * ol_txrx_vdev_txqs_init() - initialise vdev tx queues
1928  * @vdev: the virtual device object
1929  *
1930  * Return: None
1931  */
1932 void ol_txrx_vdev_txqs_init(struct ol_txrx_vdev_t *vdev)
1933 {
1934 	uint8_t i;
1935 
1936 	for (i = 0; i < OL_TX_VDEV_NUM_QUEUES; i++) {
1937 		TAILQ_INIT(&vdev->txqs[i].head);
1938 		vdev->txqs[i].paused_count.total = 0;
1939 		vdev->txqs[i].frms = 0;
1940 		vdev->txqs[i].bytes = 0;
1941 		vdev->txqs[i].ext_tid = OL_TX_NUM_TIDS + i;
1942 		vdev->txqs[i].flag = ol_tx_queue_empty;
1943 		/* aggregation is not applicable for vdev tx queues */
1944 		vdev->txqs[i].aggr_state = ol_tx_aggr_disabled;
1945 		ol_tx_txq_set_group_ptr(&vdev->txqs[i], NULL);
1946 		ol_txrx_set_txq_peer(&vdev->txqs[i], NULL);
1947 	}
1948 }
1949 
1950 /**
1951  * ol_txrx_vdev_tx_queue_free() - free vdev tx queues
1952  * @vdev: the virtual device object
1953  *
1954  * Return: None
1955  */
1956 void ol_txrx_vdev_tx_queue_free(struct ol_txrx_vdev_t *vdev)
1957 {
1958 	struct ol_txrx_pdev_t *pdev = vdev->pdev;
1959 	struct ol_tx_frms_queue_t *txq;
1960 	int i;
1961 
1962 	for (i = 0; i < OL_TX_VDEV_NUM_QUEUES; i++) {
1963 		txq = &vdev->txqs[i];
1964 		ol_tx_queue_free(pdev, txq, (i + OL_TX_NUM_TIDS), false);
1965 	}
1966 }
1967 
1968 /**
1969  * ol_txrx_peer_txqs_init() - initialise peer tx queues
1970  * @pdev: the physical device object
1971  * @peer: peer object
1972  *
1973  * Return: None
1974  */
1975 void ol_txrx_peer_txqs_init(struct ol_txrx_pdev_t *pdev,
1976 			    struct ol_txrx_peer_t *peer)
1977 {
1978 	uint8_t i;
1979 	struct ol_txrx_vdev_t *vdev = peer->vdev;
1980 
1981 	qdf_spin_lock_bh(&pdev->tx_queue_spinlock);
1982 	for (i = 0; i < OL_TX_NUM_TIDS; i++) {
1983 		TAILQ_INIT(&peer->txqs[i].head);
1984 		peer->txqs[i].paused_count.total = 0;
1985 		peer->txqs[i].frms = 0;
1986 		peer->txqs[i].bytes = 0;
1987 		peer->txqs[i].ext_tid = i;
1988 		peer->txqs[i].flag = ol_tx_queue_empty;
1989 		peer->txqs[i].aggr_state = ol_tx_aggr_untried;
1990 		ol_tx_set_peer_group_ptr(pdev, peer, vdev->vdev_id, i);
1991 		ol_txrx_set_txq_peer(&peer->txqs[i], peer);
1992 	}
1993 	qdf_spin_unlock_bh(&pdev->tx_queue_spinlock);
1994 
1995 	/* aggregation is not applicable for mgmt and non-QoS tx queues */
1996 	for (i = OL_TX_NUM_QOS_TIDS; i < OL_TX_NUM_TIDS; i++)
1997 		peer->txqs[i].aggr_state = ol_tx_aggr_disabled;
1998 
1999 	ol_txrx_peer_pause(peer);
2000 }
2001 
2002 /**
2003  * ol_txrx_peer_tx_queue_free() - free peer tx queues
2004  * @pdev: the physical device object
2005  * @peer: peer object
2006  *
2007  * Return: None
2008  */
2009 void ol_txrx_peer_tx_queue_free(struct ol_txrx_pdev_t *pdev,
2010 				struct ol_txrx_peer_t *peer)
2011 {
2012 	struct ol_tx_frms_queue_t *txq;
2013 	uint8_t i;
2014 
2015 	for (i = 0; i < OL_TX_NUM_TIDS; i++) {
2016 		txq = &peer->txqs[i];
2017 		ol_tx_queue_free(pdev, txq, i, true);
2018 	}
2019 }
2020 
2021 #ifdef FEATURE_HL_GROUP_CREDIT_FLOW_CONTROL
2022 
2023 /**
2024  * ol_txrx_update_group_credit() - update group credit for tx queue
2025  * @group: for which credit needs to be updated
2026  * @credit: credits
2027  * @absolute: TXQ group absolute
2028  *
2029  * Return: allocated pool size
2030  */
2031 void ol_txrx_update_group_credit(
2032 		struct ol_tx_queue_group_t *group,
2033 		int32_t credit,
2034 		u_int8_t absolute)
2035 {
2036 	if (absolute)
2037 		qdf_atomic_set(&group->credit, credit);
2038 	else
2039 		qdf_atomic_add(credit, &group->credit);
2040 }
2041 
2042 /**
2043  * ol_txrx_update_tx_queue_groups() - update vdev tx queue group if
2044  *				      vdev id mask and ac mask is not matching
2045  * @pdev: the data physical device
2046  * @group_id: TXQ group id
2047  * @credit: TXQ group credit count
2048  * @absolute: TXQ group absolute
2049  * @vdev_id_mask: TXQ vdev group id mask
2050  * @ac_mask: TQX access category mask
2051  *
2052  * Return: None
2053  */
2054 void ol_txrx_update_tx_queue_groups(
2055 		ol_txrx_pdev_handle pdev,
2056 		u_int8_t group_id,
2057 		int32_t credit,
2058 		u_int8_t absolute,
2059 		u_int32_t vdev_id_mask,
2060 		u_int32_t ac_mask
2061 		)
2062 {
2063 	struct ol_tx_queue_group_t *group;
2064 	u_int32_t group_vdev_bit_mask, vdev_bit_mask, group_vdev_id_mask;
2065 	u_int32_t membership;
2066 	struct ol_txrx_vdev_t *vdev;
2067 
2068 	if (group_id >= OL_TX_MAX_TXQ_GROUPS) {
2069 		ol_txrx_warn("invalid group_id=%u, ignore update", group_id);
2070 		return;
2071 	}
2072 
2073 	group = &pdev->txq_grps[group_id];
2074 
2075 	membership = OL_TXQ_GROUP_MEMBERSHIP_GET(vdev_id_mask, ac_mask);
2076 
2077 	qdf_spin_lock_bh(&pdev->tx_queue_spinlock);
2078 	/*
2079 	 * if the membership (vdev id mask and ac mask)
2080 	 * matches then no need to update tx qeue groups.
2081 	 */
2082 	if (group->membership == membership)
2083 		/* Update Credit Only */
2084 		goto credit_update;
2085 
2086 	credit += ol_txrx_distribute_group_credits(pdev, group_id,
2087 						   vdev_id_mask);
2088 	/*
2089 	 * membership (vdev id mask and ac mask) is not matching
2090 	 * TODO: ignoring ac mask for now
2091 	 */
2092 	qdf_assert(ac_mask == 0xffff);
2093 	group_vdev_id_mask =
2094 		OL_TXQ_GROUP_VDEV_ID_MASK_GET(group->membership);
2095 
2096 	TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) {
2097 		group_vdev_bit_mask =
2098 			OL_TXQ_GROUP_VDEV_ID_BIT_MASK_GET(
2099 					group_vdev_id_mask, vdev->vdev_id);
2100 		vdev_bit_mask =
2101 			OL_TXQ_GROUP_VDEV_ID_BIT_MASK_GET(
2102 					vdev_id_mask, vdev->vdev_id);
2103 
2104 		if (group_vdev_bit_mask != vdev_bit_mask) {
2105 			/*
2106 			 * Change in vdev tx queue group
2107 			 */
2108 			if (!vdev_bit_mask) {
2109 				/* Set Group Pointer (vdev and peer) to NULL */
2110 				ol_txrx_info("Group membership removed for vdev_id %d from group_id %d",
2111 					     vdev->vdev_id, group_id);
2112 				ol_tx_set_vdev_group_ptr(
2113 						pdev, vdev->vdev_id, NULL);
2114 			} else {
2115 				/* Set Group Pointer (vdev and peer) */
2116 				ol_txrx_info("Group membership updated for vdev_id %d to group_id %d",
2117 					     vdev->vdev_id, group_id);
2118 				ol_tx_set_vdev_group_ptr(
2119 						pdev, vdev->vdev_id, group);
2120 			}
2121 		}
2122 	}
2123 	/* Update membership */
2124 	group->membership = membership;
2125 	ol_txrx_info("Group membership updated for group_id %d membership 0x%x",
2126 		     group_id, group->membership);
2127 credit_update:
2128 	/* Update Credit */
2129 	ol_txrx_update_group_credit(group, credit, absolute);
2130 	qdf_spin_unlock_bh(&pdev->tx_queue_spinlock);
2131 }
2132 #endif
2133 
2134 #if defined(FEATURE_HL_GROUP_CREDIT_FLOW_CONTROL) && \
2135 	defined(FEATURE_HL_DBS_GROUP_CREDIT_SHARING)
2136 #define MIN_INIT_GROUP_CREDITS	10
2137 int ol_txrx_distribute_group_credits(struct ol_txrx_pdev_t *pdev,
2138 				     u8 group_id,
2139 				     u32 vdevid_mask_new)
2140 {
2141 	struct ol_tx_queue_group_t *grp = &pdev->txq_grps[group_id];
2142 	struct ol_tx_queue_group_t *grp_nxt = &pdev->txq_grps[!group_id];
2143 	int creds_nxt = qdf_atomic_read(&grp_nxt->credit);
2144 	int vdevid_mask = OL_TXQ_GROUP_VDEV_ID_MASK_GET(grp->membership);
2145 	int vdevid_mask_othgrp =
2146 		OL_TXQ_GROUP_VDEV_ID_MASK_GET(grp_nxt->membership);
2147 	int creds_distribute = 0;
2148 
2149 	/* if vdev added to the group is the first vdev */
2150 	if ((vdevid_mask == 0) && (vdevid_mask_new != 0)) {
2151 		/* if other group has members */
2152 		if (vdevid_mask_othgrp) {
2153 			if (creds_nxt < MIN_INIT_GROUP_CREDITS)
2154 				creds_distribute = creds_nxt / 2;
2155 			else
2156 				creds_distribute = MIN_INIT_GROUP_CREDITS;
2157 
2158 			ol_txrx_update_group_credit(grp_nxt, -creds_distribute,
2159 						    0);
2160 		} else {
2161 			/*
2162 			 * Other grp has no members, give all credits to this
2163 			 * grp.
2164 			 */
2165 			creds_distribute =
2166 				qdf_atomic_read(&pdev->target_tx_credit);
2167 		}
2168 	/* if all vdevs are removed from this grp */
2169 	} else if ((vdevid_mask != 0) && (vdevid_mask_new == 0)) {
2170 		if (vdevid_mask_othgrp)
2171 			/* Transfer credits to other grp */
2172 			ol_txrx_update_group_credit(grp_nxt,
2173 						    qdf_atomic_read(&grp->
2174 						    credit),
2175 						    0);
2176 		/* Set current grp credits to zero */
2177 		ol_txrx_update_group_credit(grp, 0, 1);
2178 	}
2179 
2180 	return creds_distribute;
2181 }
2182 #endif /*
2183 	* FEATURE_HL_GROUP_CREDIT_FLOW_CONTROL &&
2184 	* FEATURE_HL_DBS_GROUP_CREDIT_SHARING
2185 	*/
2186 
2187 #ifdef QCA_HL_NETDEV_FLOW_CONTROL
2188 int ol_txrx_register_hl_flow_control(struct cdp_soc_t *soc_hdl,
2189 				     uint8_t pdev_id,
2190 				     tx_pause_callback flowcontrol)
2191 {
2192 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
2193 	ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
2194 	u32 desc_pool_size;
2195 
2196 	if (!pdev || !flowcontrol) {
2197 		ol_txrx_err("pdev or pause_cb is NULL");
2198 		return QDF_STATUS_E_INVAL;
2199 	}
2200 
2201 	desc_pool_size = ol_tx_desc_pool_size_hl(pdev->ctrl_pdev);
2202 	/*
2203 	 * Assert if the tx descriptor pool size meets the requirements
2204 	 * Maximum 2 sessions are allowed on a band.
2205 	 */
2206 	QDF_ASSERT((2 * ol_txrx_tx_desc_alloc_table[TXRX_FC_5GH_80M_2x2] +
2207 		    ol_txrx_tx_desc_alloc_table[TXRX_FC_2GH_40M_2x2])
2208 		    <= desc_pool_size);
2209 
2210 	pdev->pause_cb = flowcontrol;
2211 	return 0;
2212 }
2213 
2214 int ol_txrx_set_vdev_os_queue_status(struct cdp_soc_t *soc_hdl, u8 vdev_id,
2215 				     enum netif_action_type action)
2216 {
2217 	struct ol_txrx_vdev_t *vdev =
2218 	(struct ol_txrx_vdev_t *)ol_txrx_get_vdev_from_vdev_id(vdev_id);
2219 
2220 	if (!vdev) {
2221 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
2222 			  "%s: Invalid vdev_id %d", __func__, vdev_id);
2223 		return -EINVAL;
2224 	}
2225 
2226 	switch (action) {
2227 	case WLAN_NETIF_PRIORITY_QUEUE_ON:
2228 		qdf_spin_lock_bh(&vdev->pdev->tx_mutex);
2229 		vdev->prio_q_paused = 0;
2230 		qdf_spin_unlock_bh(&vdev->pdev->tx_mutex);
2231 		break;
2232 	case WLAN_WAKE_NON_PRIORITY_QUEUE:
2233 		qdf_atomic_set(&vdev->os_q_paused, 0);
2234 		break;
2235 	default:
2236 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
2237 			  "%s: Invalid action %d", __func__, action);
2238 		return -EINVAL;
2239 	}
2240 	return 0;
2241 }
2242 
2243 int ol_txrx_set_vdev_tx_desc_limit(struct cdp_soc_t *soc_hdl, u8 vdev_id,
2244 				   u32 chan_freq)
2245 {
2246 	struct ol_txrx_vdev_t *vdev =
2247 	(struct ol_txrx_vdev_t *)ol_txrx_get_vdev_from_vdev_id(vdev_id);
2248 	enum ol_txrx_fc_limit_id fc_limit_id;
2249 	u32 td_limit;
2250 
2251 	if (!vdev) {
2252 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
2253 			  "%s: Invalid vdev_id %d", __func__, vdev_id);
2254 		return -EINVAL;
2255 	}
2256 
2257 	/* TODO: Handle no of spatial streams and channel BW */
2258 	if (WLAN_REG_IS_5GHZ_CH_FREQ(chan_freq))
2259 		fc_limit_id = TXRX_FC_5GH_80M_2x2;
2260 	else
2261 		fc_limit_id = TXRX_FC_2GH_40M_2x2;
2262 
2263 	qdf_spin_lock_bh(&vdev->pdev->tx_mutex);
2264 	td_limit = ol_txrx_tx_desc_alloc_table[fc_limit_id];
2265 	vdev->tx_desc_limit = td_limit;
2266 	vdev->queue_stop_th = td_limit - TXRX_HL_TX_DESC_HI_PRIO_RESERVED;
2267 	vdev->queue_restart_th = td_limit - TXRX_HL_TX_DESC_QUEUE_RESTART_TH;
2268 	qdf_spin_unlock_bh(&vdev->pdev->tx_mutex);
2269 
2270 	return 0;
2271 }
2272 
2273 void ol_tx_dump_flow_pool_info_compact(struct ol_txrx_pdev_t *pdev)
2274 {
2275 	char *comb_log_str;
2276 	int bytes_written = 0;
2277 	uint32_t free_size;
2278 	struct ol_txrx_vdev_t *vdev;
2279 	int i = 0;
2280 
2281 	free_size = WLAN_MAX_VDEVS * 100;
2282 	comb_log_str = qdf_mem_malloc(free_size);
2283 	if (!comb_log_str)
2284 		return;
2285 
2286 	qdf_spin_lock_bh(&pdev->tx_mutex);
2287 	TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) {
2288 		bytes_written += snprintf(&comb_log_str[bytes_written],
2289 				free_size, "%d (%d,%d)(%d,%d)(%d,%d) |",
2290 				vdev->vdev_id, vdev->tx_desc_limit,
2291 				qdf_atomic_read(&vdev->tx_desc_count),
2292 				qdf_atomic_read(&vdev->os_q_paused),
2293 				vdev->prio_q_paused, vdev->queue_stop_th,
2294 				vdev->queue_restart_th);
2295 		free_size -= bytes_written;
2296 	}
2297 	qdf_spin_unlock_bh(&pdev->tx_mutex);
2298 	qdf_nofl_debug("STATS | FC: %s", comb_log_str);
2299 
2300 	free_size = WLAN_MAX_VDEVS * 100;
2301 	bytes_written = 0;
2302 	qdf_mem_zero(comb_log_str, free_size);
2303 
2304 	bytes_written = snprintf(&comb_log_str[bytes_written], free_size,
2305 				 "%d ",
2306 				 qdf_atomic_read(&pdev->target_tx_credit));
2307 	for (i = 0; i < OL_TX_MAX_TXQ_GROUPS; i++) {
2308 		bytes_written += snprintf(&comb_log_str[bytes_written],
2309 					  free_size, "|%d, (0x%x, %d)", i,
2310 					  OL_TXQ_GROUP_VDEV_ID_MASK_GET(
2311 					  pdev->txq_grps[i].membership),
2312 					  qdf_atomic_read(
2313 					  &pdev->txq_grps[i].credit));
2314 	       free_size -= bytes_written;
2315 	}
2316 	qdf_nofl_debug("STATS | CREDIT: %s", comb_log_str);
2317 	qdf_mem_free(comb_log_str);
2318 }
2319 
2320 void ol_tx_dump_flow_pool_info(struct cdp_soc_t *soc_hdl)
2321 {
2322 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
2323 	ol_txrx_pdev_handle pdev;
2324 	struct ol_txrx_vdev_t *vdev;
2325 
2326 	pdev = ol_txrx_get_pdev_from_pdev_id(soc, OL_TXRX_PDEV_ID);
2327 	if (!pdev) {
2328 		ol_txrx_err("pdev is NULL");
2329 		return;
2330 	}
2331 
2332 	qdf_spin_lock_bh(&pdev->tx_mutex);
2333 	TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) {
2334 		txrx_nofl_info("vdev_id %d", vdev->vdev_id);
2335 		txrx_nofl_info("limit %d available %d stop_threshold %d restart_threshold %d",
2336 			       vdev->tx_desc_limit,
2337 			       qdf_atomic_read(&vdev->tx_desc_count),
2338 			       vdev->queue_stop_th, vdev->queue_restart_th);
2339 		txrx_nofl_info("q_paused %d prio_q_paused %d",
2340 			       qdf_atomic_read(&vdev->os_q_paused),
2341 			       vdev->prio_q_paused);
2342 		txrx_nofl_info("no_of_bundle_sent_after_threshold %lld",
2343 			       vdev->no_of_bundle_sent_after_threshold);
2344 		txrx_nofl_info("no_of_bundle_sent_in_timer %lld",
2345 			       vdev->no_of_bundle_sent_in_timer);
2346 		txrx_nofl_info("no_of_pkt_not_added_in_queue %lld",
2347 			       vdev->no_of_pkt_not_added_in_queue);
2348 	}
2349 	qdf_spin_unlock_bh(&pdev->tx_mutex);
2350 }
2351 #endif /* QCA_HL_NETDEV_FLOW_CONTROL */
2352