xref: /wlan-dirver/qcacld-3.0/core/wma/src/wma_features.c (revision 63d7e2a202b3cd37d6c1c20a39582b297a267b6b)
1 /*
2  * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for
5  * any purpose with or without fee is hereby granted, provided that the
6  * above copyright notice and this permission notice appear in all
7  * copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /**
20  *  DOC:    wma_features.c
21  *  This file contains different features related functions like WoW,
22  *  Offloads, TDLS etc.
23  */
24 
25 /* Header files */
26 
27 #include "cds_ieee80211_common.h"	/* ieee80211_frame */
28 #include "wma.h"
29 #include "wma_api.h"
30 #include "cds_api.h"
31 #include "wmi_unified_api.h"
32 #include "wlan_qct_sys.h"
33 #include "wni_api.h"
34 #include "ani_global.h"
35 #include "wmi_unified.h"
36 #include "wni_cfg.h"
37 #include <cdp_txrx_tx_delay.h>
38 #include <cdp_txrx_peer_ops.h>
39 
40 #include "qdf_nbuf.h"
41 #include "qdf_types.h"
42 #include "qdf_mem.h"
43 #include "qdf_util.h"
44 
45 #include "wma_types.h"
46 #include "lim_api.h"
47 #include "lim_session_utils.h"
48 #include "cfg_ucfg_api.h"
49 #include "cds_utils.h"
50 #include "cfg_qos.h"
51 #if !defined(REMOVE_PKT_LOG)
52 #include "pktlog_ac.h"
53 #endif /* REMOVE_PKT_LOG */
54 
55 #include "dbglog_host.h"
56 #include "csr_api.h"
57 #include "ol_fw.h"
58 
59 #include "wma_internal.h"
60 #include "wma_nan_datapath.h"
61 #include <cdp_txrx_handle.h>
62 #include "wlan_pmo_ucfg_api.h"
63 #include <target_if_scan.h>
64 #include "wlan_reg_services_api.h"
65 #include "wlan_roam_debug.h"
66 #include <wlan_cp_stats_mc_ucfg_api.h>
67 #ifdef WLAN_FEATURE_NAN
68 #include "target_if_nan.h"
69 #endif
70 #include "wlan_scan_api.h"
71 #include <wlan_crypto_global_api.h>
72 #include "cdp_txrx_host_stats.h"
73 
74 /**
75  * WMA_SET_VDEV_IE_SOURCE_HOST - Flag to identify the source of VDEV SET IE
76  * command. The value is 0x0 for the VDEV SET IE WMI commands from mobile
77  * MCL platform.
78  */
79 #define WMA_SET_VDEV_IE_SOURCE_HOST 0x0
80 
81 static bool is_wakeup_event_console_logs_enabled = false;
82 
83 void wma_set_wakeup_logs_to_console(bool value)
84 {
85 	is_wakeup_event_console_logs_enabled = value;
86 }
87 
88 #if defined(FEATURE_WLAN_DIAG_SUPPORT)
89 /**
90  * qdf_wma_wow_wakeup_stats_event()- send wow wakeup stats
91  * @tp_wma_handle wma: WOW wakeup packet counter
92  *
93  * This function sends wow wakeup stats diag event
94  *
95  * Return: void.
96  */
97 static inline void qdf_wma_wow_wakeup_stats_event(tp_wma_handle wma)
98 {
99 	QDF_STATUS status;
100 	struct wake_lock_stats stats = {0};
101 
102 	WLAN_HOST_DIAG_EVENT_DEF(wow_stats,
103 	struct host_event_wlan_powersave_wow_stats);
104 
105 	status = ucfg_mc_cp_stats_get_psoc_wake_lock_stats(wma->psoc, &stats);
106 	if (QDF_IS_STATUS_ERROR(status))
107 		return;
108 	qdf_mem_zero(&wow_stats, sizeof(wow_stats));
109 
110 	wow_stats.wow_bcast_wake_up_count = stats.bcast_wake_up_count;
111 	wow_stats.wow_ipv4_mcast_wake_up_count = stats.ipv4_mcast_wake_up_count;
112 	wow_stats.wow_ipv6_mcast_wake_up_count = stats.ipv6_mcast_wake_up_count;
113 	wow_stats.wow_ipv6_mcast_ra_stats = stats.ipv6_mcast_ra_stats;
114 	wow_stats.wow_ipv6_mcast_ns_stats = stats.ipv6_mcast_ns_stats;
115 	wow_stats.wow_ipv6_mcast_na_stats = stats.ipv6_mcast_na_stats;
116 	wow_stats.wow_pno_match_wake_up_count = stats.pno_match_wake_up_count;
117 	wow_stats.wow_pno_complete_wake_up_count =
118 				stats.pno_complete_wake_up_count;
119 	wow_stats.wow_gscan_wake_up_count = stats.gscan_wake_up_count;
120 	wow_stats.wow_low_rssi_wake_up_count = stats.low_rssi_wake_up_count;
121 	wow_stats.wow_rssi_breach_wake_up_count =
122 				stats.rssi_breach_wake_up_count;
123 	wow_stats.wow_icmpv4_count = stats.icmpv4_count;
124 	wow_stats.wow_icmpv6_count = stats.icmpv6_count;
125 	wow_stats.wow_oem_response_wake_up_count =
126 				stats.oem_response_wake_up_count;
127 
128 	WLAN_HOST_DIAG_EVENT_REPORT(&wow_stats, EVENT_WLAN_POWERSAVE_WOW_STATS);
129 }
130 #else
131 static inline void qdf_wma_wow_wakeup_stats_event(tp_wma_handle wma)
132 {
133 	return;
134 }
135 #endif
136 
137 #ifdef FEATURE_WLAN_AUTO_SHUTDOWN
138 /**
139  * wma_wake_reason_auto_shutdown() - to post auto shutdown event to sme
140  *
141  * Return: 0 for success or error code
142  */
143 static int wma_wake_reason_auto_shutdown(void)
144 {
145 	QDF_STATUS qdf_status;
146 	struct scheduler_msg sme_msg = { 0 };
147 
148 	sme_msg.type = eWNI_SME_AUTO_SHUTDOWN_IND;
149 	qdf_status = scheduler_post_message(QDF_MODULE_ID_WMA,
150 					    QDF_MODULE_ID_SME,
151 					    QDF_MODULE_ID_SME, &sme_msg);
152 	if (!QDF_IS_STATUS_SUCCESS(qdf_status))
153 		wma_err("Fail to post eWNI_SME_AUTO_SHUTDOWN_IND msg to SME");
154 
155 	return qdf_status_to_os_return(qdf_status);
156 }
157 #else
158 static inline int wma_wake_reason_auto_shutdown(void)
159 {
160 	return 0;
161 }
162 #endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
163 
164 #ifdef FEATURE_WLAN_SCAN_PNO
165 static int wma_wake_reason_nlod(t_wma_handle *wma, uint8_t vdev_id)
166 {
167 	wmi_nlo_event nlo_event = { .vdev_id = vdev_id };
168 	WMI_NLO_MATCH_EVENTID_param_tlvs param = { .fixed_param = &nlo_event };
169 
170 	return target_if_nlo_match_event_handler(wma, (uint8_t *)&param,
171 						 sizeof(param));
172 }
173 #else
174 static inline int wma_wake_reason_nlod(t_wma_handle *wma, uint8_t vdev_id)
175 {
176 	return 0;
177 }
178 #endif /* FEATURE_WLAN_SCAN_PNO */
179 
180 #ifdef WLAN_FEATURE_NAN
181 /**
182  * wma_nan_rsp_handler_callback() - call NAN Discovery event handler
183  * @handle: wma handle
184  * @event: event buffer
185  * @len: buffer length
186  *
187  * Return: 0 for success or error code
188  */
189 static int wma_nan_rsp_handler_callback(void *handle, uint8_t *event,
190 					uint32_t len)
191 {
192 	return target_if_nan_rsp_handler(handle, event, len);
193 }
194 #else
195 static inline int wma_nan_rsp_handler_callback(void *handle, uint8_t *event,
196 					       uint32_t len)
197 {
198 	return 0;
199 }
200 #endif
201 
202 /**
203  * wma_get_snr() - get RSSI from fw
204  * @psnr_req: request params
205  *
206  * Return: QDF status
207  */
208 QDF_STATUS wma_get_snr(tAniGetSnrReq *psnr_req)
209 {
210 	tAniGetSnrReq *psnr_req_bkp;
211 	tp_wma_handle wma_handle = NULL;
212 	struct wma_txrx_node *intr;
213 
214 	wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
215 	if (!wma_handle)
216 		return QDF_STATUS_E_FAULT;
217 
218 	intr = &wma_handle->interfaces[psnr_req->sessionId];
219 	/* command is in progress */
220 	if (intr->psnr_req) {
221 		wma_err("previous snr request is pending");
222 		return QDF_STATUS_SUCCESS;
223 	}
224 
225 	psnr_req_bkp = qdf_mem_malloc(sizeof(tAniGetSnrReq));
226 	if (!psnr_req_bkp)
227 		return QDF_STATUS_E_NOMEM;
228 
229 	qdf_mem_zero(psnr_req_bkp, sizeof(tAniGetSnrReq));
230 	psnr_req_bkp->pDevContext = psnr_req->pDevContext;
231 	psnr_req_bkp->snrCallback = psnr_req->snrCallback;
232 	intr->psnr_req = (void *)psnr_req_bkp;
233 
234 	if (wmi_unified_snr_cmd(wma_handle->wmi_handle,
235 				 psnr_req->sessionId)) {
236 		wma_err("Failed to send host stats request to fw");
237 		qdf_mem_free(psnr_req_bkp);
238 		intr->psnr_req = NULL;
239 		return QDF_STATUS_E_FAILURE;
240 	}
241 
242 	return QDF_STATUS_SUCCESS;
243 }
244 
245 void wma_get_rx_retry_cnt(struct mac_context *mac, uint8_t vdev_id,
246 			  uint8_t *mac_addr)
247 {
248 	struct cdp_peer_stats *peer_stats;
249 	QDF_STATUS status;
250 
251 	peer_stats = qdf_mem_malloc(sizeof(*peer_stats));
252 	if (!peer_stats)
253 		return;
254 
255 	status = cdp_host_get_peer_stats(cds_get_context(QDF_MODULE_ID_SOC),
256 					 vdev_id, mac_addr, peer_stats);
257 
258 	if (QDF_IS_STATUS_ERROR(status)) {
259 		wma_err("Failed to get peer stats");
260 		goto exit;
261 	}
262 
263 	mac->rx_retry_cnt = peer_stats->rx.rx_retries;
264 	wma_debug("Rx retry count %d, Peer" QDF_MAC_ADDR_FMT, mac->rx_retry_cnt,
265 		  QDF_MAC_ADDR_REF(mac_addr));
266 
267 exit:
268 	qdf_mem_free(peer_stats);
269 }
270 
271 /**
272  * wma_process_link_status_req() - process link status request from UMAC
273  * @wma: wma handle
274  * @pGetLinkStatus: get link params
275  *
276  * Return: none
277  */
278 void wma_process_link_status_req(tp_wma_handle wma,
279 				 tAniGetLinkStatus *pGetLinkStatus)
280 {
281 	struct link_status_params cmd = {0};
282 	struct wma_txrx_node *iface =
283 		&wma->interfaces[pGetLinkStatus->sessionId];
284 
285 	if (iface->plink_status_req) {
286 		wma_err("previous link status request is pending,deleting the new request");
287 		qdf_mem_free(pGetLinkStatus);
288 		return;
289 	}
290 
291 	iface->plink_status_req = pGetLinkStatus;
292 	cmd.vdev_id = pGetLinkStatus->sessionId;
293 	if (wmi_unified_link_status_req_cmd(wma->wmi_handle, &cmd)) {
294 		wma_err("Failed to send WMI link  status request to fw");
295 		iface->plink_status_req = NULL;
296 		goto end;
297 	}
298 
299 	return;
300 
301 end:
302 	wma_post_link_status(pGetLinkStatus, LINK_STATUS_LEGACY);
303 }
304 
305 #ifdef WLAN_FEATURE_TSF
306 /**
307  * wma_vdev_tsf_handler() - handle tsf event indicated by FW
308  * @handle: wma context
309  * @data: event buffer
310  * @data len: length of event buffer
311  *
312  * Return: 0 on success
313  */
314 int wma_vdev_tsf_handler(void *handle, uint8_t *data, uint32_t data_len)
315 {
316 	struct scheduler_msg tsf_msg = {0};
317 	WMI_VDEV_TSF_REPORT_EVENTID_param_tlvs *param_buf;
318 	wmi_vdev_tsf_report_event_fixed_param *tsf_event;
319 	struct stsf *ptsf;
320 
321 	if (!data) {
322 		wma_err("invalid pointer");
323 		return -EINVAL;
324 	}
325 	ptsf = qdf_mem_malloc(sizeof(*ptsf));
326 	if (!ptsf)
327 		return -ENOMEM;
328 
329 	param_buf = (WMI_VDEV_TSF_REPORT_EVENTID_param_tlvs *)data;
330 	tsf_event = param_buf->fixed_param;
331 
332 	ptsf->vdev_id = tsf_event->vdev_id;
333 	ptsf->tsf_low = tsf_event->tsf_low;
334 	ptsf->tsf_high = tsf_event->tsf_high;
335 	ptsf->soc_timer_low = tsf_event->qtimer_low;
336 	ptsf->soc_timer_high = tsf_event->qtimer_high;
337 	ptsf->global_tsf_low = tsf_event->wlan_global_tsf_low;
338 	ptsf->global_tsf_high = tsf_event->wlan_global_tsf_high;
339 	wma_nofl_debug("receive WMI_VDEV_TSF_REPORT_EVENTID on %d, tsf: %d %d",
340 		       ptsf->vdev_id, ptsf->tsf_low, ptsf->tsf_high);
341 
342 	wma_nofl_debug("g_tsf: %d %d; soc_timer: %d %d",
343 		       ptsf->global_tsf_low, ptsf->global_tsf_high,
344 			   ptsf->soc_timer_low, ptsf->soc_timer_high);
345 	tsf_msg.type = eWNI_SME_TSF_EVENT;
346 	tsf_msg.bodyptr = ptsf;
347 	tsf_msg.bodyval = 0;
348 
349 	if (QDF_STATUS_SUCCESS !=
350 		scheduler_post_message(QDF_MODULE_ID_WMA,
351 				       QDF_MODULE_ID_SME,
352 				       QDF_MODULE_ID_SME, &tsf_msg)) {
353 		qdf_mem_free(ptsf);
354 		return -EINVAL;
355 	}
356 	return 0;
357 }
358 
359 #if defined(QCA_WIFI_3_0) || defined(WLAN_FEATURE_TSF_TIMER_SYNC)
360 #define TSF_FW_ACTION_CMD TSF_TSTAMP_QTIMER_CAPTURE_REQ
361 #else
362 #define TSF_FW_ACTION_CMD TSF_TSTAMP_CAPTURE_REQ
363 #endif
364 /**
365  * wma_capture_tsf() - send wmi to fw to capture tsf
366  * @wma_handle: wma handler
367  * @vdev_id: vdev id
368  *
369  * Return: wmi send state
370  */
371 QDF_STATUS wma_capture_tsf(tp_wma_handle wma_handle, uint32_t vdev_id)
372 {
373 	QDF_STATUS status;
374 	wmi_buf_t buf;
375 	wmi_vdev_tsf_tstamp_action_cmd_fixed_param *cmd;
376 	int len = sizeof(*cmd);
377 
378 	buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
379 	if (!buf)
380 		return QDF_STATUS_E_NOMEM;
381 
382 	cmd = (wmi_vdev_tsf_tstamp_action_cmd_fixed_param *) wmi_buf_data(buf);
383 	cmd->vdev_id = vdev_id;
384 	cmd->tsf_action = TSF_FW_ACTION_CMD;
385 	wma_debug("vdev_id %u, tsf_cmd: %d", cmd->vdev_id, cmd->tsf_action);
386 
387 	WMITLV_SET_HDR(&cmd->tlv_header,
388 	WMITLV_TAG_STRUC_wmi_vdev_tsf_tstamp_action_cmd_fixed_param,
389 	WMITLV_GET_STRUCT_TLVLEN(
390 	wmi_vdev_tsf_tstamp_action_cmd_fixed_param));
391 
392 	status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
393 				      WMI_VDEV_TSF_TSTAMP_ACTION_CMDID);
394 	if (QDF_IS_STATUS_ERROR(status))
395 		wmi_buf_free(buf);
396 
397 	return status;
398 }
399 
400 /**
401  * wma_reset_tsf_gpio() - send wmi to fw to reset GPIO
402  * @wma_handle: wma handler
403  * @vdev_id: vdev id
404  *
405  * Return: wmi send state
406  */
407 QDF_STATUS wma_reset_tsf_gpio(tp_wma_handle wma_handle, uint32_t vdev_id)
408 {
409 	QDF_STATUS status;
410 	wmi_buf_t buf;
411 	wmi_vdev_tsf_tstamp_action_cmd_fixed_param *cmd;
412 	int len = sizeof(*cmd);
413 	uint8_t *buf_ptr;
414 
415 	buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
416 	if (!buf)
417 		return QDF_STATUS_E_NOMEM;
418 
419 	buf_ptr = (uint8_t *) wmi_buf_data(buf);
420 	cmd = (wmi_vdev_tsf_tstamp_action_cmd_fixed_param *) buf_ptr;
421 	cmd->vdev_id = vdev_id;
422 	cmd->tsf_action = TSF_TSTAMP_CAPTURE_RESET;
423 
424 	wma_debug("vdev_id %u, TSF_TSTAMP_CAPTURE_RESET", cmd->vdev_id);
425 
426 	WMITLV_SET_HDR(&cmd->tlv_header,
427 		WMITLV_TAG_STRUC_wmi_vdev_tsf_tstamp_action_cmd_fixed_param,
428 		WMITLV_GET_STRUCT_TLVLEN(
429 				wmi_vdev_tsf_tstamp_action_cmd_fixed_param));
430 
431 	status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
432 				      WMI_VDEV_TSF_TSTAMP_ACTION_CMDID);
433 	if (QDF_IS_STATUS_ERROR(status))
434 		wmi_buf_free(buf);
435 
436 	return status;
437 }
438 
439 /**
440  * wma_set_tsf_gpio_pin() - send wmi cmd to configure gpio pin
441  * @handle: wma handler
442  * @pin: GPIO pin id
443  *
444  * Return: QDF_STATUS
445  */
446 QDF_STATUS wma_set_tsf_gpio_pin(WMA_HANDLE handle, uint32_t pin)
447 {
448 	tp_wma_handle wma = (tp_wma_handle)handle;
449 	struct pdev_params pdev_param = {0};
450 	int32_t ret;
451 	struct wmi_unified *wmi_handle;
452 
453 	if (wma_validate_handle(wma))
454 		return QDF_STATUS_E_INVAL;
455 
456 	wmi_handle = wma->wmi_handle;
457 	if (wmi_validate_handle(wmi_handle))
458 		return QDF_STATUS_E_INVAL;
459 
460 	wma_debug("set tsf gpio pin: %d", pin);
461 
462 	pdev_param.param_id = WMI_PDEV_PARAM_WNTS_CONFIG;
463 	pdev_param.param_value = pin;
464 	ret = wmi_unified_pdev_param_send(wmi_handle,
465 					 &pdev_param,
466 					 WMA_WILDCARD_PDEV_ID);
467 	if (ret) {
468 		wma_err("Failed to set tsf gpio pin (status=%d)", ret);
469 		return QDF_STATUS_E_FAILURE;
470 	}
471 	return QDF_STATUS_SUCCESS;
472 }
473 #endif
474 
475 /**
476  * wma_set_wisa_params(): Set WISA features related params in FW
477  * @wma_handle: WMA handle
478  * @wisa: Pointer to WISA param struct
479  *
480  * Return: CDF status
481  */
482 QDF_STATUS wma_set_wisa_params(tp_wma_handle wma_handle,
483 				struct sir_wisa_params *wisa)
484 {
485 	QDF_STATUS status;
486 	wmi_buf_t buf;
487 	wmi_vdev_wisa_cmd_fixed_param *cmd;
488 	int len = sizeof(*cmd);
489 
490 	buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
491 	if (!buf)
492 		return QDF_STATUS_E_NOMEM;
493 
494 	cmd = (wmi_vdev_wisa_cmd_fixed_param *) wmi_buf_data(buf);
495 	cmd->wisa_mode = wisa->mode;
496 	cmd->vdev_id = wisa->vdev_id;
497 
498 	WMITLV_SET_HDR(&cmd->tlv_header,
499 		WMITLV_TAG_STRUC_wmi_vdev_wisa_cmd_fixed_param,
500 		WMITLV_GET_STRUCT_TLVLEN(
501 				wmi_vdev_wisa_cmd_fixed_param));
502 
503 	status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
504 				      WMI_VDEV_WISA_CMDID);
505 	if (QDF_IS_STATUS_ERROR(status))
506 		wmi_buf_free(buf);
507 
508 	return status;
509 }
510 
511 /**
512  * wma_process_dhcp_ind() - process dhcp indication from SME
513  * @wma_handle: wma handle
514  * @ta_dhcp_ind: DHCP indication
515  *
516  * Return: QDF Status
517  */
518 QDF_STATUS wma_process_dhcp_ind(WMA_HANDLE handle,
519 				tAniDHCPInd *ta_dhcp_ind)
520 {
521 	tp_wma_handle wma_handle = (tp_wma_handle) handle;
522 	uint8_t vdev_id;
523 	wmi_peer_set_param_cmd_fixed_param peer_set_param_fp = {0};
524 
525 	if (wma_validate_handle(wma_handle))
526 		return QDF_STATUS_E_FAILURE;
527 
528 	if (!ta_dhcp_ind) {
529 		wma_err("DHCP indication is NULL");
530 		return QDF_STATUS_E_FAILURE;
531 	}
532 
533 	if (wma_find_vdev_id_by_addr(wma_handle,
534 				     ta_dhcp_ind->adapterMacAddr.bytes,
535 				     &vdev_id)) {
536 		wma_err("Failed to find vdev id for DHCP indication");
537 		return QDF_STATUS_E_FAILURE;
538 	}
539 
540 	wma_debug("WMA --> WMI_PEER_SET_PARAM triggered by DHCP, msgType=%s, device_mode=%d, macAddr=" QDF_MAC_ADDR_FMT,
541 		ta_dhcp_ind->msgType == WMA_DHCP_START_IND ?
542 		"WMA_DHCP_START_IND" : "WMA_DHCP_STOP_IND",
543 		ta_dhcp_ind->device_mode,
544 		QDF_MAC_ADDR_REF(ta_dhcp_ind->peerMacAddr.bytes));
545 
546 	/* fill in values */
547 	peer_set_param_fp.vdev_id = vdev_id;
548 	peer_set_param_fp.param_id = WMI_PEER_CRIT_PROTO_HINT_ENABLED;
549 	if (WMA_DHCP_START_IND == ta_dhcp_ind->msgType)
550 		peer_set_param_fp.param_value = 1;
551 	else
552 		peer_set_param_fp.param_value = 0;
553 	WMI_CHAR_ARRAY_TO_MAC_ADDR(ta_dhcp_ind->peerMacAddr.bytes,
554 				   &peer_set_param_fp.peer_macaddr);
555 
556 	return wmi_unified_process_dhcp_ind(wma_handle->wmi_handle,
557 					    &peer_set_param_fp);
558 }
559 
560 #ifdef WLAN_FEATURE_11BE
561 static enum wlan_phymode
562 wma_eht_chan_phy_mode(uint32_t freq, uint8_t dot11_mode, uint16_t bw_val,
563 		      enum phy_ch_width chan_width)
564 {
565 	if((dot11_mode == MLME_DOT11_MODE_11BE) ||
566 		(dot11_mode == MLME_DOT11_MODE_11BE_ONLY))
567 	{
568 		if (wlan_reg_is_24ghz_ch_freq(freq)) {
569 			if (bw_val == 20)
570 				return WLAN_PHYMODE_11BEG_EHT20;
571 			else if (bw_val == 40)
572 				return WLAN_PHYMODE_11BEG_EHT40;
573 		} else {
574 			if (bw_val == 20)
575 				return WLAN_PHYMODE_11BEA_EHT20;
576 			else if (bw_val == 40)
577 				return WLAN_PHYMODE_11BEA_EHT40;
578 			else if (bw_val == 80)
579 				return WLAN_PHYMODE_11BEA_EHT80;
580 			else if (chan_width == CH_WIDTH_160MHZ)
581 				return WLAN_PHYMODE_11BEA_EHT160;
582 			else if (chan_width == CH_WIDTH_320MHZ)
583 				return WLAN_PHYMODE_11BEA_EHT320;
584 		}
585 	}
586 
587 	return WLAN_PHYMODE_AUTO;
588 }
589 #else
590 static enum wlan_phymode
591 wma_eht_chan_phy_mode(uint32_t freq, uint8_t dot11_mode, uint16_t bw_val,
592 		      enum phy_ch_width chan_width)
593 {
594 	return WLAN_PHYMODE_AUTO;
595 }
596 #endif
597 
598 enum wlan_phymode wma_chan_phy_mode(uint32_t freq, enum phy_ch_width chan_width,
599 				    uint8_t dot11_mode)
600 {
601 	enum wlan_phymode phymode = WLAN_PHYMODE_AUTO;
602 	uint16_t bw_val = wlan_reg_get_bw_value(chan_width);
603 	t_wma_handle *wma = cds_get_context(QDF_MODULE_ID_WMA);
604 
605 	if (!wma)
606 		return WLAN_PHYMODE_AUTO;
607 
608 	if (chan_width >= CH_WIDTH_INVALID) {
609 		wma_err_rl("Invalid channel width %d", chan_width);
610 		return WLAN_PHYMODE_AUTO;
611 	}
612 
613 	if (wlan_reg_is_24ghz_ch_freq(freq)) {
614 		if (((CH_WIDTH_5MHZ == chan_width) ||
615 		     (CH_WIDTH_10MHZ == chan_width)) &&
616 		    ((MLME_DOT11_MODE_11B == dot11_mode) ||
617 		     (MLME_DOT11_MODE_11G == dot11_mode) ||
618 		     (MLME_DOT11_MODE_11N == dot11_mode) ||
619 		     (MLME_DOT11_MODE_ALL == dot11_mode) ||
620 		     (MLME_DOT11_MODE_11AC == dot11_mode) ||
621 		     (MLME_DOT11_MODE_11AX == dot11_mode)))
622 			phymode = WLAN_PHYMODE_11G;
623 		else {
624 			switch (dot11_mode) {
625 			case MLME_DOT11_MODE_11B:
626 				if ((bw_val == 20) || (bw_val == 40))
627 					phymode = WLAN_PHYMODE_11B;
628 				break;
629 			case MLME_DOT11_MODE_11G:
630 				if ((bw_val == 20) || (bw_val == 40))
631 					phymode = WLAN_PHYMODE_11G;
632 				break;
633 			case MLME_DOT11_MODE_11G_ONLY:
634 				if ((bw_val == 20) || (bw_val == 40))
635 					phymode = WLAN_PHYMODE_11G_ONLY;
636 				break;
637 			case MLME_DOT11_MODE_11N:
638 			case MLME_DOT11_MODE_11N_ONLY:
639 				if (bw_val == 20)
640 					phymode = WLAN_PHYMODE_11NG_HT20;
641 				else if (bw_val == 40)
642 					phymode = WLAN_PHYMODE_11NG_HT40;
643 				break;
644 			case MLME_DOT11_MODE_ALL:
645 			case MLME_DOT11_MODE_11AC:
646 			case MLME_DOT11_MODE_11AC_ONLY:
647 				if (bw_val == 20)
648 					phymode = WLAN_PHYMODE_11AC_VHT20_2G;
649 				else if (bw_val == 40)
650 					phymode = WLAN_PHYMODE_11AC_VHT40_2G;
651 				break;
652 			case MLME_DOT11_MODE_11AX:
653 			case MLME_DOT11_MODE_11AX_ONLY:
654 				if (20 == bw_val)
655 					phymode = WLAN_PHYMODE_11AXG_HE20;
656 				else if (40 == bw_val)
657 					phymode = WLAN_PHYMODE_11AXG_HE40;
658 				break;
659 			default:
660 				phymode = wma_eht_chan_phy_mode(freq,
661 								dot11_mode,
662 								bw_val,
663 								chan_width);
664 				break;
665 			}
666 		}
667 	} else if (wlan_reg_is_dsrc_freq(freq))
668 		phymode = WLAN_PHYMODE_11A;
669 	else {
670 		if (((CH_WIDTH_5MHZ == chan_width) ||
671 		     (CH_WIDTH_10MHZ == chan_width)) &&
672 		    ((MLME_DOT11_MODE_11A == dot11_mode) ||
673 		     (MLME_DOT11_MODE_11N == dot11_mode) ||
674 		     (MLME_DOT11_MODE_ALL == dot11_mode) ||
675 		     (MLME_DOT11_MODE_11AC == dot11_mode) ||
676 		     (MLME_DOT11_MODE_11AX == dot11_mode)))
677 			phymode = WLAN_PHYMODE_11A;
678 		else {
679 			switch (dot11_mode) {
680 			case MLME_DOT11_MODE_11A:
681 				if (0 < bw_val)
682 					phymode = WLAN_PHYMODE_11A;
683 				break;
684 			case MLME_DOT11_MODE_11N:
685 			case MLME_DOT11_MODE_11N_ONLY:
686 				if (bw_val == 20)
687 					phymode = WLAN_PHYMODE_11NA_HT20;
688 				else if (40 <= bw_val)
689 					phymode = WLAN_PHYMODE_11NA_HT40;
690 				break;
691 			case MLME_DOT11_MODE_ALL:
692 			case MLME_DOT11_MODE_11AC:
693 			case MLME_DOT11_MODE_11AC_ONLY:
694 				if (bw_val == 20)
695 					phymode = WLAN_PHYMODE_11AC_VHT20;
696 				else if (bw_val == 40)
697 					phymode = WLAN_PHYMODE_11AC_VHT40;
698 				else if (bw_val == 80)
699 					phymode = WLAN_PHYMODE_11AC_VHT80;
700 				else if (chan_width == CH_WIDTH_160MHZ)
701 					phymode = WLAN_PHYMODE_11AC_VHT160;
702 				else if (chan_width == CH_WIDTH_80P80MHZ)
703 					phymode = WLAN_PHYMODE_11AC_VHT80_80;
704 				break;
705 			case MLME_DOT11_MODE_11AX:
706 			case MLME_DOT11_MODE_11AX_ONLY:
707 				if (20 == bw_val)
708 					phymode = WLAN_PHYMODE_11AXA_HE20;
709 				else if (40 == bw_val)
710 					phymode = WLAN_PHYMODE_11AXA_HE40;
711 				else if (80 == bw_val)
712 					phymode = WLAN_PHYMODE_11AXA_HE80;
713 				else if (CH_WIDTH_160MHZ == chan_width)
714 					phymode = WLAN_PHYMODE_11AXA_HE160;
715 				else if (CH_WIDTH_80P80MHZ == chan_width)
716 					phymode = WLAN_PHYMODE_11AXA_HE80_80;
717 				break;
718 			default:
719 				phymode = wma_eht_chan_phy_mode(freq,
720 								dot11_mode,
721 								bw_val,
722 								chan_width);
723 				break;
724 			}
725 		}
726 	}
727 
728 	wma_debug("phymode %d freq %d ch_width %d dot11_mode %d",
729 		 phymode, freq, chan_width, dot11_mode);
730 
731 	QDF_ASSERT(phymode != WLAN_PHYMODE_AUTO);
732 	return phymode;
733 }
734 
735 /**
736  * wma_get_link_speed() -send command to get linkspeed
737  * @handle: wma handle
738  * @pLinkSpeed: link speed info
739  *
740  * Return: QDF status
741  */
742 QDF_STATUS wma_get_link_speed(WMA_HANDLE handle,
743 			      struct link_speed_info *pLinkSpeed)
744 {
745 	tp_wma_handle wma_handle = (tp_wma_handle) handle;
746 	wmi_mac_addr peer_macaddr;
747 	struct wmi_unified *wmi_handle;
748 
749 	if (wma_validate_handle(wma_handle))
750 		return QDF_STATUS_E_INVAL;
751 
752 	wmi_handle = wma_handle->wmi_handle;
753 	if (wmi_validate_handle(wmi_handle))
754 		return QDF_STATUS_E_INVAL;
755 
756 	if (!wmi_service_enabled(wmi_handle,
757 				 wmi_service_estimate_linkspeed)) {
758 		wma_err("Linkspeed feature bit not enabled Sending value 0 as link speed");
759 		wma_send_link_speed(0);
760 		return QDF_STATUS_E_FAILURE;
761 	}
762 	/* Copy the peer macaddress to the wma buffer */
763 	WMI_CHAR_ARRAY_TO_MAC_ADDR(pLinkSpeed->peer_macaddr.bytes,
764 				   &peer_macaddr);
765 	wma_debug("pLinkSpeed->peerMacAddr: "QDF_MAC_ADDR_FMT", peer_macaddr.mac_addr31to0: 0x%x, peer_macaddr.mac_addr47to32: 0x%x",
766 		 QDF_MAC_ADDR_REF(pLinkSpeed->peer_macaddr.bytes),
767 		 peer_macaddr.mac_addr31to0,
768 		 peer_macaddr.mac_addr47to32);
769 	if (wmi_unified_get_link_speed_cmd(wmi_handle, peer_macaddr)) {
770 		return QDF_STATUS_E_FAILURE;
771 	}
772 
773 	return QDF_STATUS_SUCCESS;
774 }
775 
776 QDF_STATUS wma_get_isolation(tp_wma_handle wma)
777 {
778 	wmi_coex_get_antenna_isolation_cmd_fixed_param *cmd;
779 	wmi_buf_t wmi_buf;
780 	uint32_t  len;
781 	uint8_t *buf_ptr;
782 	struct wmi_unified *wmi_handle;
783 
784 	wma_debug("get isolation");
785 
786 	if (wma_validate_handle(wma))
787 		return QDF_STATUS_E_INVAL;
788 
789 	wmi_handle = wma->wmi_handle;
790 	if (wmi_validate_handle(wma->wmi_handle))
791 		return QDF_STATUS_E_INVAL;
792 
793 	len  = sizeof(wmi_coex_get_antenna_isolation_cmd_fixed_param);
794 	wmi_buf = wmi_buf_alloc(wmi_handle, len);
795 	if (!wmi_buf) {
796 		wma_err("wmi_buf_alloc failed");
797 		return QDF_STATUS_E_NOMEM;
798 	}
799 	buf_ptr = (uint8_t *)wmi_buf_data(wmi_buf);
800 
801 	cmd = (wmi_coex_get_antenna_isolation_cmd_fixed_param *)buf_ptr;
802 	WMITLV_SET_HDR(
803 	&cmd->tlv_header,
804 	WMITLV_TAG_STRUC_wmi_coex_get_antenna_isolation_cmd_fixed_param,
805 	WMITLV_GET_STRUCT_TLVLEN(
806 	wmi_coex_get_antenna_isolation_cmd_fixed_param));
807 
808 	if (wmi_unified_cmd_send(wmi_handle, wmi_buf, len,
809 				 WMI_COEX_GET_ANTENNA_ISOLATION_CMDID)) {
810 		wma_err("Failed to get isolation request from fw");
811 		wmi_buf_free(wmi_buf);
812 		return QDF_STATUS_E_FAILURE;
813 	}
814 
815 	return QDF_STATUS_SUCCESS;
816 }
817 
818 /**
819  * wma_add_beacon_filter() - Issue WMI command to set beacon filter
820  * @wma: wma handler
821  * @filter_params: beacon_filter_param to set
822  *
823  * Return: Return QDF_STATUS
824  */
825 QDF_STATUS wma_add_beacon_filter(WMA_HANDLE handle,
826 				struct beacon_filter_param *filter_params)
827 {
828 	int i;
829 	wmi_buf_t wmi_buf;
830 	u_int8_t *buf;
831 	A_UINT32 *ie_map;
832 	int ret;
833 	struct wma_txrx_node *iface;
834 	tp_wma_handle wma = (tp_wma_handle) handle;
835 	struct wmi_unified *wmi_handle;
836 
837 	wmi_add_bcn_filter_cmd_fixed_param *cmd;
838 	int len = sizeof(wmi_add_bcn_filter_cmd_fixed_param);
839 
840 	len += WMI_TLV_HDR_SIZE;
841 	len += BCN_FLT_MAX_ELEMS_IE_LIST*sizeof(A_UINT32);
842 
843 	if (wma_validate_handle(wma))
844 		return QDF_STATUS_E_INVAL;
845 
846 	wmi_handle = wma->wmi_handle;
847 	if (wmi_validate_handle(wma->wmi_handle))
848 		return QDF_STATUS_E_INVAL;
849 
850 	iface = &wma->interfaces[filter_params->vdev_id];
851 	qdf_mem_copy(&iface->beacon_filter, filter_params,
852 			sizeof(struct beacon_filter_param));
853 	iface->beacon_filter_enabled = true;
854 
855 	wmi_buf = wmi_buf_alloc(wmi_handle, len);
856 	if (!wmi_buf)
857 		return QDF_STATUS_E_NOMEM;
858 
859 	buf = (u_int8_t *) wmi_buf_data(wmi_buf);
860 
861 	cmd = (wmi_add_bcn_filter_cmd_fixed_param *)wmi_buf_data(wmi_buf);
862 	cmd->vdev_id = filter_params->vdev_id;
863 
864 	WMITLV_SET_HDR(&cmd->tlv_header,
865 			WMITLV_TAG_STRUC_wmi_add_bcn_filter_cmd_fixed_param,
866 			WMITLV_GET_STRUCT_TLVLEN(
867 				wmi_add_bcn_filter_cmd_fixed_param));
868 
869 	buf += sizeof(wmi_add_bcn_filter_cmd_fixed_param);
870 
871 	WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_UINT32,
872 			(BCN_FLT_MAX_ELEMS_IE_LIST * sizeof(u_int32_t)));
873 
874 	ie_map = (A_UINT32 *)(buf + WMI_TLV_HDR_SIZE);
875 	for (i = 0; i < BCN_FLT_MAX_ELEMS_IE_LIST; i++) {
876 		ie_map[i] = filter_params->ie_map[i];
877 		wma_debug("beacon filter ie map = %u", ie_map[i]);
878 	}
879 
880 	ret = wmi_unified_cmd_send(wmi_handle, wmi_buf, len,
881 			WMI_ADD_BCN_FILTER_CMDID);
882 	if (ret) {
883 		wmi_buf_free(wmi_buf);
884 		return QDF_STATUS_E_FAILURE;
885 	}
886 
887 	return QDF_STATUS_SUCCESS;
888 }
889 
890 /**
891 * wma_remove_beacon_filter() - Issue WMI command to remove beacon filter
892 * @wma: wma handler
893 * @filter_params: beacon_filter_params
894 *
895 * Return: Return QDF_STATUS
896 */
897 QDF_STATUS wma_remove_beacon_filter(WMA_HANDLE handle,
898 				struct beacon_filter_param *filter_params)
899 {
900 	wmi_buf_t buf;
901 	tp_wma_handle wma = (tp_wma_handle) handle;
902 	wmi_rmv_bcn_filter_cmd_fixed_param *cmd;
903 	int len = sizeof(wmi_rmv_bcn_filter_cmd_fixed_param);
904 	int ret;
905 	struct wmi_unified *wmi_handle;
906 
907 	if (wma_validate_handle(wma))
908 		return QDF_STATUS_E_INVAL;
909 
910 	wmi_handle = wma->wmi_handle;
911 	if (wmi_validate_handle(wma->wmi_handle))
912 		return QDF_STATUS_E_INVAL;
913 
914 	buf = wmi_buf_alloc(wmi_handle, len);
915 	if (!buf)
916 		return QDF_STATUS_E_NOMEM;
917 
918 	cmd = (wmi_rmv_bcn_filter_cmd_fixed_param *)wmi_buf_data(buf);
919 	cmd->vdev_id = filter_params->vdev_id;
920 
921 	WMITLV_SET_HDR(&cmd->tlv_header,
922 			WMITLV_TAG_STRUC_wmi_rmv_bcn_filter_cmd_fixed_param,
923 			WMITLV_GET_STRUCT_TLVLEN(
924 				wmi_rmv_bcn_filter_cmd_fixed_param));
925 
926 	ret = wmi_unified_cmd_send(wmi_handle, buf, len,
927 			WMI_RMV_BCN_FILTER_CMDID);
928 	if (ret) {
929 		wmi_buf_free(buf);
930 		return QDF_STATUS_E_FAILURE;
931 	}
932 
933 	return QDF_STATUS_SUCCESS;
934 }
935 
936 /**
937  * wma_send_adapt_dwelltime_params() - send adaptive dwelltime configuration
938  * params to firmware
939  * @wma_handle:	 wma handler
940  * @dwelltime_params: pointer to dwelltime_params
941  *
942  * Return: QDF_STATUS_SUCCESS on success and QDF failure reason code for failure
943  */
944 QDF_STATUS wma_send_adapt_dwelltime_params(WMA_HANDLE handle,
945 			struct adaptive_dwelltime_params *dwelltime_params)
946 {
947 	tp_wma_handle wma_handle = (tp_wma_handle) handle;
948 	struct wmi_adaptive_dwelltime_params wmi_param = {0};
949 	int32_t err;
950 
951 	wmi_param.is_enabled = dwelltime_params->is_enabled;
952 	wmi_param.dwelltime_mode = dwelltime_params->dwelltime_mode;
953 	wmi_param.lpf_weight = dwelltime_params->lpf_weight;
954 	wmi_param.passive_mon_intval = dwelltime_params->passive_mon_intval;
955 	wmi_param.wifi_act_threshold = dwelltime_params->wifi_act_threshold;
956 	err = wmi_unified_send_adapt_dwelltime_params_cmd(wma_handle->
957 					wmi_handle, &wmi_param);
958 	if (err)
959 		return QDF_STATUS_E_FAILURE;
960 
961 	return QDF_STATUS_SUCCESS;
962 }
963 
964 QDF_STATUS wma_send_dbs_scan_selection_params(WMA_HANDLE handle,
965 			struct wmi_dbs_scan_sel_params *dbs_scan_params)
966 {
967 	tp_wma_handle wma_handle = (tp_wma_handle) handle;
968 	int32_t err;
969 
970 	err = wmi_unified_send_dbs_scan_sel_params_cmd(wma_handle->
971 					wmi_handle, dbs_scan_params);
972 	if (err)
973 		return QDF_STATUS_E_FAILURE;
974 
975 	return QDF_STATUS_SUCCESS;
976 }
977 
978 /**
979  * wma_unified_fw_profiling_cmd() - send FW profiling cmd to WLAN FW
980  * @wma: wma handle
981  * @cmd: Profiling command index
982  * @value1: parameter1 value
983  * @value2: parameter2 value
984  *
985  * Return: 0 for success else error code
986  */
987 QDF_STATUS wma_unified_fw_profiling_cmd(wmi_unified_t wmi_handle,
988 			uint32_t cmd, uint32_t value1, uint32_t value2)
989 {
990 	int ret;
991 
992 	ret = wmi_unified_fw_profiling_data_cmd(wmi_handle, cmd,
993 			value1, value2);
994 	if (ret) {
995 		wma_err("enable cmd Failed for id %d value %d",	value1, value2);
996 		return ret;
997 	}
998 
999 	return QDF_STATUS_SUCCESS;
1000 }
1001 
1002 /**
1003  * wma_wow_set_wake_time() - set timer pattern tlv, so that firmware will wake
1004  * up host after specified time is elapsed
1005  * @wma_handle: wma handle
1006  * @vdev_id: vdev id
1007  * @cookie: value to identify reason why host set up wake call.
1008  * @time: time in ms
1009  *
1010  * Return: QDF status
1011  */
1012 static QDF_STATUS wma_wow_set_wake_time(WMA_HANDLE wma_handle, uint8_t vdev_id,
1013 					uint32_t cookie, uint32_t time)
1014 {
1015 	int ret;
1016 	tp_wma_handle wma = (tp_wma_handle)wma_handle;
1017 
1018 	wma_debug("send timer patter with time: %d and vdev = %d to fw",
1019 		 time, vdev_id);
1020 	ret = wmi_unified_wow_timer_pattern_cmd(wma->wmi_handle, vdev_id,
1021 						cookie, time);
1022 	if (ret) {
1023 		wma_err("Failed to send timer patter to fw");
1024 		return QDF_STATUS_E_FAILURE;
1025 	}
1026 
1027 	return QDF_STATUS_SUCCESS;
1028 }
1029 
1030 #ifdef WLAN_POWER_MANAGEMENT_OFFLOAD
1031 /**
1032  * wma_check_and_set_wake_timer(): checks all interfaces and if any interface
1033  * has install_key pending, sets timer pattern in fw to wake up host after
1034  * specified time has elapsed.
1035  * @wma: wma handle
1036  * @time: time after which host wants to be awaken.
1037  *
1038  * Return: None
1039  */
1040 void wma_check_and_set_wake_timer(uint32_t time)
1041 {
1042 	int i;
1043 	struct wma_txrx_node *iface;
1044 	bool is_set_key_in_progress = false;
1045 	t_wma_handle *wma = cds_get_context(QDF_MODULE_ID_WMA);
1046 
1047 	if (!wma)
1048 		return;
1049 
1050 	if (!wmi_service_enabled(wma->wmi_handle,
1051 		wmi_service_wow_wakeup_by_timer_pattern)) {
1052 		wma_debug("TIME_PATTERN is not enabled");
1053 		return;
1054 	}
1055 
1056 	for (i = 0; i < wma->max_bssid; i++) {
1057 		iface = &wma->interfaces[i];
1058 		if (iface->vdev_active && iface->is_waiting_for_key) {
1059 			/*
1060 			 * right now cookie is dont care, since FW disregards
1061 			 * that.
1062 			 */
1063 			is_set_key_in_progress = true;
1064 			wma_wow_set_wake_time((WMA_HANDLE)wma, i, 0, time);
1065 			break;
1066 		}
1067 	}
1068 
1069 	if (!is_set_key_in_progress)
1070 		wma_debug("set key not in progress for any vdev");
1071 }
1072 
1073 /**
1074  * wma_unified_csa_offload_enable() - sen CSA offload enable command
1075  * @wma: wma handle
1076  * @vdev_id: vdev id
1077  *
1078  * Return: 0 for success or error code
1079  */
1080 int wma_unified_csa_offload_enable(tp_wma_handle wma, uint8_t vdev_id)
1081 {
1082 	if (wmi_unified_csa_offload_enable(wma->wmi_handle,
1083 				 vdev_id)) {
1084 		wma_alert("Failed to send CSA offload enable command");
1085 		return -EIO;
1086 	}
1087 
1088 	return 0;
1089 }
1090 #endif /* WLAN_POWER_MANAGEMENT_OFFLOAD */
1091 
1092 static uint8_t *
1093 wma_parse_ch_switch_wrapper_ie(uint8_t *ch_wr_ie, uint8_t sub_ele_id)
1094 {
1095 	uint8_t len = 0, sub_ele_len = 0;
1096 	struct ie_header *ele;
1097 
1098 	ele = (struct ie_header *)ch_wr_ie;
1099 	if (ele->ie_id != WLAN_ELEMID_CHAN_SWITCH_WRAP ||
1100 	    ele->ie_len == 0)
1101 		return NULL;
1102 
1103 	len = ele->ie_len;
1104 	ele = (struct ie_header *)(ch_wr_ie + sizeof(struct ie_header));
1105 
1106 	while (len > 0) {
1107 		sub_ele_len = sizeof(struct ie_header) + ele->ie_len;
1108 		len -= sub_ele_len;
1109 		if (ele->ie_id == sub_ele_id)
1110 			return (uint8_t *)ele;
1111 
1112 		ele = (struct ie_header *)((uint8_t *)ele + sub_ele_len);
1113 	}
1114 
1115 	return NULL;
1116 }
1117 
1118 /**
1119  * wma_csa_offload_handler() - CSA event handler
1120  * @handle: wma handle
1121  * @event: event buffer
1122  * @len: buffer length
1123  *
1124  * This event is sent by firmware when it receives CSA IE.
1125  *
1126  * Return: 0 for success or error code
1127  */
1128 int wma_csa_offload_handler(void *handle, uint8_t *event, uint32_t len)
1129 {
1130 	tp_wma_handle wma = (tp_wma_handle) handle;
1131 	WMI_CSA_HANDLING_EVENTID_param_tlvs *param_buf;
1132 	wmi_csa_event_fixed_param *csa_event;
1133 	uint8_t bssid[QDF_MAC_ADDR_SIZE];
1134 	uint8_t vdev_id = 0;
1135 	uint8_t cur_chan = 0;
1136 	struct ieee80211_channelswitch_ie *csa_ie;
1137 	struct csa_offload_params *csa_offload_event;
1138 	struct ieee80211_extendedchannelswitch_ie *xcsa_ie;
1139 	struct ieee80211_ie_wide_bw_switch *wb_ie;
1140 	struct wma_txrx_node *intr = wma->interfaces;
1141 
1142 	param_buf = (WMI_CSA_HANDLING_EVENTID_param_tlvs *) event;
1143 
1144 	wma_debug("Enter");
1145 	if (!param_buf) {
1146 		wma_err("Invalid csa event buffer");
1147 		return -EINVAL;
1148 	}
1149 	csa_event = param_buf->fixed_param;
1150 	WMI_MAC_ADDR_TO_CHAR_ARRAY(&csa_event->i_addr2, &bssid[0]);
1151 
1152 	if (wma_find_vdev_id_by_bssid(wma, bssid, &vdev_id)) {
1153 		wma_err("Invalid bssid received");
1154 		return -EINVAL;
1155 	}
1156 
1157 	csa_offload_event = qdf_mem_malloc(sizeof(*csa_offload_event));
1158 	if (!csa_offload_event)
1159 		return -EINVAL;
1160 
1161 	if (MLME_IS_ROAM_SYNCH_IN_PROGRESS(wma->psoc, vdev_id) ||
1162 	    wma->interfaces[vdev_id].roaming_in_progress) {
1163 		wma_err("Roaming in progress for vdev %d, ignore csa event",
1164 			 vdev_id);
1165 		qdf_mem_free(csa_offload_event);
1166 		return -EINVAL;
1167 	}
1168 
1169 	qdf_mem_zero(csa_offload_event, sizeof(*csa_offload_event));
1170 	qdf_mem_copy(csa_offload_event->bssId, &bssid, QDF_MAC_ADDR_SIZE);
1171 
1172 	if (csa_event->ies_present_flag & WMI_CSA_IE_PRESENT) {
1173 		csa_ie = (struct ieee80211_channelswitch_ie *)
1174 						(&csa_event->csa_ie[0]);
1175 		csa_offload_event->channel = csa_ie->newchannel;
1176 		csa_offload_event->csa_chan_freq =
1177 			wlan_reg_legacy_chan_to_freq(wma->pdev,
1178 						     csa_ie->newchannel);
1179 		csa_offload_event->switch_mode = csa_ie->switchmode;
1180 	} else if (csa_event->ies_present_flag & WMI_XCSA_IE_PRESENT) {
1181 		xcsa_ie = (struct ieee80211_extendedchannelswitch_ie *)
1182 						(&csa_event->xcsa_ie[0]);
1183 		csa_offload_event->channel = xcsa_ie->newchannel;
1184 		csa_offload_event->switch_mode = xcsa_ie->switchmode;
1185 		csa_offload_event->new_op_class = xcsa_ie->newClass;
1186 		if (wlan_reg_is_6ghz_op_class(wma->pdev, xcsa_ie->newClass)) {
1187 			csa_offload_event->csa_chan_freq =
1188 				wlan_reg_chan_band_to_freq
1189 					(wma->pdev, xcsa_ie->newchannel,
1190 					 BIT(REG_BAND_6G));
1191 		} else {
1192 			csa_offload_event->csa_chan_freq =
1193 				wlan_reg_legacy_chan_to_freq
1194 					(wma->pdev, xcsa_ie->newchannel);
1195 		}
1196 	} else {
1197 		wma_err("CSA Event error: No CSA IE present");
1198 		qdf_mem_free(csa_offload_event);
1199 		return -EINVAL;
1200 	}
1201 
1202 	if (csa_event->ies_present_flag & WMI_WBW_IE_PRESENT) {
1203 		wb_ie = (struct ieee80211_ie_wide_bw_switch *)
1204 						(&csa_event->wb_ie[0]);
1205 		csa_offload_event->new_ch_width = wb_ie->new_ch_width;
1206 		csa_offload_event->new_ch_freq_seg1 = wb_ie->new_ch_freq_seg1;
1207 		csa_offload_event->new_ch_freq_seg2 = wb_ie->new_ch_freq_seg2;
1208 	} else if (csa_event->ies_present_flag &
1209 		   WMI_CSWRAP_IE_EXTENDED_PRESENT) {
1210 		wb_ie = (struct ieee80211_ie_wide_bw_switch *)
1211 				wma_parse_ch_switch_wrapper_ie(
1212 				(uint8_t *)&csa_event->cswrap_ie_extended,
1213 				WLAN_ELEMID_WIDE_BAND_CHAN_SWITCH);
1214 		if (wb_ie) {
1215 			csa_offload_event->new_ch_width = wb_ie->new_ch_width;
1216 			csa_offload_event->new_ch_freq_seg1 =
1217 						wb_ie->new_ch_freq_seg1;
1218 			csa_offload_event->new_ch_freq_seg2 =
1219 						wb_ie->new_ch_freq_seg2;
1220 			csa_event->ies_present_flag |= WMI_WBW_IE_PRESENT;
1221 		}
1222 	}
1223 
1224 	csa_offload_event->ies_present_flag = csa_event->ies_present_flag;
1225 
1226 	wma_debug("CSA: BSSID "QDF_MAC_ADDR_FMT" chan %d freq %d flag 0x%x width = %d freq1 = %d freq2 = %d op class = %d",
1227 		 QDF_MAC_ADDR_REF(csa_offload_event->bssId),
1228 		 csa_offload_event->channel,
1229 		 csa_offload_event->csa_chan_freq,
1230 		 csa_event->ies_present_flag,
1231 		 csa_offload_event->new_ch_width,
1232 		 csa_offload_event->new_ch_freq_seg1,
1233 		 csa_offload_event->new_ch_freq_seg2,
1234 		 csa_offload_event->new_op_class);
1235 
1236 	cur_chan = cds_freq_to_chan(intr[vdev_id].ch_freq);
1237 	/*
1238 	 * basic sanity check: requested channel should not be 0
1239 	 * and equal to home channel
1240 	 */
1241 	if (0 == csa_offload_event->channel) {
1242 		wma_err("CSA Event with channel %d. Ignore !!",
1243 			 csa_offload_event->channel);
1244 		qdf_mem_free(csa_offload_event);
1245 		return -EINVAL;
1246 	}
1247 
1248 	wma_send_msg(wma, WMA_CSA_OFFLOAD_EVENT, (void *)csa_offload_event, 0);
1249 	return 0;
1250 }
1251 
1252 #ifdef FEATURE_OEM_DATA_SUPPORT
1253 /**
1254  * wma_oem_data_response_handler() - OEM data response event handler
1255  * @handle: wma handle
1256  * @datap: data ptr
1257  * @len: data length
1258  *
1259  * Return: 0 for success or error code
1260  */
1261 int wma_oem_data_response_handler(void *handle,
1262 				  uint8_t *datap, uint32_t len)
1263 {
1264 	WMI_OEM_RESPONSE_EVENTID_param_tlvs *param_buf;
1265 	uint8_t *data;
1266 	uint32_t datalen;
1267 	struct oem_data_rsp *oem_rsp;
1268 	struct mac_context *pmac = cds_get_context(QDF_MODULE_ID_PE);
1269 
1270 	if (!pmac)
1271 		return -EINVAL;
1272 
1273 	if (!pmac->sme.oem_data_rsp_callback) {
1274 		wma_err("Callback not registered");
1275 		return -EINVAL;
1276 	}
1277 
1278 	param_buf = (WMI_OEM_RESPONSE_EVENTID_param_tlvs *) datap;
1279 	if (!param_buf) {
1280 		wma_err("Received NULL buf ptr from FW");
1281 		return -ENOMEM;
1282 	}
1283 
1284 	data = param_buf->data;
1285 	datalen = param_buf->num_data;
1286 
1287 	if (!data) {
1288 		wma_err("Received NULL data from FW");
1289 		return -EINVAL;
1290 	}
1291 
1292 	if (datalen > OEM_DATA_RSP_SIZE) {
1293 		wma_err("Received data len %d exceeds max value %d",
1294 			 datalen, OEM_DATA_RSP_SIZE);
1295 		return -EINVAL;
1296 	}
1297 
1298 	oem_rsp = qdf_mem_malloc(sizeof(*oem_rsp));
1299 	if (!oem_rsp)
1300 		return -ENOMEM;
1301 
1302 	oem_rsp->rsp_len = datalen;
1303 	if (oem_rsp->rsp_len) {
1304 		oem_rsp->data = qdf_mem_malloc(oem_rsp->rsp_len);
1305 		if (!oem_rsp->data) {
1306 			qdf_mem_free(oem_rsp);
1307 			return -ENOMEM;
1308 		}
1309 	} else {
1310 		wma_err("Invalid rsp length: %d", oem_rsp->rsp_len);
1311 		qdf_mem_free(oem_rsp);
1312 		return -EINVAL;
1313 	}
1314 
1315 	qdf_mem_copy(oem_rsp->data, data, datalen);
1316 
1317 	wma_debug("Sending OEM_DATA_RSP(len: %d) to upper layer", datalen);
1318 
1319 	pmac->sme.oem_data_rsp_callback(oem_rsp);
1320 
1321 	if (oem_rsp->data)
1322 		qdf_mem_free(oem_rsp->data);
1323 	qdf_mem_free(oem_rsp);
1324 
1325 	return 0;
1326 }
1327 
1328 QDF_STATUS wma_start_oem_req_cmd(tp_wma_handle wma_handle,
1329 				 struct oem_data_req *oem_data_req)
1330 {
1331 	QDF_STATUS ret;
1332 	struct wmi_unified *wmi_handle;
1333 
1334 	wma_debug("Send OEM Data Request to target");
1335 
1336 	if (!oem_data_req || !oem_data_req->data) {
1337 		wma_err("oem_data_req is null");
1338 		return QDF_STATUS_E_INVAL;
1339 	}
1340 
1341 	if (wma_validate_handle(wma_handle)) {
1342 		qdf_mem_free(oem_data_req->data);
1343 		return QDF_STATUS_E_INVAL;
1344 	}
1345 
1346 	wmi_handle = wma_handle->wmi_handle;
1347 	if (wmi_validate_handle(wmi_handle)) {
1348 		qdf_mem_free(oem_data_req->data);
1349 		return QDF_STATUS_E_INVAL;
1350 	}
1351 
1352 	/* legacy api, for oem data request case */
1353 	ret = wmi_unified_start_oem_data_cmd(wmi_handle,
1354 					     oem_data_req->data_len,
1355 					     oem_data_req->data);
1356 
1357 	if (!QDF_IS_STATUS_SUCCESS(ret))
1358 		wma_err("wmi cmd send failed");
1359 
1360 	return ret;
1361 }
1362 #endif /* FEATURE_OEM_DATA_SUPPORT */
1363 
1364 #ifdef FEATURE_OEM_DATA
1365 QDF_STATUS wma_start_oem_data_cmd(tp_wma_handle wma_handle,
1366 				  struct oem_data *oem_data)
1367 {
1368 	QDF_STATUS ret;
1369 	struct wmi_unified *wmi_handle;
1370 
1371 	wma_debug("Send OEM Data to target");
1372 
1373 	if (!oem_data || !oem_data->data) {
1374 		wma_err("oem_data is null");
1375 		return QDF_STATUS_E_INVAL;
1376 	}
1377 
1378 	if (wma_validate_handle(wma_handle))
1379 		return QDF_STATUS_E_INVAL;
1380 
1381 	wmi_handle = wma_handle->wmi_handle;
1382 	if (wmi_validate_handle(wmi_handle))
1383 		return QDF_STATUS_E_INVAL;
1384 
1385 	/* common api, for oem data command case */
1386 	ret = wmi_unified_start_oemv2_data_cmd(wmi_handle, oem_data);
1387 	if (!QDF_IS_STATUS_SUCCESS(ret))
1388 		wma_err("call start wmi cmd failed");
1389 
1390 	return ret;
1391 }
1392 #endif
1393 
1394 #if !defined(REMOVE_PKT_LOG) && defined(FEATURE_PKTLOG)
1395 /**
1396  * wma_pktlog_wmi_send_cmd() - send pktlog enable/disable command to target
1397  * @handle: wma handle
1398  * @params: pktlog params
1399  *
1400  * Return: QDF status
1401  */
1402 QDF_STATUS wma_pktlog_wmi_send_cmd(WMA_HANDLE handle,
1403 				   struct ath_pktlog_wmi_params *params)
1404 {
1405 	tp_wma_handle wma_handle = (tp_wma_handle) handle;
1406 	int ret;
1407 
1408 	ret = wmi_unified_pktlog_wmi_send_cmd(wma_handle->wmi_handle,
1409 			params->pktlog_event,
1410 			params->cmd_id, params->user_triggered);
1411 	if (ret)
1412 		return QDF_STATUS_E_FAILURE;
1413 
1414 	return QDF_STATUS_SUCCESS;
1415 }
1416 #endif /* !REMOVE_PKT_LOG && FEATURE_PKTLOG */
1417 
1418 /**
1419  * wma_wow_wake_reason_str() -  Converts wow wakeup reason code to text format
1420  * @wake_reason - WOW wake reason
1421  *
1422  * Return: reason code in string format
1423  */
1424 static const uint8_t *wma_wow_wake_reason_str(A_INT32 wake_reason)
1425 {
1426 	switch (wake_reason) {
1427 	case WOW_REASON_UNSPECIFIED:
1428 		return "UNSPECIFIED";
1429 	case WOW_REASON_NLOD:
1430 		return "NLOD";
1431 	case WOW_REASON_AP_ASSOC_LOST:
1432 		return "AP_ASSOC_LOST";
1433 	case WOW_REASON_LOW_RSSI:
1434 		return "LOW_RSSI";
1435 	case WOW_REASON_DEAUTH_RECVD:
1436 		return "DEAUTH_RECVD";
1437 	case WOW_REASON_DISASSOC_RECVD:
1438 		return "DISASSOC_RECVD";
1439 	case WOW_REASON_GTK_HS_ERR:
1440 		return "GTK_HS_ERR";
1441 	case WOW_REASON_EAP_REQ:
1442 		return "EAP_REQ";
1443 	case WOW_REASON_FOURWAY_HS_RECV:
1444 		return "FOURWAY_HS_RECV";
1445 	case WOW_REASON_TIMER_INTR_RECV:
1446 		return "TIMER_INTR_RECV";
1447 	case WOW_REASON_PATTERN_MATCH_FOUND:
1448 		return "PATTERN_MATCH_FOUND";
1449 	case WOW_REASON_RECV_MAGIC_PATTERN:
1450 		return "RECV_MAGIC_PATTERN";
1451 	case WOW_REASON_P2P_DISC:
1452 		return "P2P_DISC";
1453 	case WOW_REASON_WLAN_HB:
1454 		return "WLAN_HB";
1455 	case WOW_REASON_CSA_EVENT:
1456 		return "CSA_EVENT";
1457 	case WOW_REASON_PROBE_REQ_WPS_IE_RECV:
1458 		return "PROBE_REQ_WPS_IE_RECV";
1459 	case WOW_REASON_AUTH_REQ_RECV:
1460 		return "AUTH_REQ_RECV";
1461 	case WOW_REASON_ASSOC_REQ_RECV:
1462 		return "ASSOC_REQ_RECV";
1463 	case WOW_REASON_HTT_EVENT:
1464 		return "HTT_EVENT";
1465 	case WOW_REASON_RA_MATCH:
1466 		return "RA_MATCH";
1467 	case WOW_REASON_HOST_AUTO_SHUTDOWN:
1468 		return "HOST_AUTO_SHUTDOWN";
1469 	case WOW_REASON_IOAC_MAGIC_EVENT:
1470 		return "IOAC_MAGIC_EVENT";
1471 	case WOW_REASON_IOAC_SHORT_EVENT:
1472 		return "IOAC_SHORT_EVENT";
1473 	case WOW_REASON_IOAC_EXTEND_EVENT:
1474 		return "IOAC_EXTEND_EVENT";
1475 	case WOW_REASON_IOAC_TIMER_EVENT:
1476 		return "IOAC_TIMER_EVENT";
1477 	case WOW_REASON_ROAM_HO:
1478 		return "ROAM_HO";
1479 	case WOW_REASON_ROAM_PREAUTH_START:
1480 		return "ROAM_PREAUTH_START_EVENT";
1481 	case WOW_REASON_DFS_PHYERR_RADADR_EVENT:
1482 		return "DFS_PHYERR_RADADR_EVENT";
1483 	case WOW_REASON_BEACON_RECV:
1484 		return "BEACON_RECV";
1485 	case WOW_REASON_CLIENT_KICKOUT_EVENT:
1486 		return "CLIENT_KICKOUT_EVENT";
1487 	case WOW_REASON_NAN_EVENT:
1488 		return "NAN_EVENT";
1489 	case WOW_REASON_EXTSCAN:
1490 		return "EXTSCAN";
1491 	case WOW_REASON_RSSI_BREACH_EVENT:
1492 		return "RSSI_BREACH_EVENT";
1493 	case WOW_REASON_IOAC_REV_KA_FAIL_EVENT:
1494 		return "IOAC_REV_KA_FAIL_EVENT";
1495 	case WOW_REASON_IOAC_SOCK_EVENT:
1496 		return "IOAC_SOCK_EVENT";
1497 	case WOW_REASON_NLO_SCAN_COMPLETE:
1498 		return "NLO_SCAN_COMPLETE";
1499 	case WOW_REASON_PACKET_FILTER_MATCH:
1500 		return "PACKET_FILTER_MATCH";
1501 	case WOW_REASON_ASSOC_RES_RECV:
1502 		return "ASSOC_RES_RECV";
1503 	case WOW_REASON_REASSOC_REQ_RECV:
1504 		return "REASSOC_REQ_RECV";
1505 	case WOW_REASON_REASSOC_RES_RECV:
1506 		return "REASSOC_RES_RECV";
1507 	case WOW_REASON_ACTION_FRAME_RECV:
1508 		return "ACTION_FRAME_RECV";
1509 	case WOW_REASON_BPF_ALLOW:
1510 		return "BPF_ALLOW";
1511 	case WOW_REASON_NAN_DATA:
1512 		return "NAN_DATA";
1513 	case WOW_REASON_OEM_RESPONSE_EVENT:
1514 		return "OEM_RESPONSE_EVENT";
1515 	case WOW_REASON_TDLS_CONN_TRACKER_EVENT:
1516 		return "TDLS_CONN_TRACKER_EVENT";
1517 	case WOW_REASON_CRITICAL_LOG:
1518 		return "CRITICAL_LOG";
1519 	case WOW_REASON_P2P_LISTEN_OFFLOAD:
1520 		return "P2P_LISTEN_OFFLOAD";
1521 	case WOW_REASON_NAN_EVENT_WAKE_HOST:
1522 		return "NAN_EVENT_WAKE_HOST";
1523 	case WOW_REASON_DEBUG_TEST:
1524 		return "DEBUG_TEST";
1525 	case WOW_REASON_CHIP_POWER_FAILURE_DETECT:
1526 		return "CHIP_POWER_FAILURE_DETECT";
1527 	case WOW_REASON_11D_SCAN:
1528 		return "11D_SCAN";
1529 	case WOW_REASON_SAP_OBSS_DETECTION:
1530 		return "SAP_OBSS_DETECTION";
1531 	case WOW_REASON_BSS_COLOR_COLLISION_DETECT:
1532 		return "BSS_COLOR_COLLISION_DETECT";
1533 #ifdef WLAN_FEATURE_MOTION_DETECTION
1534 	case WOW_REASON_WLAN_MD:
1535 		return "MOTION_DETECT";
1536 	case WOW_REASON_WLAN_BL:
1537 		return "MOTION_DETECT_BASELINE";
1538 #endif /* WLAN_FEATURE_MOTION_DETECTION */
1539 	case WOW_REASON_PAGE_FAULT:
1540 		return "PAGE_FAULT";
1541 	case WOW_REASON_ROAM_PMKID_REQUEST:
1542 		return "ROAM_PMKID_REQUEST";
1543 	case WOW_REASON_VDEV_DISCONNECT:
1544 		return "VDEV_DISCONNECT";
1545 	case WOW_REASON_LOCAL_DATA_UC_DROP:
1546 		return "LOCAL_DATA_UC_DROP";
1547 	case WOW_REASON_FATAL_EVENT_WAKE:
1548 		return "FATAL_EVENT_WAKE";
1549 	case WOW_REASON_GENERIC_WAKE:
1550 		return "GENERIC_WAKE";
1551 	case WOW_REASON_TWT:
1552 		return "TWT Event";
1553 	default:
1554 		return "unknown";
1555 	}
1556 }
1557 
1558 static bool wma_wow_reason_has_stats(enum wake_reason_e reason)
1559 {
1560 	switch (reason) {
1561 	case WOW_REASON_ASSOC_REQ_RECV:
1562 	case WOW_REASON_DISASSOC_RECVD:
1563 	case WOW_REASON_ASSOC_RES_RECV:
1564 	case WOW_REASON_REASSOC_REQ_RECV:
1565 	case WOW_REASON_REASSOC_RES_RECV:
1566 	case WOW_REASON_AUTH_REQ_RECV:
1567 	case WOW_REASON_DEAUTH_RECVD:
1568 	case WOW_REASON_ACTION_FRAME_RECV:
1569 	case WOW_REASON_BPF_ALLOW:
1570 	case WOW_REASON_PATTERN_MATCH_FOUND:
1571 	case WOW_REASON_PACKET_FILTER_MATCH:
1572 	case WOW_REASON_RA_MATCH:
1573 	case WOW_REASON_NLOD:
1574 	case WOW_REASON_NLO_SCAN_COMPLETE:
1575 	case WOW_REASON_LOW_RSSI:
1576 	case WOW_REASON_EXTSCAN:
1577 	case WOW_REASON_RSSI_BREACH_EVENT:
1578 	case WOW_REASON_OEM_RESPONSE_EVENT:
1579 	case WOW_REASON_CHIP_POWER_FAILURE_DETECT:
1580 	case WOW_REASON_11D_SCAN:
1581 	case WOW_REASON_LOCAL_DATA_UC_DROP:
1582 	case WOW_REASON_FATAL_EVENT_WAKE:
1583 		return true;
1584 #ifdef WLAN_FEATURE_MOTION_DETECTION
1585 	case WOW_REASON_WLAN_MD:
1586 	case WOW_REASON_WLAN_BL:
1587 		return true;
1588 #endif /* WLAN_FEATURE_MOTION_DETECTION */
1589 	default:
1590 		return false;
1591 	}
1592 }
1593 
1594 static void wma_inc_wow_stats(t_wma_handle *wma,
1595 			      WOW_EVENT_INFO_fixed_param *wake_info)
1596 {
1597 	ucfg_mc_cp_stats_inc_wake_lock_stats(wma->psoc,
1598 					     wake_info->vdev_id,
1599 					     wake_info->wake_reason);
1600 }
1601 
1602 static void wma_wow_stats_display(struct wake_lock_stats *stats)
1603 {
1604 	wma_conditional_log(is_wakeup_event_console_logs_enabled,
1605 			    "WLAN wake reason counters:");
1606 	wma_conditional_log(is_wakeup_event_console_logs_enabled,
1607 			    "uc:%d bc:%d v4_mc:%d v6_mc:%d ra:%d ns:%d na:%d "
1608 			    "icmp:%d icmpv6:%d",
1609 			    stats->ucast_wake_up_count,
1610 			    stats->bcast_wake_up_count,
1611 			    stats->ipv4_mcast_wake_up_count,
1612 			    stats->ipv6_mcast_wake_up_count,
1613 			    stats->ipv6_mcast_ra_stats,
1614 			    stats->ipv6_mcast_ns_stats,
1615 			    stats->ipv6_mcast_na_stats,
1616 			    stats->icmpv4_count,
1617 			    stats->icmpv6_count);
1618 
1619 	wma_conditional_log(is_wakeup_event_console_logs_enabled,
1620 			    "assoc:%d disassoc:%d assoc_resp:%d reassoc:%d "
1621 			    "reassoc_resp:%d auth:%d deauth:%d action:%d",
1622 			    stats->mgmt_assoc,
1623 			    stats->mgmt_disassoc,
1624 			    stats->mgmt_assoc_resp,
1625 			    stats->mgmt_reassoc,
1626 			    stats->mgmt_reassoc_resp,
1627 			    stats->mgmt_auth,
1628 			    stats->mgmt_deauth,
1629 			    stats->mgmt_action);
1630 
1631 	wma_conditional_log(is_wakeup_event_console_logs_enabled,
1632 			    "pno_match:%d pno_complete:%d gscan:%d low_rssi:%d"
1633 			    " rssi_breach:%d oem:%d ucdrop:%d scan_11d:%d"
1634 			    " fatal_event:%d",
1635 			    stats->pno_match_wake_up_count,
1636 			    stats->pno_complete_wake_up_count,
1637 			    stats->gscan_wake_up_count,
1638 			    stats->low_rssi_wake_up_count,
1639 			    stats->rssi_breach_wake_up_count,
1640 			    stats->oem_response_wake_up_count,
1641 			    stats->uc_drop_wake_up_count,
1642 			    stats->scan_11d,
1643 			    stats->fatal_event_wake_up_count);
1644 }
1645 
1646 static void wma_print_wow_stats(t_wma_handle *wma,
1647 				WOW_EVENT_INFO_fixed_param *wake_info)
1648 {
1649 	struct wlan_objmgr_vdev *vdev;
1650 	struct wake_lock_stats stats = {0};
1651 
1652 	if (!wma_wow_reason_has_stats(wake_info->wake_reason))
1653 		return;
1654 
1655 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(wma->psoc,
1656 						    wake_info->vdev_id,
1657 						    WLAN_LEGACY_WMA_ID);
1658 	if (!vdev) {
1659 		wma_err("vdev_id: %d, failed to get vdev from psoc",
1660 			wake_info->vdev_id);
1661 		return;
1662 	}
1663 
1664 	ucfg_mc_cp_stats_get_vdev_wake_lock_stats(vdev, &stats);
1665 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_WMA_ID);
1666 	wma_wow_stats_display(&stats);
1667 }
1668 
1669 #ifdef FEATURE_WLAN_EXTSCAN
1670 /**
1671  * wma_extscan_get_eventid_from_tlvtag() - map tlv tag to corresponding event id
1672  * @tag: WMI TLV tag
1673  *
1674  * Return:
1675  *	0 if TLV tag is invalid
1676  *	else return corresponding WMI event id
1677  */
1678 static int wma_extscan_get_eventid_from_tlvtag(uint32_t tag)
1679 {
1680 	uint32_t event_id;
1681 
1682 	switch (tag) {
1683 	case WMITLV_TAG_STRUC_wmi_extscan_start_stop_event_fixed_param:
1684 		event_id = WMI_EXTSCAN_START_STOP_EVENTID;
1685 		break;
1686 
1687 	case WMITLV_TAG_STRUC_wmi_extscan_operation_event_fixed_param:
1688 		event_id = WMI_EXTSCAN_OPERATION_EVENTID;
1689 		break;
1690 
1691 	case WMITLV_TAG_STRUC_wmi_extscan_table_usage_event_fixed_param:
1692 		event_id = WMI_EXTSCAN_TABLE_USAGE_EVENTID;
1693 		break;
1694 
1695 	case WMITLV_TAG_STRUC_wmi_extscan_cached_results_event_fixed_param:
1696 		event_id = WMI_EXTSCAN_CACHED_RESULTS_EVENTID;
1697 		break;
1698 
1699 	case WMITLV_TAG_STRUC_wmi_extscan_wlan_change_results_event_fixed_param:
1700 		event_id = WMI_EXTSCAN_WLAN_CHANGE_RESULTS_EVENTID;
1701 		break;
1702 
1703 	case WMITLV_TAG_STRUC_wmi_extscan_hotlist_match_event_fixed_param:
1704 		event_id = WMI_EXTSCAN_HOTLIST_MATCH_EVENTID;
1705 		break;
1706 
1707 	case WMITLV_TAG_STRUC_wmi_extscan_capabilities_event_fixed_param:
1708 		event_id = WMI_EXTSCAN_CAPABILITIES_EVENTID;
1709 		break;
1710 
1711 	default:
1712 		event_id = 0;
1713 		wma_err("Unknown tag: %d", tag);
1714 		break;
1715 	}
1716 
1717 	wma_info("For tag %d WMI event 0x%x", tag, event_id);
1718 	return event_id;
1719 }
1720 #else
1721 static int wma_extscan_get_eventid_from_tlvtag(uint32_t tag)
1722 {
1723 	return 0;
1724 }
1725 #endif
1726 
1727 /**
1728  * wow_get_wmi_eventid() - map reason or tlv tag to corresponding event id
1729  * @tag: WMI TLV tag
1730  * @reason: WOW reason
1731  *
1732  * WOW reason type is primarily used to find the ID. If there could be
1733  * multiple events that can be sent as a WOW event with same reason
1734  * then tlv tag is used to identify the corresponding event.
1735  *
1736  * Return:
1737  *      0 if TLV tag/reason is invalid
1738  *      else return corresponding WMI event id
1739  */
1740 static int wow_get_wmi_eventid(int32_t reason, uint32_t tag)
1741 {
1742 	int event_id;
1743 
1744 	switch (reason) {
1745 	case WOW_REASON_AP_ASSOC_LOST:
1746 		event_id = WMI_ROAM_EVENTID;
1747 		break;
1748 	case WOW_REASON_NLO_SCAN_COMPLETE:
1749 		event_id = WMI_NLO_SCAN_COMPLETE_EVENTID;
1750 		break;
1751 	case WOW_REASON_CSA_EVENT:
1752 		event_id = WMI_CSA_HANDLING_EVENTID;
1753 		break;
1754 	case WOW_REASON_LOW_RSSI:
1755 		event_id = WMI_ROAM_EVENTID;
1756 		break;
1757 	case WOW_REASON_CLIENT_KICKOUT_EVENT:
1758 		event_id = WMI_PEER_STA_KICKOUT_EVENTID;
1759 		break;
1760 	case WOW_REASON_EXTSCAN:
1761 		event_id = wma_extscan_get_eventid_from_tlvtag(tag);
1762 		break;
1763 	case WOW_REASON_RSSI_BREACH_EVENT:
1764 		event_id = WMI_RSSI_BREACH_EVENTID;
1765 		break;
1766 	case WOW_REASON_NAN_EVENT:
1767 		event_id = WMI_NAN_EVENTID;
1768 		break;
1769 	case WOW_REASON_NAN_DATA:
1770 		event_id = wma_ndp_get_eventid_from_tlvtag(tag);
1771 		break;
1772 	case WOW_REASON_TDLS_CONN_TRACKER_EVENT:
1773 		event_id = WOW_TDLS_CONN_TRACKER_EVENT;
1774 		break;
1775 	case WOW_REASON_ROAM_HO:
1776 		event_id = WMI_ROAM_EVENTID;
1777 		break;
1778 	case WOW_REASON_11D_SCAN:
1779 		event_id = WMI_11D_NEW_COUNTRY_EVENTID;
1780 		break;
1781 	case WOW_ROAM_PREAUTH_START_EVENT:
1782 		event_id = WMI_ROAM_PREAUTH_STATUS_CMDID;
1783 		break;
1784 	case WOW_REASON_ROAM_PMKID_REQUEST:
1785 		event_id = WMI_ROAM_PMKID_REQUEST_EVENTID;
1786 		break;
1787 	case WOW_REASON_VDEV_DISCONNECT:
1788 		event_id = WMI_VDEV_DISCONNECT_EVENTID;
1789 		break;
1790 	default:
1791 		wma_debug("No Event Id for WOW reason %s(%d)",
1792 			 wma_wow_wake_reason_str(reason), reason);
1793 		event_id = 0;
1794 		break;
1795 	}
1796 	wlan_roam_debug_log(WMA_INVALID_VDEV_ID, DEBUG_WOW_REASON,
1797 			    DEBUG_INVALID_PEER_ID, NULL, NULL,
1798 			    reason, event_id);
1799 
1800 	return event_id;
1801 }
1802 
1803 /**
1804  * is_piggybacked_event() - Returns true if the given wake reason indicates
1805  *	there will be piggybacked TLV event data
1806  * @reason: WOW reason
1807  *
1808  * There are three types of WoW event payloads: none, piggybacked event, and
1809  * network packet. This function returns true for wake reasons that fall into
1810  * the piggybacked event case.
1811  *
1812  * Return: true for piggybacked event data
1813  */
1814 static bool is_piggybacked_event(int32_t reason)
1815 {
1816 	switch (reason) {
1817 	case WOW_REASON_AP_ASSOC_LOST:
1818 	case WOW_REASON_NLO_SCAN_COMPLETE:
1819 	case WOW_REASON_CSA_EVENT:
1820 	case WOW_REASON_LOW_RSSI:
1821 	case WOW_REASON_CLIENT_KICKOUT_EVENT:
1822 	case WOW_REASON_EXTSCAN:
1823 	case WOW_REASON_RSSI_BREACH_EVENT:
1824 	case WOW_REASON_NAN_EVENT:
1825 	case WOW_REASON_NAN_DATA:
1826 	case WOW_REASON_TDLS_CONN_TRACKER_EVENT:
1827 	case WOW_REASON_ROAM_HO:
1828 	case WOW_REASON_ROAM_PMKID_REQUEST:
1829 	case WOW_REASON_VDEV_DISCONNECT:
1830 	case WOW_REASON_TWT:
1831 		return true;
1832 	default:
1833 		return false;
1834 	}
1835 }
1836 
1837 /**
1838  * wma_pkt_proto_subtype_to_string() - to convert proto subtype
1839  *         of data packet to string.
1840  * @proto_subtype: proto subtype for data packet
1841  *
1842  * This function returns the string for the proto subtype of
1843  * data packet.
1844  *
1845  * Return: string for proto subtype for data packet
1846  */
1847 static const char *
1848 wma_pkt_proto_subtype_to_string(enum qdf_proto_subtype proto_subtype)
1849 {
1850 	switch (proto_subtype) {
1851 	case QDF_PROTO_EAPOL_M1:
1852 		return "EAPOL M1";
1853 	case QDF_PROTO_EAPOL_M2:
1854 		return "EAPOL M2";
1855 	case QDF_PROTO_EAPOL_M3:
1856 		return "EAPOL M3";
1857 	case QDF_PROTO_EAPOL_M4:
1858 		return "EAPOL M4";
1859 	case QDF_PROTO_DHCP_DISCOVER:
1860 		return "DHCP DISCOVER";
1861 	case QDF_PROTO_DHCP_REQUEST:
1862 		return "DHCP REQUEST";
1863 	case QDF_PROTO_DHCP_OFFER:
1864 		return "DHCP OFFER";
1865 	case QDF_PROTO_DHCP_ACK:
1866 		return "DHCP ACK";
1867 	case QDF_PROTO_DHCP_NACK:
1868 		return "DHCP NACK";
1869 	case QDF_PROTO_DHCP_RELEASE:
1870 		return "DHCP RELEASE";
1871 	case QDF_PROTO_DHCP_INFORM:
1872 		return "DHCP INFORM";
1873 	case QDF_PROTO_DHCP_DECLINE:
1874 		return "DHCP DECLINE";
1875 	case QDF_PROTO_ARP_REQ:
1876 		return "ARP REQUEST";
1877 	case QDF_PROTO_ARP_RES:
1878 		return "ARP RESPONSE";
1879 	case QDF_PROTO_ICMP_REQ:
1880 		return "ICMP REQUEST";
1881 	case QDF_PROTO_ICMP_RES:
1882 		return "ICMP RESPONSE";
1883 	case QDF_PROTO_ICMPV6_REQ:
1884 		return "ICMPV6 REQUEST";
1885 	case QDF_PROTO_ICMPV6_RES:
1886 		return "ICMPV6 RESPONSE";
1887 	case QDF_PROTO_ICMPV6_RS:
1888 		return "ICMPV6 RS";
1889 	case QDF_PROTO_ICMPV6_RA:
1890 		return "ICMPV6 RA";
1891 	case QDF_PROTO_ICMPV6_NS:
1892 		return "ICMPV6 NS";
1893 	case QDF_PROTO_ICMPV6_NA:
1894 		return "ICMPV6 NA";
1895 	case QDF_PROTO_IPV4_UDP:
1896 		return "IPV4 UDP Packet";
1897 	case QDF_PROTO_IPV4_TCP:
1898 		return "IPV4 TCP Packet";
1899 	case QDF_PROTO_IPV6_UDP:
1900 		return "IPV6 UDP Packet";
1901 	case QDF_PROTO_IPV6_TCP:
1902 		return "IPV6 TCP Packet";
1903 	default:
1904 		return NULL;
1905 	}
1906 }
1907 
1908 /**
1909  * wma_wow_get_pkt_proto_subtype() - get the proto subtype of the packet.
1910  * @data: Pointer to the packet data buffer
1911  * @len: length of the packet data buffer
1912  *
1913  * Return: proto subtype of the packet.
1914  */
1915 static enum qdf_proto_subtype
1916 wma_wow_get_pkt_proto_subtype(uint8_t *data, uint32_t len)
1917 {
1918 	uint16_t eth_type;
1919 	uint8_t proto_type;
1920 
1921 	if (len < QDF_NBUF_TRAC_ETH_TYPE_OFFSET + 2) {
1922 		wma_err("Malformed ethernet packet: length %u < %d",
1923 			len, QDF_NBUF_TRAC_ETH_TYPE_OFFSET + 2);
1924 		return QDF_PROTO_INVALID;
1925 	}
1926 
1927 	eth_type = *(uint16_t *)(data + QDF_NBUF_TRAC_ETH_TYPE_OFFSET);
1928 	eth_type = qdf_cpu_to_be16(eth_type);
1929 
1930 	wma_debug("Ether Type: 0x%04x", eth_type);
1931 	switch (eth_type) {
1932 	case QDF_NBUF_TRAC_EAPOL_ETH_TYPE:
1933 		if (len < WMA_EAPOL_SUBTYPE_GET_MIN_LEN)
1934 			return QDF_PROTO_INVALID;
1935 
1936 		wma_debug("EAPOL Packet");
1937 		return qdf_nbuf_data_get_eapol_subtype(data);
1938 
1939 	case QDF_NBUF_TRAC_ARP_ETH_TYPE:
1940 		if (len < WMA_ARP_SUBTYPE_GET_MIN_LEN)
1941 			return QDF_PROTO_INVALID;
1942 
1943 		wma_debug("ARP Packet");
1944 		return qdf_nbuf_data_get_arp_subtype(data);
1945 
1946 	case QDF_NBUF_TRAC_IPV4_ETH_TYPE:
1947 		if (len < WMA_IPV4_PROTO_GET_MIN_LEN)
1948 			return QDF_PROTO_INVALID;
1949 
1950 		wma_debug("IPV4 Packet");
1951 
1952 		proto_type = qdf_nbuf_data_get_ipv4_proto(data);
1953 		wma_debug("IPV4_proto_type: %u", proto_type);
1954 
1955 		switch (proto_type) {
1956 		case QDF_NBUF_TRAC_ICMP_TYPE:
1957 			if (len < WMA_ICMP_SUBTYPE_GET_MIN_LEN)
1958 				return QDF_PROTO_INVALID;
1959 
1960 			wma_debug("ICMP Packet");
1961 			return qdf_nbuf_data_get_icmp_subtype(data);
1962 
1963 		case QDF_NBUF_TRAC_UDP_TYPE:
1964 			if (len < WMA_IS_DHCP_GET_MIN_LEN)
1965 				return QDF_PROTO_IPV4_UDP;
1966 
1967 			if (!qdf_nbuf_data_is_ipv4_dhcp_pkt(data))
1968 				return QDF_PROTO_INVALID;
1969 
1970 			if (len < WMA_DHCP_SUBTYPE_GET_MIN_LEN)
1971 				return QDF_PROTO_INVALID;
1972 
1973 			wma_debug("DHCP Packet");
1974 			return qdf_nbuf_data_get_dhcp_subtype(data);
1975 
1976 		case QDF_NBUF_TRAC_TCP_TYPE:
1977 			return QDF_PROTO_IPV4_TCP;
1978 
1979 		default:
1980 			return QDF_PROTO_INVALID;
1981 		}
1982 
1983 	case QDF_NBUF_TRAC_IPV6_ETH_TYPE:
1984 		if (len < WMA_IPV6_PROTO_GET_MIN_LEN)
1985 			return QDF_PROTO_INVALID;
1986 
1987 		wma_debug("IPV6 Packet");
1988 
1989 		proto_type = qdf_nbuf_data_get_ipv6_proto(data);
1990 		wma_debug("IPV6_proto_type: %u", proto_type);
1991 
1992 		switch (proto_type) {
1993 		case QDF_NBUF_TRAC_ICMPV6_TYPE:
1994 			if (len < WMA_ICMPV6_SUBTYPE_GET_MIN_LEN)
1995 				return QDF_PROTO_INVALID;
1996 
1997 			wma_debug("ICMPV6 Packet");
1998 			return qdf_nbuf_data_get_icmpv6_subtype(data);
1999 
2000 		case QDF_NBUF_TRAC_UDP_TYPE:
2001 			return QDF_PROTO_IPV6_UDP;
2002 
2003 		case QDF_NBUF_TRAC_TCP_TYPE:
2004 			return QDF_PROTO_IPV6_TCP;
2005 
2006 		default:
2007 			return QDF_PROTO_INVALID;
2008 		}
2009 
2010 	default:
2011 		return QDF_PROTO_INVALID;
2012 	}
2013 }
2014 
2015 static void wma_log_pkt_eapol(uint8_t *data, uint32_t length)
2016 {
2017 	uint16_t pkt_len, key_len;
2018 
2019 	if (length < WMA_EAPOL_INFO_GET_MIN_LEN)
2020 		return;
2021 
2022 	pkt_len = *(uint16_t *)(data + EAPOL_PKT_LEN_OFFSET);
2023 	key_len = *(uint16_t *)(data + EAPOL_KEY_LEN_OFFSET);
2024 	wma_debug("Pkt_len: %u, Key_len: %u",
2025 		 qdf_cpu_to_be16(pkt_len), qdf_cpu_to_be16(key_len));
2026 }
2027 
2028 static void wma_log_pkt_dhcp(uint8_t *data, uint32_t length)
2029 {
2030 	uint16_t pkt_len;
2031 	uint32_t trans_id;
2032 
2033 	if (length < WMA_DHCP_INFO_GET_MIN_LEN)
2034 		return;
2035 
2036 	pkt_len = *(uint16_t *)(data + DHCP_PKT_LEN_OFFSET);
2037 	trans_id = *(uint32_t *)(data + DHCP_TRANSACTION_ID_OFFSET);
2038 	wma_debug("Pkt_len: %u, Transaction_id: %u",
2039 		 qdf_cpu_to_be16(pkt_len), qdf_cpu_to_be16(trans_id));
2040 }
2041 
2042 static void wma_log_pkt_icmpv4(uint8_t *data, uint32_t length)
2043 {
2044 	uint16_t pkt_len, seq_num;
2045 
2046 	if (length < WMA_IPV4_PKT_INFO_GET_MIN_LEN)
2047 		return;
2048 
2049 	pkt_len = *(uint16_t *)(data + IPV4_PKT_LEN_OFFSET);
2050 	seq_num = *(uint16_t *)(data + ICMP_SEQ_NUM_OFFSET);
2051 	wma_debug("Pkt_len: %u, Seq_num: %u",
2052 		 qdf_cpu_to_be16(pkt_len), qdf_cpu_to_be16(seq_num));
2053 }
2054 
2055 static void wma_log_pkt_icmpv6(uint8_t *data, uint32_t length)
2056 {
2057 	uint16_t pkt_len, seq_num;
2058 
2059 	if (length < WMA_IPV6_PKT_INFO_GET_MIN_LEN)
2060 		return;
2061 
2062 	pkt_len = *(uint16_t *)(data + IPV6_PKT_LEN_OFFSET);
2063 	seq_num = *(uint16_t *)(data + ICMPV6_SEQ_NUM_OFFSET);
2064 	wma_debug("Pkt_len: %u, Seq_num: %u",
2065 		 qdf_cpu_to_be16(pkt_len), qdf_cpu_to_be16(seq_num));
2066 }
2067 
2068 static void wma_log_pkt_ipv4(uint8_t *data, uint32_t length)
2069 {
2070 	uint16_t pkt_len, src_port, dst_port;
2071 	char *ip_addr;
2072 
2073 	if (length < WMA_IPV4_PKT_INFO_GET_MIN_LEN)
2074 		return;
2075 
2076 	pkt_len = *(uint16_t *)(data + IPV4_PKT_LEN_OFFSET);
2077 	ip_addr = (char *)(data + IPV4_SRC_ADDR_OFFSET);
2078 	wma_nofl_debug("src addr %d:%d:%d:%d", ip_addr[0], ip_addr[1],
2079 		      ip_addr[2], ip_addr[3]);
2080 	ip_addr = (char *)(data + IPV4_DST_ADDR_OFFSET);
2081 	wma_nofl_debug("dst addr %d:%d:%d:%d", ip_addr[0], ip_addr[1],
2082 		      ip_addr[2], ip_addr[3]);
2083 	src_port = *(uint16_t *)(data + IPV4_SRC_PORT_OFFSET);
2084 	dst_port = *(uint16_t *)(data + IPV4_DST_PORT_OFFSET);
2085 	wma_info("Pkt_len: %u, src_port: %u, dst_port: %u",
2086 		qdf_cpu_to_be16(pkt_len),
2087 		qdf_cpu_to_be16(src_port),
2088 		qdf_cpu_to_be16(dst_port));
2089 }
2090 
2091 static void wma_log_pkt_ipv6(uint8_t *data, uint32_t length)
2092 {
2093 	uint16_t pkt_len, src_port, dst_port;
2094 	char *ip_addr;
2095 
2096 	if (length < WMA_IPV6_PKT_INFO_GET_MIN_LEN)
2097 		return;
2098 
2099 	pkt_len = *(uint16_t *)(data + IPV6_PKT_LEN_OFFSET);
2100 	ip_addr = (char *)(data + IPV6_SRC_ADDR_OFFSET);
2101 	wma_nofl_debug("src addr "IPV6_ADDR_STR, ip_addr[0],
2102 		 ip_addr[1], ip_addr[2], ip_addr[3], ip_addr[4],
2103 		 ip_addr[5], ip_addr[6], ip_addr[7], ip_addr[8],
2104 		 ip_addr[9], ip_addr[10], ip_addr[11],
2105 		 ip_addr[12], ip_addr[13], ip_addr[14],
2106 		 ip_addr[15]);
2107 	ip_addr = (char *)(data + IPV6_DST_ADDR_OFFSET);
2108 	wma_nofl_debug("dst addr "IPV6_ADDR_STR, ip_addr[0],
2109 		 ip_addr[1], ip_addr[2], ip_addr[3], ip_addr[4],
2110 		 ip_addr[5], ip_addr[6], ip_addr[7], ip_addr[8],
2111 		 ip_addr[9], ip_addr[10], ip_addr[11],
2112 		 ip_addr[12], ip_addr[13], ip_addr[14],
2113 		 ip_addr[15]);
2114 	src_port = *(uint16_t *)(data + IPV6_SRC_PORT_OFFSET);
2115 	dst_port = *(uint16_t *)(data + IPV6_DST_PORT_OFFSET);
2116 	wma_info("Pkt_len: %u, src_port: %u, dst_port: %u",
2117 		 qdf_cpu_to_be16(pkt_len),
2118 		 qdf_cpu_to_be16(src_port),
2119 		 qdf_cpu_to_be16(dst_port));
2120 }
2121 
2122 static void wma_log_pkt_tcpv4(uint8_t *data, uint32_t length)
2123 {
2124 	uint32_t seq_num;
2125 
2126 	if (length < WMA_IPV4_PKT_INFO_GET_MIN_LEN)
2127 		return;
2128 
2129 	seq_num = *(uint32_t *)(data + IPV4_TCP_SEQ_NUM_OFFSET);
2130 	wma_debug("TCP_seq_num: %u", qdf_cpu_to_be16(seq_num));
2131 }
2132 
2133 static void wma_log_pkt_tcpv6(uint8_t *data, uint32_t length)
2134 {
2135 	uint32_t seq_num;
2136 
2137 	if (length < WMA_IPV6_PKT_INFO_GET_MIN_LEN)
2138 		return;
2139 
2140 	seq_num = *(uint32_t *)(data + IPV6_TCP_SEQ_NUM_OFFSET);
2141 	wma_debug("TCP_seq_num: %u", qdf_cpu_to_be16(seq_num));
2142 }
2143 
2144 static void wma_wow_inc_wake_lock_stats_by_dst_addr(t_wma_handle *wma,
2145 						    uint8_t vdev_id,
2146 						    uint8_t *dest_mac)
2147 {
2148 	ucfg_mc_cp_stats_inc_wake_lock_stats_by_dst_addr(wma->psoc,
2149 							 vdev_id,
2150 							 dest_mac);
2151 }
2152 
2153 static void wma_wow_inc_wake_lock_stats_by_protocol(t_wma_handle *wma,
2154 			uint8_t vdev_id, enum qdf_proto_subtype proto_subtype)
2155 {
2156 	ucfg_mc_cp_stats_inc_wake_lock_stats_by_protocol(wma->psoc,
2157 							 vdev_id,
2158 							 proto_subtype);
2159 }
2160 
2161 /**
2162  * wma_wow_parse_data_pkt() - API to parse data buffer for data
2163  *    packet that resulted in WOW wakeup.
2164  * @stats: per-vdev stats for tracking packet types
2165  * @data: Pointer to data buffer
2166  * @length: data buffer length
2167  *
2168  * This function parses the data buffer received (first few bytes of
2169  * skb->data) to get information like src mac addr, dst mac addr, packet
2170  * len, seq_num, etc. It also increments stats for different packet types.
2171  *
2172  * Return: void
2173  */
2174 static void wma_wow_parse_data_pkt(t_wma_handle *wma,
2175 				   uint8_t vdev_id, uint8_t *data,
2176 				   uint32_t length)
2177 {
2178 	uint8_t *src_mac;
2179 	uint8_t *dest_mac;
2180 	const char *proto_subtype_name;
2181 	enum qdf_proto_subtype proto_subtype;
2182 
2183 	wma_debug("packet length: %u", length);
2184 	if (length < QDF_NBUF_TRAC_IPV4_OFFSET)
2185 		return;
2186 
2187 	src_mac = data + QDF_NBUF_SRC_MAC_OFFSET;
2188 	dest_mac = data + QDF_NBUF_DEST_MAC_OFFSET;
2189 	wma_conditional_log(is_wakeup_event_console_logs_enabled,
2190 			    "Src_mac: " QDF_MAC_ADDR_FMT ", Dst_mac: "
2191 			    QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(src_mac),
2192 			    QDF_MAC_ADDR_REF(dest_mac));
2193 
2194 	wma_wow_inc_wake_lock_stats_by_dst_addr(wma, vdev_id, dest_mac);
2195 
2196 	proto_subtype = wma_wow_get_pkt_proto_subtype(data, length);
2197 	proto_subtype_name = wma_pkt_proto_subtype_to_string(proto_subtype);
2198 	if (proto_subtype_name)
2199 		wma_conditional_log(is_wakeup_event_console_logs_enabled,
2200 				    "WOW Wakeup: %s rcvd", proto_subtype_name);
2201 
2202 	switch (proto_subtype) {
2203 	case QDF_PROTO_EAPOL_M1:
2204 	case QDF_PROTO_EAPOL_M2:
2205 	case QDF_PROTO_EAPOL_M3:
2206 	case QDF_PROTO_EAPOL_M4:
2207 		wma_log_pkt_eapol(data, length);
2208 		break;
2209 
2210 	case QDF_PROTO_DHCP_DISCOVER:
2211 	case QDF_PROTO_DHCP_REQUEST:
2212 	case QDF_PROTO_DHCP_OFFER:
2213 	case QDF_PROTO_DHCP_ACK:
2214 	case QDF_PROTO_DHCP_NACK:
2215 	case QDF_PROTO_DHCP_RELEASE:
2216 	case QDF_PROTO_DHCP_INFORM:
2217 	case QDF_PROTO_DHCP_DECLINE:
2218 		wma_log_pkt_dhcp(data, length);
2219 		break;
2220 
2221 	case QDF_PROTO_ICMP_REQ:
2222 	case QDF_PROTO_ICMP_RES:
2223 		wma_wow_inc_wake_lock_stats_by_protocol(wma, vdev_id,
2224 							proto_subtype);
2225 		wma_log_pkt_icmpv4(data, length);
2226 		break;
2227 
2228 	case QDF_PROTO_ICMPV6_REQ:
2229 	case QDF_PROTO_ICMPV6_RES:
2230 	case QDF_PROTO_ICMPV6_RS:
2231 	case QDF_PROTO_ICMPV6_RA:
2232 	case QDF_PROTO_ICMPV6_NS:
2233 	case QDF_PROTO_ICMPV6_NA:
2234 		wma_wow_inc_wake_lock_stats_by_protocol(wma, vdev_id,
2235 							proto_subtype);
2236 		wma_log_pkt_icmpv6(data, length);
2237 		break;
2238 
2239 	case QDF_PROTO_IPV4_UDP:
2240 		wma_log_pkt_ipv4(data, length);
2241 		break;
2242 	case QDF_PROTO_IPV4_TCP:
2243 		wma_log_pkt_ipv4(data, length);
2244 		wma_log_pkt_tcpv4(data, length);
2245 		break;
2246 
2247 	case QDF_PROTO_IPV6_UDP:
2248 		wma_log_pkt_ipv6(data, length);
2249 		break;
2250 	case QDF_PROTO_IPV6_TCP:
2251 		wma_log_pkt_ipv6(data, length);
2252 		wma_log_pkt_tcpv6(data, length);
2253 		break;
2254 	default:
2255 		break;
2256 	}
2257 }
2258 
2259 /**
2260  * wma_wow_dump_mgmt_buffer() - API to parse data buffer for mgmt.
2261  *    packet that resulted in WOW wakeup.
2262  * @wow_packet_buffer: Pointer to data buffer
2263  * @buf_len: length of data buffer
2264  *
2265  * This function parses the data buffer received (802.11 header)
2266  * to get information like src mac addr, dst mac addr, seq_num,
2267  * frag_num, etc.
2268  *
2269  * Return: void
2270  */
2271 static void wma_wow_dump_mgmt_buffer(uint8_t *wow_packet_buffer,
2272 				     uint32_t buf_len)
2273 {
2274 	struct ieee80211_frame_addr4 *wh;
2275 
2276 	wma_debug("wow_buf_pkt_len: %u", buf_len);
2277 	wh = (struct ieee80211_frame_addr4 *)
2278 		(wow_packet_buffer);
2279 	if (buf_len >= sizeof(struct ieee80211_frame)) {
2280 		uint8_t to_from_ds, frag_num;
2281 		uint32_t seq_num;
2282 
2283 		wma_conditional_log(is_wakeup_event_console_logs_enabled,
2284 				    "RA: " QDF_MAC_ADDR_FMT " TA: "
2285 				    QDF_MAC_ADDR_FMT,
2286 				    QDF_MAC_ADDR_REF(wh->i_addr1),
2287 				    QDF_MAC_ADDR_REF(wh->i_addr2));
2288 
2289 		wma_conditional_log(is_wakeup_event_console_logs_enabled,
2290 				    "TO_DS: %u, FROM_DS: %u",
2291 				    wh->i_fc[1] & IEEE80211_FC1_DIR_TODS,
2292 				    wh->i_fc[1] & IEEE80211_FC1_DIR_FROMDS);
2293 
2294 		to_from_ds = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK;
2295 
2296 		switch (to_from_ds) {
2297 		case IEEE80211_FC1_DIR_NODS:
2298 			wma_conditional_log(
2299 				is_wakeup_event_console_logs_enabled,
2300 				"BSSID: " QDF_MAC_ADDR_FMT,
2301 				QDF_MAC_ADDR_REF(wh->i_addr3));
2302 			break;
2303 		case IEEE80211_FC1_DIR_TODS:
2304 			wma_conditional_log(
2305 				is_wakeup_event_console_logs_enabled,
2306 				"DA: " QDF_MAC_ADDR_FMT,
2307 				QDF_MAC_ADDR_REF(wh->i_addr3));
2308 			break;
2309 		case IEEE80211_FC1_DIR_FROMDS:
2310 			wma_conditional_log(
2311 				is_wakeup_event_console_logs_enabled,
2312 				"SA: " QDF_MAC_ADDR_FMT,
2313 				QDF_MAC_ADDR_REF(wh->i_addr3));
2314 			break;
2315 		case IEEE80211_FC1_DIR_DSTODS:
2316 			if (buf_len >= sizeof(struct ieee80211_frame_addr4))
2317 				wma_conditional_log(
2318 					is_wakeup_event_console_logs_enabled,
2319 					"DA: " QDF_MAC_ADDR_FMT " SA: "
2320 					QDF_MAC_ADDR_FMT,
2321 					QDF_MAC_ADDR_REF(wh->i_addr3),
2322 					QDF_MAC_ADDR_REF(wh->i_addr4));
2323 			break;
2324 		}
2325 
2326 		seq_num = (((*(uint16_t *)wh->i_seq) &
2327 				IEEE80211_SEQ_SEQ_MASK) >>
2328 				IEEE80211_SEQ_SEQ_SHIFT);
2329 		frag_num = (((*(uint16_t *)wh->i_seq) &
2330 				IEEE80211_SEQ_FRAG_MASK) >>
2331 				IEEE80211_SEQ_FRAG_SHIFT);
2332 
2333 		wma_conditional_log(is_wakeup_event_console_logs_enabled,
2334 				    "SEQ_NUM: %u, FRAG_NUM: %u", seq_num,
2335 				    frag_num);
2336 	} else {
2337 		wma_err("Insufficient buffer length for mgmt. packet");
2338 	}
2339 }
2340 
2341 /**
2342  * wma_acquire_wakelock() - conditionally aquires a wakelock base on wake reason
2343  * @wma: the wma handle with the wakelocks to aquire
2344  * @wake_reason: wow wakeup reason
2345  *
2346  * Return: None
2347  */
2348 static void wma_acquire_wow_wakelock(t_wma_handle *wma, int wake_reason)
2349 {
2350 	qdf_wake_lock_t *wl;
2351 	uint32_t ms;
2352 
2353 	switch (wake_reason) {
2354 	case WOW_REASON_AUTH_REQ_RECV:
2355 		wl = &wma->wow_auth_req_wl;
2356 		ms = WMA_AUTH_REQ_RECV_WAKE_LOCK_TIMEOUT;
2357 		break;
2358 	case WOW_REASON_ASSOC_REQ_RECV:
2359 		wl = &wma->wow_assoc_req_wl;
2360 		ms = WMA_ASSOC_REQ_RECV_WAKE_LOCK_DURATION;
2361 		break;
2362 	case WOW_REASON_DEAUTH_RECVD:
2363 		wl = &wma->wow_deauth_rec_wl;
2364 		ms = WMA_DEAUTH_RECV_WAKE_LOCK_DURATION;
2365 		break;
2366 	case WOW_REASON_DISASSOC_RECVD:
2367 		wl = &wma->wow_disassoc_rec_wl;
2368 		ms = WMA_DISASSOC_RECV_WAKE_LOCK_DURATION;
2369 		break;
2370 	case WOW_REASON_AP_ASSOC_LOST:
2371 		wl = &wma->wow_ap_assoc_lost_wl;
2372 		ms = WMA_BMISS_EVENT_WAKE_LOCK_DURATION;
2373 		break;
2374 #ifdef FEATURE_WLAN_AUTO_SHUTDOWN
2375 	case WOW_REASON_HOST_AUTO_SHUTDOWN:
2376 		wl = &wma->wow_auto_shutdown_wl;
2377 		ms = WMA_AUTO_SHUTDOWN_WAKE_LOCK_DURATION;
2378 		break;
2379 #endif
2380 	case WOW_REASON_ROAM_HO:
2381 		wl = &wma->roam_ho_wl;
2382 		ms = WMA_ROAM_HO_WAKE_LOCK_DURATION;
2383 		break;
2384 	case WOW_REASON_ROAM_PREAUTH_START:
2385 		wl = &wma->roam_preauth_wl;
2386 		ms = WMA_ROAM_PREAUTH_WAKE_LOCK_DURATION;
2387 		break;
2388 	case WOW_REASON_PROBE_REQ_WPS_IE_RECV:
2389 		wl = &wma->probe_req_wps_wl;
2390 		ms = WMA_REASON_PROBE_REQ_WPS_IE_RECV_DURATION;
2391 		break;
2392 	default:
2393 		return;
2394 	}
2395 
2396 	wma_alert("Holding %d msec wake_lock", ms);
2397 	cds_host_diag_log_work(wl, ms, WIFI_POWER_EVENT_WAKELOCK_WOW);
2398 	qdf_wake_lock_timeout_acquire(wl, ms);
2399 }
2400 
2401 /**
2402  * wma_wake_reason_ap_assoc_lost() - WOW_REASON_AP_ASSOC_LOST handler
2403  * @wma: Pointer to wma handle
2404  * @event: pointer to piggybacked WMI_ROAM_EVENTID_param_tlvs buffer
2405  * @len: length of the event buffer
2406  *
2407  * Return: Errno
2408  */
2409 static int
2410 wma_wake_reason_ap_assoc_lost(t_wma_handle *wma, void *event, uint32_t len)
2411 {
2412 	WMI_ROAM_EVENTID_param_tlvs *event_param;
2413 	wmi_roam_event_fixed_param *roam_event;
2414 
2415 	event_param = event;
2416 	if (!event_param) {
2417 		wma_err("AP Assoc Lost event data is null");
2418 		return -EINVAL;
2419 	}
2420 
2421 	roam_event = event_param->fixed_param;
2422 	wma_alert("Beacon miss indication on vdev %d", roam_event->vdev_id);
2423 
2424 	wma_beacon_miss_handler(wma, roam_event->vdev_id, roam_event->rssi);
2425 
2426 	return 0;
2427 }
2428 
2429 static const char *wma_vdev_type_str(uint32_t vdev_type)
2430 {
2431 	switch (vdev_type) {
2432 	case WMI_VDEV_TYPE_AP:
2433 		return "AP";
2434 	case WMI_VDEV_TYPE_STA:
2435 		return "STA";
2436 	case WMI_VDEV_TYPE_IBSS:
2437 		return "IBSS";
2438 	case WMI_VDEV_TYPE_MONITOR:
2439 		return "MONITOR";
2440 	case WMI_VDEV_TYPE_NAN:
2441 		return "NAN";
2442 	case WMI_VDEV_TYPE_OCB:
2443 		return "OCB";
2444 	case WMI_VDEV_TYPE_NDI:
2445 		return "NDI";
2446 	default:
2447 		return "unknown";
2448 	}
2449 }
2450 
2451 static int wma_wake_event_packet(
2452 	t_wma_handle *wma,
2453 	WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *event_param,
2454 	uint32_t length)
2455 {
2456 	WOW_EVENT_INFO_fixed_param *wake_info;
2457 	struct wma_txrx_node *vdev;
2458 	uint8_t *packet;
2459 	uint32_t packet_len;
2460 
2461 	if (event_param->num_wow_packet_buffer <= 4) {
2462 		wma_err("Invalid wow packet buffer from firmware %u",
2463 			 event_param->num_wow_packet_buffer);
2464 		return -EINVAL;
2465 	}
2466 	/* first 4 bytes are the length, followed by the buffer */
2467 	packet_len = *(uint32_t *)event_param->wow_packet_buffer;
2468 	packet = event_param->wow_packet_buffer + 4;
2469 
2470 	if (!packet_len) {
2471 		wma_err("Wake event packet is empty");
2472 		return 0;
2473 	}
2474 
2475 	if (packet_len > (event_param->num_wow_packet_buffer - 4)) {
2476 		wma_err("Invalid packet_len from firmware, packet_len: %u, num_wow_packet_buffer: %u",
2477 			 packet_len,
2478 			 event_param->num_wow_packet_buffer);
2479 		return -EINVAL;
2480 	}
2481 
2482 	wake_info = event_param->fixed_param;
2483 
2484 	switch (wake_info->wake_reason) {
2485 	case WOW_REASON_AUTH_REQ_RECV:
2486 	case WOW_REASON_ASSOC_REQ_RECV:
2487 	case WOW_REASON_DEAUTH_RECVD:
2488 	case WOW_REASON_DISASSOC_RECVD:
2489 	case WOW_REASON_ASSOC_RES_RECV:
2490 	case WOW_REASON_REASSOC_REQ_RECV:
2491 	case WOW_REASON_REASSOC_RES_RECV:
2492 	case WOW_REASON_BEACON_RECV:
2493 	case WOW_REASON_ACTION_FRAME_RECV:
2494 		/* management frame case */
2495 		wma_wow_dump_mgmt_buffer(packet, packet_len);
2496 		break;
2497 
2498 	case WOW_REASON_BPF_ALLOW:
2499 	case WOW_REASON_PATTERN_MATCH_FOUND:
2500 	case WOW_REASON_RA_MATCH:
2501 	case WOW_REASON_RECV_MAGIC_PATTERN:
2502 	case WOW_REASON_PACKET_FILTER_MATCH:
2503 		wma_debug("Wake event packet:");
2504 		qdf_trace_hex_dump(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_DEBUG,
2505 				   packet, packet_len);
2506 
2507 		vdev = &wma->interfaces[wake_info->vdev_id];
2508 		wma_wow_parse_data_pkt(wma, wake_info->vdev_id,
2509 				       packet, packet_len);
2510 		break;
2511 
2512 	case WOW_REASON_PAGE_FAULT:
2513 		/*
2514 		 * In case PAGE_FAULT occurs on non-DRV platform,
2515 		 * dump event buffer which contains more info regarding
2516 		 * current page fault.
2517 		 */
2518 		wma_info("PAGE_FAULT occurs during suspend: packet_len %u",
2519 			 packet_len);
2520 		qdf_trace_hex_dump(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_INFO,
2521 				   packet, packet_len);
2522 		break;
2523 
2524 	default:
2525 		return -EINVAL;
2526 	}
2527 
2528 	return 0;
2529 }
2530 
2531 static int wma_wake_event_no_payload(
2532 	t_wma_handle *wma,
2533 	WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *event_param,
2534 	uint32_t length)
2535 {
2536 	WOW_EVENT_INFO_fixed_param *wake_info = event_param->fixed_param;
2537 
2538 	switch (wake_info->wake_reason) {
2539 	case WOW_REASON_HOST_AUTO_SHUTDOWN:
2540 		return wma_wake_reason_auto_shutdown();
2541 
2542 	case WOW_REASON_NLOD:
2543 		return wma_wake_reason_nlod(wma, wake_info->vdev_id);
2544 
2545 	case WOW_REASON_GENERIC_WAKE:
2546 		wma_info("Wake reason %s",
2547 			 wma_wow_wake_reason_str(wake_info->wake_reason));
2548 		return 0;
2549 
2550 	default:
2551 		return 0;
2552 	}
2553 }
2554 
2555 static int wma_wake_event_piggybacked(
2556 	t_wma_handle *wma,
2557 	WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *event_param,
2558 	uint32_t length)
2559 {
2560 	int errno = 0;
2561 	void *pb_event;
2562 	uint32_t pb_event_len;
2563 	uint32_t wake_reason;
2564 	uint32_t event_id;
2565 	uint8_t *bssid;
2566 	tpDeleteStaContext del_sta_ctx;
2567 
2568 	/*
2569 	 * There are "normal" cases where a wake reason that usually contains a
2570 	 * piggybacked event is empty. In these cases we just want to wake up,
2571 	 * and no action is needed. Bail out now if that is the case.
2572 	 */
2573 	if (!event_param->wow_packet_buffer ||
2574 	    event_param->num_wow_packet_buffer <= 4) {
2575 		wma_err("Invalid wow packet buffer from firmware %u",
2576 			 event_param->num_wow_packet_buffer);
2577 		return 0;
2578 	}
2579 
2580 	bssid = wma_get_vdev_bssid
2581 		(wma->interfaces[event_param->fixed_param->vdev_id].vdev);
2582 	if (!bssid) {
2583 		wma_err("Failed to get bssid for vdev_%d",
2584 			event_param->fixed_param->vdev_id);
2585 		return 0;
2586 	}
2587 	wake_reason = event_param->fixed_param->wake_reason;
2588 
2589 	/* parse piggybacked event from param buffer */
2590 	{
2591 		int ret_code;
2592 		uint8_t *pb_event_buf;
2593 		uint32_t tag;
2594 
2595 		/* first 4 bytes are the length, followed by the buffer */
2596 		pb_event_len = *(uint32_t *)event_param->wow_packet_buffer;
2597 		if (pb_event_len > (event_param->num_wow_packet_buffer - 4)) {
2598 			wma_err("Invalid pb_event_len from firmware, pb_event_len: %u, num_wow_packet_buffer: %u",
2599 				 pb_event_len,
2600 				 event_param->num_wow_packet_buffer);
2601 			return -EINVAL;
2602 		}
2603 		pb_event_buf = event_param->wow_packet_buffer + 4;
2604 
2605 		wma_debug("piggybacked event buffer:");
2606 		qdf_trace_hex_dump(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_DEBUG,
2607 				   pb_event_buf, pb_event_len);
2608 
2609 		tag = WMITLV_GET_TLVTAG(WMITLV_GET_HDR(pb_event_buf));
2610 		event_id = wow_get_wmi_eventid(wake_reason, tag);
2611 		if (!event_id) {
2612 			wma_err("Unable to find Event Id");
2613 			return -EINVAL;
2614 		}
2615 
2616 		ret_code = wmitlv_check_and_pad_event_tlvs(wma, pb_event_buf,
2617 							   pb_event_len,
2618 							   event_id, &pb_event);
2619 		if (ret_code) {
2620 			wma_err("Bad TLVs; len:%d, event_id:%d, status:%d",
2621 				 pb_event_len, event_id, ret_code);
2622 			return -EINVAL;
2623 		}
2624 	}
2625 
2626 	switch (wake_reason) {
2627 	case WOW_REASON_AP_ASSOC_LOST:
2628 		errno = wma_wake_reason_ap_assoc_lost(wma, pb_event,
2629 						      pb_event_len);
2630 		break;
2631 
2632 #ifdef FEATURE_WLAN_SCAN_PNO
2633 	case WOW_REASON_NLO_SCAN_COMPLETE:
2634 		errno = target_if_nlo_complete_handler(wma, pb_event,
2635 						       pb_event_len);
2636 		break;
2637 #endif /* FEATURE_WLAN_SCAN_PNO */
2638 
2639 	case WOW_REASON_CSA_EVENT:
2640 		errno = wma_csa_offload_handler(wma, pb_event, pb_event_len);
2641 		break;
2642 
2643 	/*
2644 	 * WOW_REASON_LOW_RSSI is used for following roaming events -
2645 	 * WMI_ROAM_REASON_BETTER_AP, WMI_ROAM_REASON_BMISS,
2646 	 * WMI_ROAM_REASON_SUITABLE_AP will be handled by
2647 	 * wma_roam_event_callback().
2648 	 * WOW_REASON_ROAM_HO is associated with
2649 	 * WMI_ROAM_REASON_HO_FAILED event and it will be handled by
2650 	 * wma_roam_event_callback().
2651 	 */
2652 	case WOW_REASON_LOW_RSSI:
2653 	case WOW_REASON_ROAM_HO:
2654 		wlan_roam_debug_log(event_param->fixed_param->vdev_id,
2655 				    DEBUG_WOW_ROAM_EVENT,
2656 				    DEBUG_INVALID_PEER_ID,
2657 				    NULL, NULL, wake_reason,
2658 				    pb_event_len);
2659 		if (pb_event_len > 0) {
2660 			errno = wma_roam_event_callback(wma, pb_event,
2661 							pb_event_len);
2662 		} else {
2663 			/*
2664 			 * No wow_packet_buffer means a better AP beacon
2665 			 * will follow in a later event.
2666 			 */
2667 			wma_debug("Host woken up because of better AP beacon");
2668 		}
2669 		break;
2670 
2671 	case WOW_REASON_CLIENT_KICKOUT_EVENT:
2672 		errno = wma_peer_sta_kickout_event_handler(wma, pb_event,
2673 							   pb_event_len);
2674 		break;
2675 
2676 #ifdef FEATURE_WLAN_EXTSCAN
2677 	case WOW_REASON_EXTSCAN:
2678 		errno = wma_extscan_wow_event_callback(wma, pb_event,
2679 						       pb_event_len);
2680 		break;
2681 #endif
2682 
2683 	case WOW_REASON_RSSI_BREACH_EVENT:
2684 		errno = wma_rssi_breached_event_handler(wma, pb_event,
2685 							pb_event_len);
2686 		break;
2687 
2688 	case WOW_REASON_NAN_EVENT:
2689 		errno = wma_nan_rsp_handler_callback(wma, pb_event,
2690 						     pb_event_len);
2691 		break;
2692 
2693 	case WOW_REASON_NAN_DATA:
2694 		errno = wma_ndp_wow_event_callback(wma, pb_event, pb_event_len,
2695 						   event_id);
2696 		break;
2697 
2698 #ifdef FEATURE_WLAN_TDLS
2699 	case WOW_REASON_TDLS_CONN_TRACKER_EVENT:
2700 		errno = wma_tdls_event_handler(wma, pb_event, pb_event_len);
2701 		break;
2702 #endif
2703 
2704 	case WOW_REASON_TIMER_INTR_RECV:
2705 		/*
2706 		 * Right now firmware is not returning any cookie host has
2707 		 * programmed. So do not check for cookie.
2708 		 */
2709 		wma_err("WOW_REASON_TIMER_INTR_RECV received, indicating key exchange did not finish. Initiate disconnect");
2710 		del_sta_ctx = qdf_mem_malloc(sizeof(*del_sta_ctx));
2711 		if (!del_sta_ctx)
2712 			break;
2713 
2714 		del_sta_ctx->is_tdls = false;
2715 		del_sta_ctx->vdev_id = event_param->fixed_param->vdev_id;
2716 		qdf_mem_copy(del_sta_ctx->addr2, bssid, QDF_MAC_ADDR_SIZE);
2717 		qdf_mem_copy(del_sta_ctx->bssId, bssid, QDF_MAC_ADDR_SIZE);
2718 		del_sta_ctx->reasonCode = HAL_DEL_STA_REASON_CODE_KEEP_ALIVE;
2719 		wma_send_msg(wma, SIR_LIM_DELETE_STA_CONTEXT_IND, del_sta_ctx,
2720 			     0);
2721 		break;
2722 	case WOW_REASON_ROAM_PMKID_REQUEST:
2723 		wma_debug("Host woken up because of PMKID request event");
2724 		errno = wma_roam_pmkid_request_event_handler(wma, pb_event,
2725 							     pb_event_len);
2726 		break;
2727 	case WOW_REASON_VDEV_DISCONNECT:
2728 		wma_debug("Host woken up because of vdev disconnect event");
2729 		errno = wma_roam_vdev_disconnect_event_handler(wma, pb_event,
2730 							       pb_event_len);
2731 		break;
2732 	default:
2733 		wma_err("Wake reason %s(%u) is not a piggybacked event",
2734 			 wma_wow_wake_reason_str(wake_reason), wake_reason);
2735 		errno = -EINVAL;
2736 		break;
2737 	}
2738 
2739 	wmitlv_free_allocated_event_tlvs(event_id, &pb_event);
2740 
2741 	return errno;
2742 }
2743 
2744 static void wma_debug_assert_page_fault_wakeup(uint32_t reason)
2745 {
2746 	/* During DRV if page fault wake up then assert */
2747 	if ((WOW_REASON_PAGE_FAULT == reason) && (qdf_is_drv_connected()))
2748 		QDF_DEBUG_PANIC("Unexpected page fault wake up detected during DRV wow");
2749 }
2750 
2751 static void wma_wake_event_log_reason(t_wma_handle *wma,
2752 				      WOW_EVENT_INFO_fixed_param *wake_info)
2753 {
2754 	struct wma_txrx_node *vdev;
2755 
2756 	/* "Unspecified" means APPS triggered wake, else firmware triggered */
2757 	if (wake_info->wake_reason != WOW_REASON_UNSPECIFIED) {
2758 		vdev = &wma->interfaces[wake_info->vdev_id];
2759 		wma_nofl_alert("WLAN triggered wakeup: %s (%d), vdev: %d (%s)",
2760 			      wma_wow_wake_reason_str(wake_info->wake_reason),
2761 			      wake_info->wake_reason,
2762 			      wake_info->vdev_id,
2763 			      wma_vdev_type_str(vdev->type));
2764 		wma_debug_assert_page_fault_wakeup(wake_info->wake_reason);
2765 	} else if (!wmi_get_runtime_pm_inprogress(wma->wmi_handle)) {
2766 		wma_nofl_alert("Non-WLAN triggered wakeup: %s (%d)",
2767 			      wma_wow_wake_reason_str(wake_info->wake_reason),
2768 			      wake_info->wake_reason);
2769 	}
2770 
2771 	qdf_wow_wakeup_host_event(wake_info->wake_reason);
2772 	qdf_wma_wow_wakeup_stats_event(wma);
2773 }
2774 
2775 /**
2776  * wma_wow_wakeup_host_event() - wakeup host event handler
2777  * @handle: wma handle
2778  * @event: event data
2779  * @len: buffer length
2780  *
2781  * Handler to catch wow wakeup host event. This event will have
2782  * reason why the firmware has woken the host.
2783  *
2784  * Return: Errno
2785  */
2786 int wma_wow_wakeup_host_event(void *handle, uint8_t *event, uint32_t len)
2787 {
2788 	int errno;
2789 	t_wma_handle *wma = handle;
2790 	WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *event_param;
2791 	WOW_EVENT_INFO_fixed_param *wake_info;
2792 
2793 	event_param = (WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *)event;
2794 	if (!event_param) {
2795 		wma_err("Wake event data is null");
2796 		return -EINVAL;
2797 	}
2798 
2799 	wake_info = event_param->fixed_param;
2800 
2801 	if (wake_info->vdev_id >= wma->max_bssid) {
2802 		wma_err("received invalid vdev_id %d", wake_info->vdev_id);
2803 		return -EINVAL;
2804 	}
2805 
2806 	wma_wake_event_log_reason(wma, wake_info);
2807 
2808 	ucfg_pmo_psoc_wakeup_host_event_received(wma->psoc);
2809 
2810 	wma_print_wow_stats(wma, wake_info);
2811 	/* split based on payload type */
2812 	if (is_piggybacked_event(wake_info->wake_reason))
2813 		errno = wma_wake_event_piggybacked(wma, event_param, len);
2814 	else if (event_param->wow_packet_buffer)
2815 		errno = wma_wake_event_packet(wma, event_param, len);
2816 	else
2817 		errno = wma_wake_event_no_payload(wma, event_param, len);
2818 
2819 	wma_inc_wow_stats(wma, wake_info);
2820 	wma_print_wow_stats(wma, wake_info);
2821 	wma_acquire_wow_wakelock(wma, wake_info->wake_reason);
2822 
2823 	return errno;
2824 }
2825 
2826 #ifdef FEATURE_WLAN_D0WOW
2827 /**
2828  * wma_d0_wow_disable_ack_event() - wakeup host event handler
2829  * @handle: wma handle
2830  * @event: event data
2831  * @len: buffer length
2832  *
2833  * Handler to catch D0-WOW disable ACK event.  This event will have
2834  * reason why the firmware has woken the host.
2835  * This is for backward compatible with cld2.0.
2836  *
2837  * Return: 0 for success or error
2838  */
2839 int wma_d0_wow_disable_ack_event(void *handle, uint8_t *event, uint32_t len)
2840 {
2841 	tp_wma_handle wma = (tp_wma_handle)handle;
2842 	WMI_D0_WOW_DISABLE_ACK_EVENTID_param_tlvs *param_buf;
2843 	wmi_d0_wow_disable_ack_event_fixed_param *resp_data;
2844 
2845 	param_buf = (WMI_D0_WOW_DISABLE_ACK_EVENTID_param_tlvs *)event;
2846 	if (!param_buf) {
2847 		wma_err("Invalid D0-WOW disable ACK event buffer!");
2848 		return -EINVAL;
2849 	}
2850 
2851 	resp_data = param_buf->fixed_param;
2852 
2853 	ucfg_pmo_psoc_wakeup_host_event_received(wma->psoc);
2854 
2855 	wma_debug("Received D0-WOW disable ACK");
2856 
2857 	return 0;
2858 }
2859 #else
2860 int wma_d0_wow_disable_ack_event(void *handle, uint8_t *event, uint32_t len)
2861 {
2862 	return 0;
2863 }
2864 #endif
2865 
2866 /**
2867  * wma_pdev_resume_event_handler() - PDEV resume event handler
2868  * @handle: wma handle
2869  * @event: event data
2870  * @len: buffer length
2871  *
2872  * Return: 0 for success or error
2873  */
2874 int wma_pdev_resume_event_handler(void *handle, uint8_t *event, uint32_t len)
2875 {
2876 	tp_wma_handle wma = (tp_wma_handle) handle;
2877 
2878 	wma_nofl_alert("Received PDEV resume event");
2879 
2880 	ucfg_pmo_psoc_wakeup_host_event_received(wma->psoc);
2881 
2882 	return 0;
2883 }
2884 
2885 /**
2886  * wma_del_ts_req() - send DELTS request to fw
2887  * @wma: wma handle
2888  * @msg: delts params
2889  *
2890  * Return: none
2891  */
2892 void wma_del_ts_req(tp_wma_handle wma, struct del_ts_params *msg)
2893 {
2894 	if (!wma_is_vdev_valid(msg->sessionId)) {
2895 		wma_err("vdev id:%d is not active ", msg->sessionId);
2896 		qdf_mem_free(msg);
2897 		return;
2898 	}
2899 	if (wmi_unified_del_ts_cmd(wma->wmi_handle,
2900 				 msg->sessionId,
2901 				 TID_TO_WME_AC(msg->userPrio))) {
2902 		wma_alert("Failed to send vdev DELTS command");
2903 	}
2904 
2905 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
2906 	if (msg->setRICparams == true)
2907 		wma_set_ric_req(wma, msg, false);
2908 #endif /* WLAN_FEATURE_ROAM_OFFLOAD */
2909 	qdf_mem_free(msg);
2910 }
2911 
2912 void wma_aggr_qos_req(tp_wma_handle wma,
2913 		      struct aggr_add_ts_param *aggr_qos_rsp_msg)
2914 {
2915 	if (!wma_is_vdev_valid(aggr_qos_rsp_msg->vdev_id)) {
2916 		wma_err("vdev id:%d is not active ",
2917 			 aggr_qos_rsp_msg->vdev_id);
2918 		return;
2919 	}
2920 	wmi_unified_aggr_qos_cmd(wma->wmi_handle, aggr_qos_rsp_msg);
2921 	/* send response to upper layers from here only. */
2922 	wma_send_msg_high_priority(wma, WMA_AGGR_QOS_RSP, aggr_qos_rsp_msg, 0);
2923 }
2924 
2925 #ifdef FEATURE_WLAN_ESE
2926 /**
2927  * wma_set_tsm_interval() - Set TSM interval
2928  * @req: pointer to ADDTS request
2929  *
2930  * Return: QDF_STATUS_E_FAILURE or QDF_STATUS_SUCCESS
2931  */
2932 static QDF_STATUS wma_set_tsm_interval(struct add_ts_param *req)
2933 {
2934 	/*
2935 	 * msmt_interval is in unit called TU (1 TU = 1024 us)
2936 	 * max value of msmt_interval cannot make resulting
2937 	 * interval_milliseconds overflow 32 bit
2938 	 *
2939 	 */
2940 	uint32_t interval_milliseconds;
2941 
2942 	interval_milliseconds = (req->tsm_interval * 1024) / 1000;
2943 
2944 	cdp_tx_set_compute_interval(cds_get_context(QDF_MODULE_ID_SOC),
2945 			WMI_PDEV_ID_SOC,
2946 			interval_milliseconds);
2947 	return QDF_STATUS_SUCCESS;
2948 }
2949 #else
2950 static inline QDF_STATUS wma_set_tsm_interval(struct add_ts_param *req)
2951 {
2952 	return QDF_STATUS_SUCCESS;
2953 }
2954 #endif /* FEATURE_WLAN_ESE */
2955 
2956 /**
2957  * wma_add_ts_req() - send ADDTS request to fw
2958  * @wma: wma handle
2959  * @msg: ADDTS params
2960  *
2961  * Return: none
2962  */
2963 void wma_add_ts_req(tp_wma_handle wma, struct add_ts_param *msg)
2964 {
2965 	struct add_ts_param cmd = {0};
2966 
2967 	msg->status = QDF_STATUS_SUCCESS;
2968 	if (wma_set_tsm_interval(msg) == QDF_STATUS_SUCCESS) {
2969 
2970 		cmd.vdev_id = msg->vdev_id;
2971 		cmd.tspec.tsinfo.traffic.userPrio =
2972 			TID_TO_WME_AC(msg->tspec.tsinfo.traffic.userPrio);
2973 		cmd.tspec.mediumTime = msg->tspec.mediumTime;
2974 		if (wmi_unified_add_ts_cmd(wma->wmi_handle, &cmd))
2975 			msg->status = QDF_STATUS_E_FAILURE;
2976 
2977 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
2978 		if (msg->set_ric_params)
2979 			wma_set_ric_req(wma, msg, true);
2980 #endif /* WLAN_FEATURE_ROAM_OFFLOAD */
2981 
2982 	}
2983 	wma_send_msg_high_priority(wma, WMA_ADD_TS_RSP, msg, 0);
2984 }
2985 
2986 #ifdef FEATURE_WLAN_ESE
2987 
2988 #define TSM_DELAY_HISTROGRAM_BINS 4
2989 /**
2990  * wma_process_tsm_stats_req() - process tsm stats request
2991  * @wma_handler - handle to wma
2992  * @pTsmStatsMsg - TSM stats struct that needs to be populated and
2993  *         passed in message.
2994  *
2995  * A parallel function to WMA_ProcessTsmStatsReq for pronto. This
2996  * function fetches stats from data path APIs and post
2997  * WMA_TSM_STATS_RSP msg back to LIM.
2998  *
2999  * Return: QDF status
3000  */
3001 QDF_STATUS wma_process_tsm_stats_req(tp_wma_handle wma_handler,
3002 				     void *pTsmStatsMsg)
3003 {
3004 	uint8_t counter;
3005 	uint32_t queue_delay_microsec = 0;
3006 	uint32_t tx_delay_microsec = 0;
3007 	uint16_t packet_count = 0;
3008 	uint16_t packet_loss_count = 0;
3009 	tpAniTrafStrmMetrics pTsmMetric = NULL;
3010 	tpAniGetTsmStatsReq pStats = (tpAniGetTsmStatsReq) pTsmStatsMsg;
3011 	tpAniGetTsmStatsRsp pTsmRspParams = NULL;
3012 	int tid = pStats->tid;
3013 	/*
3014 	 * The number of histrogram bin report by data path api are different
3015 	 * than required by TSM, hence different (6) size array used
3016 	 */
3017 	uint16_t bin_values[QCA_TX_DELAY_HIST_REPORT_BINS] = { 0, };
3018 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3019 
3020 	/* get required values from data path APIs */
3021 	cdp_tx_delay(soc,
3022 		WMI_PDEV_ID_SOC,
3023 		&queue_delay_microsec,
3024 		&tx_delay_microsec, tid);
3025 	cdp_tx_delay_hist(soc,
3026 		WMI_PDEV_ID_SOC,
3027 		bin_values, tid);
3028 	cdp_tx_packet_count(soc,
3029 		WMI_PDEV_ID_SOC,
3030 		&packet_count,
3031 		&packet_loss_count, tid);
3032 
3033 	pTsmRspParams = qdf_mem_malloc(sizeof(*pTsmRspParams));
3034 	if (!pTsmRspParams) {
3035 		QDF_ASSERT(0);
3036 		qdf_mem_free(pTsmStatsMsg);
3037 		return QDF_STATUS_E_NOMEM;
3038 	}
3039 
3040 	qdf_copy_macaddr(&pTsmRspParams->bssid, &pStats->bssId);
3041 	pTsmRspParams->rc = QDF_STATUS_E_FAILURE;
3042 	pTsmRspParams->tsmStatsReq = pStats;
3043 	pTsmMetric = &pTsmRspParams->tsmMetrics;
3044 	/* populate pTsmMetric */
3045 	pTsmMetric->UplinkPktQueueDly = queue_delay_microsec;
3046 	/* store only required number of bin values */
3047 	for (counter = 0; counter < TSM_DELAY_HISTROGRAM_BINS; counter++) {
3048 		pTsmMetric->UplinkPktQueueDlyHist[counter] =
3049 			bin_values[counter];
3050 	}
3051 	pTsmMetric->UplinkPktTxDly = tx_delay_microsec;
3052 	pTsmMetric->UplinkPktLoss = packet_loss_count;
3053 	pTsmMetric->UplinkPktCount = packet_count;
3054 
3055 	/*
3056 	 * No need to populate roaming delay and roaming count as they are
3057 	 * being populated just before sending IAPP frame out
3058 	 */
3059 	/* post this message to LIM/PE */
3060 	wma_send_msg(wma_handler, WMA_TSM_STATS_RSP, (void *)pTsmRspParams, 0);
3061 	return QDF_STATUS_SUCCESS;
3062 }
3063 
3064 #endif /* FEATURE_WLAN_ESE */
3065 
3066 /**
3067  * wma_process_mcbc_set_filter_req() - process mcbc set filter request
3068  * @wma_handle: wma handle
3069  * @mcbc_param: mcbc params
3070  *
3071  * Return: QDF status
3072  */
3073 QDF_STATUS wma_process_mcbc_set_filter_req(tp_wma_handle wma_handle,
3074 					   tSirRcvFltMcAddrList *mcbc_param)
3075 {
3076 	return QDF_STATUS_SUCCESS;
3077 }
3078 
3079 /**
3080  * wma_process_add_periodic_tx_ptrn_ind() - add periodic tx pattern
3081  * @handle: wma handle
3082  * @pattern: tx pattern params
3083  *
3084  * Return: QDF status
3085  */
3086 QDF_STATUS wma_process_add_periodic_tx_ptrn_ind(WMA_HANDLE handle,
3087 						tSirAddPeriodicTxPtrn *pattern)
3088 {
3089 	tp_wma_handle wma_handle = (tp_wma_handle) handle;
3090 	struct periodic_tx_pattern *params_ptr;
3091 	uint8_t vdev_id;
3092 	QDF_STATUS status;
3093 	struct wmi_unified *wmi_handle;
3094 
3095 	if (wma_validate_handle(wma_handle))
3096 		return QDF_STATUS_E_INVAL;
3097 
3098 	wmi_handle = wma_handle->wmi_handle;
3099 	if (wmi_validate_handle(wmi_handle))
3100 		return QDF_STATUS_E_INVAL;
3101 
3102 	if (wma_find_vdev_id_by_addr(wma_handle,
3103 				     pattern->mac_address.bytes,
3104 				     &vdev_id)) {
3105 		wma_err("Failed to find vdev id for "QDF_MAC_ADDR_FMT,
3106 			 QDF_MAC_ADDR_REF(pattern->mac_address.bytes));
3107 		return QDF_STATUS_E_INVAL;
3108 	}
3109 
3110 	params_ptr = qdf_mem_malloc(sizeof(*params_ptr));
3111 	if (!params_ptr)
3112 		return QDF_STATUS_E_NOMEM;
3113 
3114 	params_ptr->ucPtrnId = pattern->ucPtrnId;
3115 	params_ptr->ucPtrnSize = pattern->ucPtrnSize;
3116 	params_ptr->usPtrnIntervalMs = pattern->usPtrnIntervalMs;
3117 	qdf_mem_copy(&params_ptr->mac_address, &pattern->mac_address,
3118 		     sizeof(struct qdf_mac_addr));
3119 	qdf_mem_copy(params_ptr->ucPattern, pattern->ucPattern,
3120 		     params_ptr->ucPtrnSize);
3121 
3122 	status = wmi_unified_process_add_periodic_tx_ptrn_cmd(
3123 				wmi_handle, params_ptr, vdev_id);
3124 
3125 	qdf_mem_free(params_ptr);
3126 	return status;
3127 }
3128 
3129 /**
3130  * wma_process_del_periodic_tx_ptrn_ind - del periodic tx ptrn
3131  * @handle: wma handle
3132  * @pDelPeriodicTxPtrnParams: tx ptrn params
3133  *
3134  * Return: QDF status
3135  */
3136 QDF_STATUS wma_process_del_periodic_tx_ptrn_ind(WMA_HANDLE handle,
3137 						tSirDelPeriodicTxPtrn *
3138 						pDelPeriodicTxPtrnParams)
3139 {
3140 	tp_wma_handle wma_handle = (tp_wma_handle) handle;
3141 	uint8_t vdev_id;
3142 	struct wmi_unified *wmi_handle;
3143 
3144 	if (wma_validate_handle(wma_handle))
3145 		return QDF_STATUS_E_INVAL;
3146 
3147 	wmi_handle = wma_handle->wmi_handle;
3148 	if (wmi_validate_handle(wmi_handle))
3149 		return QDF_STATUS_E_INVAL;
3150 
3151 	if (wma_find_vdev_id_by_addr(
3152 			wma_handle,
3153 			pDelPeriodicTxPtrnParams->mac_address.bytes,
3154 			&vdev_id)) {
3155 		wma_err("Failed to find vdev id for "QDF_MAC_ADDR_FMT,
3156 			QDF_MAC_ADDR_REF(pDelPeriodicTxPtrnParams->mac_address.bytes));
3157 		return QDF_STATUS_E_INVAL;
3158 	}
3159 
3160 	return wmi_unified_process_del_periodic_tx_ptrn_cmd(
3161 				wmi_handle, vdev_id,
3162 				pDelPeriodicTxPtrnParams->ucPtrnId);
3163 }
3164 
3165 #ifdef WLAN_FEATURE_STATS_EXT
3166 QDF_STATUS wma_stats_ext_req(void *wma_ptr, tpStatsExtRequest preq)
3167 {
3168 	tp_wma_handle wma = (tp_wma_handle) wma_ptr;
3169 	struct stats_ext_params *params;
3170 	size_t params_len;
3171 	QDF_STATUS status;
3172 
3173 	if (!wma) {
3174 		wma_err("wma handle is NULL");
3175 		return QDF_STATUS_E_FAILURE;
3176 	}
3177 
3178 	params_len = sizeof(*params) + preq->request_data_len;
3179 	params = qdf_mem_malloc(params_len);
3180 	if (!params)
3181 		return QDF_STATUS_E_NOMEM;
3182 
3183 	params->vdev_id = preq->vdev_id;
3184 	params->request_data_len = preq->request_data_len;
3185 	if (preq->request_data_len > 0)
3186 		qdf_mem_copy(params->request_data, preq->request_data,
3187 			     params->request_data_len);
3188 
3189 	status = wmi_unified_stats_ext_req_cmd(wma->wmi_handle, params);
3190 	qdf_mem_free(params);
3191 
3192 	return status;
3193 }
3194 
3195 #endif /* WLAN_FEATURE_STATS_EXT */
3196 
3197 #ifdef WLAN_FEATURE_EXTWOW_SUPPORT
3198 /**
3199  * wma_send_status_of_ext_wow() - send ext wow status to SME
3200  * @wma: wma handle
3201  * @status: status
3202  *
3203  * Return: none
3204  */
3205 static void wma_send_status_of_ext_wow(tp_wma_handle wma, bool status)
3206 {
3207 	tSirReadyToExtWoWInd *ready_to_extwow;
3208 	QDF_STATUS vstatus;
3209 	struct scheduler_msg message = {0};
3210 	uint8_t len;
3211 
3212 	wma_debug("Posting ready to suspend indication to umac");
3213 
3214 	len = sizeof(tSirReadyToExtWoWInd);
3215 	ready_to_extwow = qdf_mem_malloc(len);
3216 	if (!ready_to_extwow)
3217 		return;
3218 
3219 	ready_to_extwow->mesgType = eWNI_SME_READY_TO_EXTWOW_IND;
3220 	ready_to_extwow->mesgLen = len;
3221 	ready_to_extwow->status = status;
3222 
3223 	message.type = eWNI_SME_READY_TO_EXTWOW_IND;
3224 	message.bodyptr = (void *)ready_to_extwow;
3225 	message.bodyval = 0;
3226 
3227 	vstatus = scheduler_post_message(QDF_MODULE_ID_WMA,
3228 					 QDF_MODULE_ID_SME,
3229 					 QDF_MODULE_ID_SME, &message);
3230 	if (vstatus != QDF_STATUS_SUCCESS)
3231 		qdf_mem_free(ready_to_extwow);
3232 }
3233 
3234 /**
3235  * wma_enable_ext_wow() - enable ext wow in fw
3236  * @wma: wma handle
3237  * @params: ext wow params
3238  *
3239  * Return:0 for success or error code
3240  */
3241 QDF_STATUS wma_enable_ext_wow(tp_wma_handle wma, tpSirExtWoWParams params)
3242 {
3243 	struct ext_wow_params wow_params = {0};
3244 	QDF_STATUS status;
3245 
3246 	if (!wma) {
3247 		wma_err("wma handle is NULL");
3248 		return QDF_STATUS_E_FAILURE;
3249 	}
3250 
3251 	wow_params.vdev_id = params->vdev_id;
3252 	wow_params.type = (enum wmi_ext_wow_type) params->type;
3253 	wow_params.wakeup_pin_num = params->wakeup_pin_num;
3254 
3255 	status = wmi_unified_enable_ext_wow_cmd(wma->wmi_handle,
3256 				&wow_params);
3257 	if (QDF_IS_STATUS_ERROR(status))
3258 		return status;
3259 
3260 	wma_send_status_of_ext_wow(wma, true);
3261 	return status;
3262 
3263 }
3264 
3265 /**
3266  * wma_set_app_type1_params_in_fw() - set app type1 params in fw
3267  * @wma: wma handle
3268  * @appType1Params: app type1 params
3269  *
3270  * Return: QDF status
3271  */
3272 int wma_set_app_type1_params_in_fw(tp_wma_handle wma,
3273 				   tpSirAppType1Params appType1Params)
3274 {
3275 	int ret;
3276 
3277 	ret = wmi_unified_app_type1_params_in_fw_cmd(wma->wmi_handle,
3278 				   (struct app_type1_params *)appType1Params);
3279 	if (ret) {
3280 		wma_err("Failed to set APP TYPE1 PARAMS");
3281 		return QDF_STATUS_E_FAILURE;
3282 	}
3283 
3284 	return QDF_STATUS_SUCCESS;
3285 }
3286 
3287 /**
3288  * wma_set_app_type2_params_in_fw() - set app type2 params in fw
3289  * @wma: wma handle
3290  * @appType2Params: app type2 params
3291  *
3292  * Return: QDF status
3293  */
3294 QDF_STATUS wma_set_app_type2_params_in_fw(tp_wma_handle wma,
3295 					  tpSirAppType2Params appType2Params)
3296 {
3297 	struct app_type2_params params = {0};
3298 
3299 	if (!wma) {
3300 		wma_err("wma handle is NULL");
3301 		return QDF_STATUS_E_FAILURE;
3302 	}
3303 
3304 	params.vdev_id = appType2Params->vdev_id;
3305 	params.rc4_key_len = appType2Params->rc4_key_len;
3306 	qdf_mem_copy(params.rc4_key, appType2Params->rc4_key, 16);
3307 	params.ip_id = appType2Params->ip_id;
3308 	params.ip_device_ip = appType2Params->ip_device_ip;
3309 	params.ip_server_ip = appType2Params->ip_server_ip;
3310 	params.tcp_src_port = appType2Params->tcp_src_port;
3311 	params.tcp_dst_port = appType2Params->tcp_dst_port;
3312 	params.tcp_seq = appType2Params->tcp_seq;
3313 	params.tcp_ack_seq = appType2Params->tcp_ack_seq;
3314 	params.keepalive_init = appType2Params->keepalive_init;
3315 	params.keepalive_min = appType2Params->keepalive_min;
3316 	params.keepalive_max = appType2Params->keepalive_max;
3317 	params.keepalive_inc = appType2Params->keepalive_inc;
3318 	params.tcp_tx_timeout_val = appType2Params->tcp_tx_timeout_val;
3319 	params.tcp_rx_timeout_val = appType2Params->tcp_rx_timeout_val;
3320 	qdf_mem_copy(&params.gateway_mac, &appType2Params->gateway_mac,
3321 			sizeof(struct qdf_mac_addr));
3322 
3323 	return wmi_unified_set_app_type2_params_in_fw_cmd(wma->wmi_handle,
3324 							&params);
3325 }
3326 #endif /* WLAN_FEATURE_EXTWOW_SUPPORT */
3327 
3328 #ifdef FEATURE_WLAN_AUTO_SHUTDOWN
3329 /**
3330  * wma_auto_shutdown_event_handler() - process auto shutdown timer trigger
3331  * @handle: wma handle
3332  * @event: event buffer
3333  * @len: buffer length
3334  *
3335  * Return: 0 for success or error code
3336  */
3337 int wma_auto_shutdown_event_handler(void *handle, uint8_t *event,
3338 				    uint32_t len)
3339 {
3340 	wmi_host_auto_shutdown_event_fixed_param *wmi_auto_sh_evt;
3341 	WMI_HOST_AUTO_SHUTDOWN_EVENTID_param_tlvs *param_buf =
3342 		(WMI_HOST_AUTO_SHUTDOWN_EVENTID_param_tlvs *)
3343 		event;
3344 
3345 	if (!param_buf || !param_buf->fixed_param) {
3346 		wma_err("Invalid Auto shutdown timer evt");
3347 		return -EINVAL;
3348 	}
3349 
3350 	wmi_auto_sh_evt = param_buf->fixed_param;
3351 
3352 	if (wmi_auto_sh_evt->shutdown_reason
3353 	    != WMI_HOST_AUTO_SHUTDOWN_REASON_TIMER_EXPIRY) {
3354 		wma_err("Invalid Auto shutdown timer evt");
3355 		return -EINVAL;
3356 	}
3357 
3358 	wma_debug("Auto Shutdown Evt: %d", wmi_auto_sh_evt->shutdown_reason);
3359 	return wma_wake_reason_auto_shutdown();
3360 }
3361 
3362 QDF_STATUS
3363 wma_set_auto_shutdown_timer_req(tp_wma_handle wma_handle,
3364 				struct auto_shutdown_cmd *auto_sh_cmd)
3365 {
3366 	if (!auto_sh_cmd) {
3367 		wma_err("Invalid Autoshutdown cfg cmd");
3368 		return QDF_STATUS_E_FAILURE;
3369 	}
3370 
3371 	return wmi_unified_set_auto_shutdown_timer_cmd(wma_handle->wmi_handle,
3372 						       auto_sh_cmd->timer_val);
3373 }
3374 #endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
3375 
3376 #ifdef DHCP_SERVER_OFFLOAD
3377 QDF_STATUS
3378 wma_process_dhcpserver_offload(tp_wma_handle wma_handle,
3379 			       struct dhcp_offload_info_params *params)
3380 {
3381 	QDF_STATUS status;
3382 	wmi_unified_t wmi_handle;
3383 
3384 	if (!wma_handle) {
3385 		wma_err("wma handle is NULL");
3386 		return QDF_STATUS_E_FAILURE;
3387 	}
3388 
3389 	wmi_handle = wma_handle->wmi_handle;
3390 	status = wmi_unified_process_dhcpserver_offload_cmd(wmi_handle,
3391 							    params);
3392 	wma_debug("Set dhcp server offload to vdev %d status %d",
3393 		 params->vdev_id, status);
3394 
3395 	return status;
3396 }
3397 #endif /* DHCP_SERVER_OFFLOAD */
3398 
3399 #ifdef WLAN_FEATURE_GPIO_LED_FLASHING
3400 /**
3401  * wma_set_led_flashing() - set led flashing in fw
3402  * @wma_handle: wma handle
3403  * @flashing: flashing request
3404  *
3405  * Return: QDF status
3406  */
3407 QDF_STATUS wma_set_led_flashing(tp_wma_handle wma_handle,
3408 				struct flashing_req_params *flashing)
3409 {
3410 	QDF_STATUS status;
3411 	struct wmi_unified *wmi_handle;
3412 
3413 	if (wma_validate_handle(wma_handle))
3414 		return QDF_STATUS_E_INVAL;
3415 
3416 	wmi_handle = wma_handle->wmi_handle;
3417 	if (wmi_validate_handle(wmi_handle))
3418 		return QDF_STATUS_E_INVAL;
3419 
3420 	if (!flashing) {
3421 		wma_err("invalid parameter: flashing");
3422 		return QDF_STATUS_E_INVAL;
3423 	}
3424 	status = wmi_unified_set_led_flashing_cmd(wmi_handle, flashing);
3425 	return status;
3426 }
3427 #endif /* WLAN_FEATURE_GPIO_LED_FLASHING */
3428 
3429 int wma_sar_rsp_evt_handler(ol_scn_t handle, uint8_t *event, uint32_t len)
3430 {
3431 	tp_wma_handle wma_handle;
3432 	wmi_unified_t wmi_handle;
3433 	QDF_STATUS status;
3434 
3435 	wma_debug("handle:%pK event:%pK len:%u", handle, event, len);
3436 
3437 	wma_handle = handle;
3438 	if (wma_validate_handle(wma_handle))
3439 		return QDF_STATUS_E_INVAL;
3440 
3441 	wmi_handle = wma_handle->wmi_handle;
3442 	if (wmi_validate_handle(wmi_handle))
3443 		return QDF_STATUS_E_INVAL;
3444 
3445 	status = wmi_unified_extract_sar2_result_event(wmi_handle,
3446 						       event, len);
3447 	if (QDF_IS_STATUS_ERROR(status)) {
3448 		wma_err("Event extract failure: %d", status);
3449 		return -EINVAL;
3450 	}
3451 
3452 	return 0;
3453 }
3454 
3455 #ifdef FEATURE_WLAN_CH_AVOID
3456 /**
3457  * wma_process_ch_avoid_update_req() - handles channel avoid update request
3458  * @wma_handle: wma handle
3459  * @ch_avoid_update_req: channel avoid update params
3460  *
3461  * Return: QDF status
3462  */
3463 QDF_STATUS wma_process_ch_avoid_update_req(tp_wma_handle wma_handle,
3464 					   tSirChAvoidUpdateReq *
3465 					   ch_avoid_update_req)
3466 {
3467 	QDF_STATUS status;
3468 	struct wmi_unified *wmi_handle;
3469 
3470 	if (wma_validate_handle(wma_handle))
3471 		return QDF_STATUS_E_FAILURE;
3472 
3473 	wmi_handle = wma_handle->wmi_handle;
3474 	if (wmi_validate_handle(wmi_handle))
3475 		return QDF_STATUS_E_FAILURE;
3476 
3477 	if (!ch_avoid_update_req) {
3478 		wma_err("ch_avoid_update_req is NULL");
3479 		return QDF_STATUS_E_FAILURE;
3480 	}
3481 
3482 	wma_debug("WMA --> WMI_CHAN_AVOID_UPDATE");
3483 
3484 	status = wmi_unified_process_ch_avoid_update_cmd(wmi_handle);
3485 	if (QDF_IS_STATUS_ERROR(status))
3486 		return status;
3487 
3488 	wma_debug("WMA --> WMI_CHAN_AVOID_UPDATE sent through WMI");
3489 	return status;
3490 }
3491 #endif
3492 
3493 void wma_send_regdomain_info_to_fw(uint32_t reg_dmn, uint16_t regdmn2G,
3494 				   uint16_t regdmn5G, uint8_t ctl2G,
3495 				   uint8_t ctl5G)
3496 {
3497 	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
3498 	int32_t cck_mask_val = 0;
3499 	struct pdev_params pdev_param = {0};
3500 	QDF_STATUS ret = QDF_STATUS_SUCCESS;
3501 	QDF_STATUS status = QDF_STATUS_SUCCESS;
3502 
3503 	wma_debug("reg_dmn: %d regdmn2g: %d regdmn5g :%d ctl2g: %d ctl5g: %d",
3504 		 reg_dmn, regdmn2G, regdmn5G, ctl2G, ctl5G);
3505 
3506 	if (!wma)
3507 		return;
3508 
3509 	status = wmi_unified_send_regdomain_info_to_fw_cmd(wma->wmi_handle,
3510 			reg_dmn, regdmn2G, regdmn5G, ctl2G, ctl5G);
3511 	if (status == QDF_STATUS_E_NOMEM)
3512 		return;
3513 
3514 	if ((((reg_dmn & ~CTRY_FLAG) == CTRY_JAPAN15) ||
3515 	     ((reg_dmn & ~CTRY_FLAG) == CTRY_KOREA_ROC)) &&
3516 	    (true == wma->tx_chain_mask_cck))
3517 		cck_mask_val = 1;
3518 
3519 	cck_mask_val |= (wma->self_gen_frm_pwr << 16);
3520 	pdev_param.param_id = WMI_PDEV_PARAM_TX_CHAIN_MASK_CCK;
3521 	pdev_param.param_value = cck_mask_val;
3522 	ret = wmi_unified_pdev_param_send(wma->wmi_handle,
3523 					 &pdev_param,
3524 					 WMA_WILDCARD_PDEV_ID);
3525 
3526 	if (QDF_IS_STATUS_ERROR(ret))
3527 		wma_err("failed to set PDEV tx_chain_mask_cck %d", ret);
3528 }
3529 
3530 #ifdef FEATURE_WLAN_TDLS
3531 /**
3532  * wma_tdls_event_handler() - handle TDLS event
3533  * @handle: wma handle
3534  * @event: event buffer
3535  * @len: buffer length
3536  *
3537  * Return: 0 for success or error code
3538  */
3539 int wma_tdls_event_handler(void *handle, uint8_t *event, uint32_t len)
3540 {
3541 	/* TODO update with target rx ops */
3542 	return 0;
3543 }
3544 
3545 /**
3546  * wma_update_tdls_peer_state() - update TDLS peer state
3547  * @handle: wma handle
3548  * @peer_state: TDLS peer state params
3549  *
3550  * Return: 0 for success or error code
3551  */
3552 int wma_update_tdls_peer_state(WMA_HANDLE handle,
3553 			       struct tdls_peer_update_state *peer_state)
3554 {
3555 	tp_wma_handle wma_handle = (tp_wma_handle) handle;
3556 	uint32_t i;
3557 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3558 	struct tdls_peer_params *peer_cap;
3559 	int ret = 0;
3560 	uint32_t *ch_mhz = NULL;
3561 	size_t ch_mhz_len;
3562 	uint8_t chan_id;
3563 	bool restore_last_peer = false;
3564 	QDF_STATUS qdf_status;
3565 	struct wmi_unified *wmi_handle;
3566 
3567 	if (wma_validate_handle(wma_handle)) {
3568 		ret = -EINVAL;
3569 		goto end_tdls_peer_state;
3570 	}
3571 
3572 	wmi_handle = wma_handle->wmi_handle;
3573 	if (wmi_validate_handle(wmi_handle)) {
3574 		ret = -EINVAL;
3575 		goto end_tdls_peer_state;
3576 	}
3577 
3578 	if (!soc) {
3579 		ret = -EINVAL;
3580 		goto end_tdls_peer_state;
3581 	}
3582 
3583 	if (MLME_IS_ROAM_SYNCH_IN_PROGRESS(wma_handle->psoc,
3584 					   peer_state->vdev_id)) {
3585 		wma_err("roaming in progress, reject peer update cmd!");
3586 		ret = -EPERM;
3587 		goto end_tdls_peer_state;
3588 	}
3589 
3590 
3591 	if (!wma_objmgr_peer_exist(wma_handle,
3592 				   peer_state->peer_macaddr, NULL)) {
3593 		wma_err("peer:" QDF_MAC_ADDR_FMT "doesn't exist",
3594 			QDF_MAC_ADDR_REF(peer_state->peer_macaddr));
3595 		ret = -EINVAL;
3596 		goto end_tdls_peer_state;
3597 	}
3598 
3599 	peer_cap = &peer_state->peer_cap;
3600 
3601 	/* peer capability info is valid only when peer state is connected */
3602 	if (TDLS_PEER_STATE_CONNECTED != peer_state->peer_state)
3603 		qdf_mem_zero(peer_cap, sizeof(*peer_cap));
3604 
3605 	if (peer_cap->peer_chanlen) {
3606 		ch_mhz_len = sizeof(*ch_mhz) * peer_cap->peer_chanlen;
3607 		ch_mhz = qdf_mem_malloc(ch_mhz_len);
3608 		if (!ch_mhz) {
3609 			ret = -ENOMEM;
3610 			goto end_tdls_peer_state;
3611 		}
3612 
3613 		for (i = 0; i < peer_cap->peer_chanlen; ++i) {
3614 			chan_id = peer_cap->peer_chan[i].chan_id;
3615 			ch_mhz[i] = cds_chan_to_freq(chan_id);
3616 		}
3617 	}
3618 
3619 	cdp_peer_set_tdls_offchan_enabled(soc, peer_state->vdev_id,
3620 					  peer_state->peer_macaddr,
3621 					  !!peer_cap->peer_off_chan_support);
3622 
3623 	if (wmi_unified_update_tdls_peer_state_cmd(wma_handle->wmi_handle,
3624 						   peer_state,
3625 						   ch_mhz)) {
3626 		wma_err("failed to send tdls peer update state command");
3627 		ret = -EIO;
3628 		/* Fall through to delete TDLS peer for teardown */
3629 	}
3630 
3631 	/* in case of teardown, remove peer from fw */
3632 	if (TDLS_PEER_STATE_TEARDOWN == peer_state->peer_state) {
3633 		restore_last_peer = cdp_peer_is_vdev_restore_last_peer(
3634 						soc,
3635 						peer_state->vdev_id,
3636 						peer_state->peer_macaddr);
3637 
3638 		wma_debug("calling wma_remove_peer for peer " QDF_MAC_ADDR_FMT
3639 			 " vdevId: %d",
3640 			 QDF_MAC_ADDR_REF(peer_state->peer_macaddr),
3641 			 peer_state->vdev_id);
3642 		qdf_status = wma_remove_peer(wma_handle,
3643 					     peer_state->peer_macaddr,
3644 					     peer_state->vdev_id, false);
3645 		if (QDF_IS_STATUS_ERROR(qdf_status)) {
3646 			wma_err("wma_remove_peer failed");
3647 			ret = -EINVAL;
3648 		}
3649 		cdp_peer_update_last_real_peer(soc, WMI_PDEV_ID_SOC,
3650 					       peer_state->vdev_id,
3651 					       restore_last_peer);
3652 	}
3653 
3654 	if (TDLS_PEER_STATE_CONNECTED == peer_state->peer_state) {
3655 		cdp_peer_state_update(soc, peer_state->peer_macaddr,
3656 				      OL_TXRX_PEER_STATE_AUTH);
3657 	}
3658 
3659 end_tdls_peer_state:
3660 	if (ch_mhz)
3661 		qdf_mem_free(ch_mhz);
3662 	if (peer_state)
3663 		qdf_mem_free(peer_state);
3664 	return ret;
3665 }
3666 #endif /* FEATURE_WLAN_TDLS */
3667 
3668 /*
3669  * wma_process_cfg_action_frm_tb_ppdu() - action frame TB PPDU cfg to firmware
3670  * @wma:                Pointer to WMA handle
3671  * @cfg_info:       Pointer for cfg info
3672  *
3673  * Return: QDF_STATUS_SUCCESS for success otherwise failure
3674  *
3675  */
3676 QDF_STATUS wma_process_cfg_action_frm_tb_ppdu(tp_wma_handle wma,
3677 				   struct cfg_action_frm_tb_ppdu *cfg_info)
3678 {
3679 	struct cfg_action_frm_tb_ppdu_param cmd = {0};
3680 
3681 	if (wma_validate_handle(wma))
3682 		return QDF_STATUS_E_FAILURE;
3683 
3684 	cmd.frm_len = cfg_info->frm_len;
3685 	cmd.cfg = cfg_info->cfg;
3686 	cmd.data = cfg_info->data;
3687 
3688 	wma_debug("cfg: %d, frm_len: %d", cfg_info->cfg, cfg_info->frm_len);
3689 
3690 	return wmi_unified_cfg_action_frm_tb_ppdu_cmd(wma->wmi_handle, &cmd);
3691 }
3692 
3693 
3694 /*
3695  * wma_process_set_ie_info() - Function to send IE info to firmware
3696  * @wma:                Pointer to WMA handle
3697  * @ie_data:       Pointer for ie data
3698  *
3699  * This function sends IE information to firmware
3700  *
3701  * Return: QDF_STATUS_SUCCESS for success otherwise failure
3702  *
3703  */
3704 QDF_STATUS wma_process_set_ie_info(tp_wma_handle wma,
3705 				   struct vdev_ie_info *ie_info)
3706 {
3707 	struct wma_txrx_node *interface;
3708 	struct vdev_ie_info_param cmd = {0};
3709 
3710 	if (!ie_info || !wma) {
3711 		wma_err("input pointer is NULL");
3712 		return QDF_STATUS_E_FAILURE;
3713 	}
3714 
3715 	/* Validate the input */
3716 	if (ie_info->length  <= 0) {
3717 		wma_err("Invalid IE length");
3718 		return QDF_STATUS_E_INVAL;
3719 	}
3720 
3721 	if (!wma_is_vdev_valid(ie_info->vdev_id)) {
3722 		wma_err("vdev_id: %d is not active", ie_info->vdev_id);
3723 		return QDF_STATUS_E_INVAL;
3724 	}
3725 
3726 	interface = &wma->interfaces[ie_info->vdev_id];
3727 	cmd.vdev_id = ie_info->vdev_id;
3728 	cmd.ie_id = ie_info->ie_id;
3729 	cmd.length = ie_info->length;
3730 	cmd.band = ie_info->band;
3731 	cmd.data = ie_info->data;
3732 	cmd.ie_source = WMA_SET_VDEV_IE_SOURCE_HOST;
3733 
3734 	wma_debug("vdev id: %d, ie_id: %d, band: %d, len: %d",
3735 		 ie_info->vdev_id, ie_info->ie_id, ie_info->band,
3736 		 ie_info->length);
3737 
3738 	QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_DEBUG,
3739 		ie_info->data, ie_info->length);
3740 
3741 	return wmi_unified_process_set_ie_info_cmd(wma->wmi_handle, &cmd);
3742 }
3743 
3744 #ifdef FEATURE_WLAN_APF
3745 /**
3746  *  wma_get_apf_caps_event_handler() - Event handler for get apf capability
3747  *  @handle: WMA global handle
3748  *  @cmd_param_info: command event data
3749  *  @len: Length of @cmd_param_info
3750  *
3751  *  Return: 0 on Success or Errno on failure
3752  */
3753 int wma_get_apf_caps_event_handler(void *handle, u_int8_t *cmd_param_info,
3754 				   u_int32_t len)
3755 {
3756 	WMI_BPF_CAPABILIY_INFO_EVENTID_param_tlvs  *param_buf;
3757 	wmi_bpf_capability_info_evt_fixed_param *event;
3758 	struct sir_apf_get_offload *apf_get_offload;
3759 	struct mac_context *pmac = (struct mac_context *)cds_get_context(
3760 				QDF_MODULE_ID_PE);
3761 
3762 	if (!pmac)
3763 		return -EINVAL;
3764 
3765 	if (!pmac->sme.apf_get_offload_cb) {
3766 		wma_err("Callback not registered");
3767 		return -EINVAL;
3768 	}
3769 
3770 	param_buf = (WMI_BPF_CAPABILIY_INFO_EVENTID_param_tlvs *)cmd_param_info;
3771 	event = param_buf->fixed_param;
3772 	apf_get_offload = qdf_mem_malloc(sizeof(*apf_get_offload));
3773 	if (!apf_get_offload)
3774 		return -ENOMEM;
3775 
3776 	apf_get_offload->apf_version = event->bpf_version;
3777 	apf_get_offload->max_apf_filters = event->max_bpf_filters;
3778 	apf_get_offload->max_bytes_for_apf_inst =
3779 			event->max_bytes_for_bpf_inst;
3780 	wma_debug("APF capabilities version: %d max apf filter size: %d",
3781 		 apf_get_offload->apf_version,
3782 		 apf_get_offload->max_bytes_for_apf_inst);
3783 
3784 	wma_debug("sending apf capabilities event to hdd");
3785 	pmac->sme.apf_get_offload_cb(pmac->sme.apf_get_offload_context,
3786 				     apf_get_offload);
3787 	qdf_mem_free(apf_get_offload);
3788 	return 0;
3789 }
3790 
3791 QDF_STATUS wma_get_apf_capabilities(tp_wma_handle wma)
3792 {
3793 	QDF_STATUS status = QDF_STATUS_SUCCESS;
3794 	wmi_bpf_get_capability_cmd_fixed_param *cmd;
3795 	wmi_buf_t wmi_buf;
3796 	uint32_t   len;
3797 	u_int8_t *buf_ptr;
3798 	struct wmi_unified *wmi_handle;
3799 
3800 	if (wma_validate_handle(wma))
3801 		return QDF_STATUS_E_INVAL;
3802 
3803 	wmi_handle = wma->wmi_handle;
3804 	if (wmi_validate_handle(wmi_handle))
3805 		return QDF_STATUS_E_INVAL;
3806 
3807 	if (!wmi_service_enabled(wmi_handle, wmi_service_apf_offload)) {
3808 		wma_err("APF cababilities feature bit not enabled");
3809 		return QDF_STATUS_E_FAILURE;
3810 	}
3811 
3812 	len = sizeof(*cmd);
3813 	wmi_buf = wmi_buf_alloc(wmi_handle, len);
3814 	if (!wmi_buf)
3815 		return QDF_STATUS_E_NOMEM;
3816 
3817 	buf_ptr = (u_int8_t *) wmi_buf_data(wmi_buf);
3818 	cmd = (wmi_bpf_get_capability_cmd_fixed_param *) buf_ptr;
3819 	WMITLV_SET_HDR(&cmd->tlv_header,
3820 	WMITLV_TAG_STRUC_wmi_bpf_get_capability_cmd_fixed_param,
3821 		WMITLV_GET_STRUCT_TLVLEN(
3822 		wmi_bpf_get_capability_cmd_fixed_param));
3823 
3824 	if (wmi_unified_cmd_send(wmi_handle, wmi_buf, len,
3825 				 WMI_BPF_GET_CAPABILITY_CMDID)) {
3826 		wmi_buf_free(wmi_buf);
3827 		return QDF_STATUS_E_FAILURE;
3828 	}
3829 	return status;
3830 }
3831 
3832 QDF_STATUS wma_set_apf_instructions(tp_wma_handle wma,
3833 				    struct sir_apf_set_offload *apf_set_offload)
3834 {
3835 	wmi_bpf_set_vdev_instructions_cmd_fixed_param *cmd;
3836 	wmi_buf_t wmi_buf;
3837 	uint32_t   len = 0, len_aligned = 0;
3838 	u_int8_t *buf_ptr;
3839 	struct wmi_unified *wmi_handle;
3840 
3841 	if (wma_validate_handle(wma))
3842 		return QDF_STATUS_E_INVAL;
3843 
3844 	wmi_handle = wma->wmi_handle;
3845 	if (wmi_validate_handle(wmi_handle))
3846 		return QDF_STATUS_E_INVAL;
3847 
3848 	if (!wmi_service_enabled(wmi_handle,
3849 		wmi_service_apf_offload)) {
3850 		wma_err("APF offload feature Disabled");
3851 		return QDF_STATUS_E_NOSUPPORT;
3852 	}
3853 
3854 	if (!apf_set_offload) {
3855 		wma_err("Invalid APF instruction request");
3856 		return QDF_STATUS_E_INVAL;
3857 	}
3858 
3859 	if (apf_set_offload->session_id >= wma->max_bssid) {
3860 		wma_err("Invalid vdev_id: %d", apf_set_offload->session_id);
3861 		return QDF_STATUS_E_INVAL;
3862 	}
3863 
3864 	if (!wma_is_vdev_up(apf_set_offload->session_id)) {
3865 		wma_err("vdev %d is not up skipping APF offload",
3866 			 apf_set_offload->session_id);
3867 		return QDF_STATUS_E_INVAL;
3868 	}
3869 
3870 	if (apf_set_offload->total_length) {
3871 		len_aligned = roundup(apf_set_offload->current_length,
3872 					sizeof(A_UINT32));
3873 		len = len_aligned + WMI_TLV_HDR_SIZE;
3874 	}
3875 
3876 	len += sizeof(*cmd);
3877 	wmi_buf = wmi_buf_alloc(wmi_handle, len);
3878 	if (!wmi_buf)
3879 		return QDF_STATUS_E_NOMEM;
3880 
3881 	buf_ptr = (u_int8_t *) wmi_buf_data(wmi_buf);
3882 	cmd = (wmi_bpf_set_vdev_instructions_cmd_fixed_param *) buf_ptr;
3883 
3884 	WMITLV_SET_HDR(&cmd->tlv_header,
3885 		WMITLV_TAG_STRUC_wmi_bpf_set_vdev_instructions_cmd_fixed_param,
3886 		WMITLV_GET_STRUCT_TLVLEN(
3887 			wmi_bpf_set_vdev_instructions_cmd_fixed_param));
3888 	cmd->vdev_id = apf_set_offload->session_id;
3889 	cmd->filter_id = apf_set_offload->filter_id;
3890 	cmd->total_length = apf_set_offload->total_length;
3891 	cmd->current_offset = apf_set_offload->current_offset;
3892 	cmd->current_length = apf_set_offload->current_length;
3893 
3894 	if (apf_set_offload->total_length) {
3895 		buf_ptr +=
3896 			sizeof(wmi_bpf_set_vdev_instructions_cmd_fixed_param);
3897 		WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, len_aligned);
3898 		buf_ptr += WMI_TLV_HDR_SIZE;
3899 		qdf_mem_copy(buf_ptr, apf_set_offload->program,
3900 			     apf_set_offload->current_length);
3901 	}
3902 
3903 	if (wmi_unified_cmd_send(wmi_handle, wmi_buf, len,
3904 				 WMI_BPF_SET_VDEV_INSTRUCTIONS_CMDID)) {
3905 		wmi_buf_free(wmi_buf);
3906 		return QDF_STATUS_E_FAILURE;
3907 	}
3908 	wma_debug("APF offload enabled in fw");
3909 
3910 	return QDF_STATUS_SUCCESS;
3911 }
3912 
3913 QDF_STATUS wma_send_apf_enable_cmd(WMA_HANDLE handle, uint8_t vdev_id,
3914 				   bool apf_enable)
3915 {
3916 	QDF_STATUS status = QDF_STATUS_SUCCESS;
3917 	tp_wma_handle wma = (tp_wma_handle) handle;
3918 	struct wmi_unified *wmi_handle;
3919 
3920 	if (wma_validate_handle(wma))
3921 		return QDF_STATUS_E_INVAL;
3922 
3923 	wmi_handle = wma->wmi_handle;
3924 	if (wmi_validate_handle(wmi_handle))
3925 		return QDF_STATUS_E_INVAL;
3926 
3927 	if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
3928 		WMI_SERVICE_BPF_OFFLOAD)) {
3929 		wma_err("APF cababilities feature bit not enabled");
3930 		return QDF_STATUS_E_FAILURE;
3931 	}
3932 
3933 	status = wmi_unified_send_apf_enable_cmd(wmi_handle, vdev_id,
3934 						 apf_enable);
3935 	if (QDF_IS_STATUS_ERROR(status)) {
3936 		wma_err("Failed to send apf enable/disable cmd");
3937 		return QDF_STATUS_E_FAILURE;
3938 	}
3939 
3940 	if (apf_enable)
3941 		wma_debug("Sent APF Enable on vdevid: %d", vdev_id);
3942 	else
3943 		wma_debug("Sent APF Disable on vdevid: %d", vdev_id);
3944 
3945 	return status;
3946 }
3947 
3948 QDF_STATUS
3949 wma_send_apf_write_work_memory_cmd(WMA_HANDLE handle,
3950 				   struct wmi_apf_write_memory_params
3951 								*write_params)
3952 {
3953 	QDF_STATUS status = QDF_STATUS_SUCCESS;
3954 	tp_wma_handle wma = (tp_wma_handle) handle;
3955 	struct wmi_unified *wmi_handle;
3956 
3957 	if (wma_validate_handle(wma))
3958 		return QDF_STATUS_E_INVAL;
3959 
3960 	wmi_handle = wma->wmi_handle;
3961 	if (wmi_validate_handle(wmi_handle))
3962 		return QDF_STATUS_E_INVAL;
3963 
3964 	if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
3965 		WMI_SERVICE_BPF_OFFLOAD)) {
3966 		wma_err("APF cababilities feature bit not enabled");
3967 		return QDF_STATUS_E_FAILURE;
3968 	}
3969 
3970 	if (wmi_unified_send_apf_write_work_memory_cmd(wmi_handle,
3971 						       write_params)) {
3972 		wma_err("Failed to send APF write mem command");
3973 		return QDF_STATUS_E_FAILURE;
3974 	}
3975 
3976 	wma_debug("Sent APF wite mem on vdevid: %d", write_params->vdev_id);
3977 	return status;
3978 }
3979 
3980 int wma_apf_read_work_memory_event_handler(void *handle, uint8_t *evt_buf,
3981 					   uint32_t len)
3982 {
3983 	tp_wma_handle wma_handle;
3984 	wmi_unified_t wmi_handle;
3985 	struct wmi_apf_read_memory_resp_event_params evt_params = {0};
3986 	QDF_STATUS status;
3987 	struct mac_context *pmac = cds_get_context(QDF_MODULE_ID_PE);
3988 
3989 	wma_debug("handle:%pK event:%pK len:%u", handle, evt_buf, len);
3990 
3991 	wma_handle = handle;
3992 	if (wma_validate_handle(wma_handle))
3993 		return -EINVAL;
3994 
3995 	wmi_handle = wma_handle->wmi_handle;
3996 	if (wmi_validate_handle(wmi_handle))
3997 		return -EINVAL;
3998 
3999 	if (!pmac)
4000 		return -EINVAL;
4001 
4002 	if (!pmac->sme.apf_read_mem_cb) {
4003 		wma_err("Callback not registered");
4004 		return -EINVAL;
4005 	}
4006 
4007 	status = wmi_extract_apf_read_memory_resp_event(wmi_handle,
4008 						evt_buf, &evt_params);
4009 	if (QDF_IS_STATUS_ERROR(status)) {
4010 		wma_err("Event extract failure: %d", status);
4011 		return -EINVAL;
4012 	}
4013 
4014 	pmac->sme.apf_read_mem_cb(pmac->hdd_handle, &evt_params);
4015 
4016 	return 0;
4017 }
4018 
4019 QDF_STATUS wma_send_apf_read_work_memory_cmd(WMA_HANDLE handle,
4020 					     struct wmi_apf_read_memory_params
4021 								  *read_params)
4022 {
4023 	QDF_STATUS status = QDF_STATUS_SUCCESS;
4024 	tp_wma_handle wma = (tp_wma_handle) handle;
4025 	struct wmi_unified *wmi_handle;
4026 
4027 	if (wma_validate_handle(wma))
4028 		return QDF_STATUS_E_INVAL;
4029 
4030 	wmi_handle = wma->wmi_handle;
4031 	if (wmi_validate_handle(wmi_handle))
4032 		return QDF_STATUS_E_INVAL;
4033 
4034 	if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
4035 		WMI_SERVICE_BPF_OFFLOAD)) {
4036 		wma_err("APF cababilities feature bit not enabled");
4037 		return QDF_STATUS_E_FAILURE;
4038 	}
4039 
4040 	if (wmi_unified_send_apf_read_work_memory_cmd(wmi_handle,
4041 						      read_params)) {
4042 		wma_err("Failed to send APF read memory command");
4043 		return QDF_STATUS_E_FAILURE;
4044 	}
4045 
4046 	wma_debug("Sent APF read memory on vdevid: %d", read_params->vdev_id);
4047 	return status;
4048 }
4049 #endif /* FEATURE_WLAN_APF */
4050 
4051 QDF_STATUS wma_set_tx_rx_aggr_size(uint8_t vdev_id,
4052 				   uint32_t tx_size,
4053 				   uint32_t rx_size,
4054 				   wmi_vdev_custom_aggr_type_t aggr_type)
4055 {
4056 	tp_wma_handle wma_handle;
4057 	struct wma_txrx_node *intr;
4058 	wmi_vdev_set_custom_aggr_size_cmd_fixed_param *cmd;
4059 	int32_t len;
4060 	wmi_buf_t buf;
4061 	u_int8_t *buf_ptr;
4062 	int ret;
4063 
4064 	wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
4065 
4066 	if (!wma_handle)
4067 		return QDF_STATUS_E_INVAL;
4068 
4069 	intr = wma_handle->interfaces;
4070 	if (!intr) {
4071 		wma_err("WMA interface is invalid!");
4072 		return QDF_STATUS_E_INVAL;
4073 	}
4074 
4075 	if (aggr_type == WMI_VDEV_CUSTOM_AGGR_TYPE_AMPDU) {
4076 		intr[vdev_id].config.tx_ampdu = tx_size;
4077 		intr[vdev_id].config.rx_ampdu = rx_size;
4078 	} else {
4079 		intr[vdev_id].config.tx_amsdu = tx_size;
4080 		intr[vdev_id].config.rx_amsdu = rx_size;
4081 	}
4082 
4083 	len = sizeof(*cmd);
4084 	buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
4085 	if (!buf)
4086 		return QDF_STATUS_E_NOMEM;
4087 
4088 	buf_ptr = (u_int8_t *) wmi_buf_data(buf);
4089 	cmd = (wmi_vdev_set_custom_aggr_size_cmd_fixed_param *) buf_ptr;
4090 	qdf_mem_zero(cmd, sizeof(*cmd));
4091 
4092 	WMITLV_SET_HDR(&cmd->tlv_header,
4093 		WMITLV_TAG_STRUC_wmi_vdev_set_custom_aggr_size_cmd_fixed_param,
4094 		WMITLV_GET_STRUCT_TLVLEN(
4095 			wmi_vdev_set_custom_aggr_size_cmd_fixed_param));
4096 
4097 	cmd->vdev_id = vdev_id;
4098 	cmd->tx_aggr_size = tx_size;
4099 	cmd->rx_aggr_size = rx_size;
4100 	/* bit 2 (aggr_type): TX Aggregation Type (0=A-MPDU, 1=A-MSDU) */
4101 	if (aggr_type == WMI_VDEV_CUSTOM_AGGR_TYPE_AMSDU)
4102 		cmd->enable_bitmap |= 0x04;
4103 	/* Set bit3(tx_aggr_size_disable) if tx_aggr_size is invalid */
4104 	if (tx_size == 0)
4105 		cmd->enable_bitmap |= (0x1 << 3);
4106 	/* Set bit4(rx_aggr_size_disable) if rx_aggr_size is invalid */
4107 	if (rx_size == 0)
4108 		cmd->enable_bitmap |= (0x1 << 4);
4109 
4110 	cmd->enable_bitmap |= (0x1 << 6);
4111 
4112 	wma_debug("tx aggr: %d rx aggr: %d vdev: %d enable_bitmap %d",
4113 		 cmd->tx_aggr_size, cmd->rx_aggr_size, cmd->vdev_id,
4114 		 cmd->enable_bitmap);
4115 
4116 	ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
4117 				WMI_VDEV_SET_CUSTOM_AGGR_SIZE_CMDID);
4118 	if (ret) {
4119 		wmi_buf_free(buf);
4120 		return QDF_STATUS_E_FAILURE;
4121 	}
4122 
4123 	return QDF_STATUS_SUCCESS;
4124 }
4125 
4126 QDF_STATUS wma_set_tx_rx_aggr_size_per_ac(WMA_HANDLE handle,
4127 					  uint8_t vdev_id,
4128 					  struct wlan_mlme_qos *qos_aggr,
4129 					  wmi_vdev_custom_aggr_type_t aggr_type)
4130 {
4131 	wmi_vdev_set_custom_aggr_size_cmd_fixed_param *cmd;
4132 	int32_t len;
4133 	wmi_buf_t buf;
4134 	u_int8_t *buf_ptr;
4135 	int ret;
4136 	int queue_num;
4137 	uint32_t tx_aggr_size[4];
4138 	tp_wma_handle wma_handle = (tp_wma_handle)handle;
4139 
4140 	if (wma_validate_handle(wma_handle))
4141 		return QDF_STATUS_E_INVAL;
4142 
4143 	tx_aggr_size[0] = qos_aggr->tx_aggregation_size_be;
4144 	tx_aggr_size[1] = qos_aggr->tx_aggregation_size_bk;
4145 	tx_aggr_size[2] = qos_aggr->tx_aggregation_size_vi;
4146 	tx_aggr_size[3] = qos_aggr->tx_aggregation_size_vo;
4147 
4148 	for (queue_num = 0; queue_num < 4; queue_num++) {
4149 		if (tx_aggr_size[queue_num] == 0)
4150 			continue;
4151 
4152 		len = sizeof(*cmd);
4153 		buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
4154 		if (!buf)
4155 			return QDF_STATUS_E_NOMEM;
4156 
4157 		buf_ptr = (u_int8_t *)wmi_buf_data(buf);
4158 		cmd = (wmi_vdev_set_custom_aggr_size_cmd_fixed_param *)buf_ptr;
4159 		qdf_mem_zero(cmd, sizeof(*cmd));
4160 
4161 		WMITLV_SET_HDR(&cmd->tlv_header,
4162 			       WMITLV_TAG_STRUC_wmi_vdev_set_custom_aggr_size_cmd_fixed_param,
4163 			       WMITLV_GET_STRUCT_TLVLEN(
4164 					wmi_vdev_set_custom_aggr_size_cmd_fixed_param));
4165 
4166 		cmd->vdev_id = vdev_id;
4167 		cmd->rx_aggr_size = qos_aggr->rx_aggregation_size;
4168 		cmd->tx_aggr_size = tx_aggr_size[queue_num];
4169 		/* bit 5: tx_ac_enable, if set, ac bitmap is valid. */
4170 		cmd->enable_bitmap = 0x20 | queue_num;
4171 		/* bit 2 (aggr_type): TX Aggregation Type (0=A-MPDU, 1=A-MSDU) */
4172 		if (aggr_type == WMI_VDEV_CUSTOM_AGGR_TYPE_AMSDU)
4173 			cmd->enable_bitmap |= 0x04;
4174 
4175 		cmd->enable_bitmap |= (0x1 << 6);
4176 
4177 		wma_debug("queue_num: %d, tx aggr: %d rx aggr: %d vdev: %d, bitmap: %d",
4178 			 queue_num, cmd->tx_aggr_size,
4179 			 cmd->rx_aggr_size, cmd->vdev_id,
4180 			 cmd->enable_bitmap);
4181 
4182 		ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
4183 					WMI_VDEV_SET_CUSTOM_AGGR_SIZE_CMDID);
4184 		if (ret) {
4185 			wmi_buf_free(buf);
4186 			return QDF_STATUS_E_FAILURE;
4187 		}
4188 	}
4189 
4190 	return QDF_STATUS_SUCCESS;
4191 }
4192 
4193 static QDF_STATUS wma_set_sw_retry_by_qos(
4194 	tp_wma_handle handle, uint8_t vdev_id,
4195 	wmi_vdev_custom_sw_retry_type_t retry_type,
4196 	wmi_traffic_ac ac_type,
4197 	uint32_t sw_retry)
4198 {
4199 	wmi_vdev_set_custom_sw_retry_th_cmd_fixed_param *cmd;
4200 	int32_t len;
4201 	wmi_buf_t buf;
4202 	u_int8_t *buf_ptr;
4203 	int ret;
4204 
4205 	len = sizeof(*cmd);
4206 	buf = wmi_buf_alloc(handle->wmi_handle, len);
4207 
4208 	if (!buf)
4209 		return QDF_STATUS_E_NOMEM;
4210 
4211 	buf_ptr = (u_int8_t *)wmi_buf_data(buf);
4212 	cmd = (wmi_vdev_set_custom_sw_retry_th_cmd_fixed_param *)buf_ptr;
4213 
4214 	WMITLV_SET_HDR(&cmd->tlv_header,
4215 		       WMITLV_TAG_STRUC_wmi_vdev_set_custom_sw_retry_th_cmd_fixed_param,
4216 		       WMITLV_GET_STRUCT_TLVLEN(
4217 		       wmi_vdev_set_custom_sw_retry_th_cmd_fixed_param));
4218 
4219 	cmd->vdev_id = vdev_id;
4220 	cmd->ac_type = ac_type;
4221 	cmd->sw_retry_type = retry_type;
4222 	cmd->sw_retry_th = sw_retry;
4223 
4224 	wma_debug("ac_type: %d re_type: %d threshold: %d vid: %d",
4225 		  cmd->ac_type, cmd->sw_retry_type,
4226 		  cmd->sw_retry_th, cmd->vdev_id);
4227 
4228 	ret = wmi_unified_cmd_send(handle->wmi_handle,
4229 				   buf, len,
4230 				   WMI_VDEV_SET_CUSTOM_SW_RETRY_TH_CMDID);
4231 
4232 	if (ret) {
4233 		wmi_buf_free(buf);
4234 		return QDF_STATUS_E_FAILURE;
4235 	}
4236 
4237 	return QDF_STATUS_SUCCESS;
4238 }
4239 
4240 QDF_STATUS wma_set_sw_retry_threshold_per_ac(WMA_HANDLE handle,
4241 					     uint8_t vdev_id,
4242 					     struct wlan_mlme_qos *qos_aggr)
4243 {
4244 	QDF_STATUS ret;
4245 	int retry_type, queue_num;
4246 	uint32_t tx_sw_retry[WMI_VDEV_CUSTOM_SW_RETRY_TYPE_MAX][WMI_AC_MAX];
4247 	uint32_t sw_retry;
4248 	tp_wma_handle wma_handle = (tp_wma_handle)handle;
4249 
4250 	if (wma_validate_handle(wma_handle))
4251 		return QDF_STATUS_E_INVAL;
4252 
4253 	tx_sw_retry[WMI_VDEV_CUSTOM_SW_RETRY_TYPE_AGGR][WMI_AC_BE] =
4254 		qos_aggr->tx_aggr_sw_retry_threshold_be;
4255 	tx_sw_retry[WMI_VDEV_CUSTOM_SW_RETRY_TYPE_AGGR][WMI_AC_BK] =
4256 		qos_aggr->tx_aggr_sw_retry_threshold_bk;
4257 	tx_sw_retry[WMI_VDEV_CUSTOM_SW_RETRY_TYPE_AGGR][WMI_AC_VI] =
4258 		qos_aggr->tx_aggr_sw_retry_threshold_vi;
4259 	tx_sw_retry[WMI_VDEV_CUSTOM_SW_RETRY_TYPE_AGGR][WMI_AC_VO] =
4260 		qos_aggr->tx_aggr_sw_retry_threshold_vo;
4261 
4262 	tx_sw_retry[WMI_VDEV_CUSTOM_SW_RETRY_TYPE_NONAGGR][WMI_AC_BE] =
4263 		qos_aggr->tx_non_aggr_sw_retry_threshold_be;
4264 	tx_sw_retry[WMI_VDEV_CUSTOM_SW_RETRY_TYPE_NONAGGR][WMI_AC_BK] =
4265 		qos_aggr->tx_non_aggr_sw_retry_threshold_bk;
4266 	tx_sw_retry[WMI_VDEV_CUSTOM_SW_RETRY_TYPE_NONAGGR][WMI_AC_VI] =
4267 		qos_aggr->tx_non_aggr_sw_retry_threshold_vi;
4268 	tx_sw_retry[WMI_VDEV_CUSTOM_SW_RETRY_TYPE_NONAGGR][WMI_AC_VO] =
4269 		qos_aggr->tx_non_aggr_sw_retry_threshold_vo;
4270 
4271 	retry_type = WMI_VDEV_CUSTOM_SW_RETRY_TYPE_NONAGGR;
4272 	while (retry_type < WMI_VDEV_CUSTOM_SW_RETRY_TYPE_MAX) {
4273 		for (queue_num = 0; queue_num < WMI_AC_MAX; queue_num++) {
4274 			if (tx_sw_retry[retry_type][queue_num] == 0)
4275 				continue;
4276 
4277 			sw_retry = tx_sw_retry[retry_type][queue_num];
4278 			ret = wma_set_sw_retry_by_qos(wma_handle,
4279 						      vdev_id,
4280 						      retry_type,
4281 						      queue_num,
4282 						      sw_retry);
4283 
4284 			if (QDF_IS_STATUS_ERROR(ret))
4285 				return ret;
4286 		}
4287 		retry_type++;
4288 	}
4289 
4290 	return QDF_STATUS_SUCCESS;
4291 }
4292 
4293 QDF_STATUS wma_set_sw_retry_threshold(uint8_t vdev_id, uint32_t retry,
4294 				      uint32_t param_id)
4295 {
4296 	uint32_t max, min;
4297 	uint32_t ret;
4298 
4299 	if (param_id == WMI_PDEV_PARAM_AGG_SW_RETRY_TH) {
4300 		max = cfg_max(CFG_TX_AGGR_SW_RETRY);
4301 		min = cfg_min(CFG_TX_AGGR_SW_RETRY);
4302 	} else {
4303 		max = cfg_max(CFG_TX_NON_AGGR_SW_RETRY);
4304 		min = cfg_min(CFG_TX_NON_AGGR_SW_RETRY);
4305 	}
4306 
4307 	retry = (retry > max) ? max : retry;
4308 	retry = (retry < min) ? min : retry;
4309 
4310 	ret = wma_cli_set_command(vdev_id, param_id, retry, PDEV_CMD);
4311 	if (ret)
4312 		return QDF_STATUS_E_IO;
4313 
4314 	return QDF_STATUS_SUCCESS;
4315 }
4316 
4317 /**
4318  * wma_process_fw_test_cmd() - send unit test command to fw.
4319  * @handle: wma handle
4320  * @wma_fwtest: fw test command
4321  *
4322  * This function send fw test command to fw.
4323  *
4324  * Return: none
4325  */
4326 QDF_STATUS wma_process_fw_test_cmd(WMA_HANDLE handle,
4327 				   struct set_fwtest_params *wma_fwtest)
4328 {
4329 	tp_wma_handle wma_handle = (tp_wma_handle) handle;
4330 	struct wmi_unified *wmi_handle;
4331 
4332 	if (wma_validate_handle(wma_handle))
4333 		return QDF_STATUS_E_INVAL;
4334 
4335 	wmi_handle = wma_handle->wmi_handle;
4336 	if (wmi_validate_handle(wmi_handle))
4337 		return QDF_STATUS_E_INVAL;
4338 
4339 	if (wmi_unified_fw_test_cmd(wmi_handle,
4340 				    (struct set_fwtest_params *)wma_fwtest)) {
4341 		wma_err("Failed to issue fw test cmd");
4342 		return QDF_STATUS_E_FAILURE;
4343 	}
4344 	return QDF_STATUS_SUCCESS;
4345 }
4346 
4347 /**
4348  * wma_enable_disable_caevent_ind() - Issue WMI command to enable or
4349  * disable ca event indication
4350  * @wma: wma handler
4351  * @val: boolean value true or false
4352  *
4353  * Return: QDF_STATUS
4354  */
4355 QDF_STATUS wma_enable_disable_caevent_ind(tp_wma_handle wma, uint8_t val)
4356 {
4357 	WMI_CHAN_AVOID_RPT_ALLOW_CMD_fixed_param *cmd;
4358 	wmi_buf_t wmi_buf;
4359 	uint8_t *buf_ptr;
4360 	uint32_t len;
4361 	struct wmi_unified *wmi_handle;
4362 
4363 	if (wma_validate_handle(wma))
4364 		return QDF_STATUS_E_INVAL;
4365 
4366 	wmi_handle = wma->wmi_handle;
4367 	if (wmi_validate_handle(wmi_handle))
4368 		return QDF_STATUS_E_INVAL;
4369 
4370 	len = sizeof(*cmd);
4371 	wmi_buf = wmi_buf_alloc(wmi_handle, len);
4372 	if (!wmi_buf)
4373 		return QDF_STATUS_E_NOMEM;
4374 
4375 	buf_ptr = (uint8_t *) wmi_buf_data(wmi_buf);
4376 	cmd = (WMI_CHAN_AVOID_RPT_ALLOW_CMD_fixed_param *) buf_ptr;
4377 	WMITLV_SET_HDR(&cmd->tlv_header,
4378 		WMITLV_TAG_STRUC_WMI_CHAN_AVOID_RPT_ALLOW_CMD_fixed_param,
4379 		WMITLV_GET_STRUCT_TLVLEN(
4380 				WMI_CHAN_AVOID_RPT_ALLOW_CMD_fixed_param));
4381 	cmd->rpt_allow = val;
4382 	if (wmi_unified_cmd_send(wmi_handle, wmi_buf, len,
4383 				WMI_CHAN_AVOID_RPT_ALLOW_CMDID)) {
4384 		wmi_buf_free(wmi_buf);
4385 		return QDF_STATUS_E_FAILURE;
4386 	}
4387 
4388 	return QDF_STATUS_SUCCESS;
4389 }
4390 
4391 static wma_sar_cb sar_callback;
4392 static void *sar_context;
4393 
4394 static int wma_sar_event_handler(void *handle, uint8_t *evt_buf, uint32_t len)
4395 {
4396 	tp_wma_handle wma_handle;
4397 	wmi_unified_t wmi_handle;
4398 	struct sar_limit_event *event;
4399 	wma_sar_cb callback;
4400 	QDF_STATUS status;
4401 
4402 	wma_info("handle:%pK event:%pK len:%u", handle, evt_buf, len);
4403 
4404 	wma_handle = handle;
4405 	if (wma_validate_handle(wma_handle))
4406 		return QDF_STATUS_E_INVAL;
4407 
4408 	wmi_handle = wma_handle->wmi_handle;
4409 	if (wmi_validate_handle(wmi_handle))
4410 		return QDF_STATUS_E_INVAL;
4411 
4412 	event = qdf_mem_malloc(sizeof(*event));
4413 	if (!event)
4414 		return QDF_STATUS_E_NOMEM;
4415 
4416 	status = wmi_unified_extract_sar_limit_event(wmi_handle,
4417 						     evt_buf, event);
4418 	if (QDF_IS_STATUS_ERROR(status)) {
4419 		wma_err("Event extract failure: %d", status);
4420 		qdf_mem_free(event);
4421 		return QDF_STATUS_E_INVAL;
4422 	}
4423 
4424 	callback = sar_callback;
4425 	sar_callback = NULL;
4426 	if (callback)
4427 		callback(sar_context, event);
4428 
4429 	qdf_mem_free(event);
4430 
4431 	return 0;
4432 }
4433 
4434 QDF_STATUS wma_sar_register_event_handlers(WMA_HANDLE handle)
4435 {
4436 	tp_wma_handle wma_handle = handle;
4437 	wmi_unified_t wmi_handle;
4438 
4439 	if (wma_validate_handle(wma_handle))
4440 		return QDF_STATUS_E_INVAL;
4441 
4442 	wmi_handle = wma_handle->wmi_handle;
4443 	if (wmi_validate_handle(wmi_handle))
4444 		return QDF_STATUS_E_INVAL;
4445 
4446 	return wmi_unified_register_event_handler(wmi_handle,
4447 						  wmi_sar_get_limits_event_id,
4448 						  wma_sar_event_handler,
4449 						  WMA_RX_WORK_CTX);
4450 }
4451 
4452 QDF_STATUS wma_get_sar_limit(WMA_HANDLE handle,
4453 			     wma_sar_cb callback, void *context)
4454 {
4455 	tp_wma_handle wma_handle = handle;
4456 	wmi_unified_t wmi_handle;
4457 	QDF_STATUS status;
4458 
4459 	if (wma_validate_handle(wma_handle))
4460 		return QDF_STATUS_E_INVAL;
4461 
4462 	wmi_handle = wma_handle->wmi_handle;
4463 	if (wmi_validate_handle(wmi_handle))
4464 		return QDF_STATUS_E_INVAL;
4465 
4466 	sar_callback = callback;
4467 	sar_context = context;
4468 	status = wmi_unified_get_sar_limit_cmd(wmi_handle);
4469 	if (QDF_IS_STATUS_ERROR(status)) {
4470 		wma_err("wmi_unified_get_sar_limit_cmd() error: %u",
4471 			 status);
4472 		sar_callback = NULL;
4473 	}
4474 
4475 	return status;
4476 }
4477 
4478 QDF_STATUS wma_set_sar_limit(WMA_HANDLE handle,
4479 		struct sar_limit_cmd_params *sar_limit_params)
4480 {
4481 	int ret;
4482 	tp_wma_handle wma = (tp_wma_handle) handle;
4483 	struct wmi_unified *wmi_handle;
4484 
4485 	if (wma_validate_handle(wma))
4486 		return QDF_STATUS_E_INVAL;
4487 
4488 	wmi_handle = wma->wmi_handle;
4489 	if (wmi_validate_handle(wmi_handle))
4490 		return QDF_STATUS_E_INVAL;
4491 
4492 	if (!sar_limit_params) {
4493 		wma_err("set sar limit ptr NULL");
4494 		return QDF_STATUS_E_INVAL;
4495 	}
4496 
4497 	ret = wmi_unified_send_sar_limit_cmd(wmi_handle,
4498 				sar_limit_params);
4499 
4500 	return ret;
4501 }
4502 
4503 QDF_STATUS wma_send_coex_config_cmd(WMA_HANDLE wma_handle,
4504 				    struct coex_config_params *coex_cfg_params)
4505 {
4506 	tp_wma_handle wma = (tp_wma_handle)wma_handle;
4507 	struct wmi_unified *wmi_handle;
4508 
4509 	if (wma_validate_handle(wma))
4510 		return QDF_STATUS_E_INVAL;
4511 
4512 	wmi_handle = wma->wmi_handle;
4513 	if (wmi_validate_handle(wmi_handle))
4514 		return QDF_STATUS_E_INVAL;
4515 
4516 	if (!coex_cfg_params) {
4517 		wma_err("coex cfg params ptr NULL");
4518 		return QDF_STATUS_E_INVAL;
4519 	}
4520 
4521 	return wmi_unified_send_coex_config_cmd(wmi_handle,
4522 					        coex_cfg_params);
4523 }
4524 
4525 /**
4526  * wma_get_arp_stats_handler() - handle arp stats data
4527  * indicated by FW
4528  * @handle: wma context
4529  * @data: event buffer
4530  * @data len: length of event buffer
4531  *
4532  * Return: 0 on success
4533  */
4534 int wma_get_arp_stats_handler(void *handle, uint8_t *data,
4535 			uint32_t data_len)
4536 {
4537 	WMI_VDEV_GET_ARP_STAT_EVENTID_param_tlvs *param_buf;
4538 	wmi_vdev_get_arp_stats_event_fixed_param *data_event;
4539 	wmi_vdev_get_connectivity_check_stats *connect_stats_event;
4540 	uint8_t *buf_ptr;
4541 	struct rsp_stats rsp = {0};
4542 	struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE);
4543 
4544 	if (!mac)
4545 		return -EINVAL;
4546 
4547 	if (!mac->sme.get_arp_stats_cb) {
4548 		wma_err("Callback not registered");
4549 		return -EINVAL;
4550 	}
4551 
4552 	if (!data) {
4553 		wma_err("invalid pointer");
4554 		return -EINVAL;
4555 	}
4556 	param_buf = (WMI_VDEV_GET_ARP_STAT_EVENTID_param_tlvs *)data;
4557 	if (!param_buf) {
4558 		wma_err("Invalid get arp stats event");
4559 		return -EINVAL;
4560 	}
4561 	data_event = param_buf->fixed_param;
4562 	if (!data_event) {
4563 		wma_err("Invalid get arp stats data event");
4564 		return -EINVAL;
4565 	}
4566 	rsp.arp_req_enqueue = data_event->arp_req_enqueue;
4567 	rsp.vdev_id = data_event->vdev_id;
4568 	rsp.arp_req_tx_success = data_event->arp_req_tx_success;
4569 	rsp.arp_req_tx_failure = data_event->arp_req_tx_failure;
4570 	rsp.arp_rsp_recvd = data_event->arp_rsp_recvd;
4571 	rsp.out_of_order_arp_rsp_drop_cnt =
4572 		data_event->out_of_order_arp_rsp_drop_cnt;
4573 	rsp.dad_detected = data_event->dad_detected;
4574 	rsp.connect_status = data_event->connect_status;
4575 	rsp.ba_session_establishment_status =
4576 		data_event->ba_session_establishment_status;
4577 
4578 	buf_ptr = (uint8_t *)data_event;
4579 	buf_ptr = buf_ptr + sizeof(wmi_vdev_get_arp_stats_event_fixed_param) +
4580 		  WMI_TLV_HDR_SIZE;
4581 	connect_stats_event = (wmi_vdev_get_connectivity_check_stats *)buf_ptr;
4582 
4583 	if (((connect_stats_event->tlv_header & 0xFFFF0000) >> 16 ==
4584 	      WMITLV_TAG_STRUC_wmi_vdev_get_connectivity_check_stats)) {
4585 		rsp.connect_stats_present = true;
4586 		rsp.tcp_ack_recvd = connect_stats_event->tcp_ack_recvd;
4587 		rsp.icmpv4_rsp_recvd = connect_stats_event->icmpv4_rsp_recvd;
4588 		wma_debug("tcp_ack_recvd %d icmpv4_rsp_recvd %d",
4589 			connect_stats_event->tcp_ack_recvd,
4590 			connect_stats_event->icmpv4_rsp_recvd);
4591 	}
4592 
4593 	mac->sme.get_arp_stats_cb(mac->hdd_handle, &rsp,
4594 				  mac->sme.get_arp_stats_context);
4595 
4596 	return 0;
4597 }
4598 
4599 /**
4600  * wma_unified_power_debug_stats_event_handler() - WMA handler function to
4601  * handle Power stats event from firmware
4602  * @handle: Pointer to wma handle
4603  * @cmd_param_info: Pointer to Power stats event TLV
4604  * @len: Length of the cmd_param_info
4605  *
4606  * Return: 0 on success, error number otherwise
4607  */
4608  #ifdef WLAN_POWER_DEBUG
4609 int wma_unified_power_debug_stats_event_handler(void *handle,
4610 			uint8_t *cmd_param_info, uint32_t len)
4611 {
4612 	WMI_PDEV_CHIP_POWER_STATS_EVENTID_param_tlvs *param_tlvs;
4613 	struct power_stats_response *power_stats_results;
4614 	wmi_pdev_chip_power_stats_event_fixed_param *param_buf;
4615 	uint32_t power_stats_len, stats_registers_len, *debug_registers;
4616 
4617 	struct mac_context *mac = (struct mac_context *)cds_get_context(QDF_MODULE_ID_PE);
4618 
4619 	param_tlvs =
4620 		(WMI_PDEV_CHIP_POWER_STATS_EVENTID_param_tlvs *) cmd_param_info;
4621 
4622 	param_buf = (wmi_pdev_chip_power_stats_event_fixed_param *)
4623 		param_tlvs->fixed_param;
4624 	if (!mac) {
4625 		wma_debug("NULL mac ptr");
4626 		return -EINVAL;
4627 	}
4628 
4629 	if (!param_buf) {
4630 		wma_debug("NULL power stats event fixed param");
4631 		return -EINVAL;
4632 	}
4633 
4634 	if (param_buf->num_debug_register > ((WMI_SVC_MSG_MAX_SIZE -
4635 		sizeof(wmi_pdev_chip_power_stats_event_fixed_param)) /
4636 		sizeof(uint32_t)) ||
4637 	    param_buf->num_debug_register > param_tlvs->num_debug_registers) {
4638 		wma_err("excess payload: LEN num_debug_register:%u",
4639 			param_buf->num_debug_register);
4640 		return -EINVAL;
4641 	}
4642 	debug_registers = param_tlvs->debug_registers;
4643 	stats_registers_len =
4644 		(sizeof(uint32_t) * param_buf->num_debug_register);
4645 	power_stats_len = stats_registers_len + sizeof(*power_stats_results);
4646 	power_stats_results = qdf_mem_malloc(power_stats_len);
4647 	if (!power_stats_results)
4648 		return -ENOMEM;
4649 
4650 	wma_debug("Cumulative sleep time %d cumulative total on time %d deep sleep enter counter %d last deep sleep enter tstamp ts %d debug registers fmt %d num debug register %d",
4651 			param_buf->cumulative_sleep_time_ms,
4652 			param_buf->cumulative_total_on_time_ms,
4653 			param_buf->deep_sleep_enter_counter,
4654 			param_buf->last_deep_sleep_enter_tstamp_ms,
4655 			param_buf->debug_register_fmt,
4656 			param_buf->num_debug_register);
4657 
4658 	power_stats_results->cumulative_sleep_time_ms
4659 		= param_buf->cumulative_sleep_time_ms;
4660 	power_stats_results->cumulative_total_on_time_ms
4661 		= param_buf->cumulative_total_on_time_ms;
4662 	power_stats_results->deep_sleep_enter_counter
4663 		= param_buf->deep_sleep_enter_counter;
4664 	power_stats_results->last_deep_sleep_enter_tstamp_ms
4665 		= param_buf->last_deep_sleep_enter_tstamp_ms;
4666 	power_stats_results->debug_register_fmt
4667 		= param_buf->debug_register_fmt;
4668 	power_stats_results->num_debug_register
4669 		= param_buf->num_debug_register;
4670 
4671 	power_stats_results->debug_registers
4672 		= (uint32_t *)(power_stats_results + 1);
4673 
4674 	qdf_mem_copy(power_stats_results->debug_registers,
4675 			debug_registers, stats_registers_len);
4676 	if (mac->sme.sme_power_debug_stats_callback)
4677 		mac->sme.sme_power_debug_stats_callback(mac,
4678 							power_stats_results);
4679 
4680 	qdf_mem_free(power_stats_results);
4681 	return 0;
4682 }
4683 #endif
4684 
4685 #ifdef WLAN_FEATURE_BEACON_RECEPTION_STATS
4686 int wma_unified_beacon_debug_stats_event_handler(void *handle,
4687 						 uint8_t *cmd_param_info,
4688 						 uint32_t len)
4689 {
4690 	WMI_VDEV_BCN_RECEPTION_STATS_EVENTID_param_tlvs *param_tlvs;
4691 	struct bcn_reception_stats_rsp *bcn_reception_stats;
4692 	wmi_vdev_bcn_recv_stats_fixed_param *param_buf;
4693 	struct mac_context *mac =
4694 			(struct mac_context *)cds_get_context(QDF_MODULE_ID_PE);
4695 
4696 	param_tlvs =
4697 	   (WMI_VDEV_BCN_RECEPTION_STATS_EVENTID_param_tlvs *)cmd_param_info;
4698 	if (!param_tlvs) {
4699 		wma_err("Invalid stats event");
4700 		return -EINVAL;
4701 	}
4702 
4703 	param_buf = (wmi_vdev_bcn_recv_stats_fixed_param *)
4704 		param_tlvs->fixed_param;
4705 	if (!param_buf || !mac || !mac->sme.beacon_stats_resp_callback) {
4706 		wma_debug("NULL mac ptr or HDD callback is null");
4707 		return -EINVAL;
4708 	}
4709 
4710 	if (!param_buf) {
4711 		wma_debug("NULL beacon stats event fixed param");
4712 		return -EINVAL;
4713 	}
4714 
4715 	bcn_reception_stats = qdf_mem_malloc(sizeof(*bcn_reception_stats));
4716 	if (!bcn_reception_stats)
4717 		return -ENOMEM;
4718 
4719 	bcn_reception_stats->total_bcn_cnt = param_buf->total_bcn_cnt;
4720 	bcn_reception_stats->total_bmiss_cnt = param_buf->total_bmiss_cnt;
4721 	bcn_reception_stats->vdev_id = param_buf->vdev_id;
4722 
4723 	wma_debug("Total beacon count %d total beacon miss count %d vdev_id %d",
4724 		 param_buf->total_bcn_cnt,
4725 		 param_buf->total_bmiss_cnt,
4726 		 param_buf->vdev_id);
4727 
4728 	qdf_mem_copy(bcn_reception_stats->bmiss_bitmap,
4729 		     param_buf->bmiss_bitmap,
4730 		     MAX_BCNMISS_BITMAP * sizeof(uint32_t));
4731 
4732 	mac->sme.beacon_stats_resp_callback(bcn_reception_stats,
4733 			mac->sme.beacon_stats_context);
4734 	qdf_mem_free(bcn_reception_stats);
4735 	return 0;
4736 }
4737 #else
4738 int wma_unified_beacon_debug_stats_event_handler(void *handle,
4739 						 uint8_t *cmd_param_info,
4740 						  uint32_t len)
4741 {
4742 	return 0;
4743 }
4744 #endif
4745 
4746 #if defined(CLD_PM_QOS) && defined(WLAN_FEATURE_LL_MODE)
4747 int
4748 wma_vdev_bcn_latency_event_handler(void *handle,
4749 				   uint8_t *event_info,
4750 				   uint32_t len)
4751 {
4752 	WMI_VDEV_BCN_LATENCY_EVENTID_param_tlvs *param_buf = NULL;
4753 	wmi_vdev_bcn_latency_fixed_param *bcn_latency = NULL;
4754 	struct mac_context *mac =
4755 			(struct mac_context *)cds_get_context(QDF_MODULE_ID_PE);
4756 	uint32_t latency_level;
4757 
4758 	param_buf = (WMI_VDEV_BCN_LATENCY_EVENTID_param_tlvs *)event_info;
4759 	if (!param_buf) {
4760 		wma_err("Invalid bcn latency event");
4761 		return -EINVAL;
4762 	}
4763 
4764 	bcn_latency = param_buf->fixed_param;
4765 	if (!bcn_latency) {
4766 		wma_debug("beacon latency event fixed param is NULL");
4767 		return -EINVAL;
4768 	}
4769 
4770 	/* Map the latency value to the level which host expects
4771 	 * 1 - normal, 2 - moderate, 3 - low, 4 - ultralow
4772 	 */
4773 	latency_level = bcn_latency->latency_level + 1;
4774 	if (latency_level < 1 || latency_level > 4) {
4775 		wma_debug("invalid beacon latency level value");
4776 		return -EINVAL;
4777 	}
4778 
4779 	/* Call the registered sme callback */
4780 	mac->sme.beacon_latency_event_cb(latency_level);
4781 
4782 	return 0;
4783 }
4784 #endif
4785 
4786 int wma_chan_info_event_handler(void *handle, uint8_t *event_buf,
4787 				uint32_t len)
4788 {
4789 	tp_wma_handle wma = (tp_wma_handle)handle;
4790 	WMI_CHAN_INFO_EVENTID_param_tlvs *param_buf;
4791 	wmi_chan_info_event_fixed_param *event;
4792 	struct scan_chan_info buf;
4793 	struct mac_context *mac = NULL;
4794 	struct lim_channel_status *channel_status;
4795 	bool snr_monitor_enabled;
4796 	struct wlan_objmgr_vdev *vdev;
4797 	enum QDF_OPMODE mode;
4798 
4799 	if (wma && wma->cds_context)
4800 		mac = (struct mac_context *)cds_get_context(QDF_MODULE_ID_PE);
4801 
4802 	if (!mac)
4803 		return -EINVAL;
4804 
4805 	param_buf = (WMI_CHAN_INFO_EVENTID_param_tlvs *)event_buf;
4806 	if (!param_buf)  {
4807 		wma_err("Invalid chan info event buffer");
4808 		return -EINVAL;
4809 	}
4810 	event = param_buf->fixed_param;
4811 	if (!event) {
4812 		wma_err("Invalid fixed param");
4813 		return -EINVAL;
4814 	}
4815 
4816 	snr_monitor_enabled = wlan_scan_is_snr_monitor_enabled(mac->psoc);
4817 	if (snr_monitor_enabled && mac->chan_info_cb) {
4818 		buf.tx_frame_count = event->tx_frame_cnt;
4819 		buf.clock_freq = event->mac_clk_mhz;
4820 		buf.cmd_flag = event->cmd_flags;
4821 		buf.freq = event->freq;
4822 		buf.noise_floor = event->noise_floor;
4823 		buf.cycle_count = event->cycle_count;
4824 		buf.rx_clear_count = event->rx_clear_count;
4825 		mac->chan_info_cb(&buf);
4826 	}
4827 
4828 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(wma->psoc, event->vdev_id,
4829 						    WLAN_LEGACY_WMA_ID);
4830 
4831 	if (!vdev) {
4832 		wma_err("vdev not found for vdev %d", event->vdev_id);
4833 		return -EINVAL;
4834 	}
4835 	mode = wlan_vdev_mlme_get_opmode(vdev);
4836 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_WMA_ID);
4837 
4838 	if (mac->sap.acs_with_more_param && mode == QDF_SAP_MODE) {
4839 		channel_status = qdf_mem_malloc(sizeof(*channel_status));
4840 		if (!channel_status)
4841 			return -ENOMEM;
4842 
4843 		wma_debug("freq %d nf %d rxcnt %u cyccnt %u tx_r %d tx_t %d",
4844 			  event->freq, event->noise_floor,
4845 			  event->rx_clear_count, event->cycle_count,
4846 			  event->chan_tx_pwr_range, event->chan_tx_pwr_tp);
4847 
4848 		channel_status->channelfreq = event->freq;
4849 		channel_status->noise_floor = event->noise_floor;
4850 		channel_status->rx_clear_count =
4851 			 event->rx_clear_count;
4852 		channel_status->cycle_count = event->cycle_count;
4853 		channel_status->chan_tx_pwr_range =
4854 			 event->chan_tx_pwr_range;
4855 		channel_status->chan_tx_pwr_throughput =
4856 			 event->chan_tx_pwr_tp;
4857 		channel_status->rx_frame_count =
4858 			 event->rx_frame_count;
4859 		channel_status->bss_rx_cycle_count =
4860 			event->my_bss_rx_cycle_count;
4861 		channel_status->rx_11b_mode_data_duration =
4862 			event->rx_11b_mode_data_duration;
4863 		channel_status->tx_frame_count = event->tx_frame_cnt;
4864 		channel_status->mac_clk_mhz = event->mac_clk_mhz;
4865 		channel_status->channel_id =
4866 			cds_freq_to_chan(event->freq);
4867 		channel_status->cmd_flags =
4868 			event->cmd_flags;
4869 
4870 		wma_send_msg(handle, WMA_RX_CHN_STATUS_EVENT,
4871 			     (void *)channel_status, 0);
4872 	}
4873 
4874 	return 0;
4875 }
4876 
4877 int wma_rx_aggr_failure_event_handler(void *handle, u_int8_t *event_buf,
4878 							u_int32_t len)
4879 {
4880 	WMI_REPORT_RX_AGGR_FAILURE_EVENTID_param_tlvs *param_buf;
4881 	struct sir_sme_rx_aggr_hole_ind *rx_aggr_hole_event;
4882 	wmi_rx_aggr_failure_event_fixed_param *rx_aggr_failure_info;
4883 	wmi_rx_aggr_failure_info *hole_info;
4884 	uint32_t i, alloc_len;
4885 	struct mac_context *mac;
4886 
4887 	mac = (struct mac_context *)cds_get_context(QDF_MODULE_ID_PE);
4888 	if (!mac || !mac->sme.stats_ext2_cb) {
4889 		wma_debug("NULL mac ptr or HDD callback is null");
4890 		return -EINVAL;
4891 	}
4892 
4893 	param_buf = (WMI_REPORT_RX_AGGR_FAILURE_EVENTID_param_tlvs *)event_buf;
4894 	if (!param_buf) {
4895 		wma_err("Invalid stats ext event buf");
4896 		return -EINVAL;
4897 	}
4898 
4899 	rx_aggr_failure_info = param_buf->fixed_param;
4900 	hole_info = param_buf->failure_info;
4901 
4902 	if (rx_aggr_failure_info->num_failure_info > ((WMI_SVC_MSG_MAX_SIZE -
4903 	    sizeof(*rx_aggr_hole_event)) /
4904 	    sizeof(rx_aggr_hole_event->hole_info_array[0]))) {
4905 		wma_err("Excess data from WMI num_failure_info %d",
4906 			rx_aggr_failure_info->num_failure_info);
4907 		return -EINVAL;
4908 	}
4909 
4910 	alloc_len = sizeof(*rx_aggr_hole_event) +
4911 		(rx_aggr_failure_info->num_failure_info)*
4912 		sizeof(rx_aggr_hole_event->hole_info_array[0]);
4913 	rx_aggr_hole_event = qdf_mem_malloc(alloc_len);
4914 	if (!rx_aggr_hole_event)
4915 		return -ENOMEM;
4916 
4917 	rx_aggr_hole_event->hole_cnt = rx_aggr_failure_info->num_failure_info;
4918 	if (rx_aggr_hole_event->hole_cnt > param_buf->num_failure_info) {
4919 		wma_err("Invalid no of hole count: %d",
4920 			rx_aggr_hole_event->hole_cnt);
4921 		qdf_mem_free(rx_aggr_hole_event);
4922 		return -EINVAL;
4923 	}
4924 	wma_debug("aggr holes_sum: %d\n",
4925 		rx_aggr_failure_info->num_failure_info);
4926 	for (i = 0; i < rx_aggr_hole_event->hole_cnt; i++) {
4927 		rx_aggr_hole_event->hole_info_array[i] =
4928 			hole_info->end_seq - hole_info->start_seq + 1;
4929 		wma_nofl_debug("aggr_index: %d\tstart_seq: %d\tend_seq: %d\t"
4930 			"hole_info: %d mpdu lost",
4931 			i, hole_info->start_seq, hole_info->end_seq,
4932 			rx_aggr_hole_event->hole_info_array[i]);
4933 		hole_info++;
4934 	}
4935 
4936 	mac->sme.stats_ext2_cb(mac->hdd_handle, rx_aggr_hole_event);
4937 	qdf_mem_free(rx_aggr_hole_event);
4938 
4939 	return 0;
4940 }
4941 
4942 int wma_wlan_bt_activity_evt_handler(void *handle, uint8_t *event, uint32_t len)
4943 {
4944 	wmi_coex_bt_activity_event_fixed_param *fixed_param;
4945 	WMI_WLAN_COEX_BT_ACTIVITY_EVENTID_param_tlvs *param_buf =
4946 		(WMI_WLAN_COEX_BT_ACTIVITY_EVENTID_param_tlvs *)event;
4947 	struct scheduler_msg sme_msg = {0};
4948 	QDF_STATUS qdf_status;
4949 
4950 	if (!param_buf) {
4951 		wma_err("Invalid BT activity event buffer");
4952 		return -EINVAL;
4953 	}
4954 
4955 	fixed_param = param_buf->fixed_param;
4956 	if (!fixed_param) {
4957 		wma_err("Invalid BT activity event fixed param buffer");
4958 		return -EINVAL;
4959 	}
4960 
4961 	wma_info("Received BT activity event %u",
4962 		fixed_param->coex_profile_evt);
4963 
4964 	sme_msg.type = eWNI_SME_BT_ACTIVITY_INFO_IND;
4965 	sme_msg.bodyptr = NULL;
4966 	sme_msg.bodyval = fixed_param->coex_profile_evt;
4967 
4968 	qdf_status = scheduler_post_message(QDF_MODULE_ID_WMA,
4969 					    QDF_MODULE_ID_SME,
4970 					    QDF_MODULE_ID_SME, &sme_msg);
4971 	if (QDF_IS_STATUS_ERROR(qdf_status))
4972 		return -EINVAL;
4973 
4974 	return 0;
4975 }
4976 
4977 int wma_pdev_div_info_evt_handler(void *handle, u_int8_t *event_buf,
4978 	u_int32_t len)
4979 {
4980 	WMI_PDEV_DIV_RSSI_ANTID_EVENTID_param_tlvs *param_buf;
4981 	wmi_pdev_div_rssi_antid_event_fixed_param *event;
4982 	struct chain_rssi_result chain_rssi_result;
4983 	u_int32_t i;
4984 	u_int8_t macaddr[QDF_MAC_ADDR_SIZE];
4985 	tp_wma_handle wma = (tp_wma_handle)handle;
4986 
4987 	struct mac_context *pmac = (struct mac_context *)cds_get_context(
4988 					QDF_MODULE_ID_PE);
4989 	if (!pmac || !wma) {
4990 		wma_err("Invalid pmac or wma");
4991 		return -EINVAL;
4992 	}
4993 
4994 	if (!pmac->sme.get_chain_rssi_cb) {
4995 		wma_err("Invalid get_chain_rssi_cb");
4996 		return -EINVAL;
4997 	}
4998 	param_buf = (WMI_PDEV_DIV_RSSI_ANTID_EVENTID_param_tlvs *) event_buf;
4999 	if (!param_buf) {
5000 		wma_err("Invalid rssi antid event buffer");
5001 		return -EINVAL;
5002 	}
5003 
5004 	event = param_buf->fixed_param;
5005 	if (!event) {
5006 		wma_err("Invalid fixed param");
5007 		return -EINVAL;
5008 	}
5009 
5010 	if (event->num_chains_valid > CHAIN_MAX_NUM) {
5011 		wma_err("Invalid num of chains");
5012 		return -EINVAL;
5013 	}
5014 
5015 	qdf_mem_zero(&chain_rssi_result, sizeof(chain_rssi_result));
5016 
5017 	WMI_MAC_ADDR_TO_CHAR_ARRAY(&event->macaddr, macaddr);
5018 	wma_debug("macaddr: " QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(macaddr));
5019 
5020 	wma_debug("num_chains_valid: %d", event->num_chains_valid);
5021 	chain_rssi_result.num_chains_valid = event->num_chains_valid;
5022 
5023 	qdf_mem_copy(chain_rssi_result.chain_rssi, event->chain_rssi,
5024 		     sizeof(event->chain_rssi));
5025 
5026 	qdf_mem_copy(chain_rssi_result.chain_evm, event->chain_evm,
5027 		     sizeof(event->chain_evm));
5028 
5029 	qdf_mem_copy(chain_rssi_result.ant_id, event->ant_id,
5030 		     sizeof(event->ant_id));
5031 
5032 	for (i = 0; i < chain_rssi_result.num_chains_valid; i++) {
5033 		wma_nofl_debug("chain_rssi: %d, chain_evm: %d,ant_id: %d",
5034 			 chain_rssi_result.chain_rssi[i],
5035 			 chain_rssi_result.chain_evm[i],
5036 			 chain_rssi_result.ant_id[i]);
5037 
5038 		if (!wmi_service_enabled(wma->wmi_handle,
5039 					 wmi_service_hw_db2dbm_support)) {
5040 			if (chain_rssi_result.chain_rssi[i] !=
5041 			    WMA_INVALID_PER_CHAIN_SNR)
5042 				chain_rssi_result.chain_rssi[i] +=
5043 						WMA_TGT_NOISE_FLOOR_DBM;
5044 			else
5045 				chain_rssi_result.chain_rssi[i] =
5046 						WMA_INVALID_PER_CHAIN_RSSI;
5047 		}
5048 	}
5049 
5050 	pmac->sme.get_chain_rssi_cb(pmac->sme.get_chain_rssi_context,
5051 				&chain_rssi_result);
5052 
5053 	return 0;
5054 }
5055 
5056 int wma_vdev_obss_detection_info_handler(void *handle, uint8_t *event,
5057 					 uint32_t len)
5058 {
5059 	tp_wma_handle wma = (tp_wma_handle) handle;
5060 	struct wmi_obss_detect_info *obss_detection;
5061 	QDF_STATUS status;
5062 
5063 	if (!event) {
5064 		wma_err("Invalid obss_detection_info event buffer");
5065 		return -EINVAL;
5066 	}
5067 
5068 	obss_detection = qdf_mem_malloc(sizeof(*obss_detection));
5069 	if (!obss_detection)
5070 		return -ENOMEM;
5071 
5072 	status = wmi_unified_extract_obss_detection_info(wma->wmi_handle,
5073 							 event, obss_detection);
5074 
5075 	if (QDF_IS_STATUS_ERROR(status)) {
5076 		wma_err("Failed to extract obss info");
5077 		qdf_mem_free(obss_detection);
5078 		return -EINVAL;
5079 	}
5080 
5081 	if (!wma_is_vdev_valid(obss_detection->vdev_id)) {
5082 		wma_err("Invalid vdev id %d", obss_detection->vdev_id);
5083 		qdf_mem_free(obss_detection);
5084 		return -EINVAL;
5085 	}
5086 
5087 	wma_send_msg(wma, WMA_OBSS_DETECTION_INFO, obss_detection, 0);
5088 
5089 	return 0;
5090 }
5091 
5092 static void wma_send_set_key_rsp(uint8_t vdev_id, bool pairwise,
5093 				 uint8_t key_index)
5094 {
5095 	tSetStaKeyParams *key_info_uc;
5096 	tSetBssKeyParams *key_info_mc;
5097 	struct wlan_crypto_key *crypto_key;
5098 	struct wlan_objmgr_vdev *vdev;
5099 	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
5100 	struct qdf_mac_addr bcast_mac = QDF_MAC_ADDR_BCAST_INIT;
5101 
5102 	if (!wma)
5103 		return;
5104 
5105 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(wma->psoc,
5106 						    vdev_id,
5107 						    WLAN_LEGACY_WMA_ID);
5108 	if (!vdev) {
5109 		wma_err("VDEV object not found");
5110 		return;
5111 	}
5112 	crypto_key = wlan_crypto_get_key(vdev, key_index);
5113 
5114 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_WMA_ID);
5115 	if (!crypto_key) {
5116 		wma_debug("crypto_key not found");
5117 		return;
5118 	}
5119 
5120 	if (pairwise) {
5121 		key_info_uc = qdf_mem_malloc(sizeof(*key_info_uc));
5122 		if (!key_info_uc)
5123 			return;
5124 		key_info_uc->vdev_id = vdev_id;
5125 		key_info_uc->status = QDF_STATUS_SUCCESS;
5126 		key_info_uc->key[0].keyLength = crypto_key->keylen;
5127 		qdf_mem_copy(&key_info_uc->macaddr, &crypto_key->macaddr,
5128 			     QDF_MAC_ADDR_SIZE);
5129 		wma_send_msg_high_priority(wma, WMA_SET_STAKEY_RSP,
5130 					   key_info_uc, 0);
5131 	} else {
5132 		key_info_mc = qdf_mem_malloc(sizeof(*key_info_mc));
5133 		if (!key_info_mc)
5134 			return;
5135 		key_info_mc->vdev_id = vdev_id;
5136 		key_info_mc->status = QDF_STATUS_SUCCESS;
5137 		key_info_mc->key[0].keyLength = crypto_key->keylen;
5138 		qdf_mem_copy(&key_info_mc->macaddr, &bcast_mac,
5139 			     QDF_MAC_ADDR_SIZE);
5140 		wma_send_msg_high_priority(wma, WMA_SET_BSSKEY_RSP,
5141 					   key_info_mc, 0);
5142 	}
5143 }
5144 
5145 void wma_set_peer_ucast_cipher(uint8_t *mac_addr, int32_t uc_cipher,
5146 			       int32_t cipher_cap)
5147 {
5148 	struct wlan_objmgr_peer *peer;
5149 	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
5150 
5151 	if (!wma)
5152 		return;
5153 	peer = wlan_objmgr_get_peer(wma->psoc,
5154 				    wlan_objmgr_pdev_get_pdev_id(wma->pdev),
5155 				    mac_addr, WLAN_LEGACY_WMA_ID);
5156 	if (!peer) {
5157 		wma_err("Peer of peer_mac "QDF_MAC_ADDR_FMT" not found",
5158 			QDF_MAC_ADDR_REF(mac_addr));
5159 		return;
5160 	}
5161 
5162 	wlan_crypto_set_peer_param(peer, WLAN_CRYPTO_PARAM_CIPHER_CAP,
5163 				   cipher_cap);
5164 	wlan_crypto_set_peer_param(peer, WLAN_CRYPTO_PARAM_UCAST_CIPHER,
5165 				   uc_cipher);
5166 	wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_WMA_ID);
5167 
5168 	wma_debug("Set unicast cipher %x and cap %x for "QDF_MAC_ADDR_FMT,
5169 		  uc_cipher, cipher_cap, QDF_MAC_ADDR_REF(mac_addr));
5170 }
5171 
5172 void wma_update_set_key(uint8_t session_id, bool pairwise,
5173 			uint8_t key_index,
5174 			enum wlan_crypto_cipher_type cipher_type)
5175 {
5176 	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
5177 	struct wma_txrx_node *iface;
5178 
5179 	if (!wma)
5180 		return;
5181 
5182 	iface = &wma->interfaces[session_id];
5183 	if (!iface) {
5184 		wma_err("iface not found for session id %d", session_id);
5185 		return;
5186 	}
5187 
5188 	if (iface)
5189 		iface->is_waiting_for_key = false;
5190 
5191 	if (!pairwise && iface) {
5192 		/* Its GTK release the wake lock */
5193 		wma_debug("Release set key wake lock");
5194 		qdf_runtime_pm_allow_suspend(
5195 				&iface->vdev_set_key_runtime_wakelock);
5196 		wma_release_wakelock(&iface->vdev_set_key_wakelock);
5197 	}
5198 
5199 	wma_send_set_key_rsp(session_id, pairwise, key_index);
5200 }
5201 
5202 int wma_vdev_bss_color_collision_info_handler(void *handle,
5203 					      uint8_t *event,
5204 					      uint32_t len)
5205 {
5206 	tp_wma_handle wma = (tp_wma_handle) handle;
5207 	struct wmi_obss_color_collision_info *obss_color_info;
5208 	QDF_STATUS status;
5209 
5210 	if (!event) {
5211 		wma_err("Invalid obss_color_collision event buffer");
5212 		return -EINVAL;
5213 	}
5214 
5215 	obss_color_info = qdf_mem_malloc(sizeof(*obss_color_info));
5216 	if (!obss_color_info)
5217 		return -ENOMEM;
5218 
5219 	status = wmi_unified_extract_obss_color_collision_info(wma->wmi_handle,
5220 							       event,
5221 							       obss_color_info);
5222 
5223 	if (QDF_IS_STATUS_ERROR(status)) {
5224 		wma_err("Failed to extract obss color info");
5225 		qdf_mem_free(obss_color_info);
5226 		return -EINVAL;
5227 	}
5228 
5229 	if (!wma_is_vdev_valid(obss_color_info->vdev_id)) {
5230 		wma_err("Invalid vdev id %d", obss_color_info->vdev_id);
5231 		qdf_mem_free(obss_color_info);
5232 		return -EINVAL;
5233 	}
5234 
5235 	wma_send_msg(wma, WMA_OBSS_COLOR_COLLISION_INFO, obss_color_info, 0);
5236 
5237 	return 0;
5238 }
5239 
5240 #ifdef FEATURE_ANI_LEVEL_REQUEST
5241 int wma_get_ani_level_evt_handler(void *handle, uint8_t *event_buf,
5242 				  uint32_t len)
5243 {
5244 	tp_wma_handle wma = (tp_wma_handle)handle;
5245 	struct wmi_host_ani_level_event *ani = NULL;
5246 	uint32_t num_freqs = 0;
5247 	QDF_STATUS status;
5248 	struct mac_context *pmac;
5249 	int ret = 0;
5250 
5251 	pmac = (struct mac_context *)cds_get_context(QDF_MODULE_ID_PE);
5252 	if (!pmac || !wma) {
5253 		wma_err("Invalid pmac or wma");
5254 		return -EINVAL;
5255 	}
5256 
5257 	status = wmi_unified_extract_ani_level(wma->wmi_handle, event_buf,
5258 					       &ani, &num_freqs);
5259 
5260 	if (QDF_IS_STATUS_ERROR(status)) {
5261 		wma_err("Failed to extract ani level");
5262 		return -EINVAL;
5263 	}
5264 
5265 	if (!pmac->ani_params.ani_level_cb) {
5266 		wma_err("Invalid ani_level_cb");
5267 		ret = -EINVAL;
5268 		goto free;
5269 	}
5270 
5271 	pmac->ani_params.ani_level_cb(ani, num_freqs,
5272 				      pmac->ani_params.context);
5273 
5274 free:
5275 	qdf_mem_free(ani);
5276 	return ret;
5277 }
5278 #else
5279 int wma_get_ani_level_evt_handler(void *handle, uint8_t *event_buf,
5280 				  uint32_t len)
5281 {
5282 	return 0;
5283 }
5284 #endif
5285 
5286