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 *)¶m,
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 *)¶ms.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(¶ms.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, ¶ms);
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(¶ms_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 ¶ms->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(¶ms.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 ¶ms);
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