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