xref: /wlan-driver/qca-wifi-host-cmn/dp/wifi3.0/dp_htt.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1 /*
2  * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-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 <htt.h>
21 #include <hal_hw_headers.h>
22 #include <hal_api.h>
23 #include "dp_peer.h"
24 #include "dp_types.h"
25 #include "dp_internal.h"
26 #include "dp_ipa.h"
27 #include "dp_rx.h"
28 #include "htt_stats.h"
29 #include "htt_ppdu_stats.h"
30 #include "dp_htt.h"
31 #ifdef WIFI_MONITOR_SUPPORT
32 #include <dp_mon.h>
33 #endif
34 #include "qdf_mem.h"   /* qdf_mem_malloc,free */
35 #include "cdp_txrx_cmn_struct.h"
36 #ifdef IPA_OPT_WIFI_DP
37 #include "cdp_txrx_ipa.h"
38 #endif
39 #ifdef FEATURE_PERPKT_INFO
40 #include "dp_ratetable.h"
41 #endif
42 #include <qdf_module.h>
43 #ifdef CONFIG_SAWF_DEF_QUEUES
44 #include <dp_sawf_htt.h>
45 #endif
46 #include <wbuff.h>
47 
48 #define HTT_TLV_HDR_LEN HTT_T2H_EXT_STATS_CONF_TLV_HDR_SIZE
49 
50 #define HTT_HTC_PKT_POOL_INIT_SIZE 64
51 
52 #define HTT_MSG_BUF_SIZE(msg_bytes) \
53 	((msg_bytes) + HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING)
54 
55 #define HTT_PID_BIT_MASK 0x3
56 
57 #define DP_EXT_MSG_LENGTH 2048
58 #define HTT_HEADER_LEN 16
59 #define HTT_MGMT_CTRL_TLV_HDR_RESERVERD_LEN 16
60 
61 #define HTT_SHIFT_UPPER_TIMESTAMP 32
62 #define HTT_MASK_UPPER_TIMESTAMP 0xFFFFFFFF00000000
63 #define HTT_BKP_STATS_MAX_QUEUE_DEPTH 16
64 
65 struct dp_htt_htc_pkt *
htt_htc_pkt_alloc(struct htt_soc * soc)66 htt_htc_pkt_alloc(struct htt_soc *soc)
67 {
68 	struct dp_htt_htc_pkt_union *pkt = NULL;
69 
70 	HTT_TX_MUTEX_ACQUIRE(&soc->htt_tx_mutex);
71 	if (soc->htt_htc_pkt_freelist) {
72 		pkt = soc->htt_htc_pkt_freelist;
73 		soc->htt_htc_pkt_freelist = soc->htt_htc_pkt_freelist->u.next;
74 	}
75 	HTT_TX_MUTEX_RELEASE(&soc->htt_tx_mutex);
76 
77 	if (!pkt)
78 		pkt = qdf_mem_malloc(sizeof(*pkt));
79 
80 	if (!pkt)
81 		return NULL;
82 
83 	htc_packet_set_magic_cookie(&(pkt->u.pkt.htc_pkt), 0);
84 
85 	return &pkt->u.pkt; /* not actually a dereference */
86 }
87 
88 qdf_export_symbol(htt_htc_pkt_alloc);
89 
90 void
htt_htc_pkt_free(struct htt_soc * soc,struct dp_htt_htc_pkt * pkt)91 htt_htc_pkt_free(struct htt_soc *soc, struct dp_htt_htc_pkt *pkt)
92 {
93 	struct dp_htt_htc_pkt_union *u_pkt =
94 		(struct dp_htt_htc_pkt_union *)pkt;
95 
96 	HTT_TX_MUTEX_ACQUIRE(&soc->htt_tx_mutex);
97 	htc_packet_set_magic_cookie(&(u_pkt->u.pkt.htc_pkt), 0);
98 	u_pkt->u.next = soc->htt_htc_pkt_freelist;
99 	soc->htt_htc_pkt_freelist = u_pkt;
100 	HTT_TX_MUTEX_RELEASE(&soc->htt_tx_mutex);
101 }
102 
103 qdf_export_symbol(htt_htc_pkt_free);
104 
105 void
htt_htc_pkt_pool_free(struct htt_soc * soc)106 htt_htc_pkt_pool_free(struct htt_soc *soc)
107 {
108 	struct dp_htt_htc_pkt_union *pkt, *next;
109 	pkt = soc->htt_htc_pkt_freelist;
110 	while (pkt) {
111 		next = pkt->u.next;
112 		qdf_mem_free(pkt);
113 		pkt = next;
114 	}
115 	soc->htt_htc_pkt_freelist = NULL;
116 }
117 
118 
119 #ifndef ENABLE_CE4_COMP_DISABLE_HTT_HTC_MISC_LIST
120 
121 /**
122  * htt_htc_misc_pkt_list_trim() - trim misc list
123  * @soc: HTT SOC handle
124  * @level: max no. of pkts in list
125  */
126 static void
htt_htc_misc_pkt_list_trim(struct htt_soc * soc,int level)127 htt_htc_misc_pkt_list_trim(struct htt_soc *soc, int level)
128 {
129 	struct dp_htt_htc_pkt_union *pkt, *next, *prev = NULL;
130 	int i = 0;
131 	qdf_nbuf_t netbuf;
132 
133 	HTT_TX_MUTEX_ACQUIRE(&soc->htt_tx_mutex);
134 	pkt = soc->htt_htc_pkt_misclist;
135 	while (pkt) {
136 		next = pkt->u.next;
137 		/* trim the out grown list*/
138 		if (++i > level) {
139 			netbuf =
140 				(qdf_nbuf_t)(pkt->u.pkt.htc_pkt.pNetBufContext);
141 			qdf_nbuf_unmap(soc->osdev, netbuf, QDF_DMA_TO_DEVICE);
142 			qdf_nbuf_free(netbuf);
143 			qdf_mem_free(pkt);
144 			pkt = NULL;
145 			if (prev)
146 				prev->u.next = NULL;
147 		}
148 		prev = pkt;
149 		pkt = next;
150 	}
151 	HTT_TX_MUTEX_RELEASE(&soc->htt_tx_mutex);
152 }
153 
154 void
htt_htc_misc_pkt_list_add(struct htt_soc * soc,struct dp_htt_htc_pkt * pkt)155 htt_htc_misc_pkt_list_add(struct htt_soc *soc, struct dp_htt_htc_pkt *pkt)
156 {
157 	struct dp_htt_htc_pkt_union *u_pkt =
158 				(struct dp_htt_htc_pkt_union *)pkt;
159 	int misclist_trim_level = htc_get_tx_queue_depth(soc->htc_soc,
160 							pkt->htc_pkt.Endpoint)
161 				+ DP_HTT_HTC_PKT_MISCLIST_SIZE;
162 
163 	HTT_TX_MUTEX_ACQUIRE(&soc->htt_tx_mutex);
164 	if (soc->htt_htc_pkt_misclist) {
165 		u_pkt->u.next = soc->htt_htc_pkt_misclist;
166 		soc->htt_htc_pkt_misclist = u_pkt;
167 	} else {
168 		soc->htt_htc_pkt_misclist = u_pkt;
169 	}
170 	HTT_TX_MUTEX_RELEASE(&soc->htt_tx_mutex);
171 
172 	/* only ce pipe size + tx_queue_depth could possibly be in use
173 	 * free older packets in the misclist
174 	 */
175 	htt_htc_misc_pkt_list_trim(soc, misclist_trim_level);
176 }
177 
178 qdf_export_symbol(htt_htc_misc_pkt_list_add);
179 #endif  /* ENABLE_CE4_COMP_DISABLE_HTT_HTC_MISC_LIST */
180 
181 /**
182  * htt_htc_misc_pkt_pool_free() - free pkts in misc list
183  * @soc:	HTT SOC handle
184  */
185 static void
htt_htc_misc_pkt_pool_free(struct htt_soc * soc)186 htt_htc_misc_pkt_pool_free(struct htt_soc *soc)
187 {
188 	struct dp_htt_htc_pkt_union *pkt, *next;
189 	qdf_nbuf_t netbuf;
190 
191 	HTT_TX_MUTEX_ACQUIRE(&soc->htt_tx_mutex);
192 	pkt = soc->htt_htc_pkt_misclist;
193 
194 	while (pkt) {
195 		next = pkt->u.next;
196 		if (htc_packet_get_magic_cookie(&(pkt->u.pkt.htc_pkt)) !=
197 		    HTC_PACKET_MAGIC_COOKIE) {
198 			pkt = next;
199 			soc->stats.skip_count++;
200 			continue;
201 		}
202 		netbuf = (qdf_nbuf_t) (pkt->u.pkt.htc_pkt.pNetBufContext);
203 		qdf_nbuf_unmap(soc->osdev, netbuf, QDF_DMA_TO_DEVICE);
204 
205 		soc->stats.htc_pkt_free++;
206 		dp_htt_info("%pK: Pkt free count %d",
207 			    soc->dp_soc, soc->stats.htc_pkt_free);
208 
209 		qdf_nbuf_free(netbuf);
210 		qdf_mem_free(pkt);
211 		pkt = next;
212 	}
213 	soc->htt_htc_pkt_misclist = NULL;
214 	HTT_TX_MUTEX_RELEASE(&soc->htt_tx_mutex);
215 	dp_info("HTC Packets, fail count = %d, skip count = %d",
216 		soc->stats.fail_count, soc->stats.skip_count);
217 }
218 
219 /**
220  * htt_t2h_mac_addr_deswizzle() - Swap MAC addr bytes if FW endianness differ
221  * @tgt_mac_addr:	Target MAC
222  * @buffer:		Output buffer
223  */
224 static u_int8_t *
htt_t2h_mac_addr_deswizzle(u_int8_t * tgt_mac_addr,u_int8_t * buffer)225 htt_t2h_mac_addr_deswizzle(u_int8_t *tgt_mac_addr, u_int8_t *buffer)
226 {
227 #ifdef BIG_ENDIAN_HOST
228 	/*
229 	 * The host endianness is opposite of the target endianness.
230 	 * To make u_int32_t elements come out correctly, the target->host
231 	 * upload has swizzled the bytes in each u_int32_t element of the
232 	 * message.
233 	 * For byte-array message fields like the MAC address, this
234 	 * upload swizzling puts the bytes in the wrong order, and needs
235 	 * to be undone.
236 	 */
237 	buffer[0] = tgt_mac_addr[3];
238 	buffer[1] = tgt_mac_addr[2];
239 	buffer[2] = tgt_mac_addr[1];
240 	buffer[3] = tgt_mac_addr[0];
241 	buffer[4] = tgt_mac_addr[7];
242 	buffer[5] = tgt_mac_addr[6];
243 	return buffer;
244 #else
245 	/*
246 	 * The host endianness matches the target endianness -
247 	 * we can use the mac addr directly from the message buffer.
248 	 */
249 	return tgt_mac_addr;
250 #endif
251 }
252 
253 /**
254  * dp_htt_h2t_send_complete_free_netbuf() - Free completed buffer
255  * @soc:	SOC handle
256  * @status:	Completion status
257  * @netbuf:	HTT buffer
258  */
259 static void
dp_htt_h2t_send_complete_free_netbuf(void * soc,A_STATUS status,qdf_nbuf_t netbuf)260 dp_htt_h2t_send_complete_free_netbuf(
261 	void *soc, A_STATUS status, qdf_nbuf_t netbuf)
262 {
263 	qdf_nbuf_free(netbuf);
264 }
265 
266 #ifdef ENABLE_CE4_COMP_DISABLE_HTT_HTC_MISC_LIST
267 void
dp_htt_h2t_send_complete(void * context,HTC_PACKET * htc_pkt)268 dp_htt_h2t_send_complete(void *context, HTC_PACKET *htc_pkt)
269 {
270 	struct htt_soc *soc =  (struct htt_soc *) context;
271 	struct dp_htt_htc_pkt *htt_pkt;
272 	qdf_nbuf_t netbuf;
273 
274 	htt_pkt = container_of(htc_pkt, struct dp_htt_htc_pkt, htc_pkt);
275 
276 	/* process (free or keep) the netbuf that held the message */
277 	netbuf = (qdf_nbuf_t) htc_pkt->pNetBufContext;
278 	/*
279 	 * adf sendcomplete is required for windows only
280 	 */
281 	/* qdf_nbuf_set_sendcompleteflag(netbuf, TRUE); */
282 	/* free the htt_htc_pkt / HTC_PACKET object */
283 	qdf_nbuf_free(netbuf);
284 	htt_htc_pkt_free(soc, htt_pkt);
285 }
286 
287 #else /* ENABLE_CE4_COMP_DISABLE_HTT_HTC_MISC_LIST */
288 
289 void
dp_htt_h2t_send_complete(void * context,HTC_PACKET * htc_pkt)290 dp_htt_h2t_send_complete(void *context, HTC_PACKET *htc_pkt)
291 {
292 	void (*send_complete_part2)(
293 	     void *soc, QDF_STATUS status, qdf_nbuf_t msdu);
294 	struct htt_soc *soc =  (struct htt_soc *) context;
295 	struct dp_htt_htc_pkt *htt_pkt;
296 	qdf_nbuf_t netbuf;
297 
298 	send_complete_part2 = htc_pkt->pPktContext;
299 
300 	htt_pkt = container_of(htc_pkt, struct dp_htt_htc_pkt, htc_pkt);
301 
302 	/* process (free or keep) the netbuf that held the message */
303 	netbuf = (qdf_nbuf_t) htc_pkt->pNetBufContext;
304 	/*
305 	 * adf sendcomplete is required for windows only
306 	 */
307 	/* qdf_nbuf_set_sendcompleteflag(netbuf, TRUE); */
308 	if (send_complete_part2){
309 		send_complete_part2(
310 		    htt_pkt->soc_ctxt, htc_pkt->Status, netbuf);
311 	}
312 	/* free the htt_htc_pkt / HTC_PACKET object */
313 	htt_htc_pkt_free(soc, htt_pkt);
314 }
315 
316 #endif /* ENABLE_CE4_COMP_DISABLE_HTT_HTC_MISC_LIST */
317 
318 /**
319  * dp_htt_h2t_add_tcl_metadata_ver_v1() - Add tcl_metadata version V1
320  * @soc:	HTT SOC handle
321  * @msg:	Pointer to nbuf
322  *
323  * Return: 0 on success; error code on failure
324  */
dp_htt_h2t_add_tcl_metadata_ver_v1(struct htt_soc * soc,qdf_nbuf_t * msg)325 static int dp_htt_h2t_add_tcl_metadata_ver_v1(struct htt_soc *soc,
326 					      qdf_nbuf_t *msg)
327 {
328 	uint32_t *msg_word;
329 
330 	*msg = qdf_nbuf_alloc(
331 		soc->osdev,
332 		HTT_MSG_BUF_SIZE(HTT_VER_REQ_BYTES),
333 		/* reserve room for the HTC header */
334 		HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, TRUE);
335 	if (!*msg)
336 		return QDF_STATUS_E_NOMEM;
337 
338 	/*
339 	 * Set the length of the message.
340 	 * The contribution from the HTC_HDR_ALIGNMENT_PADDING is added
341 	 * separately during the below call to qdf_nbuf_push_head.
342 	 * The contribution from the HTC header is added separately inside HTC.
343 	 */
344 	if (!qdf_nbuf_put_tail(*msg, HTT_VER_REQ_BYTES)) {
345 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
346 			  "%s: Failed to expand head for HTT_H2T_MSG_TYPE_VERSION_REQ msg",
347 			  __func__);
348 		return QDF_STATUS_E_FAILURE;
349 	}
350 
351 	/* fill in the message contents */
352 	msg_word = (u_int32_t *)qdf_nbuf_data(*msg);
353 
354 	/* rewind beyond alignment pad to get to the HTC header reserved area */
355 	qdf_nbuf_push_head(*msg, HTC_HDR_ALIGNMENT_PADDING);
356 
357 	*msg_word = 0;
358 	HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_VERSION_REQ);
359 
360 	return QDF_STATUS_SUCCESS;
361 }
362 
363 #ifdef QCA_DP_TX_FW_METADATA_V2
364 /**
365  * dp_htt_h2t_add_tcl_metadata_ver_v2() - Add tcl_metadata version V2
366  * @soc:	HTT SOC handle
367  * @msg:	Pointer to nbuf
368  *
369  * Return: 0 on success; error code on failure
370  */
dp_htt_h2t_add_tcl_metadata_ver_v2(struct htt_soc * soc,qdf_nbuf_t * msg)371 static int dp_htt_h2t_add_tcl_metadata_ver_v2(struct htt_soc *soc,
372 					      qdf_nbuf_t *msg)
373 {
374 	uint32_t *msg_word;
375 
376 	*msg = qdf_nbuf_alloc(
377 		soc->osdev,
378 		HTT_MSG_BUF_SIZE(HTT_VER_REQ_BYTES + HTT_TCL_METADATA_VER_SZ),
379 		/* reserve room for the HTC header */
380 		HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, TRUE);
381 	if (!*msg)
382 		return QDF_STATUS_E_NOMEM;
383 
384 	/*
385 	 * Set the length of the message.
386 	 * The contribution from the HTC_HDR_ALIGNMENT_PADDING is added
387 	 * separately during the below call to qdf_nbuf_push_head.
388 	 * The contribution from the HTC header is added separately inside HTC.
389 	 */
390 	if (!qdf_nbuf_put_tail(*msg,
391 			       HTT_VER_REQ_BYTES + HTT_TCL_METADATA_VER_SZ)) {
392 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
393 			  "%s: Failed to expand head for HTT_H2T_MSG_TYPE_VERSION_REQ msg",
394 			  __func__);
395 		return QDF_STATUS_E_FAILURE;
396 	}
397 
398 	/* fill in the message contents */
399 	msg_word = (u_int32_t *)qdf_nbuf_data(*msg);
400 
401 	/* rewind beyond alignment pad to get to the HTC header reserved area */
402 	qdf_nbuf_push_head(*msg, HTC_HDR_ALIGNMENT_PADDING);
403 
404 	*msg_word = 0;
405 	HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_VERSION_REQ);
406 
407 	/* word 1 */
408 	msg_word++;
409 	*msg_word = 0;
410 	HTT_OPTION_TLV_TAG_SET(*msg_word, HTT_OPTION_TLV_TAG_TCL_METADATA_VER);
411 	HTT_OPTION_TLV_LENGTH_SET(*msg_word, HTT_TCL_METADATA_VER_SZ);
412 	HTT_OPTION_TLV_TCL_METADATA_VER_SET(*msg_word,
413 					    HTT_OPTION_TLV_TCL_METADATA_V21);
414 
415 	return QDF_STATUS_SUCCESS;
416 }
417 
418 /**
419  * dp_htt_h2t_add_tcl_metadata_ver() - Add tcl_metadata version
420  * @soc:	HTT SOC handle
421  * @msg:	Pointer to nbuf
422  *
423  * Return: 0 on success; error code on failure
424  */
dp_htt_h2t_add_tcl_metadata_ver(struct htt_soc * soc,qdf_nbuf_t * msg)425 static int dp_htt_h2t_add_tcl_metadata_ver(struct htt_soc *soc, qdf_nbuf_t *msg)
426 {
427 	/* Use tcl_metadata_v1 when NSS offload is enabled */
428 	if (wlan_cfg_get_dp_soc_nss_cfg(soc->dp_soc->wlan_cfg_ctx) ||
429 	    soc->dp_soc->cdp_soc.ol_ops->get_con_mode() == QDF_GLOBAL_FTM_MODE)
430 		return dp_htt_h2t_add_tcl_metadata_ver_v1(soc, msg);
431 	else
432 		return dp_htt_h2t_add_tcl_metadata_ver_v2(soc, msg);
433 }
434 #else
dp_htt_h2t_add_tcl_metadata_ver(struct htt_soc * soc,qdf_nbuf_t * msg)435 static int dp_htt_h2t_add_tcl_metadata_ver(struct htt_soc *soc, qdf_nbuf_t *msg)
436 {
437 	return dp_htt_h2t_add_tcl_metadata_ver_v1(soc, msg);
438 }
439 #endif
440 
441 /**
442  * htt_h2t_ver_req_msg() - Send HTT version request message to target
443  * @soc:	HTT SOC handle
444  *
445  * Return: 0 on success; error code on failure
446  */
htt_h2t_ver_req_msg(struct htt_soc * soc)447 static int htt_h2t_ver_req_msg(struct htt_soc *soc)
448 {
449 	struct dp_htt_htc_pkt *pkt;
450 	qdf_nbuf_t msg = NULL;
451 	QDF_STATUS status;
452 
453 	status = dp_htt_h2t_add_tcl_metadata_ver(soc, &msg);
454 	if (status != QDF_STATUS_SUCCESS)
455 		return status;
456 
457 	pkt = htt_htc_pkt_alloc(soc);
458 	if (!pkt) {
459 		qdf_nbuf_free(msg);
460 		return QDF_STATUS_E_FAILURE;
461 	}
462 	pkt->soc_ctxt = NULL; /* not used during send-done callback */
463 
464 	SET_HTC_PACKET_INFO_TX(&pkt->htc_pkt,
465 		dp_htt_h2t_send_complete_free_netbuf, qdf_nbuf_data(msg),
466 		qdf_nbuf_len(msg), soc->htc_endpoint,
467 		HTC_TX_PACKET_TAG_RTPM_PUT_RC);
468 
469 	SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg);
470 	status = DP_HTT_SEND_HTC_PKT(soc, pkt, HTT_H2T_MSG_TYPE_VERSION_REQ,
471 				     NULL);
472 
473 	if (status != QDF_STATUS_SUCCESS) {
474 		qdf_nbuf_free(msg);
475 		htt_htc_pkt_free(soc, pkt);
476 	}
477 
478 	return status;
479 }
480 
481 #ifdef IPA_OPT_WIFI_DP
htt_h2t_rx_cce_super_rule_setup(struct htt_soc * soc,void * param)482 QDF_STATUS htt_h2t_rx_cce_super_rule_setup(struct htt_soc *soc, void *param)
483 {
484 	struct wifi_dp_flt_setup *flt_params =
485 			(struct wifi_dp_flt_setup *)param;
486 	struct dp_htt_htc_pkt *pkt;
487 	qdf_nbuf_t msg;
488 	uint32_t *msg_word;
489 	uint8_t *htt_logger_bufp;
490 	uint16_t ver = 0;
491 	uint8_t i, valid = 0;
492 	uint8_t num_filters = flt_params->num_filters;
493 	uint8_t pdev_id = flt_params->pdev_id;
494 	uint8_t op = flt_params->op;
495 	uint16_t ipv4 = qdf_ntohs(QDF_NBUF_TRAC_IPV4_ETH_TYPE);
496 	uint16_t ipv6 = qdf_ntohs(QDF_NBUF_TRAC_IPV6_ETH_TYPE);
497 	QDF_STATUS status;
498 
499 	if (num_filters > RX_CCE_SUPER_RULE_SETUP_NUM) {
500 		dp_htt_err("Wrong filter count %d", num_filters);
501 		return QDF_STATUS_FILT_REQ_ERROR;
502 	}
503 
504 	msg = qdf_nbuf_alloc(soc->osdev,
505 			     HTT_MSG_BUF_SIZE(HTT_RX_CCE_SUPER_RULE_SETUP_SZ),
506 			     HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4,
507 			     true);
508 	if (!msg) {
509 		dp_htt_err("Fail to allocate SUPER_RULE_SETUP msg ");
510 		return QDF_STATUS_E_FAILURE;
511 	}
512 
513 	qdf_nbuf_put_tail(msg, HTT_RX_CCE_SUPER_RULE_SETUP_SZ);
514 	msg_word = (uint32_t *)qdf_nbuf_data(msg);
515 	memset(msg_word, 0, HTT_RX_CCE_SUPER_RULE_SETUP_SZ);
516 
517 	qdf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING);
518 	htt_logger_bufp = (uint8_t *)msg_word;
519 
520 	*msg_word = 0;
521 	HTT_H2T_MSG_TYPE_SET(*msg_word,
522 			     HTT_H2T_MSG_TYPE_RX_CCE_SUPER_RULE_SETUP);
523 	HTT_RX_CCE_SUPER_RULE_SETUP_PDEV_ID_SET(*msg_word, pdev_id);
524 	HTT_RX_CCE_SUPER_RULE_SETUP_OPERATION_SET(*msg_word, op);
525 
526 	/* Set cce_super_rule_params */
527 	for (i = 0; i < RX_CCE_SUPER_RULE_SETUP_NUM; i++) {
528 		valid = flt_params->flt_addr_params[i].valid;
529 		ver = flt_params->flt_addr_params[i].l3_type;
530 		msg_word++;
531 
532 		if (ver == ipv4) {
533 			HTT_RX_CCE_SUPER_RULE_SETUP_IPV4_ADDR_ARRAY_SET(
534 				msg_word,
535 				flt_params->flt_addr_params[i].src_ipv4_addr);
536 		} else if (ver == ipv6) {
537 			HTT_RX_CCE_SUPER_RULE_SETUP_IPV6_ADDR_ARRAY_SET(
538 				msg_word,
539 				flt_params->flt_addr_params[i].src_ipv6_addr);
540 		} else {
541 			dp_htt_debug("Filter %d not in use.", i);
542 		}
543 
544 		/* move uint32_t *msg_word by IPV6 addr size */
545 		msg_word += (QDF_IPV6_ADDR_SIZE / 4);
546 
547 		if (ver == ipv4) {
548 			HTT_RX_CCE_SUPER_RULE_SETUP_IPV4_ADDR_ARRAY_SET(
549 				msg_word,
550 				flt_params->flt_addr_params[i].dst_ipv4_addr);
551 		} else if (ver == ipv6) {
552 			HTT_RX_CCE_SUPER_RULE_SETUP_IPV6_ADDR_ARRAY_SET(
553 				msg_word,
554 				flt_params->flt_addr_params[i].dst_ipv6_addr);
555 		} else {
556 			dp_htt_debug("Filter %d not in use.", i);
557 		}
558 
559 		/* move uint32_t *msg_word by IPV6 addr size */
560 		msg_word += (QDF_IPV6_ADDR_SIZE / 4);
561 		HTT_RX_CCE_SUPER_RULE_SETUP_L3_TYPE_SET(*msg_word, ver);
562 		HTT_RX_CCE_SUPER_RULE_SETUP_L4_TYPE_SET(
563 					*msg_word,
564 					flt_params->flt_addr_params[i].l4_type);
565 		HTT_RX_CCE_SUPER_RULE_SETUP_IS_VALID_SET(*msg_word, valid);
566 		msg_word++;
567 		HTT_RX_CCE_SUPER_RULE_SETUP_L4_SRC_PORT_SET(
568 				*msg_word,
569 				flt_params->flt_addr_params[i].src_port);
570 		HTT_RX_CCE_SUPER_RULE_SETUP_L4_DST_PORT_SET(
571 				*msg_word,
572 				flt_params->flt_addr_params[i].dst_port);
573 
574 		dp_info("opt_dp:: pdev: %u ver %u, flt_num %u, op %u",
575 			pdev_id, ver, i, op);
576 		dp_info("valid %u", valid);
577 	}
578 
579 	pkt = htt_htc_pkt_alloc(soc);
580 	if (!pkt) {
581 		dp_htt_err("Fail to allocate dp_htt_htc_pkt buffer");
582 		qdf_assert(0);
583 		qdf_nbuf_free(msg);
584 		return QDF_STATUS_E_NOMEM;
585 	}
586 
587 	pkt->soc_ctxt = NULL; /*not used during send-done callback */
588 	SET_HTC_PACKET_INFO_TX(&pkt->htc_pkt,
589 			       dp_htt_h2t_send_complete_free_netbuf,
590 			       qdf_nbuf_data(msg), qdf_nbuf_len(msg),
591 			       soc->htc_endpoint,
592 			       HTC_TX_PACKET_TAG_RUNTIME_PUT);
593 
594 	SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg);
595 	status = DP_HTT_SEND_HTC_PKT(soc, pkt,
596 				     HTT_H2T_MSG_TYPE_RX_CCE_SUPER_RULE_SETUP,
597 				     htt_logger_bufp);
598 
599 	if (status != QDF_STATUS_SUCCESS) {
600 		qdf_nbuf_free(msg);
601 		htt_htc_pkt_free(soc, pkt);
602 	}
603 	return status;
604 }
605 #endif /* IPA_OPT_WIFI_DP */
606 
htt_srng_setup(struct htt_soc * soc,int mac_id,hal_ring_handle_t hal_ring_hdl,int hal_ring_type)607 int htt_srng_setup(struct htt_soc *soc, int mac_id,
608 		   hal_ring_handle_t hal_ring_hdl,
609 		   int hal_ring_type)
610 {
611 	struct dp_htt_htc_pkt *pkt;
612 	qdf_nbuf_t htt_msg;
613 	uint32_t *msg_word;
614 	struct hal_srng_params srng_params;
615 	qdf_dma_addr_t hp_addr, tp_addr;
616 	uint32_t ring_entry_size =
617 		hal_srng_get_entrysize(soc->hal_soc, hal_ring_type);
618 	int htt_ring_type, htt_ring_id;
619 	uint8_t *htt_logger_bufp;
620 	int target_pdev_id;
621 	int lmac_id = dp_get_lmac_id_for_pdev_id(soc->dp_soc, 0, mac_id);
622 	QDF_STATUS status;
623 
624 	/* Sizes should be set in 4-byte words */
625 	ring_entry_size = ring_entry_size >> 2;
626 
627 	htt_msg = qdf_nbuf_alloc(soc->osdev,
628 		HTT_MSG_BUF_SIZE(HTT_SRING_SETUP_SZ),
629 		/* reserve room for the HTC header */
630 		HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, TRUE);
631 	if (!htt_msg) {
632 		dp_err("htt_msg alloc failed ring type %d", hal_ring_type);
633 		goto fail0;
634 	}
635 
636 	hal_get_srng_params(soc->hal_soc, hal_ring_hdl, &srng_params);
637 	hp_addr = hal_srng_get_hp_addr(soc->hal_soc, hal_ring_hdl);
638 	tp_addr = hal_srng_get_tp_addr(soc->hal_soc, hal_ring_hdl);
639 
640 	switch (hal_ring_type) {
641 	case RXDMA_BUF:
642 #ifdef QCA_HOST2FW_RXBUF_RING
643 		if (srng_params.ring_id ==
644 		    (HAL_SRNG_WMAC1_SW2RXDMA0_BUF0 +
645 		    (lmac_id * HAL_MAX_RINGS_PER_LMAC))) {
646 			htt_ring_id = HTT_HOST1_TO_FW_RXBUF_RING;
647 			htt_ring_type = HTT_SW_TO_SW_RING;
648 #ifdef IPA_OFFLOAD
649 		} else if (srng_params.ring_id ==
650 		    (HAL_SRNG_WMAC1_SW2RXDMA0_BUF1 +
651 		    (lmac_id * HAL_MAX_RINGS_PER_LMAC))) {
652 			htt_ring_id = HTT_HOST2_TO_FW_RXBUF_RING;
653 			htt_ring_type = HTT_SW_TO_SW_RING;
654 #ifdef IPA_WDI3_VLAN_SUPPORT
655 		} else if (srng_params.ring_id ==
656 		    (HAL_SRNG_WMAC1_SW2RXDMA0_BUF2 +
657 		    (lmac_id * HAL_MAX_RINGS_PER_LMAC))) {
658 			htt_ring_id = HTT_HOST3_TO_FW_RXBUF_RING;
659 			htt_ring_type = HTT_SW_TO_SW_RING;
660 #endif
661 #endif
662 #else
663 		if (srng_params.ring_id ==
664 			(HAL_SRNG_WMAC1_SW2RXDMA0_BUF0 +
665 			(lmac_id * HAL_MAX_RINGS_PER_LMAC))) {
666 			htt_ring_id = HTT_RXDMA_HOST_BUF_RING;
667 			htt_ring_type = HTT_SW_TO_HW_RING;
668 #endif
669 		} else if (srng_params.ring_id ==
670 			 (HAL_SRNG_WMAC1_SW2RXDMA1_BUF +
671 			(lmac_id * HAL_MAX_RINGS_PER_LMAC))) {
672 			htt_ring_id = HTT_RXDMA_HOST_BUF_RING;
673 			htt_ring_type = HTT_SW_TO_HW_RING;
674 #ifdef FEATURE_DIRECT_LINK
675 		} else if (srng_params.ring_id ==
676 			   (HAL_SRNG_WMAC1_RX_DIRECT_LINK_SW_REFILL_RING +
677 			    (lmac_id * HAL_MAX_RINGS_PER_LMAC))) {
678 			htt_ring_id = HTT_LPASS_TO_FW_RXBUF_RING;
679 			htt_ring_type = HTT_SW_TO_SW_RING;
680 #endif
681 		} else {
682 			QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
683 				   "%s: Ring %d currently not supported",
684 				   __func__, srng_params.ring_id);
685 			goto fail1;
686 		}
687 
688 		break;
689 	case RXDMA_MONITOR_BUF:
690 		htt_ring_id = dp_htt_get_mon_htt_ring_id(soc->dp_soc,
691 							 RXDMA_MONITOR_BUF);
692 		htt_ring_type = HTT_SW_TO_HW_RING;
693 		break;
694 	case RXDMA_MONITOR_STATUS:
695 		htt_ring_id = HTT_RXDMA_MONITOR_STATUS_RING;
696 		htt_ring_type = HTT_SW_TO_HW_RING;
697 		break;
698 	case RXDMA_MONITOR_DST:
699 		htt_ring_id = dp_htt_get_mon_htt_ring_id(soc->dp_soc,
700 							 RXDMA_MONITOR_DST);
701 		htt_ring_type = HTT_HW_TO_SW_RING;
702 		break;
703 	case RXDMA_MONITOR_DESC:
704 		htt_ring_id = HTT_RXDMA_MONITOR_DESC_RING;
705 		htt_ring_type = HTT_SW_TO_HW_RING;
706 		break;
707 	case RXDMA_DST:
708 		htt_ring_id = HTT_RXDMA_NON_MONITOR_DEST_RING;
709 		htt_ring_type = HTT_HW_TO_SW_RING;
710 		break;
711 	case TX_MONITOR_BUF:
712 		htt_ring_id = HTT_TX_MON_HOST2MON_BUF_RING;
713 		htt_ring_type = HTT_SW_TO_HW_RING;
714 		break;
715 	case TX_MONITOR_DST:
716 		htt_ring_id = HTT_TX_MON_MON2HOST_DEST_RING;
717 		htt_ring_type = HTT_HW_TO_SW_RING;
718 		break;
719 	case SW2RXDMA_LINK_RELEASE:
720 		htt_ring_id = HTT_RXDMA_MONITOR_DESC_RING;
721 		htt_ring_type = HTT_SW_TO_HW_RING;
722 		break;
723 
724 	default:
725 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
726 			"%s: Ring currently not supported", __func__);
727 			goto fail1;
728 	}
729 
730 	dp_info("ring_type %d ring_id %d htt_ring_id %d hp_addr 0x%llx tp_addr 0x%llx",
731 		hal_ring_type, srng_params.ring_id, htt_ring_id,
732 		(uint64_t)hp_addr,
733 		(uint64_t)tp_addr);
734 	/*
735 	 * Set the length of the message.
736 	 * The contribution from the HTC_HDR_ALIGNMENT_PADDING is added
737 	 * separately during the below call to qdf_nbuf_push_head.
738 	 * The contribution from the HTC header is added separately inside HTC.
739 	 */
740 	if (qdf_nbuf_put_tail(htt_msg, HTT_SRING_SETUP_SZ) == NULL) {
741 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
742 			"%s: Failed to expand head for SRING_SETUP msg",
743 			__func__);
744 		return QDF_STATUS_E_FAILURE;
745 	}
746 
747 	msg_word = (uint32_t *)qdf_nbuf_data(htt_msg);
748 
749 	/* rewind beyond alignment pad to get to the HTC header reserved area */
750 	qdf_nbuf_push_head(htt_msg, HTC_HDR_ALIGNMENT_PADDING);
751 
752 	/* word 0 */
753 	*msg_word = 0;
754 	htt_logger_bufp = (uint8_t *)msg_word;
755 	HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_SRING_SETUP);
756 	target_pdev_id =
757 	dp_get_target_pdev_id_for_host_pdev_id(soc->dp_soc, mac_id);
758 
759 	if ((htt_ring_type == HTT_SW_TO_HW_RING) ||
760 			(htt_ring_type == HTT_HW_TO_SW_RING))
761 		HTT_SRING_SETUP_PDEV_ID_SET(*msg_word, target_pdev_id);
762 	else
763 		HTT_SRING_SETUP_PDEV_ID_SET(*msg_word, mac_id);
764 
765 	dp_info("mac_id %d", mac_id);
766 	HTT_SRING_SETUP_RING_TYPE_SET(*msg_word, htt_ring_type);
767 	/* TODO: Discuss with FW on changing this to unique ID and using
768 	 * htt_ring_type to send the type of ring
769 	 */
770 	HTT_SRING_SETUP_RING_ID_SET(*msg_word, htt_ring_id);
771 
772 	/* word 1 */
773 	msg_word++;
774 	*msg_word = 0;
775 	HTT_SRING_SETUP_RING_BASE_ADDR_LO_SET(*msg_word,
776 		srng_params.ring_base_paddr & 0xffffffff);
777 
778 	/* word 2 */
779 	msg_word++;
780 	*msg_word = 0;
781 	HTT_SRING_SETUP_RING_BASE_ADDR_HI_SET(*msg_word,
782 		(uint64_t)srng_params.ring_base_paddr >> 32);
783 
784 	/* word 3 */
785 	msg_word++;
786 	*msg_word = 0;
787 	HTT_SRING_SETUP_ENTRY_SIZE_SET(*msg_word, ring_entry_size);
788 	HTT_SRING_SETUP_RING_SIZE_SET(*msg_word,
789 		(ring_entry_size * srng_params.num_entries));
790 	dp_info("entry_size %d", ring_entry_size);
791 	dp_info("num_entries %d", srng_params.num_entries);
792 	dp_info("ring_size %d", (ring_entry_size * srng_params.num_entries));
793 	if (htt_ring_type == HTT_SW_TO_HW_RING)
794 		HTT_SRING_SETUP_RING_MISC_CFG_FLAG_LOOPCOUNT_DISABLE_SET(
795 						*msg_word, 1);
796 	HTT_SRING_SETUP_RING_MISC_CFG_FLAG_MSI_SWAP_SET(*msg_word,
797 		!!(srng_params.flags & HAL_SRNG_MSI_SWAP));
798 	HTT_SRING_SETUP_RING_MISC_CFG_FLAG_TLV_SWAP_SET(*msg_word,
799 		!!(srng_params.flags & HAL_SRNG_DATA_TLV_SWAP));
800 	HTT_SRING_SETUP_RING_MISC_CFG_FLAG_HOST_FW_SWAP_SET(*msg_word,
801 		!!(srng_params.flags & HAL_SRNG_RING_PTR_SWAP));
802 
803 	/* word 4 */
804 	msg_word++;
805 	*msg_word = 0;
806 	HTT_SRING_SETUP_HEAD_OFFSET32_REMOTE_BASE_ADDR_LO_SET(*msg_word,
807 		hp_addr & 0xffffffff);
808 
809 	/* word 5 */
810 	msg_word++;
811 	*msg_word = 0;
812 	HTT_SRING_SETUP_HEAD_OFFSET32_REMOTE_BASE_ADDR_HI_SET(*msg_word,
813 		(uint64_t)hp_addr >> 32);
814 
815 	/* word 6 */
816 	msg_word++;
817 	*msg_word = 0;
818 	HTT_SRING_SETUP_TAIL_OFFSET32_REMOTE_BASE_ADDR_LO_SET(*msg_word,
819 		tp_addr & 0xffffffff);
820 
821 	/* word 7 */
822 	msg_word++;
823 	*msg_word = 0;
824 	HTT_SRING_SETUP_TAIL_OFFSET32_REMOTE_BASE_ADDR_HI_SET(*msg_word,
825 		(uint64_t)tp_addr >> 32);
826 
827 	/* word 8 */
828 	msg_word++;
829 	*msg_word = 0;
830 	HTT_SRING_SETUP_RING_MSI_ADDR_LO_SET(*msg_word,
831 		srng_params.msi_addr & 0xffffffff);
832 
833 	/* word 9 */
834 	msg_word++;
835 	*msg_word = 0;
836 	HTT_SRING_SETUP_RING_MSI_ADDR_HI_SET(*msg_word,
837 		(uint64_t)(srng_params.msi_addr) >> 32);
838 
839 	/* word 10 */
840 	msg_word++;
841 	*msg_word = 0;
842 	HTT_SRING_SETUP_RING_MSI_DATA_SET(*msg_word,
843 		qdf_cpu_to_le32(srng_params.msi_data));
844 
845 	/* word 11 */
846 	msg_word++;
847 	*msg_word = 0;
848 	HTT_SRING_SETUP_INTR_BATCH_COUNTER_TH_SET(*msg_word,
849 		srng_params.intr_batch_cntr_thres_entries *
850 		ring_entry_size);
851 	HTT_SRING_SETUP_INTR_TIMER_TH_SET(*msg_word,
852 		srng_params.intr_timer_thres_us >> 3);
853 
854 	/* word 12 */
855 	msg_word++;
856 	*msg_word = 0;
857 	if (srng_params.flags & HAL_SRNG_LOW_THRES_INTR_ENABLE) {
858 		/* TODO: Setting low threshold to 1/8th of ring size - see
859 		 * if this needs to be configurable
860 		 */
861 		HTT_SRING_SETUP_INTR_LOW_TH_SET(*msg_word,
862 			srng_params.low_threshold);
863 	}
864 	/* "response_required" field should be set if a HTT response message is
865 	 * required after setting up the ring.
866 	 */
867 	pkt = htt_htc_pkt_alloc(soc);
868 	if (!pkt) {
869 		dp_err("pkt alloc failed, ring_type %d ring_id %d htt_ring_id %d",
870 		       hal_ring_type, srng_params.ring_id, htt_ring_id);
871 		goto fail1;
872 	}
873 
874 	pkt->soc_ctxt = NULL; /* not used during send-done callback */
875 
876 	SET_HTC_PACKET_INFO_TX(
877 		&pkt->htc_pkt,
878 		dp_htt_h2t_send_complete_free_netbuf,
879 		qdf_nbuf_data(htt_msg),
880 		qdf_nbuf_len(htt_msg),
881 		soc->htc_endpoint,
882 		HTC_TX_PACKET_TAG_RUNTIME_PUT); /* tag for no FW response msg */
883 
884 	SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, htt_msg);
885 	status = DP_HTT_SEND_HTC_PKT(soc, pkt, HTT_H2T_MSG_TYPE_SRING_SETUP,
886 				     htt_logger_bufp);
887 
888 	if (status != QDF_STATUS_SUCCESS) {
889 		qdf_nbuf_free(htt_msg);
890 		htt_htc_pkt_free(soc, pkt);
891 	}
892 
893 	return status;
894 
895 fail1:
896 	qdf_nbuf_free(htt_msg);
897 fail0:
898 	return QDF_STATUS_E_FAILURE;
899 }
900 
901 qdf_export_symbol(htt_srng_setup);
902 
903 #ifdef QCA_SUPPORT_FULL_MON
904 /**
905  * htt_h2t_full_mon_cfg() - Send full monitor configuration msg to FW
906  *
907  * @htt_soc: HTT Soc handle
908  * @pdev_id: Radio id
909  * @config: enabled/disable configuration
910  *
911  * Return: Success when HTT message is sent, error on failure
912  */
913 int htt_h2t_full_mon_cfg(struct htt_soc *htt_soc,
914 			 uint8_t pdev_id,
915 			 enum dp_full_mon_config config)
916 {
917 	struct htt_soc *soc = (struct htt_soc *)htt_soc;
918 	struct dp_htt_htc_pkt *pkt;
919 	qdf_nbuf_t htt_msg;
920 	uint32_t *msg_word;
921 	uint8_t *htt_logger_bufp;
922 	QDF_STATUS status;
923 
924 	htt_msg = qdf_nbuf_alloc(soc->osdev,
925 				 HTT_MSG_BUF_SIZE(
926 				 HTT_RX_FULL_MONITOR_MODE_SETUP_SZ),
927 				 /* reserve room for the HTC header */
928 				 HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING,
929 				 4,
930 				 TRUE);
931 	if (!htt_msg)
932 		return QDF_STATUS_E_FAILURE;
933 
934 	/*
935 	 * Set the length of the message.
936 	 * The contribution from the HTC_HDR_ALIGNMENT_PADDING is added
937 	 * separately during the below call to qdf_nbuf_push_head.
938 	 * The contribution from the HTC header is added separately inside HTC.
939 	 */
940 	if (!qdf_nbuf_put_tail(htt_msg, HTT_RX_FULL_MONITOR_MODE_SETUP_SZ)) {
941 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
942 			  "%s: Failed to expand head for RX Ring Cfg msg",
943 			  __func__);
944 		goto fail1;
945 	}
946 
947 	msg_word = (uint32_t *)qdf_nbuf_data(htt_msg);
948 
949 	/* rewind beyond alignment pad to get to the HTC header reserved area */
950 	qdf_nbuf_push_head(htt_msg, HTC_HDR_ALIGNMENT_PADDING);
951 
952 	/* word 0 */
953 	*msg_word = 0;
954 	htt_logger_bufp = (uint8_t *)msg_word;
955 	HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_RX_FULL_MONITOR_MODE);
956 	HTT_RX_FULL_MONITOR_MODE_OPERATION_PDEV_ID_SET(
957 			*msg_word, DP_SW2HW_MACID(pdev_id));
958 
959 	msg_word++;
960 	*msg_word = 0;
961 	/* word 1 */
962 	if (config == DP_FULL_MON_ENABLE) {
963 		HTT_RX_FULL_MONITOR_MODE_ENABLE_SET(*msg_word, true);
964 		HTT_RX_FULL_MONITOR_MODE_ZERO_MPDU_SET(*msg_word, true);
965 		HTT_RX_FULL_MONITOR_MODE_NON_ZERO_MPDU_SET(*msg_word, true);
966 		HTT_RX_FULL_MONITOR_MODE_RELEASE_RINGS_SET(*msg_word, 0x2);
967 	} else if (config == DP_FULL_MON_DISABLE) {
968 		/* As per MAC team's suggestion, While disabling full monitor
969 		 * mode, Set 'en' bit to true in full monitor mode register.
970 		 */
971 		HTT_RX_FULL_MONITOR_MODE_ENABLE_SET(*msg_word, true);
972 		HTT_RX_FULL_MONITOR_MODE_ZERO_MPDU_SET(*msg_word, false);
973 		HTT_RX_FULL_MONITOR_MODE_NON_ZERO_MPDU_SET(*msg_word, false);
974 		HTT_RX_FULL_MONITOR_MODE_RELEASE_RINGS_SET(*msg_word, 0x2);
975 	}
976 
977 	pkt = htt_htc_pkt_alloc(soc);
978 	if (!pkt) {
979 		qdf_err("HTC packet allocation failed");
980 		goto fail1;
981 	}
982 
983 	pkt->soc_ctxt = NULL; /* not used during send-done callback */
984 
985 	SET_HTC_PACKET_INFO_TX(
986 		&pkt->htc_pkt,
987 		dp_htt_h2t_send_complete_free_netbuf,
988 		qdf_nbuf_data(htt_msg),
989 		qdf_nbuf_len(htt_msg),
990 		soc->htc_endpoint,
991 		HTC_TX_PACKET_TAG_RUNTIME_PUT); /* tag for no FW response msg */
992 
993 	SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, htt_msg);
994 	qdf_debug("config: %d", config);
995 	status = DP_HTT_SEND_HTC_PKT(soc, pkt,
996 				     HTT_H2T_MSG_TYPE_RX_FULL_MONITOR_MODE,
997 				     htt_logger_bufp);
998 
999 	if (status != QDF_STATUS_SUCCESS) {
1000 		qdf_nbuf_free(htt_msg);
1001 		htt_htc_pkt_free(soc, pkt);
1002 	}
1003 
1004 	return status;
1005 fail1:
1006 	qdf_nbuf_free(htt_msg);
1007 	return QDF_STATUS_E_FAILURE;
1008 }
1009 
1010 qdf_export_symbol(htt_h2t_full_mon_cfg);
1011 #else
1012 int htt_h2t_full_mon_cfg(struct htt_soc *htt_soc,
1013 			 uint8_t pdev_id,
1014 			 enum dp_full_mon_config config)
1015 {
1016 	return 0;
1017 }
1018 
1019 qdf_export_symbol(htt_h2t_full_mon_cfg);
1020 #endif
1021 
1022 #ifdef QCA_UNDECODED_METADATA_SUPPORT
1023 static inline void
1024 dp_mon_rx_enable_phy_errors(uint32_t *msg_word,
1025 			    struct htt_rx_ring_tlv_filter *htt_tlv_filter)
1026 {
1027 	if (htt_tlv_filter->phy_err_filter_valid) {
1028 		HTT_RX_RING_SELECTION_CFG_FP_PHY_ERR_SET
1029 			(*msg_word, htt_tlv_filter->fp_phy_err);
1030 		HTT_RX_RING_SELECTION_CFG_FP_PHY_ERR_BUF_SRC_SET
1031 			(*msg_word, htt_tlv_filter->fp_phy_err_buf_src);
1032 		HTT_RX_RING_SELECTION_CFG_FP_PHY_ERR_BUF_DEST_SET
1033 			(*msg_word, htt_tlv_filter->fp_phy_err_buf_dest);
1034 
1035 		/* word 12*/
1036 		msg_word++;
1037 		*msg_word = 0;
1038 		HTT_RX_RING_SELECTION_CFG_PHY_ERR_MASK_SET
1039 			(*msg_word, htt_tlv_filter->phy_err_mask);
1040 
1041 		/* word 13*/
1042 		msg_word++;
1043 		*msg_word = 0;
1044 		HTT_RX_RING_SELECTION_CFG_PHY_ERR_MASK_CONT_SET
1045 			(*msg_word, htt_tlv_filter->phy_err_mask_cont);
1046 	}
1047 }
1048 #else
1049 static inline void
1050 dp_mon_rx_enable_phy_errors(uint32_t *msg_word,
1051 			    struct htt_rx_ring_tlv_filter *htt_tlv_filter)
1052 {
1053 }
1054 #endif
1055 
1056 int htt_h2t_rx_ring_cfg(struct htt_soc *htt_soc, int pdev_id,
1057 			hal_ring_handle_t hal_ring_hdl,
1058 			int hal_ring_type, int ring_buf_size,
1059 			struct htt_rx_ring_tlv_filter *htt_tlv_filter)
1060 {
1061 	struct htt_soc *soc = (struct htt_soc *)htt_soc;
1062 	struct dp_htt_htc_pkt *pkt;
1063 	qdf_nbuf_t htt_msg;
1064 	uint32_t *msg_word;
1065 	uint32_t *msg_word_data;
1066 	struct hal_srng_params srng_params;
1067 	uint32_t htt_ring_type, htt_ring_id;
1068 	uint32_t tlv_filter;
1069 	uint8_t *htt_logger_bufp;
1070 	struct wlan_cfg_dp_soc_ctxt *wlan_cfg_ctx = soc->dp_soc->wlan_cfg_ctx;
1071 	uint32_t mon_drop_th = wlan_cfg_get_mon_drop_thresh(wlan_cfg_ctx);
1072 	int target_pdev_id;
1073 	QDF_STATUS status;
1074 
1075 	htt_msg = qdf_nbuf_alloc(soc->osdev,
1076 		HTT_MSG_BUF_SIZE(HTT_RX_RING_SELECTION_CFG_SZ),
1077 	/* reserve room for the HTC header */
1078 	HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, TRUE);
1079 	if (!htt_msg) {
1080 		dp_err("htt_msg alloc failed ring type %d", hal_ring_type);
1081 		goto fail0;
1082 	}
1083 
1084 	hal_get_srng_params(soc->hal_soc, hal_ring_hdl, &srng_params);
1085 
1086 	switch (hal_ring_type) {
1087 	case RXDMA_BUF:
1088 		htt_ring_id = HTT_RXDMA_HOST_BUF_RING;
1089 		htt_ring_type = HTT_SW_TO_HW_RING;
1090 		break;
1091 	case RXDMA_MONITOR_BUF:
1092 		htt_ring_id = dp_htt_get_mon_htt_ring_id(soc->dp_soc,
1093 							 RXDMA_MONITOR_BUF);
1094 		htt_ring_type = HTT_SW_TO_HW_RING;
1095 		break;
1096 	case RXDMA_MONITOR_STATUS:
1097 		htt_ring_id = HTT_RXDMA_MONITOR_STATUS_RING;
1098 		htt_ring_type = HTT_SW_TO_HW_RING;
1099 		break;
1100 	case RXDMA_MONITOR_DST:
1101 		htt_ring_id = dp_htt_get_mon_htt_ring_id(soc->dp_soc,
1102 							 RXDMA_MONITOR_DST);
1103 		htt_ring_type = HTT_HW_TO_SW_RING;
1104 		break;
1105 	case RXDMA_MONITOR_DESC:
1106 		htt_ring_id = HTT_RXDMA_MONITOR_DESC_RING;
1107 		htt_ring_type = HTT_SW_TO_HW_RING;
1108 		break;
1109 	case RXDMA_DST:
1110 		htt_ring_id = HTT_RXDMA_NON_MONITOR_DEST_RING;
1111 		htt_ring_type = HTT_HW_TO_SW_RING;
1112 		break;
1113 
1114 	default:
1115 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1116 			"%s: Ring currently not supported", __func__);
1117 		goto fail1;
1118 	}
1119 
1120 	dp_info("ring_type %d ring_id %d htt_ring_id %d",
1121 		hal_ring_type, srng_params.ring_id, htt_ring_id);
1122 
1123 	/*
1124 	 * Set the length of the message.
1125 	 * The contribution from the HTC_HDR_ALIGNMENT_PADDING is added
1126 	 * separately during the below call to qdf_nbuf_push_head.
1127 	 * The contribution from the HTC header is added separately inside HTC.
1128 	 */
1129 	if (qdf_nbuf_put_tail(htt_msg, HTT_RX_RING_SELECTION_CFG_SZ) == NULL) {
1130 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1131 			"%s: Failed to expand head for RX Ring Cfg msg",
1132 			__func__);
1133 		goto fail1; /* failure */
1134 	}
1135 
1136 	msg_word = (uint32_t *)qdf_nbuf_data(htt_msg);
1137 
1138 	/* rewind beyond alignment pad to get to the HTC header reserved area */
1139 	qdf_nbuf_push_head(htt_msg, HTC_HDR_ALIGNMENT_PADDING);
1140 
1141 	/* word 0 */
1142 	htt_logger_bufp = (uint8_t *)msg_word;
1143 	*msg_word = 0;
1144 	HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_RX_RING_SELECTION_CFG);
1145 
1146 	/* applicable only for post Li */
1147 	dp_rx_mon_enable(soc->dp_soc, msg_word, htt_tlv_filter);
1148 
1149 	/*
1150 	 * pdev_id is indexed from 0 whereas mac_id is indexed from 1
1151 	 * SW_TO_SW and SW_TO_HW rings are unaffected by this
1152 	 */
1153 	target_pdev_id =
1154 	dp_get_target_pdev_id_for_host_pdev_id(soc->dp_soc, pdev_id);
1155 
1156 	if (htt_ring_type == HTT_SW_TO_SW_RING ||
1157 			htt_ring_type == HTT_SW_TO_HW_RING ||
1158 			htt_ring_type == HTT_HW_TO_SW_RING)
1159 		HTT_RX_RING_SELECTION_CFG_PDEV_ID_SET(*msg_word,
1160 						      target_pdev_id);
1161 
1162 	/* TODO: Discuss with FW on changing this to unique ID and using
1163 	 * htt_ring_type to send the type of ring
1164 	 */
1165 	HTT_RX_RING_SELECTION_CFG_RING_ID_SET(*msg_word, htt_ring_id);
1166 
1167 	HTT_RX_RING_SELECTION_CFG_STATUS_TLV_SET(*msg_word,
1168 		!!(srng_params.flags & HAL_SRNG_MSI_SWAP));
1169 
1170 	HTT_RX_RING_SELECTION_CFG_RX_OFFSETS_VALID_SET(*msg_word,
1171 						htt_tlv_filter->offset_valid);
1172 
1173 	if (mon_drop_th > 0)
1174 		HTT_RX_RING_SELECTION_CFG_DROP_THRESHOLD_VALID_SET(*msg_word,
1175 								   1);
1176 	else
1177 		HTT_RX_RING_SELECTION_CFG_DROP_THRESHOLD_VALID_SET(*msg_word,
1178 								   0);
1179 
1180 	/* word 1 */
1181 	msg_word++;
1182 	*msg_word = 0;
1183 	HTT_RX_RING_SELECTION_CFG_RING_BUFFER_SIZE_SET(*msg_word,
1184 		ring_buf_size);
1185 
1186 	dp_mon_rx_packet_length_set(soc->dp_soc, msg_word, htt_tlv_filter);
1187 	dp_mon_rx_hdr_length_set(soc->dp_soc, msg_word, htt_tlv_filter);
1188 	dp_mon_rx_mac_filter_set(soc->dp_soc, msg_word, htt_tlv_filter);
1189 
1190 	/* word 2 */
1191 	msg_word++;
1192 	*msg_word = 0;
1193 
1194 	if (htt_tlv_filter->enable_fp) {
1195 		/* TYPE: MGMT */
1196 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0,
1197 			FP, MGMT, 0000,
1198 			(htt_tlv_filter->fp_mgmt_filter &
1199 			FILTER_MGMT_ASSOC_REQ) ? 1 : 0);
1200 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0,
1201 			FP, MGMT, 0001,
1202 			(htt_tlv_filter->fp_mgmt_filter &
1203 			FILTER_MGMT_ASSOC_RES) ? 1 : 0);
1204 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0,
1205 			FP, MGMT, 0010,
1206 			(htt_tlv_filter->fp_mgmt_filter &
1207 			FILTER_MGMT_REASSOC_REQ) ? 1 : 0);
1208 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0,
1209 			FP, MGMT, 0011,
1210 			(htt_tlv_filter->fp_mgmt_filter &
1211 			FILTER_MGMT_REASSOC_RES) ? 1 : 0);
1212 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0,
1213 			FP, MGMT, 0100,
1214 			(htt_tlv_filter->fp_mgmt_filter &
1215 			FILTER_MGMT_PROBE_REQ) ? 1 : 0);
1216 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0,
1217 			FP, MGMT, 0101,
1218 			(htt_tlv_filter->fp_mgmt_filter &
1219 			FILTER_MGMT_PROBE_RES) ? 1 : 0);
1220 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0,
1221 			FP, MGMT, 0110,
1222 			(htt_tlv_filter->fp_mgmt_filter &
1223 			FILTER_MGMT_TIM_ADVT) ? 1 : 0);
1224 		/* reserved */
1225 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, FP,
1226 			MGMT, 0111,
1227 			(htt_tlv_filter->fp_mgmt_filter &
1228 			FILTER_MGMT_RESERVED_7) ? 1 : 0);
1229 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0,
1230 			FP, MGMT, 1000,
1231 			(htt_tlv_filter->fp_mgmt_filter &
1232 			FILTER_MGMT_BEACON) ? 1 : 0);
1233 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0,
1234 			FP, MGMT, 1001,
1235 			(htt_tlv_filter->fp_mgmt_filter &
1236 			FILTER_MGMT_ATIM) ? 1 : 0);
1237 	}
1238 
1239 	if (htt_tlv_filter->enable_md) {
1240 			/* TYPE: MGMT */
1241 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0,
1242 			MD, MGMT, 0000,
1243 			(htt_tlv_filter->md_mgmt_filter &
1244 			FILTER_MGMT_ASSOC_REQ) ? 1 : 0);
1245 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0,
1246 			MD, MGMT, 0001,
1247 			(htt_tlv_filter->md_mgmt_filter &
1248 			FILTER_MGMT_ASSOC_RES) ? 1 : 0);
1249 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0,
1250 			MD, MGMT, 0010,
1251 			(htt_tlv_filter->md_mgmt_filter &
1252 			FILTER_MGMT_REASSOC_REQ) ? 1 : 0);
1253 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0,
1254 			MD, MGMT, 0011,
1255 			(htt_tlv_filter->md_mgmt_filter &
1256 			FILTER_MGMT_REASSOC_RES) ? 1 : 0);
1257 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0,
1258 			MD, MGMT, 0100,
1259 			(htt_tlv_filter->md_mgmt_filter &
1260 			FILTER_MGMT_PROBE_REQ) ? 1 : 0);
1261 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0,
1262 			MD, MGMT, 0101,
1263 			(htt_tlv_filter->md_mgmt_filter &
1264 			FILTER_MGMT_PROBE_RES) ? 1 : 0);
1265 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0,
1266 			MD, MGMT, 0110,
1267 			(htt_tlv_filter->md_mgmt_filter &
1268 			FILTER_MGMT_TIM_ADVT) ? 1 : 0);
1269 		/* reserved */
1270 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, MD,
1271 			MGMT, 0111,
1272 			(htt_tlv_filter->md_mgmt_filter &
1273 			FILTER_MGMT_RESERVED_7) ? 1 : 0);
1274 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0,
1275 			MD, MGMT, 1000,
1276 			(htt_tlv_filter->md_mgmt_filter &
1277 			FILTER_MGMT_BEACON) ? 1 : 0);
1278 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0,
1279 			MD, MGMT, 1001,
1280 			(htt_tlv_filter->md_mgmt_filter &
1281 			FILTER_MGMT_ATIM) ? 1 : 0);
1282 	}
1283 
1284 	if (htt_tlv_filter->enable_mo) {
1285 		/* TYPE: MGMT */
1286 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0,
1287 			MO, MGMT, 0000,
1288 			(htt_tlv_filter->mo_mgmt_filter &
1289 			FILTER_MGMT_ASSOC_REQ) ? 1 : 0);
1290 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0,
1291 			MO, MGMT, 0001,
1292 			(htt_tlv_filter->mo_mgmt_filter &
1293 			FILTER_MGMT_ASSOC_RES) ? 1 : 0);
1294 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0,
1295 			MO, MGMT, 0010,
1296 			(htt_tlv_filter->mo_mgmt_filter &
1297 			FILTER_MGMT_REASSOC_REQ) ? 1 : 0);
1298 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0,
1299 			MO, MGMT, 0011,
1300 			(htt_tlv_filter->mo_mgmt_filter &
1301 			FILTER_MGMT_REASSOC_RES) ? 1 : 0);
1302 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0,
1303 			MO, MGMT, 0100,
1304 			(htt_tlv_filter->mo_mgmt_filter &
1305 			FILTER_MGMT_PROBE_REQ) ? 1 : 0);
1306 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0,
1307 			MO, MGMT, 0101,
1308 			(htt_tlv_filter->mo_mgmt_filter &
1309 			FILTER_MGMT_PROBE_RES) ? 1 : 0);
1310 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0,
1311 			MO, MGMT, 0110,
1312 			(htt_tlv_filter->mo_mgmt_filter &
1313 			FILTER_MGMT_TIM_ADVT) ? 1 : 0);
1314 		/* reserved */
1315 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, MO,
1316 			MGMT, 0111,
1317 			(htt_tlv_filter->mo_mgmt_filter &
1318 			FILTER_MGMT_RESERVED_7) ? 1 : 0);
1319 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0,
1320 			MO, MGMT, 1000,
1321 			(htt_tlv_filter->mo_mgmt_filter &
1322 			FILTER_MGMT_BEACON) ? 1 : 0);
1323 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0,
1324 			MO, MGMT, 1001,
1325 			(htt_tlv_filter->mo_mgmt_filter &
1326 			FILTER_MGMT_ATIM) ? 1 : 0);
1327 	}
1328 
1329 	/* word 3 */
1330 	msg_word++;
1331 	*msg_word = 0;
1332 
1333 	if (htt_tlv_filter->enable_fp) {
1334 		/* TYPE: MGMT */
1335 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1,
1336 			FP, MGMT, 1010,
1337 			(htt_tlv_filter->fp_mgmt_filter &
1338 			FILTER_MGMT_DISASSOC) ? 1 : 0);
1339 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1,
1340 			FP, MGMT, 1011,
1341 			(htt_tlv_filter->fp_mgmt_filter &
1342 			FILTER_MGMT_AUTH) ? 1 : 0);
1343 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1,
1344 			FP, MGMT, 1100,
1345 			(htt_tlv_filter->fp_mgmt_filter &
1346 			FILTER_MGMT_DEAUTH) ? 1 : 0);
1347 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1,
1348 			FP, MGMT, 1101,
1349 			(htt_tlv_filter->fp_mgmt_filter &
1350 			FILTER_MGMT_ACTION) ? 1 : 0);
1351 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1,
1352 			FP, MGMT, 1110,
1353 			(htt_tlv_filter->fp_mgmt_filter &
1354 			FILTER_MGMT_ACT_NO_ACK) ? 1 : 0);
1355 		/* reserved*/
1356 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1, FP,
1357 			MGMT, 1111,
1358 			(htt_tlv_filter->fp_mgmt_filter &
1359 			FILTER_MGMT_RESERVED_15) ? 1 : 0);
1360 	}
1361 
1362 	if (htt_tlv_filter->enable_md) {
1363 			/* TYPE: MGMT */
1364 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1,
1365 			MD, MGMT, 1010,
1366 			(htt_tlv_filter->md_mgmt_filter &
1367 			FILTER_MGMT_DISASSOC) ? 1 : 0);
1368 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1,
1369 			MD, MGMT, 1011,
1370 			(htt_tlv_filter->md_mgmt_filter &
1371 			FILTER_MGMT_AUTH) ? 1 : 0);
1372 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1,
1373 			MD, MGMT, 1100,
1374 			(htt_tlv_filter->md_mgmt_filter &
1375 			FILTER_MGMT_DEAUTH) ? 1 : 0);
1376 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1,
1377 			MD, MGMT, 1101,
1378 			(htt_tlv_filter->md_mgmt_filter &
1379 			FILTER_MGMT_ACTION) ? 1 : 0);
1380 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1,
1381 			MD, MGMT, 1110,
1382 			(htt_tlv_filter->md_mgmt_filter &
1383 			FILTER_MGMT_ACT_NO_ACK) ? 1 : 0);
1384 	}
1385 
1386 	if (htt_tlv_filter->enable_mo) {
1387 		/* TYPE: MGMT */
1388 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1,
1389 			MO, MGMT, 1010,
1390 			(htt_tlv_filter->mo_mgmt_filter &
1391 			FILTER_MGMT_DISASSOC) ? 1 : 0);
1392 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1,
1393 			MO, MGMT, 1011,
1394 			(htt_tlv_filter->mo_mgmt_filter &
1395 			FILTER_MGMT_AUTH) ? 1 : 0);
1396 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1,
1397 			MO, MGMT, 1100,
1398 			(htt_tlv_filter->mo_mgmt_filter &
1399 			FILTER_MGMT_DEAUTH) ? 1 : 0);
1400 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1,
1401 			MO, MGMT, 1101,
1402 			(htt_tlv_filter->mo_mgmt_filter &
1403 			FILTER_MGMT_ACTION) ? 1 : 0);
1404 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1,
1405 			MO, MGMT, 1110,
1406 			(htt_tlv_filter->mo_mgmt_filter &
1407 			FILTER_MGMT_ACT_NO_ACK) ? 1 : 0);
1408 		/* reserved*/
1409 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1, MO,
1410 			MGMT, 1111,
1411 			(htt_tlv_filter->mo_mgmt_filter &
1412 			FILTER_MGMT_RESERVED_15) ? 1 : 0);
1413 	}
1414 
1415 	/* word 4 */
1416 	msg_word++;
1417 	*msg_word = 0;
1418 
1419 	if (htt_tlv_filter->enable_fp) {
1420 		/* TYPE: CTRL */
1421 		/* reserved */
1422 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, FP,
1423 			CTRL, 0000,
1424 			(htt_tlv_filter->fp_ctrl_filter &
1425 			FILTER_CTRL_RESERVED_1) ? 1 : 0);
1426 		/* reserved */
1427 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, FP,
1428 			CTRL, 0001,
1429 			(htt_tlv_filter->fp_ctrl_filter &
1430 			FILTER_CTRL_RESERVED_2) ? 1 : 0);
1431 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, FP,
1432 			CTRL, 0010,
1433 			(htt_tlv_filter->fp_ctrl_filter &
1434 			FILTER_CTRL_TRIGGER) ? 1 : 0);
1435 		/* reserved */
1436 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, FP,
1437 			CTRL, 0011,
1438 			(htt_tlv_filter->fp_ctrl_filter &
1439 			FILTER_CTRL_RESERVED_4) ? 1 : 0);
1440 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, FP,
1441 			CTRL, 0100,
1442 			(htt_tlv_filter->fp_ctrl_filter &
1443 			FILTER_CTRL_BF_REP_POLL) ? 1 : 0);
1444 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, FP,
1445 			CTRL, 0101,
1446 			(htt_tlv_filter->fp_ctrl_filter &
1447 			FILTER_CTRL_VHT_NDP) ? 1 : 0);
1448 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, FP,
1449 			CTRL, 0110,
1450 			(htt_tlv_filter->fp_ctrl_filter &
1451 			FILTER_CTRL_FRAME_EXT) ? 1 : 0);
1452 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, FP,
1453 			CTRL, 0111,
1454 			(htt_tlv_filter->fp_ctrl_filter &
1455 			FILTER_CTRL_CTRLWRAP) ? 1 : 0);
1456 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, FP,
1457 			CTRL, 1000,
1458 			(htt_tlv_filter->fp_ctrl_filter &
1459 			FILTER_CTRL_BA_REQ) ? 1 : 0);
1460 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, FP,
1461 			CTRL, 1001,
1462 			(htt_tlv_filter->fp_ctrl_filter &
1463 			FILTER_CTRL_BA) ? 1 : 0);
1464 	}
1465 
1466 	if (htt_tlv_filter->enable_md) {
1467 		/* TYPE: CTRL */
1468 		/* reserved */
1469 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MD,
1470 			CTRL, 0000,
1471 			(htt_tlv_filter->md_ctrl_filter &
1472 			FILTER_CTRL_RESERVED_1) ? 1 : 0);
1473 		/* reserved */
1474 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MD,
1475 			CTRL, 0001,
1476 			(htt_tlv_filter->md_ctrl_filter &
1477 			FILTER_CTRL_RESERVED_2) ? 1 : 0);
1478 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MD,
1479 			CTRL, 0010,
1480 			(htt_tlv_filter->md_ctrl_filter &
1481 			FILTER_CTRL_TRIGGER) ? 1 : 0);
1482 		/* reserved */
1483 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MD,
1484 			CTRL, 0011,
1485 			(htt_tlv_filter->md_ctrl_filter &
1486 			FILTER_CTRL_RESERVED_4) ? 1 : 0);
1487 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MD,
1488 			CTRL, 0100,
1489 			(htt_tlv_filter->md_ctrl_filter &
1490 			FILTER_CTRL_BF_REP_POLL) ? 1 : 0);
1491 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MD,
1492 			CTRL, 0101,
1493 			(htt_tlv_filter->md_ctrl_filter &
1494 			FILTER_CTRL_VHT_NDP) ? 1 : 0);
1495 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MD,
1496 			CTRL, 0110,
1497 			(htt_tlv_filter->md_ctrl_filter &
1498 			FILTER_CTRL_FRAME_EXT) ? 1 : 0);
1499 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MD,
1500 			CTRL, 0111,
1501 			(htt_tlv_filter->md_ctrl_filter &
1502 			FILTER_CTRL_CTRLWRAP) ? 1 : 0);
1503 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MD,
1504 			CTRL, 1000,
1505 			(htt_tlv_filter->md_ctrl_filter &
1506 			FILTER_CTRL_BA_REQ) ? 1 : 0);
1507 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MD,
1508 			CTRL, 1001,
1509 			(htt_tlv_filter->md_ctrl_filter &
1510 			FILTER_CTRL_BA) ? 1 : 0);
1511 	}
1512 
1513 	if (htt_tlv_filter->enable_mo) {
1514 		/* TYPE: CTRL */
1515 		/* reserved */
1516 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MO,
1517 			CTRL, 0000,
1518 			(htt_tlv_filter->mo_ctrl_filter &
1519 			FILTER_CTRL_RESERVED_1) ? 1 : 0);
1520 		/* reserved */
1521 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MO,
1522 			CTRL, 0001,
1523 			(htt_tlv_filter->mo_ctrl_filter &
1524 			FILTER_CTRL_RESERVED_2) ? 1 : 0);
1525 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MO,
1526 			CTRL, 0010,
1527 			(htt_tlv_filter->mo_ctrl_filter &
1528 			FILTER_CTRL_TRIGGER) ? 1 : 0);
1529 		/* reserved */
1530 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MO,
1531 			CTRL, 0011,
1532 			(htt_tlv_filter->mo_ctrl_filter &
1533 			FILTER_CTRL_RESERVED_4) ? 1 : 0);
1534 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MO,
1535 			CTRL, 0100,
1536 			(htt_tlv_filter->mo_ctrl_filter &
1537 			FILTER_CTRL_BF_REP_POLL) ? 1 : 0);
1538 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MO,
1539 			CTRL, 0101,
1540 			(htt_tlv_filter->mo_ctrl_filter &
1541 			FILTER_CTRL_VHT_NDP) ? 1 : 0);
1542 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MO,
1543 			CTRL, 0110,
1544 			(htt_tlv_filter->mo_ctrl_filter &
1545 			FILTER_CTRL_FRAME_EXT) ? 1 : 0);
1546 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MO,
1547 			CTRL, 0111,
1548 			(htt_tlv_filter->mo_ctrl_filter &
1549 			FILTER_CTRL_CTRLWRAP) ? 1 : 0);
1550 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MO,
1551 			CTRL, 1000,
1552 			(htt_tlv_filter->mo_ctrl_filter &
1553 			FILTER_CTRL_BA_REQ) ? 1 : 0);
1554 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MO,
1555 			CTRL, 1001,
1556 			(htt_tlv_filter->mo_ctrl_filter &
1557 			FILTER_CTRL_BA) ? 1 : 0);
1558 	}
1559 
1560 	/* word 5 */
1561 	msg_word++;
1562 	*msg_word = 0;
1563 	if (htt_tlv_filter->enable_fp) {
1564 		/* TYPE: CTRL */
1565 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, FP,
1566 			CTRL, 1010,
1567 			(htt_tlv_filter->fp_ctrl_filter &
1568 			FILTER_CTRL_PSPOLL) ? 1 : 0);
1569 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, FP,
1570 			CTRL, 1011,
1571 			(htt_tlv_filter->fp_ctrl_filter &
1572 			FILTER_CTRL_RTS) ? 1 : 0);
1573 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, FP,
1574 			CTRL, 1100,
1575 			(htt_tlv_filter->fp_ctrl_filter &
1576 			FILTER_CTRL_CTS) ? 1 : 0);
1577 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, FP,
1578 			CTRL, 1101,
1579 			(htt_tlv_filter->fp_ctrl_filter &
1580 			FILTER_CTRL_ACK) ? 1 : 0);
1581 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, FP,
1582 			CTRL, 1110,
1583 			(htt_tlv_filter->fp_ctrl_filter &
1584 			FILTER_CTRL_CFEND) ? 1 : 0);
1585 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, FP,
1586 			CTRL, 1111,
1587 			(htt_tlv_filter->fp_ctrl_filter &
1588 			FILTER_CTRL_CFEND_CFACK) ? 1 : 0);
1589 		/* TYPE: DATA */
1590 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, FP,
1591 			DATA, MCAST,
1592 			(htt_tlv_filter->fp_data_filter &
1593 			FILTER_DATA_MCAST) ? 1 : 0);
1594 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, FP,
1595 			DATA, UCAST,
1596 			(htt_tlv_filter->fp_data_filter &
1597 			FILTER_DATA_UCAST) ? 1 : 0);
1598 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, FP,
1599 			DATA, NULL,
1600 			(htt_tlv_filter->fp_data_filter &
1601 			FILTER_DATA_NULL) ? 1 : 0);
1602 	}
1603 
1604 	if (htt_tlv_filter->enable_md) {
1605 		/* TYPE: CTRL */
1606 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MD,
1607 			CTRL, 1010,
1608 			(htt_tlv_filter->md_ctrl_filter &
1609 			FILTER_CTRL_PSPOLL) ? 1 : 0);
1610 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MD,
1611 			CTRL, 1011,
1612 			(htt_tlv_filter->md_ctrl_filter &
1613 			FILTER_CTRL_RTS) ? 1 : 0);
1614 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MD,
1615 			CTRL, 1100,
1616 			(htt_tlv_filter->md_ctrl_filter &
1617 			FILTER_CTRL_CTS) ? 1 : 0);
1618 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MD,
1619 			CTRL, 1101,
1620 			(htt_tlv_filter->md_ctrl_filter &
1621 			FILTER_CTRL_ACK) ? 1 : 0);
1622 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MD,
1623 			CTRL, 1110,
1624 			(htt_tlv_filter->md_ctrl_filter &
1625 			FILTER_CTRL_CFEND) ? 1 : 0);
1626 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MD,
1627 			CTRL, 1111,
1628 			(htt_tlv_filter->md_ctrl_filter &
1629 			FILTER_CTRL_CFEND_CFACK) ? 1 : 0);
1630 		/* TYPE: DATA */
1631 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MD,
1632 			DATA, MCAST,
1633 			(htt_tlv_filter->md_data_filter &
1634 			FILTER_DATA_MCAST) ? 1 : 0);
1635 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MD,
1636 			DATA, UCAST,
1637 			(htt_tlv_filter->md_data_filter &
1638 			FILTER_DATA_UCAST) ? 1 : 0);
1639 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MD,
1640 			DATA, NULL,
1641 			(htt_tlv_filter->md_data_filter &
1642 			FILTER_DATA_NULL) ? 1 : 0);
1643 	}
1644 
1645 	if (htt_tlv_filter->enable_mo) {
1646 		/* TYPE: CTRL */
1647 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MO,
1648 			CTRL, 1010,
1649 			(htt_tlv_filter->mo_ctrl_filter &
1650 			FILTER_CTRL_PSPOLL) ? 1 : 0);
1651 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MO,
1652 			CTRL, 1011,
1653 			(htt_tlv_filter->mo_ctrl_filter &
1654 			FILTER_CTRL_RTS) ? 1 : 0);
1655 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MO,
1656 			CTRL, 1100,
1657 			(htt_tlv_filter->mo_ctrl_filter &
1658 			FILTER_CTRL_CTS) ? 1 : 0);
1659 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MO,
1660 			CTRL, 1101,
1661 			(htt_tlv_filter->mo_ctrl_filter &
1662 			FILTER_CTRL_ACK) ? 1 : 0);
1663 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MO,
1664 			CTRL, 1110,
1665 			(htt_tlv_filter->mo_ctrl_filter &
1666 			FILTER_CTRL_CFEND) ? 1 : 0);
1667 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MO,
1668 			CTRL, 1111,
1669 			(htt_tlv_filter->mo_ctrl_filter &
1670 			FILTER_CTRL_CFEND_CFACK) ? 1 : 0);
1671 		/* TYPE: DATA */
1672 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MO,
1673 			DATA, MCAST,
1674 			(htt_tlv_filter->mo_data_filter &
1675 			FILTER_DATA_MCAST) ? 1 : 0);
1676 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MO,
1677 			DATA, UCAST,
1678 			(htt_tlv_filter->mo_data_filter &
1679 			FILTER_DATA_UCAST) ? 1 : 0);
1680 		htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MO,
1681 			DATA, NULL,
1682 			(htt_tlv_filter->mo_data_filter &
1683 			FILTER_DATA_NULL) ? 1 : 0);
1684 	}
1685 
1686 	/* word 6 */
1687 	msg_word++;
1688 	*msg_word = 0;
1689 	tlv_filter = 0;
1690 	htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, MPDU_START,
1691 		htt_tlv_filter->mpdu_start);
1692 	htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, MSDU_START,
1693 		htt_tlv_filter->msdu_start);
1694 	htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, PACKET,
1695 		htt_tlv_filter->packet);
1696 	htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, MSDU_END,
1697 		htt_tlv_filter->msdu_end);
1698 	htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, MPDU_END,
1699 		htt_tlv_filter->mpdu_end);
1700 	htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, PACKET_HEADER,
1701 		htt_tlv_filter->packet_header);
1702 	htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, ATTENTION,
1703 		htt_tlv_filter->attention);
1704 	htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, PPDU_START,
1705 		htt_tlv_filter->ppdu_start);
1706 	htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, PPDU_END,
1707 		htt_tlv_filter->ppdu_end);
1708 	htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, PPDU_END_USER_STATS,
1709 		htt_tlv_filter->ppdu_end_user_stats);
1710 	htt_rx_ring_tlv_filter_in_enable_set(tlv_filter,
1711 		PPDU_END_USER_STATS_EXT,
1712 		htt_tlv_filter->ppdu_end_user_stats_ext);
1713 	htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, PPDU_END_STATUS_DONE,
1714 		htt_tlv_filter->ppdu_end_status_done);
1715 	htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, PPDU_START_USER_INFO,
1716 		htt_tlv_filter->ppdu_start_user_info);
1717 	/* RESERVED bit maps to header_per_msdu in htt_tlv_filter*/
1718 	 htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, RESERVED,
1719 		 htt_tlv_filter->header_per_msdu);
1720 
1721 	HTT_RX_RING_SELECTION_CFG_TLV_FILTER_IN_FLAG_SET(*msg_word, tlv_filter);
1722 
1723 	msg_word_data = (uint32_t *)qdf_nbuf_data(htt_msg);
1724 	dp_info("config_data: [0x%x][0x%x][0x%x][0x%x][0x%x][0x%x][0x%x]",
1725 		msg_word_data[0], msg_word_data[1], msg_word_data[2],
1726 		msg_word_data[3], msg_word_data[4], msg_word_data[5],
1727 		msg_word_data[6]);
1728 
1729 	/* word 7 */
1730 	msg_word++;
1731 	*msg_word = 0;
1732 	if (htt_tlv_filter->offset_valid) {
1733 		HTT_RX_RING_SELECTION_CFG_RX_PACKET_OFFSET_SET(*msg_word,
1734 					htt_tlv_filter->rx_packet_offset);
1735 		HTT_RX_RING_SELECTION_CFG_RX_HEADER_OFFSET_SET(*msg_word,
1736 					htt_tlv_filter->rx_header_offset);
1737 
1738 		/* word 8 */
1739 		msg_word++;
1740 		*msg_word = 0;
1741 		HTT_RX_RING_SELECTION_CFG_RX_MPDU_END_OFFSET_SET(*msg_word,
1742 					htt_tlv_filter->rx_mpdu_end_offset);
1743 		HTT_RX_RING_SELECTION_CFG_RX_MPDU_START_OFFSET_SET(*msg_word,
1744 					htt_tlv_filter->rx_mpdu_start_offset);
1745 
1746 		/* word 9 */
1747 		msg_word++;
1748 		*msg_word = 0;
1749 		HTT_RX_RING_SELECTION_CFG_RX_MSDU_END_OFFSET_SET(*msg_word,
1750 					htt_tlv_filter->rx_msdu_end_offset);
1751 		HTT_RX_RING_SELECTION_CFG_RX_MSDU_START_OFFSET_SET(*msg_word,
1752 					htt_tlv_filter->rx_msdu_start_offset);
1753 
1754 		/* word 10 */
1755 		msg_word++;
1756 		*msg_word = 0;
1757 		HTT_RX_RING_SELECTION_CFG_RX_ATTENTION_OFFSET_SET(*msg_word,
1758 					htt_tlv_filter->rx_attn_offset);
1759 
1760 		/* word 11 */
1761 		msg_word++;
1762 		*msg_word = 0;
1763 	} else {
1764 		/* word 11 */
1765 		msg_word += 4;
1766 		*msg_word = 0;
1767 	}
1768 
1769 	soc->dp_soc->arch_ops.dp_rx_word_mask_subscribe(
1770 						soc->dp_soc,
1771 						msg_word,
1772 						(void *)htt_tlv_filter);
1773 
1774 	dp_mon_rx_wmask_subscribe(soc->dp_soc, msg_word,
1775 				  pdev_id, htt_tlv_filter);
1776 
1777 	if (mon_drop_th > 0)
1778 		HTT_RX_RING_SELECTION_CFG_RX_DROP_THRESHOLD_SET(*msg_word,
1779 				mon_drop_th);
1780 
1781 	dp_mon_rx_enable_mpdu_logging(soc->dp_soc, msg_word, htt_tlv_filter);
1782 
1783 	dp_mon_rx_enable_phy_errors(msg_word, htt_tlv_filter);
1784 
1785 	/* word 14*/
1786 	msg_word += 3;
1787 
1788 	/* word 15*/
1789 	msg_word++;
1790 
1791 	/* word 16*/
1792 	msg_word++;
1793 	*msg_word = 0;
1794 
1795 	dp_mon_rx_enable_pkt_tlv_offset(soc->dp_soc, msg_word, htt_tlv_filter);
1796 
1797 	/* word 20 and 21*/
1798 	msg_word += 4;
1799 	*msg_word = 0;
1800 
1801 	dp_mon_rx_enable_fpmo(soc->dp_soc, msg_word, htt_tlv_filter);
1802 
1803 	/* "response_required" field should be set if a HTT response message is
1804 	 * required after setting up the ring.
1805 	 */
1806 	pkt = htt_htc_pkt_alloc(soc);
1807 	if (!pkt) {
1808 		dp_err("pkt alloc failed, ring_type %d ring_id %d htt_ring_id %d",
1809 		       hal_ring_type, srng_params.ring_id, htt_ring_id);
1810 		goto fail1;
1811 	}
1812 
1813 	pkt->soc_ctxt = NULL; /* not used during send-done callback */
1814 
1815 	SET_HTC_PACKET_INFO_TX(
1816 		&pkt->htc_pkt,
1817 		dp_htt_h2t_send_complete_free_netbuf,
1818 		qdf_nbuf_data(htt_msg),
1819 		qdf_nbuf_len(htt_msg),
1820 		soc->htc_endpoint,
1821 		HTC_TX_PACKET_TAG_RUNTIME_PUT); /* tag for no FW response msg */
1822 
1823 	SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, htt_msg);
1824 	status = DP_HTT_SEND_HTC_PKT(soc, pkt,
1825 				     HTT_H2T_MSG_TYPE_RX_RING_SELECTION_CFG,
1826 				     htt_logger_bufp);
1827 
1828 	if (status != QDF_STATUS_SUCCESS) {
1829 		qdf_nbuf_free(htt_msg);
1830 		htt_htc_pkt_free(soc, pkt);
1831 	}
1832 
1833 	return status;
1834 
1835 fail1:
1836 	qdf_nbuf_free(htt_msg);
1837 fail0:
1838 	return QDF_STATUS_E_FAILURE;
1839 }
1840 
1841 qdf_export_symbol(htt_h2t_rx_ring_cfg);
1842 
1843 #if defined(HTT_STATS_ENABLE)
1844 static inline QDF_STATUS dp_send_htt_stat_resp(struct htt_stats_context *htt_stats,
1845 					struct dp_soc *soc, qdf_nbuf_t htt_msg)
1846 
1847 {
1848 	uint32_t pdev_id;
1849 	uint32_t *msg_word = NULL;
1850 	uint32_t msg_remain_len = 0;
1851 
1852 	msg_word = (uint32_t *) qdf_nbuf_data(htt_msg);
1853 
1854 	/*COOKIE MSB*/
1855 	pdev_id = *(msg_word + 2) & HTT_PID_BIT_MASK;
1856 
1857 	/* stats message length + 16 size of HTT header*/
1858 	msg_remain_len = qdf_min(htt_stats->msg_len + 16,
1859 				(uint32_t)DP_EXT_MSG_LENGTH);
1860 
1861 	dp_wdi_event_handler(WDI_EVENT_HTT_STATS, soc,
1862 			msg_word,  msg_remain_len,
1863 			WDI_NO_VAL, pdev_id);
1864 
1865 	if (htt_stats->msg_len >= DP_EXT_MSG_LENGTH) {
1866 		htt_stats->msg_len -= DP_EXT_MSG_LENGTH;
1867 	}
1868 	/* Need to be freed here as WDI handler will
1869 	 * make a copy of pkt to send data to application
1870 	 */
1871 	qdf_nbuf_free(htt_msg);
1872 	return QDF_STATUS_SUCCESS;
1873 }
1874 #else
1875 static inline QDF_STATUS
1876 dp_send_htt_stat_resp(struct htt_stats_context *htt_stats,
1877 		      struct dp_soc *soc, qdf_nbuf_t htt_msg)
1878 {
1879 	return QDF_STATUS_E_NOSUPPORT;
1880 }
1881 #endif
1882 
1883 #ifdef HTT_STATS_DEBUGFS_SUPPORT
1884 /* dp_send_htt_stats_dbgfs_msg() - Function to send htt data to upper layer.
1885  * @pdev: dp pdev handle
1886  * @msg_word: HTT msg
1887  * @msg_len: Length of HTT msg sent
1888  *
1889  * Return: none
1890  */
1891 static inline void
1892 dp_htt_stats_dbgfs_send_msg(struct dp_pdev *pdev, uint32_t *msg_word,
1893 			    uint32_t msg_len)
1894 {
1895 	struct htt_dbgfs_cfg dbgfs_cfg;
1896 	int done = 0;
1897 
1898 	/* send 5th word of HTT msg to upper layer */
1899 	dbgfs_cfg.msg_word = (msg_word + 4);
1900 	dbgfs_cfg.m = pdev->dbgfs_cfg->m;
1901 
1902 	/* stats message length + 16 size of HTT header*/
1903 	msg_len = qdf_min(msg_len + HTT_HEADER_LEN, (uint32_t)DP_EXT_MSG_LENGTH);
1904 
1905 	if (pdev->dbgfs_cfg->htt_stats_dbgfs_msg_process)
1906 		pdev->dbgfs_cfg->htt_stats_dbgfs_msg_process(&dbgfs_cfg,
1907 							     (msg_len - HTT_HEADER_LEN));
1908 
1909 	/* Get TLV Done bit from 4th msg word */
1910 	done = HTT_T2H_EXT_STATS_CONF_TLV_DONE_GET(*(msg_word + 3));
1911 	if (done) {
1912 		if (qdf_event_set(&pdev->dbgfs_cfg->htt_stats_dbgfs_event))
1913 			dp_htt_err("%pK: Failed to set event for debugfs htt stats"
1914 				   , pdev->soc);
1915 	}
1916 }
1917 #else
1918 static inline void
1919 dp_htt_stats_dbgfs_send_msg(struct dp_pdev *pdev, uint32_t *msg_word,
1920 			    uint32_t msg_len)
1921 {
1922 }
1923 #endif /* HTT_STATS_DEBUGFS_SUPPORT */
1924 
1925 #ifdef WLAN_SYSFS_DP_STATS
1926 /* dp_htt_stats_sysfs_update_config() - Function to send htt data to upper layer.
1927  * @pdev: dp pdev handle
1928  *
1929  * This function sets the process id and printing mode within the sysfs config
1930  * struct. which enables DP_PRINT statements within this process to write to the
1931  * console buffer provided by the user space.
1932  *
1933  * Return: None
1934  */
1935 static inline void
1936 dp_htt_stats_sysfs_update_config(struct dp_pdev *pdev)
1937 {
1938 	struct dp_soc *soc = pdev->soc;
1939 
1940 	if (!soc) {
1941 		dp_htt_err("soc is null");
1942 		return;
1943 	}
1944 
1945 	if (!soc->sysfs_config) {
1946 		dp_htt_err("soc->sysfs_config is NULL");
1947 		return;
1948 	}
1949 
1950 	/* set sysfs config parameters */
1951 	soc->sysfs_config->process_id = qdf_get_current_pid();
1952 	soc->sysfs_config->printing_mode = PRINTING_MODE_ENABLED;
1953 }
1954 
1955 /**
1956  * dp_htt_stats_sysfs_set_event() - Set sysfs stats event.
1957  * @soc: soc handle.
1958  * @msg_word: Pointer to htt msg word.
1959  *
1960  * Return: void
1961  */
1962 static inline void
1963 dp_htt_stats_sysfs_set_event(struct dp_soc *soc, uint32_t *msg_word)
1964 {
1965 	int done = 0;
1966 
1967 	done = HTT_T2H_EXT_STATS_CONF_TLV_DONE_GET(*(msg_word + 3));
1968 	if (done) {
1969 		if (qdf_event_set(&soc->sysfs_config->sysfs_txrx_fw_request_done))
1970 			dp_htt_err("%pK:event compl Fail to set event ",
1971 				   soc);
1972 	}
1973 }
1974 #else /* WLAN_SYSFS_DP_STATS */
1975 static inline void
1976 dp_htt_stats_sysfs_update_config(struct dp_pdev *pdev)
1977 {
1978 }
1979 
1980 static inline void
1981 dp_htt_stats_sysfs_set_event(struct dp_soc *dp_soc, uint32_t *msg_word)
1982 {
1983 }
1984 #endif /* WLAN_SYSFS_DP_STATS */
1985 
1986 /* dp_htt_set_pdev_obss_stats() - Function to set pdev obss stats.
1987  * @pdev: dp pdev handle
1988  * @tag_type: HTT TLV tag type
1989  * @tag_buf: TLV buffer pointer
1990  *
1991  * Return: None
1992  */
1993 static inline void
1994 dp_htt_set_pdev_obss_stats(struct dp_pdev *pdev, uint32_t tag_type,
1995 			   uint32_t *tag_buf)
1996 {
1997 	if (tag_type != HTT_STATS_PDEV_OBSS_PD_TAG) {
1998 		dp_err("Tag mismatch");
1999 		return;
2000 	}
2001 	qdf_mem_copy(&pdev->stats.htt_tx_pdev_stats.obss_pd_stats_tlv,
2002 		     tag_buf, sizeof(struct cdp_pdev_obss_pd_stats_tlv));
2003 	qdf_event_set(&pdev->fw_obss_stats_event);
2004 }
2005 
2006 /**
2007  * dp_process_htt_stat_msg(): Process the list of buffers of HTT EXT stats
2008  * @htt_stats: htt stats info
2009  * @soc: dp_soc
2010  *
2011  * The FW sends the HTT EXT STATS as a stream of T2H messages. Each T2H message
2012  * contains sub messages which are identified by a TLV header.
2013  * In this function we will process the stream of T2H messages and read all the
2014  * TLV contained in the message.
2015  *
2016  * The following cases have been taken care of
2017  * Case 1: When the tlv_remain_length <= msg_remain_length of HTT MSG buffer
2018  *		In this case the buffer will contain multiple tlvs.
2019  * Case 2: When the tlv_remain_length > msg_remain_length of HTT MSG buffer.
2020  *		Only one tlv will be contained in the HTT message and this tag
2021  *		will extend onto the next buffer.
2022  * Case 3: When the buffer is the continuation of the previous message
2023  * Case 4: tlv length is 0. which will indicate the end of message
2024  *
2025  * Return: void
2026  */
2027 static inline void dp_process_htt_stat_msg(struct htt_stats_context *htt_stats,
2028 					struct dp_soc *soc)
2029 {
2030 	htt_tlv_tag_t tlv_type = 0xff;
2031 	qdf_nbuf_t htt_msg = NULL;
2032 	uint32_t *msg_word;
2033 	uint8_t *tlv_buf_head = NULL;
2034 	uint8_t *tlv_buf_tail = NULL;
2035 	uint32_t msg_remain_len = 0;
2036 	uint32_t tlv_remain_len = 0;
2037 	uint32_t *tlv_start;
2038 	int cookie_val = 0;
2039 	int cookie_msb = 0;
2040 	int pdev_id;
2041 	bool copy_stats = false;
2042 	struct dp_pdev *pdev;
2043 
2044 	/* Process node in the HTT message queue */
2045 	while ((htt_msg = qdf_nbuf_queue_remove(&htt_stats->msg))
2046 		!= NULL) {
2047 		msg_word = (uint32_t *) qdf_nbuf_data(htt_msg);
2048 		cookie_val = *(msg_word + 1);
2049 		htt_stats->msg_len = HTT_T2H_EXT_STATS_CONF_TLV_LENGTH_GET(
2050 					*(msg_word +
2051 					HTT_T2H_EXT_STATS_TLV_START_OFFSET));
2052 
2053 		if (cookie_val) {
2054 			if (dp_send_htt_stat_resp(htt_stats, soc, htt_msg)
2055 					== QDF_STATUS_SUCCESS) {
2056 				continue;
2057 			}
2058 		}
2059 
2060 		cookie_msb = *(msg_word + 2);
2061 		pdev_id = *(msg_word + 2) & HTT_PID_BIT_MASK;
2062 		pdev = soc->pdev_list[pdev_id];
2063 
2064 		if (!cookie_val && (cookie_msb & DBG_STATS_COOKIE_HTT_DBGFS)) {
2065 			dp_htt_stats_dbgfs_send_msg(pdev, msg_word,
2066 						    htt_stats->msg_len);
2067 			qdf_nbuf_free(htt_msg);
2068 			continue;
2069 		}
2070 
2071 		if (!cookie_val && (cookie_msb & DBG_SYSFS_STATS_COOKIE))
2072 			dp_htt_stats_sysfs_update_config(pdev);
2073 
2074 		if (cookie_msb & DBG_STATS_COOKIE_DP_STATS)
2075 			copy_stats = true;
2076 
2077 		/* read 5th word */
2078 		msg_word = msg_word + 4;
2079 		msg_remain_len = qdf_min(htt_stats->msg_len,
2080 				(uint32_t) DP_EXT_MSG_LENGTH);
2081 		/* Keep processing the node till node length is 0 */
2082 		while (msg_remain_len) {
2083 			/*
2084 			 * if message is not a continuation of previous message
2085 			 * read the tlv type and tlv length
2086 			 */
2087 			if (!tlv_buf_head) {
2088 				tlv_type = HTT_STATS_TLV_TAG_GET(
2089 						*msg_word);
2090 				tlv_remain_len = HTT_STATS_TLV_LENGTH_GET(
2091 						*msg_word);
2092 			}
2093 
2094 			if (tlv_remain_len == 0) {
2095 				msg_remain_len = 0;
2096 
2097 				if (tlv_buf_head) {
2098 					qdf_mem_free(tlv_buf_head);
2099 					tlv_buf_head = NULL;
2100 					tlv_buf_tail = NULL;
2101 				}
2102 
2103 				goto error;
2104 			}
2105 
2106 			if (!tlv_buf_head)
2107 				tlv_remain_len += HTT_TLV_HDR_LEN;
2108 
2109 			if ((tlv_remain_len <= msg_remain_len)) {
2110 				/* Case 3 */
2111 				if (tlv_buf_head) {
2112 					qdf_mem_copy(tlv_buf_tail,
2113 							(uint8_t *)msg_word,
2114 							tlv_remain_len);
2115 					tlv_start = (uint32_t *)tlv_buf_head;
2116 				} else {
2117 					/* Case 1 */
2118 					tlv_start = msg_word;
2119 				}
2120 
2121 				if (copy_stats)
2122 					dp_htt_stats_copy_tag(pdev,
2123 							      tlv_type,
2124 							      tlv_start);
2125 				else
2126 					dp_htt_stats_print_tag(pdev,
2127 							       tlv_type,
2128 							       tlv_start);
2129 
2130 				if (tlv_type == HTT_STATS_PEER_DETAILS_TAG ||
2131 				    tlv_type == HTT_STATS_PEER_STATS_CMN_TAG)
2132 					dp_peer_update_inactive_time(pdev,
2133 								     tlv_type,
2134 								     tlv_start);
2135 
2136 				if (cookie_msb & DBG_STATS_COOKIE_HTT_OBSS)
2137 					dp_htt_set_pdev_obss_stats(pdev,
2138 								   tlv_type,
2139 								   tlv_start);
2140 
2141 				msg_remain_len -= tlv_remain_len;
2142 
2143 				msg_word = (uint32_t *)
2144 					(((uint8_t *)msg_word) +
2145 					tlv_remain_len);
2146 
2147 				tlv_remain_len = 0;
2148 
2149 				if (tlv_buf_head) {
2150 					qdf_mem_free(tlv_buf_head);
2151 					tlv_buf_head = NULL;
2152 					tlv_buf_tail = NULL;
2153 				}
2154 
2155 			} else { /* tlv_remain_len > msg_remain_len */
2156 				/* Case 2 & 3 */
2157 				if (!tlv_buf_head) {
2158 					tlv_buf_head = qdf_mem_malloc(
2159 							tlv_remain_len);
2160 
2161 					if (!tlv_buf_head) {
2162 						QDF_TRACE(QDF_MODULE_ID_TXRX,
2163 								QDF_TRACE_LEVEL_ERROR,
2164 								"Alloc failed");
2165 						goto error;
2166 					}
2167 
2168 					tlv_buf_tail = tlv_buf_head;
2169 				}
2170 
2171 				qdf_mem_copy(tlv_buf_tail, (uint8_t *)msg_word,
2172 						msg_remain_len);
2173 				tlv_remain_len -= msg_remain_len;
2174 				tlv_buf_tail += msg_remain_len;
2175 			}
2176 		}
2177 
2178 		if (htt_stats->msg_len >= DP_EXT_MSG_LENGTH) {
2179 			htt_stats->msg_len -= DP_EXT_MSG_LENGTH;
2180 		}
2181 
2182 		/* indicate event completion in case the event is done */
2183 		if (!cookie_val && (cookie_msb & DBG_SYSFS_STATS_COOKIE))
2184 			dp_htt_stats_sysfs_set_event(soc, msg_word);
2185 
2186 		qdf_nbuf_free(htt_msg);
2187 	}
2188 	return;
2189 
2190 error:
2191 	qdf_nbuf_free(htt_msg);
2192 	while ((htt_msg = qdf_nbuf_queue_remove(&htt_stats->msg))
2193 			!= NULL)
2194 		qdf_nbuf_free(htt_msg);
2195 }
2196 
2197 void htt_t2h_stats_handler(void *context)
2198 {
2199 	struct dp_soc *soc = (struct dp_soc *)context;
2200 	struct htt_stats_context htt_stats;
2201 	uint32_t *msg_word;
2202 	qdf_nbuf_t htt_msg = NULL;
2203 	uint8_t done;
2204 	uint32_t rem_stats;
2205 
2206 	if (!soc) {
2207 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
2208 			  "soc is NULL");
2209 		return;
2210 	}
2211 
2212 	if (!qdf_atomic_read(&soc->cmn_init_done)) {
2213 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
2214 			  "soc: 0x%pK, init_done: %d", soc,
2215 			  qdf_atomic_read(&soc->cmn_init_done));
2216 		return;
2217 	}
2218 
2219 	qdf_mem_zero(&htt_stats, sizeof(htt_stats));
2220 	qdf_nbuf_queue_init(&htt_stats.msg);
2221 
2222 	/* pull one completed stats from soc->htt_stats_msg and process */
2223 	qdf_spin_lock_bh(&soc->htt_stats.lock);
2224 	if (!soc->htt_stats.num_stats) {
2225 		qdf_spin_unlock_bh(&soc->htt_stats.lock);
2226 		return;
2227 	}
2228 	while ((htt_msg = qdf_nbuf_queue_remove(&soc->htt_stats.msg)) != NULL) {
2229 		msg_word = (uint32_t *) qdf_nbuf_data(htt_msg);
2230 		msg_word = msg_word + HTT_T2H_EXT_STATS_TLV_START_OFFSET;
2231 		done = HTT_T2H_EXT_STATS_CONF_TLV_DONE_GET(*msg_word);
2232 		qdf_nbuf_queue_add(&htt_stats.msg, htt_msg);
2233 		/*
2234 		 * Done bit signifies that this is the last T2H buffer in the
2235 		 * stream of HTT EXT STATS message
2236 		 */
2237 		if (done)
2238 			break;
2239 	}
2240 	rem_stats = --soc->htt_stats.num_stats;
2241 	qdf_spin_unlock_bh(&soc->htt_stats.lock);
2242 
2243 	/* If there are more stats to process, schedule stats work again.
2244 	 * Scheduling prior to processing ht_stats to queue with early
2245 	 * index
2246 	 */
2247 	if (rem_stats)
2248 		qdf_sched_work(0, &soc->htt_stats.work);
2249 
2250 	dp_process_htt_stat_msg(&htt_stats, soc);
2251 }
2252 
2253 /**
2254  * dp_txrx_fw_stats_handler() - Function to process HTT EXT stats
2255  * @soc: DP SOC handle
2256  * @htt_t2h_msg: HTT message nbuf
2257  *
2258  * return:void
2259  */
2260 static inline void dp_txrx_fw_stats_handler(struct dp_soc *soc,
2261 					    qdf_nbuf_t htt_t2h_msg)
2262 {
2263 	uint8_t done;
2264 	qdf_nbuf_t msg_copy;
2265 	uint32_t *msg_word;
2266 
2267 	msg_word = (uint32_t *)qdf_nbuf_data(htt_t2h_msg);
2268 	msg_word = msg_word + 3;
2269 	done = HTT_T2H_EXT_STATS_CONF_TLV_DONE_GET(*msg_word);
2270 
2271 	/*
2272 	 * HTT EXT stats response comes as stream of TLVs which span over
2273 	 * multiple T2H messages.
2274 	 * The first message will carry length of the response.
2275 	 * For rest of the messages length will be zero.
2276 	 *
2277 	 * Clone the T2H message buffer and store it in a list to process
2278 	 * it later.
2279 	 *
2280 	 * The original T2H message buffers gets freed in the T2H HTT event
2281 	 * handler
2282 	 */
2283 	msg_copy = qdf_nbuf_clone(htt_t2h_msg);
2284 
2285 	if (!msg_copy) {
2286 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO,
2287 			  "T2H message clone failed for HTT EXT STATS");
2288 		goto error;
2289 	}
2290 
2291 	qdf_spin_lock_bh(&soc->htt_stats.lock);
2292 	qdf_nbuf_queue_add(&soc->htt_stats.msg, msg_copy);
2293 	/*
2294 	 * Done bit signifies that this is the last T2H buffer in the stream of
2295 	 * HTT EXT STATS message
2296 	 */
2297 	if (done) {
2298 		soc->htt_stats.num_stats++;
2299 		qdf_sched_work(0, &soc->htt_stats.work);
2300 	}
2301 	qdf_spin_unlock_bh(&soc->htt_stats.lock);
2302 
2303 	return;
2304 
2305 error:
2306 	qdf_spin_lock_bh(&soc->htt_stats.lock);
2307 	while ((msg_copy = qdf_nbuf_queue_remove(&soc->htt_stats.msg))
2308 			!= NULL) {
2309 		qdf_nbuf_free(msg_copy);
2310 	}
2311 	soc->htt_stats.num_stats = 0;
2312 	qdf_spin_unlock_bh(&soc->htt_stats.lock);
2313 	return;
2314 }
2315 
2316 int htt_soc_attach_target(struct htt_soc *htt_soc)
2317 {
2318 	struct htt_soc *soc = (struct htt_soc *)htt_soc;
2319 
2320 	return htt_h2t_ver_req_msg(soc);
2321 }
2322 
2323 void htt_set_htc_handle(struct htt_soc *htt_soc, HTC_HANDLE htc_soc)
2324 {
2325 	htt_soc->htc_soc = htc_soc;
2326 }
2327 
2328 HTC_HANDLE htt_get_htc_handle(struct htt_soc *htt_soc)
2329 {
2330 	return htt_soc->htc_soc;
2331 }
2332 
2333 struct htt_soc *htt_soc_attach(struct dp_soc *soc, HTC_HANDLE htc_handle)
2334 {
2335 	int i;
2336 	int j;
2337 	int umac_alloc_size = HTT_SW_UMAC_RING_IDX_MAX *
2338 			      sizeof(struct bp_handler);
2339 	int lmac_alloc_size = HTT_SW_LMAC_RING_IDX_MAX *
2340 			      sizeof(struct bp_handler);
2341 	struct htt_soc *htt_soc = NULL;
2342 
2343 	htt_soc = qdf_mem_malloc(sizeof(*htt_soc));
2344 	if (!htt_soc) {
2345 		dp_err("HTT attach failed");
2346 		return NULL;
2347 	}
2348 
2349 	for (i = 0; i < MAX_PDEV_CNT; i++) {
2350 		htt_soc->pdevid_tt[i].umac_path =
2351 			qdf_mem_malloc(umac_alloc_size);
2352 		if (!htt_soc->pdevid_tt[i].umac_path)
2353 			break;
2354 		for (j = 0; j < HTT_SW_UMAC_RING_IDX_MAX; j++)
2355 			htt_soc->pdevid_tt[i].umac_path[j].bp_start_tt = -1;
2356 		htt_soc->pdevid_tt[i].lmac_path =
2357 			qdf_mem_malloc(lmac_alloc_size);
2358 		if (!htt_soc->pdevid_tt[i].lmac_path) {
2359 			qdf_mem_free(htt_soc->pdevid_tt[i].umac_path);
2360 			break;
2361 		}
2362 		for (j = 0; j < HTT_SW_LMAC_RING_IDX_MAX ; j++)
2363 			htt_soc->pdevid_tt[i].lmac_path[j].bp_start_tt = -1;
2364 	}
2365 
2366 	if (i != MAX_PDEV_CNT) {
2367 		for (j = 0; j < i; j++) {
2368 			qdf_mem_free(htt_soc->pdevid_tt[j].umac_path);
2369 			qdf_mem_free(htt_soc->pdevid_tt[j].lmac_path);
2370 		}
2371 		qdf_mem_free(htt_soc);
2372 		return NULL;
2373 	}
2374 
2375 	htt_soc->dp_soc = soc;
2376 	htt_soc->htc_soc = htc_handle;
2377 	HTT_TX_MUTEX_INIT(&htt_soc->htt_tx_mutex);
2378 
2379 	return htt_soc;
2380 }
2381 
2382 #if defined(WDI_EVENT_ENABLE) && \
2383 	!defined(REMOVE_PKT_LOG)
2384 /**
2385  * dp_pktlog_msg_handler() - Pktlog msg handler
2386  * @soc:	 HTT SOC handle
2387  * @msg_word:    Pointer to payload
2388  *
2389  * Return: None
2390  */
2391 static void
2392 dp_pktlog_msg_handler(struct htt_soc *soc,
2393 		      uint32_t *msg_word)
2394 {
2395 	uint8_t pdev_id;
2396 	uint8_t target_pdev_id;
2397 	uint32_t *pl_hdr;
2398 
2399 	target_pdev_id = HTT_T2H_PKTLOG_PDEV_ID_GET(*msg_word);
2400 	pdev_id = dp_get_host_pdev_id_for_target_pdev_id(soc->dp_soc,
2401 							 target_pdev_id);
2402 	pl_hdr = (msg_word + 1);
2403 	dp_wdi_event_handler(WDI_EVENT_OFFLOAD_ALL, soc->dp_soc,
2404 		pl_hdr, HTT_INVALID_PEER, WDI_NO_VAL,
2405 		pdev_id);
2406 }
2407 #else
2408 static void
2409 dp_pktlog_msg_handler(struct htt_soc *soc,
2410 		      uint32_t *msg_word)
2411 {
2412 }
2413 #endif
2414 
2415 #ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE
2416 QDF_STATUS
2417 dp_h2t_ptqm_migration_msg_send(struct dp_soc *dp_soc, uint16_t vdev_id,
2418 			       uint8_t pdev_id,
2419 			       uint8_t chip_id, uint16_t peer_id,
2420 			       uint16_t ml_peer_id, uint16_t src_info,
2421 			       QDF_STATUS status)
2422 {
2423 	struct htt_soc *soc = dp_soc->htt_handle;
2424 	struct dp_htt_htc_pkt *pkt;
2425 	uint8_t *htt_logger_bufp;
2426 	qdf_nbuf_t msg;
2427 	uint32_t *msg_word;
2428 	QDF_STATUS ret = QDF_STATUS_SUCCESS;
2429 	bool src_info_valid = false;
2430 
2431 	msg = qdf_nbuf_alloc(
2432 			soc->osdev,
2433 			HTT_MSG_BUF_SIZE(sizeof(htt_h2t_primary_link_peer_migrate_resp_t)),
2434 			HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, TRUE);
2435 
2436 	if (!msg)
2437 		return QDF_STATUS_E_NOMEM;
2438 
2439 	/*
2440 	 * Set the length of the message.
2441 	 * The contribution from the HTC_HDR_ALIGNMENT_PADDING is added
2442 	 * separately during the below call to qdf_nbuf_push_head.
2443 	 * The contribution from the HTC header is added separately inside HTC.
2444 	 */
2445 	if (qdf_nbuf_put_tail(msg, sizeof(htt_h2t_primary_link_peer_migrate_resp_t))
2446 			      == NULL) {
2447 		dp_htt_err("Failed to expand head for"
2448 			   "HTT_H2T_MSG_TYPE_PRIMARY_LINK_PEER_MIGRATE_RESP");
2449 		qdf_nbuf_free(msg);
2450 		return QDF_STATUS_E_FAILURE;
2451 	}
2452 
2453 	msg_word = (uint32_t *)qdf_nbuf_data(msg);
2454 	memset(msg_word, 0, sizeof(htt_h2t_primary_link_peer_migrate_resp_t));
2455 
2456 	qdf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING);
2457 	htt_logger_bufp = (uint8_t *)msg_word;
2458 	*msg_word = 0;
2459 	HTT_H2T_MSG_TYPE_SET(*msg_word,
2460 			     HTT_H2T_MSG_TYPE_PRIMARY_LINK_PEER_MIGRATE_RESP);
2461 	HTT_H2T_PRIMARY_LINK_PEER_MIGRATE_PDEV_ID_SET(*msg_word, pdev_id);
2462 	HTT_H2T_PRIMARY_LINK_PEER_MIGRATE_CHIP_ID_SET(*msg_word, chip_id);
2463 	HTT_H2T_PRIMARY_LINK_PEER_MIGRATE_VDEV_ID_SET(*msg_word, vdev_id);
2464 
2465 	/* word 1 */
2466 	msg_word++;
2467 	*msg_word = 0;
2468 	HTT_H2T_PRIMARY_LINK_PEER_MIGRATE_SW_LINK_PEER_ID_SET(*msg_word,
2469 							      peer_id);
2470 	HTT_H2T_PRIMARY_LINK_PEER_MIGRATE_ML_PEER_ID_SET(*msg_word,
2471 							 ml_peer_id);
2472 
2473 	/* word 1 */
2474 	msg_word++;
2475 	*msg_word = 0;
2476 
2477 	if (src_info != 0)
2478 		src_info_valid = true;
2479 
2480 	HTT_H2T_PRIMARY_LINK_PEER_MIGRATE_SRC_INFO_VALID_SET(*msg_word,
2481 							     src_info_valid);
2482 	HTT_H2T_PRIMARY_LINK_PEER_MIGRATE_SRC_INFO_SET(*msg_word,
2483 						       src_info);
2484 	HTT_H2T_PRIMARY_LINK_PEER_MIGRATE_STATUS_SET(*msg_word,
2485 						     status);
2486 
2487 	pkt = htt_htc_pkt_alloc(soc);
2488 	if (!pkt) {
2489 		dp_htt_err("Fail to allocate dp_htt_htc_pkt buffer");
2490 		qdf_nbuf_free(msg);
2491 		return QDF_STATUS_E_NOMEM;
2492 	}
2493 
2494 	pkt->soc_ctxt = NULL;
2495 
2496 	/* macro to set packet parameters for TX */
2497 	SET_HTC_PACKET_INFO_TX(
2498 			&pkt->htc_pkt,
2499 			dp_htt_h2t_send_complete_free_netbuf,
2500 			qdf_nbuf_data(msg),
2501 			qdf_nbuf_len(msg),
2502 			soc->htc_endpoint,
2503 			HTC_TX_PACKET_TAG_RUNTIME_PUT);
2504 
2505 	SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg);
2506 
2507 	ret = DP_HTT_SEND_HTC_PKT(
2508 			soc, pkt,
2509 			HTT_H2T_MSG_TYPE_PRIMARY_LINK_PEER_MIGRATE_RESP,
2510 			htt_logger_bufp);
2511 
2512 	if (ret != QDF_STATUS_SUCCESS) {
2513 		qdf_nbuf_free(msg);
2514 		htt_htc_pkt_free(soc, pkt);
2515 	}
2516 
2517 	return ret;
2518 }
2519 #endif
2520 
2521 #ifdef QCA_VDEV_STATS_HW_OFFLOAD_SUPPORT
2522 /**
2523  * dp_vdev_txrx_hw_stats_handler - Handle vdev stats received from FW
2524  * @soc: htt soc handle
2525  * @msg_word: buffer containing stats
2526  *
2527  * Return: void
2528  */
2529 static void dp_vdev_txrx_hw_stats_handler(struct htt_soc *soc,
2530 					  uint32_t *msg_word)
2531 {
2532 	struct dp_soc *dpsoc = (struct dp_soc *)soc->dp_soc;
2533 	uint8_t pdev_id;
2534 	uint8_t vdev_id;
2535 	uint8_t target_pdev_id;
2536 	uint16_t payload_size;
2537 	struct dp_pdev *pdev;
2538 	struct dp_vdev *vdev;
2539 	uint8_t *tlv_buf;
2540 	uint32_t *tlv_buf_temp;
2541 	uint32_t *tag_buf;
2542 	htt_tlv_tag_t tlv_type;
2543 	uint16_t tlv_length;
2544 	uint64_t pkt_count = 0;
2545 	uint64_t byte_count = 0;
2546 	uint64_t soc_drop_cnt = 0;
2547 	struct cdp_pkt_info tx_comp = { 0 };
2548 	struct cdp_pkt_info tx_failed =  { 0 };
2549 
2550 	target_pdev_id =
2551 		HTT_T2H_VDEVS_TXRX_STATS_PERIODIC_IND_PDEV_ID_GET(*msg_word);
2552 	pdev_id = dp_get_host_pdev_id_for_target_pdev_id(dpsoc,
2553 							 target_pdev_id);
2554 
2555 	if (pdev_id >= MAX_PDEV_CNT)
2556 		return;
2557 
2558 	pdev = dpsoc->pdev_list[pdev_id];
2559 	if (!pdev) {
2560 		dp_err("PDEV is NULL for pdev_id:%d", pdev_id);
2561 		return;
2562 	}
2563 
2564 	payload_size =
2565 	HTT_T2H_VDEVS_TXRX_STATS_PERIODIC_IND_PAYLOAD_SIZE_GET(*msg_word);
2566 
2567 	qdf_trace_hex_dump(QDF_MODULE_ID_DP_HTT, QDF_TRACE_LEVEL_INFO,
2568 			   (void *)msg_word, payload_size + 16);
2569 
2570 	/* Adjust msg_word to point to the first TLV in buffer */
2571 	msg_word = msg_word + 4;
2572 
2573 	/* Parse the received buffer till payload size reaches 0 */
2574 	while (payload_size > 0) {
2575 		tlv_buf = (uint8_t *)msg_word;
2576 		tlv_buf_temp = msg_word;
2577 		tlv_type = HTT_STATS_TLV_TAG_GET(*msg_word);
2578 		tlv_length = HTT_STATS_TLV_LENGTH_GET(*msg_word);
2579 
2580 		/* Add header size to tlv length*/
2581 		tlv_length += 4;
2582 
2583 		switch (tlv_type) {
2584 		case HTT_STATS_SOC_TXRX_STATS_COMMON_TAG:
2585 		{
2586 			tag_buf = tlv_buf_temp +
2587 					HTT_VDEV_STATS_GET_INDEX(SOC_DROP_CNT);
2588 			soc_drop_cnt = HTT_VDEV_GET_STATS_U64(tag_buf);
2589 			DP_STATS_UPD(dpsoc, tx.tqm_drop_no_peer, soc_drop_cnt);
2590 			break;
2591 		}
2592 		case HTT_STATS_VDEV_TXRX_STATS_HW_STATS_TAG:
2593 		{
2594 			tag_buf = tlv_buf_temp +
2595 					HTT_VDEV_STATS_GET_INDEX(VDEV_ID);
2596 			vdev_id = (uint8_t)(*tag_buf);
2597 			vdev = dp_vdev_get_ref_by_id(dpsoc, vdev_id,
2598 						     DP_MOD_ID_HTT);
2599 
2600 			if (!vdev)
2601 				goto invalid_vdev;
2602 
2603 			/* Extract received packet count from buffer */
2604 			tag_buf = tlv_buf_temp +
2605 					HTT_VDEV_STATS_GET_INDEX(RX_PKT_CNT);
2606 			pkt_count = HTT_VDEV_GET_STATS_U64(tag_buf);
2607 			DP_STATS_UPD(vdev, rx_i.reo_rcvd_pkt.num, pkt_count);
2608 
2609 			/* Extract received packet byte count from buffer */
2610 			tag_buf = tlv_buf_temp +
2611 					HTT_VDEV_STATS_GET_INDEX(RX_BYTE_CNT);
2612 			byte_count = HTT_VDEV_GET_STATS_U64(tag_buf);
2613 			DP_STATS_UPD(vdev, rx_i.reo_rcvd_pkt.bytes, byte_count);
2614 
2615 			/* Extract tx success packet count from buffer */
2616 			tag_buf = tlv_buf_temp +
2617 				HTT_VDEV_STATS_GET_INDEX(TX_SUCCESS_PKT_CNT);
2618 			pkt_count = HTT_VDEV_GET_STATS_U64(tag_buf);
2619 			tx_comp.num = pkt_count;
2620 
2621 			/* Extract tx success packet byte count from buffer */
2622 			tag_buf = tlv_buf_temp +
2623 				HTT_VDEV_STATS_GET_INDEX(TX_SUCCESS_BYTE_CNT);
2624 			byte_count = HTT_VDEV_GET_STATS_U64(tag_buf);
2625 			tx_comp.bytes = byte_count;
2626 
2627 			/* Extract tx retry packet count from buffer */
2628 			tag_buf = tlv_buf_temp +
2629 				HTT_VDEV_STATS_GET_INDEX(TX_RETRY_PKT_CNT);
2630 			pkt_count = HTT_VDEV_GET_STATS_U64(tag_buf);
2631 			tx_comp.num += pkt_count;
2632 			tx_failed.num = pkt_count;
2633 
2634 			/* Extract tx retry packet byte count from buffer */
2635 			tag_buf = tlv_buf_temp +
2636 				HTT_VDEV_STATS_GET_INDEX(TX_RETRY_BYTE_CNT);
2637 			byte_count = HTT_VDEV_GET_STATS_U64(tag_buf);
2638 			tx_comp.bytes += byte_count;
2639 			tx_failed.bytes = byte_count;
2640 
2641 			/* Extract tx drop packet count from buffer */
2642 			tag_buf = tlv_buf_temp +
2643 				HTT_VDEV_STATS_GET_INDEX(TX_DROP_PKT_CNT);
2644 			pkt_count = HTT_VDEV_GET_STATS_U64(tag_buf);
2645 			tx_comp.num += pkt_count;
2646 			tx_failed.num += pkt_count;
2647 
2648 			/* Extract tx drop packet byte count from buffer */
2649 			tag_buf = tlv_buf_temp +
2650 				HTT_VDEV_STATS_GET_INDEX(TX_DROP_BYTE_CNT);
2651 			byte_count = HTT_VDEV_GET_STATS_U64(tag_buf);
2652 			tx_comp.bytes += byte_count;
2653 			tx_failed.bytes += byte_count;
2654 
2655 			/* Extract tx age-out packet count from buffer */
2656 			tag_buf = tlv_buf_temp +
2657 				HTT_VDEV_STATS_GET_INDEX(TX_AGE_OUT_PKT_CNT);
2658 			pkt_count = HTT_VDEV_GET_STATS_U64(tag_buf);
2659 			tx_comp.num += pkt_count;
2660 			tx_failed.num += pkt_count;
2661 
2662 			/* Extract tx age-out packet byte count from buffer */
2663 			tag_buf = tlv_buf_temp +
2664 				HTT_VDEV_STATS_GET_INDEX(TX_AGE_OUT_BYTE_CNT);
2665 			byte_count = HTT_VDEV_GET_STATS_U64(tag_buf);
2666 			tx_comp.bytes += byte_count;
2667 			tx_failed.bytes += byte_count;
2668 
2669 			/* Extract tqm bypass packet count from buffer */
2670 			tag_buf = tlv_buf_temp +
2671 				HTT_VDEV_STATS_GET_INDEX(TX_TQM_BYPASS_PKT_CNT);
2672 			pkt_count = HTT_VDEV_GET_STATS_U64(tag_buf);
2673 			tx_comp.num += pkt_count;
2674 
2675 			/* Extract tx bypass packet byte count from buffer */
2676 			tag_buf = tlv_buf_temp +
2677 				HTT_VDEV_STATS_GET_INDEX(TX_TQM_BYPASS_BYTE_CNT);
2678 			byte_count = HTT_VDEV_GET_STATS_U64(tag_buf);
2679 			tx_comp.bytes += byte_count;
2680 
2681 			DP_STATS_UPD(vdev, tx.comp_pkt.num, tx_comp.num);
2682 			DP_STATS_UPD(vdev, tx.comp_pkt.bytes, tx_comp.bytes);
2683 
2684 			DP_STATS_UPD(vdev, tx.tx_failed, tx_failed.num);
2685 
2686 			dp_vdev_unref_delete(dpsoc, vdev, DP_MOD_ID_HTT);
2687 			break;
2688 		}
2689 		default:
2690 			dp_htt_err("Invalid tlv_type value:%d\n", tlv_type);
2691 		}
2692 invalid_vdev:
2693 		msg_word = (uint32_t *)((uint8_t *)tlv_buf + tlv_length);
2694 		payload_size -= tlv_length;
2695 	}
2696 }
2697 #else
2698 static void dp_vdev_txrx_hw_stats_handler(struct htt_soc *soc,
2699 					  uint32_t *msg_word)
2700 {}
2701 #endif
2702 
2703 #ifdef CONFIG_SAWF_DEF_QUEUES
2704 static void dp_sawf_def_queues_update_map_report_conf(struct htt_soc *soc,
2705 						      uint32_t *msg_word,
2706 						      qdf_nbuf_t htt_t2h_msg)
2707 {
2708 	dp_htt_sawf_def_queues_map_report_conf(soc, msg_word, htt_t2h_msg);
2709 }
2710 #else
2711 static void dp_sawf_def_queues_update_map_report_conf(struct htt_soc *soc,
2712 						      uint32_t *msg_word,
2713 						      qdf_nbuf_t htt_t2h_msg)
2714 {}
2715 #endif
2716 
2717 #ifdef CONFIG_SAWF
2718 /**
2719  * dp_sawf_msduq_map() - Msdu queue creation information received
2720  * from target
2721  * @soc: soc handle.
2722  * @msg_word: Pointer to htt msg word.
2723  * @htt_t2h_msg: HTT message nbuf
2724  *
2725  * Return: void
2726  */
2727 static void dp_sawf_msduq_map(struct htt_soc *soc, uint32_t *msg_word,
2728 			      qdf_nbuf_t htt_t2h_msg)
2729 {
2730 	dp_htt_sawf_msduq_map(soc, msg_word, htt_t2h_msg);
2731 }
2732 
2733 /**
2734  * dp_sawf_dynamic_ast_update() - Dynamic AST index update for SAWF peer
2735  * from target
2736  * @soc: soc handle.
2737  * @msg_word: Pointer to htt msg word.
2738  * @htt_t2h_msg: HTT message nbuf
2739  *
2740  * Return: void
2741  */
2742 static void dp_sawf_dynamic_ast_update(struct htt_soc *soc, uint32_t *msg_word,
2743 				       qdf_nbuf_t htt_t2h_msg)
2744 {
2745 	dp_htt_sawf_dynamic_ast_update(soc, msg_word, htt_t2h_msg);
2746 }
2747 
2748 /**
2749  * dp_sawf_mpdu_stats_handler() - HTT message handler for MPDU stats
2750  * @soc: soc handle.
2751  * @htt_t2h_msg: HTT message nbuf
2752  *
2753  * Return: void
2754  */
2755 static void dp_sawf_mpdu_stats_handler(struct htt_soc *soc,
2756 				       qdf_nbuf_t htt_t2h_msg)
2757 {
2758 	dp_sawf_htt_mpdu_stats_handler(soc, htt_t2h_msg);
2759 }
2760 #else
2761 static void dp_sawf_msduq_map(struct htt_soc *soc, uint32_t *msg_word,
2762 			      qdf_nbuf_t htt_t2h_msg)
2763 {}
2764 
2765 static void dp_sawf_mpdu_stats_handler(struct htt_soc *soc,
2766 				       qdf_nbuf_t htt_t2h_msg)
2767 {}
2768 static void dp_sawf_dynamic_ast_update(struct htt_soc *soc, uint32_t *msg_word,
2769 				       qdf_nbuf_t htt_t2h_msg)
2770 {}
2771 #endif
2772 
2773 /**
2774  * time_allow_print() - time allow print
2775  * @htt_bp_handler:	backpressure handler
2776  * @ring_id:		ring_id (index)
2777  * @th_time:		threshold time
2778  *
2779  * Return: 1 for successfully saving timestamp in array
2780  *	and 0 for timestamp falling within 2 seconds after last one
2781  */
2782 static bool time_allow_print(struct bp_handler *htt_bp_handler,
2783 			     u_int8_t ring_id, u_int32_t th_time)
2784 {
2785 	unsigned long tstamp;
2786 	struct bp_handler *path = &htt_bp_handler[ring_id];
2787 
2788 	tstamp = qdf_get_system_timestamp();
2789 
2790 	if (!path)
2791 		return 0; //unable to print backpressure messages
2792 
2793 	if (path->bp_start_tt == -1) {
2794 		path->bp_start_tt = tstamp;
2795 		path->bp_duration = 0;
2796 		path->bp_last_tt = tstamp;
2797 		path->bp_counter = 1;
2798 		return 1;
2799 	}
2800 
2801 	path->bp_duration = tstamp - path->bp_start_tt;
2802 	path->bp_last_tt = tstamp;
2803 	path->bp_counter++;
2804 
2805 	if (path->bp_duration >= th_time) {
2806 		path->bp_start_tt = -1;
2807 		return 1;
2808 	}
2809 
2810 	return 0;
2811 }
2812 
2813 static void dp_htt_alert_print(enum htt_t2h_msg_type msg_type,
2814 			       struct dp_pdev *pdev, u_int8_t ring_id,
2815 			       u_int16_t hp_idx, u_int16_t tp_idx,
2816 			       u_int32_t bkp_time,
2817 			       struct bp_handler *htt_bp_handler,
2818 			       char *ring_stype)
2819 {
2820 	dp_alert("seq_num %u msg_type: %d pdev_id: %d ring_type: %s ",
2821 		 pdev->bkp_stats.seq_num, msg_type, pdev->pdev_id, ring_stype);
2822 	dp_alert("ring_id: %d hp_idx: %d tp_idx: %d bkpressure_time_ms: %d ",
2823 		 ring_id, hp_idx, tp_idx, bkp_time);
2824 	dp_alert("last_bp_event: %ld, total_bp_duration: %ld, bp_counter: %ld",
2825 		 htt_bp_handler[ring_id].bp_last_tt,
2826 		 htt_bp_handler[ring_id].bp_duration,
2827 		 htt_bp_handler[ring_id].bp_counter);
2828 }
2829 
2830 /**
2831  * dp_get_srng_ring_state_from_hal(): Get hal level ring stats
2832  * @soc: DP_SOC handle
2833  * @pdev: DP pdev handle
2834  * @srng: DP_SRNG handle
2835  * @ring_type: srng src/dst ring
2836  * @state: ring state
2837  * @pdev: pdev
2838  * @srng: DP_SRNG handle
2839  * @ring_type: srng src/dst ring
2840  * @state: ring_state
2841  *
2842  * Return: void
2843  */
2844 static QDF_STATUS
2845 dp_get_srng_ring_state_from_hal(struct dp_soc *soc,
2846 				struct dp_pdev *pdev,
2847 				struct dp_srng *srng,
2848 				enum hal_ring_type ring_type,
2849 				struct dp_srng_ring_state *state)
2850 {
2851 	struct hal_soc *hal_soc;
2852 
2853 	if (!soc || !srng || !srng->hal_srng || !state)
2854 		return QDF_STATUS_E_INVAL;
2855 
2856 	hal_soc = (struct hal_soc *)soc->hal_soc;
2857 
2858 	hal_get_sw_hptp(soc->hal_soc, srng->hal_srng, &state->sw_tail,
2859 			&state->sw_head);
2860 
2861 	hal_get_hw_hptp(soc->hal_soc, srng->hal_srng, &state->hw_head,
2862 			&state->hw_tail, ring_type);
2863 
2864 	state->ring_type = ring_type;
2865 
2866 	return QDF_STATUS_SUCCESS;
2867 }
2868 
2869 #ifdef QCA_MONITOR_PKT_SUPPORT
2870 static void
2871 dp_queue_mon_ring_stats(struct dp_pdev *pdev,
2872 			int lmac_id, uint32_t *num_srng,
2873 			struct dp_soc_srngs_state *soc_srngs_state)
2874 {
2875 	QDF_STATUS status;
2876 
2877 	if (pdev->soc->wlan_cfg_ctx->rxdma1_enable) {
2878 		status = dp_get_srng_ring_state_from_hal
2879 			(pdev->soc, pdev,
2880 			 &pdev->soc->rxdma_mon_buf_ring[lmac_id],
2881 			 RXDMA_MONITOR_BUF,
2882 			 &soc_srngs_state->ring_state[*num_srng]);
2883 
2884 		if (status == QDF_STATUS_SUCCESS) {
2885 			++(*num_srng);
2886 			qdf_assert_always(*num_srng < DP_MAX_SRNGS);
2887 		}
2888 
2889 		status = dp_get_srng_ring_state_from_hal
2890 			(pdev->soc, pdev,
2891 			 &pdev->soc->rxdma_mon_dst_ring[lmac_id],
2892 			 RXDMA_MONITOR_DST,
2893 			 &soc_srngs_state->ring_state[*num_srng]);
2894 
2895 		if (status == QDF_STATUS_SUCCESS) {
2896 			++(*num_srng);
2897 			qdf_assert_always(*num_srng < DP_MAX_SRNGS);
2898 		}
2899 
2900 		status = dp_get_srng_ring_state_from_hal
2901 			(pdev->soc, pdev,
2902 			 &pdev->soc->rxdma_mon_desc_ring[lmac_id],
2903 			 RXDMA_MONITOR_DESC,
2904 			 &soc_srngs_state->ring_state[*num_srng]);
2905 
2906 		if (status == QDF_STATUS_SUCCESS) {
2907 			++(*num_srng);
2908 			qdf_assert_always(*num_srng < DP_MAX_SRNGS);
2909 		}
2910 	}
2911 }
2912 #else
2913 static void
2914 dp_queue_mon_ring_stats(struct dp_pdev *pdev,
2915 			int lmac_id, uint32_t *num_srng,
2916 			struct dp_soc_srngs_state *soc_srngs_state)
2917 {
2918 }
2919 #endif
2920 
2921 #ifndef WLAN_DP_DISABLE_TCL_CMD_CRED_SRNG
2922 static inline QDF_STATUS
2923 dp_get_tcl_cmd_cred_ring_state_from_hal(struct dp_pdev *pdev,
2924 					struct dp_srng_ring_state *ring_state)
2925 {
2926 	return dp_get_srng_ring_state_from_hal(pdev->soc, pdev,
2927 					       &pdev->soc->tcl_cmd_credit_ring,
2928 					       TCL_CMD_CREDIT, ring_state);
2929 }
2930 #else
2931 static inline QDF_STATUS
2932 dp_get_tcl_cmd_cred_ring_state_from_hal(struct dp_pdev *pdev,
2933 					struct dp_srng_ring_state *ring_state)
2934 {
2935 	return QDF_STATUS_SUCCESS;
2936 }
2937 #endif
2938 
2939 #ifndef WLAN_DP_DISABLE_TCL_STATUS_SRNG
2940 static inline QDF_STATUS
2941 dp_get_tcl_status_ring_state_from_hal(struct dp_pdev *pdev,
2942 				      struct dp_srng_ring_state *ring_state)
2943 {
2944 	return dp_get_srng_ring_state_from_hal(pdev->soc, pdev,
2945 					       &pdev->soc->tcl_status_ring,
2946 					       TCL_STATUS, ring_state);
2947 }
2948 #else
2949 static inline QDF_STATUS
2950 dp_get_tcl_status_ring_state_from_hal(struct dp_pdev *pdev,
2951 				      struct dp_srng_ring_state *ring_state)
2952 {
2953 	return QDF_STATUS_SUCCESS;
2954 }
2955 #endif
2956 
2957 /**
2958  * dp_queue_ring_stats() - Print pdev hal level ring stats
2959  * dp_queue_ring_stats(): Print pdev hal level ring stats
2960  * @pdev: DP_pdev handle
2961  *
2962  * Return: void
2963  */
2964 static void dp_queue_ring_stats(struct dp_pdev *pdev)
2965 {
2966 	uint32_t i;
2967 	int mac_id;
2968 	int lmac_id;
2969 	uint32_t j = 0;
2970 	struct dp_soc *soc = pdev->soc;
2971 	struct dp_soc_srngs_state * soc_srngs_state = NULL;
2972 	struct dp_soc_srngs_state *drop_srngs_state = NULL;
2973 	QDF_STATUS status;
2974 
2975 	soc_srngs_state = qdf_mem_malloc(sizeof(struct dp_soc_srngs_state));
2976 	if (!soc_srngs_state) {
2977 		dp_htt_alert("Memory alloc failed for back pressure event");
2978 		return;
2979 	}
2980 
2981 	status = dp_get_srng_ring_state_from_hal
2982 				(pdev->soc, pdev,
2983 				 &pdev->soc->reo_exception_ring,
2984 				 REO_EXCEPTION,
2985 				 &soc_srngs_state->ring_state[j]);
2986 
2987 	if (status == QDF_STATUS_SUCCESS) {
2988 		j++;
2989 		qdf_assert_always(j < DP_MAX_SRNGS);
2990 	}
2991 
2992 	status = dp_get_srng_ring_state_from_hal
2993 				(pdev->soc, pdev,
2994 				 &pdev->soc->reo_reinject_ring,
2995 				 REO_REINJECT,
2996 				 &soc_srngs_state->ring_state[j]);
2997 
2998 	if (status == QDF_STATUS_SUCCESS) {
2999 		j++;
3000 		qdf_assert_always(j < DP_MAX_SRNGS);
3001 	}
3002 
3003 	status = dp_get_srng_ring_state_from_hal
3004 				(pdev->soc, pdev,
3005 				 &pdev->soc->reo_cmd_ring,
3006 				 REO_CMD,
3007 				 &soc_srngs_state->ring_state[j]);
3008 
3009 	if (status == QDF_STATUS_SUCCESS) {
3010 		j++;
3011 		qdf_assert_always(j < DP_MAX_SRNGS);
3012 	}
3013 
3014 	status = dp_get_srng_ring_state_from_hal
3015 				(pdev->soc, pdev,
3016 				 &pdev->soc->reo_status_ring,
3017 				 REO_STATUS,
3018 				 &soc_srngs_state->ring_state[j]);
3019 
3020 	if (status == QDF_STATUS_SUCCESS) {
3021 		j++;
3022 		qdf_assert_always(j < DP_MAX_SRNGS);
3023 	}
3024 
3025 	status = dp_get_srng_ring_state_from_hal
3026 				(pdev->soc, pdev,
3027 				 &pdev->soc->rx_rel_ring,
3028 				 WBM2SW_RELEASE,
3029 				 &soc_srngs_state->ring_state[j]);
3030 
3031 	if (status == QDF_STATUS_SUCCESS) {
3032 		j++;
3033 		qdf_assert_always(j < DP_MAX_SRNGS);
3034 	}
3035 
3036 	status = dp_get_tcl_cmd_cred_ring_state_from_hal
3037 				(pdev, &soc_srngs_state->ring_state[j]);
3038 	if (status == QDF_STATUS_SUCCESS) {
3039 		j++;
3040 		qdf_assert_always(j < DP_MAX_SRNGS);
3041 	}
3042 
3043 	status = dp_get_tcl_status_ring_state_from_hal
3044 				(pdev, &soc_srngs_state->ring_state[j]);
3045 	if (status == QDF_STATUS_SUCCESS) {
3046 		j++;
3047 		qdf_assert_always(j < DP_MAX_SRNGS);
3048 	}
3049 
3050 	status = dp_get_srng_ring_state_from_hal
3051 				(pdev->soc, pdev,
3052 				 &pdev->soc->wbm_desc_rel_ring,
3053 				 SW2WBM_RELEASE,
3054 				 &soc_srngs_state->ring_state[j]);
3055 
3056 	if (status == QDF_STATUS_SUCCESS) {
3057 		j++;
3058 		qdf_assert_always(j < DP_MAX_SRNGS);
3059 	}
3060 
3061 	for (i = 0; i < MAX_REO_DEST_RINGS; i++) {
3062 		status = dp_get_srng_ring_state_from_hal
3063 				(pdev->soc, pdev,
3064 				 &pdev->soc->reo_dest_ring[i],
3065 				 REO_DST,
3066 				 &soc_srngs_state->ring_state[j]);
3067 
3068 		if (status == QDF_STATUS_SUCCESS) {
3069 			j++;
3070 			qdf_assert_always(j < DP_MAX_SRNGS);
3071 		}
3072 	}
3073 
3074 	for (i = 0; i < pdev->soc->num_tcl_data_rings; i++) {
3075 		status = dp_get_srng_ring_state_from_hal
3076 				(pdev->soc, pdev,
3077 				 &pdev->soc->tcl_data_ring[i],
3078 				 TCL_DATA,
3079 				 &soc_srngs_state->ring_state[j]);
3080 
3081 		if (status == QDF_STATUS_SUCCESS) {
3082 			j++;
3083 			qdf_assert_always(j < DP_MAX_SRNGS);
3084 		}
3085 	}
3086 
3087 	for (i = 0; i < MAX_TCL_DATA_RINGS; i++) {
3088 		status = dp_get_srng_ring_state_from_hal
3089 				(pdev->soc, pdev,
3090 				 &pdev->soc->tx_comp_ring[i],
3091 				 WBM2SW_RELEASE,
3092 				 &soc_srngs_state->ring_state[j]);
3093 
3094 		if (status == QDF_STATUS_SUCCESS) {
3095 			j++;
3096 			qdf_assert_always(j < DP_MAX_SRNGS);
3097 		}
3098 	}
3099 
3100 	lmac_id = dp_get_lmac_id_for_pdev_id(pdev->soc, 0, pdev->pdev_id);
3101 	status = dp_get_srng_ring_state_from_hal
3102 				(pdev->soc, pdev,
3103 				 &pdev->soc->rx_refill_buf_ring
3104 				 [lmac_id],
3105 				 RXDMA_BUF,
3106 				 &soc_srngs_state->ring_state[j]);
3107 
3108 	if (status == QDF_STATUS_SUCCESS) {
3109 		j++;
3110 		qdf_assert_always(j < DP_MAX_SRNGS);
3111 	}
3112 
3113 	status = dp_get_srng_ring_state_from_hal
3114 				(pdev->soc, pdev,
3115 				 &pdev->rx_refill_buf_ring2,
3116 				 RXDMA_BUF,
3117 				 &soc_srngs_state->ring_state[j]);
3118 
3119 	if (status == QDF_STATUS_SUCCESS) {
3120 		j++;
3121 		qdf_assert_always(j < DP_MAX_SRNGS);
3122 	}
3123 
3124 
3125 	for (i = 0; i < MAX_RX_MAC_RINGS; i++) {
3126 		status = dp_get_srng_ring_state_from_hal
3127 				(pdev->soc, pdev,
3128 				 &pdev->rx_mac_buf_ring[i],
3129 				 RXDMA_BUF,
3130 				 &soc_srngs_state->ring_state[j]);
3131 
3132 		if (status == QDF_STATUS_SUCCESS) {
3133 			j++;
3134 			qdf_assert_always(j < DP_MAX_SRNGS);
3135 		}
3136 	}
3137 
3138 	for (mac_id = 0;
3139 	     mac_id  < soc->wlan_cfg_ctx->num_rxdma_status_rings_per_pdev;
3140 	     mac_id++) {
3141 		lmac_id = dp_get_lmac_id_for_pdev_id(pdev->soc,
3142 						     mac_id, pdev->pdev_id);
3143 
3144 		dp_queue_mon_ring_stats(pdev, lmac_id, &j,
3145 					soc_srngs_state);
3146 
3147 		status = dp_get_srng_ring_state_from_hal
3148 			(pdev->soc, pdev,
3149 			 &pdev->soc->rxdma_mon_status_ring[lmac_id],
3150 			 RXDMA_MONITOR_STATUS,
3151 			 &soc_srngs_state->ring_state[j]);
3152 
3153 		if (status == QDF_STATUS_SUCCESS) {
3154 			j++;
3155 			qdf_assert_always(j < DP_MAX_SRNGS);
3156 		}
3157 	}
3158 
3159 	for (i = 0; i < soc->wlan_cfg_ctx->num_rxdma_dst_rings_per_pdev; i++) {
3160 		lmac_id = dp_get_lmac_id_for_pdev_id(pdev->soc,
3161 						     i, pdev->pdev_id);
3162 
3163 		status = dp_get_srng_ring_state_from_hal
3164 				(pdev->soc, pdev,
3165 				 &pdev->soc->rxdma_err_dst_ring
3166 				 [lmac_id],
3167 				 RXDMA_DST,
3168 				 &soc_srngs_state->ring_state[j]);
3169 
3170 		if (status == QDF_STATUS_SUCCESS) {
3171 			j++;
3172 			qdf_assert_always(j < DP_MAX_SRNGS);
3173 		}
3174 	}
3175 	soc_srngs_state->max_ring_id = j;
3176 
3177 	qdf_spin_lock_bh(&pdev->bkp_stats.list_lock);
3178 
3179 	soc_srngs_state->seq_num = pdev->bkp_stats.seq_num;
3180 
3181 	if (pdev->bkp_stats.queue_depth >= HTT_BKP_STATS_MAX_QUEUE_DEPTH) {
3182 		drop_srngs_state = TAILQ_FIRST(&pdev->bkp_stats.list);
3183 		qdf_assert_always(drop_srngs_state);
3184 		TAILQ_REMOVE(&pdev->bkp_stats.list, drop_srngs_state,
3185 			     list_elem);
3186 		qdf_mem_free(drop_srngs_state);
3187 		pdev->bkp_stats.queue_depth--;
3188 	}
3189 
3190 	pdev->bkp_stats.queue_depth++;
3191 	TAILQ_INSERT_TAIL(&pdev->bkp_stats.list, soc_srngs_state,
3192 			  list_elem);
3193 	pdev->bkp_stats.seq_num++;
3194 	qdf_spin_unlock_bh(&pdev->bkp_stats.list_lock);
3195 
3196 	qdf_queue_work(0, pdev->bkp_stats.work_queue,
3197 		       &pdev->bkp_stats.work);
3198 }
3199 
3200 #ifdef WIFI_MONITOR_SUPPORT
3201 static void
3202 dp_check_backpressure_in_monitor(uint8_t ring_id, struct dp_pdev *pdev)
3203 {
3204 	if (ring_id >= HTT_SW_RING_IDX_MONITOR_STATUS_RING &&
3205 	    ring_id <= HTT_SW_LMAC_RING_IDX_MAX)
3206 		pdev->monitor_pdev->is_bkpressure = true;
3207 }
3208 #else
3209 static void
3210 dp_check_backpressure_in_monitor(uint8_t ring_id, struct dp_pdev *pdev)
3211 {
3212 }
3213 #endif
3214 
3215 /**
3216  * dp_htt_bkp_event_alert() - htt backpressure event alert
3217  * @msg_word:	htt packet context
3218  * @soc:	HTT SOC handle
3219  *
3220  * Return: after attempting to print stats
3221  */
3222 static void dp_htt_bkp_event_alert(u_int32_t *msg_word, struct htt_soc *soc)
3223 {
3224 	u_int8_t ring_type;
3225 	u_int8_t pdev_id;
3226 	uint8_t target_pdev_id;
3227 	u_int8_t ring_id;
3228 	u_int16_t hp_idx;
3229 	u_int16_t tp_idx;
3230 	u_int32_t bkp_time;
3231 	u_int32_t th_time;
3232 	enum htt_t2h_msg_type msg_type;
3233 	struct dp_soc *dpsoc;
3234 	struct dp_pdev *pdev;
3235 	struct dp_htt_timestamp *radio_tt;
3236 	struct wlan_cfg_dp_soc_ctxt *soc_cfg_ctx;
3237 
3238 
3239 	if (!soc)
3240 		return;
3241 
3242 	dpsoc = (struct dp_soc *)soc->dp_soc;
3243 	soc_cfg_ctx = dpsoc->wlan_cfg_ctx;
3244 	msg_type = HTT_T2H_MSG_TYPE_GET(*msg_word);
3245 	ring_type = HTT_T2H_RX_BKPRESSURE_RING_TYPE_GET(*msg_word);
3246 	target_pdev_id = HTT_T2H_RX_BKPRESSURE_PDEV_ID_GET(*msg_word);
3247 	pdev_id = dp_get_host_pdev_id_for_target_pdev_id(soc->dp_soc,
3248 							 target_pdev_id);
3249 	if (pdev_id >= MAX_PDEV_CNT) {
3250 		dp_htt_debug("%pK: pdev id %d is invalid", soc, pdev_id);
3251 		return;
3252 	}
3253 
3254 	th_time = wlan_cfg_time_control_bp(soc_cfg_ctx);
3255 	pdev = (struct dp_pdev *)dpsoc->pdev_list[pdev_id];
3256 	ring_id = HTT_T2H_RX_BKPRESSURE_RINGID_GET(*msg_word);
3257 	hp_idx = HTT_T2H_RX_BKPRESSURE_HEAD_IDX_GET(*(msg_word + 1));
3258 	tp_idx = HTT_T2H_RX_BKPRESSURE_TAIL_IDX_GET(*(msg_word + 1));
3259 	bkp_time = HTT_T2H_RX_BKPRESSURE_TIME_MS_GET(*(msg_word + 2));
3260 	radio_tt = &soc->pdevid_tt[pdev_id];
3261 
3262 	switch (ring_type) {
3263 	case HTT_SW_RING_TYPE_UMAC:
3264 		if (!time_allow_print(radio_tt->umac_path, ring_id, th_time))
3265 			return;
3266 		dp_htt_alert_print(msg_type, pdev, ring_id, hp_idx, tp_idx,
3267 				   bkp_time, radio_tt->umac_path,
3268 				   "HTT_SW_RING_TYPE_UMAC");
3269 	break;
3270 	case HTT_SW_RING_TYPE_LMAC:
3271 		if (!time_allow_print(radio_tt->lmac_path, ring_id, th_time))
3272 			return;
3273 		dp_check_backpressure_in_monitor(ring_id, pdev);
3274 		dp_htt_alert_print(msg_type, pdev, ring_id, hp_idx, tp_idx,
3275 				   bkp_time, radio_tt->lmac_path,
3276 				   "HTT_SW_RING_TYPE_LMAC");
3277 	break;
3278 	default:
3279 		dp_alert("Invalid ring type: %d", ring_type);
3280 	break;
3281 	}
3282 
3283 	dp_queue_ring_stats(pdev);
3284 }
3285 
3286 #ifdef WLAN_FEATURE_PKT_CAPTURE_V2
3287 /**
3288  * dp_offload_ind_handler() - offload msg handler
3289  * @soc: HTT SOC handle
3290  * @msg_word: Pointer to payload
3291  *
3292  * Return: None
3293  */
3294 static void
3295 dp_offload_ind_handler(struct htt_soc *soc, uint32_t *msg_word)
3296 {
3297 	u_int8_t pdev_id;
3298 	u_int8_t target_pdev_id;
3299 
3300 	target_pdev_id = HTT_T2H_PPDU_STATS_PDEV_ID_GET(*msg_word);
3301 	pdev_id = dp_get_host_pdev_id_for_target_pdev_id(soc->dp_soc,
3302 							 target_pdev_id);
3303 	dp_wdi_event_handler(WDI_EVENT_PKT_CAPTURE_OFFLOAD_TX_DATA, soc->dp_soc,
3304 			     msg_word, HTT_INVALID_VDEV, WDI_NO_VAL,
3305 			     pdev_id);
3306 }
3307 #else
3308 static void
3309 dp_offload_ind_handler(struct htt_soc *soc, uint32_t *msg_word)
3310 {
3311 }
3312 #endif
3313 
3314 #ifdef WLAN_FEATURE_11BE_MLO
3315 #ifdef WLAN_MLO_MULTI_CHIP
3316 static inline void dp_update_mlo_ts_offset(struct dp_soc *soc,
3317 					   uint32_t ts_lo, uint32_t ts_hi)
3318 {
3319 	uint64_t mlo_offset;
3320 
3321 	mlo_offset = ((uint64_t)(ts_hi) << 32 | ts_lo);
3322 	soc->cdp_soc.ops->mlo_ops->mlo_update_mlo_ts_offset
3323 		((struct cdp_soc_t *)soc, mlo_offset);
3324 }
3325 
3326 static inline
3327 void dp_update_mlo_delta_tsf2(struct dp_soc *soc, struct dp_pdev *pdev)
3328 {
3329 	uint64_t delta_tsf2 = 0;
3330 
3331 	hal_get_tsf2_offset(soc->hal_soc, pdev->lmac_id, &delta_tsf2);
3332 	soc->cdp_soc.ops->mlo_ops->mlo_update_delta_tsf2
3333 		((struct cdp_soc_t *)soc, pdev->pdev_id, delta_tsf2);
3334 }
3335 #else
3336 static inline void dp_update_mlo_ts_offset(struct dp_soc *soc,
3337 					   uint32_t ts_lo, uint32_t ts_hi)
3338 {}
3339 static inline
3340 void dp_update_mlo_delta_tsf2(struct dp_soc *soc, struct dp_pdev *pdev)
3341 {}
3342 #endif
3343 static void dp_htt_mlo_peer_map_handler(struct htt_soc *soc,
3344 					uint32_t *msg_word)
3345 {
3346 	uint8_t mac_addr_deswizzle_buf[QDF_MAC_ADDR_SIZE];
3347 	uint8_t *mlo_peer_mac_addr;
3348 	uint16_t mlo_peer_id;
3349 	uint8_t num_links;
3350 	struct dp_mlo_flow_override_info mlo_flow_info[DP_MLO_FLOW_INFO_MAX];
3351 	struct dp_mlo_link_info mlo_link_info[DP_MAX_MLO_LINKS];
3352 	MLO_PEER_MAP_TLV_TAG_ID tlv_type = 0xff;
3353 	uint16_t tlv_len = 0;
3354 	int i = 0;
3355 
3356 	mlo_peer_id = HTT_RX_MLO_PEER_MAP_MLO_PEER_ID_GET(*msg_word);
3357 	num_links =
3358 		HTT_RX_MLO_PEER_MAP_NUM_LOGICAL_LINKS_GET(*msg_word);
3359 	mlo_peer_mac_addr =
3360 	htt_t2h_mac_addr_deswizzle((u_int8_t *)(msg_word + 1),
3361 				   &mac_addr_deswizzle_buf[0]);
3362 
3363 	mlo_flow_info[0].ast_idx =
3364 		HTT_RX_MLO_PEER_MAP_PRIMARY_AST_INDEX_GET(*(msg_word + 3));
3365 	mlo_flow_info[0].ast_idx_valid =
3366 		HTT_RX_MLO_PEER_MAP_AST_INDEX_VALID_FLAG_GET(*(msg_word + 3));
3367 	mlo_flow_info[0].chip_id =
3368 		HTT_RX_MLO_PEER_MAP_CHIP_ID_AST_INDEX_GET(*(msg_word + 3));
3369 	mlo_flow_info[0].tidmask =
3370 		HTT_RX_MLO_PEER_MAP_TIDMASK_AST_INDEX_GET(*(msg_word + 3));
3371 	mlo_flow_info[0].cache_set_num =
3372 	HTT_RX_MLO_PEER_MAP_CACHE_SET_NUM_AST_INDEX_GET(*(msg_word + 3));
3373 
3374 	mlo_flow_info[1].ast_idx =
3375 		HTT_RX_MLO_PEER_MAP_PRIMARY_AST_INDEX_GET(*(msg_word + 3));
3376 	mlo_flow_info[1].ast_idx_valid =
3377 		HTT_RX_MLO_PEER_MAP_AST_INDEX_VALID_FLAG_GET(*(msg_word + 3));
3378 	mlo_flow_info[1].chip_id =
3379 		HTT_RX_MLO_PEER_MAP_CHIP_ID_AST_INDEX_GET(*(msg_word + 3));
3380 	mlo_flow_info[1].tidmask =
3381 		HTT_RX_MLO_PEER_MAP_TIDMASK_AST_INDEX_GET(*(msg_word + 3));
3382 	mlo_flow_info[1].cache_set_num =
3383 	HTT_RX_MLO_PEER_MAP_CACHE_SET_NUM_AST_INDEX_GET(*(msg_word + 3));
3384 
3385 	mlo_flow_info[2].ast_idx =
3386 		HTT_RX_MLO_PEER_MAP_PRIMARY_AST_INDEX_GET(*(msg_word + 3));
3387 	mlo_flow_info[2].ast_idx_valid =
3388 		HTT_RX_MLO_PEER_MAP_AST_INDEX_VALID_FLAG_GET(*(msg_word + 3));
3389 	mlo_flow_info[2].chip_id =
3390 		HTT_RX_MLO_PEER_MAP_CHIP_ID_AST_INDEX_GET(*(msg_word + 3));
3391 	mlo_flow_info[2].tidmask =
3392 		HTT_RX_MLO_PEER_MAP_TIDMASK_AST_INDEX_GET(*(msg_word + 3));
3393 	mlo_flow_info[2].cache_set_num =
3394 	HTT_RX_MLO_PEER_MAP_CACHE_SET_NUM_AST_INDEX_GET(*(msg_word + 3));
3395 
3396 	msg_word = msg_word + 8;
3397 	while (msg_word && (i < DP_MAX_MLO_LINKS)) {
3398 		mlo_link_info[i].peer_chip_id = 0xFF;
3399 		mlo_link_info[i].vdev_id = 0xFF;
3400 
3401 		tlv_type = HTT_RX_MLO_PEER_MAP_TLV_TAG_GET(*msg_word);
3402 		tlv_len = HTT_RX_MLO_PEER_MAP_TLV_LENGTH_GET(*msg_word);
3403 
3404 		if (tlv_len == 0) {
3405 			dp_err("TLV Length is 0");
3406 			break;
3407 		}
3408 
3409 		if (tlv_type == MLO_PEER_MAP_TLV_STRUCT_SOC_VDEV_PEER_IDS) {
3410 			mlo_link_info[i].peer_chip_id =
3411 				HTT_RX_MLO_PEER_MAP_CHIP_ID_GET(
3412 							*(msg_word + 1));
3413 			mlo_link_info[i].vdev_id =
3414 				HTT_RX_MLO_PEER_MAP_VDEV_ID_GET(
3415 							*(msg_word + 1));
3416 		}
3417 		/* Add header size to tlv length */
3418 		tlv_len = tlv_len + HTT_TLV_HDR_LEN;
3419 		msg_word = (uint32_t *)(((uint8_t *)msg_word) + tlv_len);
3420 		i++;
3421 	}
3422 
3423 	dp_rx_mlo_peer_map_handler(soc->dp_soc, mlo_peer_id,
3424 				   mlo_peer_mac_addr,
3425 				   mlo_flow_info, mlo_link_info);
3426 }
3427 
3428 #ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE
3429 static void dp_htt_t2h_primary_link_migration(struct htt_soc *soc,
3430 					      uint32_t *msg_word)
3431 {
3432 	u_int16_t peer_id;
3433 	u_int16_t ml_peer_id;
3434 	u_int16_t vdev_id;
3435 	u_int8_t pdev_id;
3436 	u_int8_t chip_id;
3437 
3438 	vdev_id = HTT_T2H_PRIMARY_LINK_PEER_MIGRATE_VDEV_ID_GET(
3439 			*msg_word);
3440 	pdev_id = HTT_T2H_PRIMARY_LINK_PEER_MIGRATE_PDEV_ID_GET(
3441 			*msg_word);
3442 	chip_id = HTT_T2H_PRIMARY_LINK_PEER_MIGRATE_CHIP_ID_GET(
3443 			*msg_word);
3444 	ml_peer_id = HTT_T2H_PRIMARY_LINK_PEER_MIGRATE_ML_PEER_ID_GET(
3445 			*(msg_word + 1));
3446 	peer_id = HTT_T2H_PRIMARY_LINK_PEER_MIGRATE_SW_LINK_PEER_ID_GET(
3447 			*(msg_word + 1));
3448 
3449 	dp_htt_info("HTT_T2H_MSG_TYPE_PRIMARY_PEER_MIGRATE_IND msg"
3450 		    "for peer id %d vdev id %d", peer_id, vdev_id);
3451 
3452 	dp_htt_reo_migration(soc->dp_soc, peer_id, ml_peer_id,
3453 			vdev_id, pdev_id, chip_id);
3454 }
3455 #else
3456 static void dp_htt_t2h_primary_link_migration(struct htt_soc *soc,
3457 					      uint32_t *msg_word)
3458 {
3459 }
3460 #endif
3461 
3462 static void dp_htt_mlo_peer_unmap_handler(struct htt_soc *soc,
3463 					  uint32_t *msg_word)
3464 {
3465 	uint16_t mlo_peer_id;
3466 
3467 	mlo_peer_id = HTT_RX_MLO_PEER_UNMAP_MLO_PEER_ID_GET(*msg_word);
3468 	dp_rx_mlo_peer_unmap_handler(soc->dp_soc, mlo_peer_id);
3469 }
3470 
3471 static void
3472 dp_rx_mlo_timestamp_ind_handler(struct dp_soc *soc,
3473 				uint32_t *msg_word)
3474 {
3475 	uint8_t pdev_id;
3476 	uint8_t target_pdev_id;
3477 	struct dp_pdev *pdev;
3478 
3479 	if (!soc)
3480 		return;
3481 
3482 	target_pdev_id = HTT_T2H_MLO_TIMESTAMP_OFFSET_PDEV_ID_GET(*msg_word);
3483 	pdev_id = dp_get_host_pdev_id_for_target_pdev_id(soc,
3484 							 target_pdev_id);
3485 
3486 	if (pdev_id >= MAX_PDEV_CNT) {
3487 		dp_htt_debug("%pK: pdev id %d is invalid", soc, pdev_id);
3488 		return;
3489 	}
3490 
3491 	pdev = (struct dp_pdev *)soc->pdev_list[pdev_id];
3492 
3493 	if (!pdev) {
3494 		dp_err("Invalid pdev");
3495 		return;
3496 	}
3497 	dp_wdi_event_handler(WDI_EVENT_MLO_TSTMP, soc,
3498 			     msg_word, HTT_INVALID_PEER, WDI_NO_VAL,
3499 			     pdev_id);
3500 
3501 	qdf_spin_lock_bh(&soc->htt_stats.lock);
3502 	pdev->timestamp.msg_type =
3503 		HTT_T2H_MLO_TIMESTAMP_OFFSET_MSG_TYPE_GET(*msg_word);
3504 	pdev->timestamp.pdev_id = pdev_id;
3505 	pdev->timestamp.chip_id =
3506 		HTT_T2H_MLO_TIMESTAMP_OFFSET_CHIP_ID_GET(*msg_word);
3507 	pdev->timestamp.mac_clk_freq =
3508 		HTT_T2H_MLO_TIMESTAMP_OFFSET_MAC_CLK_FREQ_MHZ_GET(*msg_word);
3509 	pdev->timestamp.sync_tstmp_lo_us = *(msg_word + 1);
3510 	pdev->timestamp.sync_tstmp_hi_us = *(msg_word + 2);
3511 	pdev->timestamp.mlo_offset_lo_us = *(msg_word + 3);
3512 	pdev->timestamp.mlo_offset_hi_us = *(msg_word + 4);
3513 	pdev->timestamp.mlo_offset_clks  = *(msg_word + 5);
3514 	pdev->timestamp.mlo_comp_us =
3515 	HTT_T2H_MLO_TIMESTAMP_OFFSET_MLO_TIMESTAMP_COMP_US_GET(
3516 							*(msg_word + 6));
3517 	pdev->timestamp.mlo_comp_clks =
3518 	HTT_T2H_MLO_TIMESTAMP_OFFSET_MLO_TIMESTAMP_COMP_CLKS_GET(
3519 							*(msg_word + 6));
3520 	pdev->timestamp.mlo_comp_timer =
3521 	HTT_T2H_MLO_TIMESTAMP_OFFSET_MLO_TIMESTAMP_COMP_PERIOD_US_GET(
3522 							*(msg_word + 7));
3523 
3524 	dp_htt_debug("tsf_lo=%d tsf_hi=%d, mlo_ofst_lo=%d, mlo_ofst_hi=%d",
3525 		     pdev->timestamp.sync_tstmp_lo_us,
3526 		     pdev->timestamp.sync_tstmp_hi_us,
3527 		     pdev->timestamp.mlo_offset_lo_us,
3528 		     pdev->timestamp.mlo_offset_hi_us);
3529 
3530 	qdf_spin_unlock_bh(&soc->htt_stats.lock);
3531 
3532 	dp_update_mlo_ts_offset(soc,
3533 				pdev->timestamp.mlo_offset_lo_us,
3534 				pdev->timestamp.mlo_offset_hi_us);
3535 
3536 	dp_update_mlo_delta_tsf2(soc, pdev);
3537 }
3538 #else
3539 static void dp_htt_mlo_peer_map_handler(struct htt_soc *soc,
3540 					uint32_t *msg_word)
3541 {
3542 	dp_alert("Unexpected event");
3543 }
3544 
3545 static void dp_htt_mlo_peer_unmap_handler(struct htt_soc *soc,
3546 					 uint32_t *msg_word)
3547 {
3548 	dp_alert("Unexpected event");
3549 }
3550 
3551 static void
3552 dp_rx_mlo_timestamp_ind_handler(void *soc_handle,
3553 				uint32_t *msg_word)
3554 {
3555 	dp_alert("Unexpected event");
3556 }
3557 
3558 static void dp_htt_t2h_primary_link_migration(struct htt_soc *soc,
3559 					      uint32_t *msg_word)
3560 {
3561 }
3562 #endif
3563 
3564 /**
3565  * dp_htt_rx_addba_handler() - RX Addba HTT msg handler
3566  * @soc: DP Soc handler
3567  * @peer_id: ID of peer
3568  * @tid: TID number
3569  * @win_sz: BA window size
3570  *
3571  * Return: None
3572  */
3573 static void
3574 dp_htt_rx_addba_handler(struct dp_soc *soc, uint16_t peer_id,
3575 			uint8_t tid, uint16_t win_sz)
3576 {
3577 	uint16_t status;
3578 	struct dp_peer *peer;
3579 
3580 	peer = dp_peer_get_ref_by_id(soc, peer_id, DP_MOD_ID_HTT);
3581 
3582 	if (!peer) {
3583 		dp_err("Peer not found peer id %d", peer_id);
3584 		return;
3585 	}
3586 
3587 	status = dp_addba_requestprocess_wifi3((struct cdp_soc_t *)soc,
3588 					       peer->mac_addr.raw,
3589 					       peer->vdev->vdev_id, 0,
3590 					       tid, 0, win_sz, 0xffff);
3591 
3592 	dp_addba_resp_tx_completion_wifi3(
3593 		(struct cdp_soc_t *)soc,
3594 		peer->mac_addr.raw, peer->vdev->vdev_id,
3595 		tid,
3596 		status);
3597 
3598 	dp_peer_unref_delete(peer, DP_MOD_ID_HTT);
3599 
3600 	dp_info("PeerID %d BAW %d TID %d stat %d",
3601 		peer_id, win_sz, tid, status);
3602 }
3603 
3604 /**
3605  * dp_htt_ppdu_id_fmt_handler() - PPDU ID Format handler
3606  * @soc: HTT SOC handle
3607  * @msg_word: Pointer to payload
3608  *
3609  * Return: None
3610  */
3611 static void
3612 dp_htt_ppdu_id_fmt_handler(struct dp_soc *soc, uint32_t *msg_word)
3613 {
3614 	uint8_t msg_type, valid, bits, offset;
3615 
3616 	msg_type = HTT_T2H_MSG_TYPE_GET(*msg_word);
3617 
3618 	msg_word += HTT_PPDU_ID_FMT_IND_LINK_ID_OFFSET;
3619 	valid = HTT_PPDU_ID_FMT_IND_VALID_GET_BITS31_16(*msg_word);
3620 	bits = HTT_PPDU_ID_FMT_IND_BITS_GET_BITS31_16(*msg_word);
3621 	offset = HTT_PPDU_ID_FMT_IND_OFFSET_GET_BITS31_16(*msg_word);
3622 
3623 	dp_info("link_id: valid %u bits %u offset %u", valid, bits, offset);
3624 
3625 	if (valid) {
3626 		soc->link_id_offset = offset;
3627 		soc->link_id_bits = bits;
3628 	}
3629 }
3630 
3631 #ifdef IPA_OPT_WIFI_DP
3632 static void dp_ipa_rx_cce_super_rule_setup_done_handler(struct htt_soc *soc,
3633 							uint32_t *msg_word)
3634 {
3635 	uint8_t pdev_id = 0;
3636 	uint8_t resp_type = 0;
3637 	uint8_t is_rules_enough = 0;
3638 	uint8_t num_rules_avail = 0;
3639 	int filter0_result = 0, filter1_result = 0;
3640 	bool is_success = false;
3641 
3642 	pdev_id = HTT_RX_CCE_SUPER_RULE_SETUP_DONE_PDEV_ID_GET(*msg_word);
3643 	resp_type = HTT_RX_CCE_SUPER_RULE_SETUP_DONE_RESPONSE_TYPE_GET(
3644 								*msg_word);
3645 	dp_info("opt_dp:: cce_super_rule_rsp pdev_id: %d resp_type: %d",
3646 		pdev_id, resp_type);
3647 
3648 	switch (resp_type) {
3649 	case HTT_RX_CCE_SUPER_RULE_SETUP_REQ_RESPONSE:
3650 	{
3651 		is_rules_enough =
3652 			HTT_RX_CCE_SUPER_RULE_SETUP_DONE_IS_RULE_ENOUGH_GET(
3653 								*msg_word);
3654 		num_rules_avail =
3655 			HTT_RX_CCE_SUPER_RULE_SETUP_DONE_AVAIL_RULE_NUM_GET(
3656 								*msg_word);
3657 		if (is_rules_enough == 1) {
3658 			is_success = true;
3659 			soc->stats.reserve_fail_cnt = 0;
3660 		} else {
3661 			is_success = false;
3662 			soc->stats.reserve_fail_cnt++;
3663 			if (soc->stats.reserve_fail_cnt >
3664 					MAX_RESERVE_FAIL_ATTEMPT) {
3665 				/*
3666 				 * IPA will retry only after an hour by default
3667 				 * after MAX_RESERVE_FAIL_ATTEMPT
3668 				 */
3669 				soc->stats.abort_count++;
3670 				soc->stats.reserve_fail_cnt = 0;
3671 				dp_info(
3672 				  "opt_dp: Filter reserve failed max attempts");
3673 			}
3674 			dp_info("opt_dp:: Filter reserve failed. Rules avail %d",
3675 				num_rules_avail);
3676 		}
3677 		dp_ipa_wdi_opt_dpath_notify_flt_rsvd(is_success);
3678 		break;
3679 	}
3680 	case HTT_RX_CCE_SUPER_RULE_INSTALL_RESPONSE:
3681 	{
3682 		filter0_result =
3683 			HTT_RX_CCE_SUPER_RULE_SETUP_DONE_CFG_RESULT_0_GET(
3684 								     *msg_word);
3685 		filter1_result =
3686 			HTT_RX_CCE_SUPER_RULE_SETUP_DONE_CFG_RESULT_1_GET(
3687 								     *msg_word);
3688 
3689 		dp_ipa_wdi_opt_dpath_notify_flt_add_rem_cb(filter0_result,
3690 							   filter1_result);
3691 		break;
3692 	}
3693 	case HTT_RX_CCE_SUPER_RULE_RELEASE_RESPONSE:
3694 	{
3695 		filter0_result =
3696 			HTT_RX_CCE_SUPER_RULE_SETUP_DONE_CFG_RESULT_0_GET(
3697 								     *msg_word);
3698 		filter1_result =
3699 			HTT_RX_CCE_SUPER_RULE_SETUP_DONE_CFG_RESULT_1_GET(
3700 								     *msg_word);
3701 
3702 		dp_ipa_wdi_opt_dpath_notify_flt_rlsd(filter0_result,
3703 						     filter1_result);
3704 		break;
3705 	}
3706 	default:
3707 		dp_info("opt_dp:: Wrong Super rule setup response");
3708 	};
3709 
3710 	dp_info("opt_dp:: cce super rule resp type: %d, is_rules_enough: %d",
3711 		resp_type, is_rules_enough);
3712 	dp_info("num_rules_avail: %d, rslt0: %d, rslt1: %d",
3713 		num_rules_avail, filter0_result, filter1_result);
3714 }
3715 #else
3716 static void dp_ipa_rx_cce_super_rule_setup_done_handler(struct htt_soc *soc,
3717 							uint32_t *msg_word)
3718 {
3719 }
3720 #endif
3721 #if defined(WLAN_FEATURE_11BE_MLO) && defined(DP_MLO_LINK_STATS_SUPPORT)
3722 static inline void
3723 dp_htt_peer_ext_evt(struct htt_soc *soc, uint32_t *msg_word)
3724 {
3725 	struct dp_peer_ext_evt_info info;
3726 	uint8_t mac_addr_deswizzle_buf[QDF_MAC_ADDR_SIZE];
3727 
3728 	info.peer_id = HTT_RX_PEER_EXTENDED_PEER_ID_GET(*msg_word);
3729 	info.vdev_id = HTT_RX_PEER_EXTENDED_VDEV_ID_GET(*msg_word);
3730 	info.link_id =
3731 		HTT_RX_PEER_EXTENDED_LOGICAL_LINK_ID_GET(*(msg_word + 2));
3732 	info.link_id_valid =
3733 		HTT_RX_PEER_EXTENDED_LOGICAL_LINK_ID_VALID_GET(*(msg_word + 2));
3734 
3735 	info.peer_mac_addr =
3736 	htt_t2h_mac_addr_deswizzle((u_int8_t *)(msg_word + 1),
3737 				   &mac_addr_deswizzle_buf[0]);
3738 
3739 	dp_htt_info("peer id %u, vdev id %u, link id %u, valid %u,peer_mac " QDF_MAC_ADDR_FMT,
3740 		    info.peer_id, info.vdev_id, info.link_id,
3741 		    info.link_id_valid, QDF_MAC_ADDR_REF(info.peer_mac_addr));
3742 
3743 	dp_rx_peer_ext_evt(soc->dp_soc, &info);
3744 }
3745 #else
3746 static inline void
3747 dp_htt_peer_ext_evt(struct htt_soc *soc, uint32_t *msg_word)
3748 {
3749 }
3750 #endif
3751 
3752 #ifdef WLAN_FEATURE_CE_RX_BUFFER_REUSE
3753 static void dp_htt_rx_nbuf_free(qdf_nbuf_t nbuf)
3754 {
3755 	nbuf = wbuff_buff_put(nbuf);
3756 	if (nbuf)
3757 		qdf_nbuf_free(nbuf);
3758 }
3759 #else
3760 static inline void dp_htt_rx_nbuf_free(qdf_nbuf_t nbuf)
3761 {
3762 	return qdf_nbuf_free(nbuf);
3763 }
3764 #endif
3765 
3766 #ifdef WLAN_FEATURE_TX_LATENCY_STATS
3767 #define TX_LATENCY_STATS_PERIOD_MAX_MS \
3768 	(HTT_H2T_TX_LATENCY_STATS_CFG_PERIODIC_INTERVAL_M >> \
3769 	 HTT_H2T_TX_LATENCY_STATS_CFG_PERIODIC_INTERVAL_S)
3770 
3771 #define TX_LATENCY_STATS_GRANULARITY_MAX_MS \
3772 	(HTT_H2T_TX_LATENCY_STATS_CFG_GRANULARITY_M >> \
3773 	 HTT_H2T_TX_LATENCY_STATS_CFG_GRANULARITY_S)
3774 
3775 /**
3776  * dp_h2t_tx_latency_stats_cfg_msg_send(): send HTT message for tx latency
3777  * stats config to FW
3778  * @dp_soc: DP SOC handle
3779  * @vdev_id: vdev id
3780  * @enable: indicates enablement of the feature
3781  * @period: statistical period for transmit latency in terms of ms
3782  * @granularity: granularity for tx latency distribution in terms of ms
3783  *
3784  * return: QDF STATUS
3785  */
3786 QDF_STATUS
3787 dp_h2t_tx_latency_stats_cfg_msg_send(struct dp_soc *dp_soc, uint16_t vdev_id,
3788 				     bool enable, uint32_t period,
3789 				     uint32_t granularity)
3790 {
3791 	struct htt_soc *soc = dp_soc->htt_handle;
3792 	struct dp_htt_htc_pkt *pkt;
3793 	uint8_t *htt_logger_bufp;
3794 	qdf_nbuf_t msg;
3795 	uint32_t *msg_word;
3796 	QDF_STATUS status;
3797 	qdf_size_t size;
3798 
3799 	if (period > TX_LATENCY_STATS_PERIOD_MAX_MS ||
3800 	    granularity > TX_LATENCY_STATS_GRANULARITY_MAX_MS)
3801 		return QDF_STATUS_E_INVAL;
3802 
3803 	size = sizeof(struct htt_h2t_tx_latency_stats_cfg);
3804 	msg = qdf_nbuf_alloc(soc->osdev, HTT_MSG_BUF_SIZE(size),
3805 			     HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING,
3806 			     4, TRUE);
3807 	if (!msg)
3808 		return QDF_STATUS_E_NOMEM;
3809 
3810 	/*
3811 	 * Set the length of the message.
3812 	 * The contribution from the HTC_HDR_ALIGNMENT_PADDING is added
3813 	 * separately during the below call to qdf_nbuf_push_head.
3814 	 * The contribution from the HTC header is added separately inside HTC.
3815 	 */
3816 	if (!qdf_nbuf_put_tail(msg, size)) {
3817 		dp_htt_err("Failed to expand head");
3818 		qdf_nbuf_free(msg);
3819 		return QDF_STATUS_E_FAILURE;
3820 	}
3821 
3822 	msg_word = (uint32_t *)qdf_nbuf_data(msg);
3823 	memset(msg_word, 0, size);
3824 
3825 	qdf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING);
3826 	htt_logger_bufp = (uint8_t *)msg_word;
3827 	HTT_H2T_MSG_TYPE_SET(*msg_word,
3828 			     HTT_H2T_MSG_TYPE_TX_LATENCY_STATS_CFG);
3829 	HTT_H2T_TX_LATENCY_STATS_CFG_VDEV_ID_SET(*msg_word, vdev_id);
3830 	HTT_H2T_TX_LATENCY_STATS_CFG_ENABLE_SET(*msg_word, enable);
3831 	HTT_H2T_TX_LATENCY_STATS_CFG_PERIODIC_INTERVAL_SET(*msg_word, period);
3832 	HTT_H2T_TX_LATENCY_STATS_CFG_GRANULARITY_SET(*msg_word, granularity);
3833 
3834 	pkt = htt_htc_pkt_alloc(soc);
3835 	if (!pkt) {
3836 		dp_htt_err("Fail to allocate dp_htt_htc_pkt buffer");
3837 		qdf_nbuf_free(msg);
3838 		return QDF_STATUS_E_NOMEM;
3839 	}
3840 
3841 	pkt->soc_ctxt = NULL;
3842 
3843 	/* macro to set packet parameters for TX */
3844 	SET_HTC_PACKET_INFO_TX(
3845 			&pkt->htc_pkt,
3846 			dp_htt_h2t_send_complete_free_netbuf,
3847 			qdf_nbuf_data(msg),
3848 			qdf_nbuf_len(msg),
3849 			soc->htc_endpoint,
3850 			HTC_TX_PACKET_TAG_RUNTIME_PUT);
3851 
3852 	SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg);
3853 
3854 	status = DP_HTT_SEND_HTC_PKT(
3855 			soc, pkt,
3856 			HTT_H2T_MSG_TYPE_TX_LATENCY_STATS_CFG,
3857 			htt_logger_bufp);
3858 
3859 	if (QDF_IS_STATUS_ERROR(status)) {
3860 		qdf_nbuf_free(msg);
3861 		htt_htc_pkt_free(soc, pkt);
3862 	}
3863 
3864 	dp_htt_debug("vdev id %u enable %u period %u granularity %u status %d",
3865 		     vdev_id, enable, period, granularity, status);
3866 	return status;
3867 }
3868 
3869 /**
3870  * dp_htt_tx_latency_get_stats_elem(): get tx latency stats from HTT message
3871  * @msg_buf: pointer to stats in HTT message
3872  * @elem_size_msg: size of per peer stats which is reported in HTT message
3873  * @local_buf: additional buffer to hold the stats
3874  * @elem_size_local: size of per peer stats according to current host side
3875  * htt definition
3876  *
3877  * This function is to handle htt version mismatch(between host and target)
3878  * case. It compares elem_size_msg with elem_size_local, when elem_size_msg
3879  * is greater than or equal to elem_size_local, return the pointer to stats
3880  * in HTT message; otherwise, copy the stas(with size elem_size_msg) from
3881  * HTT message to local buffer and leave the left as zero, then return pointer
3882  * to this local buffer.
3883  *
3884  * return: pointer to tx latency stats
3885  */
3886 static inline htt_t2h_peer_tx_latency_stats *
3887 dp_htt_tx_latency_get_stats_elem(uint8_t *msg_buf, uint32_t elem_size_msg,
3888 				 htt_t2h_peer_tx_latency_stats *local_buf,
3889 				 uint32_t elem_size_local) {
3890 	if (elem_size_msg >= elem_size_local)
3891 		return (htt_t2h_peer_tx_latency_stats *)msg_buf;
3892 
3893 	qdf_mem_zero(local_buf, sizeof(*local_buf));
3894 	qdf_mem_copy(local_buf, msg_buf, elem_size_msg);
3895 	return local_buf;
3896 }
3897 
3898 #define TX_LATENCY_STATS_GET_PAYLOAD_ELEM_SIZE \
3899 	HTT_T2H_TX_LATENCY_STATS_PERIODIC_IND_PAYLOAD_ELEM_SIZE_GET
3900 #define TX_LATENCY_STATS_GET_GRANULARITY \
3901 	HTT_T2H_TX_LATENCY_STATS_PERIODIC_IND_GRANULARITY_GET
3902 
3903 /**
3904  * dp_htt_tx_latency_stats_handler - Handle tx latency stats received from FW
3905  * @soc: htt soc handle
3906  * @htt_t2h_msg: HTT message nbuf
3907  *
3908  * Return: void
3909  */
3910 static void
3911 dp_htt_tx_latency_stats_handler(struct htt_soc *soc,
3912 				qdf_nbuf_t htt_t2h_msg)
3913 {
3914 	struct dp_soc *dpsoc = (struct dp_soc *)soc->dp_soc;
3915 	uint8_t pdev_id;
3916 	uint8_t target_pdev_id;
3917 	struct dp_pdev *pdev;
3918 	htt_t2h_peer_tx_latency_stats stats, *pstats;
3919 	uint32_t elem_size_msg, elem_size_local, granularity;
3920 	uint32_t *msg_word;
3921 	int32_t buf_len;
3922 	uint8_t *pbuf;
3923 
3924 	buf_len = qdf_nbuf_len(htt_t2h_msg);
3925 	if (buf_len <= HTT_T2H_TX_LATENCY_STATS_PERIODIC_IND_HDR_SIZE)
3926 		return;
3927 
3928 	pbuf = qdf_nbuf_data(htt_t2h_msg);
3929 	msg_word = (uint32_t *)pbuf;
3930 	target_pdev_id =
3931 		HTT_T2H_TX_LATENCY_STATS_PERIODIC_IND_PDEV_ID_GET(*msg_word);
3932 	pdev_id = dp_get_host_pdev_id_for_target_pdev_id(dpsoc,
3933 							 target_pdev_id);
3934 	if (pdev_id >= MAX_PDEV_CNT)
3935 		return;
3936 
3937 	pdev = dpsoc->pdev_list[pdev_id];
3938 	if (!pdev) {
3939 		dp_err("PDEV is NULL for pdev_id:%d", pdev_id);
3940 		return;
3941 	}
3942 
3943 	qdf_trace_hex_dump(QDF_MODULE_ID_DP_HTT, QDF_TRACE_LEVEL_INFO,
3944 			   (void *)pbuf, buf_len);
3945 
3946 	elem_size_msg = TX_LATENCY_STATS_GET_PAYLOAD_ELEM_SIZE(*msg_word);
3947 	elem_size_local = sizeof(stats);
3948 	granularity = TX_LATENCY_STATS_GET_GRANULARITY(*msg_word);
3949 
3950 	/* Adjust pbuf to point to the first stat in buffer */
3951 	pbuf += HTT_T2H_TX_LATENCY_STATS_PERIODIC_IND_HDR_SIZE;
3952 	buf_len -= HTT_T2H_TX_LATENCY_STATS_PERIODIC_IND_HDR_SIZE;
3953 
3954 	/* Parse the received buffer till payload size reaches 0 */
3955 	while (buf_len > 0) {
3956 		if (buf_len < elem_size_msg) {
3957 			dp_err_rl("invalid payload size left %d - %d",
3958 				  buf_len, elem_size_msg);
3959 			break;
3960 		}
3961 
3962 		pstats = dp_htt_tx_latency_get_stats_elem(pbuf, elem_size_msg,
3963 							  &stats,
3964 							  elem_size_local);
3965 		dp_tx_latency_stats_update_cca(dpsoc, pstats->peer_id,
3966 					       granularity,
3967 					       pstats->peer_tx_latency,
3968 					       pstats->avg_latency);
3969 		pbuf += elem_size_msg;
3970 		buf_len -= elem_size_msg;
3971 	}
3972 
3973 	dp_tx_latency_stats_report(dpsoc, pdev);
3974 }
3975 #else
3976 static inline void
3977 dp_htt_tx_latency_stats_handler(struct htt_soc *soc,
3978 				qdf_nbuf_t htt_t2h_msg)
3979 {
3980 }
3981 #endif
3982 
3983 void dp_htt_t2h_msg_handler(void *context, HTC_PACKET *pkt)
3984 {
3985 	struct htt_soc *soc = (struct htt_soc *) context;
3986 	qdf_nbuf_t htt_t2h_msg = (qdf_nbuf_t) pkt->pPktContext;
3987 	u_int32_t *msg_word;
3988 	enum htt_t2h_msg_type msg_type;
3989 	bool free_buf = true;
3990 
3991 	/* check for successful message reception */
3992 	if (pkt->Status != QDF_STATUS_SUCCESS) {
3993 		if (pkt->Status != QDF_STATUS_E_CANCELED)
3994 			soc->stats.htc_err_cnt++;
3995 
3996 		dp_htt_rx_nbuf_free(htt_t2h_msg);
3997 		return;
3998 	}
3999 
4000 	/* TODO: Check if we should pop the HTC/HTT header alignment padding */
4001 
4002 	msg_word = (u_int32_t *) qdf_nbuf_data(htt_t2h_msg);
4003 	msg_type = HTT_T2H_MSG_TYPE_GET(*msg_word);
4004 	htt_event_record(soc->htt_logger_handle,
4005 			 msg_type, (uint8_t *)msg_word);
4006 	switch (msg_type) {
4007 	case HTT_T2H_MSG_TYPE_BKPRESSURE_EVENT_IND:
4008 	{
4009 		dp_htt_bkp_event_alert(msg_word, soc);
4010 		break;
4011 	}
4012 	case HTT_T2H_MSG_TYPE_PEER_MAP:
4013 		{
4014 			u_int8_t mac_addr_deswizzle_buf[QDF_MAC_ADDR_SIZE];
4015 			u_int8_t *peer_mac_addr;
4016 			u_int16_t peer_id;
4017 			u_int16_t hw_peer_id;
4018 			u_int8_t vdev_id;
4019 			u_int8_t is_wds;
4020 			struct dp_soc *dpsoc = (struct dp_soc *)soc->dp_soc;
4021 
4022 			peer_id = HTT_RX_PEER_MAP_PEER_ID_GET(*msg_word);
4023 			hw_peer_id =
4024 				HTT_RX_PEER_MAP_HW_PEER_ID_GET(*(msg_word+2));
4025 			vdev_id = HTT_RX_PEER_MAP_VDEV_ID_GET(*msg_word);
4026 			peer_mac_addr = htt_t2h_mac_addr_deswizzle(
4027 				(u_int8_t *) (msg_word+1),
4028 				&mac_addr_deswizzle_buf[0]);
4029 			QDF_TRACE(QDF_MODULE_ID_TXRX,
4030 				QDF_TRACE_LEVEL_DEBUG,
4031 				"HTT_T2H_MSG_TYPE_PEER_MAP msg for peer id %d vdev id %d n",
4032 				peer_id, vdev_id);
4033 
4034 			/*
4035 			 * check if peer already exists for this peer_id, if so
4036 			 * this peer map event is in response for a wds peer add
4037 			 * wmi command sent during wds source port learning.
4038 			 * in this case just add the ast entry to the existing
4039 			 * peer ast_list.
4040 			 */
4041 			is_wds = !!(dpsoc->peer_id_to_obj_map[peer_id]);
4042 			dp_rx_peer_map_handler(soc->dp_soc, peer_id, hw_peer_id,
4043 					       vdev_id, peer_mac_addr, 0,
4044 					       is_wds);
4045 			break;
4046 		}
4047 	case HTT_T2H_MSG_TYPE_PEER_UNMAP:
4048 		{
4049 			u_int16_t peer_id;
4050 			u_int8_t vdev_id;
4051 			u_int8_t mac_addr[QDF_MAC_ADDR_SIZE] = {0};
4052 			peer_id = HTT_RX_PEER_UNMAP_PEER_ID_GET(*msg_word);
4053 			vdev_id = HTT_RX_PEER_UNMAP_VDEV_ID_GET(*msg_word);
4054 
4055 			dp_rx_peer_unmap_handler(soc->dp_soc, peer_id,
4056 						 vdev_id, mac_addr, 0,
4057 						 DP_PEER_WDS_COUNT_INVALID);
4058 			break;
4059 		}
4060 	case HTT_T2H_MSG_TYPE_SEC_IND:
4061 		{
4062 			u_int16_t peer_id;
4063 			enum cdp_sec_type sec_type;
4064 			int is_unicast;
4065 
4066 			peer_id = HTT_SEC_IND_PEER_ID_GET(*msg_word);
4067 			sec_type = HTT_SEC_IND_SEC_TYPE_GET(*msg_word);
4068 			is_unicast = HTT_SEC_IND_UNICAST_GET(*msg_word);
4069 			/* point to the first part of the Michael key */
4070 			msg_word++;
4071 			dp_rx_sec_ind_handler(
4072 				soc->dp_soc, peer_id, sec_type, is_unicast,
4073 				msg_word, msg_word + 2);
4074 			break;
4075 		}
4076 
4077 	case HTT_T2H_MSG_TYPE_PPDU_STATS_IND:
4078 		{
4079 			free_buf =
4080 				dp_monitor_ppdu_stats_ind_handler(soc,
4081 								  msg_word,
4082 								  htt_t2h_msg);
4083 			break;
4084 		}
4085 
4086 	case HTT_T2H_MSG_TYPE_PKTLOG:
4087 		{
4088 			dp_pktlog_msg_handler(soc, msg_word);
4089 			break;
4090 		}
4091 
4092 	case HTT_T2H_MSG_TYPE_VERSION_CONF:
4093 		{
4094 			/*
4095 			 * HTC maintains runtime pm count for H2T messages that
4096 			 * have a response msg from FW. This count ensures that
4097 			 * in the case FW does not sent out the response or host
4098 			 * did not process this indication runtime_put happens
4099 			 * properly in the cleanup path.
4100 			 */
4101 			if (htc_dec_return_htt_runtime_cnt(soc->htc_soc) >= 0)
4102 				htc_pm_runtime_put(soc->htc_soc);
4103 			else
4104 				soc->stats.htt_ver_req_put_skip++;
4105 			soc->tgt_ver.major = HTT_VER_CONF_MAJOR_GET(*msg_word);
4106 			soc->tgt_ver.minor = HTT_VER_CONF_MINOR_GET(*msg_word);
4107 			QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW,
4108 				"target uses HTT version %d.%d; host uses %d.%d",
4109 				soc->tgt_ver.major, soc->tgt_ver.minor,
4110 				HTT_CURRENT_VERSION_MAJOR,
4111 				HTT_CURRENT_VERSION_MINOR);
4112 			if (soc->tgt_ver.major != HTT_CURRENT_VERSION_MAJOR) {
4113 				QDF_TRACE(QDF_MODULE_ID_TXRX,
4114 					QDF_TRACE_LEVEL_WARN,
4115 					"*** Incompatible host/target HTT versions!");
4116 			}
4117 			/* abort if the target is incompatible with the host */
4118 			qdf_assert(soc->tgt_ver.major ==
4119 				HTT_CURRENT_VERSION_MAJOR);
4120 			if (soc->tgt_ver.minor != HTT_CURRENT_VERSION_MINOR) {
4121 				QDF_TRACE(QDF_MODULE_ID_TXRX,
4122 					QDF_TRACE_LEVEL_INFO_LOW,
4123 					"*** Warning: host/target HTT versions"
4124 					" are different, though compatible!");
4125 			}
4126 			break;
4127 		}
4128 	case HTT_T2H_MSG_TYPE_RX_ADDBA:
4129 		{
4130 			uint16_t peer_id;
4131 			uint8_t tid;
4132 			uint16_t win_sz;
4133 
4134 			/*
4135 			 * Update REO Queue Desc with new values
4136 			 */
4137 			peer_id = HTT_RX_ADDBA_PEER_ID_GET(*msg_word);
4138 			tid = HTT_RX_ADDBA_TID_GET(*msg_word);
4139 			win_sz = HTT_RX_ADDBA_WIN_SIZE_GET(*msg_word);
4140 
4141 			/*
4142 			 * Window size needs to be incremented by 1
4143 			 * since fw needs to represent a value of 256
4144 			 * using just 8 bits
4145 			 */
4146 			dp_htt_rx_addba_handler(soc->dp_soc, peer_id,
4147 						tid, win_sz + 1);
4148 			break;
4149 		}
4150 	case HTT_T2H_MSG_TYPE_RX_ADDBA_EXTN:
4151 		{
4152 			uint16_t peer_id;
4153 			uint8_t tid;
4154 			uint16_t win_sz;
4155 
4156 			peer_id = HTT_RX_ADDBA_EXTN_PEER_ID_GET(*msg_word);
4157 			tid = HTT_RX_ADDBA_EXTN_TID_GET(*msg_word);
4158 
4159 			msg_word++;
4160 			win_sz = HTT_RX_ADDBA_EXTN_WIN_SIZE_GET(*msg_word);
4161 
4162 			dp_htt_rx_addba_handler(soc->dp_soc, peer_id,
4163 						tid, win_sz);
4164 			break;
4165 		}
4166 	case HTT_T2H_PPDU_ID_FMT_IND:
4167 		{
4168 			dp_htt_ppdu_id_fmt_handler(soc->dp_soc, msg_word);
4169 			break;
4170 		}
4171 	case HTT_T2H_MSG_TYPE_EXT_STATS_CONF:
4172 		{
4173 			dp_txrx_fw_stats_handler(soc->dp_soc, htt_t2h_msg);
4174 			break;
4175 		}
4176 	case HTT_T2H_MSG_TYPE_PEER_MAP_V2:
4177 		{
4178 			u_int8_t mac_addr_deswizzle_buf[QDF_MAC_ADDR_SIZE];
4179 			u_int8_t *peer_mac_addr;
4180 			u_int16_t peer_id;
4181 			u_int16_t hw_peer_id;
4182 			u_int8_t vdev_id;
4183 			bool is_wds;
4184 			u_int16_t ast_hash;
4185 			struct dp_ast_flow_override_info ast_flow_info = {0};
4186 
4187 			peer_id = HTT_RX_PEER_MAP_V2_SW_PEER_ID_GET(*msg_word);
4188 			hw_peer_id =
4189 			HTT_RX_PEER_MAP_V2_HW_PEER_ID_GET(*(msg_word + 2));
4190 			vdev_id = HTT_RX_PEER_MAP_V2_VDEV_ID_GET(*msg_word);
4191 			peer_mac_addr =
4192 			htt_t2h_mac_addr_deswizzle((u_int8_t *)(msg_word + 1),
4193 						   &mac_addr_deswizzle_buf[0]);
4194 			is_wds =
4195 			HTT_RX_PEER_MAP_V2_NEXT_HOP_GET(*(msg_word + 3));
4196 			ast_hash =
4197 			HTT_RX_PEER_MAP_V2_AST_HASH_VALUE_GET(*(msg_word + 3));
4198 			/*
4199 			 * Update 4 ast_index per peer, ast valid mask
4200 			 * and TID flow valid mask.
4201 			 * AST valid mask is 3 bit field corresponds to
4202 			 * ast_index[3:1]. ast_index 0 is always valid.
4203 			 */
4204 			ast_flow_info.ast_valid_mask =
4205 			HTT_RX_PEER_MAP_V2_AST_VALID_MASK_GET(*(msg_word + 3));
4206 			ast_flow_info.ast_idx[0] = hw_peer_id;
4207 			ast_flow_info.ast_flow_mask[0] =
4208 			HTT_RX_PEER_MAP_V2_AST_0_FLOW_MASK_GET(*(msg_word + 4));
4209 			ast_flow_info.ast_idx[1] =
4210 			HTT_RX_PEER_MAP_V2_AST_INDEX_1_GET(*(msg_word + 4));
4211 			ast_flow_info.ast_flow_mask[1] =
4212 			HTT_RX_PEER_MAP_V2_AST_1_FLOW_MASK_GET(*(msg_word + 4));
4213 			ast_flow_info.ast_idx[2] =
4214 			HTT_RX_PEER_MAP_V2_AST_INDEX_2_GET(*(msg_word + 5));
4215 			ast_flow_info.ast_flow_mask[2] =
4216 			HTT_RX_PEER_MAP_V2_AST_2_FLOW_MASK_GET(*(msg_word + 4));
4217 			ast_flow_info.ast_idx[3] =
4218 			HTT_RX_PEER_MAP_V2_AST_INDEX_3_GET(*(msg_word + 6));
4219 			ast_flow_info.ast_flow_mask[3] =
4220 			HTT_RX_PEER_MAP_V2_AST_3_FLOW_MASK_GET(*(msg_word + 4));
4221 			/*
4222 			 * TID valid mask is applicable only
4223 			 * for HI and LOW priority flows.
4224 			 * tid_valid_mas is 8 bit field corresponds
4225 			 * to TID[7:0]
4226 			 */
4227 			ast_flow_info.tid_valid_low_pri_mask =
4228 			HTT_RX_PEER_MAP_V2_TID_VALID_LOW_PRI_GET(*(msg_word + 5));
4229 			ast_flow_info.tid_valid_hi_pri_mask =
4230 			HTT_RX_PEER_MAP_V2_TID_VALID_HI_PRI_GET(*(msg_word + 5));
4231 
4232 			QDF_TRACE(QDF_MODULE_ID_TXRX,
4233 				  QDF_TRACE_LEVEL_DEBUG,
4234 				  "HTT_T2H_MSG_TYPE_PEER_MAP msg for peer id %d vdev id %d n",
4235 				  peer_id, vdev_id);
4236 
4237 			QDF_TRACE(QDF_MODULE_ID_TXRX,
4238 				  QDF_TRACE_LEVEL_INFO,
4239 				  "ast_idx[0] %d ast_idx[1] %d ast_idx[2] %d ast_idx[3] %d n",
4240 				  ast_flow_info.ast_idx[0],
4241 				  ast_flow_info.ast_idx[1],
4242 				  ast_flow_info.ast_idx[2],
4243 				  ast_flow_info.ast_idx[3]);
4244 
4245 			dp_rx_peer_map_handler(soc->dp_soc, peer_id,
4246 					       hw_peer_id, vdev_id,
4247 					       peer_mac_addr, ast_hash,
4248 					       is_wds);
4249 
4250 			/*
4251 			 * Update ast indexes for flow override support
4252 			 * Applicable only for non wds peers
4253 			 */
4254 			if (!soc->dp_soc->ast_offload_support)
4255 				dp_peer_ast_index_flow_queue_map_create(
4256 						soc->dp_soc, is_wds,
4257 						peer_id, peer_mac_addr,
4258 						&ast_flow_info);
4259 
4260 			break;
4261 		}
4262 	case HTT_T2H_MSG_TYPE_PEER_UNMAP_V2:
4263 		{
4264 			u_int8_t mac_addr_deswizzle_buf[QDF_MAC_ADDR_SIZE];
4265 			u_int8_t *mac_addr;
4266 			u_int16_t peer_id;
4267 			u_int8_t vdev_id;
4268 			u_int8_t is_wds;
4269 			u_int32_t free_wds_count;
4270 
4271 			peer_id =
4272 			HTT_RX_PEER_UNMAP_V2_SW_PEER_ID_GET(*msg_word);
4273 			vdev_id = HTT_RX_PEER_UNMAP_V2_VDEV_ID_GET(*msg_word);
4274 			mac_addr =
4275 			htt_t2h_mac_addr_deswizzle((u_int8_t *)(msg_word + 1),
4276 						   &mac_addr_deswizzle_buf[0]);
4277 			is_wds =
4278 			HTT_RX_PEER_UNMAP_V2_NEXT_HOP_GET(*(msg_word + 2));
4279 			free_wds_count =
4280 			HTT_RX_PEER_UNMAP_V2_PEER_WDS_FREE_COUNT_GET(*(msg_word + 4));
4281 
4282 			QDF_TRACE(QDF_MODULE_ID_TXRX,
4283 				  QDF_TRACE_LEVEL_INFO,
4284 				  "HTT_T2H_MSG_TYPE_PEER_UNMAP msg for peer id %d vdev id %d n",
4285 				  peer_id, vdev_id);
4286 
4287 			dp_rx_peer_unmap_handler(soc->dp_soc, peer_id,
4288 						 vdev_id, mac_addr,
4289 						 is_wds, free_wds_count);
4290 			break;
4291 		}
4292 	case HTT_T2H_MSG_TYPE_RX_DELBA:
4293 		{
4294 			uint16_t peer_id;
4295 			uint8_t tid;
4296 			uint8_t win_sz;
4297 			QDF_STATUS status;
4298 
4299 			peer_id = HTT_RX_DELBA_PEER_ID_GET(*msg_word);
4300 			tid = HTT_RX_DELBA_TID_GET(*msg_word);
4301 			win_sz = HTT_RX_DELBA_WIN_SIZE_GET(*msg_word);
4302 
4303 			status = dp_rx_delba_ind_handler(
4304 				soc->dp_soc,
4305 				peer_id, tid, win_sz);
4306 
4307 			QDF_TRACE(QDF_MODULE_ID_TXRX,
4308 				  QDF_TRACE_LEVEL_INFO,
4309 				  FL("DELBA PeerID %d BAW %d TID %d stat %d"),
4310 				  peer_id, win_sz, tid, status);
4311 			break;
4312 		}
4313 	case HTT_T2H_MSG_TYPE_RX_DELBA_EXTN:
4314 		{
4315 			uint16_t peer_id;
4316 			uint8_t tid;
4317 			uint16_t win_sz;
4318 			QDF_STATUS status;
4319 
4320 			peer_id = HTT_RX_DELBA_EXTN_PEER_ID_GET(*msg_word);
4321 			tid = HTT_RX_DELBA_EXTN_TID_GET(*msg_word);
4322 
4323 			msg_word++;
4324 			win_sz = HTT_RX_DELBA_EXTN_WIN_SIZE_GET(*msg_word);
4325 
4326 			status = dp_rx_delba_ind_handler(soc->dp_soc,
4327 							 peer_id, tid,
4328 							 win_sz);
4329 
4330 			dp_info("DELBA PeerID %d BAW %d TID %d stat %d",
4331 				peer_id, win_sz, tid, status);
4332 			break;
4333 		}
4334 	case HTT_T2H_MSG_TYPE_FSE_CMEM_BASE_SEND:
4335 		{
4336 			uint16_t num_entries;
4337 			uint32_t cmem_ba_lo;
4338 			uint32_t cmem_ba_hi;
4339 
4340 			num_entries = HTT_CMEM_BASE_SEND_NUM_ENTRIES_GET(*msg_word);
4341 			cmem_ba_lo = *(msg_word + 1);
4342 			cmem_ba_hi = *(msg_word + 2);
4343 
4344 			QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO,
4345 				  FL("CMEM FSE num_entries %u CMEM BA LO %x HI %x"),
4346 				  num_entries, cmem_ba_lo, cmem_ba_hi);
4347 
4348 			dp_rx_fst_update_cmem_params(soc->dp_soc, num_entries,
4349 						     cmem_ba_lo, cmem_ba_hi);
4350 			break;
4351 		}
4352 	case HTT_T2H_MSG_TYPE_TX_OFFLOAD_DELIVER_IND:
4353 		{
4354 			dp_offload_ind_handler(soc, msg_word);
4355 			break;
4356 		}
4357 	case HTT_T2H_MSG_TYPE_PEER_MAP_V3:
4358 	{
4359 		u_int8_t mac_addr_deswizzle_buf[QDF_MAC_ADDR_SIZE];
4360 		u_int8_t *peer_mac_addr;
4361 		u_int16_t peer_id;
4362 		u_int16_t hw_peer_id;
4363 		u_int8_t vdev_id;
4364 		uint8_t is_wds;
4365 		u_int16_t ast_hash = 0;
4366 
4367 		peer_id = HTT_RX_PEER_MAP_V3_SW_PEER_ID_GET(*msg_word);
4368 		vdev_id = HTT_RX_PEER_MAP_V3_VDEV_ID_GET(*msg_word);
4369 		peer_mac_addr =
4370 		htt_t2h_mac_addr_deswizzle((u_int8_t *)(msg_word + 1),
4371 					   &mac_addr_deswizzle_buf[0]);
4372 		hw_peer_id = HTT_RX_PEER_MAP_V3_HW_PEER_ID_GET(*(msg_word + 3));
4373 		ast_hash = HTT_RX_PEER_MAP_V3_CACHE_SET_NUM_GET(*(msg_word + 3));
4374 		is_wds = HTT_RX_PEER_MAP_V3_NEXT_HOP_GET(*(msg_word + 4));
4375 
4376 		dp_htt_info("HTT_T2H_MSG_TYPE_PEER_MAP_V3 msg for peer id %d vdev id %d n",
4377 			    peer_id, vdev_id);
4378 
4379 		dp_rx_peer_map_handler(soc->dp_soc, peer_id,
4380 				       hw_peer_id, vdev_id,
4381 				       peer_mac_addr, ast_hash,
4382 				       is_wds);
4383 
4384 		break;
4385 	}
4386 	case HTT_T2H_MSG_TYPE_PRIMARY_LINK_PEER_MIGRATE_IND:
4387 	{
4388 		dp_htt_t2h_primary_link_migration(soc, msg_word);
4389 		break;
4390 	}
4391 	case HTT_T2H_MSG_TYPE_MLO_RX_PEER_MAP:
4392 	{
4393 		dp_htt_mlo_peer_map_handler(soc, msg_word);
4394 		break;
4395 	}
4396 	case HTT_T2H_MSG_TYPE_MLO_RX_PEER_UNMAP:
4397 	{
4398 		dp_htt_mlo_peer_unmap_handler(soc, msg_word);
4399 		break;
4400 	}
4401 	case HTT_T2H_MSG_TYPE_MLO_TIMESTAMP_OFFSET_IND:
4402 	{
4403 		dp_rx_mlo_timestamp_ind_handler(soc->dp_soc, msg_word);
4404 		break;
4405 	}
4406 	case HTT_T2H_MSG_TYPE_VDEVS_TXRX_STATS_PERIODIC_IND:
4407 	{
4408 		dp_vdev_txrx_hw_stats_handler(soc, msg_word);
4409 		break;
4410 	}
4411 	case HTT_T2H_SAWF_DEF_QUEUES_MAP_REPORT_CONF:
4412 	{
4413 		dp_sawf_def_queues_update_map_report_conf(soc, msg_word,
4414 							  htt_t2h_msg);
4415 		break;
4416 	}
4417 	case HTT_T2H_SAWF_MSDUQ_INFO_IND:
4418 	{
4419 		dp_sawf_msduq_map(soc, msg_word, htt_t2h_msg);
4420 		break;
4421 	}
4422 	case HTT_T2H_MSG_TYPE_PEER_AST_OVERRIDE_INDEX_IND:
4423 	{
4424 		dp_sawf_dynamic_ast_update(soc, msg_word, htt_t2h_msg);
4425 		break;
4426 	}
4427 	case HTT_T2H_MSG_TYPE_STREAMING_STATS_IND:
4428 	{
4429 		dp_sawf_mpdu_stats_handler(soc, htt_t2h_msg);
4430 		break;
4431 	}
4432 	case HTT_T2H_MSG_TYPE_RX_CCE_SUPER_RULE_SETUP_DONE:
4433 	{
4434 		dp_ipa_rx_cce_super_rule_setup_done_handler(soc, msg_word);
4435 		break;
4436 	}
4437 	case HTT_T2H_MSG_TYPE_PEER_EXTENDED_EVENT:
4438 	{
4439 		dp_htt_peer_ext_evt(soc, msg_word);
4440 		break;
4441 	}
4442 	case HTT_T2H_MSG_TYPE_TX_LATENCY_STATS_PERIODIC_IND:
4443 	{
4444 		dp_htt_tx_latency_stats_handler(soc, htt_t2h_msg);
4445 		break;
4446 	}
4447 	default:
4448 		break;
4449 	};
4450 
4451 	/* Free the indication buffer */
4452 	if (free_buf)
4453 		dp_htt_rx_nbuf_free(htt_t2h_msg);
4454 }
4455 
4456 enum htc_send_full_action
4457 dp_htt_h2t_full(void *context, HTC_PACKET *pkt)
4458 {
4459 	return HTC_SEND_FULL_KEEP;
4460 }
4461 
4462 QDF_STATUS
4463 dp_htt_hif_t2h_hp_callback (void *context, qdf_nbuf_t nbuf, uint8_t pipe_id)
4464 {
4465 	QDF_STATUS rc = QDF_STATUS_SUCCESS;
4466 	HTC_PACKET htc_pkt;
4467 
4468 	qdf_assert_always(pipe_id == DP_HTT_T2H_HP_PIPE);
4469 	qdf_mem_zero(&htc_pkt, sizeof(htc_pkt));
4470 	htc_pkt.Status = QDF_STATUS_SUCCESS;
4471 	htc_pkt.pPktContext = (void *)nbuf;
4472 	dp_htt_t2h_msg_handler(context, &htc_pkt);
4473 
4474 	return rc;
4475 }
4476 
4477 /**
4478  * htt_htc_soc_attach() - Register SOC level HTT instance with HTC
4479  * @soc:	HTT SOC handle
4480  *
4481  * Return: QDF_STATUS
4482  */
4483 static QDF_STATUS
4484 htt_htc_soc_attach(struct htt_soc *soc)
4485 {
4486 	struct htc_service_connect_req connect;
4487 	struct htc_service_connect_resp response;
4488 	QDF_STATUS status;
4489 	struct dp_soc *dpsoc = soc->dp_soc;
4490 
4491 	qdf_mem_zero(&connect, sizeof(connect));
4492 	qdf_mem_zero(&response, sizeof(response));
4493 
4494 	connect.pMetaData = NULL;
4495 	connect.MetaDataLength = 0;
4496 	connect.EpCallbacks.pContext = soc;
4497 	connect.EpCallbacks.EpTxComplete = dp_htt_h2t_send_complete;
4498 	connect.EpCallbacks.EpTxCompleteMultiple = NULL;
4499 	connect.EpCallbacks.EpRecv = dp_htt_t2h_msg_handler;
4500 
4501 	/* rx buffers currently are provided by HIF, not by EpRecvRefill */
4502 	connect.EpCallbacks.EpRecvRefill = NULL;
4503 
4504 	/* N/A, fill is done by HIF */
4505 	connect.EpCallbacks.RecvRefillWaterMark = 1;
4506 
4507 	connect.EpCallbacks.EpSendFull = dp_htt_h2t_full;
4508 	/*
4509 	 * Specify how deep to let a queue get before htc_send_pkt will
4510 	 * call the EpSendFull function due to excessive send queue depth.
4511 	 */
4512 	connect.MaxSendQueueDepth = DP_HTT_MAX_SEND_QUEUE_DEPTH;
4513 
4514 	/* disable flow control for HTT data message service */
4515 	connect.ConnectionFlags |= HTC_CONNECT_FLAGS_DISABLE_CREDIT_FLOW_CTRL;
4516 
4517 	/* connect to control service */
4518 	connect.service_id = HTT_DATA_MSG_SVC;
4519 
4520 	status = htc_connect_service(soc->htc_soc, &connect, &response);
4521 
4522 	if (status != QDF_STATUS_SUCCESS)
4523 		return status;
4524 
4525 	soc->htc_endpoint = response.Endpoint;
4526 
4527 	hif_save_htc_htt_config_endpoint(dpsoc->hif_handle, soc->htc_endpoint);
4528 
4529 	htt_interface_logging_init(&soc->htt_logger_handle, soc->ctrl_psoc);
4530 	dp_hif_update_pipe_callback(soc->dp_soc, (void *)soc,
4531 		dp_htt_hif_t2h_hp_callback, DP_HTT_T2H_HP_PIPE);
4532 
4533 	return QDF_STATUS_SUCCESS; /* success */
4534 }
4535 
4536 void *
4537 htt_soc_initialize(struct htt_soc *htt_soc,
4538 		   struct cdp_ctrl_objmgr_psoc *ctrl_psoc,
4539 		   HTC_HANDLE htc_soc,
4540 		   hal_soc_handle_t hal_soc_hdl, qdf_device_t osdev)
4541 {
4542 	struct htt_soc *soc = (struct htt_soc *)htt_soc;
4543 
4544 	soc->osdev = osdev;
4545 	soc->ctrl_psoc = ctrl_psoc;
4546 	soc->htc_soc = htc_soc;
4547 	soc->hal_soc = hal_soc_hdl;
4548 
4549 	if (htt_htc_soc_attach(soc))
4550 		goto fail2;
4551 
4552 	return soc;
4553 
4554 fail2:
4555 	return NULL;
4556 }
4557 
4558 void htt_soc_htc_dealloc(struct htt_soc *htt_handle)
4559 {
4560 	htt_interface_logging_deinit(htt_handle->htt_logger_handle);
4561 	htt_htc_misc_pkt_pool_free(htt_handle);
4562 	htt_htc_pkt_pool_free(htt_handle);
4563 }
4564 
4565 QDF_STATUS htt_soc_htc_prealloc(struct htt_soc *soc)
4566 {
4567 	int i;
4568 
4569 	soc->htt_htc_pkt_freelist = NULL;
4570 	/* pre-allocate some HTC_PACKET objects */
4571 	for (i = 0; i < HTT_HTC_PKT_POOL_INIT_SIZE; i++) {
4572 		struct dp_htt_htc_pkt_union *pkt;
4573 		pkt = qdf_mem_malloc(sizeof(*pkt));
4574 		if (!pkt)
4575 			return QDF_STATUS_E_NOMEM;
4576 
4577 		htt_htc_pkt_free(soc, &pkt->u.pkt);
4578 	}
4579 	return QDF_STATUS_SUCCESS;
4580 }
4581 
4582 void htt_soc_detach(struct htt_soc *htt_hdl)
4583 {
4584 	int i;
4585 	struct htt_soc *htt_handle = (struct htt_soc *)htt_hdl;
4586 
4587 	for (i = 0; i < MAX_PDEV_CNT; i++) {
4588 		qdf_mem_free(htt_handle->pdevid_tt[i].umac_path);
4589 		qdf_mem_free(htt_handle->pdevid_tt[i].lmac_path);
4590 	}
4591 
4592 	HTT_TX_MUTEX_DESTROY(&htt_handle->htt_tx_mutex);
4593 	qdf_mem_free(htt_handle);
4594 
4595 }
4596 
4597 /**
4598  * dp_h2t_ext_stats_msg_send(): function to construct HTT message to pass to FW
4599  * @pdev: DP PDEV handle
4600  * @stats_type_upload_mask: stats type requested by user
4601  * @config_param_0: extra configuration parameters
4602  * @config_param_1: extra configuration parameters
4603  * @config_param_2: extra configuration parameters
4604  * @config_param_3: extra configuration parameters
4605  * @cookie_val: cookie value
4606  * @cookie_msb: msb of debug status cookie
4607  * @mac_id: mac number
4608  *
4609  * return: QDF STATUS
4610  */
4611 QDF_STATUS dp_h2t_ext_stats_msg_send(struct dp_pdev *pdev,
4612 		uint32_t stats_type_upload_mask, uint32_t config_param_0,
4613 		uint32_t config_param_1, uint32_t config_param_2,
4614 		uint32_t config_param_3, int cookie_val, int cookie_msb,
4615 		uint8_t mac_id)
4616 {
4617 	struct htt_soc *soc = pdev->soc->htt_handle;
4618 	struct dp_htt_htc_pkt *pkt;
4619 	qdf_nbuf_t msg;
4620 	uint32_t *msg_word;
4621 	uint8_t pdev_mask = 0;
4622 	uint8_t *htt_logger_bufp;
4623 	int mac_for_pdev;
4624 	int target_pdev_id;
4625 	QDF_STATUS status;
4626 
4627 	msg = qdf_nbuf_alloc(
4628 			soc->osdev,
4629 			HTT_MSG_BUF_SIZE(HTT_H2T_EXT_STATS_REQ_MSG_SZ),
4630 			HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, TRUE);
4631 
4632 	if (!msg)
4633 		return QDF_STATUS_E_NOMEM;
4634 
4635 	/*TODO:Add support for SOC stats
4636 	 * Bit 0: SOC Stats
4637 	 * Bit 1: Pdev stats for pdev id 0
4638 	 * Bit 2: Pdev stats for pdev id 1
4639 	 * Bit 3: Pdev stats for pdev id 2
4640 	 */
4641 	mac_for_pdev = dp_get_mac_id_for_pdev(mac_id, pdev->pdev_id);
4642 	target_pdev_id =
4643 	dp_get_target_pdev_id_for_host_pdev_id(pdev->soc, mac_for_pdev);
4644 
4645 	pdev_mask = 1 << target_pdev_id;
4646 
4647 	/*
4648 	 * Set the length of the message.
4649 	 * The contribution from the HTC_HDR_ALIGNMENT_PADDING is added
4650 	 * separately during the below call to qdf_nbuf_push_head.
4651 	 * The contribution from the HTC header is added separately inside HTC.
4652 	 */
4653 	if (qdf_nbuf_put_tail(msg, HTT_H2T_EXT_STATS_REQ_MSG_SZ) == NULL) {
4654 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
4655 				"Failed to expand head for HTT_EXT_STATS");
4656 		qdf_nbuf_free(msg);
4657 		return QDF_STATUS_E_FAILURE;
4658 	}
4659 
4660 	msg_word = (uint32_t *) qdf_nbuf_data(msg);
4661 
4662 	qdf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING);
4663 	htt_logger_bufp = (uint8_t *)msg_word;
4664 	*msg_word = 0;
4665 	HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_EXT_STATS_REQ);
4666 	HTT_H2T_EXT_STATS_REQ_PDEV_MASK_SET(*msg_word, pdev_mask);
4667 	HTT_H2T_EXT_STATS_REQ_STATS_TYPE_SET(*msg_word, stats_type_upload_mask);
4668 
4669 	/* word 1 */
4670 	msg_word++;
4671 	*msg_word = 0;
4672 	HTT_H2T_EXT_STATS_REQ_CONFIG_PARAM_SET(*msg_word, config_param_0);
4673 
4674 	/* word 2 */
4675 	msg_word++;
4676 	*msg_word = 0;
4677 	HTT_H2T_EXT_STATS_REQ_CONFIG_PARAM_SET(*msg_word, config_param_1);
4678 
4679 	/* word 3 */
4680 	msg_word++;
4681 	*msg_word = 0;
4682 	HTT_H2T_EXT_STATS_REQ_CONFIG_PARAM_SET(*msg_word, config_param_2);
4683 
4684 	/* word 4 */
4685 	msg_word++;
4686 	*msg_word = 0;
4687 	HTT_H2T_EXT_STATS_REQ_CONFIG_PARAM_SET(*msg_word, config_param_3);
4688 
4689 	HTT_H2T_EXT_STATS_REQ_CONFIG_PARAM_SET(*msg_word, 0);
4690 
4691 	/* word 5 */
4692 	msg_word++;
4693 
4694 	/* word 6 */
4695 	msg_word++;
4696 	*msg_word = 0;
4697 	HTT_H2T_EXT_STATS_REQ_CONFIG_PARAM_SET(*msg_word, cookie_val);
4698 
4699 	/* word 7 */
4700 	msg_word++;
4701 	*msg_word = 0;
4702 	/* Currently Using last 2 bits for pdev_id
4703 	 * For future reference, reserving 3 bits in cookie_msb for pdev_id
4704 	 */
4705 	cookie_msb = (cookie_msb | pdev->pdev_id);
4706 	HTT_H2T_EXT_STATS_REQ_CONFIG_PARAM_SET(*msg_word, cookie_msb);
4707 
4708 	pkt = htt_htc_pkt_alloc(soc);
4709 	if (!pkt) {
4710 		qdf_nbuf_free(msg);
4711 		return QDF_STATUS_E_NOMEM;
4712 	}
4713 
4714 	pkt->soc_ctxt = NULL; /* not used during send-done callback */
4715 
4716 	SET_HTC_PACKET_INFO_TX(&pkt->htc_pkt,
4717 			dp_htt_h2t_send_complete_free_netbuf,
4718 			qdf_nbuf_data(msg), qdf_nbuf_len(msg),
4719 			soc->htc_endpoint,
4720 			/* tag for FW response msg not guaranteed */
4721 			HTC_TX_PACKET_TAG_RUNTIME_PUT);
4722 
4723 	SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg);
4724 	status = DP_HTT_SEND_HTC_PKT(soc, pkt, HTT_H2T_MSG_TYPE_EXT_STATS_REQ,
4725 				     htt_logger_bufp);
4726 
4727 	if (status != QDF_STATUS_SUCCESS) {
4728 		qdf_nbuf_free(msg);
4729 		htt_htc_pkt_free(soc, pkt);
4730 	}
4731 
4732 	return status;
4733 }
4734 
4735 #ifdef QCA_VDEV_STATS_HW_OFFLOAD_SUPPORT
4736 #define HTT_VDEV_TXRX_STATS_RESET_BITMASK_L32_MASK 0xFFFFFFFF
4737 #define HTT_VDEV_TXRX_STATS_RESET_BITMASK_U32_MASK 0xFFFFFFFF00000000
4738 #define HTT_VDEV_TXRX_STATS_RESET_BITMASK_U32_SHIFT 32
4739 
4740 QDF_STATUS dp_h2t_hw_vdev_stats_config_send(struct dp_soc *dpsoc,
4741 					    uint8_t pdev_id, bool enable,
4742 					    bool reset, uint64_t reset_bitmask)
4743 {
4744 	struct htt_soc *soc = dpsoc->htt_handle;
4745 	struct dp_htt_htc_pkt *pkt;
4746 	qdf_nbuf_t msg;
4747 	uint32_t *msg_word;
4748 	uint8_t *htt_logger_bufp;
4749 	QDF_STATUS status;
4750 	int duration;
4751 	uint32_t bitmask;
4752 	int target_pdev_id;
4753 
4754 	msg = qdf_nbuf_alloc(
4755 			soc->osdev,
4756 			HTT_MSG_BUF_SIZE(sizeof(struct htt_h2t_vdevs_txrx_stats_cfg)),
4757 			HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, true);
4758 
4759 	if (!msg) {
4760 		dp_htt_err("%pK: Fail to allocate "
4761 		"HTT_H2T_HW_VDEV_TXRX_STATS_CFG_MSG_SZ msg buffer", dpsoc);
4762 		return QDF_STATUS_E_NOMEM;
4763 	}
4764 
4765 	if (pdev_id != INVALID_PDEV_ID)
4766 		target_pdev_id = DP_SW2HW_MACID(pdev_id);
4767 	else
4768 		target_pdev_id = 0;
4769 
4770 	duration =
4771 	wlan_cfg_get_vdev_stats_hw_offload_timer(dpsoc->wlan_cfg_ctx);
4772 
4773 	/*
4774 	 * Set the length of the message.
4775 	 * The contribution from the HTC_HDR_ALIGNMENT_PADDING is added
4776 	 * separately during the below call to qdf_nbuf_push_head.
4777 	 * The contribution from the HTC header is added separately inside HTC.
4778 	 */
4779 	if (!qdf_nbuf_put_tail(msg,
4780 			       sizeof(struct htt_h2t_vdevs_txrx_stats_cfg))) {
4781 		dp_htt_err("%pK: Failed to expand head for HTT_HW_VDEV_STATS"
4782 			   , dpsoc);
4783 		qdf_nbuf_free(msg);
4784 		return QDF_STATUS_E_FAILURE;
4785 	}
4786 
4787 	msg_word = (uint32_t *)qdf_nbuf_data(msg);
4788 
4789 	qdf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING);
4790 	htt_logger_bufp = (uint8_t *)msg_word;
4791 	*msg_word = 0;
4792 
4793 	HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_VDEVS_TXRX_STATS_CFG);
4794 	HTT_RX_VDEVS_TXRX_STATS_PDEV_ID_SET(*msg_word, target_pdev_id);
4795 
4796 	HTT_RX_VDEVS_TXRX_STATS_ENABLE_SET(*msg_word, enable);
4797 
4798 	HTT_RX_VDEVS_TXRX_STATS_PERIODIC_INTERVAL_SET(*msg_word,
4799 						      (duration >> 3));
4800 
4801 	HTT_RX_VDEVS_TXRX_STATS_RESET_STATS_BITS_SET(*msg_word, reset);
4802 
4803 	msg_word++;
4804 	*msg_word = 0;
4805 	bitmask = (reset_bitmask & HTT_VDEV_TXRX_STATS_RESET_BITMASK_L32_MASK);
4806 	*msg_word = bitmask;
4807 
4808 	msg_word++;
4809 	*msg_word = 0;
4810 	bitmask =
4811 		((reset_bitmask & HTT_VDEV_TXRX_STATS_RESET_BITMASK_U32_MASK) >>
4812 		 HTT_VDEV_TXRX_STATS_RESET_BITMASK_U32_SHIFT);
4813 	*msg_word = bitmask;
4814 
4815 	pkt = htt_htc_pkt_alloc(soc);
4816 	if (!pkt) {
4817 		dp_htt_err("%pK: Fail to allocate dp_htt_htc_pkt buffer",
4818 			   dpsoc);
4819 		qdf_assert(0);
4820 		qdf_nbuf_free(msg);
4821 		return QDF_STATUS_E_NOMEM;
4822 	}
4823 
4824 	pkt->soc_ctxt = NULL; /* not used during send-done callback */
4825 
4826 	SET_HTC_PACKET_INFO_TX(&pkt->htc_pkt,
4827 			       dp_htt_h2t_send_complete_free_netbuf,
4828 			       qdf_nbuf_data(msg), qdf_nbuf_len(msg),
4829 			       soc->htc_endpoint,
4830 			       /* tag for no FW response msg */
4831 			       HTC_TX_PACKET_TAG_RUNTIME_PUT);
4832 
4833 	SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg);
4834 	status = DP_HTT_SEND_HTC_PKT(soc, pkt,
4835 				     HTT_H2T_MSG_TYPE_VDEVS_TXRX_STATS_CFG,
4836 				     htt_logger_bufp);
4837 
4838 	if (status != QDF_STATUS_SUCCESS) {
4839 		qdf_nbuf_free(msg);
4840 		htt_htc_pkt_free(soc, pkt);
4841 	}
4842 
4843 	return status;
4844 }
4845 #else
4846 QDF_STATUS dp_h2t_hw_vdev_stats_config_send(struct dp_soc *dpsoc,
4847 					    uint8_t pdev_id, bool enable,
4848 					    bool reset, uint64_t reset_bitmask)
4849 {
4850 	return QDF_STATUS_SUCCESS;
4851 }
4852 #endif
4853 
4854 /**
4855  * dp_h2t_3tuple_config_send(): function to construct 3 tuple configuration
4856  * HTT message to pass to FW
4857  * @pdev: DP PDEV handle
4858  * @tuple_mask: tuple configuration to report 3 tuple hash value in either
4859  * toeplitz_2_or_4 or flow_id_toeplitz in MSDU START TLV.
4860  * @mac_id: mac id
4861  *
4862  * tuple_mask[1:0]:
4863  *   00 - Do not report 3 tuple hash value
4864  *   10 - Report 3 tuple hash value in toeplitz_2_or_4
4865  *   01 - Report 3 tuple hash value in flow_id_toeplitz
4866  *   11 - Report 3 tuple hash value in both toeplitz_2_or_4 & flow_id_toeplitz
4867  *
4868  * return: QDF STATUS
4869  */
4870 QDF_STATUS dp_h2t_3tuple_config_send(struct dp_pdev *pdev,
4871 				     uint32_t tuple_mask, uint8_t mac_id)
4872 {
4873 	struct htt_soc *soc = pdev->soc->htt_handle;
4874 	struct dp_htt_htc_pkt *pkt;
4875 	qdf_nbuf_t msg;
4876 	uint32_t *msg_word;
4877 	uint8_t *htt_logger_bufp;
4878 	int mac_for_pdev;
4879 	int target_pdev_id;
4880 
4881 	msg = qdf_nbuf_alloc(
4882 			soc->osdev,
4883 			HTT_MSG_BUF_SIZE(HTT_3_TUPLE_HASH_CFG_REQ_BYTES),
4884 			HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, TRUE);
4885 
4886 	if (!msg)
4887 		return QDF_STATUS_E_NOMEM;
4888 
4889 	mac_for_pdev = dp_get_mac_id_for_pdev(mac_id, pdev->pdev_id);
4890 	target_pdev_id =
4891 	dp_get_target_pdev_id_for_host_pdev_id(pdev->soc, mac_for_pdev);
4892 
4893 	/*
4894 	 * Set the length of the message.
4895 	 * The contribution from the HTC_HDR_ALIGNMENT_PADDING is added
4896 	 * separately during the below call to qdf_nbuf_push_head.
4897 	 * The contribution from the HTC header is added separately inside HTC.
4898 	 */
4899 	if (!qdf_nbuf_put_tail(msg, HTT_3_TUPLE_HASH_CFG_REQ_BYTES)) {
4900 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
4901 			  "Failed to expand head for HTT_3TUPLE_CONFIG");
4902 		qdf_nbuf_free(msg);
4903 		return QDF_STATUS_E_FAILURE;
4904 	}
4905 
4906 	dp_htt_info("%pK: config_param_sent 0x%x for target_pdev %d\n -------------",
4907 		    pdev->soc, tuple_mask, target_pdev_id);
4908 
4909 	msg_word = (uint32_t *)qdf_nbuf_data(msg);
4910 	qdf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING);
4911 	htt_logger_bufp = (uint8_t *)msg_word;
4912 
4913 	*msg_word = 0;
4914 	HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_3_TUPLE_HASH_CFG);
4915 	HTT_RX_3_TUPLE_HASH_PDEV_ID_SET(*msg_word, target_pdev_id);
4916 
4917 	msg_word++;
4918 	*msg_word = 0;
4919 	HTT_H2T_FLOW_ID_TOEPLITZ_FIELD_CONFIG_SET(*msg_word, tuple_mask);
4920 	HTT_H2T_TOEPLITZ_2_OR_4_FIELD_CONFIG_SET(*msg_word, tuple_mask);
4921 
4922 	pkt = htt_htc_pkt_alloc(soc);
4923 	if (!pkt) {
4924 		qdf_nbuf_free(msg);
4925 		return QDF_STATUS_E_NOMEM;
4926 	}
4927 
4928 	pkt->soc_ctxt = NULL; /* not used during send-done callback */
4929 
4930 	SET_HTC_PACKET_INFO_TX(
4931 			&pkt->htc_pkt,
4932 			dp_htt_h2t_send_complete_free_netbuf,
4933 			qdf_nbuf_data(msg),
4934 			qdf_nbuf_len(msg),
4935 			soc->htc_endpoint,
4936 			/* tag for no FW response msg */
4937 			HTC_TX_PACKET_TAG_RUNTIME_PUT);
4938 
4939 	SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg);
4940 	DP_HTT_SEND_HTC_PKT(soc, pkt, HTT_H2T_MSG_TYPE_3_TUPLE_HASH_CFG,
4941 			    htt_logger_bufp);
4942 
4943 	return QDF_STATUS_SUCCESS;
4944 }
4945 
4946 /* This macro will revert once proper HTT header will define for
4947  * HTT_H2T_MSG_TYPE_PPDU_STATS_CFG in htt.h file
4948  * */
4949 #if defined(WDI_EVENT_ENABLE)
4950 QDF_STATUS dp_h2t_cfg_stats_msg_send(struct dp_pdev *pdev,
4951 		uint32_t stats_type_upload_mask, uint8_t mac_id)
4952 {
4953 	struct htt_soc *soc = pdev->soc->htt_handle;
4954 	struct dp_htt_htc_pkt *pkt;
4955 	qdf_nbuf_t msg;
4956 	uint32_t *msg_word;
4957 	uint8_t pdev_mask;
4958 	QDF_STATUS status;
4959 
4960 	msg = qdf_nbuf_alloc(
4961 			soc->osdev,
4962 			HTT_MSG_BUF_SIZE(HTT_H2T_PPDU_STATS_CFG_MSG_SZ),
4963 			HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, true);
4964 
4965 	if (!msg) {
4966 		dp_htt_err("%pK: Fail to allocate HTT_H2T_PPDU_STATS_CFG_MSG_SZ msg buffer"
4967 			   , pdev->soc);
4968 		qdf_assert(0);
4969 		return QDF_STATUS_E_NOMEM;
4970 	}
4971 
4972 	/*TODO:Add support for SOC stats
4973 	 * Bit 0: SOC Stats
4974 	 * Bit 1: Pdev stats for pdev id 0
4975 	 * Bit 2: Pdev stats for pdev id 1
4976 	 * Bit 3: Pdev stats for pdev id 2
4977 	 */
4978 	pdev_mask = 1 << dp_get_target_pdev_id_for_host_pdev_id(pdev->soc,
4979 								mac_id);
4980 
4981 	/*
4982 	 * Set the length of the message.
4983 	 * The contribution from the HTC_HDR_ALIGNMENT_PADDING is added
4984 	 * separately during the below call to qdf_nbuf_push_head.
4985 	 * The contribution from the HTC header is added separately inside HTC.
4986 	 */
4987 	if (qdf_nbuf_put_tail(msg, HTT_H2T_PPDU_STATS_CFG_MSG_SZ) == NULL) {
4988 		dp_htt_err("%pK: Failed to expand head for HTT_CFG_STATS"
4989 			   , pdev->soc);
4990 		qdf_nbuf_free(msg);
4991 		return QDF_STATUS_E_FAILURE;
4992 	}
4993 
4994 	msg_word = (uint32_t *) qdf_nbuf_data(msg);
4995 
4996 	qdf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING);
4997 	*msg_word = 0;
4998 	HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_PPDU_STATS_CFG);
4999 	HTT_H2T_PPDU_STATS_CFG_PDEV_MASK_SET(*msg_word, pdev_mask);
5000 	HTT_H2T_PPDU_STATS_CFG_TLV_BITMASK_SET(*msg_word,
5001 			stats_type_upload_mask);
5002 
5003 	pkt = htt_htc_pkt_alloc(soc);
5004 	if (!pkt) {
5005 		dp_htt_err("%pK: Fail to allocate dp_htt_htc_pkt buffer", pdev->soc);
5006 		qdf_assert(0);
5007 		qdf_nbuf_free(msg);
5008 		return QDF_STATUS_E_NOMEM;
5009 	}
5010 
5011 	pkt->soc_ctxt = NULL; /* not used during send-done callback */
5012 
5013 	SET_HTC_PACKET_INFO_TX(&pkt->htc_pkt,
5014 			dp_htt_h2t_send_complete_free_netbuf,
5015 			qdf_nbuf_data(msg), qdf_nbuf_len(msg),
5016 			soc->htc_endpoint,
5017 			/* tag for no FW response msg */
5018 			HTC_TX_PACKET_TAG_RUNTIME_PUT);
5019 
5020 	SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg);
5021 	status = DP_HTT_SEND_HTC_PKT(soc, pkt, HTT_H2T_MSG_TYPE_PPDU_STATS_CFG,
5022 				     (uint8_t *)msg_word);
5023 
5024 	if (status != QDF_STATUS_SUCCESS) {
5025 		qdf_nbuf_free(msg);
5026 		htt_htc_pkt_free(soc, pkt);
5027 	}
5028 
5029 	return status;
5030 }
5031 
5032 qdf_export_symbol(dp_h2t_cfg_stats_msg_send);
5033 #endif
5034 
5035 void
5036 dp_peer_update_inactive_time(struct dp_pdev *pdev, uint32_t tag_type,
5037 			     uint32_t *tag_buf)
5038 {
5039 	struct dp_peer *peer = NULL;
5040 	switch (tag_type) {
5041 	case HTT_STATS_PEER_DETAILS_TAG:
5042 	{
5043 		htt_peer_details_tlv *dp_stats_buf =
5044 			(htt_peer_details_tlv *)tag_buf;
5045 
5046 		pdev->fw_stats_peer_id = dp_stats_buf->sw_peer_id;
5047 	}
5048 	break;
5049 	case HTT_STATS_PEER_STATS_CMN_TAG:
5050 	{
5051 		htt_peer_stats_cmn_tlv *dp_stats_buf =
5052 			(htt_peer_stats_cmn_tlv *)tag_buf;
5053 
5054 		peer = dp_peer_get_ref_by_id(pdev->soc, pdev->fw_stats_peer_id,
5055 					     DP_MOD_ID_HTT);
5056 
5057 		if (peer && !peer->bss_peer) {
5058 			peer->stats.tx.inactive_time =
5059 				dp_stats_buf->inactive_time;
5060 			qdf_event_set(&pdev->fw_peer_stats_event);
5061 		}
5062 		if (peer)
5063 			dp_peer_unref_delete(peer, DP_MOD_ID_HTT);
5064 	}
5065 	break;
5066 	default:
5067 		qdf_err("Invalid tag_type: %u", tag_type);
5068 	}
5069 }
5070 
5071 QDF_STATUS
5072 dp_htt_rx_flow_fst_setup(struct dp_pdev *pdev,
5073 			 struct dp_htt_rx_flow_fst_setup *fse_setup_info)
5074 {
5075 	struct htt_soc *soc = pdev->soc->htt_handle;
5076 	struct dp_htt_htc_pkt *pkt;
5077 	qdf_nbuf_t msg;
5078 	u_int32_t *msg_word;
5079 	struct htt_h2t_msg_rx_fse_setup_t *fse_setup;
5080 	uint8_t *htt_logger_bufp;
5081 	u_int32_t *key;
5082 	QDF_STATUS status;
5083 
5084 	msg = qdf_nbuf_alloc(
5085 		soc->osdev,
5086 		HTT_MSG_BUF_SIZE(sizeof(struct htt_h2t_msg_rx_fse_setup_t)),
5087 		/* reserve room for the HTC header */
5088 		HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, TRUE);
5089 
5090 	if (!msg)
5091 		return QDF_STATUS_E_NOMEM;
5092 
5093 	/*
5094 	 * Set the length of the message.
5095 	 * The contribution from the HTC_HDR_ALIGNMENT_PADDING is added
5096 	 * separately during the below call to qdf_nbuf_push_head.
5097 	 * The contribution from the HTC header is added separately inside HTC.
5098 	 */
5099 	if (!qdf_nbuf_put_tail(msg,
5100 			       sizeof(struct htt_h2t_msg_rx_fse_setup_t))) {
5101 		qdf_err("Failed to expand head for HTT RX_FSE_SETUP msg");
5102 		return QDF_STATUS_E_FAILURE;
5103 	}
5104 
5105 	/* fill in the message contents */
5106 	msg_word = (u_int32_t *)qdf_nbuf_data(msg);
5107 
5108 	memset(msg_word, 0, sizeof(struct htt_h2t_msg_rx_fse_setup_t));
5109 	/* rewind beyond alignment pad to get to the HTC header reserved area */
5110 	qdf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING);
5111 	htt_logger_bufp = (uint8_t *)msg_word;
5112 
5113 	*msg_word = 0;
5114 	HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_RX_FSE_SETUP_CFG);
5115 
5116 	fse_setup = (struct htt_h2t_msg_rx_fse_setup_t *)msg_word;
5117 
5118 	HTT_RX_FSE_SETUP_PDEV_ID_SET(*msg_word, fse_setup_info->pdev_id);
5119 
5120 	msg_word++;
5121 	HTT_RX_FSE_SETUP_NUM_REC_SET(*msg_word, fse_setup_info->max_entries);
5122 	HTT_RX_FSE_SETUP_MAX_SEARCH_SET(*msg_word, fse_setup_info->max_search);
5123 	HTT_RX_FSE_SETUP_IP_DA_SA_PREFIX_SET(*msg_word,
5124 					     fse_setup_info->ip_da_sa_prefix);
5125 
5126 	msg_word++;
5127 	HTT_RX_FSE_SETUP_BASE_ADDR_LO_SET(*msg_word,
5128 					  fse_setup_info->base_addr_lo);
5129 	msg_word++;
5130 	HTT_RX_FSE_SETUP_BASE_ADDR_HI_SET(*msg_word,
5131 					  fse_setup_info->base_addr_hi);
5132 
5133 	key = (u_int32_t *)fse_setup_info->hash_key;
5134 	fse_setup->toeplitz31_0 = *key++;
5135 	fse_setup->toeplitz63_32 = *key++;
5136 	fse_setup->toeplitz95_64 = *key++;
5137 	fse_setup->toeplitz127_96 = *key++;
5138 	fse_setup->toeplitz159_128 = *key++;
5139 	fse_setup->toeplitz191_160 = *key++;
5140 	fse_setup->toeplitz223_192 = *key++;
5141 	fse_setup->toeplitz255_224 = *key++;
5142 	fse_setup->toeplitz287_256 = *key++;
5143 	fse_setup->toeplitz314_288 = *key;
5144 
5145 	msg_word++;
5146 	HTT_RX_FSE_SETUP_HASH_VALUE_SET(*msg_word, fse_setup->toeplitz31_0);
5147 	msg_word++;
5148 	HTT_RX_FSE_SETUP_HASH_VALUE_SET(*msg_word, fse_setup->toeplitz63_32);
5149 	msg_word++;
5150 	HTT_RX_FSE_SETUP_HASH_VALUE_SET(*msg_word, fse_setup->toeplitz95_64);
5151 	msg_word++;
5152 	HTT_RX_FSE_SETUP_HASH_VALUE_SET(*msg_word, fse_setup->toeplitz127_96);
5153 	msg_word++;
5154 	HTT_RX_FSE_SETUP_HASH_VALUE_SET(*msg_word, fse_setup->toeplitz159_128);
5155 	msg_word++;
5156 	HTT_RX_FSE_SETUP_HASH_VALUE_SET(*msg_word, fse_setup->toeplitz191_160);
5157 	msg_word++;
5158 	HTT_RX_FSE_SETUP_HASH_VALUE_SET(*msg_word, fse_setup->toeplitz223_192);
5159 	msg_word++;
5160 	HTT_RX_FSE_SETUP_HASH_VALUE_SET(*msg_word, fse_setup->toeplitz255_224);
5161 	msg_word++;
5162 	HTT_RX_FSE_SETUP_HASH_VALUE_SET(*msg_word, fse_setup->toeplitz287_256);
5163 	msg_word++;
5164 	HTT_RX_FSE_SETUP_HASH_314_288_SET(*msg_word,
5165 					  fse_setup->toeplitz314_288);
5166 
5167 	pkt = htt_htc_pkt_alloc(soc);
5168 	if (!pkt) {
5169 		qdf_err("Fail to allocate dp_htt_htc_pkt buffer");
5170 		qdf_assert(0);
5171 		qdf_nbuf_free(msg);
5172 		return QDF_STATUS_E_RESOURCES; /* failure */
5173 	}
5174 
5175 	pkt->soc_ctxt = NULL; /* not used during send-done callback */
5176 
5177 	SET_HTC_PACKET_INFO_TX(
5178 		&pkt->htc_pkt,
5179 		dp_htt_h2t_send_complete_free_netbuf,
5180 		qdf_nbuf_data(msg),
5181 		qdf_nbuf_len(msg),
5182 		soc->htc_endpoint,
5183 		/* tag for no FW response msg */
5184 		HTC_TX_PACKET_TAG_RUNTIME_PUT);
5185 
5186 	SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg);
5187 
5188 	status = DP_HTT_SEND_HTC_PKT(soc, pkt,
5189 				     HTT_H2T_MSG_TYPE_RX_FSE_SETUP_CFG,
5190 				     htt_logger_bufp);
5191 
5192 	if (status == QDF_STATUS_SUCCESS) {
5193 		dp_info("HTT_H2T RX_FSE_SETUP sent to FW for pdev = %u",
5194 			fse_setup_info->pdev_id);
5195 		QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_ANY, QDF_TRACE_LEVEL_DEBUG,
5196 				   (void *)fse_setup_info->hash_key,
5197 				   fse_setup_info->hash_key_len);
5198 	} else {
5199 		qdf_nbuf_free(msg);
5200 		htt_htc_pkt_free(soc, pkt);
5201 	}
5202 
5203 	return status;
5204 }
5205 
5206 QDF_STATUS
5207 dp_htt_rx_flow_fse_operation(struct dp_pdev *pdev,
5208 			     struct dp_htt_rx_flow_fst_operation *fse_op_info)
5209 {
5210 	struct htt_soc *soc = pdev->soc->htt_handle;
5211 	struct dp_htt_htc_pkt *pkt;
5212 	qdf_nbuf_t msg;
5213 	u_int32_t *msg_word;
5214 	struct htt_h2t_msg_rx_fse_operation_t *fse_operation;
5215 	uint8_t *htt_logger_bufp;
5216 	QDF_STATUS status;
5217 
5218 	msg = qdf_nbuf_alloc(
5219 		soc->osdev,
5220 		HTT_MSG_BUF_SIZE(sizeof(struct htt_h2t_msg_rx_fse_operation_t)),
5221 		/* reserve room for the HTC header */
5222 		HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, TRUE);
5223 	if (!msg)
5224 		return QDF_STATUS_E_NOMEM;
5225 
5226 	/*
5227 	 * Set the length of the message.
5228 	 * The contribution from the HTC_HDR_ALIGNMENT_PADDING is added
5229 	 * separately during the below call to qdf_nbuf_push_head.
5230 	 * The contribution from the HTC header is added separately inside HTC.
5231 	 */
5232 	if (!qdf_nbuf_put_tail(msg,
5233 			       sizeof(struct htt_h2t_msg_rx_fse_operation_t))) {
5234 		qdf_err("Failed to expand head for HTT_RX_FSE_OPERATION msg");
5235 		qdf_nbuf_free(msg);
5236 		return QDF_STATUS_E_FAILURE;
5237 	}
5238 
5239 	/* fill in the message contents */
5240 	msg_word = (u_int32_t *)qdf_nbuf_data(msg);
5241 
5242 	memset(msg_word, 0, sizeof(struct htt_h2t_msg_rx_fse_operation_t));
5243 	/* rewind beyond alignment pad to get to the HTC header reserved area */
5244 	qdf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING);
5245 	htt_logger_bufp = (uint8_t *)msg_word;
5246 
5247 	*msg_word = 0;
5248 	HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_RX_FSE_OPERATION_CFG);
5249 
5250 	fse_operation = (struct htt_h2t_msg_rx_fse_operation_t *)msg_word;
5251 
5252 	HTT_RX_FSE_OPERATION_PDEV_ID_SET(*msg_word, fse_op_info->pdev_id);
5253 	msg_word++;
5254 	HTT_RX_FSE_IPSEC_VALID_SET(*msg_word, false);
5255 	if (fse_op_info->op_code == DP_HTT_FST_CACHE_INVALIDATE_ENTRY) {
5256 		HTT_RX_FSE_OPERATION_SET(*msg_word,
5257 					 HTT_RX_FSE_CACHE_INVALIDATE_ENTRY);
5258 		msg_word++;
5259 		HTT_RX_FSE_OPERATION_IP_ADDR_SET(
5260 		*msg_word,
5261 		qdf_htonl(fse_op_info->rx_flow->flow_tuple_info.src_ip_31_0));
5262 		msg_word++;
5263 		HTT_RX_FSE_OPERATION_IP_ADDR_SET(
5264 		*msg_word,
5265 		qdf_htonl(fse_op_info->rx_flow->flow_tuple_info.src_ip_63_32));
5266 		msg_word++;
5267 		HTT_RX_FSE_OPERATION_IP_ADDR_SET(
5268 		*msg_word,
5269 		qdf_htonl(fse_op_info->rx_flow->flow_tuple_info.src_ip_95_64));
5270 		msg_word++;
5271 		HTT_RX_FSE_OPERATION_IP_ADDR_SET(
5272 		*msg_word,
5273 		qdf_htonl(fse_op_info->rx_flow->flow_tuple_info.src_ip_127_96));
5274 		msg_word++;
5275 		HTT_RX_FSE_OPERATION_IP_ADDR_SET(
5276 		*msg_word,
5277 		qdf_htonl(fse_op_info->rx_flow->flow_tuple_info.dest_ip_31_0));
5278 		msg_word++;
5279 		HTT_RX_FSE_OPERATION_IP_ADDR_SET(
5280 		*msg_word,
5281 		qdf_htonl(fse_op_info->rx_flow->flow_tuple_info.dest_ip_63_32));
5282 		msg_word++;
5283 		HTT_RX_FSE_OPERATION_IP_ADDR_SET(
5284 		*msg_word,
5285 		qdf_htonl(fse_op_info->rx_flow->flow_tuple_info.dest_ip_95_64));
5286 		msg_word++;
5287 		HTT_RX_FSE_OPERATION_IP_ADDR_SET(
5288 		*msg_word,
5289 		qdf_htonl(
5290 		fse_op_info->rx_flow->flow_tuple_info.dest_ip_127_96));
5291 		msg_word++;
5292 		HTT_RX_FSE_SOURCEPORT_SET(
5293 			*msg_word,
5294 			fse_op_info->rx_flow->flow_tuple_info.src_port);
5295 		HTT_RX_FSE_DESTPORT_SET(
5296 			*msg_word,
5297 			fse_op_info->rx_flow->flow_tuple_info.dest_port);
5298 		msg_word++;
5299 		HTT_RX_FSE_L4_PROTO_SET(
5300 			*msg_word,
5301 			fse_op_info->rx_flow->flow_tuple_info.l4_protocol);
5302 	} else if (fse_op_info->op_code == DP_HTT_FST_CACHE_INVALIDATE_FULL) {
5303 		HTT_RX_FSE_OPERATION_SET(*msg_word,
5304 					 HTT_RX_FSE_CACHE_INVALIDATE_FULL);
5305 	} else if (fse_op_info->op_code == DP_HTT_FST_DISABLE) {
5306 		HTT_RX_FSE_OPERATION_SET(*msg_word, HTT_RX_FSE_DISABLE);
5307 	} else if (fse_op_info->op_code == DP_HTT_FST_ENABLE) {
5308 		HTT_RX_FSE_OPERATION_SET(*msg_word, HTT_RX_FSE_ENABLE);
5309 	}
5310 
5311 	pkt = htt_htc_pkt_alloc(soc);
5312 	if (!pkt) {
5313 		qdf_err("Fail to allocate dp_htt_htc_pkt buffer");
5314 		qdf_assert(0);
5315 		qdf_nbuf_free(msg);
5316 		return QDF_STATUS_E_RESOURCES; /* failure */
5317 	}
5318 
5319 	pkt->soc_ctxt = NULL; /* not used during send-done callback */
5320 
5321 	SET_HTC_PACKET_INFO_TX(
5322 		&pkt->htc_pkt,
5323 		dp_htt_h2t_send_complete_free_netbuf,
5324 		qdf_nbuf_data(msg),
5325 		qdf_nbuf_len(msg),
5326 		soc->htc_endpoint,
5327 		/* tag for no FW response msg */
5328 		HTC_TX_PACKET_TAG_RUNTIME_PUT);
5329 
5330 	SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg);
5331 
5332 	status = DP_HTT_SEND_HTC_PKT(soc, pkt,
5333 				     HTT_H2T_MSG_TYPE_RX_FSE_OPERATION_CFG,
5334 				     htt_logger_bufp);
5335 
5336 	if (status == QDF_STATUS_SUCCESS) {
5337 		dp_info("HTT_H2T RX_FSE_OPERATION_CFG sent to FW for pdev = %u",
5338 			fse_op_info->pdev_id);
5339 	} else {
5340 		qdf_nbuf_free(msg);
5341 		htt_htc_pkt_free(soc, pkt);
5342 	}
5343 
5344 	return status;
5345 }
5346 
5347 /**
5348  * dp_htt_rx_fisa_config(): Send HTT msg to configure FISA
5349  * @pdev: DP pdev handle
5350  * @fisa_config: Fisa config struct
5351  *
5352  * Return: Success when HTT message is sent, error on failure
5353  */
5354 QDF_STATUS
5355 dp_htt_rx_fisa_config(struct dp_pdev *pdev,
5356 		      struct dp_htt_rx_fisa_cfg *fisa_config)
5357 {
5358 	struct htt_soc *soc = pdev->soc->htt_handle;
5359 	struct dp_htt_htc_pkt *pkt;
5360 	qdf_nbuf_t msg;
5361 	u_int32_t *msg_word;
5362 	struct htt_h2t_msg_type_fisa_config_t *htt_fisa_config;
5363 	uint8_t *htt_logger_bufp;
5364 	uint32_t len;
5365 	QDF_STATUS status;
5366 
5367 	len = HTT_MSG_BUF_SIZE(sizeof(struct htt_h2t_msg_type_fisa_config_t));
5368 
5369 	msg = qdf_nbuf_alloc(soc->osdev,
5370 			     len,
5371 			     /* reserve room for the HTC header */
5372 			     HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING,
5373 			     4,
5374 			     TRUE);
5375 	if (!msg)
5376 		return QDF_STATUS_E_NOMEM;
5377 
5378 	/*
5379 	 * Set the length of the message.
5380 	 * The contribution from the HTC_HDR_ALIGNMENT_PADDING is added
5381 	 * separately during the below call to qdf_nbuf_push_head.
5382 	 * The contribution from the HTC header is added separately inside HTC.
5383 	 */
5384 	if (!qdf_nbuf_put_tail(msg,
5385 			       sizeof(struct htt_h2t_msg_type_fisa_config_t))) {
5386 		qdf_err("Failed to expand head for HTT_RX_FSE_OPERATION msg");
5387 		qdf_nbuf_free(msg);
5388 		return QDF_STATUS_E_FAILURE;
5389 	}
5390 
5391 	/* fill in the message contents */
5392 	msg_word = (u_int32_t *)qdf_nbuf_data(msg);
5393 
5394 	memset(msg_word, 0, sizeof(struct htt_h2t_msg_type_fisa_config_t));
5395 	/* rewind beyond alignment pad to get to the HTC header reserved area */
5396 	qdf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING);
5397 	htt_logger_bufp = (uint8_t *)msg_word;
5398 
5399 	*msg_word = 0;
5400 	HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_RX_FISA_CFG);
5401 
5402 	htt_fisa_config = (struct htt_h2t_msg_type_fisa_config_t *)msg_word;
5403 
5404 	HTT_RX_FSE_OPERATION_PDEV_ID_SET(*msg_word, htt_fisa_config->pdev_id);
5405 
5406 	msg_word++;
5407 	HTT_RX_FISA_CONFIG_FISA_V2_ENABLE_SET(*msg_word, 1);
5408 	HTT_RX_FISA_CONFIG_FISA_V2_AGGR_LIMIT_SET(*msg_word,
5409 	(fisa_config->max_aggr_supported ? fisa_config->max_aggr_supported : 0xf));
5410 
5411 	msg_word++;
5412 	htt_fisa_config->fisa_timeout_threshold = fisa_config->fisa_timeout;
5413 
5414 	pkt = htt_htc_pkt_alloc(soc);
5415 	if (!pkt) {
5416 		qdf_err("Fail to allocate dp_htt_htc_pkt buffer");
5417 		qdf_assert(0);
5418 		qdf_nbuf_free(msg);
5419 		return QDF_STATUS_E_RESOURCES; /* failure */
5420 	}
5421 
5422 	pkt->soc_ctxt = NULL; /* not used during send-done callback */
5423 
5424 	SET_HTC_PACKET_INFO_TX(&pkt->htc_pkt,
5425 			       dp_htt_h2t_send_complete_free_netbuf,
5426 			       qdf_nbuf_data(msg),
5427 			       qdf_nbuf_len(msg),
5428 			       soc->htc_endpoint,
5429 			       /* tag for no FW response msg */
5430 			       HTC_TX_PACKET_TAG_RUNTIME_PUT);
5431 
5432 	SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg);
5433 
5434 	status = DP_HTT_SEND_HTC_PKT(soc, pkt, HTT_H2T_MSG_TYPE_RX_FISA_CFG,
5435 				     htt_logger_bufp);
5436 
5437 	if (status == QDF_STATUS_SUCCESS) {
5438 		dp_info("HTT_H2T_MSG_TYPE_RX_FISA_CFG sent to FW for pdev = %u",
5439 			fisa_config->pdev_id);
5440 	} else {
5441 		qdf_nbuf_free(msg);
5442 		htt_htc_pkt_free(soc, pkt);
5443 	}
5444 
5445 	return status;
5446 }
5447 
5448 #ifdef WLAN_SUPPORT_PPEDS
5449 /**
5450  * dp_htt_rxdma_rxole_ppe_cfg_set() - Send RxOLE and RxDMA PPE config
5451  * @soc: Data path SoC handle
5452  * @cfg: RxDMA and RxOLE PPE config
5453  *
5454  * Return: Success when HTT message is sent, error on failure
5455  */
5456 QDF_STATUS
5457 dp_htt_rxdma_rxole_ppe_cfg_set(struct dp_soc *soc,
5458 			       struct dp_htt_rxdma_rxole_ppe_config *cfg)
5459 {
5460 	struct htt_soc *htt_handle = soc->htt_handle;
5461 	uint32_t len;
5462 	qdf_nbuf_t msg;
5463 	u_int32_t *msg_word;
5464 	QDF_STATUS status;
5465 	uint8_t *htt_logger_bufp;
5466 	struct dp_htt_htc_pkt *pkt;
5467 
5468 	len = HTT_MSG_BUF_SIZE(
5469 	      sizeof(struct htt_h2t_msg_type_rxdma_rxole_ppe_cfg_t));
5470 
5471 	msg = qdf_nbuf_alloc(soc->osdev,
5472 			     len,
5473 			     /* reserve room for the HTC header */
5474 			     HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING,
5475 			     4,
5476 			     TRUE);
5477 	if (!msg)
5478 		return QDF_STATUS_E_NOMEM;
5479 
5480 	/*
5481 	 * Set the length of the message.
5482 	 * The contribution from the HTC_HDR_ALIGNMENT_PADDING is added
5483 	 * separately during the below call to qdf_nbuf_push_head.
5484 	 * The contribution from the HTC header is added separately inside HTC.
5485 	 */
5486 	if (!qdf_nbuf_put_tail(
5487 		msg, sizeof(struct htt_h2t_msg_type_rxdma_rxole_ppe_cfg_t))) {
5488 		qdf_err("Failed to expand head for HTT_H2T_MSG_TYPE_RXDMA_RXOLE_PPE_CFG msg");
5489 		qdf_nbuf_free(msg);
5490 		return QDF_STATUS_E_FAILURE;
5491 	}
5492 
5493 	/* fill in the message contents */
5494 	msg_word = (u_int32_t *)qdf_nbuf_data(msg);
5495 
5496 	memset(msg_word, 0,
5497 	       sizeof(struct htt_h2t_msg_type_rxdma_rxole_ppe_cfg_t));
5498 
5499 	/* Rewind beyond alignment pad to get to the HTC header reserved area */
5500 	qdf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING);
5501 	htt_logger_bufp = (uint8_t *)msg_word;
5502 
5503 	*msg_word = 0;
5504 	HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_RXDMA_RXOLE_PPE_CFG);
5505 	HTT_PPE_CFG_OVERRIDE_SET(*msg_word, cfg->override);
5506 	HTT_PPE_CFG_REO_DEST_IND_SET(
5507 			*msg_word, cfg->reo_destination_indication);
5508 	HTT_PPE_CFG_MULTI_BUF_MSDU_OVERRIDE_EN_SET(
5509 			*msg_word, cfg->multi_buffer_msdu_override_en);
5510 	HTT_PPE_CFG_INTRA_BSS_OVERRIDE_EN_SET(
5511 			*msg_word, cfg->intra_bss_override);
5512 	HTT_PPE_CFG_DECAP_RAW_OVERRIDE_EN_SET(
5513 			*msg_word, cfg->decap_raw_override);
5514 	HTT_PPE_CFG_DECAP_NWIFI_OVERRIDE_EN_SET(
5515 			*msg_word, cfg->decap_nwifi_override);
5516 	HTT_PPE_CFG_IP_FRAG_OVERRIDE_EN_SET(
5517 			*msg_word, cfg->ip_frag_override);
5518 
5519 	pkt = htt_htc_pkt_alloc(htt_handle);
5520 	if (!pkt) {
5521 		qdf_err("Fail to allocate dp_htt_htc_pkt buffer");
5522 		qdf_assert(0);
5523 		qdf_nbuf_free(msg);
5524 		return QDF_STATUS_E_RESOURCES; /* failure */
5525 	}
5526 
5527 	pkt->soc_ctxt = NULL; /* not used during send-done callback */
5528 
5529 	SET_HTC_PACKET_INFO_TX(&pkt->htc_pkt,
5530 			       dp_htt_h2t_send_complete_free_netbuf,
5531 			       qdf_nbuf_data(msg),
5532 			       qdf_nbuf_len(msg),
5533 			       htt_handle->htc_endpoint,
5534 			       /* tag for no FW response msg */
5535 			       HTC_TX_PACKET_TAG_RUNTIME_PUT);
5536 
5537 	SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg);
5538 
5539 	status = DP_HTT_SEND_HTC_PKT(htt_handle, pkt,
5540 				     HTT_H2T_MSG_TYPE_RXDMA_RXOLE_PPE_CFG,
5541 				     htt_logger_bufp);
5542 
5543 	if (status != QDF_STATUS_SUCCESS) {
5544 		qdf_nbuf_free(msg);
5545 		htt_htc_pkt_free(htt_handle, pkt);
5546 		return status;
5547 	}
5548 
5549 	dp_info("HTT_H2T_MSG_TYPE_RXDMA_RXOLE_PPE_CFG sent");
5550 	return status;
5551 }
5552 #endif /* WLAN_SUPPORT_PPEDS */
5553 
5554 /**
5555  * dp_bk_pressure_stats_handler(): worker function to print back pressure
5556  *				   stats
5557  *
5558  * @context : argument to work function
5559  */
5560 static void dp_bk_pressure_stats_handler(void *context)
5561 {
5562 	struct dp_pdev *pdev = (struct dp_pdev *)context;
5563 	struct dp_soc_srngs_state *soc_srngs_state = NULL;
5564 	const char *ring_name;
5565 	int i;
5566 	struct dp_srng_ring_state *ring_state;
5567 	bool empty_flag;
5568 
5569 	qdf_spin_lock_bh(&pdev->bkp_stats.list_lock);
5570 
5571 	/* Extract only first entry for printing in one work event */
5572 	if (pdev->bkp_stats.queue_depth &&
5573 	    !TAILQ_EMPTY(&pdev->bkp_stats.list)) {
5574 		soc_srngs_state = TAILQ_FIRST(&pdev->bkp_stats.list);
5575 		TAILQ_REMOVE(&pdev->bkp_stats.list, soc_srngs_state,
5576 			     list_elem);
5577 		pdev->bkp_stats.queue_depth--;
5578 	}
5579 
5580 	empty_flag = TAILQ_EMPTY(&pdev->bkp_stats.list);
5581 	qdf_spin_unlock_bh(&pdev->bkp_stats.list_lock);
5582 
5583 	if (soc_srngs_state) {
5584 		DP_PRINT_STATS("### BKP stats for seq_num %u START ###",
5585 			       soc_srngs_state->seq_num);
5586 		for (i = 0; i < soc_srngs_state->max_ring_id; i++) {
5587 			ring_state = &soc_srngs_state->ring_state[i];
5588 			ring_name = dp_srng_get_str_from_hal_ring_type
5589 						(ring_state->ring_type);
5590 			DP_PRINT_STATS("%s: SW:Head pointer = %d Tail Pointer = %d\n",
5591 				       ring_name,
5592 				       ring_state->sw_head,
5593 				       ring_state->sw_tail);
5594 
5595 			DP_PRINT_STATS("%s: HW:Head pointer = %d Tail Pointer = %d\n",
5596 				       ring_name,
5597 				       ring_state->hw_head,
5598 				       ring_state->hw_tail);
5599 		}
5600 
5601 		DP_PRINT_STATS("### BKP stats for seq_num %u COMPLETE ###",
5602 			       soc_srngs_state->seq_num);
5603 		qdf_mem_free(soc_srngs_state);
5604 	}
5605 	dp_print_napi_stats(pdev->soc);
5606 
5607 	/* Schedule work again if queue is not empty */
5608 	if (!empty_flag)
5609 		qdf_queue_work(0, pdev->bkp_stats.work_queue,
5610 			       &pdev->bkp_stats.work);
5611 }
5612 
5613 void dp_pdev_bkp_stats_detach(struct dp_pdev *pdev)
5614 {
5615 	struct dp_soc_srngs_state *ring_state, *ring_state_next;
5616 
5617 	if (!pdev->bkp_stats.work_queue)
5618 		return;
5619 
5620 	qdf_flush_workqueue(0, pdev->bkp_stats.work_queue);
5621 	qdf_destroy_workqueue(0, pdev->bkp_stats.work_queue);
5622 	qdf_flush_work(&pdev->bkp_stats.work);
5623 	qdf_disable_work(&pdev->bkp_stats.work);
5624 	qdf_spin_lock_bh(&pdev->bkp_stats.list_lock);
5625 	TAILQ_FOREACH_SAFE(ring_state, &pdev->bkp_stats.list,
5626 			   list_elem, ring_state_next) {
5627 		TAILQ_REMOVE(&pdev->bkp_stats.list, ring_state,
5628 			     list_elem);
5629 		qdf_mem_free(ring_state);
5630 	}
5631 	qdf_spin_unlock_bh(&pdev->bkp_stats.list_lock);
5632 	qdf_spinlock_destroy(&pdev->bkp_stats.list_lock);
5633 }
5634 
5635 QDF_STATUS dp_pdev_bkp_stats_attach(struct dp_pdev *pdev)
5636 {
5637 	TAILQ_INIT(&pdev->bkp_stats.list);
5638 	pdev->bkp_stats.seq_num = 0;
5639 	pdev->bkp_stats.queue_depth = 0;
5640 
5641 	qdf_create_work(0, &pdev->bkp_stats.work,
5642 			dp_bk_pressure_stats_handler, pdev);
5643 
5644 	pdev->bkp_stats.work_queue =
5645 		qdf_alloc_unbound_workqueue("dp_bkp_work_queue");
5646 	if (!pdev->bkp_stats.work_queue)
5647 		goto fail;
5648 
5649 	qdf_spinlock_create(&pdev->bkp_stats.list_lock);
5650 	return QDF_STATUS_SUCCESS;
5651 
5652 fail:
5653 	dp_htt_alert("BKP stats attach failed");
5654 	qdf_flush_work(&pdev->bkp_stats.work);
5655 	qdf_disable_work(&pdev->bkp_stats.work);
5656 	return QDF_STATUS_E_FAILURE;
5657 }
5658 
5659 #ifdef DP_UMAC_HW_RESET_SUPPORT
5660 QDF_STATUS dp_htt_umac_reset_send_setup_cmd(
5661 		struct dp_soc *soc,
5662 		const struct dp_htt_umac_reset_setup_cmd_params *setup_params)
5663 {
5664 	struct htt_soc *htt_handle = soc->htt_handle;
5665 	uint32_t len;
5666 	qdf_nbuf_t msg;
5667 	u_int32_t *msg_word;
5668 	QDF_STATUS status;
5669 	uint8_t *htt_logger_bufp;
5670 	struct dp_htt_htc_pkt *pkt;
5671 
5672 	len = HTT_MSG_BUF_SIZE(
5673 		HTT_H2T_UMAC_HANG_RECOVERY_PREREQUISITE_SETUP_BYTES);
5674 
5675 	msg = qdf_nbuf_alloc(soc->osdev,
5676 			     len,
5677 			     /* reserve room for the HTC header */
5678 			     HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING,
5679 			     4,
5680 			     TRUE);
5681 	if (!msg)
5682 		return QDF_STATUS_E_NOMEM;
5683 
5684 	/*
5685 	 * Set the length of the message.
5686 	 * The contribution from the HTC_HDR_ALIGNMENT_PADDING is added
5687 	 * separately during the below call to qdf_nbuf_push_head.
5688 	 * The contribution from the HTC header is added separately inside HTC.
5689 	 */
5690 	if (!qdf_nbuf_put_tail(
5691 		msg, HTT_H2T_UMAC_HANG_RECOVERY_PREREQUISITE_SETUP_BYTES)) {
5692 		dp_htt_err("Failed to expand head");
5693 		qdf_nbuf_free(msg);
5694 		return QDF_STATUS_E_FAILURE;
5695 	}
5696 
5697 	/* fill in the message contents */
5698 	msg_word = (uint32_t *)qdf_nbuf_data(msg);
5699 
5700 	/* Rewind beyond alignment pad to get to the HTC header reserved area */
5701 	qdf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING);
5702 	htt_logger_bufp = (uint8_t *)msg_word;
5703 
5704 	qdf_mem_zero(msg_word,
5705 		     HTT_H2T_UMAC_HANG_RECOVERY_PREREQUISITE_SETUP_BYTES);
5706 
5707 	HTT_H2T_MSG_TYPE_SET(
5708 		*msg_word,
5709 		HTT_H2T_MSG_TYPE_UMAC_HANG_RECOVERY_PREREQUISITE_SETUP);
5710 	HTT_H2T_UMAC_HANG_RECOVERY_PREREQUISITE_SETUP_T2H_MSG_METHOD_SET(
5711 		*msg_word, htt_umac_hang_recovery_msg_t2h_msi_and_h2t_polling);
5712 	HTT_H2T_UMAC_HANG_RECOVERY_PREREQUISITE_SETUP_H2T_MSG_METHOD_SET(
5713 		*msg_word, htt_umac_hang_recovery_msg_t2h_msi_and_h2t_polling);
5714 
5715 	msg_word++;
5716 	*msg_word = setup_params->msi_data;
5717 
5718 	msg_word++;
5719 	*msg_word = sizeof(htt_umac_hang_recovery_msg_shmem_t);
5720 
5721 	msg_word++;
5722 	*msg_word = setup_params->shmem_addr_low;
5723 
5724 	msg_word++;
5725 	*msg_word = setup_params->shmem_addr_high;
5726 
5727 	pkt = htt_htc_pkt_alloc(htt_handle);
5728 	if (!pkt) {
5729 		qdf_err("Fail to allocate dp_htt_htc_pkt buffer");
5730 		qdf_assert(0);
5731 		qdf_nbuf_free(msg);
5732 		return QDF_STATUS_E_NOMEM;
5733 	}
5734 
5735 	pkt->soc_ctxt = NULL; /* not used during send-done callback */
5736 
5737 	SET_HTC_PACKET_INFO_TX(&pkt->htc_pkt,
5738 			       dp_htt_h2t_send_complete_free_netbuf,
5739 			       qdf_nbuf_data(msg),
5740 			       qdf_nbuf_len(msg),
5741 			       htt_handle->htc_endpoint,
5742 			       /* tag for no FW response msg */
5743 			       HTC_TX_PACKET_TAG_RUNTIME_PUT);
5744 
5745 	SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg);
5746 
5747 	status = DP_HTT_SEND_HTC_PKT(
5748 			htt_handle, pkt,
5749 			HTT_H2T_MSG_TYPE_UMAC_HANG_RECOVERY_PREREQUISITE_SETUP,
5750 			htt_logger_bufp);
5751 
5752 	if (QDF_IS_STATUS_ERROR(status)) {
5753 		qdf_nbuf_free(msg);
5754 		htt_htc_pkt_free(htt_handle, pkt);
5755 		return status;
5756 	}
5757 
5758 	dp_info("HTT_H2T_MSG_TYPE_UMAC_HANG_RECOVERY_PREREQUISITE_SETUP sent");
5759 	return status;
5760 }
5761 
5762 QDF_STATUS dp_htt_umac_reset_send_start_pre_reset_cmd(
5763 		struct dp_soc *soc, bool is_initiator, bool is_umac_hang)
5764 {
5765 	struct htt_soc *htt_handle = soc->htt_handle;
5766 	uint32_t len;
5767 	qdf_nbuf_t msg;
5768 	u_int32_t *msg_word;
5769 	QDF_STATUS status;
5770 	uint8_t *htt_logger_bufp;
5771 	struct dp_htt_htc_pkt *pkt;
5772 
5773 	len = HTT_MSG_BUF_SIZE(
5774 		HTT_H2T_UMAC_HANG_RECOVERY_START_PRE_RESET_BYTES);
5775 
5776 	msg = qdf_nbuf_alloc(soc->osdev,
5777 			     len,
5778 			     /* reserve room for the HTC header */
5779 			     HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING,
5780 			     4,
5781 			     TRUE);
5782 	if (!msg)
5783 		return QDF_STATUS_E_NOMEM;
5784 
5785 	/*
5786 	 * Set the length of the message.
5787 	 * The contribution from the HTC_HDR_ALIGNMENT_PADDING is added
5788 	 * separately during the below call to qdf_nbuf_push_head.
5789 	 * The contribution from the HTC header is added separately inside HTC.
5790 	 */
5791 	if (!qdf_nbuf_put_tail(
5792 		msg, HTT_H2T_UMAC_HANG_RECOVERY_START_PRE_RESET_BYTES)) {
5793 		dp_htt_err("Failed to expand head");
5794 		qdf_nbuf_free(msg);
5795 		return QDF_STATUS_E_FAILURE;
5796 	}
5797 
5798 	/* fill in the message contents */
5799 	msg_word = (uint32_t *)qdf_nbuf_data(msg);
5800 
5801 	/* Rewind beyond alignment pad to get to the HTC header reserved area */
5802 	qdf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING);
5803 	htt_logger_bufp = (uint8_t *)msg_word;
5804 
5805 	qdf_mem_zero(msg_word,
5806 		     HTT_H2T_UMAC_HANG_RECOVERY_START_PRE_RESET_BYTES);
5807 
5808 	HTT_H2T_MSG_TYPE_SET(
5809 		*msg_word,
5810 		HTT_H2T_MSG_TYPE_UMAC_HANG_RECOVERY_SOC_START_PRE_RESET);
5811 
5812 	HTT_H2T_UMAC_HANG_RECOVERY_START_PRE_RESET_IS_INITIATOR_SET(
5813 		*msg_word, is_initiator);
5814 
5815 	HTT_H2T_UMAC_HANG_RECOVERY_START_PRE_RESET_IS_UMAC_HANG_SET(
5816 		*msg_word, is_umac_hang);
5817 
5818 	pkt = htt_htc_pkt_alloc(htt_handle);
5819 	if (!pkt) {
5820 		qdf_err("Fail to allocate dp_htt_htc_pkt buffer");
5821 		qdf_assert(0);
5822 		qdf_nbuf_free(msg);
5823 		return QDF_STATUS_E_NOMEM;
5824 	}
5825 
5826 	pkt->soc_ctxt = NULL; /* not used during send-done callback */
5827 
5828 	SET_HTC_PACKET_INFO_TX(&pkt->htc_pkt,
5829 			       dp_htt_h2t_send_complete_free_netbuf,
5830 			       qdf_nbuf_data(msg),
5831 			       qdf_nbuf_len(msg),
5832 			       htt_handle->htc_endpoint,
5833 			       /* tag for no FW response msg */
5834 			       HTC_TX_PACKET_TAG_RUNTIME_PUT);
5835 
5836 	SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg);
5837 
5838 	status = DP_HTT_SEND_HTC_PKT(
5839 			htt_handle, pkt,
5840 			HTT_H2T_MSG_TYPE_UMAC_HANG_RECOVERY_SOC_START_PRE_RESET,
5841 			htt_logger_bufp);
5842 
5843 	if (QDF_IS_STATUS_ERROR(status)) {
5844 		qdf_nbuf_free(msg);
5845 		htt_htc_pkt_free(htt_handle, pkt);
5846 		return status;
5847 	}
5848 
5849 	dp_info("HTT_H2T_MSG_TYPE_UMAC_HANG_RECOVERY_SOC_START_PRE_RESET sent");
5850 	return status;
5851 }
5852 #endif
5853