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