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 
wma_set_wakeup_logs_to_console(bool value)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  */
qdf_wma_wow_wakeup_stats_event(tp_wma_handle wma)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
qdf_wma_wow_wakeup_stats_event(tp_wma_handle wma)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  */
wma_wake_reason_auto_shutdown(void)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
wma_wake_reason_auto_shutdown(void)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
wma_wake_reason_nlod(t_wma_handle * wma,uint8_t vdev_id)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
wma_wake_reason_nlod(t_wma_handle * wma,uint8_t vdev_id)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  */
wma_nan_rsp_handler_callback(void * handle,uint8_t * event,uint32_t len)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
wma_nan_rsp_handler_callback(void * handle,uint8_t * event,uint32_t len)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  */
wma_get_snr(tAniGetSnrReq * psnr_req)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 
wma_get_rx_retry_cnt(struct mac_context * mac,uint8_t vdev_id,uint8_t * mac_addr)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  */
wma_process_link_status_req(tp_wma_handle wma,tAniGetLinkStatus * pGetLinkStatus)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
wma_vdev_tsf_set_mac_id_tsf_id(struct stsf * ptsf,uint32_t mac_id,uint32_t mac_id_valid,uint32_t tsf_id,uint32_t tsf_id_valid)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
wma_vdev_tsf_set_mac_id_tsf_id(struct stsf * ptsf,uint32_t mac_id,uint32_t mac_id_valid,uint32_t tsf_id,uint32_t tsf_id_valid)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  */
wma_vdev_tsf_handler(void * handle,uint8_t * data,uint32_t data_len)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  */
wma_capture_tsf(tp_wma_handle wma_handle,uint32_t vdev_id)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  */
wma_reset_tsf_gpio(tp_wma_handle wma_handle,uint32_t vdev_id)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  */
wma_set_tsf_gpio_pin(WMA_HANDLE handle,uint32_t pin)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
wma_set_tsf_auto_report(WMA_HANDLE handle,uint32_t vdev_id,uint32_t param_id,bool ena)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  */
wma_set_wisa_params(tp_wma_handle wma_handle,struct sir_wisa_params * wisa)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  */
wma_process_dhcp_ind(WMA_HANDLE handle,tAniDHCPInd * ta_dhcp_ind)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
wma_eht_chan_phy_mode(uint32_t freq,uint8_t dot11_mode,uint16_t bw_val,enum phy_ch_width chan_width)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
wma_eht_chan_phy_mode(uint32_t freq,uint8_t dot11_mode,uint16_t bw_val,enum phy_ch_width chan_width)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 
wma_chan_phy_mode(uint32_t freq,enum phy_ch_width chan_width,uint8_t dot11_mode)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  */
wma_get_link_speed(WMA_HANDLE handle,struct link_speed_info * pLinkSpeed)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 
wma_get_isolation(tp_wma_handle wma)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  */
wma_add_beacon_filter(WMA_HANDLE handle,struct beacon_filter_param * filter_params)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 */
wma_remove_beacon_filter(WMA_HANDLE handle,struct beacon_filter_param * filter_params)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  */
wma_send_adapt_dwelltime_params(WMA_HANDLE handle,struct adaptive_dwelltime_params * dwelltime_params)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 
wma_send_dbs_scan_selection_params(WMA_HANDLE handle,struct wmi_dbs_scan_sel_params * dbs_scan_params)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  */
wma_unified_fw_profiling_cmd(wmi_unified_t wmi_handle,uint32_t cmd,uint32_t value1,uint32_t value2)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  */
wma_wow_set_wake_time(WMA_HANDLE wma_handle,uint8_t vdev_id,uint32_t cookie,uint32_t time)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  */
wma_check_and_set_wake_timer(uint32_t time)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  */
wma_unified_csa_offload_enable(tp_wma_handle wma,uint8_t vdev_id)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 *
wma_parse_ch_switch_wrapper_ie(uint8_t * ch_wr_ie,uint8_t sub_ele_id,uint8_t ie_extn_id)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
wma_parse_bw_indication_ie(uint8_t * ie,uint8_t tlv_len,struct csa_offload_params * csa_event)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
wma_parse_bw_indication_ie(uint8_t * ie,uint8_t tlv_len,struct csa_offload_params * csa_event)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 
fill_csa_offload_params(wmi_csa_event_fixed_param * csa_event,struct csa_offload_params * csa_offload_event,struct wlan_objmgr_pdev * pdev)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
handle_csa_standby_link(wmi_csa_event_fixed_param * csa_event,struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_pdev * pdev)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 
fill_peer_mac_addr(wmi_csa_event_fixed_param * csa_event,uint8_t * bssid)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
fill_peer_mac_addr(wmi_csa_event_fixed_param * csa_event,uint8_t * bssid)1502 static int fill_peer_mac_addr(wmi_csa_event_fixed_param *csa_event,
1503 			      uint8_t *bssid)
1504 {
1505 	return 0;
1506 }
1507 
handle_csa_standby_link(wmi_csa_event_fixed_param * csa_event,struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_pdev * pdev)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  */
wma_csa_offload_handler(void * handle,uint8_t * event,uint32_t len)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  */
wma_oem_data_response_handler(void * handle,uint8_t * datap,uint32_t len)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 
wma_start_oem_req_cmd(tp_wma_handle wma_handle,struct oem_data_req * oem_data_req)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
wma_start_oem_data_cmd(tp_wma_handle wma_handle,struct oem_data * 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  */
wma_pktlog_wmi_send_cmd(WMA_HANDLE handle,struct ath_pktlog_wmi_params * params)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  */
wma_wow_wake_reason_str(A_INT32 wake_reason)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 
wma_wow_reason_has_stats(enum wake_reason_e reason)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 
wma_inc_wow_stats(t_wma_handle * wma,WOW_EVENT_INFO_fixed_param * wake_info)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 
wma_wow_stats_display(struct wake_lock_stats * stats)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 
wma_print_wow_stats(t_wma_handle * wma,WOW_EVENT_INFO_fixed_param * wake_info)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  */
wma_extscan_get_eventid_from_tlvtag(uint32_t tag)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
wma_extscan_get_eventid_from_tlvtag(uint32_t tag)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  */
wow_get_wmi_eventid(int32_t reason,uint32_t tag)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  */
is_piggybacked_event(int32_t reason)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 *
wma_pkt_proto_subtype_to_string(enum qdf_proto_subtype proto_subtype)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
wma_wow_get_pkt_proto_subtype(uint8_t * data,uint32_t len)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 
wma_log_pkt_eapol(uint8_t * data,uint32_t length)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 
wma_log_pkt_dhcp(uint8_t * data,uint32_t length)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 
wma_log_pkt_icmpv4(uint8_t * data,uint32_t length)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 
wma_log_pkt_icmpv6(uint8_t * data,uint32_t length)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 
wma_log_pkt_ipv4(uint8_t * data,uint32_t length)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 
wma_log_pkt_ipv6(uint8_t * data,uint32_t length)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 
wma_log_pkt_tcpv4(uint8_t * data,uint32_t length)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 
wma_log_pkt_tcpv6(uint8_t * data,uint32_t length)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 
wma_wow_inc_wake_lock_stats_by_dst_addr(t_wma_handle * wma,uint8_t vdev_id,uint8_t * dest_mac)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 
wma_wow_inc_wake_lock_stats_by_protocol(t_wma_handle * wma,uint8_t vdev_id,enum qdf_proto_subtype proto_subtype)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  */
wma_wow_parse_data_pkt(t_wma_handle * wma,uint8_t vdev_id,uint8_t * data,uint32_t length)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  */
wma_wow_dump_mgmt_buffer(uint8_t * wow_packet_buffer,uint32_t buf_len)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  */
wma_acquire_wow_wakelock(t_wma_handle * wma,int wake_reason)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
wma_wake_reason_ap_assoc_lost(t_wma_handle * wma,void * event,uint32_t len)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 
wma_vdev_type_str(uint32_t vdev_type)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 
wma_wake_event_packet(t_wma_handle * wma,WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs * event_param,uint32_t length)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 
wma_wake_event_no_payload(t_wma_handle * wma,WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs * event_param,uint32_t length)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 
wma_wake_event_piggybacked(t_wma_handle * wma,WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs * event_param,uint32_t length)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 
wma_debug_assert_page_fault_wakeup(uint32_t reason)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 
wma_wake_event_log_reason(t_wma_handle * wma,WOW_EVENT_INFO_fixed_param * wake_info)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 
wma_wow_pagefault_action_cb(void * buf)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 	if (!mac) {
3235 		wma_err("NULL mac ptr");
3236 		return QDF_STATUS_E_INVAL;
3237 	}
3238 
3239 	return mac->sme.pagefault_action_cb(buf, WLAN_WMA_PF_APPS_NOTIFY_BUF_LEN);
3240 }
3241 
3242 static QDF_STATUS
wma_wow_pagefault_add_sym_to_event(tp_wma_handle wma,struct wow_pf_sym * pf_sym)3243 wma_wow_pagefault_add_sym_to_event(tp_wma_handle wma, struct wow_pf_sym *pf_sym)
3244 {
3245 	uint8_t *buf_ptr = wma->wma_pf_hist.pf_notify_buf_ptr;
3246 	uint32_t buf_len = wma->wma_pf_hist.pf_notify_buf_len;
3247 
3248 	if (WLAN_WMA_PF_APPS_NOTIFY_BUF_LEN - buf_len <
3249 	    WLAN_WMA_PER_PF_SYM_NOTIFY_BUF_LEN) {
3250 		wma_wow_pagefault_action_cb(buf_ptr);
3251 		buf_len = 0;
3252 	}
3253 
3254 	/* Mem zero to send buffer with zero padding */
3255 	if (!buf_len)
3256 		qdf_mem_zero(buf_ptr, WLAN_WMA_PF_APPS_NOTIFY_BUF_LEN);
3257 
3258 	qdf_mem_copy(buf_ptr + buf_len, pf_sym,
3259 		     WLAN_WMA_PER_PF_SYM_NOTIFY_BUF_LEN);
3260 	buf_len += WLAN_WMA_PER_PF_SYM_NOTIFY_BUF_LEN;
3261 
3262 	wma->wma_pf_hist.pf_notify_buf_len = buf_len;
3263 
3264 	return QDF_STATUS_SUCCESS;
3265 }
3266 
3267 static void
wma_wow_pagefault_add_new_sym_from_event(tp_wma_handle wma,struct wow_pf_wakeup_ev_data * pf_sym_list,qdf_time_t cur_time)3268 wma_wow_pagefault_add_new_sym_from_event(tp_wma_handle wma,
3269 					 struct wow_pf_wakeup_ev_data *pf_sym_list,
3270 					 qdf_time_t cur_time)
3271 {
3272 	uint8_t tbl_idx, ev_lst_idx, new_pf_idx, idx2;
3273 	uint8_t new_idx_cnt, cur_idx_cnt, ev_sym_cnt, pf_th;
3274 	uint8_t max_sym_count = WLAN_WMA_MAX_PF_SYM;
3275 	qdf_time_t new_idx_last_ts, cur_idx_last_ts;
3276 	qdf_time_t new_idx_old_ts, cur_idx_old_ts;
3277 	struct wma_pf_sym *cur_pf_entry, *new_pf_entry;
3278 	struct wma_pf_sym_hist *pf_sym_hist = &wma->wma_pf_hist;
3279 
3280 	pf_th = wlan_pmo_get_min_pagefault_wakeups_for_action(wma->psoc);
3281 	for (tbl_idx = 0; tbl_idx < max_sym_count; tbl_idx++) {
3282 		if (!pf_sym_list->pending_pf_syms)
3283 			break;
3284 
3285 		new_pf_idx = tbl_idx;
3286 		new_pf_entry = &pf_sym_hist->wma_pf_sym[tbl_idx];
3287 		new_idx_cnt = new_pf_entry->pf_sym.count;
3288 		new_idx_last_ts = new_pf_entry->pf_ev_ts[new_idx_cnt - 1];
3289 		new_idx_old_ts = new_pf_entry->pf_ev_ts[0];
3290 
3291 		for (ev_lst_idx = 0; ev_lst_idx < pf_sym_list->num_pf_syms;
3292 		     ev_lst_idx++) {
3293 			if (!pf_sym_list->pf_sym[ev_lst_idx].count)
3294 				continue;
3295 
3296 			/* Add the sym that already met threshold to the buf */
3297 			if (pf_sym_list->pf_sym[ev_lst_idx].count >= pf_th) {
3298 				wma_wow_pagefault_add_sym_to_event(wma,
3299 								   pf_sym_list->pf_sym);
3300 				pf_sym_list->pf_sym[ev_lst_idx].count = 0x0;
3301 				pf_sym_list->pending_pf_syms--;
3302 				continue;
3303 			}
3304 
3305 			ev_sym_cnt = pf_sym_list->pf_sym[ev_lst_idx].count;
3306 
3307 			/* If current entry is NULL, add the symbol here */
3308 			if (!new_idx_cnt)
3309 				goto add_sym;
3310 
3311 			/* Replace event if count is equal as current event
3312 			 * is latest and don't replace symbol from current event
3313 			 */
3314 			if (new_idx_cnt > ev_sym_cnt ||
3315 			    qdf_system_time_after_eq(new_idx_last_ts, cur_time))
3316 				break;
3317 
3318 			for (idx2 = tbl_idx + 1; idx2 < max_sym_count; idx2++) {
3319 				cur_pf_entry = &pf_sym_hist->wma_pf_sym[idx2];
3320 				cur_idx_cnt = cur_pf_entry->pf_sym.count;
3321 				cur_idx_last_ts =
3322 					cur_pf_entry->pf_ev_ts[cur_idx_cnt - 1];
3323 				cur_idx_old_ts = cur_pf_entry->pf_ev_ts[0];
3324 
3325 				if (cur_idx_cnt > new_idx_cnt)
3326 					continue;
3327 
3328 				/* Don't replace symbol from current event */
3329 				if (qdf_system_time_after_eq(cur_idx_last_ts,
3330 							     cur_time)) {
3331 					continue;
3332 				}
3333 
3334 				if (cur_idx_cnt == new_idx_cnt &&
3335 				    qdf_system_time_after_eq(cur_idx_old_ts,
3336 							     new_idx_old_ts)) {
3337 					continue;
3338 				}
3339 
3340 				new_pf_idx = idx2;
3341 				new_idx_cnt = cur_idx_cnt;
3342 				new_idx_last_ts = cur_idx_last_ts;
3343 				new_idx_old_ts = cur_idx_old_ts;
3344 			}
3345 
3346 add_sym:
3347 			/* Replace symbol with current event symbol */
3348 			new_pf_entry = &pf_sym_hist->wma_pf_sym[new_pf_idx];
3349 			new_pf_entry->pf_sym.symbol =
3350 					pf_sym_list->pf_sym[ev_lst_idx].symbol;
3351 			new_pf_entry->pf_sym.count = ev_sym_cnt;
3352 			for (idx2 = 0; idx2 < ev_sym_cnt; idx2++)
3353 				new_pf_entry->pf_ev_ts[idx2] = cur_time;
3354 
3355 			pf_sym_list->pending_pf_syms--;
3356 			pf_sym_list->pf_sym[ev_lst_idx].count = 0;
3357 			break;
3358 		}
3359 	}
3360 }
3361 
3362 static void
wma_wow_pagefault_process_existing_syms(tp_wma_handle wma,struct wma_pf_sym * pf_sym_entry,struct wow_pf_wakeup_ev_data * ev_list,qdf_time_t cur_time)3363 wma_wow_pagefault_process_existing_syms(tp_wma_handle wma,
3364 					struct wma_pf_sym *pf_sym_entry,
3365 					struct wow_pf_wakeup_ev_data *ev_list,
3366 					qdf_time_t cur_time)
3367 {
3368 	uint8_t ev_idx, add_idx;
3369 	uint8_t pf_th, *tbl_sym_cnt, ev_sym_cnt;
3370 
3371 	pf_th = wlan_pmo_get_min_pagefault_wakeups_for_action(wma->psoc);
3372 	tbl_sym_cnt = &pf_sym_entry->pf_sym.count;
3373 
3374 	for (ev_idx = 0; ev_idx < ev_list->num_pf_syms; ev_idx++) {
3375 		/* Ignore if all symbols are processed */
3376 		if (!ev_list->pending_pf_syms)
3377 			break;
3378 
3379 		if (!ev_list->pf_sym[ev_idx].count)
3380 			continue;
3381 
3382 		/* Only process symbol equals current entry in the history */
3383 		if (ev_list->pf_sym[ev_idx].symbol !=
3384 		    pf_sym_entry->pf_sym.symbol) {
3385 			continue;
3386 		}
3387 
3388 		ev_sym_cnt = ev_list->pf_sym[ev_idx].count;
3389 
3390 		/* If symbol reaches threshold, then clear the ts data */
3391 		if (*tbl_sym_cnt + ev_sym_cnt >= pf_th) {
3392 			qdf_mem_zero(&pf_sym_entry->pf_ev_ts[0],
3393 				     (*tbl_sym_cnt * sizeof(qdf_time_t)));
3394 			*tbl_sym_cnt += ev_sym_cnt;
3395 			wma_wow_pagefault_add_sym_to_event(wma,
3396 							   &pf_sym_entry->pf_sym);
3397 			*tbl_sym_cnt = 0x0;
3398 
3399 			goto sym_handled;
3400 		}
3401 
3402 		for (add_idx = 0; add_idx < ev_sym_cnt; add_idx++)
3403 			pf_sym_entry->pf_ev_ts[(*tbl_sym_cnt)++] = cur_time;
3404 
3405 sym_handled:
3406 		ev_list->pending_pf_syms--;
3407 		ev_list->pf_sym[ev_idx].count = 0;
3408 		break;
3409 	}
3410 }
3411 
3412 static void
wma_wow_pagefault_flush_ageout_entries(struct wma_pf_sym * pf_sym_entry,qdf_time_t cutoff_time)3413 wma_wow_pagefault_flush_ageout_entries(struct wma_pf_sym *pf_sym_entry,
3414 				       qdf_time_t cutoff_time)
3415 {
3416 	qdf_time_t entry_ts;
3417 	uint8_t *cur_pf_count, pf_ts_idx;
3418 
3419 	cur_pf_count = &pf_sym_entry->pf_sym.count;
3420 	/* Find the count of entries which elapsed cutoff time */
3421 	for (pf_ts_idx = 0; pf_ts_idx < *cur_pf_count; pf_ts_idx++) {
3422 		entry_ts = pf_sym_entry->pf_ev_ts[pf_ts_idx];
3423 		if (qdf_system_time_before(cutoff_time, entry_ts))
3424 			break;
3425 	}
3426 
3427 	/* Remove the entries which elapsed cutoff time */
3428 	if (pf_ts_idx > 0) {
3429 		*cur_pf_count -= pf_ts_idx;
3430 		qdf_mem_copy(&pf_sym_entry->pf_ev_ts[0],
3431 			     &pf_sym_entry->pf_ev_ts[pf_ts_idx],
3432 			     (*cur_pf_count * sizeof(qdf_time_t)));
3433 		qdf_mem_zero(&pf_sym_entry->pf_ev_ts[*cur_pf_count],
3434 			     pf_ts_idx * sizeof(qdf_time_t));
3435 	}
3436 }
3437 
3438 static QDF_STATUS
wma_wow_pagefault_parse_event(struct wlan_objmgr_psoc * psoc,void * ev,uint32_t ev_len,struct wow_pf_wakeup_ev_data * pf_sym_list)3439 wma_wow_pagefault_parse_event(struct wlan_objmgr_psoc *psoc,
3440 			      void *ev, uint32_t ev_len,
3441 			      struct wow_pf_wakeup_ev_data *pf_sym_list)
3442 {
3443 	WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *event_param = ev;
3444 	uint8_t *cur_list_count, *pf_sym_addr, buf_idx, sym_idx, i;
3445 	uint32_t packet_len, symbol, pf_sym_count;
3446 	struct wow_pf_sym tmp_pf_sym;
3447 
3448 	if (event_param->num_wow_packet_buffer <= sizeof(packet_len)) {
3449 		wma_err("Invalid wow packet buffer from FW %u",
3450 			event_param->num_wow_packet_buffer);
3451 		return QDF_STATUS_E_INVAL;
3452 	}
3453 
3454 	packet_len = *(uint32_t *)event_param->wow_packet_buffer;
3455 	if (!packet_len) {
3456 		wma_err("Wake event packet is empty");
3457 		return QDF_STATUS_E_INVAL;
3458 	}
3459 
3460 	if (packet_len >
3461 	    (event_param->num_wow_packet_buffer - sizeof(packet_len))) {
3462 		wma_err("Invalid packet_len from firmware, packet_len: %u, num_wow_packet_buffer: %u",
3463 			packet_len, event_param->num_wow_packet_buffer);
3464 		return QDF_STATUS_E_INVAL;
3465 	}
3466 
3467 	pf_sym_count = packet_len / sizeof(symbol);
3468 	/* First 4 bytes following packet len contains UUID */
3469 	pf_sym_count--;
3470 
3471 	pf_sym_list->pf_sym =
3472 		qdf_mem_malloc(pf_sym_count * sizeof(*pf_sym_list->pf_sym));
3473 	if (!pf_sym_list->pf_sym)
3474 		return QDF_STATUS_E_NOMEM;
3475 
3476 	/* First 4 bytes of buffer gives length and next 4 bytes for UUID */
3477 	pf_sym_addr = event_param->wow_packet_buffer + (sizeof(packet_len) * 2);
3478 
3479 	cur_list_count = &pf_sym_list->num_pf_syms;
3480 	for (buf_idx = 0; buf_idx < pf_sym_count; buf_idx++) {
3481 		symbol = *(uint32_t *)pf_sym_addr;
3482 
3483 		/* Ignore invalid symbols */
3484 		if (!symbol || symbol == (uint32_t)-1)
3485 			goto iter_next_sym;
3486 
3487 		for (sym_idx = 0; sym_idx < *cur_list_count; sym_idx++) {
3488 			if (pf_sym_list->pf_sym[sym_idx].symbol == symbol) {
3489 				pf_sym_list->pf_sym[sym_idx].count++;
3490 				goto iter_next_sym;
3491 			}
3492 		}
3493 
3494 		pf_sym_list->pf_sym[*cur_list_count].symbol = symbol;
3495 		pf_sym_list->pf_sym[*cur_list_count].count++;
3496 		(*cur_list_count)++;
3497 
3498 iter_next_sym:
3499 		pf_sym_addr += sizeof(symbol);
3500 	}
3501 
3502 	pf_sym_list->pending_pf_syms = *cur_list_count;
3503 
3504 	/* Reorder to prioritize syms with high frequency */
3505 	for (sym_idx = 0; sym_idx < *cur_list_count; sym_idx++) {
3506 		for (i = sym_idx + 1; i < *cur_list_count; i++) {
3507 			if (pf_sym_list->pf_sym[i].count <=
3508 			    pf_sym_list->pf_sym[sym_idx].count) {
3509 				continue;
3510 			}
3511 
3512 			tmp_pf_sym.symbol = pf_sym_list->pf_sym[sym_idx].symbol;
3513 			tmp_pf_sym.count = pf_sym_list->pf_sym[sym_idx].count;
3514 
3515 			pf_sym_list->pf_sym[sym_idx].symbol =
3516 						pf_sym_list->pf_sym[i].symbol;
3517 			pf_sym_list->pf_sym[sym_idx].count =
3518 						pf_sym_list->pf_sym[i].count;
3519 
3520 			pf_sym_list->pf_sym[i].symbol = tmp_pf_sym.symbol;
3521 			pf_sym_list->pf_sym[i].count = tmp_pf_sym.count;
3522 		}
3523 	}
3524 
3525 	return QDF_STATUS_SUCCESS;
3526 }
3527 
wma_wow_pagefault_handle_ssr_action(tp_wma_handle wma)3528 static void wma_wow_pagefault_handle_ssr_action(tp_wma_handle wma)
3529 {
3530 	QDF_STATUS status;
3531 	uint8_t *cur_count, pf_thresh;
3532 	qdf_time_t cur_time, cutoff_time;
3533 	uint32_t pf_wakeup_intv;
3534 	struct wma_pf_sym *pf_sym_entry;
3535 
3536 	cur_time = qdf_get_system_uptime();
3537 	pf_wakeup_intv =
3538 		wlan_pmo_get_interval_for_pagefault_wakeup_counts(wma->psoc);
3539 	pf_thresh = wlan_pmo_get_min_pagefault_wakeups_for_action(wma->psoc);
3540 	cutoff_time = cur_time - qdf_system_msecs_to_ticks(pf_wakeup_intv);
3541 
3542 	pf_sym_entry = &wma->wma_pf_hist.wma_pf_sym[0];
3543 	cur_count = &pf_sym_entry->pf_sym.count;
3544 	if (cutoff_time < cur_time) {
3545 		wma_wow_pagefault_flush_ageout_entries(pf_sym_entry,
3546 						       cutoff_time);
3547 	}
3548 
3549 	pf_sym_entry->pf_ev_ts[(*cur_count)++] = cur_time;
3550 	if (*cur_count < pf_thresh)
3551 		return;
3552 
3553 	/* If SSR threshold condition fails, SSR will not be triggered, so
3554 	 * save current event and flush oldest entry.
3555 	 */
3556 	status = wma_wow_pagefault_action_cb(NULL);
3557 	if (QDF_IS_STATUS_ERROR(status)) {
3558 		(*cur_count)--;
3559 		qdf_mem_copy(&pf_sym_entry->pf_ev_ts[0],
3560 			     &pf_sym_entry->pf_ev_ts[1],
3561 			     (*cur_count * sizeof(qdf_time_t)));
3562 		qdf_mem_zero(&pf_sym_entry->pf_ev_ts[*cur_count],
3563 			     sizeof(qdf_time_t));
3564 	}
3565 }
3566 
3567 static void
wma_wow_wakeup_pagefault_notify(tp_wma_handle wma,void * ev,uint32_t ev_len)3568 wma_wow_wakeup_pagefault_notify(tp_wma_handle wma, void *ev, uint32_t ev_len)
3569 {
3570 	QDF_STATUS status;
3571 	uint32_t pf_wakeup_intv;
3572 	qdf_time_t cur_time, cutoff_time;
3573 	struct wma_pf_sym *pf_sym_entry;
3574 	struct wma_pf_sym_hist *pf_sym_hist = &wma->wma_pf_hist;
3575 	struct wlan_objmgr_psoc *psoc = wma->psoc;
3576 	uint8_t pf_tbl_idx;
3577 	struct wow_pf_wakeup_ev_data pf_sym_list = {0};
3578 	struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE);
3579 
3580 	if (!mac) {
3581 		wma_debug("MAC context NULL");
3582 		return;
3583 	}
3584 
3585 	if (wlan_pmo_no_op_on_page_fault(psoc))
3586 		return;
3587 
3588 	if (wmi_get_runtime_pm_inprogress(wma->wmi_handle)) {
3589 		wma_debug("Ignore run time pm wakeup");
3590 		return;
3591 	}
3592 
3593 	if (!mac->sme.pagefault_action_cb) {
3594 		wma_debug("NULL pagefault action cb");
3595 		return;
3596 	}
3597 
3598 	if (wlan_pmo_enable_ssr_on_page_fault(psoc)) {
3599 		wma_wow_pagefault_handle_ssr_action(wma);
3600 		return;
3601 	}
3602 
3603 	cur_time = qdf_get_system_uptime();
3604 	pf_wakeup_intv =
3605 		wlan_pmo_get_interval_for_pagefault_wakeup_counts(psoc);
3606 	cutoff_time = cur_time - qdf_system_msecs_to_ticks(pf_wakeup_intv);
3607 
3608 	status = wma_wow_pagefault_parse_event(psoc, ev, ev_len, &pf_sym_list);
3609 	if (QDF_IS_STATUS_ERROR(status)) {
3610 		wma_debug("Failed during page fault payload parse");
3611 		return;
3612 	}
3613 
3614 	qdf_spinlock_acquire(&pf_sym_hist->lock);
3615 	for (pf_tbl_idx = 0; pf_tbl_idx < WLAN_WMA_MAX_PF_SYM; pf_tbl_idx++) {
3616 		pf_sym_entry = &pf_sym_hist->wma_pf_sym[pf_tbl_idx];
3617 		if (cutoff_time < cur_time) {
3618 			wma_wow_pagefault_flush_ageout_entries(pf_sym_entry,
3619 							       cutoff_time);
3620 		}
3621 
3622 		wma_wow_pagefault_process_existing_syms(wma, pf_sym_entry,
3623 							&pf_sym_list, cur_time);
3624 
3625 		if (!pf_sym_list.pending_pf_syms)
3626 			goto send_event;
3627 	}
3628 
3629 	/* Process if any new symbols are present in the event */
3630 	wma_wow_pagefault_add_new_sym_from_event(wma, &pf_sym_list, cur_time);
3631 
3632 send_event:
3633 	if (pf_sym_hist->pf_notify_buf_len) {
3634 		wma_wow_pagefault_action_cb(pf_sym_hist->pf_notify_buf_ptr);
3635 		pf_sym_hist->pf_notify_buf_len = 0;
3636 	}
3637 
3638 	qdf_spinlock_release(&pf_sym_hist->lock);
3639 
3640 	qdf_mem_free(pf_sym_list.pf_sym);
3641 	pf_sym_list.pf_sym = NULL;
3642 }
3643 
3644 /**
3645  * wma_wow_wakeup_host_event() - wakeup host event handler
3646  * @handle: wma handle
3647  * @event: event data
3648  * @len: buffer length
3649  *
3650  * Handler to catch wow wakeup host event. This event will have
3651  * reason why the firmware has woken the host.
3652  *
3653  * Return: Errno
3654  */
wma_wow_wakeup_host_event(void * handle,uint8_t * event,uint32_t len)3655 int wma_wow_wakeup_host_event(void *handle, uint8_t *event, uint32_t len)
3656 {
3657 	int errno;
3658 	t_wma_handle *wma = handle;
3659 	WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *event_param;
3660 	WOW_EVENT_INFO_fixed_param *wake_info;
3661 
3662 	event_param = (WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *)event;
3663 	if (!event_param) {
3664 		wma_err("Wake event data is null");
3665 		return -EINVAL;
3666 	}
3667 
3668 	wake_info = event_param->fixed_param;
3669 
3670 	if (wake_info->vdev_id >= wma->max_bssid) {
3671 		wma_err("received invalid vdev_id %d", wake_info->vdev_id);
3672 		return -EINVAL;
3673 	}
3674 
3675 	wma_wake_event_log_reason(wma, wake_info);
3676 	if (wake_info->wake_reason == WOW_REASON_PAGE_FAULT)
3677 		wma_wow_wakeup_pagefault_notify(wma, event, len);
3678 
3679 	if (wake_info->wake_reason == WOW_REASON_LOCAL_DATA_UC_DROP)
3680 		hif_rtpm_set_autosuspend_delay(WOW_LARGE_RX_RTPM_DELAY);
3681 
3682 	ucfg_pmo_psoc_wakeup_host_event_received(wma->psoc);
3683 
3684 	wma_print_wow_stats(wma, wake_info);
3685 	/* split based on payload type */
3686 	if (is_piggybacked_event(wake_info->wake_reason))
3687 		errno = wma_wake_event_piggybacked(wma, event_param, len);
3688 	else if (event_param->wow_packet_buffer)
3689 		errno = wma_wake_event_packet(wma, event_param, len);
3690 	else
3691 		errno = wma_wake_event_no_payload(wma, event_param, len);
3692 
3693 	wma_inc_wow_stats(wma, wake_info);
3694 	wma_print_wow_stats(wma, wake_info);
3695 	wma_acquire_wow_wakelock(wma, wake_info->wake_reason);
3696 
3697 	return errno;
3698 }
3699 
3700 #ifdef FEATURE_WLAN_D0WOW
3701 /**
3702  * wma_d0_wow_disable_ack_event() - wakeup host event handler
3703  * @handle: wma handle
3704  * @event: event data
3705  * @len: buffer length
3706  *
3707  * Handler to catch D0-WOW disable ACK event.  This event will have
3708  * reason why the firmware has woken the host.
3709  * This is for backward compatible with cld2.0.
3710  *
3711  * Return: 0 for success or error
3712  */
wma_d0_wow_disable_ack_event(void * handle,uint8_t * event,uint32_t len)3713 int wma_d0_wow_disable_ack_event(void *handle, uint8_t *event, uint32_t len)
3714 {
3715 	tp_wma_handle wma = (tp_wma_handle)handle;
3716 	WMI_D0_WOW_DISABLE_ACK_EVENTID_param_tlvs *param_buf;
3717 	wmi_d0_wow_disable_ack_event_fixed_param *resp_data;
3718 
3719 	param_buf = (WMI_D0_WOW_DISABLE_ACK_EVENTID_param_tlvs *)event;
3720 	if (!param_buf) {
3721 		wma_err("Invalid D0-WOW disable ACK event buffer!");
3722 		return -EINVAL;
3723 	}
3724 
3725 	resp_data = param_buf->fixed_param;
3726 
3727 	ucfg_pmo_psoc_wakeup_host_event_received(wma->psoc);
3728 
3729 	wma_debug("Received D0-WOW disable ACK");
3730 
3731 	return 0;
3732 }
3733 #else
wma_d0_wow_disable_ack_event(void * handle,uint8_t * event,uint32_t len)3734 int wma_d0_wow_disable_ack_event(void *handle, uint8_t *event, uint32_t len)
3735 {
3736 	return 0;
3737 }
3738 #endif
3739 
3740 /**
3741  * wma_pdev_resume_event_handler() - PDEV resume event handler
3742  * @handle: wma handle
3743  * @event: event data
3744  * @len: buffer length
3745  *
3746  * Return: 0 for success or error
3747  */
wma_pdev_resume_event_handler(void * handle,uint8_t * event,uint32_t len)3748 int wma_pdev_resume_event_handler(void *handle, uint8_t *event, uint32_t len)
3749 {
3750 	tp_wma_handle wma = (tp_wma_handle) handle;
3751 
3752 	wma_nofl_info("Received PDEV resume event");
3753 
3754 	ucfg_pmo_psoc_wakeup_host_event_received(wma->psoc);
3755 
3756 	return 0;
3757 }
3758 
3759 /**
3760  * wma_del_ts_req() - send DELTS request to fw
3761  * @wma: wma handle
3762  * @msg: delts params
3763  *
3764  * Return: none
3765  */
wma_del_ts_req(tp_wma_handle wma,struct del_ts_params * msg)3766 void wma_del_ts_req(tp_wma_handle wma, struct del_ts_params *msg)
3767 {
3768 	if (!wma_is_vdev_valid(msg->sessionId)) {
3769 		wma_err("vdev id:%d is not active ", msg->sessionId);
3770 		qdf_mem_free(msg);
3771 		return;
3772 	}
3773 	if (wmi_unified_del_ts_cmd(wma->wmi_handle,
3774 				 msg->sessionId,
3775 				 TID_TO_WME_AC(msg->userPrio))) {
3776 		wma_alert("Failed to send vdev DELTS command");
3777 	}
3778 
3779 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
3780 	if (msg->setRICparams == true)
3781 		wma_set_ric_req(wma, msg, false);
3782 #endif /* WLAN_FEATURE_ROAM_OFFLOAD */
3783 	qdf_mem_free(msg);
3784 }
3785 
wma_aggr_qos_req(tp_wma_handle wma,struct aggr_add_ts_param * aggr_qos_rsp_msg)3786 void wma_aggr_qos_req(tp_wma_handle wma,
3787 		      struct aggr_add_ts_param *aggr_qos_rsp_msg)
3788 {
3789 	if (!wma_is_vdev_valid(aggr_qos_rsp_msg->vdev_id)) {
3790 		wma_err("vdev id:%d is not active ",
3791 			 aggr_qos_rsp_msg->vdev_id);
3792 		return;
3793 	}
3794 	wmi_unified_aggr_qos_cmd(wma->wmi_handle, aggr_qos_rsp_msg);
3795 	/* send response to upper layers from here only. */
3796 	wma_send_msg_high_priority(wma, WMA_AGGR_QOS_RSP, aggr_qos_rsp_msg, 0);
3797 }
3798 
3799 #ifdef FEATURE_WLAN_ESE
3800 /**
3801  * wma_set_tsm_interval() - Set TSM interval
3802  * @req: pointer to ADDTS request
3803  *
3804  * Return: QDF_STATUS_E_FAILURE or QDF_STATUS_SUCCESS
3805  */
wma_set_tsm_interval(struct add_ts_param * req)3806 static QDF_STATUS wma_set_tsm_interval(struct add_ts_param *req)
3807 {
3808 	/*
3809 	 * msmt_interval is in unit called TU (1 TU = 1024 us)
3810 	 * max value of msmt_interval cannot make resulting
3811 	 * interval_milliseconds overflow 32 bit
3812 	 *
3813 	 */
3814 	uint32_t interval_milliseconds;
3815 
3816 	interval_milliseconds = (req->tsm_interval * 1024) / 1000;
3817 
3818 	cdp_tx_set_compute_interval(cds_get_context(QDF_MODULE_ID_SOC),
3819 			WMI_PDEV_ID_SOC,
3820 			interval_milliseconds);
3821 	return QDF_STATUS_SUCCESS;
3822 }
3823 #else
wma_set_tsm_interval(struct add_ts_param * req)3824 static inline QDF_STATUS wma_set_tsm_interval(struct add_ts_param *req)
3825 {
3826 	return QDF_STATUS_SUCCESS;
3827 }
3828 #endif /* FEATURE_WLAN_ESE */
3829 
3830 /**
3831  * wma_add_ts_req() - send ADDTS request to fw
3832  * @wma: wma handle
3833  * @msg: ADDTS params
3834  *
3835  * Return: none
3836  */
wma_add_ts_req(tp_wma_handle wma,struct add_ts_param * msg)3837 void wma_add_ts_req(tp_wma_handle wma, struct add_ts_param *msg)
3838 {
3839 	struct add_ts_param cmd = {0};
3840 
3841 	msg->status = QDF_STATUS_SUCCESS;
3842 	if (wma_set_tsm_interval(msg) == QDF_STATUS_SUCCESS) {
3843 
3844 		cmd.vdev_id = msg->vdev_id;
3845 		cmd.tspec.tsinfo.traffic.userPrio =
3846 			TID_TO_WME_AC(msg->tspec.tsinfo.traffic.userPrio);
3847 		cmd.tspec.mediumTime = msg->tspec.mediumTime;
3848 		if (wmi_unified_add_ts_cmd(wma->wmi_handle, &cmd))
3849 			msg->status = QDF_STATUS_E_FAILURE;
3850 
3851 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
3852 		if (msg->set_ric_params)
3853 			wma_set_ric_req(wma, msg, true);
3854 #endif /* WLAN_FEATURE_ROAM_OFFLOAD */
3855 
3856 	}
3857 	wma_send_msg_high_priority(wma, WMA_ADD_TS_RSP, msg, 0);
3858 }
3859 
3860 #ifdef FEATURE_WLAN_ESE
3861 
3862 #define TSM_DELAY_HISTROGRAM_BINS 4
3863 /**
3864  * wma_process_tsm_stats_req() - process tsm stats request
3865  * @wma_handler - handle to wma
3866  * @pTsmStatsMsg - TSM stats struct that needs to be populated and
3867  *         passed in message.
3868  *
3869  * A parallel function to WMA_ProcessTsmStatsReq for pronto. This
3870  * function fetches stats from data path APIs and post
3871  * WMA_TSM_STATS_RSP msg back to LIM.
3872  *
3873  * Return: QDF status
3874  */
wma_process_tsm_stats_req(tp_wma_handle wma_handler,void * pTsmStatsMsg)3875 QDF_STATUS wma_process_tsm_stats_req(tp_wma_handle wma_handler,
3876 				     void *pTsmStatsMsg)
3877 {
3878 	uint8_t counter;
3879 	uint32_t queue_delay_microsec = 0;
3880 	uint32_t tx_delay_microsec = 0;
3881 	uint16_t packet_count = 0;
3882 	uint16_t packet_loss_count = 0;
3883 	tpAniTrafStrmMetrics pTsmMetric = NULL;
3884 	tpAniGetTsmStatsReq pStats = (tpAniGetTsmStatsReq) pTsmStatsMsg;
3885 	tpAniGetTsmStatsRsp pTsmRspParams = NULL;
3886 	int tid = pStats->tid;
3887 	/*
3888 	 * The number of histrogram bin report by data path api are different
3889 	 * than required by TSM, hence different (6) size array used
3890 	 */
3891 	uint16_t bin_values[QCA_TX_DELAY_HIST_REPORT_BINS] = { 0, };
3892 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3893 
3894 	/* get required values from data path APIs */
3895 	cdp_tx_delay(soc,
3896 		WMI_PDEV_ID_SOC,
3897 		&queue_delay_microsec,
3898 		&tx_delay_microsec, tid);
3899 	cdp_tx_delay_hist(soc,
3900 		WMI_PDEV_ID_SOC,
3901 		bin_values, tid);
3902 	cdp_tx_packet_count(soc,
3903 		WMI_PDEV_ID_SOC,
3904 		&packet_count,
3905 		&packet_loss_count, tid);
3906 
3907 	pTsmRspParams = qdf_mem_malloc(sizeof(*pTsmRspParams));
3908 	if (!pTsmRspParams) {
3909 		QDF_ASSERT(0);
3910 		qdf_mem_free(pTsmStatsMsg);
3911 		return QDF_STATUS_E_NOMEM;
3912 	}
3913 
3914 	qdf_copy_macaddr(&pTsmRspParams->bssid, &pStats->bssId);
3915 	pTsmRspParams->rc = QDF_STATUS_E_FAILURE;
3916 	pTsmRspParams->tsmStatsReq = pStats;
3917 	pTsmMetric = &pTsmRspParams->tsmMetrics;
3918 	/* populate pTsmMetric */
3919 	pTsmMetric->UplinkPktQueueDly = queue_delay_microsec;
3920 	/* store only required number of bin values */
3921 	for (counter = 0; counter < TSM_DELAY_HISTROGRAM_BINS; counter++) {
3922 		pTsmMetric->UplinkPktQueueDlyHist[counter] =
3923 			bin_values[counter];
3924 	}
3925 	pTsmMetric->UplinkPktTxDly = tx_delay_microsec;
3926 	pTsmMetric->UplinkPktLoss = packet_loss_count;
3927 	pTsmMetric->UplinkPktCount = packet_count;
3928 
3929 	/*
3930 	 * No need to populate roaming delay and roaming count as they are
3931 	 * being populated just before sending IAPP frame out
3932 	 */
3933 	/* post this message to LIM/PE */
3934 	wma_send_msg(wma_handler, WMA_TSM_STATS_RSP, (void *)pTsmRspParams, 0);
3935 	return QDF_STATUS_SUCCESS;
3936 }
3937 
3938 #endif /* FEATURE_WLAN_ESE */
3939 
3940 /**
3941  * wma_process_mcbc_set_filter_req() - process mcbc set filter request
3942  * @wma_handle: wma handle
3943  * @mcbc_param: mcbc params
3944  *
3945  * Return: QDF status
3946  */
wma_process_mcbc_set_filter_req(tp_wma_handle wma_handle,tSirRcvFltMcAddrList * mcbc_param)3947 QDF_STATUS wma_process_mcbc_set_filter_req(tp_wma_handle wma_handle,
3948 					   tSirRcvFltMcAddrList *mcbc_param)
3949 {
3950 	return QDF_STATUS_SUCCESS;
3951 }
3952 
3953 /**
3954  * wma_process_add_periodic_tx_ptrn_ind() - add periodic tx pattern
3955  * @handle: wma handle
3956  * @pattern: tx pattern params
3957  *
3958  * Return: QDF status
3959  */
wma_process_add_periodic_tx_ptrn_ind(WMA_HANDLE handle,tSirAddPeriodicTxPtrn * pattern)3960 QDF_STATUS wma_process_add_periodic_tx_ptrn_ind(WMA_HANDLE handle,
3961 						tSirAddPeriodicTxPtrn *pattern)
3962 {
3963 	tp_wma_handle wma_handle = (tp_wma_handle) handle;
3964 	struct periodic_tx_pattern *params_ptr;
3965 	uint8_t vdev_id;
3966 	QDF_STATUS status;
3967 	struct wmi_unified *wmi_handle;
3968 
3969 	if (wma_validate_handle(wma_handle))
3970 		return QDF_STATUS_E_INVAL;
3971 
3972 	wmi_handle = wma_handle->wmi_handle;
3973 	if (wmi_validate_handle(wmi_handle))
3974 		return QDF_STATUS_E_INVAL;
3975 
3976 	if (wma_find_vdev_id_by_addr(wma_handle,
3977 				     pattern->mac_address.bytes,
3978 				     &vdev_id)) {
3979 		wma_err("Failed to find vdev id for "QDF_MAC_ADDR_FMT,
3980 			 QDF_MAC_ADDR_REF(pattern->mac_address.bytes));
3981 		return QDF_STATUS_E_INVAL;
3982 	}
3983 
3984 	params_ptr = qdf_mem_malloc(sizeof(*params_ptr));
3985 	if (!params_ptr)
3986 		return QDF_STATUS_E_NOMEM;
3987 
3988 	params_ptr->ucPtrnId = pattern->ucPtrnId;
3989 	params_ptr->ucPtrnSize = pattern->ucPtrnSize;
3990 	params_ptr->usPtrnIntervalMs = pattern->usPtrnIntervalMs;
3991 	qdf_mem_copy(&params_ptr->mac_address, &pattern->mac_address,
3992 		     sizeof(struct qdf_mac_addr));
3993 	qdf_mem_copy(params_ptr->ucPattern, pattern->ucPattern,
3994 		     params_ptr->ucPtrnSize);
3995 
3996 	status = wmi_unified_process_add_periodic_tx_ptrn_cmd(
3997 				wmi_handle, params_ptr, vdev_id);
3998 
3999 	qdf_mem_free(params_ptr);
4000 	return status;
4001 }
4002 
4003 /**
4004  * wma_process_del_periodic_tx_ptrn_ind - del periodic tx ptrn
4005  * @handle: wma handle
4006  * @pDelPeriodicTxPtrnParams: tx ptrn params
4007  *
4008  * Return: QDF status
4009  */
wma_process_del_periodic_tx_ptrn_ind(WMA_HANDLE handle,tSirDelPeriodicTxPtrn * pDelPeriodicTxPtrnParams)4010 QDF_STATUS wma_process_del_periodic_tx_ptrn_ind(WMA_HANDLE handle,
4011 						tSirDelPeriodicTxPtrn *
4012 						pDelPeriodicTxPtrnParams)
4013 {
4014 	tp_wma_handle wma_handle = (tp_wma_handle) handle;
4015 	uint8_t vdev_id;
4016 	struct wmi_unified *wmi_handle;
4017 
4018 	if (wma_validate_handle(wma_handle))
4019 		return QDF_STATUS_E_INVAL;
4020 
4021 	wmi_handle = wma_handle->wmi_handle;
4022 	if (wmi_validate_handle(wmi_handle))
4023 		return QDF_STATUS_E_INVAL;
4024 
4025 	if (wma_find_vdev_id_by_addr(
4026 			wma_handle,
4027 			pDelPeriodicTxPtrnParams->mac_address.bytes,
4028 			&vdev_id)) {
4029 		wma_err("Failed to find vdev id for "QDF_MAC_ADDR_FMT,
4030 			QDF_MAC_ADDR_REF(pDelPeriodicTxPtrnParams->mac_address.bytes));
4031 		return QDF_STATUS_E_INVAL;
4032 	}
4033 
4034 	return wmi_unified_process_del_periodic_tx_ptrn_cmd(
4035 				wmi_handle, vdev_id,
4036 				pDelPeriodicTxPtrnParams->ucPtrnId);
4037 }
4038 
4039 #ifdef WLAN_FEATURE_STATS_EXT
4040 #ifdef WLAN_FEATURE_11BE_MLO
4041 /*
4042  * wma_stats_ext_req_vdev_id_bitmap() -API to calculate connected links bitmap
4043  * in case of MLO.
4044  * psoc: psoc common object
4045  * vdev_id: vdev_id for the stats ext request
4046  * bitmap: connected links bitmap
4047  *
4048  * Return None
4049  */
wma_stats_ext_req_vdev_id_bitmap(struct wlan_objmgr_psoc * psoc,uint32_t vdev_id,uint32_t * bitmap)4050 static void wma_stats_ext_req_vdev_id_bitmap(struct wlan_objmgr_psoc *psoc,
4051 					     uint32_t vdev_id, uint32_t *bitmap)
4052 {
4053 	struct wlan_objmgr_vdev *vdev, *link_vdev;
4054 	struct wlan_mlo_dev_context *mlo_dev_ctx;
4055 	uint32_t i, connected_links_bitmap = 0;
4056 	uint8_t connected_vdev_id;
4057 
4058 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
4059 						    WLAN_LEGACY_WMA_ID);
4060 	if (!vdev) {
4061 		wma_err("vdev object is NULL for vdev_id %d", vdev_id);
4062 		return;
4063 	}
4064 
4065 	mlo_dev_ctx = vdev->mlo_dev_ctx;
4066 	if (!mlo_dev_ctx)
4067 		goto end;
4068 
4069 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
4070 		link_vdev = mlo_dev_ctx->wlan_vdev_list[i];
4071 		if (!link_vdev)
4072 			continue;
4073 
4074 		connected_vdev_id = wlan_vdev_get_id(link_vdev);
4075 		if (wlan_cm_is_vdev_connected(link_vdev))
4076 			connected_links_bitmap |= BIT(connected_vdev_id);
4077 	}
4078 
4079 	wma_debug("mlo connected links bitmap[0x%x]", connected_links_bitmap);
4080 	*bitmap = connected_links_bitmap;
4081 
4082 end:
4083 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_WMA_ID);
4084 }
4085 #else
wma_stats_ext_req_vdev_id_bitmap(struct wlan_objmgr_psoc * psoc,uint32_t vdev_id,uint32_t * bitmap)4086 static void wma_stats_ext_req_vdev_id_bitmap(struct wlan_objmgr_psoc *psoc,
4087 					     uint32_t vdev_id, uint32_t *bitmap)
4088 {
4089 	*bitmap = 0;
4090 }
4091 #endif
4092 
wma_stats_ext_req(void * wma_ptr,tpStatsExtRequest preq)4093 QDF_STATUS wma_stats_ext_req(void *wma_ptr, tpStatsExtRequest preq)
4094 {
4095 	tp_wma_handle wma = (tp_wma_handle) wma_ptr;
4096 	struct stats_ext_params *params;
4097 	size_t params_len;
4098 	QDF_STATUS status;
4099 
4100 	if (!wma) {
4101 		wma_err("wma handle is NULL");
4102 		return QDF_STATUS_E_FAILURE;
4103 	}
4104 
4105 	params_len = sizeof(*params) + preq->request_data_len;
4106 	params = qdf_mem_malloc(params_len);
4107 	if (!params)
4108 		return QDF_STATUS_E_NOMEM;
4109 
4110 	params->vdev_id = preq->vdev_id;
4111 	params->request_data_len = preq->request_data_len;
4112 	if (preq->request_data_len > 0)
4113 		qdf_mem_copy(params->request_data, preq->request_data,
4114 			     params->request_data_len);
4115 
4116 	wma_stats_ext_req_vdev_id_bitmap(wma->psoc, params->vdev_id,
4117 					 &params->vdev_id_bitmap);
4118 
4119 	status = wmi_unified_stats_ext_req_cmd(wma->wmi_handle, params);
4120 	qdf_mem_free(params);
4121 
4122 	return status;
4123 }
4124 
4125 #endif /* WLAN_FEATURE_STATS_EXT */
4126 
4127 #ifdef WLAN_FEATURE_EXTWOW_SUPPORT
4128 /**
4129  * wma_send_status_of_ext_wow() - send ext wow status to SME
4130  * @wma: wma handle
4131  * @status: status
4132  *
4133  * Return: none
4134  */
wma_send_status_of_ext_wow(tp_wma_handle wma,bool status)4135 static void wma_send_status_of_ext_wow(tp_wma_handle wma, bool status)
4136 {
4137 	tSirReadyToExtWoWInd *ready_to_extwow;
4138 	QDF_STATUS vstatus;
4139 	struct scheduler_msg message = {0};
4140 	uint8_t len;
4141 
4142 	wma_debug("Posting ready to suspend indication to umac");
4143 
4144 	len = sizeof(tSirReadyToExtWoWInd);
4145 	ready_to_extwow = qdf_mem_malloc(len);
4146 	if (!ready_to_extwow)
4147 		return;
4148 
4149 	ready_to_extwow->mesgType = eWNI_SME_READY_TO_EXTWOW_IND;
4150 	ready_to_extwow->mesgLen = len;
4151 	ready_to_extwow->status = status;
4152 
4153 	message.type = eWNI_SME_READY_TO_EXTWOW_IND;
4154 	message.bodyptr = (void *)ready_to_extwow;
4155 	message.bodyval = 0;
4156 
4157 	vstatus = scheduler_post_message(QDF_MODULE_ID_WMA,
4158 					 QDF_MODULE_ID_SME,
4159 					 QDF_MODULE_ID_SME, &message);
4160 	if (vstatus != QDF_STATUS_SUCCESS)
4161 		qdf_mem_free(ready_to_extwow);
4162 }
4163 
4164 /**
4165  * wma_enable_ext_wow() - enable ext wow in fw
4166  * @wma: wma handle
4167  * @params: ext wow params
4168  *
4169  * Return:0 for success or error code
4170  */
wma_enable_ext_wow(tp_wma_handle wma,tpSirExtWoWParams params)4171 QDF_STATUS wma_enable_ext_wow(tp_wma_handle wma, tpSirExtWoWParams params)
4172 {
4173 	struct ext_wow_params wow_params = {0};
4174 	QDF_STATUS status;
4175 
4176 	if (!wma) {
4177 		wma_err("wma handle is NULL");
4178 		return QDF_STATUS_E_FAILURE;
4179 	}
4180 
4181 	wow_params.vdev_id = params->vdev_id;
4182 	wow_params.type = (enum wmi_ext_wow_type) params->type;
4183 	wow_params.wakeup_pin_num = params->wakeup_pin_num;
4184 
4185 	status = wmi_unified_enable_ext_wow_cmd(wma->wmi_handle,
4186 				&wow_params);
4187 	if (QDF_IS_STATUS_ERROR(status))
4188 		return status;
4189 
4190 	wma_send_status_of_ext_wow(wma, true);
4191 	return status;
4192 
4193 }
4194 
4195 /**
4196  * wma_set_app_type1_params_in_fw() - set app type1 params in fw
4197  * @wma: wma handle
4198  * @appType1Params: app type1 params
4199  *
4200  * Return: QDF status
4201  */
wma_set_app_type1_params_in_fw(tp_wma_handle wma,tpSirAppType1Params appType1Params)4202 int wma_set_app_type1_params_in_fw(tp_wma_handle wma,
4203 				   tpSirAppType1Params appType1Params)
4204 {
4205 	int ret;
4206 
4207 	ret = wmi_unified_app_type1_params_in_fw_cmd(wma->wmi_handle,
4208 				   (struct app_type1_params *)appType1Params);
4209 	if (ret) {
4210 		wma_err("Failed to set APP TYPE1 PARAMS");
4211 		return QDF_STATUS_E_FAILURE;
4212 	}
4213 
4214 	return QDF_STATUS_SUCCESS;
4215 }
4216 
4217 /**
4218  * wma_set_app_type2_params_in_fw() - set app type2 params in fw
4219  * @wma: wma handle
4220  * @appType2Params: app type2 params
4221  *
4222  * Return: QDF status
4223  */
wma_set_app_type2_params_in_fw(tp_wma_handle wma,tpSirAppType2Params appType2Params)4224 QDF_STATUS wma_set_app_type2_params_in_fw(tp_wma_handle wma,
4225 					  tpSirAppType2Params appType2Params)
4226 {
4227 	struct app_type2_params params = {0};
4228 
4229 	if (!wma) {
4230 		wma_err("wma handle is NULL");
4231 		return QDF_STATUS_E_FAILURE;
4232 	}
4233 
4234 	params.vdev_id = appType2Params->vdev_id;
4235 	params.rc4_key_len = appType2Params->rc4_key_len;
4236 	qdf_mem_copy(params.rc4_key, appType2Params->rc4_key, 16);
4237 	params.ip_id = appType2Params->ip_id;
4238 	params.ip_device_ip = appType2Params->ip_device_ip;
4239 	params.ip_server_ip = appType2Params->ip_server_ip;
4240 	params.tcp_src_port = appType2Params->tcp_src_port;
4241 	params.tcp_dst_port = appType2Params->tcp_dst_port;
4242 	params.tcp_seq = appType2Params->tcp_seq;
4243 	params.tcp_ack_seq = appType2Params->tcp_ack_seq;
4244 	params.keepalive_init = appType2Params->keepalive_init;
4245 	params.keepalive_min = appType2Params->keepalive_min;
4246 	params.keepalive_max = appType2Params->keepalive_max;
4247 	params.keepalive_inc = appType2Params->keepalive_inc;
4248 	params.tcp_tx_timeout_val = appType2Params->tcp_tx_timeout_val;
4249 	params.tcp_rx_timeout_val = appType2Params->tcp_rx_timeout_val;
4250 	qdf_mem_copy(&params.gateway_mac, &appType2Params->gateway_mac,
4251 			sizeof(struct qdf_mac_addr));
4252 
4253 	return wmi_unified_set_app_type2_params_in_fw_cmd(wma->wmi_handle,
4254 							&params);
4255 }
4256 #endif /* WLAN_FEATURE_EXTWOW_SUPPORT */
4257 
4258 #ifdef FEATURE_WLAN_AUTO_SHUTDOWN
4259 /**
4260  * wma_auto_shutdown_event_handler() - process auto shutdown timer trigger
4261  * @handle: wma handle
4262  * @event: event buffer
4263  * @len: buffer length
4264  *
4265  * Return: 0 for success or error code
4266  */
wma_auto_shutdown_event_handler(void * handle,uint8_t * event,uint32_t len)4267 int wma_auto_shutdown_event_handler(void *handle, uint8_t *event,
4268 				    uint32_t len)
4269 {
4270 	wmi_host_auto_shutdown_event_fixed_param *wmi_auto_sh_evt;
4271 	WMI_HOST_AUTO_SHUTDOWN_EVENTID_param_tlvs *param_buf =
4272 		(WMI_HOST_AUTO_SHUTDOWN_EVENTID_param_tlvs *)
4273 		event;
4274 
4275 	if (!param_buf || !param_buf->fixed_param) {
4276 		wma_err("Invalid Auto shutdown timer evt");
4277 		return -EINVAL;
4278 	}
4279 
4280 	wmi_auto_sh_evt = param_buf->fixed_param;
4281 
4282 	if (wmi_auto_sh_evt->shutdown_reason
4283 	    != WMI_HOST_AUTO_SHUTDOWN_REASON_TIMER_EXPIRY) {
4284 		wma_err("Invalid Auto shutdown timer evt");
4285 		return -EINVAL;
4286 	}
4287 
4288 	wma_debug("Auto Shutdown Evt: %d", wmi_auto_sh_evt->shutdown_reason);
4289 	return wma_wake_reason_auto_shutdown();
4290 }
4291 
4292 QDF_STATUS
wma_set_auto_shutdown_timer_req(tp_wma_handle wma_handle,struct auto_shutdown_cmd * auto_sh_cmd)4293 wma_set_auto_shutdown_timer_req(tp_wma_handle wma_handle,
4294 				struct auto_shutdown_cmd *auto_sh_cmd)
4295 {
4296 	if (!auto_sh_cmd) {
4297 		wma_err("Invalid Autoshutdown cfg cmd");
4298 		return QDF_STATUS_E_FAILURE;
4299 	}
4300 
4301 	return wmi_unified_set_auto_shutdown_timer_cmd(wma_handle->wmi_handle,
4302 						       auto_sh_cmd->timer_val);
4303 }
4304 #endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
4305 
4306 #ifdef DHCP_SERVER_OFFLOAD
4307 QDF_STATUS
wma_process_dhcpserver_offload(tp_wma_handle wma_handle,struct dhcp_offload_info_params * params)4308 wma_process_dhcpserver_offload(tp_wma_handle wma_handle,
4309 			       struct dhcp_offload_info_params *params)
4310 {
4311 	QDF_STATUS status;
4312 	wmi_unified_t wmi_handle;
4313 
4314 	if (!wma_handle) {
4315 		wma_err("wma handle is NULL");
4316 		return QDF_STATUS_E_FAILURE;
4317 	}
4318 
4319 	wmi_handle = wma_handle->wmi_handle;
4320 	status = wmi_unified_process_dhcpserver_offload_cmd(wmi_handle,
4321 							    params);
4322 	wma_debug("Set dhcp server offload to vdev %d status %d",
4323 		 params->vdev_id, status);
4324 
4325 	return status;
4326 }
4327 #endif /* DHCP_SERVER_OFFLOAD */
4328 
4329 #ifdef WLAN_FEATURE_GPIO_LED_FLASHING
4330 /**
4331  * wma_set_led_flashing() - set led flashing in fw
4332  * @wma_handle: wma handle
4333  * @flashing: flashing request
4334  *
4335  * Return: QDF status
4336  */
wma_set_led_flashing(tp_wma_handle wma_handle,struct flashing_req_params * flashing)4337 QDF_STATUS wma_set_led_flashing(tp_wma_handle wma_handle,
4338 				struct flashing_req_params *flashing)
4339 {
4340 	QDF_STATUS status;
4341 	struct wmi_unified *wmi_handle;
4342 
4343 	if (wma_validate_handle(wma_handle))
4344 		return QDF_STATUS_E_INVAL;
4345 
4346 	wmi_handle = wma_handle->wmi_handle;
4347 	if (wmi_validate_handle(wmi_handle))
4348 		return QDF_STATUS_E_INVAL;
4349 
4350 	if (!flashing) {
4351 		wma_err("invalid parameter: flashing");
4352 		return QDF_STATUS_E_INVAL;
4353 	}
4354 	status = wmi_unified_set_led_flashing_cmd(wmi_handle, flashing);
4355 	return status;
4356 }
4357 #endif /* WLAN_FEATURE_GPIO_LED_FLASHING */
4358 
wma_sar_rsp_evt_handler(ol_scn_t handle,uint8_t * event,uint32_t len)4359 int wma_sar_rsp_evt_handler(ol_scn_t handle, uint8_t *event, uint32_t len)
4360 {
4361 	tp_wma_handle wma_handle;
4362 	wmi_unified_t wmi_handle;
4363 	QDF_STATUS status;
4364 
4365 	wma_debug("handle:%pK event:%pK len:%u", handle, event, len);
4366 
4367 	wma_handle = handle;
4368 	if (wma_validate_handle(wma_handle))
4369 		return QDF_STATUS_E_INVAL;
4370 
4371 	wmi_handle = wma_handle->wmi_handle;
4372 	if (wmi_validate_handle(wmi_handle))
4373 		return QDF_STATUS_E_INVAL;
4374 
4375 	status = wmi_unified_extract_sar2_result_event(wmi_handle,
4376 						       event, len);
4377 	if (QDF_IS_STATUS_ERROR(status)) {
4378 		wma_err("Event extract failure: %d", status);
4379 		return -EINVAL;
4380 	}
4381 
4382 	return 0;
4383 }
4384 
4385 #ifdef FEATURE_WLAN_CH_AVOID
4386 /**
4387  * wma_process_ch_avoid_update_req() - handles channel avoid update request
4388  * @wma_handle: wma handle
4389  * @ch_avoid_update_req: channel avoid update params
4390  *
4391  * Return: QDF status
4392  */
wma_process_ch_avoid_update_req(tp_wma_handle wma_handle,tSirChAvoidUpdateReq * ch_avoid_update_req)4393 QDF_STATUS wma_process_ch_avoid_update_req(tp_wma_handle wma_handle,
4394 					   tSirChAvoidUpdateReq *
4395 					   ch_avoid_update_req)
4396 {
4397 	QDF_STATUS status;
4398 	struct wmi_unified *wmi_handle;
4399 
4400 	if (wma_validate_handle(wma_handle))
4401 		return QDF_STATUS_E_FAILURE;
4402 
4403 	wmi_handle = wma_handle->wmi_handle;
4404 	if (wmi_validate_handle(wmi_handle))
4405 		return QDF_STATUS_E_FAILURE;
4406 
4407 	if (!ch_avoid_update_req) {
4408 		wma_err("ch_avoid_update_req is NULL");
4409 		return QDF_STATUS_E_FAILURE;
4410 	}
4411 
4412 	wma_debug("WMA --> WMI_CHAN_AVOID_UPDATE");
4413 
4414 	status = wmi_unified_process_ch_avoid_update_cmd(wmi_handle);
4415 	if (QDF_IS_STATUS_ERROR(status))
4416 		return status;
4417 
4418 	wma_debug("WMA --> WMI_CHAN_AVOID_UPDATE sent through WMI");
4419 	return status;
4420 }
4421 #endif
4422 
wma_send_regdomain_info_to_fw(uint32_t reg_dmn,uint16_t regdmn2G,uint16_t regdmn5G,uint8_t ctl2G,uint8_t ctl5G)4423 void wma_send_regdomain_info_to_fw(uint32_t reg_dmn, uint16_t regdmn2G,
4424 				   uint16_t regdmn5G, uint8_t ctl2G,
4425 				   uint8_t ctl5G)
4426 {
4427 	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
4428 	int32_t cck_mask_val = 0;
4429 	struct pdev_params pdev_param = {0};
4430 	QDF_STATUS ret = QDF_STATUS_SUCCESS;
4431 	QDF_STATUS status = QDF_STATUS_SUCCESS;
4432 
4433 	wma_debug("reg_dmn: %d regdmn2g: %d regdmn5g :%d ctl2g: %d ctl5g: %d",
4434 		 reg_dmn, regdmn2G, regdmn5G, ctl2G, ctl5G);
4435 
4436 	if (!wma)
4437 		return;
4438 
4439 	status = wmi_unified_send_regdomain_info_to_fw_cmd(wma->wmi_handle,
4440 			reg_dmn, regdmn2G, regdmn5G, ctl2G, ctl5G);
4441 	if (status == QDF_STATUS_E_NOMEM)
4442 		return;
4443 
4444 	if ((((reg_dmn & ~CTRY_FLAG) == CTRY_JAPAN15) ||
4445 	     ((reg_dmn & ~CTRY_FLAG) == CTRY_KOREA_ROC)) &&
4446 	    (true == wma->tx_chain_mask_cck))
4447 		cck_mask_val = 1;
4448 
4449 	cck_mask_val |= (wma->self_gen_frm_pwr << 16);
4450 	pdev_param.param_id = wmi_pdev_param_tx_chain_mask_cck;
4451 	pdev_param.param_value = cck_mask_val;
4452 	ret = wmi_unified_pdev_param_send(wma->wmi_handle,
4453 					 &pdev_param,
4454 					 WMA_WILDCARD_PDEV_ID);
4455 
4456 	if (QDF_IS_STATUS_ERROR(ret))
4457 		wma_err("failed to set PDEV tx_chain_mask_cck %d", ret);
4458 }
4459 
4460 #ifdef FEATURE_WLAN_TDLS
4461 /**
4462  * wma_tdls_event_handler() - handle TDLS event
4463  * @handle: wma handle
4464  * @event: event buffer
4465  * @len: buffer length
4466  *
4467  * Return: 0 for success or error code
4468  */
wma_tdls_event_handler(void * handle,uint8_t * event,uint32_t len)4469 int wma_tdls_event_handler(void *handle, uint8_t *event, uint32_t len)
4470 {
4471 	/* TODO update with target rx ops */
4472 	return 0;
4473 }
4474 
4475 /**
4476  * wma_update_tdls_peer_state() - update TDLS peer state
4477  * @handle: wma handle
4478  * @peer_state: TDLS peer state params
4479  *
4480  * Return: 0 for success or error code
4481  */
wma_update_tdls_peer_state(WMA_HANDLE handle,struct tdls_peer_update_state * peer_state)4482 int wma_update_tdls_peer_state(WMA_HANDLE handle,
4483 			       struct tdls_peer_update_state *peer_state)
4484 {
4485 	tp_wma_handle wma_handle = (tp_wma_handle) handle;
4486 	uint32_t i;
4487 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
4488 	struct tdls_peer_params *peer_cap;
4489 	int ret = 0;
4490 	uint32_t *ch_mhz = NULL;
4491 	size_t ch_mhz_len;
4492 	bool restore_last_peer = false;
4493 	QDF_STATUS qdf_status;
4494 	struct wmi_unified *wmi_handle;
4495 
4496 	if (wma_validate_handle(wma_handle)) {
4497 		ret = -EINVAL;
4498 		goto end_tdls_peer_state;
4499 	}
4500 
4501 	wmi_handle = wma_handle->wmi_handle;
4502 	if (wmi_validate_handle(wmi_handle)) {
4503 		ret = -EINVAL;
4504 		goto end_tdls_peer_state;
4505 	}
4506 
4507 	if (!soc) {
4508 		ret = -EINVAL;
4509 		goto end_tdls_peer_state;
4510 	}
4511 
4512 	if (wlan_cm_is_roam_sync_in_progress(wma_handle->psoc,
4513 					     peer_state->vdev_id)) {
4514 		wma_err("roaming in progress, reject peer update cmd!");
4515 		ret = -EPERM;
4516 		goto end_tdls_peer_state;
4517 	}
4518 
4519 
4520 	if (!wma_objmgr_peer_exist(wma_handle,
4521 				   peer_state->peer_macaddr, NULL)) {
4522 		wma_err("peer:" QDF_MAC_ADDR_FMT "doesn't exist",
4523 			QDF_MAC_ADDR_REF(peer_state->peer_macaddr));
4524 		ret = -EINVAL;
4525 		goto end_tdls_peer_state;
4526 	}
4527 
4528 	peer_cap = &peer_state->peer_cap;
4529 
4530 	/* peer capability info is valid only when peer state is connected */
4531 	if (TDLS_PEER_STATE_CONNECTED != peer_state->peer_state)
4532 		qdf_mem_zero(peer_cap, sizeof(*peer_cap));
4533 
4534 	if (peer_cap->peer_chanlen) {
4535 		ch_mhz_len = sizeof(*ch_mhz) * peer_cap->peer_chanlen;
4536 		ch_mhz = qdf_mem_malloc(ch_mhz_len);
4537 		if (!ch_mhz) {
4538 			ret = -ENOMEM;
4539 			goto end_tdls_peer_state;
4540 		}
4541 
4542 		for (i = 0; i < peer_cap->peer_chanlen; ++i)
4543 			ch_mhz[i] = peer_cap->peer_chan[i].ch_freq;
4544 	}
4545 
4546 	cdp_peer_set_tdls_offchan_enabled(soc, peer_state->vdev_id,
4547 					  peer_state->peer_macaddr,
4548 					  !!peer_cap->peer_off_chan_support);
4549 
4550 	if (wmi_unified_update_tdls_peer_state_cmd(wma_handle->wmi_handle,
4551 						   peer_state,
4552 						   ch_mhz)) {
4553 		wma_err("failed to send tdls peer update state command");
4554 		ret = -EIO;
4555 		/* Fall through to delete TDLS peer for teardown */
4556 	}
4557 
4558 	/* in case of teardown, remove peer from fw */
4559 	if (TDLS_PEER_STATE_TEARDOWN == peer_state->peer_state) {
4560 		restore_last_peer = cdp_peer_is_vdev_restore_last_peer(
4561 						soc,
4562 						peer_state->vdev_id,
4563 						peer_state->peer_macaddr);
4564 
4565 		wma_debug("calling wma_remove_peer for peer " QDF_MAC_ADDR_FMT
4566 			 " vdevId: %d",
4567 			 QDF_MAC_ADDR_REF(peer_state->peer_macaddr),
4568 			 peer_state->vdev_id);
4569 		qdf_status = wma_remove_peer(wma_handle,
4570 					     peer_state->peer_macaddr,
4571 					     peer_state->vdev_id, false);
4572 		if (QDF_IS_STATUS_ERROR(qdf_status)) {
4573 			wma_err("wma_remove_peer failed");
4574 			ret = -EINVAL;
4575 		}
4576 		cdp_peer_update_last_real_peer(soc, WMI_PDEV_ID_SOC,
4577 					       peer_state->vdev_id,
4578 					       restore_last_peer);
4579 	}
4580 
4581 	if (TDLS_PEER_STATE_CONNECTED == peer_state->peer_state) {
4582 		cdp_peer_state_update(soc, peer_state->peer_macaddr,
4583 				      OL_TXRX_PEER_STATE_AUTH);
4584 	}
4585 
4586 end_tdls_peer_state:
4587 	if (ch_mhz)
4588 		qdf_mem_free(ch_mhz);
4589 	if (peer_state)
4590 		qdf_mem_free(peer_state);
4591 	return ret;
4592 }
4593 #endif /* FEATURE_WLAN_TDLS */
4594 
4595 /*
4596  * wma_process_cfg_action_frm_tb_ppdu() - action frame TB PPDU cfg to firmware
4597  * @wma:                Pointer to WMA handle
4598  * @cfg_info:       Pointer for cfg info
4599  *
4600  * Return: QDF_STATUS_SUCCESS for success otherwise failure
4601  *
4602  */
wma_process_cfg_action_frm_tb_ppdu(tp_wma_handle wma,struct cfg_action_frm_tb_ppdu * cfg_info)4603 QDF_STATUS wma_process_cfg_action_frm_tb_ppdu(tp_wma_handle wma,
4604 				   struct cfg_action_frm_tb_ppdu *cfg_info)
4605 {
4606 	struct cfg_action_frm_tb_ppdu_param cmd = {0};
4607 
4608 	if (wma_validate_handle(wma))
4609 		return QDF_STATUS_E_FAILURE;
4610 
4611 	cmd.frm_len = cfg_info->frm_len;
4612 	cmd.cfg = cfg_info->cfg;
4613 	cmd.data = cfg_info->data;
4614 
4615 	wma_debug("cfg: %d, frm_len: %d", cfg_info->cfg, cfg_info->frm_len);
4616 
4617 	return wmi_unified_cfg_action_frm_tb_ppdu_cmd(wma->wmi_handle, &cmd);
4618 }
4619 
4620 
4621 /*
4622  * wma_process_set_ie_info() - Function to send IE info to firmware
4623  * @wma:                Pointer to WMA handle
4624  * @ie_data:       Pointer for ie data
4625  *
4626  * This function sends IE information to firmware
4627  *
4628  * Return: QDF_STATUS_SUCCESS for success otherwise failure
4629  *
4630  */
wma_process_set_ie_info(tp_wma_handle wma,struct vdev_ie_info * ie_info)4631 QDF_STATUS wma_process_set_ie_info(tp_wma_handle wma,
4632 				   struct vdev_ie_info *ie_info)
4633 {
4634 	struct wma_txrx_node *interface;
4635 	struct vdev_ie_info_param cmd = {0};
4636 
4637 	if (!ie_info || !wma) {
4638 		wma_err("input pointer is NULL");
4639 		return QDF_STATUS_E_FAILURE;
4640 	}
4641 
4642 	/* Validate the input */
4643 	if (ie_info->length  <= 0) {
4644 		wma_err("Invalid IE length");
4645 		return QDF_STATUS_E_INVAL;
4646 	}
4647 
4648 	if (!wma_is_vdev_valid(ie_info->vdev_id)) {
4649 		wma_err("vdev_id: %d is not active", ie_info->vdev_id);
4650 		return QDF_STATUS_E_INVAL;
4651 	}
4652 
4653 	interface = &wma->interfaces[ie_info->vdev_id];
4654 	cmd.vdev_id = ie_info->vdev_id;
4655 	cmd.ie_id = ie_info->ie_id;
4656 	cmd.length = ie_info->length;
4657 	cmd.band = ie_info->band;
4658 	cmd.data = ie_info->data;
4659 	cmd.ie_source = WMA_SET_VDEV_IE_SOURCE_HOST;
4660 
4661 	wma_debug("vdev id: %d, ie_id: %d, band: %d, len: %d",
4662 		 ie_info->vdev_id, ie_info->ie_id, ie_info->band,
4663 		 ie_info->length);
4664 
4665 	QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_DEBUG,
4666 		ie_info->data, ie_info->length);
4667 
4668 	return wmi_unified_process_set_ie_info_cmd(wma->wmi_handle, &cmd);
4669 }
4670 
4671 #ifdef FEATURE_WLAN_APF
4672 /**
4673  *  wma_get_apf_caps_event_handler() - Event handler for get apf capability
4674  *  @handle: WMA global handle
4675  *  @cmd_param_info: command event data
4676  *  @len: Length of @cmd_param_info
4677  *
4678  *  Return: 0 on Success or Errno on failure
4679  */
wma_get_apf_caps_event_handler(void * handle,u_int8_t * cmd_param_info,u_int32_t len)4680 int wma_get_apf_caps_event_handler(void *handle, u_int8_t *cmd_param_info,
4681 				   u_int32_t len)
4682 {
4683 	WMI_BPF_CAPABILIY_INFO_EVENTID_param_tlvs  *param_buf;
4684 	wmi_bpf_capability_info_evt_fixed_param *event;
4685 	struct sir_apf_get_offload *apf_get_offload;
4686 	struct mac_context *pmac = (struct mac_context *)cds_get_context(
4687 				QDF_MODULE_ID_PE);
4688 
4689 	if (!pmac)
4690 		return -EINVAL;
4691 
4692 	if (!pmac->sme.apf_get_offload_cb) {
4693 		wma_err("Callback not registered");
4694 		return -EINVAL;
4695 	}
4696 
4697 	param_buf = (WMI_BPF_CAPABILIY_INFO_EVENTID_param_tlvs *)cmd_param_info;
4698 	event = param_buf->fixed_param;
4699 	apf_get_offload = qdf_mem_malloc(sizeof(*apf_get_offload));
4700 	if (!apf_get_offload)
4701 		return -ENOMEM;
4702 
4703 	apf_get_offload->apf_version = event->bpf_version;
4704 	apf_get_offload->max_apf_filters = event->max_bpf_filters;
4705 	apf_get_offload->max_bytes_for_apf_inst =
4706 			event->max_bytes_for_bpf_inst;
4707 	wma_debug("APF capabilities version: %d max apf filter size: %d",
4708 		 apf_get_offload->apf_version,
4709 		 apf_get_offload->max_bytes_for_apf_inst);
4710 
4711 	wma_debug("sending apf capabilities event to hdd");
4712 	pmac->sme.apf_get_offload_cb(pmac->sme.apf_get_offload_context,
4713 				     apf_get_offload);
4714 	qdf_mem_free(apf_get_offload);
4715 	return 0;
4716 }
4717 
wma_get_apf_capabilities(tp_wma_handle wma)4718 QDF_STATUS wma_get_apf_capabilities(tp_wma_handle wma)
4719 {
4720 	QDF_STATUS status = QDF_STATUS_SUCCESS;
4721 	wmi_bpf_get_capability_cmd_fixed_param *cmd;
4722 	wmi_buf_t wmi_buf;
4723 	uint32_t   len;
4724 	u_int8_t *buf_ptr;
4725 	struct wmi_unified *wmi_handle;
4726 
4727 	if (wma_validate_handle(wma))
4728 		return QDF_STATUS_E_INVAL;
4729 
4730 	wmi_handle = wma->wmi_handle;
4731 	if (wmi_validate_handle(wmi_handle))
4732 		return QDF_STATUS_E_INVAL;
4733 
4734 	if (!wmi_service_enabled(wmi_handle, wmi_service_apf_offload)) {
4735 		wma_err("APF cababilities feature bit not enabled");
4736 		return QDF_STATUS_E_FAILURE;
4737 	}
4738 
4739 	len = sizeof(*cmd);
4740 	wmi_buf = wmi_buf_alloc(wmi_handle, len);
4741 	if (!wmi_buf)
4742 		return QDF_STATUS_E_NOMEM;
4743 
4744 	buf_ptr = (u_int8_t *) wmi_buf_data(wmi_buf);
4745 	cmd = (wmi_bpf_get_capability_cmd_fixed_param *) buf_ptr;
4746 	WMITLV_SET_HDR(&cmd->tlv_header,
4747 	WMITLV_TAG_STRUC_wmi_bpf_get_capability_cmd_fixed_param,
4748 		WMITLV_GET_STRUCT_TLVLEN(
4749 		wmi_bpf_get_capability_cmd_fixed_param));
4750 
4751 	if (wmi_unified_cmd_send(wmi_handle, wmi_buf, len,
4752 				 WMI_BPF_GET_CAPABILITY_CMDID)) {
4753 		wmi_buf_free(wmi_buf);
4754 		return QDF_STATUS_E_FAILURE;
4755 	}
4756 	return status;
4757 }
4758 
wma_set_apf_instructions(tp_wma_handle wma,struct sir_apf_set_offload * apf_set_offload)4759 QDF_STATUS wma_set_apf_instructions(tp_wma_handle wma,
4760 				    struct sir_apf_set_offload *apf_set_offload)
4761 {
4762 	wmi_bpf_set_vdev_instructions_cmd_fixed_param *cmd;
4763 	wmi_buf_t wmi_buf;
4764 	uint32_t   len = 0, len_aligned = 0;
4765 	u_int8_t *buf_ptr;
4766 	struct wmi_unified *wmi_handle;
4767 
4768 	if (wma_validate_handle(wma))
4769 		return QDF_STATUS_E_INVAL;
4770 
4771 	wmi_handle = wma->wmi_handle;
4772 	if (wmi_validate_handle(wmi_handle))
4773 		return QDF_STATUS_E_INVAL;
4774 
4775 	if (!wmi_service_enabled(wmi_handle,
4776 		wmi_service_apf_offload)) {
4777 		wma_err("APF offload feature Disabled");
4778 		return QDF_STATUS_E_NOSUPPORT;
4779 	}
4780 
4781 	if (!apf_set_offload) {
4782 		wma_err("Invalid APF instruction request");
4783 		return QDF_STATUS_E_INVAL;
4784 	}
4785 
4786 	if (apf_set_offload->session_id >= wma->max_bssid) {
4787 		wma_err("Invalid vdev_id: %d", apf_set_offload->session_id);
4788 		return QDF_STATUS_E_INVAL;
4789 	}
4790 
4791 	if (!wma_is_vdev_up(apf_set_offload->session_id)) {
4792 		wma_err("vdev %d is not up skipping APF offload",
4793 			 apf_set_offload->session_id);
4794 		return QDF_STATUS_E_INVAL;
4795 	}
4796 
4797 	if (apf_set_offload->total_length) {
4798 		len_aligned = roundup(apf_set_offload->current_length,
4799 					sizeof(A_UINT32));
4800 		len = len_aligned + WMI_TLV_HDR_SIZE;
4801 	}
4802 
4803 	len += sizeof(*cmd);
4804 	wmi_buf = wmi_buf_alloc(wmi_handle, len);
4805 	if (!wmi_buf)
4806 		return QDF_STATUS_E_NOMEM;
4807 
4808 	buf_ptr = (u_int8_t *) wmi_buf_data(wmi_buf);
4809 	cmd = (wmi_bpf_set_vdev_instructions_cmd_fixed_param *) buf_ptr;
4810 
4811 	WMITLV_SET_HDR(&cmd->tlv_header,
4812 		WMITLV_TAG_STRUC_wmi_bpf_set_vdev_instructions_cmd_fixed_param,
4813 		WMITLV_GET_STRUCT_TLVLEN(
4814 			wmi_bpf_set_vdev_instructions_cmd_fixed_param));
4815 	cmd->vdev_id = apf_set_offload->session_id;
4816 	cmd->filter_id = apf_set_offload->filter_id;
4817 	cmd->total_length = apf_set_offload->total_length;
4818 	cmd->current_offset = apf_set_offload->current_offset;
4819 	cmd->current_length = apf_set_offload->current_length;
4820 
4821 	if (apf_set_offload->total_length) {
4822 		buf_ptr +=
4823 			sizeof(wmi_bpf_set_vdev_instructions_cmd_fixed_param);
4824 		WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, len_aligned);
4825 		buf_ptr += WMI_TLV_HDR_SIZE;
4826 		qdf_mem_copy(buf_ptr, apf_set_offload->program,
4827 			     apf_set_offload->current_length);
4828 	}
4829 
4830 	if (wmi_unified_cmd_send(wmi_handle, wmi_buf, len,
4831 				 WMI_BPF_SET_VDEV_INSTRUCTIONS_CMDID)) {
4832 		wmi_buf_free(wmi_buf);
4833 		return QDF_STATUS_E_FAILURE;
4834 	}
4835 	wma_debug("APF offload enabled in fw");
4836 
4837 	return QDF_STATUS_SUCCESS;
4838 }
4839 
wma_send_apf_enable_cmd(WMA_HANDLE handle,uint8_t vdev_id,bool apf_enable)4840 QDF_STATUS wma_send_apf_enable_cmd(WMA_HANDLE handle, uint8_t vdev_id,
4841 				   bool apf_enable)
4842 {
4843 	QDF_STATUS status = QDF_STATUS_SUCCESS;
4844 	tp_wma_handle wma = (tp_wma_handle) handle;
4845 	struct wmi_unified *wmi_handle;
4846 
4847 	if (!wma_is_vdev_valid(vdev_id))
4848 		return QDF_STATUS_E_INVAL;
4849 
4850 	if (wma_validate_handle(wma))
4851 		return QDF_STATUS_E_INVAL;
4852 
4853 	wmi_handle = wma->wmi_handle;
4854 	if (wmi_validate_handle(wmi_handle))
4855 		return QDF_STATUS_E_INVAL;
4856 
4857 	if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
4858 		WMI_SERVICE_BPF_OFFLOAD)) {
4859 		wma_err("APF cababilities feature bit not enabled");
4860 		return QDF_STATUS_E_FAILURE;
4861 	}
4862 
4863 	status = wmi_unified_send_apf_enable_cmd(wmi_handle, vdev_id,
4864 						 apf_enable);
4865 	if (QDF_IS_STATUS_ERROR(status)) {
4866 		wma_err("Failed to send apf enable/disable cmd");
4867 		return QDF_STATUS_E_FAILURE;
4868 	}
4869 
4870 	if (apf_enable)
4871 		wma_debug("Sent APF Enable on vdevid: %d", vdev_id);
4872 	else
4873 		wma_debug("Sent APF Disable on vdevid: %d", vdev_id);
4874 
4875 	return status;
4876 }
4877 
4878 QDF_STATUS
wma_send_apf_write_work_memory_cmd(WMA_HANDLE handle,struct wmi_apf_write_memory_params * write_params)4879 wma_send_apf_write_work_memory_cmd(WMA_HANDLE handle,
4880 				   struct wmi_apf_write_memory_params
4881 								*write_params)
4882 {
4883 	QDF_STATUS status = QDF_STATUS_SUCCESS;
4884 	tp_wma_handle wma = (tp_wma_handle) handle;
4885 	struct wmi_unified *wmi_handle;
4886 
4887 	if (wma_validate_handle(wma))
4888 		return QDF_STATUS_E_INVAL;
4889 
4890 	wmi_handle = wma->wmi_handle;
4891 	if (wmi_validate_handle(wmi_handle))
4892 		return QDF_STATUS_E_INVAL;
4893 
4894 	if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
4895 		WMI_SERVICE_BPF_OFFLOAD)) {
4896 		wma_err("APF cababilities feature bit not enabled");
4897 		return QDF_STATUS_E_FAILURE;
4898 	}
4899 
4900 	if (wmi_unified_send_apf_write_work_memory_cmd(wmi_handle,
4901 						       write_params)) {
4902 		wma_err("Failed to send APF write mem command");
4903 		return QDF_STATUS_E_FAILURE;
4904 	}
4905 
4906 	wma_debug("Sent APF write mem on vdevid: %d", write_params->vdev_id);
4907 	return status;
4908 }
4909 
wma_apf_read_work_memory_event_handler(void * handle,uint8_t * evt_buf,uint32_t len)4910 int wma_apf_read_work_memory_event_handler(void *handle, uint8_t *evt_buf,
4911 					   uint32_t len)
4912 {
4913 	tp_wma_handle wma_handle;
4914 	wmi_unified_t wmi_handle;
4915 	struct wmi_apf_read_memory_resp_event_params evt_params = {0};
4916 	QDF_STATUS status;
4917 	struct mac_context *pmac = cds_get_context(QDF_MODULE_ID_PE);
4918 
4919 	wma_debug("handle:%pK event:%pK len:%u", handle, evt_buf, len);
4920 
4921 	wma_handle = handle;
4922 	if (wma_validate_handle(wma_handle))
4923 		return -EINVAL;
4924 
4925 	wmi_handle = wma_handle->wmi_handle;
4926 	if (wmi_validate_handle(wmi_handle))
4927 		return -EINVAL;
4928 
4929 	if (!pmac)
4930 		return -EINVAL;
4931 
4932 	if (!pmac->sme.apf_read_mem_cb) {
4933 		wma_err("Callback not registered");
4934 		return -EINVAL;
4935 	}
4936 
4937 	status = wmi_extract_apf_read_memory_resp_event(wmi_handle,
4938 						evt_buf, &evt_params);
4939 	if (QDF_IS_STATUS_ERROR(status)) {
4940 		wma_err("Event extract failure: %d", status);
4941 		return -EINVAL;
4942 	}
4943 
4944 	pmac->sme.apf_read_mem_cb(pmac->hdd_handle, &evt_params);
4945 
4946 	return 0;
4947 }
4948 
wma_send_apf_read_work_memory_cmd(WMA_HANDLE handle,struct wmi_apf_read_memory_params * read_params)4949 QDF_STATUS wma_send_apf_read_work_memory_cmd(WMA_HANDLE handle,
4950 					     struct wmi_apf_read_memory_params
4951 								  *read_params)
4952 {
4953 	QDF_STATUS status = QDF_STATUS_SUCCESS;
4954 	tp_wma_handle wma = (tp_wma_handle) handle;
4955 	struct wmi_unified *wmi_handle;
4956 
4957 	if (wma_validate_handle(wma))
4958 		return QDF_STATUS_E_INVAL;
4959 
4960 	wmi_handle = wma->wmi_handle;
4961 	if (wmi_validate_handle(wmi_handle))
4962 		return QDF_STATUS_E_INVAL;
4963 
4964 	if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
4965 		WMI_SERVICE_BPF_OFFLOAD)) {
4966 		wma_err("APF cababilities feature bit not enabled");
4967 		return QDF_STATUS_E_FAILURE;
4968 	}
4969 
4970 	if (wmi_unified_send_apf_read_work_memory_cmd(wmi_handle,
4971 						      read_params)) {
4972 		wma_err("Failed to send APF read memory command");
4973 		return QDF_STATUS_E_FAILURE;
4974 	}
4975 
4976 	wma_debug("Sent APF read memory on vdevid: %d", read_params->vdev_id);
4977 	return status;
4978 }
4979 #endif /* FEATURE_WLAN_APF */
4980 
wma_set_tx_rx_aggr_size(uint8_t vdev_id,uint32_t tx_size,uint32_t rx_size,wmi_vdev_custom_aggr_type_t aggr_type)4981 QDF_STATUS wma_set_tx_rx_aggr_size(uint8_t vdev_id,
4982 				   uint32_t tx_size,
4983 				   uint32_t rx_size,
4984 				   wmi_vdev_custom_aggr_type_t aggr_type)
4985 {
4986 	tp_wma_handle wma_handle;
4987 	struct wma_txrx_node *intr;
4988 	wmi_vdev_set_custom_aggr_size_cmd_fixed_param *cmd;
4989 	int32_t len;
4990 	wmi_buf_t buf;
4991 	u_int8_t *buf_ptr;
4992 	int ret;
4993 
4994 	wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
4995 
4996 	if (!wma_handle)
4997 		return QDF_STATUS_E_INVAL;
4998 
4999 	intr = wma_handle->interfaces;
5000 	if (!intr) {
5001 		wma_err("WMA interface is invalid!");
5002 		return QDF_STATUS_E_INVAL;
5003 	}
5004 
5005 	if (aggr_type == WMI_VDEV_CUSTOM_AGGR_TYPE_AMPDU) {
5006 		intr[vdev_id].config.tx_ampdu = tx_size;
5007 		intr[vdev_id].config.rx_ampdu = rx_size;
5008 	} else {
5009 		intr[vdev_id].config.tx_amsdu = tx_size;
5010 		intr[vdev_id].config.rx_amsdu = rx_size;
5011 	}
5012 
5013 	len = sizeof(*cmd);
5014 	buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
5015 	if (!buf)
5016 		return QDF_STATUS_E_NOMEM;
5017 
5018 	buf_ptr = (u_int8_t *) wmi_buf_data(buf);
5019 	cmd = (wmi_vdev_set_custom_aggr_size_cmd_fixed_param *) buf_ptr;
5020 	qdf_mem_zero(cmd, sizeof(*cmd));
5021 
5022 	WMITLV_SET_HDR(&cmd->tlv_header,
5023 		WMITLV_TAG_STRUC_wmi_vdev_set_custom_aggr_size_cmd_fixed_param,
5024 		WMITLV_GET_STRUCT_TLVLEN(
5025 			wmi_vdev_set_custom_aggr_size_cmd_fixed_param));
5026 
5027 	if (wmi_service_enabled(wma_handle->wmi_handle,
5028 				wmi_service_ampdu_tx_buf_size_256_support)) {
5029 		cmd->enable_bitmap |= (0x1 << 6);
5030 	}
5031 
5032 	if ((tx_size > ADDBA_TXAGGR_SIZE_HELIUM) &&
5033 	    (tx_size != ADDBA_TXAGGR_SIZE_LITHIUM) &&
5034 	    (tx_size != ADDBA_TXAGGR_SIZE_512) &&
5035 	    (tx_size != ADDBA_TXAGGR_SIZE_BERYLLIUM)) {
5036 		wma_err("Invalid AMPDU Size");
5037 		return QDF_STATUS_E_INVAL;
5038 	}
5039 
5040 	cmd->vdev_id = vdev_id;
5041 	cmd->tx_aggr_size = tx_size;
5042 	cmd->rx_aggr_size = rx_size;
5043 	/* bit 2 (aggr_type): TX Aggregation Type (0=A-MPDU, 1=A-MSDU) */
5044 	if (aggr_type == WMI_VDEV_CUSTOM_AGGR_TYPE_AMSDU)
5045 		cmd->enable_bitmap |= 0x04;
5046 
5047 	wma_debug("tx aggr: %d rx aggr: %d vdev: %d enable_bitmap %d",
5048 		 cmd->tx_aggr_size, cmd->rx_aggr_size, cmd->vdev_id,
5049 		 cmd->enable_bitmap);
5050 
5051 	ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
5052 				WMI_VDEV_SET_CUSTOM_AGGR_SIZE_CMDID);
5053 	if (ret) {
5054 		wmi_buf_free(buf);
5055 		return QDF_STATUS_E_FAILURE;
5056 	}
5057 
5058 	return QDF_STATUS_SUCCESS;
5059 }
5060 
wma_set_tx_rx_aggr_size_per_ac(WMA_HANDLE handle,uint8_t vdev_id,struct wlan_mlme_qos * qos_aggr,wmi_vdev_custom_aggr_type_t aggr_type)5061 QDF_STATUS wma_set_tx_rx_aggr_size_per_ac(WMA_HANDLE handle,
5062 					  uint8_t vdev_id,
5063 					  struct wlan_mlme_qos *qos_aggr,
5064 					  wmi_vdev_custom_aggr_type_t aggr_type)
5065 {
5066 	wmi_vdev_set_custom_aggr_size_cmd_fixed_param *cmd;
5067 	int32_t len;
5068 	wmi_buf_t buf;
5069 	u_int8_t *buf_ptr;
5070 	int ret;
5071 	int queue_num;
5072 	uint32_t tx_aggr_size[4];
5073 	tp_wma_handle wma_handle = (tp_wma_handle)handle;
5074 
5075 	if (wma_validate_handle(wma_handle))
5076 		return QDF_STATUS_E_INVAL;
5077 
5078 	tx_aggr_size[0] = qos_aggr->tx_aggregation_size_be;
5079 	tx_aggr_size[1] = qos_aggr->tx_aggregation_size_bk;
5080 	tx_aggr_size[2] = qos_aggr->tx_aggregation_size_vi;
5081 	tx_aggr_size[3] = qos_aggr->tx_aggregation_size_vo;
5082 
5083 	for (queue_num = 0; queue_num < 4; queue_num++) {
5084 		if (tx_aggr_size[queue_num] == 0)
5085 			continue;
5086 
5087 		len = sizeof(*cmd);
5088 		buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
5089 		if (!buf)
5090 			return QDF_STATUS_E_NOMEM;
5091 
5092 		buf_ptr = (u_int8_t *)wmi_buf_data(buf);
5093 		cmd = (wmi_vdev_set_custom_aggr_size_cmd_fixed_param *)buf_ptr;
5094 		qdf_mem_zero(cmd, sizeof(*cmd));
5095 
5096 		WMITLV_SET_HDR(&cmd->tlv_header,
5097 			       WMITLV_TAG_STRUC_wmi_vdev_set_custom_aggr_size_cmd_fixed_param,
5098 			       WMITLV_GET_STRUCT_TLVLEN(
5099 					wmi_vdev_set_custom_aggr_size_cmd_fixed_param));
5100 
5101 		cmd->vdev_id = vdev_id;
5102 		cmd->rx_aggr_size = qos_aggr->rx_aggregation_size;
5103 		cmd->tx_aggr_size = tx_aggr_size[queue_num];
5104 
5105 		if (wmi_service_enabled(wma_handle->wmi_handle,
5106 					wmi_service_ampdu_tx_buf_size_256_support)) {
5107 			cmd->enable_bitmap |= (0x1 << 6);
5108 		}
5109 
5110 		if ((tx_aggr_size[queue_num] != ADDBA_TXAGGR_SIZE_LITHIUM) &&
5111 		    (tx_aggr_size[queue_num] > ADDBA_TXAGGR_SIZE_HELIUM)) {
5112 			wma_err("Invalid AMPDU Size");
5113 			return QDF_STATUS_E_INVAL;
5114 		}
5115 
5116 		/* bit 5: tx_ac_enable, if set, ac bitmap is valid. */
5117 		cmd->enable_bitmap |= 0x20 | queue_num;
5118 		/* bit 2 (aggr_type): TX Aggregation Type (0=A-MPDU, 1=A-MSDU) */
5119 		if (aggr_type == WMI_VDEV_CUSTOM_AGGR_TYPE_AMSDU)
5120 			cmd->enable_bitmap |= 0x04;
5121 
5122 		wma_debug("queue_num: %d, tx aggr: %d rx aggr: %d vdev: %d, bitmap: %d",
5123 			 queue_num, cmd->tx_aggr_size,
5124 			 cmd->rx_aggr_size, cmd->vdev_id,
5125 			 cmd->enable_bitmap);
5126 
5127 		ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
5128 					WMI_VDEV_SET_CUSTOM_AGGR_SIZE_CMDID);
5129 		if (ret) {
5130 			wmi_buf_free(buf);
5131 			return QDF_STATUS_E_FAILURE;
5132 		}
5133 	}
5134 
5135 	return QDF_STATUS_SUCCESS;
5136 }
5137 
wma_set_sw_retry_by_qos(tp_wma_handle handle,uint8_t vdev_id,wmi_vdev_custom_sw_retry_type_t retry_type,wmi_traffic_ac ac_type,uint32_t sw_retry)5138 static QDF_STATUS wma_set_sw_retry_by_qos(
5139 	tp_wma_handle handle, uint8_t vdev_id,
5140 	wmi_vdev_custom_sw_retry_type_t retry_type,
5141 	wmi_traffic_ac ac_type,
5142 	uint32_t sw_retry)
5143 {
5144 	wmi_vdev_set_custom_sw_retry_th_cmd_fixed_param *cmd;
5145 	int32_t len;
5146 	wmi_buf_t buf;
5147 	u_int8_t *buf_ptr;
5148 	int ret;
5149 
5150 	len = sizeof(*cmd);
5151 	buf = wmi_buf_alloc(handle->wmi_handle, len);
5152 
5153 	if (!buf)
5154 		return QDF_STATUS_E_NOMEM;
5155 
5156 	buf_ptr = (u_int8_t *)wmi_buf_data(buf);
5157 	cmd = (wmi_vdev_set_custom_sw_retry_th_cmd_fixed_param *)buf_ptr;
5158 
5159 	WMITLV_SET_HDR(&cmd->tlv_header,
5160 		       WMITLV_TAG_STRUC_wmi_vdev_set_custom_sw_retry_th_cmd_fixed_param,
5161 		       WMITLV_GET_STRUCT_TLVLEN(
5162 		       wmi_vdev_set_custom_sw_retry_th_cmd_fixed_param));
5163 
5164 	cmd->vdev_id = vdev_id;
5165 	cmd->ac_type = ac_type;
5166 	cmd->sw_retry_type = retry_type;
5167 	cmd->sw_retry_th = sw_retry;
5168 
5169 	wma_debug("ac_type: %d re_type: %d threshold: %d vid: %d",
5170 		  cmd->ac_type, cmd->sw_retry_type,
5171 		  cmd->sw_retry_th, cmd->vdev_id);
5172 
5173 	ret = wmi_unified_cmd_send(handle->wmi_handle,
5174 				   buf, len,
5175 				   WMI_VDEV_SET_CUSTOM_SW_RETRY_TH_CMDID);
5176 
5177 	if (ret) {
5178 		wmi_buf_free(buf);
5179 		return QDF_STATUS_E_FAILURE;
5180 	}
5181 
5182 	return QDF_STATUS_SUCCESS;
5183 }
5184 
wma_set_vdev_sw_retry_th(uint8_t vdev_id,uint8_t sw_retry_count,wmi_vdev_custom_sw_retry_type_t retry_type)5185 QDF_STATUS wma_set_vdev_sw_retry_th(uint8_t vdev_id, uint8_t sw_retry_count,
5186 				    wmi_vdev_custom_sw_retry_type_t retry_type)
5187 {
5188 	QDF_STATUS status = QDF_STATUS_SUCCESS;
5189 	tp_wma_handle wma_handle;
5190 	uint32_t queue_num;
5191 
5192 	wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
5193 	if (!wma_handle)
5194 		return QDF_STATUS_E_FAILURE;
5195 
5196 
5197 	for (queue_num = 0; queue_num < WMI_AC_MAX; queue_num++) {
5198 		if (sw_retry_count == 0)
5199 			continue;
5200 
5201 		status = wma_set_sw_retry_by_qos(wma_handle,
5202 						 vdev_id,
5203 						 retry_type,
5204 						 queue_num,
5205 						 sw_retry_count);
5206 
5207 		if (QDF_IS_STATUS_ERROR(status))
5208 			return status;
5209 	}
5210 
5211 	return QDF_STATUS_SUCCESS;
5212 }
5213 
wma_set_sw_retry_threshold_per_ac(WMA_HANDLE handle,uint8_t vdev_id,struct wlan_mlme_qos * qos_aggr)5214 QDF_STATUS wma_set_sw_retry_threshold_per_ac(WMA_HANDLE handle,
5215 					     uint8_t vdev_id,
5216 					     struct wlan_mlme_qos *qos_aggr)
5217 {
5218 	QDF_STATUS ret;
5219 	int retry_type, queue_num;
5220 	uint32_t tx_sw_retry[WMI_VDEV_CUSTOM_SW_RETRY_TYPE_MAX][WMI_AC_MAX];
5221 	uint32_t sw_retry;
5222 	tp_wma_handle wma_handle = (tp_wma_handle)handle;
5223 
5224 	if (wma_validate_handle(wma_handle))
5225 		return QDF_STATUS_E_INVAL;
5226 
5227 	tx_sw_retry[WMI_VDEV_CUSTOM_SW_RETRY_TYPE_AGGR][WMI_AC_BE] =
5228 		qos_aggr->tx_aggr_sw_retry_threshold_be;
5229 	tx_sw_retry[WMI_VDEV_CUSTOM_SW_RETRY_TYPE_AGGR][WMI_AC_BK] =
5230 		qos_aggr->tx_aggr_sw_retry_threshold_bk;
5231 	tx_sw_retry[WMI_VDEV_CUSTOM_SW_RETRY_TYPE_AGGR][WMI_AC_VI] =
5232 		qos_aggr->tx_aggr_sw_retry_threshold_vi;
5233 	tx_sw_retry[WMI_VDEV_CUSTOM_SW_RETRY_TYPE_AGGR][WMI_AC_VO] =
5234 		qos_aggr->tx_aggr_sw_retry_threshold_vo;
5235 
5236 	tx_sw_retry[WMI_VDEV_CUSTOM_SW_RETRY_TYPE_NONAGGR][WMI_AC_BE] =
5237 		qos_aggr->tx_non_aggr_sw_retry_threshold_be;
5238 	tx_sw_retry[WMI_VDEV_CUSTOM_SW_RETRY_TYPE_NONAGGR][WMI_AC_BK] =
5239 		qos_aggr->tx_non_aggr_sw_retry_threshold_bk;
5240 	tx_sw_retry[WMI_VDEV_CUSTOM_SW_RETRY_TYPE_NONAGGR][WMI_AC_VI] =
5241 		qos_aggr->tx_non_aggr_sw_retry_threshold_vi;
5242 	tx_sw_retry[WMI_VDEV_CUSTOM_SW_RETRY_TYPE_NONAGGR][WMI_AC_VO] =
5243 		qos_aggr->tx_non_aggr_sw_retry_threshold_vo;
5244 
5245 	retry_type = WMI_VDEV_CUSTOM_SW_RETRY_TYPE_NONAGGR;
5246 	while (retry_type < WMI_VDEV_CUSTOM_SW_RETRY_TYPE_MAX) {
5247 		for (queue_num = 0; queue_num < WMI_AC_MAX; queue_num++) {
5248 			if (tx_sw_retry[retry_type][queue_num] == 0)
5249 				continue;
5250 
5251 			sw_retry = tx_sw_retry[retry_type][queue_num];
5252 			ret = wma_set_sw_retry_by_qos(wma_handle,
5253 						      vdev_id,
5254 						      retry_type,
5255 						      queue_num,
5256 						      sw_retry);
5257 
5258 			if (QDF_IS_STATUS_ERROR(ret))
5259 				return ret;
5260 		}
5261 		retry_type++;
5262 	}
5263 
5264 	return QDF_STATUS_SUCCESS;
5265 }
5266 
5267 #define MAX_PDEV_SW_RETRY_PARAMS 2
5268 /* params being sent:
5269  * 1.wmi_pdev_param_agg_sw_retry_th
5270  * 2.wmi_pdev_param_non_agg_sw_retry_th
5271  */
5272 
wma_set_sw_retry_threshold(struct wlan_mlme_qos * qos_aggr)5273 QDF_STATUS wma_set_sw_retry_threshold(struct wlan_mlme_qos *qos_aggr)
5274 {
5275 	uint32_t max, min, retry;
5276 	struct dev_set_param setparam[MAX_PDEV_SW_RETRY_PARAMS];
5277 	QDF_STATUS ret;
5278 	uint8_t index = 0;
5279 
5280 	retry = qos_aggr->tx_aggr_sw_retry_threshold;
5281 	max = cfg_max(CFG_TX_AGGR_SW_RETRY);
5282 	min = cfg_min(CFG_TX_AGGR_SW_RETRY);
5283 	retry = (retry > max) ? max : retry;
5284 	retry = (retry < min) ? min : retry;
5285 
5286 	ret = mlme_check_index_setparam(setparam,
5287 					wmi_pdev_param_agg_sw_retry_th,
5288 					retry, index++,
5289 					MAX_PDEV_SW_RETRY_PARAMS);
5290 	if (QDF_IS_STATUS_ERROR(ret)) {
5291 		wma_debug("failed to set wmi_pdev_param_agg_sw_retry_th");
5292 		return ret;
5293 	}
5294 	retry = qos_aggr->tx_non_aggr_sw_retry_threshold;
5295 	max = cfg_max(CFG_TX_NON_AGGR_SW_RETRY);
5296 	min = cfg_min(CFG_TX_NON_AGGR_SW_RETRY);
5297 	retry = (retry > max) ? max : retry;
5298 	retry = (retry < min) ? min : retry;
5299 	ret = mlme_check_index_setparam(setparam,
5300 					wmi_pdev_param_non_agg_sw_retry_th,
5301 					retry, index++,
5302 					MAX_PDEV_SW_RETRY_PARAMS);
5303 	if (QDF_IS_STATUS_ERROR(ret)) {
5304 		wma_debug("failed to set wmi_pdev_param_non_agg_sw_retry_th");
5305 		return ret;
5306 	}
5307 	ret = wma_send_multi_pdev_vdev_set_params(MLME_PDEV_SETPARAM,
5308 						  WMI_PDEV_ID_SOC, setparam,
5309 						  index);
5310 	return ret;
5311 }
5312 
5313 /**
5314  * wma_process_fw_test_cmd() - send unit test command to fw.
5315  * @handle: wma handle
5316  * @wma_fwtest: fw test command
5317  *
5318  * This function send fw test command to fw.
5319  *
5320  * Return: none
5321  */
wma_process_fw_test_cmd(WMA_HANDLE handle,struct set_fwtest_params * wma_fwtest)5322 QDF_STATUS wma_process_fw_test_cmd(WMA_HANDLE handle,
5323 				   struct set_fwtest_params *wma_fwtest)
5324 {
5325 	tp_wma_handle wma_handle = (tp_wma_handle) handle;
5326 	struct wmi_unified *wmi_handle;
5327 
5328 	if (wma_validate_handle(wma_handle))
5329 		return QDF_STATUS_E_INVAL;
5330 
5331 	wmi_handle = wma_handle->wmi_handle;
5332 	if (wmi_validate_handle(wmi_handle))
5333 		return QDF_STATUS_E_INVAL;
5334 
5335 	if (wmi_unified_fw_test_cmd(wmi_handle,
5336 				    (struct set_fwtest_params *)wma_fwtest)) {
5337 		wma_err("Failed to issue fw test cmd");
5338 		return QDF_STATUS_E_FAILURE;
5339 	}
5340 	return QDF_STATUS_SUCCESS;
5341 }
5342 
5343 /**
5344  * wma_enable_disable_caevent_ind() - Issue WMI command to enable or
5345  * disable ca event indication
5346  * @wma: wma handler
5347  * @val: boolean value true or false
5348  *
5349  * Return: QDF_STATUS
5350  */
wma_enable_disable_caevent_ind(tp_wma_handle wma,uint8_t val)5351 QDF_STATUS wma_enable_disable_caevent_ind(tp_wma_handle wma, uint8_t val)
5352 {
5353 	WMI_CHAN_AVOID_RPT_ALLOW_CMD_fixed_param *cmd;
5354 	wmi_buf_t wmi_buf;
5355 	uint8_t *buf_ptr;
5356 	uint32_t len;
5357 	struct wmi_unified *wmi_handle;
5358 
5359 	if (wma_validate_handle(wma))
5360 		return QDF_STATUS_E_INVAL;
5361 
5362 	wmi_handle = wma->wmi_handle;
5363 	if (wmi_validate_handle(wmi_handle))
5364 		return QDF_STATUS_E_INVAL;
5365 
5366 	len = sizeof(*cmd);
5367 	wmi_buf = wmi_buf_alloc(wmi_handle, len);
5368 	if (!wmi_buf)
5369 		return QDF_STATUS_E_NOMEM;
5370 
5371 	buf_ptr = (uint8_t *) wmi_buf_data(wmi_buf);
5372 	cmd = (WMI_CHAN_AVOID_RPT_ALLOW_CMD_fixed_param *) buf_ptr;
5373 	WMITLV_SET_HDR(&cmd->tlv_header,
5374 		WMITLV_TAG_STRUC_WMI_CHAN_AVOID_RPT_ALLOW_CMD_fixed_param,
5375 		WMITLV_GET_STRUCT_TLVLEN(
5376 				WMI_CHAN_AVOID_RPT_ALLOW_CMD_fixed_param));
5377 	cmd->rpt_allow = val;
5378 	if (wmi_unified_cmd_send(wmi_handle, wmi_buf, len,
5379 				WMI_CHAN_AVOID_RPT_ALLOW_CMDID)) {
5380 		wmi_buf_free(wmi_buf);
5381 		return QDF_STATUS_E_FAILURE;
5382 	}
5383 
5384 	return QDF_STATUS_SUCCESS;
5385 }
5386 
5387 static wma_sar_cb sar_callback;
5388 static void *sar_context;
5389 
wma_sar_event_handler(void * handle,uint8_t * evt_buf,uint32_t len)5390 static int wma_sar_event_handler(void *handle, uint8_t *evt_buf, uint32_t len)
5391 {
5392 	tp_wma_handle wma_handle;
5393 	wmi_unified_t wmi_handle;
5394 	struct sar_limit_event *event;
5395 	wma_sar_cb callback;
5396 	QDF_STATUS status;
5397 
5398 	wma_info("handle:%pK event:%pK len:%u", handle, evt_buf, len);
5399 
5400 	wma_handle = handle;
5401 	if (wma_validate_handle(wma_handle))
5402 		return QDF_STATUS_E_INVAL;
5403 
5404 	wmi_handle = wma_handle->wmi_handle;
5405 	if (wmi_validate_handle(wmi_handle))
5406 		return QDF_STATUS_E_INVAL;
5407 
5408 	event = qdf_mem_malloc(sizeof(*event));
5409 	if (!event)
5410 		return QDF_STATUS_E_NOMEM;
5411 
5412 	status = wmi_unified_extract_sar_limit_event(wmi_handle,
5413 						     evt_buf, event);
5414 	if (QDF_IS_STATUS_ERROR(status)) {
5415 		wma_err("Event extract failure: %d", status);
5416 		qdf_mem_free(event);
5417 		return QDF_STATUS_E_INVAL;
5418 	}
5419 
5420 	callback = sar_callback;
5421 	sar_callback = NULL;
5422 	if (callback)
5423 		callback(sar_context, event);
5424 
5425 	qdf_mem_free(event);
5426 
5427 	return 0;
5428 }
5429 
wma_sar_register_event_handlers(WMA_HANDLE handle)5430 QDF_STATUS wma_sar_register_event_handlers(WMA_HANDLE handle)
5431 {
5432 	tp_wma_handle wma_handle = handle;
5433 	wmi_unified_t wmi_handle;
5434 
5435 	if (wma_validate_handle(wma_handle))
5436 		return QDF_STATUS_E_INVAL;
5437 
5438 	wmi_handle = wma_handle->wmi_handle;
5439 	if (wmi_validate_handle(wmi_handle))
5440 		return QDF_STATUS_E_INVAL;
5441 
5442 	return wmi_unified_register_event_handler(wmi_handle,
5443 						  wmi_sar_get_limits_event_id,
5444 						  wma_sar_event_handler,
5445 						  WMA_RX_WORK_CTX);
5446 }
5447 
wma_get_sar_limit(WMA_HANDLE handle,wma_sar_cb callback,void * context)5448 QDF_STATUS wma_get_sar_limit(WMA_HANDLE handle,
5449 			     wma_sar_cb callback, void *context)
5450 {
5451 	tp_wma_handle wma_handle = handle;
5452 	wmi_unified_t wmi_handle;
5453 	QDF_STATUS status;
5454 
5455 	if (wma_validate_handle(wma_handle))
5456 		return QDF_STATUS_E_INVAL;
5457 
5458 	wmi_handle = wma_handle->wmi_handle;
5459 	if (wmi_validate_handle(wmi_handle))
5460 		return QDF_STATUS_E_INVAL;
5461 
5462 	sar_callback = callback;
5463 	sar_context = context;
5464 	status = wmi_unified_get_sar_limit_cmd(wmi_handle);
5465 	if (QDF_IS_STATUS_ERROR(status)) {
5466 		wma_err("wmi_unified_get_sar_limit_cmd() error: %u",
5467 			 status);
5468 		sar_callback = NULL;
5469 	}
5470 
5471 	return status;
5472 }
5473 
wma_set_sar_limit(WMA_HANDLE handle,struct sar_limit_cmd_params * sar_limit_params)5474 QDF_STATUS wma_set_sar_limit(WMA_HANDLE handle,
5475 		struct sar_limit_cmd_params *sar_limit_params)
5476 {
5477 	int ret;
5478 	tp_wma_handle wma = (tp_wma_handle) handle;
5479 	struct wmi_unified *wmi_handle;
5480 
5481 	if (wma_validate_handle(wma))
5482 		return QDF_STATUS_E_INVAL;
5483 
5484 	wmi_handle = wma->wmi_handle;
5485 	if (wmi_validate_handle(wmi_handle))
5486 		return QDF_STATUS_E_INVAL;
5487 
5488 	if (!sar_limit_params) {
5489 		wma_err("set sar limit ptr NULL");
5490 		return QDF_STATUS_E_INVAL;
5491 	}
5492 
5493 	ret = wmi_unified_send_sar_limit_cmd(wmi_handle,
5494 				sar_limit_params);
5495 
5496 	return ret;
5497 }
5498 
wma_send_coex_config_cmd(WMA_HANDLE wma_handle,struct coex_config_params * coex_cfg_params)5499 QDF_STATUS wma_send_coex_config_cmd(WMA_HANDLE wma_handle,
5500 				    struct coex_config_params *coex_cfg_params)
5501 {
5502 	tp_wma_handle wma = (tp_wma_handle)wma_handle;
5503 	struct wmi_unified *wmi_handle;
5504 
5505 	if (wma_validate_handle(wma))
5506 		return QDF_STATUS_E_INVAL;
5507 
5508 	wmi_handle = wma->wmi_handle;
5509 	if (wmi_validate_handle(wmi_handle))
5510 		return QDF_STATUS_E_INVAL;
5511 
5512 	if (!coex_cfg_params) {
5513 		wma_err("coex cfg params ptr NULL");
5514 		return QDF_STATUS_E_INVAL;
5515 	}
5516 
5517 	return wmi_unified_send_coex_config_cmd(wmi_handle,
5518 					        coex_cfg_params);
5519 }
5520 
5521 /**
5522  * wma_get_arp_stats_handler() - handle arp stats data
5523  * indicated by FW
5524  * @handle: wma context
5525  * @data: event buffer
5526  * @data len: length of event buffer
5527  *
5528  * Return: 0 on success
5529  */
wma_get_arp_stats_handler(void * handle,uint8_t * data,uint32_t data_len)5530 int wma_get_arp_stats_handler(void *handle, uint8_t *data,
5531 			uint32_t data_len)
5532 {
5533 	WMI_VDEV_GET_ARP_STAT_EVENTID_param_tlvs *param_buf;
5534 	wmi_vdev_get_arp_stats_event_fixed_param *data_event;
5535 	wmi_vdev_get_connectivity_check_stats *connect_stats_event;
5536 	uint8_t *buf_ptr;
5537 	struct rsp_stats rsp = {0};
5538 	struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE);
5539 
5540 	if (!mac)
5541 		return -EINVAL;
5542 
5543 	if (!mac->sme.get_arp_stats_cb) {
5544 		wma_err("Callback not registered");
5545 		return -EINVAL;
5546 	}
5547 
5548 	if (!data) {
5549 		wma_err("invalid pointer");
5550 		return -EINVAL;
5551 	}
5552 	param_buf = (WMI_VDEV_GET_ARP_STAT_EVENTID_param_tlvs *)data;
5553 	if (!param_buf) {
5554 		wma_err("Invalid get arp stats event");
5555 		return -EINVAL;
5556 	}
5557 	data_event = param_buf->fixed_param;
5558 	if (!data_event) {
5559 		wma_err("Invalid get arp stats data event");
5560 		return -EINVAL;
5561 	}
5562 	rsp.arp_req_enqueue = data_event->arp_req_enqueue;
5563 	rsp.vdev_id = data_event->vdev_id;
5564 	rsp.arp_req_tx_success = data_event->arp_req_tx_success;
5565 	rsp.arp_req_tx_failure = data_event->arp_req_tx_failure;
5566 	rsp.arp_rsp_recvd = data_event->arp_rsp_recvd;
5567 	rsp.out_of_order_arp_rsp_drop_cnt =
5568 		data_event->out_of_order_arp_rsp_drop_cnt;
5569 	rsp.dad_detected = data_event->dad_detected;
5570 	rsp.connect_status = data_event->connect_status;
5571 	rsp.ba_session_establishment_status =
5572 		data_event->ba_session_establishment_status;
5573 
5574 	buf_ptr = (uint8_t *)data_event;
5575 	buf_ptr = buf_ptr + sizeof(wmi_vdev_get_arp_stats_event_fixed_param) +
5576 		  WMI_TLV_HDR_SIZE;
5577 	connect_stats_event = (wmi_vdev_get_connectivity_check_stats *)buf_ptr;
5578 
5579 	if (((connect_stats_event->tlv_header & 0xFFFF0000) >> 16 ==
5580 	      WMITLV_TAG_STRUC_wmi_vdev_get_connectivity_check_stats)) {
5581 		rsp.connect_stats_present = true;
5582 		rsp.tcp_ack_recvd = connect_stats_event->tcp_ack_recvd;
5583 		rsp.icmpv4_rsp_recvd = connect_stats_event->icmpv4_rsp_recvd;
5584 		wma_debug("tcp_ack_recvd %d icmpv4_rsp_recvd %d",
5585 			connect_stats_event->tcp_ack_recvd,
5586 			connect_stats_event->icmpv4_rsp_recvd);
5587 	}
5588 
5589 	mac->sme.get_arp_stats_cb(mac->hdd_handle, &rsp,
5590 				  mac->sme.get_arp_stats_context);
5591 
5592 	return 0;
5593 }
5594 
5595 /**
5596  * wma_unified_power_debug_stats_event_handler() - WMA handler function to
5597  * handle Power stats event from firmware
5598  * @handle: Pointer to wma handle
5599  * @cmd_param_info: Pointer to Power stats event TLV
5600  * @len: Length of the cmd_param_info
5601  *
5602  * Return: 0 on success, error number otherwise
5603  */
5604  #ifdef WLAN_POWER_DEBUG
wma_unified_power_debug_stats_event_handler(void * handle,uint8_t * cmd_param_info,uint32_t len)5605 int wma_unified_power_debug_stats_event_handler(void *handle,
5606 			uint8_t *cmd_param_info, uint32_t len)
5607 {
5608 	WMI_PDEV_CHIP_POWER_STATS_EVENTID_param_tlvs *param_tlvs;
5609 	struct power_stats_response *power_stats_results;
5610 	wmi_pdev_chip_power_stats_event_fixed_param *param_buf;
5611 	uint32_t power_stats_len, stats_registers_len, *debug_registers;
5612 
5613 	struct mac_context *mac = (struct mac_context *)cds_get_context(QDF_MODULE_ID_PE);
5614 
5615 	param_tlvs =
5616 		(WMI_PDEV_CHIP_POWER_STATS_EVENTID_param_tlvs *) cmd_param_info;
5617 
5618 	param_buf = (wmi_pdev_chip_power_stats_event_fixed_param *)
5619 		param_tlvs->fixed_param;
5620 	if (!mac) {
5621 		wma_debug("NULL mac ptr");
5622 		return -EINVAL;
5623 	}
5624 
5625 	if (!param_buf) {
5626 		wma_debug("NULL power stats event fixed param");
5627 		return -EINVAL;
5628 	}
5629 
5630 	if (param_buf->num_debug_register > ((WMI_SVC_MSG_MAX_SIZE -
5631 		sizeof(wmi_pdev_chip_power_stats_event_fixed_param)) /
5632 		sizeof(uint32_t)) ||
5633 	    param_buf->num_debug_register > param_tlvs->num_debug_registers) {
5634 		wma_err("excess payload: LEN num_debug_register:%u",
5635 			param_buf->num_debug_register);
5636 		return -EINVAL;
5637 	}
5638 	debug_registers = param_tlvs->debug_registers;
5639 	stats_registers_len =
5640 		(sizeof(uint32_t) * param_buf->num_debug_register);
5641 	power_stats_len = stats_registers_len + sizeof(*power_stats_results);
5642 	power_stats_results = qdf_mem_malloc(power_stats_len);
5643 	if (!power_stats_results)
5644 		return -ENOMEM;
5645 
5646 	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",
5647 			param_buf->cumulative_sleep_time_ms,
5648 			param_buf->cumulative_total_on_time_ms,
5649 			param_buf->deep_sleep_enter_counter,
5650 			param_buf->last_deep_sleep_enter_tstamp_ms,
5651 			param_buf->debug_register_fmt,
5652 			param_buf->num_debug_register);
5653 
5654 	power_stats_results->cumulative_sleep_time_ms
5655 		= param_buf->cumulative_sleep_time_ms;
5656 	power_stats_results->cumulative_total_on_time_ms
5657 		= param_buf->cumulative_total_on_time_ms;
5658 	power_stats_results->deep_sleep_enter_counter
5659 		= param_buf->deep_sleep_enter_counter;
5660 	power_stats_results->last_deep_sleep_enter_tstamp_ms
5661 		= param_buf->last_deep_sleep_enter_tstamp_ms;
5662 	power_stats_results->debug_register_fmt
5663 		= param_buf->debug_register_fmt;
5664 	power_stats_results->num_debug_register
5665 		= param_buf->num_debug_register;
5666 
5667 	power_stats_results->debug_registers
5668 		= (uint32_t *)(power_stats_results + 1);
5669 
5670 	qdf_mem_copy(power_stats_results->debug_registers,
5671 			debug_registers, stats_registers_len);
5672 	if (mac->sme.sme_power_debug_stats_callback)
5673 		mac->sme.sme_power_debug_stats_callback(mac,
5674 							power_stats_results);
5675 
5676 	qdf_mem_free(power_stats_results);
5677 	return 0;
5678 }
5679 #endif
5680 
5681 #ifdef WLAN_FEATURE_BEACON_RECEPTION_STATS
wma_unified_beacon_debug_stats_event_handler(void * handle,uint8_t * cmd_param_info,uint32_t len)5682 int wma_unified_beacon_debug_stats_event_handler(void *handle,
5683 						 uint8_t *cmd_param_info,
5684 						 uint32_t len)
5685 {
5686 	WMI_VDEV_BCN_RECEPTION_STATS_EVENTID_param_tlvs *param_tlvs;
5687 	struct bcn_reception_stats_rsp *bcn_reception_stats;
5688 	wmi_vdev_bcn_recv_stats_fixed_param *param_buf;
5689 	struct mac_context *mac =
5690 			(struct mac_context *)cds_get_context(QDF_MODULE_ID_PE);
5691 
5692 	param_tlvs =
5693 	   (WMI_VDEV_BCN_RECEPTION_STATS_EVENTID_param_tlvs *)cmd_param_info;
5694 	if (!param_tlvs) {
5695 		wma_err("Invalid stats event");
5696 		return -EINVAL;
5697 	}
5698 
5699 	param_buf = (wmi_vdev_bcn_recv_stats_fixed_param *)
5700 		param_tlvs->fixed_param;
5701 	if (!param_buf || !mac || !mac->sme.beacon_stats_resp_callback) {
5702 		wma_debug("NULL mac ptr or HDD callback is null");
5703 		return -EINVAL;
5704 	}
5705 
5706 	if (!param_buf) {
5707 		wma_debug("NULL beacon stats event fixed param");
5708 		return -EINVAL;
5709 	}
5710 
5711 	bcn_reception_stats = qdf_mem_malloc(sizeof(*bcn_reception_stats));
5712 	if (!bcn_reception_stats)
5713 		return -ENOMEM;
5714 
5715 	bcn_reception_stats->total_bcn_cnt = param_buf->total_bcn_cnt;
5716 	bcn_reception_stats->total_bmiss_cnt = param_buf->total_bmiss_cnt;
5717 	bcn_reception_stats->vdev_id = param_buf->vdev_id;
5718 
5719 	wma_debug("Total beacon count %d total beacon miss count %d vdev_id %d",
5720 		 param_buf->total_bcn_cnt,
5721 		 param_buf->total_bmiss_cnt,
5722 		 param_buf->vdev_id);
5723 
5724 	qdf_mem_copy(bcn_reception_stats->bmiss_bitmap,
5725 		     param_buf->bmiss_bitmap,
5726 		     MAX_BCNMISS_BITMAP * sizeof(uint32_t));
5727 
5728 	mac->sme.beacon_stats_resp_callback(bcn_reception_stats,
5729 			mac->sme.beacon_stats_context);
5730 	qdf_mem_free(bcn_reception_stats);
5731 	return 0;
5732 }
5733 #else
wma_unified_beacon_debug_stats_event_handler(void * handle,uint8_t * cmd_param_info,uint32_t len)5734 int wma_unified_beacon_debug_stats_event_handler(void *handle,
5735 						 uint8_t *cmd_param_info,
5736 						  uint32_t len)
5737 {
5738 	return 0;
5739 }
5740 #endif
5741 
5742 #if defined(CLD_PM_QOS) && defined(WLAN_FEATURE_LL_MODE)
5743 int
wma_vdev_bcn_latency_event_handler(void * handle,uint8_t * event_info,uint32_t len)5744 wma_vdev_bcn_latency_event_handler(void *handle,
5745 				   uint8_t *event_info,
5746 				   uint32_t len)
5747 {
5748 	WMI_VDEV_BCN_LATENCY_EVENTID_param_tlvs *param_buf = NULL;
5749 	wmi_vdev_bcn_latency_fixed_param *bcn_latency = NULL;
5750 	struct mac_context *mac =
5751 			(struct mac_context *)cds_get_context(QDF_MODULE_ID_PE);
5752 	uint32_t latency_level;
5753 
5754 	param_buf = (WMI_VDEV_BCN_LATENCY_EVENTID_param_tlvs *)event_info;
5755 	if (!param_buf) {
5756 		wma_err("Invalid bcn latency event");
5757 		return -EINVAL;
5758 	}
5759 
5760 	bcn_latency = param_buf->fixed_param;
5761 	if (!bcn_latency) {
5762 		wma_debug("beacon latency event fixed param is NULL");
5763 		return -EINVAL;
5764 	}
5765 
5766 	/* Map the latency value to the level which host expects
5767 	 * 1 - normal, 2 - moderate, 3 - low, 4 - ultralow
5768 	 */
5769 	latency_level = bcn_latency->latency_level + 1;
5770 	if (latency_level < 1 || latency_level > 4) {
5771 		wma_debug("invalid beacon latency level value");
5772 		return -EINVAL;
5773 	}
5774 
5775 	/* Call the registered sme callback */
5776 	mac->sme.beacon_latency_event_cb(latency_level);
5777 
5778 	return 0;
5779 }
5780 #endif
5781 
5782 static void
wma_update_scan_channel_info_buf(wmi_unified_t wmi_handle,wmi_chan_info_event_fixed_param * event,struct scan_chan_info * buf,wmi_cca_busy_subband_info * cca_info,uint32_t num_tlvs)5783 wma_update_scan_channel_info_buf(wmi_unified_t wmi_handle,
5784 				 wmi_chan_info_event_fixed_param *event,
5785 				 struct scan_chan_info *buf,
5786 				 wmi_cca_busy_subband_info *cca_info,
5787 				 uint32_t num_tlvs)
5788 {
5789 	uint32_t i;
5790 
5791 	if (cca_info && num_tlvs > 0) {
5792 		buf->subband_info.num_chan = 0;
5793 		for (i = 0; i < num_tlvs && i < MAX_WIDE_BAND_SCAN_CHAN; i++) {
5794 			buf->subband_info.cca_busy_subband_info[i] =
5795 						cca_info->rx_clear_count;
5796 			wma_debug("cca_info->rx_clear_count:%d",
5797 				  cca_info->rx_clear_count);
5798 			buf->subband_info.num_chan++;
5799 			cca_info++;
5800 		}
5801 
5802 		buf->subband_info.is_wide_band_scan = true;
5803 		buf->subband_info.vdev_id = event->vdev_id;
5804 	}
5805 }
5806 
5807 static void
wma_update_scan_channel_subband_info(wmi_chan_info_event_fixed_param * event,struct channel_status * channel_status,wmi_cca_busy_subband_info * cca_info,uint32_t num_tlvs)5808 wma_update_scan_channel_subband_info(wmi_chan_info_event_fixed_param *event,
5809 				     struct channel_status *channel_status,
5810 				     wmi_cca_busy_subband_info *cca_info,
5811 				     uint32_t num_tlvs)
5812 {
5813 	uint32_t i;
5814 
5815 	if (cca_info && num_tlvs > 0) {
5816 		channel_status->subband_info.num_chan = 0;
5817 		for (i = 0; i < num_tlvs && i < MAX_WIDE_BAND_SCAN_CHAN; i++) {
5818 			channel_status->subband_info.cca_busy_subband_info[i] =
5819 						cca_info->rx_clear_count;
5820 			wma_debug("cca_info->rx_clear_count[%d]: %d", i,
5821 				  cca_info->rx_clear_count);
5822 			channel_status->subband_info.num_chan++;
5823 			cca_info++;
5824 		}
5825 
5826 		channel_status->subband_info.is_wide_band_scan = true;
5827 		channel_status->subband_info.vdev_id = event->vdev_id;
5828 	}
5829 }
5830 
wma_chan_info_event_handler(void * handle,uint8_t * event_buf,uint32_t len)5831 int wma_chan_info_event_handler(void *handle, uint8_t *event_buf, uint32_t len)
5832 {
5833 	tp_wma_handle wma = (tp_wma_handle)handle;
5834 	WMI_CHAN_INFO_EVENTID_param_tlvs *param_buf;
5835 	wmi_chan_info_event_fixed_param *event;
5836 	struct scan_chan_info buf = {0};
5837 	struct mac_context *mac = NULL;
5838 	struct channel_status *channel_status;
5839 	bool snr_monitor_enabled;
5840 	struct scheduler_msg sme_msg = {0};
5841 	wmi_cca_busy_subband_info *cca_info = NULL;
5842 	uint32_t num_tlvs = 0;
5843 	bool is_cca_busy_info;
5844 	QDF_STATUS qdf_status;
5845 
5846 	if (wma && wma->cds_context)
5847 		mac = (struct mac_context *)cds_get_context(QDF_MODULE_ID_PE);
5848 
5849 	if (!mac)
5850 		return -EINVAL;
5851 
5852 	param_buf = (WMI_CHAN_INFO_EVENTID_param_tlvs *)event_buf;
5853 	if (!param_buf)  {
5854 		wma_err("Invalid chan info event buffer");
5855 		return -EINVAL;
5856 	}
5857 
5858 	event = param_buf->fixed_param;
5859 	if (!event) {
5860 		wma_err("Invalid fixed param");
5861 		return -EINVAL;
5862 	}
5863 
5864 	/* Ignore the last channel event data whose command flag is set to 1.
5865 	 * It’s basically an event with empty data only to indicate scan event
5866 	 * completion.
5867 	 */
5868 	if (event->cmd_flags == WMI_CHAN_INFO_END_RESP)
5869 		return 0;
5870 
5871 	cca_info = param_buf->cca_busy_subband_info;
5872 	num_tlvs  = param_buf->num_cca_busy_subband_info;
5873 	is_cca_busy_info = wmi_service_enabled(wma->wmi_handle,
5874 				wmi_service_cca_busy_info_for_each_20mhz);
5875 
5876 	snr_monitor_enabled = wlan_scan_is_snr_monitor_enabled(mac->psoc);
5877 	if (snr_monitor_enabled && mac->chan_info_cb) {
5878 		buf.tx_frame_count = event->tx_frame_cnt;
5879 		buf.clock_freq = event->mac_clk_mhz;
5880 		buf.cmd_flag = event->cmd_flags;
5881 		buf.freq = event->freq;
5882 		buf.noise_floor = event->noise_floor;
5883 		buf.cycle_count = event->cycle_count;
5884 		buf.rx_clear_count = event->rx_clear_count;
5885 		/* wide band scan case */
5886 		if (is_cca_busy_info && num_tlvs)
5887 			wma_update_scan_channel_info_buf(wma->wmi_handle,
5888 							 event, &buf,
5889 							 cca_info, num_tlvs);
5890 		mac->chan_info_cb(&buf);
5891 	}
5892 
5893 	channel_status = qdf_mem_malloc(sizeof(*channel_status));
5894 	if (!channel_status)
5895 		return -ENOMEM;
5896 
5897 	channel_status->channel_freq = event->freq;
5898 	channel_status->noise_floor = event->noise_floor;
5899 
5900 	if (is_cca_busy_info && num_tlvs)
5901 		wma_update_scan_channel_subband_info(event, channel_status,
5902 						     cca_info, num_tlvs);
5903 	else
5904 		channel_status->rx_clear_count = event->rx_clear_count;
5905 
5906 	channel_status->cycle_count = event->cycle_count;
5907 	channel_status->chan_tx_pwr_range = event->chan_tx_pwr_range;
5908 	channel_status->chan_tx_pwr_throughput = event->chan_tx_pwr_tp;
5909 	channel_status->rx_frame_count = event->rx_frame_count;
5910 	channel_status->bss_rx_cycle_count = event->my_bss_rx_cycle_count;
5911 	channel_status->rx_11b_mode_data_duration =
5912 			event->rx_11b_mode_data_duration;
5913 	channel_status->tx_frame_count = event->tx_frame_cnt;
5914 	channel_status->mac_clk_mhz = event->mac_clk_mhz;
5915 	channel_status->channel_id = cds_freq_to_chan(event->freq);
5916 	channel_status->cmd_flags = event->cmd_flags;
5917 
5918 	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",
5919 		  event->freq, event->noise_floor,
5920 		  event->rx_clear_count, channel_status->rx_clear_count,
5921 		  event->cycle_count, event->chan_tx_pwr_range,
5922 		  event->chan_tx_pwr_tp, channel_status->channel_id,
5923 		  channel_status->cmd_flags, is_cca_busy_info, num_tlvs);
5924 
5925 	sme_msg.type = eWNI_SME_CHAN_INFO_EVENT;
5926 	sme_msg.bodyptr = channel_status;
5927 	sme_msg.bodyval = event->vdev_id;
5928 	qdf_status = scheduler_post_message(QDF_MODULE_ID_WMA,
5929 					    QDF_MODULE_ID_SME,
5930 					    QDF_MODULE_ID_SME, &sme_msg);
5931 	if (QDF_IS_STATUS_ERROR(qdf_status))
5932 		qdf_mem_free(channel_status);
5933 
5934 	return 0;
5935 }
5936 
wma_rx_aggr_failure_event_handler(void * handle,u_int8_t * event_buf,u_int32_t len)5937 int wma_rx_aggr_failure_event_handler(void *handle, u_int8_t *event_buf,
5938 							u_int32_t len)
5939 {
5940 	WMI_REPORT_RX_AGGR_FAILURE_EVENTID_param_tlvs *param_buf;
5941 	struct sir_sme_rx_aggr_hole_ind *rx_aggr_hole_event;
5942 	wmi_rx_aggr_failure_event_fixed_param *rx_aggr_failure_info;
5943 	wmi_rx_aggr_failure_info *hole_info;
5944 	uint32_t i, alloc_len;
5945 	struct mac_context *mac;
5946 
5947 	mac = (struct mac_context *)cds_get_context(QDF_MODULE_ID_PE);
5948 	if (!mac || !mac->sme.stats_ext2_cb) {
5949 		wma_debug("NULL mac ptr or HDD callback is null");
5950 		return -EINVAL;
5951 	}
5952 
5953 	param_buf = (WMI_REPORT_RX_AGGR_FAILURE_EVENTID_param_tlvs *)event_buf;
5954 	if (!param_buf) {
5955 		wma_err("Invalid stats ext event buf");
5956 		return -EINVAL;
5957 	}
5958 
5959 	rx_aggr_failure_info = param_buf->fixed_param;
5960 	hole_info = param_buf->failure_info;
5961 
5962 	if (rx_aggr_failure_info->num_failure_info > ((WMI_SVC_MSG_MAX_SIZE -
5963 	    sizeof(*rx_aggr_hole_event)) /
5964 	    sizeof(rx_aggr_hole_event->hole_info_array[0]))) {
5965 		wma_err("Excess data from WMI num_failure_info %d",
5966 			rx_aggr_failure_info->num_failure_info);
5967 		return -EINVAL;
5968 	}
5969 
5970 	alloc_len = sizeof(*rx_aggr_hole_event) +
5971 		(rx_aggr_failure_info->num_failure_info)*
5972 		sizeof(rx_aggr_hole_event->hole_info_array[0]);
5973 	rx_aggr_hole_event = qdf_mem_malloc(alloc_len);
5974 	if (!rx_aggr_hole_event)
5975 		return -ENOMEM;
5976 
5977 	rx_aggr_hole_event->hole_cnt = rx_aggr_failure_info->num_failure_info;
5978 	if (rx_aggr_hole_event->hole_cnt > param_buf->num_failure_info) {
5979 		wma_err("Invalid no of hole count: %d",
5980 			rx_aggr_hole_event->hole_cnt);
5981 		qdf_mem_free(rx_aggr_hole_event);
5982 		return -EINVAL;
5983 	}
5984 	wma_debug("aggr holes_sum: %d\n",
5985 		rx_aggr_failure_info->num_failure_info);
5986 	for (i = 0; i < rx_aggr_hole_event->hole_cnt; i++) {
5987 		rx_aggr_hole_event->hole_info_array[i] =
5988 			hole_info->end_seq - hole_info->start_seq + 1;
5989 		wma_nofl_debug("aggr_index: %d\tstart_seq: %d\tend_seq: %d\t"
5990 			"hole_info: %d mpdu lost",
5991 			i, hole_info->start_seq, hole_info->end_seq,
5992 			rx_aggr_hole_event->hole_info_array[i]);
5993 		hole_info++;
5994 	}
5995 
5996 	mac->sme.stats_ext2_cb(mac->hdd_handle, rx_aggr_hole_event);
5997 	qdf_mem_free(rx_aggr_hole_event);
5998 
5999 	return 0;
6000 }
6001 
wma_wlan_bt_activity_evt_handler(void * handle,uint8_t * event,uint32_t len)6002 int wma_wlan_bt_activity_evt_handler(void *handle, uint8_t *event, uint32_t len)
6003 {
6004 	wmi_coex_bt_activity_event_fixed_param *fixed_param;
6005 	WMI_WLAN_COEX_BT_ACTIVITY_EVENTID_param_tlvs *param_buf =
6006 		(WMI_WLAN_COEX_BT_ACTIVITY_EVENTID_param_tlvs *)event;
6007 	struct scheduler_msg sme_msg = {0};
6008 	QDF_STATUS qdf_status;
6009 
6010 	if (!param_buf) {
6011 		wma_err("Invalid BT activity event buffer");
6012 		return -EINVAL;
6013 	}
6014 
6015 	fixed_param = param_buf->fixed_param;
6016 	if (!fixed_param) {
6017 		wma_err("Invalid BT activity event fixed param buffer");
6018 		return -EINVAL;
6019 	}
6020 
6021 	wma_info("Received BT activity event %u",
6022 		fixed_param->coex_profile_evt);
6023 
6024 	sme_msg.type = eWNI_SME_BT_ACTIVITY_INFO_IND;
6025 	sme_msg.bodyptr = NULL;
6026 	sme_msg.bodyval = fixed_param->coex_profile_evt;
6027 
6028 	qdf_status = scheduler_post_message(QDF_MODULE_ID_WMA,
6029 					    QDF_MODULE_ID_SME,
6030 					    QDF_MODULE_ID_SME, &sme_msg);
6031 	if (QDF_IS_STATUS_ERROR(qdf_status))
6032 		return -EINVAL;
6033 
6034 	return 0;
6035 }
6036 
wma_pdev_div_info_evt_handler(void * handle,u_int8_t * event_buf,u_int32_t len)6037 int wma_pdev_div_info_evt_handler(void *handle, u_int8_t *event_buf,
6038 	u_int32_t len)
6039 {
6040 	WMI_PDEV_DIV_RSSI_ANTID_EVENTID_param_tlvs *param_buf;
6041 	wmi_pdev_div_rssi_antid_event_fixed_param *event;
6042 	struct chain_rssi_result chain_rssi_result;
6043 	u_int32_t i;
6044 	u_int8_t macaddr[QDF_MAC_ADDR_SIZE];
6045 	tp_wma_handle wma = (tp_wma_handle)handle;
6046 
6047 	struct mac_context *pmac = (struct mac_context *)cds_get_context(
6048 					QDF_MODULE_ID_PE);
6049 	if (!pmac || !wma) {
6050 		wma_err("Invalid pmac or wma");
6051 		return -EINVAL;
6052 	}
6053 
6054 	if (!pmac->sme.get_chain_rssi_cb) {
6055 		wma_err("Invalid get_chain_rssi_cb");
6056 		return -EINVAL;
6057 	}
6058 	param_buf = (WMI_PDEV_DIV_RSSI_ANTID_EVENTID_param_tlvs *) event_buf;
6059 	if (!param_buf) {
6060 		wma_err("Invalid rssi antid event buffer");
6061 		return -EINVAL;
6062 	}
6063 
6064 	event = param_buf->fixed_param;
6065 	if (!event) {
6066 		wma_err("Invalid fixed param");
6067 		return -EINVAL;
6068 	}
6069 
6070 	if (event->num_chains_valid > CHAIN_MAX_NUM) {
6071 		wma_err("Invalid num of chains");
6072 		return -EINVAL;
6073 	}
6074 
6075 	qdf_mem_zero(&chain_rssi_result, sizeof(chain_rssi_result));
6076 
6077 	WMI_MAC_ADDR_TO_CHAR_ARRAY(&event->macaddr, macaddr);
6078 	wma_debug("macaddr: " QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(macaddr));
6079 
6080 	wma_debug("num_chains_valid: %d", event->num_chains_valid);
6081 	chain_rssi_result.num_chains_valid = event->num_chains_valid;
6082 
6083 	qdf_mem_copy(chain_rssi_result.chain_rssi, event->chain_rssi,
6084 		     sizeof(event->chain_rssi));
6085 
6086 	qdf_mem_copy(chain_rssi_result.chain_evm, event->chain_evm,
6087 		     sizeof(event->chain_evm));
6088 
6089 	qdf_mem_copy(chain_rssi_result.ant_id, event->ant_id,
6090 		     sizeof(event->ant_id));
6091 
6092 	for (i = 0; i < chain_rssi_result.num_chains_valid; i++) {
6093 		wma_nofl_debug("chain_rssi: %d, chain_evm: %d,ant_id: %d",
6094 			 chain_rssi_result.chain_rssi[i],
6095 			 chain_rssi_result.chain_evm[i],
6096 			 chain_rssi_result.ant_id[i]);
6097 
6098 		if (!wmi_service_enabled(wma->wmi_handle,
6099 					 wmi_service_hw_db2dbm_support)) {
6100 			if (chain_rssi_result.chain_rssi[i] !=
6101 			    WMA_INVALID_PER_CHAIN_SNR)
6102 				chain_rssi_result.chain_rssi[i] +=
6103 						WMA_TGT_NOISE_FLOOR_DBM;
6104 			else
6105 				chain_rssi_result.chain_rssi[i] =
6106 						WMA_INVALID_PER_CHAIN_RSSI;
6107 		}
6108 	}
6109 
6110 	pmac->sme.get_chain_rssi_cb(pmac->sme.get_chain_rssi_context,
6111 				&chain_rssi_result);
6112 
6113 	return 0;
6114 }
6115 
wma_vdev_obss_detection_info_handler(void * handle,uint8_t * event,uint32_t len)6116 int wma_vdev_obss_detection_info_handler(void *handle, uint8_t *event,
6117 					 uint32_t len)
6118 {
6119 	tp_wma_handle wma = (tp_wma_handle) handle;
6120 	struct wmi_obss_detect_info *obss_detection;
6121 	QDF_STATUS status;
6122 
6123 	if (!event) {
6124 		wma_err("Invalid obss_detection_info event buffer");
6125 		return -EINVAL;
6126 	}
6127 
6128 	obss_detection = qdf_mem_malloc(sizeof(*obss_detection));
6129 	if (!obss_detection)
6130 		return -ENOMEM;
6131 
6132 	status = wmi_unified_extract_obss_detection_info(wma->wmi_handle,
6133 							 event, obss_detection);
6134 
6135 	if (QDF_IS_STATUS_ERROR(status)) {
6136 		wma_err("Failed to extract obss info");
6137 		qdf_mem_free(obss_detection);
6138 		return -EINVAL;
6139 	}
6140 
6141 	if (!wma_is_vdev_valid(obss_detection->vdev_id)) {
6142 		wma_err("Invalid vdev id %d", obss_detection->vdev_id);
6143 		qdf_mem_free(obss_detection);
6144 		return -EINVAL;
6145 	}
6146 
6147 	wma_send_msg(wma, WMA_OBSS_DETECTION_INFO, obss_detection, 0);
6148 
6149 	return 0;
6150 }
6151 
wma_send_set_key_rsp(uint8_t vdev_id,bool pairwise,uint8_t key_index)6152 static void wma_send_set_key_rsp(uint8_t vdev_id, bool pairwise,
6153 				 uint8_t key_index)
6154 {
6155 	tSetStaKeyParams *key_info_uc;
6156 	tSetBssKeyParams *key_info_mc;
6157 	struct wlan_crypto_key *crypto_key;
6158 	struct wlan_objmgr_vdev *vdev;
6159 	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
6160 	struct qdf_mac_addr bcast_mac = QDF_MAC_ADDR_BCAST_INIT;
6161 
6162 	if (!wma)
6163 		return;
6164 
6165 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(wma->psoc,
6166 						    vdev_id,
6167 						    WLAN_LEGACY_WMA_ID);
6168 	if (!vdev) {
6169 		wma_err("VDEV object not found");
6170 		return;
6171 	}
6172 	crypto_key = wlan_crypto_get_key(vdev, key_index);
6173 
6174 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_WMA_ID);
6175 	if (!crypto_key) {
6176 		wma_debug("crypto_key not found");
6177 		return;
6178 	}
6179 
6180 	if (pairwise) {
6181 		key_info_uc = qdf_mem_malloc(sizeof(*key_info_uc));
6182 		if (!key_info_uc)
6183 			return;
6184 		key_info_uc->vdev_id = vdev_id;
6185 		key_info_uc->status = QDF_STATUS_SUCCESS;
6186 		key_info_uc->key_len = crypto_key->keylen;
6187 		qdf_mem_copy(&key_info_uc->macaddr, &crypto_key->macaddr,
6188 			     QDF_MAC_ADDR_SIZE);
6189 		wma_send_msg_high_priority(wma, WMA_SET_STAKEY_RSP,
6190 					   key_info_uc, 0);
6191 		wlan_release_peer_key_wakelock(wma->pdev, crypto_key->macaddr);
6192 	} else {
6193 		key_info_mc = qdf_mem_malloc(sizeof(*key_info_mc));
6194 		if (!key_info_mc)
6195 			return;
6196 		key_info_mc->vdev_id = vdev_id;
6197 		key_info_mc->status = QDF_STATUS_SUCCESS;
6198 		key_info_mc->key_len = crypto_key->keylen;
6199 		qdf_mem_copy(&key_info_mc->macaddr, &bcast_mac,
6200 			     QDF_MAC_ADDR_SIZE);
6201 		wma_send_msg_high_priority(wma, WMA_SET_BSSKEY_RSP,
6202 					   key_info_mc, 0);
6203 	}
6204 }
6205 
wma_set_peer_ucast_cipher(uint8_t * mac_addr,int32_t uc_cipher,int32_t cipher_cap)6206 void wma_set_peer_ucast_cipher(uint8_t *mac_addr, int32_t uc_cipher,
6207 			       int32_t cipher_cap)
6208 {
6209 	struct wlan_objmgr_peer *peer;
6210 	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
6211 
6212 	if (!wma)
6213 		return;
6214 	peer = wlan_objmgr_get_peer(wma->psoc,
6215 				    wlan_objmgr_pdev_get_pdev_id(wma->pdev),
6216 				    mac_addr, WLAN_LEGACY_WMA_ID);
6217 	if (!peer) {
6218 		wma_err("Peer of peer_mac "QDF_MAC_ADDR_FMT" not found",
6219 			QDF_MAC_ADDR_REF(mac_addr));
6220 		return;
6221 	}
6222 
6223 	wlan_crypto_set_peer_param(peer, WLAN_CRYPTO_PARAM_CIPHER_CAP,
6224 				   cipher_cap);
6225 	wlan_crypto_set_peer_param(peer, WLAN_CRYPTO_PARAM_UCAST_CIPHER,
6226 				   uc_cipher);
6227 	wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_WMA_ID);
6228 
6229 	wma_debug("Set unicast cipher %x and cap %x for "QDF_MAC_ADDR_FMT,
6230 		  uc_cipher, cipher_cap, QDF_MAC_ADDR_REF(mac_addr));
6231 }
6232 
wma_update_set_key(uint8_t session_id,bool pairwise,uint8_t key_index,enum wlan_crypto_cipher_type cipher_type)6233 void wma_update_set_key(uint8_t session_id, bool pairwise,
6234 			uint8_t key_index,
6235 			enum wlan_crypto_cipher_type cipher_type)
6236 {
6237 	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
6238 	struct wma_txrx_node *iface;
6239 
6240 	if (!wma)
6241 		return;
6242 
6243 	iface = &wma->interfaces[session_id];
6244 	if (!iface) {
6245 		wma_err("iface not found for session id %d", session_id);
6246 		return;
6247 	}
6248 
6249 	if (iface)
6250 		iface->is_waiting_for_key = false;
6251 
6252 	wma_send_set_key_rsp(session_id, pairwise, key_index);
6253 }
6254 
wma_vdev_bss_color_collision_info_handler(void * handle,uint8_t * event,uint32_t len)6255 int wma_vdev_bss_color_collision_info_handler(void *handle,
6256 					      uint8_t *event,
6257 					      uint32_t len)
6258 {
6259 	tp_wma_handle wma = (tp_wma_handle) handle;
6260 	struct wmi_obss_color_collision_info *obss_color_info;
6261 	QDF_STATUS status;
6262 
6263 	if (!event) {
6264 		wma_err("Invalid obss_color_collision event buffer");
6265 		return -EINVAL;
6266 	}
6267 
6268 	obss_color_info = qdf_mem_malloc(sizeof(*obss_color_info));
6269 	if (!obss_color_info)
6270 		return -ENOMEM;
6271 
6272 	status = wmi_unified_extract_obss_color_collision_info(wma->wmi_handle,
6273 							       event,
6274 							       obss_color_info);
6275 
6276 	if (QDF_IS_STATUS_ERROR(status)) {
6277 		wma_err("Failed to extract obss color info");
6278 		qdf_mem_free(obss_color_info);
6279 		return -EINVAL;
6280 	}
6281 
6282 	if (!wma_is_vdev_valid(obss_color_info->vdev_id)) {
6283 		wma_err("Invalid vdev id %d", obss_color_info->vdev_id);
6284 		qdf_mem_free(obss_color_info);
6285 		return -EINVAL;
6286 	}
6287 
6288 	wma_send_msg(wma, WMA_OBSS_COLOR_COLLISION_INFO, obss_color_info, 0);
6289 
6290 	return 0;
6291 }
6292 
6293 #ifdef FEATURE_ANI_LEVEL_REQUEST
wma_get_ani_level_evt_handler(void * handle,uint8_t * event_buf,uint32_t len)6294 int wma_get_ani_level_evt_handler(void *handle, uint8_t *event_buf,
6295 				  uint32_t len)
6296 {
6297 	tp_wma_handle wma = (tp_wma_handle)handle;
6298 	struct wmi_host_ani_level_event *ani = NULL;
6299 	uint32_t num_freqs = 0;
6300 	QDF_STATUS status;
6301 	struct mac_context *pmac;
6302 	int ret = 0;
6303 
6304 	pmac = (struct mac_context *)cds_get_context(QDF_MODULE_ID_PE);
6305 	if (!pmac || !wma) {
6306 		wma_err("Invalid pmac or wma");
6307 		return -EINVAL;
6308 	}
6309 
6310 	status = wmi_unified_extract_ani_level(wma->wmi_handle, event_buf,
6311 					       &ani, &num_freqs);
6312 
6313 	if (QDF_IS_STATUS_ERROR(status)) {
6314 		wma_err("Failed to extract ani level");
6315 		return -EINVAL;
6316 	}
6317 
6318 	if (!pmac->ani_params.ani_level_cb) {
6319 		wma_err("Invalid ani_level_cb");
6320 		ret = -EINVAL;
6321 		goto free;
6322 	}
6323 
6324 	pmac->ani_params.ani_level_cb(ani, num_freqs,
6325 				      pmac->ani_params.context);
6326 
6327 free:
6328 	qdf_mem_free(ani);
6329 	return ret;
6330 }
6331 #else
wma_get_ani_level_evt_handler(void * handle,uint8_t * event_buf,uint32_t len)6332 int wma_get_ani_level_evt_handler(void *handle, uint8_t *event_buf,
6333 				  uint32_t len)
6334 {
6335 	return 0;
6336 }
6337 #endif
6338 
6339