blob: a9323d22871dfd60d3a6a9062f56f95fc83c8466 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Paul Zhange79e7db2017-01-04 16:37:05 +08002 * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/**
29 * DOC: wma_features.c
30 * This file contains different features related functions like WoW,
31 * Offloads, TDLS etc.
32 */
33
34/* Header files */
35
Himanshu Agarwaldd356df2016-07-20 19:04:39 +053036#include "cds_ieee80211_common.h" /* ieee80211_frame */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080037#include "wma.h"
38#include "wma_api.h"
39#include "cds_api.h"
40#include "wmi_unified_api.h"
41#include "wlan_qct_sys.h"
42#include "wni_api.h"
43#include "ani_global.h"
44#include "wmi_unified.h"
45#include "wni_cfg.h"
46#include "cfg_api.h"
Manjunathappa Prakash3454fd62016-04-01 08:52:06 -070047#include <cdp_txrx_tx_delay.h>
Manjunathappa Prakash3454fd62016-04-01 08:52:06 -070048#include <cdp_txrx_peer_ops.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080049
Nirav Shahcbc6d722016-03-01 16:24:53 +053050#include "qdf_nbuf.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053051#include "qdf_types.h"
Anurag Chouhan600c3a02016-03-01 10:33:54 +053052#include "qdf_mem.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080053
54#include "wma_types.h"
55#include "lim_api.h"
56#include "lim_session_utils.h"
57
58#include "cds_utils.h"
59
60#if !defined(REMOVE_PKT_LOG)
61#include "pktlog_ac.h"
62#endif /* REMOVE_PKT_LOG */
63
64#include "dbglog_host.h"
65#include "csr_api.h"
66#include "ol_fw.h"
67
68#include "dfs.h"
69#include "radar_filters.h"
70#include "wma_internal.h"
Naveen Rawate82c1f32016-06-22 15:34:36 -070071#include "wma_nan_datapath.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080072
73#ifndef ARRAY_LENGTH
74#define ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0]))
75#endif
76
77#define WMA_WOW_STA_WAKE_UP_EVENTS ((1 << WOW_CSA_IE_EVENT) |\
78 (1 << WOW_CLIENT_KICKOUT_EVENT) |\
79 (1 << WOW_PATTERN_MATCH_EVENT) |\
80 (1 << WOW_MAGIC_PKT_RECVD_EVENT) |\
81 (1 << WOW_DEAUTH_RECVD_EVENT) |\
82 (1 << WOW_DISASSOC_RECVD_EVENT) |\
83 (1 << WOW_BMISS_EVENT) |\
84 (1 << WOW_GTK_ERR_EVENT) |\
85 (1 << WOW_BETTER_AP_EVENT) |\
86 (1 << WOW_HTT_EVENT) |\
87 (1 << WOW_RA_MATCH_EVENT) |\
88 (1 << WOW_NLO_DETECTED_EVENT) |\
Selvaraj, Sridhar172cabc2016-07-05 15:19:24 +053089 (1 << WOW_EXTSCAN_EVENT)) |\
Masti, Narayanraddi2194de22016-09-20 16:34:02 +053090 (1 << WOW_OEM_RESPONSE_EVENT)|\
91 (1 << WOW_TDLS_CONN_TRACKER_EVENT)\
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080092
93#define WMA_WOW_SAP_WAKE_UP_EVENTS ((1 << WOW_PROBE_REQ_WPS_IE_EVENT) |\
94 (1 << WOW_PATTERN_MATCH_EVENT) |\
95 (1 << WOW_AUTH_REQ_EVENT) |\
96 (1 << WOW_ASSOC_REQ_EVENT) |\
97 (1 << WOW_DEAUTH_RECVD_EVENT) |\
98 (1 << WOW_DISASSOC_RECVD_EVENT) |\
99 (1 << WOW_HTT_EVENT))\
100
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +0530101/**
102 * WMA_SET_VDEV_IE_SOURCE_HOST - Flag to identify the source of VDEV SET IE
103 * command. The value is 0x0 for the VDEV SET IE WMI commands from mobile
104 * MCL platform.
105 */
106#define WMA_SET_VDEV_IE_SOURCE_HOST 0x0
107
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800108static const uint8_t arp_ptrn[] = {0x08, 0x06};
109static const uint8_t arp_mask[] = {0xff, 0xff};
110static const uint8_t ns_ptrn[] = {0x86, 0xDD};
111static const uint8_t discvr_ptrn[] = {0xe0, 0x00, 0x00, 0xf8};
112static const uint8_t discvr_mask[] = {0xf0, 0x00, 0x00, 0xf8};
113
114#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
115/**
116 * wma_post_auto_shutdown_msg() - to post auto shutdown event to sme
117 *
118 * Return: 0 for success or error code
119 */
120static int wma_post_auto_shutdown_msg(void)
121{
122 tSirAutoShutdownEvtParams *auto_sh_evt;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530123 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800124 cds_msg_t sme_msg = { 0 };
125
126 auto_sh_evt = (tSirAutoShutdownEvtParams *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530127 qdf_mem_malloc(sizeof(tSirAutoShutdownEvtParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800128 if (!auto_sh_evt) {
129 WMA_LOGE(FL("No Mem"));
130 return -ENOMEM;
131 }
132
133 auto_sh_evt->shutdown_reason =
134 WMI_HOST_AUTO_SHUTDOWN_REASON_TIMER_EXPIRY;
135 sme_msg.type = eWNI_SME_AUTO_SHUTDOWN_IND;
136 sme_msg.bodyptr = auto_sh_evt;
137 sme_msg.bodyval = 0;
138
Anurag Chouhan6d760662016-02-20 16:05:43 +0530139 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530140 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800141 WMA_LOGE("Fail to post eWNI_SME_AUTO_SHUTDOWN_IND msg to SME");
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530142 qdf_mem_free(auto_sh_evt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800143 return -EINVAL;
144 }
145
146 return 0;
147}
148#endif
149/**
150 * wma_send_snr_request() - send request to fw to get RSSI stats
151 * @wma_handle: wma handle
152 * @pGetRssiReq: get RSSI request
153 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530154 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800155 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530156QDF_STATUS wma_send_snr_request(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800157 void *pGetRssiReq)
158{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800159 tAniGetRssiReq *pRssiBkUp = NULL;
160
161 /* command is in progess */
162 if (NULL != wma_handle->pGetRssiReq)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530163 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800164
165 /* create a copy of csrRssiCallback to send rssi value
166 * after wmi event
167 */
168 if (pGetRssiReq) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530169 pRssiBkUp = qdf_mem_malloc(sizeof(tAniGetRssiReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800170 if (!pRssiBkUp) {
171 WMA_LOGE("Failed to allocate memory for tAniGetRssiReq");
172 wma_handle->pGetRssiReq = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530173 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800174 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800175 pRssiBkUp->sessionId =
176 ((tAniGetRssiReq *) pGetRssiReq)->sessionId;
177 pRssiBkUp->rssiCallback =
178 ((tAniGetRssiReq *) pGetRssiReq)->rssiCallback;
179 pRssiBkUp->pDevContext =
180 ((tAniGetRssiReq *) pGetRssiReq)->pDevContext;
181 wma_handle->pGetRssiReq = (void *)pRssiBkUp;
182 }
183
Govind Singhaa64c242016-03-08 11:31:49 +0530184 if (wmi_unified_snr_request_cmd(wma_handle->wmi_handle)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800185 WMA_LOGE("Failed to send host stats request to fw");
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530186 qdf_mem_free(pRssiBkUp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800187 wma_handle->pGetRssiReq = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530188 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800189 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530190 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800191}
192
193/**
194 * wma_get_snr() - get RSSI from fw
195 * @psnr_req: request params
196 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530197 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800198 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530199QDF_STATUS wma_get_snr(tAniGetSnrReq *psnr_req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800200{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800201 tAniGetSnrReq *psnr_req_bkp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800202 tp_wma_handle wma_handle = NULL;
203 struct wma_txrx_node *intr;
204
Anurag Chouhan6d760662016-02-20 16:05:43 +0530205 wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800206
207 if (NULL == wma_handle) {
208 WMA_LOGE("%s : Failed to get wma_handle", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530209 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800210 }
211
212 intr = &wma_handle->interfaces[psnr_req->sessionId];
213 /* command is in progess */
214 if (NULL != intr->psnr_req) {
215 WMA_LOGE("%s : previous snr request is pending", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530216 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800217 }
218
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530219 psnr_req_bkp = qdf_mem_malloc(sizeof(tAniGetSnrReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800220 if (!psnr_req_bkp) {
221 WMA_LOGE("Failed to allocate memory for tAniGetSnrReq");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530222 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800223 }
224
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530225 qdf_mem_set(psnr_req_bkp, sizeof(tAniGetSnrReq), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800226 psnr_req_bkp->staId = psnr_req->staId;
227 psnr_req_bkp->pDevContext = psnr_req->pDevContext;
228 psnr_req_bkp->snrCallback = psnr_req->snrCallback;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800229 intr->psnr_req = (void *)psnr_req_bkp;
Govind Singhaa64c242016-03-08 11:31:49 +0530230
231 if (wmi_unified_snr_cmd(wma_handle->wmi_handle,
232 psnr_req->sessionId)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800233 WMA_LOGE("Failed to send host stats request to fw");
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530234 qdf_mem_free(psnr_req_bkp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800235 intr->psnr_req = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530236 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800237 }
238
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530239 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800240}
241
242/**
243 * wma_process_link_status_req() - process link status request from UMAC
244 * @wma: wma handle
245 * @pGetLinkStatus: get link params
246 *
247 * Return: none
248 */
249void wma_process_link_status_req(tp_wma_handle wma,
250 tAniGetLinkStatus *pGetLinkStatus)
251{
Govind Singhaa64c242016-03-08 11:31:49 +0530252 struct link_status_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800253 struct wma_txrx_node *iface =
254 &wma->interfaces[pGetLinkStatus->sessionId];
255
256 if (iface->plink_status_req) {
257 WMA_LOGE("%s:previous link status request is pending,deleting the new request",
258 __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530259 qdf_mem_free(pGetLinkStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800260 return;
261 }
262
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800263 iface->plink_status_req = pGetLinkStatus;
Govind Singhaa64c242016-03-08 11:31:49 +0530264 cmd.session_id = pGetLinkStatus->sessionId;
265 if (wmi_unified_link_status_req_cmd(wma->wmi_handle, &cmd)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800266 WMA_LOGE("Failed to send WMI link status request to fw");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800267 iface->plink_status_req = NULL;
268 goto end;
269 }
270
271 return;
272
273end:
274 wma_post_link_status(pGetLinkStatus, LINK_STATUS_LEGACY);
275}
276
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700277#ifdef WLAN_FEATURE_TSF
278/**
279 * wma_vdev_tsf_handler() - handle tsf event indicated by FW
280 * @handle: wma context
281 * @data: event buffer
282 * @data len: length of event buffer
283 *
284 * Return: 0 on success
285 */
286int wma_vdev_tsf_handler(void *handle, uint8_t *data, uint32_t data_len)
287{
288 cds_msg_t tsf_msg = {0};
289 WMI_VDEV_TSF_REPORT_EVENTID_param_tlvs *param_buf;
290 wmi_vdev_tsf_report_event_fixed_param *tsf_event;
291 struct stsf *ptsf;
292
293 if (data == NULL) {
294 WMA_LOGE("%s: invalid pointer", __func__);
295 return -EINVAL;
296 }
297 ptsf = qdf_mem_malloc(sizeof(*ptsf));
298 if (NULL == ptsf) {
299 WMA_LOGE("%s: failed to allocate tsf data structure", __func__);
300 return -ENOMEM;
301 }
302
303 param_buf = (WMI_VDEV_TSF_REPORT_EVENTID_param_tlvs *)data;
304 tsf_event = param_buf->fixed_param;
305
306 ptsf->vdev_id = tsf_event->vdev_id;
307 ptsf->tsf_low = tsf_event->tsf_low;
308 ptsf->tsf_high = tsf_event->tsf_high;
Manikandan Mohan5356c2b2016-04-03 15:51:35 -0700309 ptsf->soc_timer_low = tsf_event->qtimer_low;
310 ptsf->soc_timer_high = tsf_event->qtimer_high;
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700311
312 WMA_LOGD("%s: receive WMI_VDEV_TSF_REPORT_EVENTID ", __func__);
313 WMA_LOGD("%s: vdev_id = %u,tsf_low =%u, tsf_high = %u", __func__,
314 ptsf->vdev_id, ptsf->tsf_low, ptsf->tsf_high);
315
316 tsf_msg.type = eWNI_SME_TSF_EVENT;
317 tsf_msg.bodyptr = ptsf;
318 tsf_msg.bodyval = 0;
319
320 if (QDF_STATUS_SUCCESS !=
Krunal Soni66c113f2016-12-21 16:46:47 -0800321 cds_mq_post_message(QDF_MODULE_ID_SME, &tsf_msg)) {
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700322
323 WMA_LOGP("%s: Failed to post eWNI_SME_TSF_EVENT", __func__);
324 qdf_mem_free(ptsf);
325 return -EINVAL;
326 }
327 return 0;
328}
329
Manikandan Mohan5356c2b2016-04-03 15:51:35 -0700330#ifdef QCA_WIFI_3_0
331#define TSF_FW_ACTION_CMD TSF_TSTAMP_QTIMER_CAPTURE_REQ
332#else
333#define TSF_FW_ACTION_CMD TSF_TSTAMP_CAPTURE_REQ
334#endif
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700335/**
336 * wma_capture_tsf() - send wmi to fw to capture tsf
337 * @wma_handle: wma handler
338 * @vdev_id: vdev id
339 *
340 * Return: wmi send state
341 */
342QDF_STATUS wma_capture_tsf(tp_wma_handle wma_handle, uint32_t vdev_id)
343{
344 QDF_STATUS status = QDF_STATUS_SUCCESS;
345 wmi_buf_t buf;
346 wmi_vdev_tsf_tstamp_action_cmd_fixed_param *cmd;
347 int ret;
348 int len = sizeof(*cmd);
349
350 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
351 if (!buf) {
352 WMA_LOGP("%s: failed to allocate memory for cap tsf cmd",
353 __func__);
354 return QDF_STATUS_E_NOMEM;
355 }
356
357 cmd = (wmi_vdev_tsf_tstamp_action_cmd_fixed_param *) wmi_buf_data(buf);
358 cmd->vdev_id = vdev_id;
Manikandan Mohan5356c2b2016-04-03 15:51:35 -0700359 cmd->tsf_action = TSF_FW_ACTION_CMD;
360 WMA_LOGD("%s :vdev_id %u, tsf_cmd: %d", __func__, cmd->vdev_id,
361 cmd->tsf_action);
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700362
363 WMITLV_SET_HDR(&cmd->tlv_header,
364 WMITLV_TAG_STRUC_wmi_vdev_tsf_tstamp_action_cmd_fixed_param,
365 WMITLV_GET_STRUCT_TLVLEN(
366 wmi_vdev_tsf_tstamp_action_cmd_fixed_param));
367
368 ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
369 WMI_VDEV_TSF_TSTAMP_ACTION_CMDID);
370 if (ret != EOK) {
371 WMA_LOGE("wmi_unified_cmd_send returned Error %d", status);
372 status = QDF_STATUS_E_FAILURE;
373 goto error;
374 }
375
376 return QDF_STATUS_SUCCESS;
377
378error:
379 if (buf)
380 wmi_buf_free(buf);
381 return status;
382}
383
384/**
385 * wma_reset_tsf_gpio() - send wmi to fw to reset GPIO
386 * @wma_handle: wma handler
387 * @vdev_id: vdev id
388 *
389 * Return: wmi send state
390 */
391QDF_STATUS wma_reset_tsf_gpio(tp_wma_handle wma_handle, uint32_t vdev_id)
392{
393 QDF_STATUS status = QDF_STATUS_SUCCESS;
394 wmi_buf_t buf;
395 wmi_vdev_tsf_tstamp_action_cmd_fixed_param *cmd;
396 int ret;
397 int len = sizeof(*cmd);
398 uint8_t *buf_ptr;
399
400 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
401 if (!buf) {
402 WMA_LOGP("%s: failed to allocate memory for reset tsf gpio",
403 __func__);
404 return QDF_STATUS_E_NOMEM;
405 }
406
407 buf_ptr = (uint8_t *) wmi_buf_data(buf);
408 cmd = (wmi_vdev_tsf_tstamp_action_cmd_fixed_param *) buf_ptr;
409 cmd->vdev_id = vdev_id;
410 cmd->tsf_action = TSF_TSTAMP_CAPTURE_RESET;
411
412 WMA_LOGD("%s :vdev_id %u, TSF_TSTAMP_CAPTURE_RESET", __func__,
413 cmd->vdev_id);
414
415 WMITLV_SET_HDR(&cmd->tlv_header,
416 WMITLV_TAG_STRUC_wmi_vdev_tsf_tstamp_action_cmd_fixed_param,
417 WMITLV_GET_STRUCT_TLVLEN(
418 wmi_vdev_tsf_tstamp_action_cmd_fixed_param));
419
420 ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
421 WMI_VDEV_TSF_TSTAMP_ACTION_CMDID);
422
423 if (ret != EOK) {
424 WMA_LOGE("wmi_unified_cmd_send returned Error %d", status);
425 status = QDF_STATUS_E_FAILURE;
426 goto error;
427 }
428 return QDF_STATUS_SUCCESS;
429
430error:
431 if (buf)
432 wmi_buf_free(buf);
433 return status;
434}
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700435
Manikandan Mohan976e7562016-03-15 16:33:31 -0700436/**
437 * wma_set_tsf_gpio_pin() - send wmi cmd to configure gpio pin
438 * @handle: wma handler
439 * @pin: GPIO pin id
440 *
441 * Return: QDF_STATUS
442 */
443QDF_STATUS wma_set_tsf_gpio_pin(WMA_HANDLE handle, uint32_t pin)
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700444{
Manikandan Mohan976e7562016-03-15 16:33:31 -0700445 tp_wma_handle wma = (tp_wma_handle)handle;
446 struct pdev_params pdev_param = {0};
447 int32_t ret;
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700448
Manikandan Mohan976e7562016-03-15 16:33:31 -0700449 if (!wma || !wma->wmi_handle) {
450 WMA_LOGE("%s: WMA is closed, can not set gpio", __func__);
451 return QDF_STATUS_E_INVAL;
452 }
453
454 WMA_LOGD("%s: set tsf gpio pin: %d", __func__, pin);
455
456 pdev_param.param_id = WMI_PDEV_PARAM_WNTS_CONFIG;
457 pdev_param.param_value = pin;
458 ret = wmi_unified_pdev_param_send(wma->wmi_handle,
459 &pdev_param,
460 WMA_WILDCARD_PDEV_ID);
461 if (ret) {
462 WMA_LOGE("%s: Failed to set tsf gpio pin (%d)", __func__, ret);
463 return QDF_STATUS_E_FAILURE;
464 }
465 return QDF_STATUS_SUCCESS;
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700466}
467#endif
468
Manikandan Mohan80dea792016-04-28 16:36:48 -0700469/**
470 * wma_set_wisa_params(): Set WISA features related params in FW
471 * @wma_handle: WMA handle
472 * @wisa: Pointer to WISA param struct
473 *
474 * Return: CDF status
475 */
476QDF_STATUS wma_set_wisa_params(tp_wma_handle wma_handle,
477 struct sir_wisa_params *wisa)
478{
479 QDF_STATUS status = QDF_STATUS_SUCCESS;
480 wmi_buf_t buf;
481 wmi_vdev_wisa_cmd_fixed_param *cmd;
482 int ret, len = sizeof(*cmd);
483
484 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
485 if (!buf) {
486 WMA_LOGP("%s: failed to allocate memory for WISA params",
487 __func__);
488 return QDF_STATUS_E_NOMEM;
489 }
490
491 cmd = (wmi_vdev_wisa_cmd_fixed_param *) wmi_buf_data(buf);
492 cmd->wisa_mode = wisa->mode;
493 cmd->vdev_id = wisa->vdev_id;
494
495 WMITLV_SET_HDR(&cmd->tlv_header,
496 WMITLV_TAG_STRUC_wmi_vdev_wisa_cmd_fixed_param,
497 WMITLV_GET_STRUCT_TLVLEN(
498 wmi_vdev_wisa_cmd_fixed_param));
499
500 ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
501 WMI_VDEV_WISA_CMDID);
502 if (ret != EOK) {
503 WMA_LOGE("wmi_unified_cmd_send returned Error %d", status);
504 status = QDF_STATUS_E_FAILURE;
505 goto error;
506 }
507 return QDF_STATUS_SUCCESS;
508
509error:
510 wmi_buf_free(buf);
511 return status;
512}
513
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800514#ifdef FEATURE_WLAN_LPHB
515/**
516 * wma_lphb_conf_hbenable() - enable command of LPHB configuration requests
517 * @wma_handle: WMA handle
518 * @lphb_conf_req: configuration info
519 * @by_user: whether this call is from user or cached resent
520 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530521 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800522 */
Jeff Johnsonc4b47a92016-10-07 12:34:41 -0700523static QDF_STATUS wma_lphb_conf_hbenable(tp_wma_handle wma_handle,
524 tSirLPHBReq *lphb_conf_req,
525 bool by_user)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800526{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530527 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800528 int status = 0;
529 tSirLPHBEnableStruct *ts_lphb_enable;
Govind Singhaa64c242016-03-08 11:31:49 +0530530 wmi_hb_set_enable_cmd_fixed_param hb_enable_fp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800531 int i;
532
533 if (lphb_conf_req == NULL) {
534 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530535 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800536 }
537
538 ts_lphb_enable = &(lphb_conf_req->params.lphbEnableReq);
539 WMA_LOGI("%s: WMA --> WMI_HB_SET_ENABLE enable=%d, item=%d, session=%d",
540 __func__,
541 ts_lphb_enable->enable,
542 ts_lphb_enable->item, ts_lphb_enable->session);
543
544 if ((ts_lphb_enable->item != 1) && (ts_lphb_enable->item != 2)) {
545 WMA_LOGE("%s : LPHB configuration wrong item %d",
546 __func__, ts_lphb_enable->item);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530547 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800548 }
549
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800550
551 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530552 hb_enable_fp.vdev_id = ts_lphb_enable->session;
553 hb_enable_fp.enable = ts_lphb_enable->enable;
554 hb_enable_fp.item = ts_lphb_enable->item;
555 hb_enable_fp.session = ts_lphb_enable->session;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800556
Govind Singhaa64c242016-03-08 11:31:49 +0530557 status = wmi_unified_lphb_config_hbenable_cmd(wma_handle->wmi_handle,
558 &hb_enable_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800559 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530560 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800561 goto error;
562 }
563
564 if (by_user) {
565 /* target already configured, now cache command status */
566 if (ts_lphb_enable->enable) {
567 i = ts_lphb_enable->item - 1;
568 wma_handle->wow.lphb_cache[i].cmd
569 = LPHB_SET_EN_PARAMS_INDID;
570 wma_handle->wow.lphb_cache[i].params.lphbEnableReq.
571 enable = ts_lphb_enable->enable;
572 wma_handle->wow.lphb_cache[i].params.lphbEnableReq.
573 item = ts_lphb_enable->item;
574 wma_handle->wow.lphb_cache[i].params.lphbEnableReq.
575 session = ts_lphb_enable->session;
576
577 WMA_LOGI("%s: cached LPHB status in WMA context for item %d",
578 __func__, i);
579 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530580 qdf_mem_zero((void *)&wma_handle->wow.lphb_cache,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800581 sizeof(wma_handle->wow.lphb_cache));
582 WMA_LOGI("%s: cleared all cached LPHB status in WMA context",
583 __func__);
584 }
585 }
586
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530587 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800588error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530589 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800590}
591
592/**
593 * wma_lphb_conf_tcp_params() - set tcp params of LPHB configuration requests
594 * @wma_handle: wma handle
595 * @lphb_conf_req: lphb config request
596 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530597 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800598 */
Jeff Johnsonc4b47a92016-10-07 12:34:41 -0700599static QDF_STATUS wma_lphb_conf_tcp_params(tp_wma_handle wma_handle,
600 tSirLPHBReq *lphb_conf_req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800601{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530602 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800603 int status = 0;
604 tSirLPHBTcpParamStruct *ts_lphb_tcp_param;
Govind Singhaa64c242016-03-08 11:31:49 +0530605 wmi_hb_set_tcp_params_cmd_fixed_param hb_tcp_params_fp = {0};
606
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800607
608 if (lphb_conf_req == NULL) {
609 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530610 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800611 }
612
613 ts_lphb_tcp_param = &(lphb_conf_req->params.lphbTcpParamReq);
Srinivas Girigowda9dc32cf2015-11-19 14:47:04 -0800614 WMA_LOGI("%s: WMA --> WMI_HB_SET_TCP_PARAMS srv_ip=%08x, "
615 "dev_ip=%08x, src_port=%d, dst_port=%d, timeout=%d, "
616 "session=%d, gateway_mac="MAC_ADDRESS_STR", timePeriodSec=%d, "
617 "tcpSn=%d", __func__, ts_lphb_tcp_param->srv_ip,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800618 ts_lphb_tcp_param->dev_ip, ts_lphb_tcp_param->src_port,
619 ts_lphb_tcp_param->dst_port, ts_lphb_tcp_param->timeout,
Srinivas Girigowda9dc32cf2015-11-19 14:47:04 -0800620 ts_lphb_tcp_param->session,
621 MAC_ADDR_ARRAY(ts_lphb_tcp_param->gateway_mac.bytes),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800622 ts_lphb_tcp_param->timePeriodSec, ts_lphb_tcp_param->tcpSn);
623
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800624 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530625 hb_tcp_params_fp.vdev_id = ts_lphb_tcp_param->session;
626 hb_tcp_params_fp.srv_ip = ts_lphb_tcp_param->srv_ip;
627 hb_tcp_params_fp.dev_ip = ts_lphb_tcp_param->dev_ip;
628 hb_tcp_params_fp.seq = ts_lphb_tcp_param->tcpSn;
629 hb_tcp_params_fp.src_port = ts_lphb_tcp_param->src_port;
630 hb_tcp_params_fp.dst_port = ts_lphb_tcp_param->dst_port;
631 hb_tcp_params_fp.interval = ts_lphb_tcp_param->timePeriodSec;
632 hb_tcp_params_fp.timeout = ts_lphb_tcp_param->timeout;
633 hb_tcp_params_fp.session = ts_lphb_tcp_param->session;
Srinivas Girigowda9dc32cf2015-11-19 14:47:04 -0800634 WMI_CHAR_ARRAY_TO_MAC_ADDR(ts_lphb_tcp_param->gateway_mac.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +0530635 &hb_tcp_params_fp.gateway_mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800636
Govind Singhaa64c242016-03-08 11:31:49 +0530637 status = wmi_unified_lphb_config_tcp_params_cmd(wma_handle->wmi_handle,
638 &hb_tcp_params_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800639 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530640 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800641 goto error;
642 }
643
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530644 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800645error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530646 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800647}
648
649/**
650 * wma_lphb_conf_tcp_pkt_filter() - configure tcp packet filter command of LPHB
651 * @wma_handle: wma handle
652 * @lphb_conf_req: lphb config request
653 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530654 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800655 */
Jeff Johnsonc4b47a92016-10-07 12:34:41 -0700656static QDF_STATUS wma_lphb_conf_tcp_pkt_filter(tp_wma_handle wma_handle,
657 tSirLPHBReq *lphb_conf_req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800658{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530659 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800660 int status = 0;
661 tSirLPHBTcpFilterStruct *ts_lphb_tcp_filter;
Govind Singhaa64c242016-03-08 11:31:49 +0530662 wmi_hb_set_tcp_pkt_filter_cmd_fixed_param hb_tcp_filter_fp = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800663
664 if (lphb_conf_req == NULL) {
665 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530666 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800667 }
668
669 ts_lphb_tcp_filter = &(lphb_conf_req->params.lphbTcpFilterReq);
670 WMA_LOGI("%s: WMA --> WMI_HB_SET_TCP_PKT_FILTER length=%d, offset=%d, session=%d, "
671 "filter=%2x:%2x:%2x:%2x:%2x:%2x ...", __func__,
672 ts_lphb_tcp_filter->length, ts_lphb_tcp_filter->offset,
673 ts_lphb_tcp_filter->session, ts_lphb_tcp_filter->filter[0],
674 ts_lphb_tcp_filter->filter[1], ts_lphb_tcp_filter->filter[2],
675 ts_lphb_tcp_filter->filter[3], ts_lphb_tcp_filter->filter[4],
676 ts_lphb_tcp_filter->filter[5]);
677
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800678 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530679 hb_tcp_filter_fp.vdev_id = ts_lphb_tcp_filter->session;
680 hb_tcp_filter_fp.length = ts_lphb_tcp_filter->length;
681 hb_tcp_filter_fp.offset = ts_lphb_tcp_filter->offset;
682 hb_tcp_filter_fp.session = ts_lphb_tcp_filter->session;
683 memcpy((void *)&hb_tcp_filter_fp.filter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800684 (void *)&ts_lphb_tcp_filter->filter,
685 WMI_WLAN_HB_MAX_FILTER_SIZE);
686
Govind Singhaa64c242016-03-08 11:31:49 +0530687 status = wmi_unified_lphb_config_tcp_pkt_filter_cmd(wma_handle->wmi_handle,
688 &hb_tcp_filter_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800689 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530690 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800691 goto error;
692 }
693
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530694 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800695error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530696 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800697}
698
699/**
700 * wma_lphb_conf_udp_params() - configure udp param command of LPHB
701 * @wma_handle: wma handle
702 * @lphb_conf_req: lphb config request
703 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530704 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800705 */
Jeff Johnsonc4b47a92016-10-07 12:34:41 -0700706static QDF_STATUS wma_lphb_conf_udp_params(tp_wma_handle wma_handle,
707 tSirLPHBReq *lphb_conf_req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800708{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530709 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800710 int status = 0;
711 tSirLPHBUdpParamStruct *ts_lphb_udp_param;
Govind Singhaa64c242016-03-08 11:31:49 +0530712 wmi_hb_set_udp_params_cmd_fixed_param hb_udp_params_fp = {0};
713
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800714
715 if (lphb_conf_req == NULL) {
716 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530717 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800718 }
719
720 ts_lphb_udp_param = &(lphb_conf_req->params.lphbUdpParamReq);
721 WMA_LOGI("%s: WMA --> WMI_HB_SET_UDP_PARAMS srv_ip=%d, dev_ip=%d, src_port=%d, "
722 "dst_port=%d, interval=%d, timeout=%d, session=%d, "
Srinivas Girigowda9eddfda2015-11-19 14:38:02 -0800723 "gateway_mac="MAC_ADDRESS_STR, __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800724 ts_lphb_udp_param->srv_ip, ts_lphb_udp_param->dev_ip,
725 ts_lphb_udp_param->src_port, ts_lphb_udp_param->dst_port,
726 ts_lphb_udp_param->interval, ts_lphb_udp_param->timeout,
Srinivas Girigowda9eddfda2015-11-19 14:38:02 -0800727 ts_lphb_udp_param->session,
728 MAC_ADDR_ARRAY(ts_lphb_udp_param->gateway_mac.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800729
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800730
731 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530732 hb_udp_params_fp.vdev_id = ts_lphb_udp_param->session;
733 hb_udp_params_fp.srv_ip = ts_lphb_udp_param->srv_ip;
734 hb_udp_params_fp.dev_ip = ts_lphb_udp_param->dev_ip;
735 hb_udp_params_fp.src_port = ts_lphb_udp_param->src_port;
736 hb_udp_params_fp.dst_port = ts_lphb_udp_param->dst_port;
737 hb_udp_params_fp.interval = ts_lphb_udp_param->interval;
738 hb_udp_params_fp.timeout = ts_lphb_udp_param->timeout;
739 hb_udp_params_fp.session = ts_lphb_udp_param->session;
Srinivas Girigowda9eddfda2015-11-19 14:38:02 -0800740 WMI_CHAR_ARRAY_TO_MAC_ADDR(ts_lphb_udp_param->gateway_mac.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +0530741 &hb_udp_params_fp.gateway_mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800742
Govind Singhaa64c242016-03-08 11:31:49 +0530743 status = wmi_unified_lphb_config_udp_params_cmd(wma_handle->wmi_handle,
744 &hb_udp_params_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800745 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530746 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800747 goto error;
748 }
749
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530750 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800751error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530752 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800753}
754
755/**
756 * wma_lphb_conf_udp_pkt_filter() - configure udp pkt filter command of LPHB
757 * @wma_handle: wma handle
758 * @lphb_conf_req: lphb config request
759 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530760 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800761 */
Jeff Johnsonc4b47a92016-10-07 12:34:41 -0700762static QDF_STATUS wma_lphb_conf_udp_pkt_filter(tp_wma_handle wma_handle,
763 tSirLPHBReq *lphb_conf_req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800764{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530765 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800766 int status = 0;
767 tSirLPHBUdpFilterStruct *ts_lphb_udp_filter;
Govind Singhaa64c242016-03-08 11:31:49 +0530768 wmi_hb_set_udp_pkt_filter_cmd_fixed_param hb_udp_filter_fp = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800769
770 if (lphb_conf_req == NULL) {
771 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530772 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800773 }
774
775 ts_lphb_udp_filter = &(lphb_conf_req->params.lphbUdpFilterReq);
776 WMA_LOGI("%s: WMA --> WMI_HB_SET_UDP_PKT_FILTER length=%d, offset=%d, session=%d, "
777 "filter=%2x:%2x:%2x:%2x:%2x:%2x ...", __func__,
778 ts_lphb_udp_filter->length, ts_lphb_udp_filter->offset,
779 ts_lphb_udp_filter->session, ts_lphb_udp_filter->filter[0],
780 ts_lphb_udp_filter->filter[1], ts_lphb_udp_filter->filter[2],
781 ts_lphb_udp_filter->filter[3], ts_lphb_udp_filter->filter[4],
782 ts_lphb_udp_filter->filter[5]);
783
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800784
785 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530786 hb_udp_filter_fp.vdev_id = ts_lphb_udp_filter->session;
787 hb_udp_filter_fp.length = ts_lphb_udp_filter->length;
788 hb_udp_filter_fp.offset = ts_lphb_udp_filter->offset;
789 hb_udp_filter_fp.session = ts_lphb_udp_filter->session;
790 memcpy((void *)&hb_udp_filter_fp.filter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800791 (void *)&ts_lphb_udp_filter->filter,
792 WMI_WLAN_HB_MAX_FILTER_SIZE);
793
Govind Singhaa64c242016-03-08 11:31:49 +0530794 status = wmi_unified_lphb_config_udp_pkt_filter_cmd(wma_handle->wmi_handle,
795 &hb_udp_filter_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800796 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530797 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800798 goto error;
799 }
800
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530801 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800802error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530803 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800804}
805
806/**
807 * wma_process_lphb_conf_req() - handle LPHB configuration requests
808 * @wma_handle: wma handle
809 * @lphb_conf_req: lphb config request
810 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530811 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800812 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530813QDF_STATUS wma_process_lphb_conf_req(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800814 tSirLPHBReq *lphb_conf_req)
815{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530816 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800817
818 if (lphb_conf_req == NULL) {
819 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530820 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800821 }
822
823 WMA_LOGI("%s : LPHB configuration cmd id is %d", __func__,
824 lphb_conf_req->cmd);
825 switch (lphb_conf_req->cmd) {
826 case LPHB_SET_EN_PARAMS_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530827 qdf_status = wma_lphb_conf_hbenable(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800828 lphb_conf_req, true);
829 break;
830
831 case LPHB_SET_TCP_PARAMS_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530832 qdf_status = wma_lphb_conf_tcp_params(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800833 lphb_conf_req);
834 break;
835
836 case LPHB_SET_TCP_PKT_FILTER_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530837 qdf_status = wma_lphb_conf_tcp_pkt_filter(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800838 lphb_conf_req);
839 break;
840
841 case LPHB_SET_UDP_PARAMS_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530842 qdf_status = wma_lphb_conf_udp_params(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800843 lphb_conf_req);
844 break;
845
846 case LPHB_SET_UDP_PKT_FILTER_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530847 qdf_status = wma_lphb_conf_udp_pkt_filter(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800848 lphb_conf_req);
849 break;
850
851 case LPHB_SET_NETWORK_INFO_INDID:
852 default:
853 break;
854 }
855
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530856 qdf_mem_free(lphb_conf_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530857 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800858}
859#endif /* FEATURE_WLAN_LPHB */
860
861/**
862 * wma_process_dhcp_ind() - process dhcp indication from SME
863 * @wma_handle: wma handle
864 * @ta_dhcp_ind: DHCP indication
865 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530866 * Return: QDF Status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800867 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530868QDF_STATUS wma_process_dhcp_ind(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800869 tAniDHCPInd *ta_dhcp_ind)
870{
871 uint8_t vdev_id;
872 int status = 0;
Govind Singhaa64c242016-03-08 11:31:49 +0530873 wmi_peer_set_param_cmd_fixed_param peer_set_param_fp = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800874
875 if (!ta_dhcp_ind) {
876 WMA_LOGE("%s : DHCP indication is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530877 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800878 }
879
Srinivas Girigowda296105a2015-09-24 16:31:16 -0700880 if (!wma_find_vdev_by_addr(wma_handle,
881 ta_dhcp_ind->adapterMacAddr.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800882 &vdev_id)) {
883 WMA_LOGE("%s: Failed to find vdev id for DHCP indication",
884 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530885 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800886 }
887
888 WMA_LOGI("%s: WMA --> WMI_PEER_SET_PARAM triggered by DHCP, "
889 "msgType=%s,"
890 "device_mode=%d, macAddr=" MAC_ADDRESS_STR,
891 __func__,
892 ta_dhcp_ind->msgType == WMA_DHCP_START_IND ?
893 "WMA_DHCP_START_IND" : "WMA_DHCP_STOP_IND",
894 ta_dhcp_ind->device_mode,
Srinivas Girigowda296105a2015-09-24 16:31:16 -0700895 MAC_ADDR_ARRAY(ta_dhcp_ind->peerMacAddr.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800896
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800897 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530898 peer_set_param_fp.vdev_id = vdev_id;
899 peer_set_param_fp.param_id = WMI_PEER_CRIT_PROTO_HINT_ENABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800900 if (WMA_DHCP_START_IND == ta_dhcp_ind->msgType)
Govind Singhaa64c242016-03-08 11:31:49 +0530901 peer_set_param_fp.param_value = 1;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800902 else
Govind Singhaa64c242016-03-08 11:31:49 +0530903 peer_set_param_fp.param_value = 0;
Srinivas Girigowda296105a2015-09-24 16:31:16 -0700904 WMI_CHAR_ARRAY_TO_MAC_ADDR(ta_dhcp_ind->peerMacAddr.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +0530905 &peer_set_param_fp.peer_macaddr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800906
Govind Singhaa64c242016-03-08 11:31:49 +0530907 status = wmi_unified_process_dhcp_ind(wma_handle->wmi_handle,
908 &peer_set_param_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800909 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530910 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800911 }
912
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530913 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800914}
915
916/**
Amar Singhal046eb8a2016-05-05 12:50:15 -0700917 * wma_chan_phy__mode() - get WLAN_PHY_MODE for channel
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800918 * @chan: channel number
Amar Singhal046eb8a2016-05-05 12:50:15 -0700919 * @chan_width: maximum channel width possible
920 * @dot11_mode: maximum phy_mode possible
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800921 *
Amar Singhal046eb8a2016-05-05 12:50:15 -0700922 * Return: return WLAN_PHY_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800923 */
Amar Singhal046eb8a2016-05-05 12:50:15 -0700924WLAN_PHY_MODE wma_chan_phy_mode(u8 chan, enum phy_ch_width chan_width,
925 u8 dot11_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800926{
927 WLAN_PHY_MODE phymode = MODE_UNKNOWN;
Amar Singhal046eb8a2016-05-05 12:50:15 -0700928 uint16_t bw_val = cds_bw_value(chan_width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800929
Amar Singhal046eb8a2016-05-05 12:50:15 -0700930 if (CDS_IS_CHANNEL_24GHZ(chan)) {
931 if (((CH_WIDTH_5MHZ == chan_width) ||
932 (CH_WIDTH_10MHZ == chan_width)) &&
933 ((WNI_CFG_DOT11_MODE_11B == dot11_mode) ||
934 (WNI_CFG_DOT11_MODE_11G == dot11_mode) ||
935 (WNI_CFG_DOT11_MODE_11N == dot11_mode) ||
936 (WNI_CFG_DOT11_MODE_ALL == dot11_mode) ||
937 (WNI_CFG_DOT11_MODE_11AC == dot11_mode)))
938 phymode = MODE_11G;
939 else {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800940 switch (dot11_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800941 case WNI_CFG_DOT11_MODE_11B:
Amar Singhal046eb8a2016-05-05 12:50:15 -0700942 if ((20 == bw_val) ||
943 (40 == bw_val))
944 phymode = MODE_11B;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800945 break;
946 case WNI_CFG_DOT11_MODE_11G:
Amar Singhal046eb8a2016-05-05 12:50:15 -0700947 if ((20 == bw_val) ||
948 (40 == bw_val))
949 phymode = MODE_11G;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800950 break;
951 case WNI_CFG_DOT11_MODE_11G_ONLY:
Amar Singhal046eb8a2016-05-05 12:50:15 -0700952 if ((20 == bw_val) ||
953 (40 == bw_val))
954 phymode = MODE_11GONLY;
955 break;
956 case WNI_CFG_DOT11_MODE_11N:
957 case WNI_CFG_DOT11_MODE_11N_ONLY:
958 if (20 == bw_val)
959 phymode = MODE_11NG_HT20;
960 else if (40 == bw_val)
961 phymode = MODE_11NG_HT40;
962 break;
963 case WNI_CFG_DOT11_MODE_ALL:
964 case WNI_CFG_DOT11_MODE_11AC:
965 case WNI_CFG_DOT11_MODE_11AC_ONLY:
966 if (20 == bw_val)
967 phymode = MODE_11AC_VHT20_2G;
968 else if (40 == bw_val)
969 phymode = MODE_11AC_VHT40_2G;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800970 break;
971 default:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800972 break;
973 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800974 }
Amar Singhal046eb8a2016-05-05 12:50:15 -0700975 } else if (CDS_IS_CHANNEL_DSRC(chan))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800976 phymode = MODE_11A;
Amar Singhal046eb8a2016-05-05 12:50:15 -0700977 else {
978 if (((CH_WIDTH_5MHZ == chan_width) ||
979 (CH_WIDTH_10MHZ == chan_width)) &&
980 ((WNI_CFG_DOT11_MODE_11A == dot11_mode) ||
981 (WNI_CFG_DOT11_MODE_11N == dot11_mode) ||
982 (WNI_CFG_DOT11_MODE_ALL == dot11_mode) ||
983 (WNI_CFG_DOT11_MODE_11AC == dot11_mode)))
984 phymode = MODE_11A;
985 else {
986 switch (dot11_mode) {
987 case WNI_CFG_DOT11_MODE_11A:
988 if (0 < bw_val)
989 phymode = MODE_11A;
990 break;
991 case WNI_CFG_DOT11_MODE_11N:
992 case WNI_CFG_DOT11_MODE_11N_ONLY:
993 if (20 == bw_val)
994 phymode = MODE_11NA_HT20;
995 else if (40 <= bw_val)
996 phymode = MODE_11NA_HT40;
997 break;
998 case WNI_CFG_DOT11_MODE_ALL:
999 case WNI_CFG_DOT11_MODE_11AC:
1000 case WNI_CFG_DOT11_MODE_11AC_ONLY:
1001 if (20 == bw_val)
1002 phymode = MODE_11AC_VHT20;
1003 else if (40 == bw_val)
1004 phymode = MODE_11AC_VHT40;
1005 else if (80 == bw_val)
1006 phymode = MODE_11AC_VHT80;
1007 else if (CH_WIDTH_160MHZ == chan_width)
1008 phymode = MODE_11AC_VHT160;
1009 else if (CH_WIDTH_80P80MHZ == chan_width)
1010 phymode = MODE_11AC_VHT80_80;
1011 break;
1012 default:
1013 break;
1014 }
1015 }
1016 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001017
Amar Singhal046eb8a2016-05-05 12:50:15 -07001018 WMA_LOGD("%s: phymode %d channel %d ch_width %d"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001019 "dot11_mode %d", __func__, phymode, chan,
Amar Singhal046eb8a2016-05-05 12:50:15 -07001020 chan_width, dot11_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001021
Amar Singhal046eb8a2016-05-05 12:50:15 -07001022 QDF_ASSERT(MODE_UNKNOWN != phymode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001023 return phymode;
1024}
1025
1026/**
1027 * wma_get_link_speed() -send command to get linkspeed
1028 * @handle: wma handle
1029 * @pLinkSpeed: link speed info
1030 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05301031 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001032 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301033QDF_STATUS wma_get_link_speed(WMA_HANDLE handle, tSirLinkSpeedInfo *pLinkSpeed)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001034{
1035 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhaa64c242016-03-08 11:31:49 +05301036 wmi_mac_addr peer_macaddr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001037
1038 if (!wma_handle || !wma_handle->wmi_handle) {
1039 WMA_LOGE("%s: WMA is closed, can not issue get link speed cmd",
1040 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301041 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001042 }
1043 if (!WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap,
1044 WMI_SERVICE_ESTIMATE_LINKSPEED)) {
1045 WMA_LOGE("%s: Linkspeed feature bit not enabled"
1046 " Sending value 0 as link speed.", __func__);
1047 wma_send_link_speed(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301048 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001049 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001050
1051 /* Copy the peer macaddress to the wma buffer */
Srinivas Girigowdadccab9a2015-11-19 14:31:14 -08001052 WMI_CHAR_ARRAY_TO_MAC_ADDR(pLinkSpeed->peer_macaddr.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +05301053 &peer_macaddr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001054
1055 WMA_LOGD("%s: pLinkSpeed->peerMacAddr: %pM, "
1056 "peer_macaddr.mac_addr31to0: 0x%x, peer_macaddr.mac_addr47to32: 0x%x",
Srinivas Girigowdadccab9a2015-11-19 14:31:14 -08001057 __func__, pLinkSpeed->peer_macaddr.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +05301058 peer_macaddr.mac_addr31to0,
1059 peer_macaddr.mac_addr47to32);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001060
Govind Singhaa64c242016-03-08 11:31:49 +05301061 if (wmi_unified_get_link_speed_cmd(wma_handle->wmi_handle,
1062 peer_macaddr)) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301063 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001064 }
Govind Singhaa64c242016-03-08 11:31:49 +05301065
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301066 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001067}
1068
Gupta, Kapil4cb1d7d2016-04-16 18:16:25 -07001069/**
1070* wma_add_beacon_filter() - Issue WMI command to set beacon filter
1071* @wma: wma handler
1072* @filter_params: beacon_filter_param to set
1073*
1074* Return: Return QDF_STATUS
1075*/
1076QDF_STATUS wma_add_beacon_filter(WMA_HANDLE handle,
1077 struct beacon_filter_param *filter_params)
1078{
1079 int i;
1080 wmi_buf_t wmi_buf;
1081 u_int8_t *buf;
1082 A_UINT32 *ie_map;
1083 int ret;
1084 tp_wma_handle wma = (tp_wma_handle) handle;
1085 wmi_add_bcn_filter_cmd_fixed_param *cmd;
1086 int len = sizeof(wmi_add_bcn_filter_cmd_fixed_param);
1087
1088 len += WMI_TLV_HDR_SIZE;
1089 len += BCN_FLT_MAX_ELEMS_IE_LIST*sizeof(A_UINT32);
1090
1091 if (!wma || !wma->wmi_handle) {
1092 WMA_LOGE("%s: WMA is closed, can not issue set beacon filter",
1093 __func__);
1094 return QDF_STATUS_E_INVAL;
1095 }
1096
1097 wmi_buf = wmi_buf_alloc(wma->wmi_handle, len);
1098 if (!wmi_buf) {
1099 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
1100 return QDF_STATUS_E_NOMEM;
1101 }
1102
1103 buf = (u_int8_t *) wmi_buf_data(wmi_buf);
1104
1105 cmd = (wmi_add_bcn_filter_cmd_fixed_param *)wmi_buf_data(wmi_buf);
1106 cmd->vdev_id = filter_params->vdev_id;
1107
1108 WMITLV_SET_HDR(&cmd->tlv_header,
1109 WMITLV_TAG_STRUC_wmi_add_bcn_filter_cmd_fixed_param,
1110 WMITLV_GET_STRUCT_TLVLEN(
1111 wmi_add_bcn_filter_cmd_fixed_param));
1112
1113 buf += sizeof(wmi_add_bcn_filter_cmd_fixed_param);
1114
1115 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_UINT32,
1116 (BCN_FLT_MAX_ELEMS_IE_LIST * sizeof(u_int32_t)));
1117
1118 ie_map = (A_UINT32 *)(buf + WMI_TLV_HDR_SIZE);
1119 for (i = 0; i < BCN_FLT_MAX_ELEMS_IE_LIST; i++) {
1120 ie_map[i] = filter_params->ie_map[i];
1121 WMA_LOGD("beacon filter ie map = %u", ie_map[i]);
1122 }
1123
1124 ret = wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len,
1125 WMI_ADD_BCN_FILTER_CMDID);
1126 if (ret) {
1127 WMA_LOGE("Failed to send wmi add beacon filter = %d",
1128 ret);
1129 wmi_buf_free(wmi_buf);
1130 return QDF_STATUS_E_FAILURE;
1131 }
Gupta, Kapil4cb1d7d2016-04-16 18:16:25 -07001132
1133 return QDF_STATUS_SUCCESS;
1134}
1135
1136/**
1137* wma_remove_beacon_filter() - Issue WMI command to remove beacon filter
1138* @wma: wma handler
1139* @filter_params: beacon_filter_params
1140*
1141* Return: Return QDF_STATUS
1142*/
1143QDF_STATUS wma_remove_beacon_filter(WMA_HANDLE handle,
1144 struct beacon_filter_param *filter_params)
1145{
1146 wmi_buf_t buf;
1147 tp_wma_handle wma = (tp_wma_handle) handle;
1148 wmi_rmv_bcn_filter_cmd_fixed_param *cmd;
1149 int len = sizeof(wmi_rmv_bcn_filter_cmd_fixed_param);
1150 int ret;
1151
1152 if (!wma || !wma->wmi_handle) {
1153 WMA_LOGE("%s: WMA is closed, cannot issue remove beacon filter",
1154 __func__);
1155 return QDF_STATUS_E_INVAL;
1156 }
1157
1158 buf = wmi_buf_alloc(wma->wmi_handle, len);
1159 if (!buf) {
1160 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
1161 return QDF_STATUS_E_NOMEM;
1162 }
1163 cmd = (wmi_rmv_bcn_filter_cmd_fixed_param *)wmi_buf_data(buf);
1164 cmd->vdev_id = filter_params->vdev_id;
1165
1166 WMITLV_SET_HDR(&cmd->tlv_header,
1167 WMITLV_TAG_STRUC_wmi_rmv_bcn_filter_cmd_fixed_param,
1168 WMITLV_GET_STRUCT_TLVLEN(
1169 wmi_rmv_bcn_filter_cmd_fixed_param));
1170
1171 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
1172 WMI_RMV_BCN_FILTER_CMDID);
1173 if (ret) {
1174 WMA_LOGE("Failed to send wmi remove beacon filter = %d",
1175 ret);
1176 wmi_buf_free(buf);
1177 return QDF_STATUS_E_FAILURE;
1178 }
Gupta, Kapil4cb1d7d2016-04-16 18:16:25 -07001179
1180 return QDF_STATUS_SUCCESS;
1181}
1182
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05301183/**
1184 * wma_send_adapt_dwelltime_params() - send adaptive dwelltime configuration
1185 * params to firmware
1186 * @wma_handle: wma handler
1187 * @dwelltime_params: pointer to dwelltime_params
1188 *
1189 * Return: QDF_STATUS_SUCCESS on success and QDF failure reason code for failure
1190 */
1191QDF_STATUS wma_send_adapt_dwelltime_params(WMA_HANDLE handle,
1192 struct adaptive_dwelltime_params *dwelltime_params)
1193{
1194 tp_wma_handle wma_handle = (tp_wma_handle) handle;
1195 struct wmi_adaptive_dwelltime_params wmi_param = {0};
1196 int32_t err;
1197
1198 wmi_param.is_enabled = dwelltime_params->is_enabled;
1199 wmi_param.dwelltime_mode = dwelltime_params->dwelltime_mode;
1200 wmi_param.lpf_weight = dwelltime_params->lpf_weight;
1201 wmi_param.passive_mon_intval = dwelltime_params->passive_mon_intval;
1202 wmi_param.wifi_act_threshold = dwelltime_params->wifi_act_threshold;
1203 err = wmi_unified_send_adapt_dwelltime_params_cmd(wma_handle->
1204 wmi_handle, &wmi_param);
1205 if (err)
1206 return QDF_STATUS_E_FAILURE;
1207
1208 return QDF_STATUS_SUCCESS;
1209}
Gupta, Kapil4cb1d7d2016-04-16 18:16:25 -07001210
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001211#ifdef FEATURE_GREEN_AP
1212
1213/**
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001214 * wma_egap_info_status_event() - egap info status event
1215 * @handle: pointer to wma handler
1216 * @event: pointer to event
1217 * @len: len of the event
1218 *
1219 * Return: 0 for success, otherwise appropriate error code
1220 */
1221static int wma_egap_info_status_event(void *handle, u_int8_t *event,
1222 uint32_t len)
1223{
1224 WMI_TX_PAUSE_EVENTID_param_tlvs *param_buf;
1225 wmi_ap_ps_egap_info_event_fixed_param *egap_info_event;
1226 wmi_ap_ps_egap_info_chainmask_list *chainmask_event;
1227 u_int8_t *buf_ptr;
1228
1229 param_buf = (WMI_TX_PAUSE_EVENTID_param_tlvs *)event;
1230 if (!param_buf) {
1231 WMA_LOGE("Invalid EGAP Info status event buffer");
1232 return -EINVAL;
1233 }
1234
1235 egap_info_event = (wmi_ap_ps_egap_info_event_fixed_param *)
1236 param_buf->fixed_param;
1237 buf_ptr = (uint8_t *)egap_info_event;
1238 buf_ptr += sizeof(wmi_ap_ps_egap_info_event_fixed_param);
1239 chainmask_event = (wmi_ap_ps_egap_info_chainmask_list *)buf_ptr;
1240
1241 WMA_LOGI("mac_id: %d, status: %d, tx_mask: %x, rx_mask: %d",
1242 chainmask_event->mac_id,
1243 egap_info_event->status,
1244 chainmask_event->tx_chainmask,
1245 chainmask_event->rx_chainmask);
1246 return 0;
1247}
1248
1249/**
1250 * wma_send_egap_conf_params() - send wmi cmd of egap configuration params
1251 * @wma_handle: wma handler
1252 * @egap_params: pointer to egap_params
1253 *
1254 * Return: 0 for success, otherwise appropriate error code
1255 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301256QDF_STATUS wma_send_egap_conf_params(WMA_HANDLE handle,
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001257 struct egap_conf_params *egap_params)
1258{
1259 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhaa64c242016-03-08 11:31:49 +05301260 wmi_ap_ps_egap_param_cmd_fixed_param cmd = {0};
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001261 int32_t err;
1262
Govind Singhaa64c242016-03-08 11:31:49 +05301263 cmd.enable = egap_params->enable;
1264 cmd.inactivity_time = egap_params->inactivity_time;
1265 cmd.wait_time = egap_params->wait_time;
1266 cmd.flags = egap_params->flags;
1267 err = wmi_unified_egap_conf_params_cmd(wma_handle->wmi_handle, &cmd);
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001268 if (err) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301269 return QDF_STATUS_E_FAILURE;
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001270 }
Govind Singhaa64c242016-03-08 11:31:49 +05301271
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301272 return QDF_STATUS_SUCCESS;
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001273}
1274
1275/**
1276 * wma_setup_egap_support() - setup the EGAP support flag
1277 * @tgt_cfg: pointer to hdd target configuration
1278 * @egap_support: EGAP support flag
1279 *
1280 * Return: None
1281 */
1282void wma_setup_egap_support(struct wma_tgt_cfg *tgt_cfg, WMA_HANDLE handle)
1283{
1284 tp_wma_handle wma_handle = (tp_wma_handle) handle;
1285
1286 if (tgt_cfg && wma_handle)
1287 tgt_cfg->egap_support = wma_handle->egap_support;
1288}
1289
1290/**
1291 * wma_register_egap_event_handle() - register the EGAP event handle
1292 * @wma_handle: wma handler
1293 *
1294 * Return: None
1295 */
1296void wma_register_egap_event_handle(WMA_HANDLE handle)
1297{
1298 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhd76a5b02016-03-08 15:12:14 +05301299 QDF_STATUS status;
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001300
1301 if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap,
1302 WMI_SERVICE_EGAP)) {
1303 status = wmi_unified_register_event_handler(
1304 wma_handle->wmi_handle,
1305 WMI_AP_PS_EGAP_INFO_EVENTID,
Govind Singhd76a5b02016-03-08 15:12:14 +05301306 wma_egap_info_status_event,
1307 WMA_RX_SERIALIZER_CTX);
1308 if (QDF_IS_STATUS_ERROR(status)) {
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001309 WMA_LOGE("Failed to register Enhance Green AP event");
1310 wma_handle->egap_support = false;
1311 } else {
1312 WMA_LOGI("Set the Enhance Green AP event handler");
1313 wma_handle->egap_support = true;
1314 }
1315 } else
1316 wma_handle->egap_support = false;
1317}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001318#endif /* FEATURE_GREEN_AP */
1319
Govind Singha471e5e2015-10-12 17:11:14 +05301320/**
Govind Singhaa64c242016-03-08 11:31:49 +05301321 * wma_unified_fw_profiling_cmd() - send FW profiling cmd to WLAN FW
Govind Singha471e5e2015-10-12 17:11:14 +05301322 * @wma: wma handle
1323 * @cmd: Profiling command index
1324 * @value1: parameter1 value
1325 * @value2: parameter2 value
1326 *
1327 * Return: 0 for success else error code
1328 */
Govind Singhaa64c242016-03-08 11:31:49 +05301329QDF_STATUS wma_unified_fw_profiling_cmd(wmi_unified_t wmi_handle,
Govind Singha471e5e2015-10-12 17:11:14 +05301330 uint32_t cmd, uint32_t value1, uint32_t value2)
1331{
Govind Singha471e5e2015-10-12 17:11:14 +05301332 int ret;
Govind Singha471e5e2015-10-12 17:11:14 +05301333
Govind Singhaa64c242016-03-08 11:31:49 +05301334 ret = wmi_unified_fw_profiling_data_cmd(wmi_handle, cmd,
1335 value1, value2);
1336 if (ret) {
1337 WMA_LOGE("enable cmd Failed for id %d value %d",
1338 value1, value2);
1339 return ret;
Govind Singha471e5e2015-10-12 17:11:14 +05301340 }
1341
Govind Singhaa64c242016-03-08 11:31:49 +05301342 return QDF_STATUS_SUCCESS;
Govind Singha471e5e2015-10-12 17:11:14 +05301343}
1344
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001345#ifdef FEATURE_WLAN_LPHB
1346/**
1347 * wma_lphb_handler() - send LPHB indication to SME
1348 * @wma: wma handle
1349 * @event: event handler
1350 *
1351 * Return: 0 for success or error code
1352 */
1353static int wma_lphb_handler(tp_wma_handle wma, uint8_t *event)
1354{
1355 wmi_hb_ind_event_fixed_param *hb_fp;
1356 tSirLPHBInd *slphb_indication;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301357 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001358 cds_msg_t sme_msg = { 0 };
1359
1360 hb_fp = (wmi_hb_ind_event_fixed_param *) event;
1361 if (!hb_fp) {
1362 WMA_LOGE("Invalid wmi_hb_ind_event_fixed_param buffer");
1363 return -EINVAL;
1364 }
1365
1366 WMA_LOGD("lphb indication received with vdev_id=%d, session=%d, reason=%d",
1367 hb_fp->vdev_id, hb_fp->session, hb_fp->reason);
1368
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301369 slphb_indication = (tSirLPHBInd *) qdf_mem_malloc(sizeof(tSirLPHBInd));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001370
1371 if (!slphb_indication) {
1372 WMA_LOGE("Invalid LPHB indication buffer");
1373 return -ENOMEM;
1374 }
1375
1376 slphb_indication->sessionIdx = hb_fp->session;
1377 slphb_indication->protocolType = hb_fp->reason;
1378 slphb_indication->eventReason = hb_fp->reason;
1379
1380 sme_msg.type = eWNI_SME_LPHB_IND;
1381 sme_msg.bodyptr = slphb_indication;
1382 sme_msg.bodyval = 0;
1383
Anurag Chouhan6d760662016-02-20 16:05:43 +05301384 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301385 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001386 WMA_LOGE("Fail to post eWNI_SME_LPHB_IND msg to SME");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301387 qdf_mem_free(slphb_indication);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001388 return -EINVAL;
1389 }
1390
1391 return 0;
1392}
1393#endif /* FEATURE_WLAN_LPHB */
1394
1395#ifdef FEATURE_WLAN_RA_FILTERING
1396/**
1397 * wma_wow_sta_ra_filter() - set RA filter pattern in fw
1398 * @wma: wma handle
1399 * @vdev_id: vdev id
1400 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05301401 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001402 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301403static QDF_STATUS wma_wow_sta_ra_filter(tp_wma_handle wma, uint8_t vdev_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001404{
1405
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001406 struct wma_txrx_node *iface;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001407 int ret;
Govind Singhaa64c242016-03-08 11:31:49 +05301408 uint8_t default_pattern;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001409
1410 iface = &wma->interfaces[vdev_id];
1411
Govind Singhaa64c242016-03-08 11:31:49 +05301412 default_pattern = iface->num_wow_default_patterns++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001413
1414 WMA_LOGD("%s: send RA rate limit [%d] to fw vdev = %d", __func__,
1415 wma->RArateLimitInterval, vdev_id);
1416
Govind Singhaa64c242016-03-08 11:31:49 +05301417 ret = wmi_unified_wow_sta_ra_filter_cmd(wma->wmi_handle, vdev_id,
1418 default_pattern, wma->RArateLimitInterval);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001419 if (ret) {
1420 WMA_LOGE("%s: Failed to send RA rate limit to fw", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001421 iface->num_wow_default_patterns--;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301422 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001423 }
1424
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301425 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001426
1427}
1428#endif /* FEATURE_WLAN_RA_FILTERING */
1429
1430/**
1431 * wmi_unified_nat_keepalive_enable() - enable NAT keepalive filter
1432 * @wma: wma handle
1433 * @vdev_id: vdev id
1434 *
1435 * Return: 0 for success or error code
1436 */
1437int wmi_unified_nat_keepalive_enable(tp_wma_handle wma, uint8_t vdev_id)
1438{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001439
Govind Singhaa64c242016-03-08 11:31:49 +05301440 if (wmi_unified_nat_keepalive_en_cmd(wma->wmi_handle, vdev_id))
1441 return QDF_STATUS_E_FAILURE;
1442
1443 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001444}
1445
1446/**
Govind Singhd76a5b02016-03-08 15:12:14 +05301447 * wma_unified_csa_offload_enable() - sen CSA offload enable command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001448 * @wma: wma handle
1449 * @vdev_id: vdev id
1450 *
1451 * Return: 0 for success or error code
1452 */
Govind Singhd76a5b02016-03-08 15:12:14 +05301453int wma_unified_csa_offload_enable(tp_wma_handle wma, uint8_t vdev_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001454{
Govind Singhaa64c242016-03-08 11:31:49 +05301455 if (wmi_unified_csa_offload_enable(wma->wmi_handle,
1456 vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001457 WMA_LOGP("%s: Failed to send CSA offload enable command",
1458 __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001459 return -EIO;
1460 }
Govind Singhaa64c242016-03-08 11:31:49 +05301461
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001462 return 0;
1463}
1464
1465#ifdef WLAN_FEATURE_NAN
1466/**
1467 * wma_nan_rsp_event_handler() - Function is used to handle nan response
1468 * @handle: wma handle
1469 * @event_buf: event buffer
1470 * @len: length of buffer
1471 *
1472 * Return: 0 for success or error code
1473 */
1474int wma_nan_rsp_event_handler(void *handle, uint8_t *event_buf,
1475 uint32_t len)
1476{
1477 WMI_NAN_EVENTID_param_tlvs *param_buf;
1478 tSirNanEvent *nan_rsp_event;
1479 wmi_nan_event_hdr *nan_rsp_event_hdr;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301480 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001481 cds_msg_t cds_msg;
1482 uint8_t *buf_ptr;
1483 uint32_t alloc_len;
1484
1485 /*
1486 * This is how received event_buf looks like
1487 *
1488 * <-------------------- event_buf ----------------------------------->
1489 *
1490 * <--wmi_nan_event_hdr--><---WMI_TLV_HDR_SIZE---><----- data -------->
1491 *
1492 * +-----------+---------+-----------------------+--------------------+
1493 * | tlv_header| data_len| WMITLV_TAG_ARRAY_BYTE | nan_rsp_event_data |
1494 * +-----------+---------+-----------------------+--------------------+
1495 */
1496
1497 WMA_LOGD("%s: Posting NaN response event to SME", __func__);
1498 param_buf = (WMI_NAN_EVENTID_param_tlvs *) event_buf;
1499 if (!param_buf) {
1500 WMA_LOGE("%s: Invalid nan response event buf", __func__);
1501 return -EINVAL;
1502 }
1503 nan_rsp_event_hdr = param_buf->fixed_param;
1504 buf_ptr = (uint8_t *) nan_rsp_event_hdr;
1505 alloc_len = sizeof(tSirNanEvent);
1506 alloc_len += nan_rsp_event_hdr->data_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301507 nan_rsp_event = (tSirNanEvent *) qdf_mem_malloc(alloc_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001508 if (NULL == nan_rsp_event) {
1509 WMA_LOGE("%s: Memory allocation failure", __func__);
1510 return -ENOMEM;
1511 }
1512
1513 nan_rsp_event->event_data_len = nan_rsp_event_hdr->data_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301514 qdf_mem_copy(nan_rsp_event->event_data, buf_ptr +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001515 sizeof(wmi_nan_event_hdr) + WMI_TLV_HDR_SIZE,
1516 nan_rsp_event->event_data_len);
1517 cds_msg.type = eWNI_SME_NAN_EVENT;
1518 cds_msg.bodyptr = (void *)nan_rsp_event;
1519 cds_msg.bodyval = 0;
1520
Krunal Soni66c113f2016-12-21 16:46:47 -08001521 status = cds_mq_post_message(QDF_MODULE_ID_SME, &cds_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301522 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001523 WMA_LOGE("%s: Failed to post NaN response event to SME",
1524 __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301525 qdf_mem_free(nan_rsp_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001526 return -EFAULT;
1527 }
1528 WMA_LOGD("%s: NaN response event Posted to SME", __func__);
1529 return 0;
1530}
Naveen Rawatc9f09522016-05-12 14:02:42 -07001531#else
1532int wma_nan_rsp_event_handler(void *handle, uint8_t *event_buf,
1533 uint32_t len)
1534{
1535 return 0;
1536}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001537#endif /* WLAN_FEATURE_NAN */
1538
1539/**
1540 * wma_csa_offload_handler() - CSA event handler
1541 * @handle: wma handle
1542 * @event: event buffer
1543 * @len: buffer length
1544 *
1545 * This event is sent by firmware when it receives CSA IE.
1546 *
1547 * Return: 0 for success or error code
1548 */
1549int wma_csa_offload_handler(void *handle, uint8_t *event, uint32_t len)
1550{
1551 tp_wma_handle wma = (tp_wma_handle) handle;
1552 WMI_CSA_HANDLING_EVENTID_param_tlvs *param_buf;
1553 wmi_csa_event_fixed_param *csa_event;
1554 uint8_t bssid[IEEE80211_ADDR_LEN];
1555 uint8_t vdev_id = 0;
1556 uint8_t cur_chan = 0;
1557 struct ieee80211_channelswitch_ie *csa_ie;
Chandrasekaran, Manishekar5c19dc52016-02-04 14:58:26 +05301558 struct csa_offload_params *csa_offload_event;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001559 struct ieee80211_extendedchannelswitch_ie *xcsa_ie;
1560 struct ieee80211_ie_wide_bw_switch *wb_ie;
1561 struct wma_txrx_node *intr = wma->interfaces;
1562
1563 param_buf = (WMI_CSA_HANDLING_EVENTID_param_tlvs *) event;
1564
1565 WMA_LOGD("%s: Enter", __func__);
1566 if (!param_buf) {
1567 WMA_LOGE("Invalid csa event buffer");
1568 return -EINVAL;
1569 }
1570 csa_event = param_buf->fixed_param;
1571 WMI_MAC_ADDR_TO_CHAR_ARRAY(&csa_event->i_addr2, &bssid[0]);
1572
1573 if (wma_find_vdev_by_bssid(wma, bssid, &vdev_id) == NULL) {
1574 WMA_LOGE("Invalid bssid received %s:%d", __func__, __LINE__);
1575 return -EINVAL;
1576 }
1577
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301578 csa_offload_event = qdf_mem_malloc(sizeof(*csa_offload_event));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001579 if (!csa_offload_event) {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05301580 WMA_LOGE("QDF MEM Alloc Failed for csa_offload_event");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001581 return -EINVAL;
1582 }
1583
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301584 qdf_mem_zero(csa_offload_event, sizeof(*csa_offload_event));
1585 qdf_mem_copy(csa_offload_event->bssId, &bssid, IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001586
1587 if (csa_event->ies_present_flag & WMI_CSA_IE_PRESENT) {
1588 csa_ie = (struct ieee80211_channelswitch_ie *)
1589 (&csa_event->csa_ie[0]);
1590 csa_offload_event->channel = csa_ie->newchannel;
Chandrasekaran, Manishekar5c19dc52016-02-04 14:58:26 +05301591 csa_offload_event->switch_mode = csa_ie->switchmode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001592 } else if (csa_event->ies_present_flag & WMI_XCSA_IE_PRESENT) {
1593 xcsa_ie = (struct ieee80211_extendedchannelswitch_ie *)
1594 (&csa_event->xcsa_ie[0]);
1595 csa_offload_event->channel = xcsa_ie->newchannel;
Chandrasekaran, Manishekar5c19dc52016-02-04 14:58:26 +05301596 csa_offload_event->switch_mode = xcsa_ie->switchmode;
Gupta, Kapil121bf212015-11-25 19:21:29 +05301597 csa_offload_event->new_op_class = xcsa_ie->newClass;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001598 } else {
1599 WMA_LOGE("CSA Event error: No CSA IE present");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301600 qdf_mem_free(csa_offload_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001601 return -EINVAL;
1602 }
1603
1604 if (csa_event->ies_present_flag & WMI_WBW_IE_PRESENT) {
1605 wb_ie = (struct ieee80211_ie_wide_bw_switch *)
1606 (&csa_event->wb_ie[0]);
1607 csa_offload_event->new_ch_width = wb_ie->new_ch_width;
1608 csa_offload_event->new_ch_freq_seg1 = wb_ie->new_ch_freq_seg1;
1609 csa_offload_event->new_ch_freq_seg2 = wb_ie->new_ch_freq_seg2;
1610 }
1611
1612 csa_offload_event->ies_present_flag = csa_event->ies_present_flag;
1613
1614 WMA_LOGD("CSA: New Channel = %d BSSID:%pM",
1615 csa_offload_event->channel, csa_offload_event->bssId);
1616
1617 cur_chan = cds_freq_to_chan(intr[vdev_id].mhz);
1618 /*
1619 * basic sanity check: requested channel should not be 0
1620 * and equal to home channel
1621 */
1622 if ((0 == csa_offload_event->channel) ||
1623 (cur_chan == csa_offload_event->channel)) {
1624 WMA_LOGE("CSA Event with channel %d. Ignore !!",
1625 csa_offload_event->channel);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301626 qdf_mem_free(csa_offload_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001627 return -EINVAL;
1628 }
1629 wma->interfaces[vdev_id].is_channel_switch = true;
1630 wma_send_msg(wma, WMA_CSA_OFFLOAD_EVENT, (void *)csa_offload_event, 0);
1631 return 0;
1632}
1633
1634#ifdef FEATURE_OEM_DATA_SUPPORT
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001635/**
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001636 * wma_oem_data_response_handler() - OEM data response event handler
1637 * @handle: wma handle
1638 * @datap: data ptr
1639 * @len: data length
1640 *
1641 * Return: 0 for success or error code
1642 */
1643int wma_oem_data_response_handler(void *handle,
1644 uint8_t *datap, uint32_t len)
1645{
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001646 WMI_OEM_RESPONSE_EVENTID_param_tlvs *param_buf;
1647 uint8_t *data;
1648 uint32_t datalen;
Krishna Kumaar Natarajanc1fa17d2016-08-03 14:19:20 -07001649 struct oem_data_rsp *oem_rsp;
Krishna Kumaar Natarajan73ea9f22016-06-30 18:38:47 -07001650 tpAniSirGlobal pmac = cds_get_context(QDF_MODULE_ID_PE);
1651
1652 if (!pmac) {
1653 WMA_LOGE(FL("Invalid pmac"));
1654 return -EINVAL;
1655 }
1656
Krishna Kumaar Natarajanbbbf2ef2016-08-03 14:06:26 -07001657 if (!pmac->sme.oem_data_rsp_callback) {
Krishna Kumaar Natarajan73ea9f22016-06-30 18:38:47 -07001658 WMA_LOGE(FL("Callback not registered"));
1659 return -EINVAL;
1660 }
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001661
1662 param_buf = (WMI_OEM_RESPONSE_EVENTID_param_tlvs *) datap;
1663 if (!param_buf) {
1664 WMA_LOGE(FL("Received NULL buf ptr from FW"));
1665 return -ENOMEM;
1666 }
1667
1668 data = param_buf->data;
1669 datalen = param_buf->num_data;
1670
1671 if (!data) {
1672 WMA_LOGE(FL("Received NULL data from FW"));
1673 return -EINVAL;
1674 }
1675
1676 if (datalen > OEM_DATA_RSP_SIZE) {
1677 WMA_LOGE(FL("Received data len %d exceeds max value %d"),
1678 datalen, OEM_DATA_RSP_SIZE);
1679 return -EINVAL;
1680 }
1681
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001682 oem_rsp = qdf_mem_malloc(sizeof(*oem_rsp));
1683 if (!oem_rsp) {
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001684 WMA_LOGE(FL("Failed to alloc oem_data_rsp"));
1685 return -ENOMEM;
1686 }
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001687 oem_rsp->rsp_len = datalen;
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001688 if (oem_rsp->rsp_len) {
Krishna Kumaar Natarajan73ea9f22016-06-30 18:38:47 -07001689 oem_rsp->data = qdf_mem_malloc(oem_rsp->rsp_len);
1690 if (!oem_rsp->data) {
1691 WMA_LOGE(FL("malloc failed for data"));
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001692 qdf_mem_free(oem_rsp);
1693 return -ENOMEM;
1694 }
1695 } else {
1696 WMA_LOGE(FL("Invalid rsp length: %d"),
1697 oem_rsp->rsp_len);
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001698 qdf_mem_free(oem_rsp);
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001699 return -EINVAL;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001700 }
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001701
Krishna Kumaar Natarajan73ea9f22016-06-30 18:38:47 -07001702 qdf_mem_copy(oem_rsp->data, data, datalen);
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001703
Krishna Kumaar Natarajan73ea9f22016-06-30 18:38:47 -07001704 WMA_LOGI(FL("Sending OEM_DATA_RSP(len: %d) to upper layer"), datalen);
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001705
Krishna Kumaar Natarajanbbbf2ef2016-08-03 14:06:26 -07001706 pmac->sme.oem_data_rsp_callback(oem_rsp);
Krishna Kumaar Natarajan73ea9f22016-06-30 18:38:47 -07001707
1708 if (oem_rsp->data)
1709 qdf_mem_free(oem_rsp->data);
1710 qdf_mem_free(oem_rsp);
1711
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001712 return 0;
1713}
1714
1715/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001716 * wma_start_oem_data_req() - start OEM data request to target
1717 * @wma_handle: wma handle
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -07001718 * @oem_data_req: start request params
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001719 *
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -07001720 * Return: QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001721 */
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -07001722QDF_STATUS wma_start_oem_data_req(tp_wma_handle wma_handle,
Krishna Kumaar Natarajanc1fa17d2016-08-03 14:19:20 -07001723 struct oem_data_req *oem_data_req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001724{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001725 int ret = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001726
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001727 WMA_LOGD(FL("Send OEM Data Request to target"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001728
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -07001729 if (!oem_data_req || !oem_data_req->data) {
1730 WMA_LOGE(FL("oem_data_req is null"));
1731 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001732 }
1733
1734 if (!wma_handle || !wma_handle->wmi_handle) {
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001735 WMA_LOGE(FL("WMA - closed, can not send Oem data request cmd"));
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -07001736 qdf_mem_free(oem_data_req->data);
1737 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001738 }
1739
Govind Singhaa64c242016-03-08 11:31:49 +05301740 ret = wmi_unified_start_oem_data_cmd(wma_handle->wmi_handle,
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -07001741 oem_data_req->data_len,
1742 oem_data_req->data);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001743
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -07001744 if (!QDF_IS_STATUS_SUCCESS(ret))
1745 WMA_LOGE(FL("wmi cmd send failed"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001746
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -07001747 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001748}
1749#endif /* FEATURE_OEM_DATA_SUPPORT */
1750
1751
1752/**
1753 * wma_unified_dfs_radar_rx_event_handler() - dfs radar rx event handler
1754 * @handle: wma handle
1755 * @data: data buffer
1756 * @datalen: data length
1757 *
1758 * WMI handler for WMI_DFS_RADAR_EVENTID
1759 * This handler is registered for handling
1760 * filtered DFS Phyerror. This handler is
1761 * will be invoked only when DFS Phyerr
1762 * filtering offload is enabled.
1763 *
1764 * Return: 1 for Success and 0 for error
1765 */
1766static int wma_unified_dfs_radar_rx_event_handler(void *handle,
1767 uint8_t *data,
1768 uint32_t datalen)
1769{
1770 tp_wma_handle wma = (tp_wma_handle) handle;
1771 struct ieee80211com *ic;
1772 struct ath_dfs *dfs;
1773 struct dfs_event *event;
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05301774 struct dfs_ieee80211_channel *chan;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001775 int empty;
1776 int do_check_chirp = 0;
1777 int is_hw_chirp = 0;
1778 int is_sw_chirp = 0;
1779 int is_pri = 0;
Vishwajith Upendrabf673e72016-01-19 16:05:40 -08001780 bool is_ch_dfs = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001781
1782 WMI_DFS_RADAR_EVENTID_param_tlvs *param_tlvs;
1783 wmi_dfs_radar_event_fixed_param *radar_event;
1784
1785 ic = wma->dfs_ic;
1786 if (NULL == ic) {
1787 WMA_LOGE("%s: dfs_ic is NULL ", __func__);
1788 return 0;
1789 }
1790
1791 dfs = (struct ath_dfs *)ic->ic_dfs;
1792 param_tlvs = (WMI_DFS_RADAR_EVENTID_param_tlvs *) data;
1793
1794 if (NULL == dfs) {
1795 WMA_LOGE("%s: dfs is NULL ", __func__);
1796 return 0;
1797 }
1798 /*
1799 * This parameter holds the number
1800 * of phyerror interrupts to the host
1801 * after the phyerrors have passed through
1802 * false detect filters in the firmware.
1803 */
1804 dfs->dfs_phyerr_count++;
1805
1806 if (!param_tlvs) {
1807 WMA_LOGE("%s: Received NULL data from FW", __func__);
1808 return 0;
1809 }
1810
1811 radar_event = param_tlvs->fixed_param;
1812
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301813 qdf_spin_lock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001814 chan = ic->ic_curchan;
Edhar, Mahesh Kumar35d9b2e2015-10-26 17:06:23 +05301815 if (ic->disable_phy_err_processing) {
1816 WMA_LOGD("%s: radar indication done,drop phyerror event",
1817 __func__);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301818 qdf_spin_unlock_bh(&ic->chan_lock);
Edhar, Mahesh Kumar35d9b2e2015-10-26 17:06:23 +05301819 return 0;
1820 }
1821
Vishwajith Upendrabf673e72016-01-19 16:05:40 -08001822 if (IEEE80211_IS_CHAN_11AC_VHT160(chan)) {
1823 is_ch_dfs = true;
1824 } else if (IEEE80211_IS_CHAN_11AC_VHT80P80(chan)) {
1825 if (cds_get_channel_state(chan->ic_ieee) == CHANNEL_STATE_DFS ||
1826 cds_get_channel_state(chan->ic_ieee_ext -
1827 WMA_80MHZ_START_CENTER_CH_DIFF) ==
1828 CHANNEL_STATE_DFS)
1829 is_ch_dfs = true;
1830 } else {
1831 if (cds_get_channel_state(chan->ic_ieee) == CHANNEL_STATE_DFS)
1832 is_ch_dfs = true;
1833 }
1834 if (!is_ch_dfs) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001835 WMA_LOGE
1836 ("%s: Invalid DFS Phyerror event. Channel=%d is Non-DFS",
1837 __func__, chan->ic_ieee);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301838 qdf_spin_unlock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001839 return 0;
1840 }
1841
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301842 qdf_spin_unlock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001843 dfs->ath_dfs_stats.total_phy_errors++;
1844
1845 if (dfs->dfs_caps.ath_chip_is_bb_tlv) {
1846 do_check_chirp = 1;
1847 is_pri = 1;
1848 is_hw_chirp = radar_event->pulse_is_chirp;
1849
1850 if ((uint32_t) dfs->dfs_phyerr_freq_min >
1851 radar_event->pulse_center_freq) {
1852 dfs->dfs_phyerr_freq_min =
1853 (int)radar_event->pulse_center_freq;
1854 }
1855
1856 if (dfs->dfs_phyerr_freq_max <
1857 (int)radar_event->pulse_center_freq) {
1858 dfs->dfs_phyerr_freq_max =
1859 (int)radar_event->pulse_center_freq;
1860 }
1861 }
1862
1863 /*
1864 * Now, add the parsed, checked and filtered
1865 * radar phyerror event radar pulse event list.
1866 * This event will then be processed by
1867 * dfs_radar_processevent() to see if the pattern
1868 * of pulses in radar pulse list match any radar
1869 * singnature in the current regulatory domain.
1870 */
1871
1872 ATH_DFSEVENTQ_LOCK(dfs);
1873 empty = STAILQ_EMPTY(&(dfs->dfs_eventq));
1874 ATH_DFSEVENTQ_UNLOCK(dfs);
1875 if (empty) {
1876 return 0;
1877 }
1878 /*
1879 * Add the event to the list, if there's space.
1880 */
1881 ATH_DFSEVENTQ_LOCK(dfs);
1882 event = STAILQ_FIRST(&(dfs->dfs_eventq));
1883 if (event == NULL) {
1884 ATH_DFSEVENTQ_UNLOCK(dfs);
1885 WMA_LOGE("%s: No more space left for queuing DFS Phyerror events",
1886 __func__);
1887 return 0;
1888 }
1889 STAILQ_REMOVE_HEAD(&(dfs->dfs_eventq), re_list);
1890 ATH_DFSEVENTQ_UNLOCK(dfs);
1891 dfs->dfs_phyerr_queued_count++;
1892 dfs->dfs_phyerr_w53_counter++;
1893 event->re_dur = (uint8_t) radar_event->pulse_duration;
1894 event->re_rssi = radar_event->rssi;
1895 event->re_ts = radar_event->pulse_detect_ts & DFS_TSMASK;
1896 event->re_full_ts = (((uint64_t) radar_event->upload_fullts_high) << 32)
1897 | radar_event->upload_fullts_low;
1898
1899 /*
1900 * Index of peak magnitude
1901 */
1902 event->sidx = radar_event->peak_sidx;
Kapil Guptae29ab4a2016-08-09 18:36:12 +05301903 event->re_flags = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001904
1905 /*
1906 * Handle chirp flags.
1907 */
1908 if (do_check_chirp) {
1909 event->re_flags |= DFS_EVENT_CHECKCHIRP;
1910 if (is_hw_chirp) {
1911 event->re_flags |= DFS_EVENT_HW_CHIRP;
1912 }
1913 if (is_sw_chirp) {
1914 event->re_flags |= DFS_EVENT_SW_CHIRP;
1915 }
1916 }
1917 /*
1918 * Correctly set which channel is being reported on
1919 */
1920 if (is_pri) {
1921 event->re_chanindex = (uint8_t) dfs->dfs_curchan_radindex;
1922 } else {
1923 if (dfs->dfs_extchan_radindex == -1) {
1924 WMA_LOGI("%s phyerr on ext channel", __func__);
1925 }
1926 event->re_chanindex = (uint8_t) dfs->dfs_extchan_radindex;
1927 WMA_LOGI("%s:New extension channel event is added to queue",
1928 __func__);
1929 }
1930
1931 ATH_DFSQ_LOCK(dfs);
1932
1933 STAILQ_INSERT_TAIL(&(dfs->dfs_radarq), event, re_list);
1934
1935 empty = STAILQ_EMPTY(&dfs->dfs_radarq);
1936
1937 ATH_DFSQ_UNLOCK(dfs);
1938
1939 if (!empty && !dfs->ath_radar_tasksched) {
1940 dfs->ath_radar_tasksched = 1;
1941 OS_SET_TIMER(&dfs->ath_dfs_task_timer, 0);
1942 }
1943
1944 return 1;
1945
1946}
1947
1948/**
1949 * wma_unified_phyerr_rx_event_handler() - phyerr event handler
1950 * @handle: wma handle
1951 * @data: data buffer
1952 * @datalen: buffer length
1953 *
1954 * WMI Handler for WMI_PHYERR_EVENTID event from firmware.
1955 * This handler is currently handling only DFS phy errors.
1956 * This handler will be invoked only when the DFS phyerror
1957 * filtering offload is disabled.
1958 *
1959 * Return: 1:Success, 0:Failure
1960 */
1961static int wma_unified_phyerr_rx_event_handler(void *handle,
1962 uint8_t *data, uint32_t datalen)
1963{
1964 tp_wma_handle wma = (tp_wma_handle) handle;
1965 WMI_PHYERR_EVENTID_param_tlvs *param_tlvs;
1966 wmi_comb_phyerr_rx_hdr *pe_hdr;
1967 uint8_t *bufp;
1968 wmi_single_phyerr_rx_event *ev;
1969 struct ieee80211com *ic = wma->dfs_ic;
Anurag Chouhan6d760662016-02-20 16:05:43 +05301970 qdf_size_t n;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001971 A_UINT64 tsf64 = 0;
1972 int phy_err_code = 0;
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08001973 A_UINT32 phy_err_mask = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001974 int error = 0;
1975 tpAniSirGlobal mac_ctx =
Anurag Chouhan6d760662016-02-20 16:05:43 +05301976 (tpAniSirGlobal)cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001977 bool enable_log = false;
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08001978 int max_dfs_buf_length = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001979
1980 if (NULL == mac_ctx) {
1981 WMA_LOGE("%s: mac_ctx is NULL", __func__);
1982 return 0;
1983 }
1984 enable_log = mac_ctx->sap.enable_dfs_phy_error_logs;
1985
1986 param_tlvs = (WMI_PHYERR_EVENTID_param_tlvs *) data;
1987
1988 if (!param_tlvs) {
1989 WMA_LOGE("%s: Received NULL data from FW", __func__);
1990 return 0;
1991 }
1992
1993 pe_hdr = param_tlvs->hdr;
1994 if (pe_hdr == NULL) {
1995 WMA_LOGE("%s: Received Data PE Header is NULL", __func__);
1996 return 0;
1997 }
1998
1999 /* Ensure it's at least the size of the header */
2000 if (datalen < sizeof(*pe_hdr)) {
2001 WMA_LOGE("%s: Expected minimum size %zu, received %d",
2002 __func__, sizeof(*pe_hdr), datalen);
2003 return 0;
2004 }
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002005 /*
2006 * The max buffer lenght is larger for DFS-3 than DFS-2.
2007 * So, accordingly use the correct max buffer size.
2008 */
2009 if (wma->hw_bd_id != WMI_HWBD_QCA6174)
2010 max_dfs_buf_length = DFS3_MAX_BUF_LENGTH;
2011 else
2012 max_dfs_buf_length = DFS_MAX_BUF_LENGTH;
2013
2014 if (pe_hdr->buf_len > max_dfs_buf_length) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002015 WMA_LOGE("%s: Received Invalid Phyerror event buffer length = %d"
2016 "Maximum allowed buf length = %d", __func__,
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002017 pe_hdr->buf_len, max_dfs_buf_length);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002018
2019 return 0;
2020 }
2021
2022 /*
2023 * Reconstruct the 64 bit event TSF. This isn't from the MAC, it's
2024 * at the time the event was sent to us, the TSF value will be
2025 * in the future.
2026 */
2027 tsf64 = pe_hdr->tsf_l32;
2028 tsf64 |= (((uint64_t) pe_hdr->tsf_u32) << 32);
2029
2030 /*
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002031 * Check the HW board ID to figure out
2032 * if DFS-3 is supported. In DFS-3
2033 * phyerror mask indicates the type of
2034 * phyerror, whereas in DFS-2 phyerrorcode
2035 * indicates the type of phyerror. If the
2036 * board is NOT WMI_HWBD_QCA6174, for now
2037 * assume that it supports DFS-3.
2038 */
2039 if (wma->hw_bd_id != WMI_HWBD_QCA6174) {
2040 phy_err_mask = pe_hdr->rsPhyErrMask0;
2041 WMA_LOGD("%s: DFS-3 phyerror mask = 0x%x",
2042 __func__, phy_err_mask);
2043 }
2044
2045 /*
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002046 * Loop over the bufp, extracting out phyerrors
2047 * wmi_unified_comb_phyerr_rx_event.bufp is a char pointer,
2048 * which isn't correct here - what we have received here
2049 * is an array of TLV-style PHY errors.
2050 */
2051 n = 0; /* Start just after the header */
2052 bufp = param_tlvs->bufp;
2053 while (n < pe_hdr->buf_len) {
2054 /* ensure there's at least space for the header */
2055 if ((pe_hdr->buf_len - n) < sizeof(ev->hdr)) {
2056 WMA_LOGE("%s: Not enough space.(datalen=%d, n=%zu, hdr=%zu bytes",
2057 __func__, pe_hdr->buf_len, n, sizeof(ev->hdr));
2058 error = 1;
2059 break;
2060 }
2061 /*
2062 * Obtain a pointer to the beginning of the current event.
2063 * data[0] is the beginning of the WMI payload.
2064 */
2065 ev = (wmi_single_phyerr_rx_event *) &bufp[n];
2066
2067 /*
2068 * Sanity check the buffer length of the event against
2069 * what we currently have.
2070 * Since buf_len is 32 bits, we check if it overflows
2071 * a large 32 bit value. It's not 0x7fffffff because
2072 * we increase n by (buf_len + sizeof(hdr)), which would
2073 * in itself cause n to overflow.
2074 * If "int" is 64 bits then this becomes a moot point.
2075 */
2076 if (ev->hdr.buf_len > 0x7f000000) {
2077 WMA_LOGE("%s:buf_len is garbage (0x%x)", __func__,
2078 ev->hdr.buf_len);
2079 error = 1;
2080 break;
2081 }
2082 if (n + ev->hdr.buf_len > pe_hdr->buf_len) {
2083 WMA_LOGE("%s: buf_len exceeds available space n=%zu,"
2084 "buf_len=%d, datalen=%d",
2085 __func__, n, ev->hdr.buf_len, pe_hdr->buf_len);
2086 error = 1;
2087 break;
2088 }
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002089 /*
2090 * If the board id is WMI_HWBD_QCA6174
2091 * then it supports only DFS-2. So, fetch
2092 * phyerror code in order to know the type
2093 * of phyerror.
2094 */
2095 if (wma->hw_bd_id == WMI_HWBD_QCA6174) {
2096 phy_err_code = WMI_UNIFIED_PHYERRCODE_GET(&ev->hdr);
2097 WMA_LOGD("%s: DFS-2 phyerror code = 0x%x",
2098 __func__, phy_err_code);
2099 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002100
2101 /*
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002102 * phy_err_code is set for DFS-2 and phy_err_mask
2103 * is set for DFS-3. Checking both to support
2104 * compatability for older platforms.
2105 * If the phyerror or phyerrmask category matches,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002106 * pass radar events to the dfs pattern matching code.
2107 * Don't pass radar events with no buffer payload.
2108 */
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002109 if (((phy_err_mask & WMI_PHY_ERROR_MASK0_RADAR) ||
2110 (phy_err_mask & WMI_PHY_ERROR_MASK0_FALSE_RADAR_EXT)) ||
2111 (phy_err_code == WMA_DFS2_PHYERROR_CODE ||
2112 phy_err_code == WMA_DFS2_FALSE_RADAR_EXT)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002113 if (ev->hdr.buf_len > 0) {
2114 /* Calling in to the DFS module to process the phyerr */
2115 dfs_process_phyerr(ic, &ev->bufp[0],
2116 ev->hdr.buf_len,
2117 WMI_UNIFIED_RSSI_COMB_GET
2118 (&ev->hdr) & 0xff,
2119 /* Extension RSSI */
2120 WMI_UNIFIED_RSSI_COMB_GET
2121 (&ev->hdr) & 0xff,
2122 ev->hdr.tsf_timestamp,
2123 tsf64, enable_log);
2124 }
2125 }
2126
2127 /*
2128 * Advance the buffer pointer to the next PHY error.
2129 * buflen is the length of this payload, so we need to
2130 * advance past the current header _AND_ the payload.
2131 */
2132 n += sizeof(*ev) + ev->hdr.buf_len;
2133
2134 } /*end while() */
2135 if (error)
2136 return 0;
2137 else
2138 return 1;
2139}
2140
2141/**
2142 * wma_register_dfs_event_handler() - register dfs event handler
2143 * @wma_handle: wma handle
2144 *
2145 * Register appropriate dfs phyerror event handler
2146 * based on phyerror filtering offload is enabled
2147 * or disabled.
2148 *
2149 * Return: none
2150 */
2151void wma_register_dfs_event_handler(tp_wma_handle wma_handle)
2152{
2153 if (NULL == wma_handle) {
2154 WMA_LOGE("%s:wma_handle is NULL", __func__);
2155 return;
2156 }
2157
2158 if (false == wma_handle->dfs_phyerr_filter_offload) {
2159 /*
2160 * Register the wma_unified_phyerr_rx_event_handler
2161 * for filtering offload disabled case to handle
2162 * the DFS phyerrors.
2163 */
2164 WMA_LOGD("%s:Phyerror Filtering offload is Disabled in ini",
2165 __func__);
2166 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Govind Singhd76a5b02016-03-08 15:12:14 +05302167 WMI_PHYERR_EVENTID,
2168 wma_unified_phyerr_rx_event_handler,
2169 WMA_RX_WORK_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002170 WMA_LOGD("%s: WMI_PHYERR_EVENTID event handler registered",
2171 __func__);
2172 } else {
2173 WMA_LOGD("%s:Phyerror Filtering offload is Enabled in ini",
2174 __func__);
2175 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Govind Singhd76a5b02016-03-08 15:12:14 +05302176 WMI_DFS_RADAR_EVENTID,
2177 wma_unified_dfs_radar_rx_event_handler,
2178 WMA_RX_WORK_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002179 WMA_LOGD("%s:WMI_DFS_RADAR_EVENTID event handler registered",
2180 __func__);
2181 }
2182
2183 return;
2184}
2185
2186
2187/**
2188 * wma_unified_dfs_phyerr_filter_offload_enable() - enable dfs phyerr filter
2189 * @wma_handle: wma handle
2190 *
2191 * Send WMI_DFS_PHYERR_FILTER_ENA_CMDID or
2192 * WMI_DFS_PHYERR_FILTER_DIS_CMDID command
2193 * to firmware based on phyerr filtering
2194 * offload status.
2195 *
2196 * Return: 1 success, 0 failure
2197 */
2198int
2199wma_unified_dfs_phyerr_filter_offload_enable(tp_wma_handle wma_handle)
2200{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002201 int ret;
2202
2203 if (NULL == wma_handle) {
2204 WMA_LOGE("%s:wma_handle is NULL", __func__);
2205 return 0;
2206 }
2207
Govind Singhaa64c242016-03-08 11:31:49 +05302208 ret = wmi_unified_dfs_phyerr_filter_offload_en_cmd(wma_handle->wmi_handle,
2209 wma_handle->dfs_phyerr_filter_offload);
2210 if (ret)
2211 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002212
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002213
Govind Singhaa64c242016-03-08 11:31:49 +05302214 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002215}
2216
2217#if !defined(REMOVE_PKT_LOG)
2218/**
2219 * wma_pktlog_wmi_send_cmd() - send pktlog enable/disable command to target
2220 * @handle: wma handle
2221 * @params: pktlog params
2222 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302223 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002224 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302225QDF_STATUS wma_pktlog_wmi_send_cmd(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002226 struct ath_pktlog_wmi_params *params)
2227{
2228 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhaa64c242016-03-08 11:31:49 +05302229 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002230
Govind Singhaa64c242016-03-08 11:31:49 +05302231 ret = wmi_unified_pktlog_wmi_send_cmd(wma_handle->wmi_handle,
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08002232 params->pktlog_event,
2233 params->cmd_id, params->user_triggered);
Govind Singhaa64c242016-03-08 11:31:49 +05302234 if (ret)
2235 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002236
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302237 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002238}
2239#endif /* REMOVE_PKT_LOG */
2240
2241static void wma_send_status_to_suspend_ind(tp_wma_handle wma, bool suspended)
2242{
2243 tSirReadyToSuspendInd *ready_to_suspend;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302244 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002245 cds_msg_t cds_msg;
2246 uint8_t len;
2247
2248 WMA_LOGD("Posting ready to suspend indication to umac");
2249
2250 len = sizeof(tSirReadyToSuspendInd);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302251 ready_to_suspend = (tSirReadyToSuspendInd *) qdf_mem_malloc(len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002252
2253 if (NULL == ready_to_suspend) {
2254 WMA_LOGE("%s: Memory allocation failure", __func__);
2255 return;
2256 }
2257
2258 ready_to_suspend->mesgType = eWNI_SME_READY_TO_SUSPEND_IND;
2259 ready_to_suspend->mesgLen = len;
2260 ready_to_suspend->suspended = suspended;
2261
2262 cds_msg.type = eWNI_SME_READY_TO_SUSPEND_IND;
2263 cds_msg.bodyptr = (void *)ready_to_suspend;
2264 cds_msg.bodyval = 0;
2265
Krunal Soni66c113f2016-12-21 16:46:47 -08002266 status = cds_mq_post_message(QDF_MODULE_ID_SME, &cds_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302267 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002268 WMA_LOGE("Failed to post ready to suspend");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302269 qdf_mem_free(ready_to_suspend);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002270 }
2271}
2272
2273/**
2274 * wma_wow_wake_reason_str() - Converts wow wakeup reason code to text format
2275 * @wake_reason - WOW wake reason
2276 *
2277 * Return: reason code in string format
2278 */
2279static const u8 *wma_wow_wake_reason_str(A_INT32 wake_reason)
2280{
2281 switch (wake_reason) {
2282 case WOW_REASON_UNSPECIFIED:
2283 return "UNSPECIFIED";
2284 case WOW_REASON_NLOD:
2285 return "NLOD";
2286 case WOW_REASON_AP_ASSOC_LOST:
2287 return "AP_ASSOC_LOST";
2288 case WOW_REASON_LOW_RSSI:
2289 return "LOW_RSSI";
2290 case WOW_REASON_DEAUTH_RECVD:
2291 return "DEAUTH_RECVD";
2292 case WOW_REASON_DISASSOC_RECVD:
2293 return "DISASSOC_RECVD";
2294 case WOW_REASON_GTK_HS_ERR:
2295 return "GTK_HS_ERR";
2296 case WOW_REASON_EAP_REQ:
2297 return "EAP_REQ";
2298 case WOW_REASON_FOURWAY_HS_RECV:
2299 return "FOURWAY_HS_RECV";
2300 case WOW_REASON_TIMER_INTR_RECV:
2301 return "TIMER_INTR_RECV";
2302 case WOW_REASON_PATTERN_MATCH_FOUND:
2303 return "PATTERN_MATCH_FOUND";
2304 case WOW_REASON_RECV_MAGIC_PATTERN:
2305 return "RECV_MAGIC_PATTERN";
2306 case WOW_REASON_P2P_DISC:
2307 return "P2P_DISC";
2308#ifdef FEATURE_WLAN_LPHB
2309 case WOW_REASON_WLAN_HB:
2310 return "WLAN_HB";
2311#endif /* FEATURE_WLAN_LPHB */
2312
2313 case WOW_REASON_CSA_EVENT:
2314 return "CSA_EVENT";
2315 case WOW_REASON_PROBE_REQ_WPS_IE_RECV:
2316 return "PROBE_REQ_RECV";
2317 case WOW_REASON_AUTH_REQ_RECV:
2318 return "AUTH_REQ_RECV";
2319 case WOW_REASON_ASSOC_REQ_RECV:
2320 return "ASSOC_REQ_RECV";
2321 case WOW_REASON_HTT_EVENT:
2322 return "WOW_REASON_HTT_EVENT";
2323#ifdef FEATURE_WLAN_RA_FILTERING
2324 case WOW_REASON_RA_MATCH:
2325 return "WOW_REASON_RA_MATCH";
2326#endif /* FEATURE_WLAN_RA_FILTERING */
2327 case WOW_REASON_BEACON_RECV:
2328 return "WOW_REASON_IBSS_BEACON_RECV";
2329#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
2330 case WOW_REASON_HOST_AUTO_SHUTDOWN:
2331 return "WOW_REASON_HOST_AUTO_SHUTDOWN";
2332#endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
2333#ifdef WLAN_FEATURE_ROAM_OFFLOAD
2334 case WOW_REASON_ROAM_HO:
2335 return "WOW_REASON_ROAM_HO";
2336#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
2337#ifdef FEATURE_WLAN_EXTSCAN
2338 case WOW_REASON_EXTSCAN:
2339 return "WOW_REASON_EXTSCAN";
2340#endif
2341 case WOW_REASON_RSSI_BREACH_EVENT:
2342 return "WOW_REASON_RSSI_BREACH_EVENT";
Srinivas Girigowdae80cea92015-11-23 11:33:57 -08002343 case WOW_REASON_NLO_SCAN_COMPLETE:
2344 return "WOW_REASON_NLO_SCAN_COMPLETE";
Naveen Rawatc9f09522016-05-12 14:02:42 -07002345 case WOW_REASON_NAN_EVENT:
2346 return "WOW_REASON_NAN_EVENT";
Selvaraj, Sridhar172cabc2016-07-05 15:19:24 +05302347 case WOW_REASON_OEM_RESPONSE_EVENT:
2348 return "WOW_OEM_RESPONSE_EVENT";
Himanshu Agarwaldd356df2016-07-20 19:04:39 +05302349 case WOW_REASON_ASSOC_RES_RECV:
2350 return "ASSOC_RES_RECV";
2351 case WOW_REASON_REASSOC_REQ_RECV:
2352 return "REASSOC_REQ_RECV";
2353 case WOW_REASON_REASSOC_RES_RECV:
2354 return "REASSOC_RES_RECV";
2355 case WOW_REASON_ACTION_FRAME_RECV:
2356 return "ACTION_FRAME_RECV";
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05302357 case WOW_REASON_BPF_ALLOW:
2358 return "WOW_REASON_BPF_ALLOW";
Rajeev Kumar969d1b12016-12-20 23:53:20 -08002359 case WOW_REASON_NAN_DATA:
2360 return "WOW_REASON_NAN_DATA";
2361 case WOW_REASON_TDLS_CONN_TRACKER_EVENT:
2362 return "WOW_REASON_TDLS_CONN_TRACKER_EVENT";
2363 case WOW_REASON_CRITICAL_LOG:
2364 return "WOW_REASON_CRITICAL_LOG";
2365 case WOW_REASON_P2P_LISTEN_OFFLOAD:
2366 return "WOW_REASON_P2P_LISTEN_OFFLOAD";
2367 case WOW_REASON_NAN_EVENT_WAKE_HOST:
2368 return "WOW_REASON_NAN_EVENT_WAKE_HOST";
2369
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002370 }
2371 return "unknown";
2372}
2373
2374/**
2375 * wma_wow_wake_up_stats_display() - display wow wake up stats
2376 * @wma: Pointer to wma handle
2377 *
2378 * Return: none
2379 */
2380static void wma_wow_wake_up_stats_display(tp_wma_handle wma)
2381{
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05302382 WMA_LOGA("uc %d bc %d v4_mc %d v6_mc %d ra %d ns %d na %d pno_match %d pno_complete %d gscan %d low_rssi %d rssi_breach %d icmp %d icmpv6 %d oem %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002383 wma->wow_ucast_wake_up_count,
2384 wma->wow_bcast_wake_up_count,
2385 wma->wow_ipv4_mcast_wake_up_count,
2386 wma->wow_ipv6_mcast_wake_up_count,
2387 wma->wow_ipv6_mcast_ra_stats,
2388 wma->wow_ipv6_mcast_ns_stats,
2389 wma->wow_ipv6_mcast_na_stats,
2390 wma->wow_pno_match_wake_up_count,
2391 wma->wow_pno_complete_wake_up_count,
2392 wma->wow_gscan_wake_up_count,
2393 wma->wow_low_rssi_wake_up_count,
Selvaraj, Sridhar172cabc2016-07-05 15:19:24 +05302394 wma->wow_rssi_breach_wake_up_count,
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05302395 wma->wow_icmpv4_count,
Himanshu Agarwal4574e282016-08-10 15:22:45 +05302396 wma->wow_icmpv6_count,
Selvaraj, Sridhar172cabc2016-07-05 15:19:24 +05302397 wma->wow_oem_response_wake_up_count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002398
2399 return;
2400}
2401
2402/**
2403 * wma_wow_ipv6_mcast_stats() - ipv6 mcast wake up stats
2404 * @wma: Pointer to wma handle
2405 * @data: Pointer to pattern match data
2406 *
2407 * Return: none
2408 */
2409static void wma_wow_ipv6_mcast_stats(tp_wma_handle wma, uint8_t *data)
2410{
Himanshu Agarwal4574e282016-08-10 15:22:45 +05302411 static const uint8_t ipv6_ether_type[] = {0x86, 0xDD};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002412
Himanshu Agarwal4574e282016-08-10 15:22:45 +05302413 if (!memcmp(ipv6_ether_type, (data + WMA_ETHER_TYPE_OFFSET),
2414 sizeof(ipv6_ether_type))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002415 if (WMA_ICMP_V6_HEADER_TYPE ==
2416 *(data + WMA_ICMP_V6_HEADER_OFFSET)) {
Himanshu Agarwal4574e282016-08-10 15:22:45 +05302417 wma->wow_icmpv6_count++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002418 if (WMA_ICMP_V6_RA_TYPE ==
2419 *(data + WMA_ICMP_V6_TYPE_OFFSET))
2420 wma->wow_ipv6_mcast_ra_stats++;
2421 else if (WMA_ICMP_V6_NS_TYPE ==
2422 *(data + WMA_ICMP_V6_TYPE_OFFSET))
2423 wma->wow_ipv6_mcast_ns_stats++;
2424 else if (WMA_ICMP_V6_NA_TYPE ==
2425 *(data + WMA_ICMP_V6_TYPE_OFFSET))
2426 wma->wow_ipv6_mcast_na_stats++;
2427 else
2428 WMA_LOGA("ICMP V6 type : 0x%x",
2429 *(data + WMA_ICMP_V6_TYPE_OFFSET));
2430 } else {
2431 WMA_LOGA("ICMP_V6 header 0x%x",
2432 *(data + WMA_ICMP_V6_HEADER_OFFSET));
2433 }
2434 } else {
2435 WMA_LOGA("Ethertype x%x:0x%x",
2436 *(data + WMA_ETHER_TYPE_OFFSET),
2437 *(data + WMA_ETHER_TYPE_OFFSET + 1));
2438 }
2439
2440 return;
2441}
2442
2443/**
2444 * wma_wow_wake_up_stats() - maintain wow pattern match wake up stats
2445 * @wma: Pointer to wma handle
2446 * @data: Pointer to pattern match data
2447 * @len: Pattern match data length
2448 * @event: Wake up event
2449 *
2450 * Return: none
2451 */
2452static void wma_wow_wake_up_stats(tp_wma_handle wma, uint8_t *data,
2453 int32_t len, WOW_WAKE_REASON_TYPE event)
2454{
2455 switch (event) {
2456
Dustin Brown75d02342016-08-29 11:23:47 -07002457 case WOW_REASON_BPF_ALLOW:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002458 case WOW_REASON_PATTERN_MATCH_FOUND:
2459 if (WMA_BCAST_MAC_ADDR == *data) {
2460 wma->wow_bcast_wake_up_count++;
Himanshu Agarwal11a08c02016-08-10 15:39:54 +05302461 if (len >= WMA_IPV4_PROTO_GET_MIN_LEN &&
2462 qdf_nbuf_data_is_icmp_pkt(data))
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05302463 wma->wow_icmpv4_count++;
Himanshu Agarwal4574e282016-08-10 15:22:45 +05302464 else if ((len > WMA_ICMP_V6_TYPE_OFFSET) &&
2465 qdf_nbuf_data_is_icmpv6_pkt(data))
2466 wma->wow_icmpv6_count++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002467 } else if (WMA_MCAST_IPV4_MAC_ADDR == *data) {
2468 wma->wow_ipv4_mcast_wake_up_count++;
Himanshu Agarwal11a08c02016-08-10 15:39:54 +05302469 if (len >= WMA_IPV4_PROTO_GET_MIN_LEN &&
2470 WMA_ICMP_PROTOCOL == *(data + WMA_IPV4_PROTOCOL))
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05302471 wma->wow_icmpv4_count++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002472 } else if (WMA_MCAST_IPV6_MAC_ADDR == *data) {
2473 wma->wow_ipv6_mcast_wake_up_count++;
2474 if (len > WMA_ICMP_V6_TYPE_OFFSET)
2475 wma_wow_ipv6_mcast_stats(wma, data);
2476 else
2477 WMA_LOGA("ICMP_V6 data len %d", len);
2478 } else {
2479 wma->wow_ucast_wake_up_count++;
Himanshu Agarwal11a08c02016-08-10 15:39:54 +05302480 if (qdf_nbuf_data_is_ipv4_mcast_pkt(data))
2481 wma->wow_ipv4_mcast_wake_up_count++;
2482 else if (qdf_nbuf_data_is_ipv6_mcast_pkt(data))
2483 wma->wow_ipv6_mcast_wake_up_count++;
2484
2485 if (len >= WMA_IPV4_PROTO_GET_MIN_LEN &&
2486 qdf_nbuf_data_is_icmp_pkt(data))
2487 wma->wow_icmpv4_count++;
2488 else if (len > WMA_ICMP_V6_TYPE_OFFSET &&
Himanshu Agarwal4574e282016-08-10 15:22:45 +05302489 qdf_nbuf_data_is_icmpv6_pkt(data))
2490 wma->wow_icmpv6_count++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002491 }
2492 break;
2493
2494 case WOW_REASON_RA_MATCH:
Himanshu Agarwal4574e282016-08-10 15:22:45 +05302495 wma->wow_icmpv6_count++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002496 wma->wow_ipv6_mcast_ra_stats++;
Himanshu Agarwal4574e282016-08-10 15:22:45 +05302497 wma->wow_ipv6_mcast_wake_up_count++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002498 break;
2499
2500 case WOW_REASON_NLOD:
2501 wma->wow_pno_match_wake_up_count++;
2502 break;
2503
2504 case WOW_REASON_NLO_SCAN_COMPLETE:
2505 wma->wow_pno_complete_wake_up_count++;
2506 break;
2507
2508 case WOW_REASON_LOW_RSSI:
2509 wma->wow_low_rssi_wake_up_count++;
2510 break;
2511
2512 case WOW_REASON_EXTSCAN:
2513 wma->wow_gscan_wake_up_count++;
2514 break;
2515
2516 case WOW_REASON_RSSI_BREACH_EVENT:
2517 wma->wow_rssi_breach_wake_up_count++;
2518 break;
Selvaraj, Sridhar172cabc2016-07-05 15:19:24 +05302519 case WOW_REASON_OEM_RESPONSE_EVENT:
2520 wma->wow_oem_response_wake_up_count++;
2521 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002522
2523 default:
2524 WMA_LOGE("Unknown wake up reason");
2525 break;
2526 }
2527
2528 wma_wow_wake_up_stats_display(wma);
2529 return;
2530}
2531
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07002532#ifdef FEATURE_WLAN_EXTSCAN
2533/**
2534 * wma_extscan_get_eventid_from_tlvtag() - map tlv tag to corresponding event id
2535 * @tag: WMI TLV tag
2536 *
2537 * Return:
2538 * 0 if TLV tag is invalid
2539 * else return corresponding WMI event id
2540 */
2541static int wma_extscan_get_eventid_from_tlvtag(uint32_t tag)
2542{
2543 uint32_t event_id;
2544
2545 switch (tag) {
2546 case WMITLV_TAG_STRUC_wmi_extscan_start_stop_event_fixed_param:
2547 event_id = WMI_EXTSCAN_START_STOP_EVENTID;
2548 break;
2549
2550 case WMITLV_TAG_STRUC_wmi_extscan_operation_event_fixed_param:
2551 event_id = WMI_EXTSCAN_OPERATION_EVENTID;
2552 break;
2553
2554 case WMITLV_TAG_STRUC_wmi_extscan_table_usage_event_fixed_param:
2555 event_id = WMI_EXTSCAN_TABLE_USAGE_EVENTID;
2556 break;
2557
2558 case WMITLV_TAG_STRUC_wmi_extscan_cached_results_event_fixed_param:
2559 event_id = WMI_EXTSCAN_CACHED_RESULTS_EVENTID;
2560 break;
2561
2562 case WMITLV_TAG_STRUC_wmi_extscan_wlan_change_results_event_fixed_param:
2563 event_id = WMI_EXTSCAN_WLAN_CHANGE_RESULTS_EVENTID;
2564 break;
2565
2566 case WMITLV_TAG_STRUC_wmi_extscan_hotlist_match_event_fixed_param:
2567 event_id = WMI_EXTSCAN_HOTLIST_MATCH_EVENTID;
2568 break;
2569
2570 case WMITLV_TAG_STRUC_wmi_extscan_capabilities_event_fixed_param:
2571 event_id = WMI_EXTSCAN_CAPABILITIES_EVENTID;
2572 break;
2573
2574 case WMITLV_TAG_STRUC_wmi_extscan_hotlist_ssid_match_event_fixed_param:
2575 event_id = WMI_EXTSCAN_HOTLIST_SSID_MATCH_EVENTID;
2576 break;
2577
2578 default:
2579 event_id = 0;
2580 WMA_LOGE("%s: Unknown tag: %d", __func__, tag);
2581 break;
2582 }
2583
2584 WMA_LOGI("%s: For tag %d WMI event 0x%x", __func__, tag, event_id);
2585 return event_id;
2586}
2587#else
2588static int wma_extscan_get_eventid_from_tlvtag(uint32_t tag)
2589{
2590 return 0;
2591}
2592#endif
2593
2594/**
2595 * wow_get_wmi_eventid() - map reason or tlv tag to corresponding event id
2596 * @tag: WMI TLV tag
2597 * @reason: WOW reason
2598 *
2599 * WOW reason type is primarily used to find the ID. If there could be
2600 * multiple events that can be sent as a WOW event with same reason
2601 * then tlv tag is used to identify the corresponding event.
2602 *
2603 * Return:
2604 * 0 if TLV tag/reason is invalid
2605 * else return corresponding WMI event id
2606 */
2607static int wow_get_wmi_eventid(int32_t reason, uint32_t tag)
2608{
2609 uint32_t event_id;
2610
2611 switch (reason) {
2612 case WOW_REASON_NLO_SCAN_COMPLETE:
2613 event_id = WMI_NLO_SCAN_COMPLETE_EVENTID;
2614 break;
2615 case WOW_REASON_CSA_EVENT:
2616 event_id = WMI_CSA_HANDLING_EVENTID;
2617 break;
2618 case WOW_REASON_LOW_RSSI:
2619 event_id = WMI_ROAM_EVENTID;
2620 break;
2621 case WOW_REASON_CLIENT_KICKOUT_EVENT:
2622 event_id = WMI_PEER_STA_KICKOUT_EVENTID;
2623 break;
2624 case WOW_REASON_EXTSCAN:
2625 event_id = wma_extscan_get_eventid_from_tlvtag(tag);
2626 break;
2627 case WOW_REASON_RSSI_BREACH_EVENT:
2628 event_id = WMI_RSSI_BREACH_EVENTID;
2629 break;
2630 case WOW_REASON_NAN_EVENT:
2631 event_id = WMI_NAN_EVENTID;
2632 break;
Naveen Rawat17dccbe2016-08-23 17:09:04 -07002633 case WOW_REASON_NAN_DATA:
2634 event_id = wma_ndp_get_eventid_from_tlvtag(tag);
2635 break;
Selvaraj, Sridhar251761a2016-06-25 16:05:15 +05302636 case WOW_REASON_TDLS_CONN_TRACKER_EVENT:
2637 event_id = WOW_TDLS_CONN_TRACKER_EVENT;
2638 break;
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07002639 default:
2640 WMA_LOGD(FL("Unexpected WOW reason : %s(%d)"),
2641 wma_wow_wake_reason_str(reason), reason);
2642 event_id = 0;
2643 break;
2644 }
2645
2646 return event_id;
2647}
2648
2649/**
2650 * tlv_check_required() - tells whether to check the wow packet buffer
2651 * for proper TLV structure.
2652 * @reason: WOW reason
2653 *
2654 * In most cases, wow wake up event carries the actual event buffer in
2655 * wow_packet_buffer with some exceptions. This function is used to
2656 * determine when to check for the TLVs in wow_packet_buffer.
2657 *
2658 * Return: true if check is required and false otherwise.
2659 */
2660static bool tlv_check_required(int32_t reason)
2661{
2662 switch (reason) {
Krishna Kumaar Natarajane1a59832016-09-07 12:19:24 -07002663 case WOW_REASON_NLO_SCAN_COMPLETE:
2664 case WOW_REASON_CSA_EVENT:
2665 case WOW_REASON_LOW_RSSI:
2666 case WOW_REASON_CLIENT_KICKOUT_EVENT:
2667 case WOW_REASON_EXTSCAN:
2668 case WOW_REASON_RSSI_BREACH_EVENT:
2669 case WOW_REASON_NAN_EVENT:
2670 case WOW_REASON_NAN_DATA:
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07002671 return true;
Krishna Kumaar Natarajane1a59832016-09-07 12:19:24 -07002672 default:
2673 return false;
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07002674 }
2675}
2676
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002677/**
Himanshu Agarwal82de9042016-07-20 18:11:03 +05302678 * wma_pkt_proto_subtype_to_string() - to convert proto subtype
2679 * of data packet to string.
2680 * @proto_subtype: proto subtype for data packet
2681 *
2682 * This function returns the string for the proto subtype of
2683 * data packet.
2684 *
2685 * Return: string for proto subtype for data packet
2686 */
Jeff Johnsonc4b47a92016-10-07 12:34:41 -07002687static const char *
Himanshu Agarwal82de9042016-07-20 18:11:03 +05302688wma_pkt_proto_subtype_to_string(enum qdf_proto_subtype proto_subtype)
2689{
2690 switch (proto_subtype) {
2691 case QDF_PROTO_EAPOL_M1:
2692 return "EAPOL M1";
2693 case QDF_PROTO_EAPOL_M2:
2694 return "EAPOL M2";
2695 case QDF_PROTO_EAPOL_M3:
2696 return "EAPOL M3";
2697 case QDF_PROTO_EAPOL_M4:
2698 return "EAPOL M4";
2699 case QDF_PROTO_DHCP_DISCOVER:
2700 return "DHCP DISCOVER";
2701 case QDF_PROTO_DHCP_REQUEST:
2702 return "DHCP REQUEST";
2703 case QDF_PROTO_DHCP_OFFER:
2704 return "DHCP OFFER";
2705 case QDF_PROTO_DHCP_ACK:
2706 return "DHCP ACK";
2707 case QDF_PROTO_DHCP_NACK:
2708 return "DHCP NACK";
2709 case QDF_PROTO_DHCP_RELEASE:
2710 return "DHCP RELEASE";
2711 case QDF_PROTO_DHCP_INFORM:
2712 return "DHCP INFORM";
2713 case QDF_PROTO_DHCP_DECLINE:
2714 return "DHCP DECLINE";
2715 case QDF_PROTO_ARP_REQ:
2716 return "ARP REQUEST";
2717 case QDF_PROTO_ARP_RES:
2718 return "ARP RESPONSE";
2719 case QDF_PROTO_ICMP_REQ:
2720 return "ICMP REQUEST";
2721 case QDF_PROTO_ICMP_RES:
2722 return "ICMP RESPONSE";
2723 case QDF_PROTO_ICMPV6_REQ:
2724 return "ICMPV6 REQUEST";
2725 case QDF_PROTO_ICMPV6_RES:
2726 return "ICMPV6 RESPONSE";
2727 case QDF_PROTO_IPV4_UDP:
2728 return "IPV4 UDP Packet";
2729 case QDF_PROTO_IPV4_TCP:
2730 return "IPV4 TCP Packet";
2731 case QDF_PROTO_IPV6_UDP:
2732 return "IPV6 UDP Packet";
2733 case QDF_PROTO_IPV6_TCP:
2734 return "IPV6 TCP Packet";
2735 default:
2736 return "Invalid Packet";
2737 }
2738}
2739
2740/**
2741 * wma_wow_get_pkt_proto_subtype() - get the proto subtype
2742 * of the packet.
2743 * @data: Pointer to data buffer
2744 * @len: length of the data buffer
2745 *
2746 * This function gives the proto subtype of the packet.
2747 *
2748 * Return: proto subtype of the packet.
2749 */
2750static enum qdf_proto_subtype
2751wma_wow_get_pkt_proto_subtype(uint8_t *data,
2752 uint32_t len)
2753{
Himanshu Agarwalec51a5a2016-07-20 19:47:26 +05302754 uint16_t ether_type = (uint16_t)(*(uint16_t *)(data +
2755 QDF_NBUF_TRAC_ETH_TYPE_OFFSET));
2756
Himanshu Agarwal0c66b1c2016-10-21 15:07:44 +05302757 WMA_LOGD("Ether Type: 0x%04x",
Himanshu Agarwalec51a5a2016-07-20 19:47:26 +05302758 ani_cpu_to_be16(ether_type));
2759
2760 if (QDF_NBUF_TRAC_EAPOL_ETH_TYPE ==
2761 ani_cpu_to_be16(ether_type)) {
2762 if (len >= WMA_EAPOL_SUBTYPE_GET_MIN_LEN)
2763 return qdf_nbuf_data_get_eapol_subtype(data);
Himanshu Agarwal0c66b1c2016-10-21 15:07:44 +05302764 WMA_LOGD("EAPOL Packet");
Himanshu Agarwalec51a5a2016-07-20 19:47:26 +05302765 return QDF_PROTO_INVALID;
2766 } else if (QDF_NBUF_TRAC_ARP_ETH_TYPE ==
2767 ani_cpu_to_be16(ether_type)) {
2768 if (len >= WMA_ARP_SUBTYPE_GET_MIN_LEN)
2769 return qdf_nbuf_data_get_arp_subtype(data);
Himanshu Agarwal0c66b1c2016-10-21 15:07:44 +05302770 WMA_LOGD("ARP Packet");
Himanshu Agarwalec51a5a2016-07-20 19:47:26 +05302771 return QDF_PROTO_INVALID;
2772 } else if (QDF_NBUF_TRAC_IPV4_ETH_TYPE ==
2773 ani_cpu_to_be16(ether_type)) {
2774 if (len >= WMA_IPV4_PROTO_GET_MIN_LEN) {
2775 uint8_t proto_type;
2776
2777 proto_type = qdf_nbuf_data_get_ipv4_proto(data);
Himanshu Agarwal0c66b1c2016-10-21 15:07:44 +05302778 WMA_LOGD("IPV4_proto_type: %u", proto_type);
Himanshu Agarwalec51a5a2016-07-20 19:47:26 +05302779 if (proto_type == QDF_NBUF_TRAC_ICMP_TYPE) {
2780 if (len >= WMA_ICMP_SUBTYPE_GET_MIN_LEN)
2781 return qdf_nbuf_data_get_icmp_subtype(
2782 data);
Himanshu Agarwal0c66b1c2016-10-21 15:07:44 +05302783 WMA_LOGD("ICMP Packet");
Himanshu Agarwalec51a5a2016-07-20 19:47:26 +05302784 return QDF_PROTO_INVALID;
2785 } else if (proto_type == QDF_NBUF_TRAC_UDP_TYPE) {
2786 if (len >= WMA_IS_DHCP_GET_MIN_LEN) {
2787 if (qdf_nbuf_data_is_ipv4_dhcp_pkt(data)) {
2788 if (len >=
2789 WMA_DHCP_SUBTYPE_GET_MIN_LEN)
2790 return qdf_nbuf_data_get_dhcp_subtype(data);
Himanshu Agarwal0c66b1c2016-10-21 15:07:44 +05302791 WMA_LOGD("DHCP Packet");
Himanshu Agarwalec51a5a2016-07-20 19:47:26 +05302792 return QDF_PROTO_INVALID;
2793 }
2794 }
2795 return QDF_PROTO_IPV4_UDP;
2796 } else if (proto_type == QDF_NBUF_TRAC_TCP_TYPE) {
2797 return QDF_PROTO_IPV4_TCP;
2798 }
Himanshu Agarwal82de9042016-07-20 18:11:03 +05302799 }
Himanshu Agarwal0c66b1c2016-10-21 15:07:44 +05302800 WMA_LOGD("IPV4 Packet");
Himanshu Agarwalec51a5a2016-07-20 19:47:26 +05302801 return QDF_PROTO_INVALID;
2802 } else if (QDF_NBUF_TRAC_IPV6_ETH_TYPE ==
2803 ani_cpu_to_be16(ether_type)) {
2804 if (len >= WMA_IPV6_PROTO_GET_MIN_LEN) {
2805 uint8_t proto_type;
2806
2807 proto_type = qdf_nbuf_data_get_ipv6_proto(data);
Himanshu Agarwal0c66b1c2016-10-21 15:07:44 +05302808 WMA_LOGD("IPV6_proto_type: %u", proto_type);
Himanshu Agarwalec51a5a2016-07-20 19:47:26 +05302809 if (proto_type == QDF_NBUF_TRAC_ICMPV6_TYPE) {
2810 if (len >= WMA_ICMPV6_SUBTYPE_GET_MIN_LEN)
2811 return qdf_nbuf_data_get_icmpv6_subtype(
2812 data);
Himanshu Agarwal0c66b1c2016-10-21 15:07:44 +05302813 WMA_LOGD("ICMPV6 Packet");
Himanshu Agarwalec51a5a2016-07-20 19:47:26 +05302814 return QDF_PROTO_INVALID;
2815 } else if (proto_type == QDF_NBUF_TRAC_UDP_TYPE) {
2816 return QDF_PROTO_IPV6_UDP;
2817 } else if (proto_type == QDF_NBUF_TRAC_TCP_TYPE) {
2818 return QDF_PROTO_IPV6_TCP;
2819 }
Himanshu Agarwal82de9042016-07-20 18:11:03 +05302820 }
Himanshu Agarwal0c66b1c2016-10-21 15:07:44 +05302821 WMA_LOGD("IPV6 Packet");
Himanshu Agarwalec51a5a2016-07-20 19:47:26 +05302822 return QDF_PROTO_INVALID;
Himanshu Agarwal82de9042016-07-20 18:11:03 +05302823 }
2824
2825 return QDF_PROTO_INVALID;
2826}
2827
2828/**
2829 * wma_wow_parse_data_pkt_buffer() - API to parse data buffer for data
2830 * packet that resulted in WOW wakeup.
2831 * @data: Pointer to data buffer
2832 * @buf_len: data buffer length
2833 *
2834 * This function parses the data buffer received (first few bytes of
2835 * skb->data) to get informaton like src mac addr, dst mac addr, packet
2836 * len, seq_num, etc.
2837 *
2838 * Return: void
2839 */
2840static void wma_wow_parse_data_pkt_buffer(uint8_t *data,
2841 uint32_t buf_len)
2842{
2843 enum qdf_proto_subtype proto_subtype;
2844 uint16_t pkt_len, key_len, seq_num;
Himanshu Agarwalec51a5a2016-07-20 19:47:26 +05302845 uint16_t src_port, dst_port;
Himanshu Agarwal82de9042016-07-20 18:11:03 +05302846 uint32_t transaction_id, tcp_seq_num;
2847
Himanshu Agarwalf9515002016-07-20 19:09:10 +05302848 WMA_LOGD("wow_buf_pkt_len: %u", buf_len);
Himanshu Agarwalec51a5a2016-07-20 19:47:26 +05302849 if (buf_len >= QDF_NBUF_TRAC_IPV4_OFFSET)
Himanshu Agarwal0c66b1c2016-10-21 15:07:44 +05302850 WMA_LOGD("Src_mac: " MAC_ADDRESS_STR " Dst_mac: " MAC_ADDRESS_STR,
Rakesh Sunki88d9c5a2016-08-25 12:48:12 -07002851 MAC_ADDR_ARRAY(data + QDF_NBUF_SRC_MAC_OFFSET),
2852 MAC_ADDR_ARRAY(data + QDF_NBUF_DEST_MAC_OFFSET));
Himanshu Agarwal82de9042016-07-20 18:11:03 +05302853 else
2854 goto end;
2855
2856 proto_subtype = wma_wow_get_pkt_proto_subtype(data, buf_len);
2857 switch (proto_subtype) {
2858 case QDF_PROTO_EAPOL_M1:
2859 case QDF_PROTO_EAPOL_M2:
2860 case QDF_PROTO_EAPOL_M3:
2861 case QDF_PROTO_EAPOL_M4:
Himanshu Agarwal0c66b1c2016-10-21 15:07:44 +05302862 WMA_LOGD("WOW Wakeup: %s rcvd",
Himanshu Agarwal82de9042016-07-20 18:11:03 +05302863 wma_pkt_proto_subtype_to_string(proto_subtype));
2864 if (buf_len >= WMA_EAPOL_INFO_GET_MIN_LEN) {
2865 pkt_len = (uint16_t)(*(uint16_t *)(data +
2866 EAPOL_PKT_LEN_OFFSET));
2867 key_len = (uint16_t)(*(uint16_t *)(data +
2868 EAPOL_KEY_LEN_OFFSET));
Himanshu Agarwal0c66b1c2016-10-21 15:07:44 +05302869 WMA_LOGD("Pkt_len: %u, Key_len: %u",
Himanshu Agarwal82de9042016-07-20 18:11:03 +05302870 ani_cpu_to_be16(pkt_len),
2871 ani_cpu_to_be16(key_len));
2872 }
2873 break;
2874
2875 case QDF_PROTO_DHCP_DISCOVER:
2876 case QDF_PROTO_DHCP_REQUEST:
2877 case QDF_PROTO_DHCP_OFFER:
2878 case QDF_PROTO_DHCP_ACK:
2879 case QDF_PROTO_DHCP_NACK:
2880 case QDF_PROTO_DHCP_RELEASE:
2881 case QDF_PROTO_DHCP_INFORM:
2882 case QDF_PROTO_DHCP_DECLINE:
Himanshu Agarwal0c66b1c2016-10-21 15:07:44 +05302883 WMA_LOGD("WOW Wakeup: %s rcvd",
Himanshu Agarwal82de9042016-07-20 18:11:03 +05302884 wma_pkt_proto_subtype_to_string(proto_subtype));
2885 if (buf_len >= WMA_DHCP_INFO_GET_MIN_LEN) {
2886 pkt_len = (uint16_t)(*(uint16_t *)(data +
2887 DHCP_PKT_LEN_OFFSET));
2888 transaction_id = (uint32_t)(*(uint32_t *)(data +
2889 DHCP_TRANSACTION_ID_OFFSET));
Himanshu Agarwal0c66b1c2016-10-21 15:07:44 +05302890 WMA_LOGD("Pkt_len: %u, Transaction_id: %u",
Himanshu Agarwal82de9042016-07-20 18:11:03 +05302891 ani_cpu_to_be16(pkt_len),
2892 ani_cpu_to_be16(transaction_id));
2893 }
2894 break;
2895
2896 case QDF_PROTO_ARP_REQ:
2897 case QDF_PROTO_ARP_RES:
Himanshu Agarwal0c66b1c2016-10-21 15:07:44 +05302898 WMA_LOGD("WOW Wakeup: %s rcvd",
Himanshu Agarwal82de9042016-07-20 18:11:03 +05302899 wma_pkt_proto_subtype_to_string(proto_subtype));
2900 break;
2901
2902 case QDF_PROTO_ICMP_REQ:
2903 case QDF_PROTO_ICMP_RES:
Himanshu Agarwal0c66b1c2016-10-21 15:07:44 +05302904 WMA_LOGD("WOW Wakeup: %s rcvd",
Himanshu Agarwal82de9042016-07-20 18:11:03 +05302905 wma_pkt_proto_subtype_to_string(proto_subtype));
2906 if (buf_len >= WMA_IPV4_PKT_INFO_GET_MIN_LEN) {
2907 pkt_len = (uint16_t)(*(uint16_t *)(data +
2908 IPV4_PKT_LEN_OFFSET));
2909 seq_num = (uint16_t)(*(uint16_t *)(data +
2910 ICMP_SEQ_NUM_OFFSET));
Himanshu Agarwal0c66b1c2016-10-21 15:07:44 +05302911 WMA_LOGD("Pkt_len: %u, Seq_num: %u",
Himanshu Agarwal82de9042016-07-20 18:11:03 +05302912 ani_cpu_to_be16(pkt_len),
2913 ani_cpu_to_be16(seq_num));
2914 }
2915 break;
2916
2917 case QDF_PROTO_ICMPV6_REQ:
2918 case QDF_PROTO_ICMPV6_RES:
Himanshu Agarwal0c66b1c2016-10-21 15:07:44 +05302919 WMA_LOGD("WOW Wakeup: %s rcvd",
Himanshu Agarwal82de9042016-07-20 18:11:03 +05302920 wma_pkt_proto_subtype_to_string(proto_subtype));
2921 if (buf_len >= WMA_IPV6_PKT_INFO_GET_MIN_LEN) {
2922 pkt_len = (uint16_t)(*(uint16_t *)(data +
2923 IPV6_PKT_LEN_OFFSET));
2924 seq_num = (uint16_t)(*(uint16_t *)(data +
2925 ICMPV6_SEQ_NUM_OFFSET));
Himanshu Agarwal0c66b1c2016-10-21 15:07:44 +05302926 WMA_LOGD("Pkt_len: %u, Seq_num: %u",
Himanshu Agarwal82de9042016-07-20 18:11:03 +05302927 ani_cpu_to_be16(pkt_len),
2928 ani_cpu_to_be16(seq_num));
2929 }
2930 break;
2931
2932 case QDF_PROTO_IPV4_UDP:
2933 case QDF_PROTO_IPV4_TCP:
Himanshu Agarwal0c66b1c2016-10-21 15:07:44 +05302934 WMA_LOGD("WOW Wakeup: %s rcvd",
Himanshu Agarwal82de9042016-07-20 18:11:03 +05302935 wma_pkt_proto_subtype_to_string(proto_subtype));
2936 if (buf_len >= WMA_IPV4_PKT_INFO_GET_MIN_LEN) {
2937 pkt_len = (uint16_t)(*(uint16_t *)(data +
2938 IPV4_PKT_LEN_OFFSET));
Himanshu Agarwalec51a5a2016-07-20 19:47:26 +05302939 src_port = (uint16_t)(*(uint16_t *)(data +
2940 IPV4_SRC_PORT_OFFSET));
2941 dst_port = (uint16_t)(*(uint16_t *)(data +
2942 IPV4_DST_PORT_OFFSET));
Himanshu Agarwal0c66b1c2016-10-21 15:07:44 +05302943 WMA_LOGD("Pkt_len: %u",
Himanshu Agarwal82de9042016-07-20 18:11:03 +05302944 ani_cpu_to_be16(pkt_len));
Himanshu Agarwal0c66b1c2016-10-21 15:07:44 +05302945 WMA_LOGD("src_port: %u, dst_port: %u",
Himanshu Agarwalec51a5a2016-07-20 19:47:26 +05302946 ani_cpu_to_be16(src_port),
2947 ani_cpu_to_be16(dst_port));
Himanshu Agarwal82de9042016-07-20 18:11:03 +05302948 if (proto_subtype == QDF_PROTO_IPV4_TCP) {
2949 tcp_seq_num = (uint32_t)(*(uint32_t *)(data +
2950 IPV4_TCP_SEQ_NUM_OFFSET));
Himanshu Agarwal0c66b1c2016-10-21 15:07:44 +05302951 WMA_LOGD("TCP_seq_num: %u",
Himanshu Agarwal82de9042016-07-20 18:11:03 +05302952 ani_cpu_to_be16(tcp_seq_num));
2953 }
2954 }
2955 break;
2956
2957 case QDF_PROTO_IPV6_UDP:
2958 case QDF_PROTO_IPV6_TCP:
Himanshu Agarwal0c66b1c2016-10-21 15:07:44 +05302959 WMA_LOGD("WOW Wakeup: %s rcvd",
Himanshu Agarwal82de9042016-07-20 18:11:03 +05302960 wma_pkt_proto_subtype_to_string(proto_subtype));
2961 if (buf_len >= WMA_IPV6_PKT_INFO_GET_MIN_LEN) {
2962 pkt_len = (uint16_t)(*(uint16_t *)(data +
2963 IPV6_PKT_LEN_OFFSET));
Himanshu Agarwalec51a5a2016-07-20 19:47:26 +05302964 src_port = (uint16_t)(*(uint16_t *)(data +
2965 IPV6_SRC_PORT_OFFSET));
2966 dst_port = (uint16_t)(*(uint16_t *)(data +
2967 IPV6_DST_PORT_OFFSET));
Himanshu Agarwal0c66b1c2016-10-21 15:07:44 +05302968 WMA_LOGD("Pkt_len: %u",
Himanshu Agarwal82de9042016-07-20 18:11:03 +05302969 ani_cpu_to_be16(pkt_len));
Himanshu Agarwal0c66b1c2016-10-21 15:07:44 +05302970 WMA_LOGD("src_port: %u, dst_port: %u",
Himanshu Agarwalec51a5a2016-07-20 19:47:26 +05302971 ani_cpu_to_be16(src_port),
2972 ani_cpu_to_be16(dst_port));
Himanshu Agarwal82de9042016-07-20 18:11:03 +05302973 if (proto_subtype == QDF_PROTO_IPV6_TCP) {
2974 tcp_seq_num = (uint32_t)(*(uint32_t *)(data +
2975 IPV6_TCP_SEQ_NUM_OFFSET));
Himanshu Agarwal0c66b1c2016-10-21 15:07:44 +05302976 WMA_LOGD("TCP_seq_num: %u",
Himanshu Agarwal82de9042016-07-20 18:11:03 +05302977 ani_cpu_to_be16(tcp_seq_num));
2978 }
2979 }
2980 break;
2981
2982 default:
2983end:
Rajeev Kumar6f16cee2016-09-09 14:45:36 -07002984 WMA_LOGD("wow_buf_pkt_len: %u", buf_len);
Himanshu Agarwal82de9042016-07-20 18:11:03 +05302985 break;
2986 }
2987}
2988
2989/**
Himanshu Agarwaldd356df2016-07-20 19:04:39 +05302990 * wma_wow_dump_mgmt_buffer() - API to parse data buffer for mgmt.
2991 * packet that resulted in WOW wakeup.
2992 * @wow_packet_buffer: Pointer to data buffer
2993 * @buf_len: length of data buffer
2994 *
2995 * This function parses the data buffer received (802.11 header)
2996 * to get informaton like src mac addr, dst mac addr, seq_num,
2997 * frag_num, etc.
2998 *
2999 * Return: void
3000 */
3001static void wma_wow_dump_mgmt_buffer(uint8_t *wow_packet_buffer,
3002 uint32_t buf_len)
3003{
3004 struct ieee80211_frame_addr4 *wh;
3005
Himanshu Agarwalf9515002016-07-20 19:09:10 +05303006 WMA_LOGD("wow_buf_pkt_len: %u", buf_len);
Himanshu Agarwaldd356df2016-07-20 19:04:39 +05303007 wh = (struct ieee80211_frame_addr4 *)
3008 (wow_packet_buffer + 4);
3009 if (buf_len >= sizeof(struct ieee80211_frame)) {
3010 uint8_t to_from_ds, frag_num;
3011 uint32_t seq_num;
3012
3013 WMA_LOGE("RA: " MAC_ADDRESS_STR " TA: " MAC_ADDRESS_STR,
3014 MAC_ADDR_ARRAY(wh->i_addr1),
3015 MAC_ADDR_ARRAY(wh->i_addr2));
3016
Himanshu Agarwalf9515002016-07-20 19:09:10 +05303017 WMA_LOGE("TO_DS: %u, FROM_DS: %u",
Himanshu Agarwaldd356df2016-07-20 19:04:39 +05303018 wh->i_fc[1] & IEEE80211_FC1_DIR_TODS,
3019 wh->i_fc[1] & IEEE80211_FC1_DIR_FROMDS);
3020
3021 to_from_ds = wh->i_fc[1] & IEEE80211_FC1_DIR_DSTODS;
3022
3023 switch (to_from_ds) {
3024 case IEEE80211_NO_DS:
3025 WMA_LOGE("BSSID: " MAC_ADDRESS_STR,
3026 MAC_ADDR_ARRAY(wh->i_addr3));
3027 break;
3028 case IEEE80211_TO_DS:
3029 WMA_LOGE("DA: " MAC_ADDRESS_STR,
3030 MAC_ADDR_ARRAY(wh->i_addr3));
3031 break;
3032 case IEEE80211_FROM_DS:
3033 WMA_LOGE("SA: " MAC_ADDRESS_STR,
3034 MAC_ADDR_ARRAY(wh->i_addr3));
3035 break;
3036 case IEEE80211_DS_TO_DS:
3037 if (buf_len >= sizeof(struct ieee80211_frame_addr4))
3038 WMA_LOGE("DA: " MAC_ADDRESS_STR " SA: "
3039 MAC_ADDRESS_STR,
3040 MAC_ADDR_ARRAY(wh->i_addr3),
3041 MAC_ADDR_ARRAY(wh->i_addr4));
3042 break;
3043 }
3044
3045 seq_num = (((*(uint16_t *)wh->i_seq) &
3046 IEEE80211_SEQ_SEQ_MASK) >>
3047 IEEE80211_SEQ_SEQ_SHIFT);
3048 frag_num = (((*(uint16_t *)wh->i_seq) &
3049 IEEE80211_SEQ_FRAG_MASK) >>
3050 IEEE80211_SEQ_FRAG_SHIFT);
3051
Himanshu Agarwalf9515002016-07-20 19:09:10 +05303052 WMA_LOGE("SEQ_NUM: %u, FRAG_NUM: %u",
Himanshu Agarwaldd356df2016-07-20 19:04:39 +05303053 seq_num, frag_num);
3054 } else {
3055 WMA_LOGE("Insufficient buffer length for mgmt. packet");
3056 }
3057}
3058
3059/**
3060 * wma_wow_get_wakelock_duration() - return the wakelock duration
3061 * for some mgmt packets received.
3062 * @wake_reason: wow wakeup reason
3063 *
3064 * This function returns the wakelock duration for some mgmt packets
3065 * received while in wow suspend.
3066 *
3067 * Return: wakelock duration
3068 */
3069static uint32_t wma_wow_get_wakelock_duration(int wake_reason)
3070{
3071 uint32_t wake_lock_duration = 0;
3072
3073 switch (wake_reason) {
3074 case WOW_REASON_AUTH_REQ_RECV:
3075 wake_lock_duration = WMA_AUTH_REQ_RECV_WAKE_LOCK_TIMEOUT;
3076 break;
3077 case WOW_REASON_ASSOC_REQ_RECV:
3078 wake_lock_duration = WMA_ASSOC_REQ_RECV_WAKE_LOCK_DURATION;
3079 break;
3080 case WOW_REASON_DEAUTH_RECVD:
3081 wake_lock_duration = WMA_DEAUTH_RECV_WAKE_LOCK_DURATION;
3082 break;
3083 case WOW_REASON_DISASSOC_RECVD:
3084 wake_lock_duration = WMA_DISASSOC_RECV_WAKE_LOCK_DURATION;
3085 break;
3086 default:
3087 break;
3088 }
3089
3090 return wake_lock_duration;
3091}
3092
3093/**
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05303094 * wma_wow_ap_lost_helper() - helper function to handle WOW_REASON_AP_ASSOC_LOST
3095 * reason code and retrieve RSSI from the event.
3096 * @wma: Pointer to wma handle
3097 * @param: WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs buffer pointer
3098 *
3099 * Return: none
3100 */
3101static void wma_wow_ap_lost_helper(tp_wma_handle wma, void *param)
3102{
3103 WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *param_buf;
3104 WOW_EVENT_INFO_fixed_param *wake_info;
3105 WMI_ROAM_EVENTID_param_tlvs event_param;
3106 wmi_roam_event_fixed_param *roam_event;
3107 u_int32_t wow_buf_pkt_len = 0;
3108
3109 param_buf = (WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *) param;
3110 wake_info = param_buf->fixed_param;
3111 WMA_LOGA("%s: Beacon miss indication on vdev %d",
3112 __func__, wake_info->vdev_id);
3113
3114 if (NULL == param_buf->wow_packet_buffer) {
3115 WMA_LOGE("%s: invalid wow packet buffer", __func__);
3116 goto exit_handler;
3117 }
3118
3119 qdf_mem_copy((u_int8_t *) &wow_buf_pkt_len,
3120 param_buf->wow_packet_buffer, 4);
3121 WMA_LOGD("wow_packet_buffer dump");
3122 qdf_trace_hex_dump(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_DEBUG,
3123 param_buf->wow_packet_buffer, wow_buf_pkt_len);
3124 if (wow_buf_pkt_len >= sizeof(event_param)) {
3125 roam_event = (wmi_roam_event_fixed_param *)
3126 (param_buf->wow_packet_buffer + 4);
3127 wma_beacon_miss_handler(wma, wake_info->vdev_id,
3128 roam_event->rssi);
3129 return;
3130 }
3131
3132exit_handler:
3133 /* in the case that no RSSI is available from the event */
3134 WMA_LOGE("%s: rssi is not available from wow_packet_buffer", __func__);
3135 wma_beacon_miss_handler(wma, wake_info->vdev_id, 0);
3136}
3137
3138/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003139 * wma_wow_wakeup_host_event() - wakeup host event handler
3140 * @handle: wma handle
3141 * @event: event data
3142 * @len: buffer length
3143 *
3144 * Handler to catch wow wakeup host event. This event will have
3145 * reason why the firmware has woken the host.
3146 *
3147 * Return: 0 for success or error
3148 */
3149int wma_wow_wakeup_host_event(void *handle, uint8_t *event,
3150 uint32_t len)
3151{
3152 tp_wma_handle wma = (tp_wma_handle) handle;
3153 WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *param_buf;
3154 WOW_EVENT_INFO_fixed_param *wake_info;
3155#ifdef FEATURE_WLAN_SCAN_PNO
3156 struct wma_txrx_node *node;
3157#endif /* FEATURE_WLAN_SCAN_PNO */
3158 uint32_t wake_lock_duration = 0;
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07003159 void *wmi_cmd_struct_ptr = NULL;
3160 uint32_t tlv_hdr, tag, wow_buf_pkt_len = 0, event_id = 0;
3161 int tlv_ok_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003162
3163 param_buf = (WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *) event;
3164 if (!param_buf) {
3165 WMA_LOGE("Invalid wow wakeup host event buf");
3166 return -EINVAL;
3167 }
3168
3169 wake_info = param_buf->fixed_param;
3170
Srinivas Girigowdae1e69132016-08-23 06:51:58 +05303171 if ((wake_info->wake_reason != WOW_REASON_UNSPECIFIED) ||
3172 (wake_info->wake_reason == WOW_REASON_UNSPECIFIED &&
Nitesh Shahd732f742016-08-23 08:07:09 +05303173 !wmi_get_runtime_pm_inprogress(wma->wmi_handle))) {
Srinivas Girigowdae1e69132016-08-23 06:51:58 +05303174 WMA_LOGA("WOW wakeup host event received (reason: %s(%d)) for vdev %d",
3175 wma_wow_wake_reason_str(wake_info->wake_reason),
3176 wake_info->wake_reason, wake_info->vdev_id);
Nitesh Shahd732f742016-08-23 08:07:09 +05303177 qdf_wow_wakeup_host_event(wake_info->wake_reason);
3178 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003179
Anurag Chouhance0dc992016-02-16 18:18:03 +05303180 qdf_event_set(&wma->wma_resume_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003181
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07003182 if (param_buf->wow_packet_buffer &&
3183 tlv_check_required(wake_info->wake_reason)) {
3184 /*
3185 * In case of wow_packet_buffer, first 4 bytes is the length.
3186 * Following the length is the actual buffer.
3187 */
3188 wow_buf_pkt_len = *(uint32_t *)param_buf->wow_packet_buffer;
3189 tlv_hdr = WMITLV_GET_HDR(
3190 (uint8_t *)param_buf->wow_packet_buffer + 4);
3191
3192 tag = WMITLV_GET_TLVTAG(tlv_hdr);
3193 event_id = wow_get_wmi_eventid(wake_info->wake_reason, tag);
3194 if (!event_id) {
3195 WMA_LOGE(FL("Unable to find matching ID"));
3196 return -EINVAL;
3197 }
3198
3199 tlv_ok_status = wmitlv_check_and_pad_event_tlvs(
3200 handle, param_buf->wow_packet_buffer + 4,
3201 wow_buf_pkt_len, event_id,
3202 &wmi_cmd_struct_ptr);
3203
3204 if (tlv_ok_status != 0) {
3205 WMA_LOGE(FL("Invalid TLVs, Length:%d event_id:%d status: %d"),
3206 wow_buf_pkt_len, event_id, tlv_ok_status);
3207 return -EINVAL;
3208 }
3209 }
3210
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003211 switch (wake_info->wake_reason) {
3212 case WOW_REASON_AUTH_REQ_RECV:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003213 case WOW_REASON_ASSOC_REQ_RECV:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003214 case WOW_REASON_DEAUTH_RECVD:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003215 case WOW_REASON_DISASSOC_RECVD:
Himanshu Agarwaldd356df2016-07-20 19:04:39 +05303216 case WOW_REASON_ASSOC_RES_RECV:
3217 case WOW_REASON_REASSOC_REQ_RECV:
3218 case WOW_REASON_REASSOC_RES_RECV:
3219 case WOW_REASON_BEACON_RECV:
3220 case WOW_REASON_ACTION_FRAME_RECV:
3221 wake_lock_duration =
3222 wma_wow_get_wakelock_duration(wake_info->wake_reason);
3223 if (param_buf->wow_packet_buffer) {
3224 /* First 4-bytes of wow_packet_buffer is the length */
3225 qdf_mem_copy((uint8_t *) &wow_buf_pkt_len,
3226 param_buf->wow_packet_buffer, 4);
3227 if (wow_buf_pkt_len)
3228 wma_wow_dump_mgmt_buffer(
3229 param_buf->wow_packet_buffer,
3230 wow_buf_pkt_len);
3231 else
3232 WMA_LOGE("wow packet buffer is empty");
3233 } else {
3234 WMA_LOGE("No wow packet buffer present");
3235 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003236 break;
3237
3238 case WOW_REASON_AP_ASSOC_LOST:
3239 wake_lock_duration = WMA_BMISS_EVENT_WAKE_LOCK_DURATION;
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05303240 wma_wow_ap_lost_helper(wma, param_buf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003241 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003242#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
3243 case WOW_REASON_HOST_AUTO_SHUTDOWN:
3244 wake_lock_duration = WMA_AUTO_SHUTDOWN_WAKE_LOCK_DURATION;
3245 WMA_LOGA("Received WOW Auto Shutdown trigger in suspend");
3246 if (wma_post_auto_shutdown_msg())
3247 return -EINVAL;
3248 break;
3249#endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
3250#ifdef FEATURE_WLAN_SCAN_PNO
3251 case WOW_REASON_NLOD:
3252 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_NLOD);
3253 node = &wma->interfaces[wake_info->vdev_id];
3254 if (node) {
3255 WMA_LOGD("NLO match happened");
3256 node->nlo_match_evt_received = true;
Anurag Chouhan01cfa4e2016-09-04 15:10:49 +05303257 cds_host_diag_log_work(&wma->pno_wake_lock,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003258 WMA_PNO_MATCH_WAKE_LOCK_TIMEOUT,
3259 WIFI_POWER_EVENT_WAKELOCK_PNO);
Anurag Chouhan01cfa4e2016-09-04 15:10:49 +05303260 qdf_wake_lock_timeout_acquire(&wma->pno_wake_lock,
3261 WMA_PNO_MATCH_WAKE_LOCK_TIMEOUT);
Srinivas Girigowdae80cea92015-11-23 11:33:57 -08003262 }
3263 break;
3264
3265 case WOW_REASON_NLO_SCAN_COMPLETE:
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07003266 WMA_LOGD("Host woken up due to pno scan complete reason");
3267 if (param_buf->wow_packet_buffer)
3268 wma_nlo_scan_cmp_evt_handler(handle,
3269 wmi_cmd_struct_ptr, wow_buf_pkt_len);
3270 else
3271 WMA_LOGD("No wow_packet_buffer present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003272 break;
3273#endif /* FEATURE_WLAN_SCAN_PNO */
3274
3275 case WOW_REASON_CSA_EVENT:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003276 WMA_LOGD("Host woken up because of CSA IE");
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07003277 wma_csa_offload_handler(handle, wmi_cmd_struct_ptr,
3278 wow_buf_pkt_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003279 break;
3280
3281#ifdef FEATURE_WLAN_LPHB
3282 case WOW_REASON_WLAN_HB:
3283 wma_lphb_handler(wma, (uint8_t *) param_buf->hb_indevt);
3284 break;
3285#endif /* FEATURE_WLAN_LPHB */
3286
3287 case WOW_REASON_HTT_EVENT:
3288 break;
Dustin Brown75d02342016-08-29 11:23:47 -07003289
3290 case WOW_REASON_BPF_ALLOW:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003291 case WOW_REASON_PATTERN_MATCH_FOUND:
Dustin Brownfc37c6a2016-10-11 13:37:34 -07003292#ifdef FEATURE_WLAN_RA_FILTERING
3293 case WOW_REASON_RA_MATCH:
3294#endif /* FEATURE_WLAN_RA_FILTERING */
3295 case WOW_REASON_RECV_MAGIC_PATTERN:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003296 wma_wow_wake_up_stats_display(wma);
3297 WMA_LOGD("Wake up for Rx packet, dump starting from ethernet hdr");
3298 if (param_buf->wow_packet_buffer) {
3299 /* First 4-bytes of wow_packet_buffer is the length */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303300 qdf_mem_copy((uint8_t *) &wow_buf_pkt_len,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003301 param_buf->wow_packet_buffer, 4);
Himanshu Agarwal82de9042016-07-20 18:11:03 +05303302 if (wow_buf_pkt_len) {
3303 uint8_t *data;
3304
3305 wma_wow_wake_up_stats(wma,
3306 param_buf->wow_packet_buffer + 4,
3307 wow_buf_pkt_len,
Dustin Brownfc37c6a2016-10-11 13:37:34 -07003308 wake_info->wake_reason);
Himanshu Agarwal82de9042016-07-20 18:11:03 +05303309 qdf_trace_hex_dump(QDF_MODULE_ID_WMA,
3310 QDF_TRACE_LEVEL_DEBUG,
3311 param_buf->wow_packet_buffer + 4,
3312 wow_buf_pkt_len);
3313
3314 data = (uint8_t *)
3315 (param_buf->wow_packet_buffer + 4);
3316 wma_wow_parse_data_pkt_buffer(data,
3317 wow_buf_pkt_len);
3318 } else {
3319 WMA_LOGE("wow packet buffer is empty");
3320 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003321 } else {
3322 WMA_LOGE("No wow packet buffer present");
3323 }
3324 break;
3325
3326 case WOW_REASON_LOW_RSSI:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003327 /* WOW_REASON_LOW_RSSI is used for all roaming events.
3328 * WMI_ROAM_REASON_BETTER_AP, WMI_ROAM_REASON_BMISS,
3329 * WMI_ROAM_REASON_SUITABLE_AP will be handled by
3330 * wma_roam_event_callback().
3331 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003332 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_LOW_RSSI);
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07003333 WMA_LOGD("Host woken up because of roam event");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003334 if (param_buf->wow_packet_buffer) {
3335 /* Roam event is embedded in wow_packet_buffer */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003336 WMA_LOGD("wow_packet_buffer dump");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303337 qdf_trace_hex_dump(QDF_MODULE_ID_WMA,
3338 QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003339 param_buf->wow_packet_buffer,
3340 wow_buf_pkt_len);
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07003341 wma_roam_event_callback(handle, wmi_cmd_struct_ptr,
3342 wow_buf_pkt_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003343 } else {
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07003344 /*
3345 * No wow_packet_buffer means a better AP beacon
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003346 * will follow in a later event.
3347 */
3348 WMA_LOGD("Host woken up because of better AP beacon");
3349 }
3350 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003351 case WOW_REASON_CLIENT_KICKOUT_EVENT:
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07003352 WMA_LOGD("Host woken up because of sta_kickout event");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003353 if (param_buf->wow_packet_buffer) {
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07003354 WMA_LOGD("wow_packet_buffer dump");
3355 qdf_trace_hex_dump(QDF_MODULE_ID_WMA,
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303356 QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003357 param_buf->wow_packet_buffer, wow_buf_pkt_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003358 wma_peer_sta_kickout_event_handler(handle,
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07003359 wmi_cmd_struct_ptr, wow_buf_pkt_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003360 } else {
3361 WMA_LOGD("No wow_packet_buffer present");
3362 }
3363 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003364#ifdef FEATURE_WLAN_EXTSCAN
3365 case WOW_REASON_EXTSCAN:
3366 WMA_LOGD("Host woken up because of extscan reason");
3367 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_EXTSCAN);
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07003368 if (param_buf->wow_packet_buffer)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003369 wma_extscan_wow_event_callback(handle,
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07003370 wmi_cmd_struct_ptr, wow_buf_pkt_len);
3371 else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003372 WMA_LOGE("wow_packet_buffer is empty");
3373 break;
3374#endif
3375 case WOW_REASON_RSSI_BREACH_EVENT:
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07003376 wma_wow_wake_up_stats(wma, NULL, 0,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003377 WOW_REASON_RSSI_BREACH_EVENT);
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07003378 WMA_LOGD("Host woken up because of rssi breach reason");
3379 /* rssi breach event is embedded in wow_packet_buffer */
3380 if (param_buf->wow_packet_buffer)
3381 wma_rssi_breached_event_handler(handle,
3382 wmi_cmd_struct_ptr, wow_buf_pkt_len);
3383 else
3384 WMA_LOGD("No wow_packet_buffer present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003385 break;
Naveen Rawatc9f09522016-05-12 14:02:42 -07003386 case WOW_REASON_NAN_EVENT:
3387 WMA_LOGA("Host woken up due to NAN event reason");
3388 wma_nan_rsp_event_handler(handle,
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07003389 wmi_cmd_struct_ptr, wow_buf_pkt_len);
Naveen Rawatc9f09522016-05-12 14:02:42 -07003390 break;
Naveen Rawate82c1f32016-06-22 15:34:36 -07003391 case WOW_REASON_NAN_DATA:
3392 WMA_LOGD(FL("Host woken up for NAN data path event from FW"));
3393 if (param_buf->wow_packet_buffer) {
Naveen Rawat17dccbe2016-08-23 17:09:04 -07003394 wma_ndp_wow_event_callback(handle, wmi_cmd_struct_ptr,
3395 wow_buf_pkt_len, event_id);
Naveen Rawate82c1f32016-06-22 15:34:36 -07003396 } else {
3397 WMA_LOGE(FL("wow_packet_buffer is empty"));
3398 }
3399 break;
Selvaraj, Sridhar172cabc2016-07-05 15:19:24 +05303400 case WOW_REASON_OEM_RESPONSE_EVENT:
3401 wma_wow_wake_up_stats(wma, NULL, 0,
3402 WOW_REASON_OEM_RESPONSE_EVENT);
3403 /*
3404 * Actual OEM Response event will follow after this
3405 * WOW Wakeup event
3406 */
3407 WMA_LOGD(FL("Host woken up for OEM Response event"));
3408 break;
Selvaraj, Sridhar251761a2016-06-25 16:05:15 +05303409#ifdef FEATURE_WLAN_TDLS
3410 case WOW_REASON_TDLS_CONN_TRACKER_EVENT:
3411 WMA_LOGD("Host woken up because of TDLS event");
3412 if (param_buf->wow_packet_buffer)
3413 wma_tdls_event_handler(handle,
3414 wmi_cmd_struct_ptr, wow_buf_pkt_len);
3415 else
3416 WMA_LOGD("No wow_packet_buffer present");
3417 break;
3418#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003419 default:
3420 break;
3421 }
3422
3423 if (wake_lock_duration) {
Anurag Chouhan01cfa4e2016-09-04 15:10:49 +05303424 cds_host_diag_log_work(&wma->wow_wake_lock,
3425 wake_lock_duration,
3426 WIFI_POWER_EVENT_WAKELOCK_WOW);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303427 qdf_wake_lock_timeout_acquire(&wma->wow_wake_lock,
Anurag Chouhan01cfa4e2016-09-04 15:10:49 +05303428 wake_lock_duration);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003429 WMA_LOGA("Holding %d msec wake_lock", wake_lock_duration);
3430 }
3431
Rajeev Kumar2c892fe2016-08-24 16:17:16 -07003432 if (wmi_cmd_struct_ptr)
3433 wmitlv_free_allocated_event_tlvs(event_id, &wmi_cmd_struct_ptr);
3434
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003435 return 0;
3436}
3437
3438/**
3439 * wma_pdev_resume_event_handler() - PDEV resume event handler
3440 * @handle: wma handle
3441 * @event: event data
3442 * @len: buffer length
3443 *
3444 * Return: 0 for success or error
3445 */
3446int wma_pdev_resume_event_handler(void *handle, uint8_t *event, uint32_t len)
3447{
3448 tp_wma_handle wma = (tp_wma_handle) handle;
3449
3450 WMA_LOGA("Received PDEV resume event");
3451
Anurag Chouhance0dc992016-02-16 18:18:03 +05303452 qdf_event_set(&wma->wma_resume_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003453
3454 return 0;
3455}
3456/**
3457 * wma_set_wow_bus_suspend() - set suspend flag
3458 * @wma: wma handle
3459 * @val: value
3460 *
3461 * Return: none
3462 */
3463static inline void wma_set_wow_bus_suspend(tp_wma_handle wma, int val)
3464{
3465
Anurag Chouhan8e0ccd32016-02-19 15:30:20 +05303466 qdf_atomic_set(&wma->is_wow_bus_suspended, val);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003467}
3468
3469
3470
3471/**
3472 * wma_add_wow_wakeup_event() - Configures wow wakeup events.
3473 * @wma: wma handle
3474 * @vdev_id: vdev id
3475 * @bitmap: Event bitmap
3476 * @enable: enable/disable
3477 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303478 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003479 */
Naveen Rawate82c1f32016-06-22 15:34:36 -07003480QDF_STATUS wma_add_wow_wakeup_event(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003481 uint32_t vdev_id,
3482 uint32_t bitmap,
3483 bool enable)
3484{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003485 int ret;
3486
Govind Singhaa64c242016-03-08 11:31:49 +05303487 ret = wmi_unified_add_wow_wakeup_event_cmd(wma->wmi_handle, vdev_id,
Rajeev Kumar4002e5b2016-06-22 12:01:15 -07003488 bitmap, enable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003489 if (ret) {
3490 WMA_LOGE("Failed to config wow wakeup event");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303491 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003492 }
3493
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303494 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003495}
3496
3497/**
3498 * wma_send_wow_patterns_to_fw() - Sends WOW patterns to FW.
3499 * @wma: wma handle
3500 * @vdev_id: vdev id
3501 * @ptrn_id: pattern id
3502 * @ptrn: pattern
3503 * @ptrn_len: pattern length
3504 * @ptrn_offset: pattern offset
3505 * @mask: mask
3506 * @mask_len: mask length
3507 * @user: true for user configured pattern and false for default pattern
3508 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303509 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003510 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303511static QDF_STATUS wma_send_wow_patterns_to_fw(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003512 uint8_t vdev_id, uint8_t ptrn_id,
3513 const uint8_t *ptrn, uint8_t ptrn_len,
3514 uint8_t ptrn_offset, const uint8_t *mask,
3515 uint8_t mask_len, bool user)
3516{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003517 struct wma_txrx_node *iface;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003518 int ret;
3519
3520 iface = &wma->interfaces[vdev_id];
Govind Singhaa64c242016-03-08 11:31:49 +05303521 ret = wmi_unified_wow_patterns_to_fw_cmd(wma->wmi_handle,
3522 vdev_id, ptrn_id, ptrn,
3523 ptrn_len, ptrn_offset, mask,
Rajeev Kumar25a0b212016-09-16 13:29:43 -07003524 mask_len, user, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003525 if (ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003526 if (!user)
3527 iface->num_wow_default_patterns--;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303528 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003529 }
3530
3531 if (user)
3532 iface->num_wow_user_patterns++;
3533
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303534 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003535}
3536
3537/**
3538 * wma_wow_ap() - set WOW patterns in ap mode
3539 * @wma: wma handle
3540 * @vdev_id: vdev id
3541 *
3542 * Configures default WOW pattern for the given vdev_id which is in AP mode.
3543 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303544 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003545 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303546static QDF_STATUS wma_wow_ap(tp_wma_handle wma, uint8_t vdev_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003547{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303548 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003549 uint8_t arp_offset = 20;
3550 uint8_t mac_mask[IEEE80211_ADDR_LEN];
Rajeev Kumar25a0b212016-09-16 13:29:43 -07003551 struct wma_txrx_node *iface = &wma->interfaces[vdev_id];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003552
Rajeev Kumar25a0b212016-09-16 13:29:43 -07003553 /*
3554 * Setup unicast pkt pattern
3555 * WoW pattern id should be unique for each vdev
3556 * WoW pattern id can be same on 2 different VDEVs
3557 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303558 qdf_mem_set(&mac_mask, IEEE80211_ADDR_LEN, 0xFF);
Rajeev Kumar25a0b212016-09-16 13:29:43 -07003559 ret = wma_send_wow_patterns_to_fw(wma, vdev_id,
3560 iface->num_wow_default_patterns++,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003561 wma->interfaces[vdev_id].addr,
3562 IEEE80211_ADDR_LEN, 0, mac_mask,
3563 IEEE80211_ADDR_LEN, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303564 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003565 WMA_LOGE("Failed to add WOW unicast pattern ret %d", ret);
3566 return ret;
3567 }
3568
3569 /*
3570 * Setup all ARP pkt pattern. This is dummy pattern hence the length
Rajeev Kumar25a0b212016-09-16 13:29:43 -07003571 * is zero. Pattern ID should be unique per vdev.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003572 */
Rajeev Kumar25a0b212016-09-16 13:29:43 -07003573 ret = wma_send_wow_patterns_to_fw(wma, vdev_id,
3574 iface->num_wow_default_patterns++,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003575 arp_ptrn, 0, arp_offset, arp_mask, 0, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303576 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003577 WMA_LOGE("Failed to add WOW ARP pattern ret %d", ret);
3578 return ret;
3579 }
3580
3581 return ret;
3582}
3583
3584/**
Komal Seelam9764a842016-05-24 11:07:23 +05303585 * wma_configure_wow_ssdp() - API to configure WoW SSDP
3586 * @wma: WMA Handle
3587 * @vdev_id: Vdev Id
3588 *
3589 * API to configure SSDP pattern as WoW pattern
3590 *
3591 * Return: Success/Failure
3592 */
3593static QDF_STATUS wma_configure_wow_ssdp(tp_wma_handle wma, uint8_t vdev_id)
3594{
3595 QDF_STATUS status = QDF_STATUS_SUCCESS;
3596 uint8_t discvr_offset = 30;
Rajeev Kumar25a0b212016-09-16 13:29:43 -07003597 struct wma_txrx_node *iface = &wma->interfaces[vdev_id];
Komal Seelam9764a842016-05-24 11:07:23 +05303598
Rajeev Kumar25a0b212016-09-16 13:29:43 -07003599 /*
3600 * WoW pattern ID should be unique for each vdev
3601 * Different WoW patterns can use same pattern ID
3602 */
3603 status = wma_send_wow_patterns_to_fw(wma, vdev_id,
3604 iface->num_wow_default_patterns++,
Komal Seelam9764a842016-05-24 11:07:23 +05303605 discvr_ptrn, sizeof(discvr_ptrn), discvr_offset,
3606 discvr_mask, sizeof(discvr_ptrn), false);
3607
3608 if (status != QDF_STATUS_SUCCESS)
3609 WMA_LOGE("Failed to add WOW mDNS/SSDP/LLMNR pattern");
3610
3611 return status;
3612}
3613
3614/**
3615 * wma_configure_mc_ssdp() - API to configure SSDP address as MC list
3616 * @wma: WMA Handle
3617 * @vdev_id: Vdev Id
3618 *
3619 * SSDP address 239.255.255.250 is converted to Multicast Mac address
3620 * and configure it to FW. Firmware will apply this pattern on the incoming
3621 * packets to filter them out during chatter/wow mode.
3622 *
3623 * Return: Success/Failure
3624 */
3625static QDF_STATUS wma_configure_mc_ssdp(tp_wma_handle wma, uint8_t vdev_id)
3626{
3627 WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param *cmd;
3628 wmi_buf_t buf;
3629 const tSirMacAddr ssdp_addr = {0x01, 0x00, 0x5e, 0x7f, 0xff, 0xfa};
3630 int ret;
3631 WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param fixed_param;
3632 uint32_t tag =
3633 WMITLV_TAG_STRUC_WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param;
3634
3635 buf = wmi_buf_alloc(wma->wmi_handle, sizeof(*cmd));
3636 if (!buf) {
3637 WMA_LOGE("%s No Memory for MC address", __func__);
3638 return QDF_STATUS_E_NOMEM;
3639 }
3640
3641 cmd = (WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param *) wmi_buf_data(buf);
3642
3643 WMITLV_SET_HDR(&cmd->tlv_header, tag,
3644 WMITLV_GET_STRUCT_TLVLEN(fixed_param));
3645
3646 cmd->action = WMI_MCAST_FILTER_SET;
3647 cmd->vdev_id = vdev_id;
3648 WMI_CHAR_ARRAY_TO_MAC_ADDR(ssdp_addr, &cmd->mcastbdcastaddr);
3649 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, sizeof(*cmd),
3650 WMI_SET_MCASTBCAST_FILTER_CMDID);
3651 if (ret != QDF_STATUS_SUCCESS) {
3652 WMA_LOGE("%s Failed to configure FW with SSDP MC address",
3653 __func__);
3654 wmi_buf_free(buf);
3655 return QDF_STATUS_E_FAILURE;
3656 }
3657
3658 return QDF_STATUS_SUCCESS;
3659}
3660
3661/**
3662 * wma_configure_ssdp() - API to Configure SSDP pattern to FW
3663 * @wma: WMA Handle
3664 * @vdev_id: VDEV ID
3665 *
3666 * Setup multicast pattern for mDNS 224.0.0.251, SSDP 239.255.255.250 and LLMNR
3667 * 224.0.0.252
3668 *
3669 * Return: Success/Failure.
3670 */
3671static QDF_STATUS wma_configure_ssdp(tp_wma_handle wma, uint8_t vdev_id)
3672{
3673 if (!wma->ssdp) {
3674 WMA_LOGD("mDNS, SSDP, LLMNR patterns are disabled from ini");
3675 return QDF_STATUS_SUCCESS;
3676 }
3677
3678 WMA_LOGD("%s, enable_mc_list:%d", __func__, wma->enable_mc_list);
3679
3680 if (wma->enable_mc_list)
3681 return wma_configure_mc_ssdp(wma, vdev_id);
3682
3683 return wma_configure_wow_ssdp(wma, vdev_id);
3684}
3685
3686/**
Paul Zhange79e7db2017-01-04 16:37:05 +08003687 * wma_register_action_frame_patterns() - register action frame map to fw
3688 * @handle: Pointer to wma handle
3689 * @vdev_id: VDEV ID
3690 *
3691 * This is called to push action frames wow patterns from local
3692 * cache to firmware.
3693 *
3694 * Return: QDF_STATUS
3695 */
3696QDF_STATUS wma_register_action_frame_patterns(WMA_HANDLE handle,
3697 uint8_t vdev_id)
3698{
3699 tp_wma_handle wma = handle;
3700 struct action_wakeup_set_param cmd = {0};
3701 int32_t err;
3702 int i = 0;
3703
3704 cmd.vdev_id = vdev_id;
3705 cmd.operation = WOW_ACTION_WAKEUP_OPERATION_SET;
3706
3707 cmd.action_category_map[i++] = ALLOWED_ACTION_FRAMES_BITMAP0;
3708 cmd.action_category_map[i++] = ALLOWED_ACTION_FRAMES_BITMAP1;
3709 cmd.action_category_map[i++] = ALLOWED_ACTION_FRAMES_BITMAP2;
3710 cmd.action_category_map[i++] = ALLOWED_ACTION_FRAMES_BITMAP3;
3711 cmd.action_category_map[i++] = ALLOWED_ACTION_FRAMES_BITMAP4;
3712 cmd.action_category_map[i++] = ALLOWED_ACTION_FRAMES_BITMAP5;
3713 cmd.action_category_map[i++] = ALLOWED_ACTION_FRAMES_BITMAP6;
3714 cmd.action_category_map[i++] = ALLOWED_ACTION_FRAMES_BITMAP7;
3715
3716 for (i = 0; i < WMI_SUPPORTED_ACTION_CATEGORY_ELE_LIST; i++) {
3717 if (i < ALLOWED_ACTION_FRAME_MAP_WORDS)
3718 WMA_LOGD("%s: %d action Wakeup pattern 0x%x in fw",
3719 __func__, i, cmd.action_category_map[i]);
3720 else
3721 cmd.action_category_map[i] = 0;
3722 }
3723
3724 err = wmi_unified_action_frame_patterns_cmd(wma->wmi_handle, &cmd);
3725 if (err) {
3726 WMA_LOGE("Failed to config wow action frame map, ret %d", err);
3727 return QDF_STATUS_E_FAILURE;
3728 }
3729
3730 return QDF_STATUS_SUCCESS;
3731}
3732
3733/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003734 * wma_wow_sta() - set WOW patterns in sta mode
3735 * @wma: wma handle
3736 * @vdev_id: vdev id
3737 *
3738 * Configures default WOW pattern for the given vdev_id which is in sta mode.
3739 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303740 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003741 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303742static QDF_STATUS wma_wow_sta(tp_wma_handle wma, uint8_t vdev_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003743{
3744 uint8_t arp_offset = 12;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003745 uint8_t mac_mask[IEEE80211_ADDR_LEN];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303746 QDF_STATUS ret = QDF_STATUS_SUCCESS;
Rajeev Kumar25a0b212016-09-16 13:29:43 -07003747 struct wma_txrx_node *iface = &wma->interfaces[vdev_id];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003748
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303749 qdf_mem_set(&mac_mask, IEEE80211_ADDR_LEN, 0xFF);
Rajeev Kumar25a0b212016-09-16 13:29:43 -07003750 /*
3751 * Set up unicast wow pattern
3752 * WoW pattern ID should be unique for each vdev
3753 * Different WoW patterns can use same pattern ID
3754 */
3755 ret = wma_send_wow_patterns_to_fw(wma, vdev_id,
3756 iface->num_wow_default_patterns++,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003757 wma->interfaces[vdev_id].addr,
3758 IEEE80211_ADDR_LEN, 0, mac_mask,
3759 IEEE80211_ADDR_LEN, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303760 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003761 WMA_LOGE("Failed to add WOW unicast pattern ret %d", ret);
3762 return ret;
3763 }
3764
Komal Seelam9764a842016-05-24 11:07:23 +05303765 ret = wma_configure_ssdp(wma, vdev_id);
3766 if (ret != QDF_STATUS_SUCCESS)
3767 WMA_LOGE("Failed to configure SSDP patterns to FW");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003768
3769 /* when arp offload or ns offloaded is disabled
3770 * from ini file, configure broad cast arp pattern
3771 * to fw, so that host can wake up
3772 */
3773 if (!(wma->ol_ini_info & 0x1)) {
3774 /* Setup all ARP pkt pattern */
Rajeev Kumar25a0b212016-09-16 13:29:43 -07003775 WMA_LOGI("ARP offload is disabled in INI enable WoW for ARP");
3776 ret = wma_send_wow_patterns_to_fw(wma, vdev_id,
3777 iface->num_wow_default_patterns++,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003778 arp_ptrn, sizeof(arp_ptrn), arp_offset,
3779 arp_mask, sizeof(arp_mask), false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303780 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003781 WMA_LOGE("Failed to add WOW ARP pattern");
3782 return ret;
3783 }
3784 }
3785
3786 /* for NS or NDP offload packets */
3787 if (!(wma->ol_ini_info & 0x2)) {
3788 /* Setup all NS pkt pattern */
Rajeev Kumar25a0b212016-09-16 13:29:43 -07003789 WMA_LOGI("NS offload is disabled in INI enable WoW for NS");
3790 ret = wma_send_wow_patterns_to_fw(wma, vdev_id,
3791 iface->num_wow_default_patterns++,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003792 ns_ptrn, sizeof(arp_ptrn), arp_offset,
3793 arp_mask, sizeof(arp_mask), false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303794 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003795 WMA_LOGE("Failed to add WOW NS pattern");
3796 return ret;
3797 }
3798 }
3799
3800 return ret;
3801}
3802
3803/**
3804 * wma_register_wow_default_patterns() - register default wow patterns with fw
3805 * @handle: Pointer to wma handle
3806 * @vdev_id: vdev id
3807 *
3808 * WoW default wake up pattern rule is:
3809 * - For STA & P2P CLI mode register for same STA specific wow patterns
3810 * - For SAP/P2P GO & IBSS mode register for same SAP specific wow patterns
3811 *
3812 * Return: none
3813 */
3814void wma_register_wow_default_patterns(WMA_HANDLE handle, uint8_t vdev_id)
3815{
3816 tp_wma_handle wma = handle;
3817 struct wma_txrx_node *iface;
3818
3819 if (vdev_id > wma->max_bssid) {
3820 WMA_LOGE("Invalid vdev id %d", vdev_id);
3821 return;
3822 }
3823 iface = &wma->interfaces[vdev_id];
3824
3825 if (iface->ptrn_match_enable) {
Houston Hoffman79b4af22015-10-06 12:01:08 -07003826 if (wma_is_vdev_in_beaconning_mode(wma, vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003827 /* Configure SAP/GO/IBSS mode default wow patterns */
3828 WMA_LOGI("Config SAP specific default wow patterns vdev_id %d",
3829 vdev_id);
3830 wma_wow_ap(wma, vdev_id);
3831 } else {
3832 /* Configure STA/P2P CLI mode default wow patterns */
3833 WMA_LOGI("Config STA specific default wow patterns vdev_id %d",
3834 vdev_id);
3835 wma_wow_sta(wma, vdev_id);
3836 if (wma->IsRArateLimitEnabled) {
3837 WMA_LOGI("Config STA RA limit wow patterns vdev_id %d",
3838 vdev_id);
3839 wma_wow_sta_ra_filter(wma, vdev_id);
3840 }
3841 }
3842 }
3843
3844 return;
3845}
3846
3847/**
3848 * wma_register_wow_wakeup_events() - register vdev specific wake events with fw
3849 * @handle: Pointer to wma handle
3850 * @vdev_id: vdev Id
3851 * @vdev_type: vdev type
3852 * @vdev_subtype: vdev sub type
3853 *
3854 * WoW wake up event rule is following:
3855 * 1) STA mode and P2P CLI mode wake up events are same
3856 * 2) SAP mode and P2P GO mode wake up events are same
3857 * 3) IBSS mode wake events are same as STA mode plus WOW_BEACON_EVENT
3858 *
3859 * Return: none
3860 */
3861void wma_register_wow_wakeup_events(WMA_HANDLE handle,
3862 uint8_t vdev_id,
3863 uint8_t vdev_type,
3864 uint8_t vdev_subtype)
3865{
3866 tp_wma_handle wma = handle;
3867 uint32_t event_bitmap;
3868
3869 WMA_LOGI("vdev_type %d vdev_subtype %d vdev_id %d", vdev_type,
3870 vdev_subtype, vdev_id);
3871
3872 if ((WMI_VDEV_TYPE_STA == vdev_type) ||
3873 ((WMI_VDEV_TYPE_AP == vdev_type) &&
3874 (WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE == vdev_subtype))) {
3875 /* Configure STA/P2P CLI mode specific default wake up events */
3876 event_bitmap = WMA_WOW_STA_WAKE_UP_EVENTS;
3877 WMA_LOGI("STA specific default wake up event 0x%x vdev id %d",
3878 event_bitmap, vdev_id);
3879 } else if (WMI_VDEV_TYPE_IBSS == vdev_type) {
3880 /* Configure IBSS mode specific default wake up events */
3881 event_bitmap = (WMA_WOW_STA_WAKE_UP_EVENTS |
3882 (1 << WOW_BEACON_EVENT));
3883 WMA_LOGI("IBSS specific default wake up event 0x%x vdev id %d",
3884 event_bitmap, vdev_id);
3885 } else if (WMI_VDEV_TYPE_AP == vdev_type) {
3886 /* Configure SAP/GO mode specific default wake up events */
3887 event_bitmap = WMA_WOW_SAP_WAKE_UP_EVENTS;
3888 WMA_LOGI("SAP specific default wake up event 0x%x vdev id %d",
3889 event_bitmap, vdev_id);
Naveen Rawate82c1f32016-06-22 15:34:36 -07003890 } else if (WMI_VDEV_TYPE_NDI == vdev_type) {
3891 /*
3892 * Configure NAN data path specific default wake up events.
3893 * Following routine sends the command to firmware.
3894 */
3895 wma_ndp_add_wow_wakeup_event(wma, vdev_id);
3896 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003897 } else {
3898 WMA_LOGE("unknown type %d subtype %d", vdev_type, vdev_subtype);
3899 return;
3900 }
3901
3902 wma_add_wow_wakeup_event(wma, vdev_id, event_bitmap, true);
3903
3904 return;
3905}
3906
3907/**
3908 * wma_enable_disable_wakeup_event() - Configures wow wakeup events
3909 * @wma: wma handle
3910 * @vdev_id: vdev id
3911 * @bitmap: Event bitmap
3912 * @enable: enable/disable
3913 *
3914 * Return: none
3915 */
3916void wma_enable_disable_wakeup_event(WMA_HANDLE handle,
3917 uint32_t vdev_id,
3918 uint32_t bitmap,
3919 bool enable)
3920{
3921 tp_wma_handle wma = handle;
3922
3923 WMA_LOGI("vdev_id %d wake up event 0x%x enable %d",
3924 vdev_id, bitmap, enable);
3925 wma_add_wow_wakeup_event(wma, vdev_id, bitmap, enable);
3926}
3927
3928/**
3929 * wma_enable_wow_in_fw() - wnable wow in fw
3930 * @wma: wma handle
Dustin Browne70fd972016-11-10 11:17:40 -08003931 * @wow_flags: bitmap of WMI WOW flags to pass to FW
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003932 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303933 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003934 */
Dustin Browne70fd972016-11-10 11:17:40 -08003935QDF_STATUS wma_enable_wow_in_fw(WMA_HANDLE handle, uint32_t wow_flags)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003936{
3937 tp_wma_handle wma = handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003938 int ret;
Komal Seelam3d202862016-02-24 18:43:24 +05303939 struct hif_opaque_softc *scn;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003940 int host_credits;
3941 int wmi_pending_cmds;
Govind Singhd76a5b02016-03-08 15:12:14 +05303942 struct wow_cmd_params param = {0};
3943
Anurag Chouhan6d760662016-02-20 16:05:43 +05303944 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003945
3946 if (NULL == pMac) {
3947 WMA_LOGE("%s: Unable to get PE context", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303948 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003949 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003950
Anurag Chouhance0dc992016-02-16 18:18:03 +05303951 qdf_event_reset(&wma->target_suspend);
Houston Hoffmana769ed32016-04-14 17:02:51 -07003952 wma->wow_nack = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003953
3954 host_credits = wmi_get_host_credits(wma->wmi_handle);
3955 wmi_pending_cmds = wmi_get_pending_cmds(wma->wmi_handle);
3956
3957 WMA_LOGD("Credits:%d; Pending_Cmds: %d",
3958 host_credits, wmi_pending_cmds);
3959
Govind Singhd76a5b02016-03-08 15:12:14 +05303960 param.enable = true;
Houston Hoffman77f0e342016-07-25 13:28:10 -07003961 param.can_suspend_link = htc_can_suspend_link(wma->htc_handle);
Dustin Browne70fd972016-11-10 11:17:40 -08003962 param.flags = wow_flags;
Govind Singhd76a5b02016-03-08 15:12:14 +05303963 ret = wmi_unified_wow_enable_send(wma->wmi_handle, &param,
3964 WMA_WILDCARD_PDEV_ID);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003965 if (ret) {
3966 WMA_LOGE("Failed to enable wow in fw");
3967 goto error;
3968 }
3969
3970 wmi_set_target_suspend(wma->wmi_handle, true);
3971
Anurag Chouhance0dc992016-02-16 18:18:03 +05303972 if (qdf_wait_single_event(&wma->target_suspend,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003973 WMA_TGT_SUSPEND_COMPLETE_TIMEOUT)
Anurag Chouhance0dc992016-02-16 18:18:03 +05303974 != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003975 WMA_LOGE("Failed to receive WoW Enable Ack from FW");
3976 WMA_LOGE("Credits:%d; Pending_Cmds: %d",
3977 wmi_get_host_credits(wma->wmi_handle),
3978 wmi_get_pending_cmds(wma->wmi_handle));
Mukul Sharma93206a42016-09-03 16:18:10 +05303979 wmi_set_target_suspend(wma->wmi_handle, false);
Prashanth Bhatta9e143052015-12-04 11:56:47 -08003980 if (!cds_is_driver_recovering()) {
Yue Ma455aff62015-10-20 18:29:16 -07003981 if (pMac->sme.enableSelfRecovery) {
Mukul Sharmab7b575b2016-10-02 23:37:07 +05303982 cds_trigger_recovery(false);
Yue Ma455aff62015-10-20 18:29:16 -07003983 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303984 QDF_BUG(0);
Yue Ma455aff62015-10-20 18:29:16 -07003985 }
Yue Ma455aff62015-10-20 18:29:16 -07003986 } else {
3987 WMA_LOGE("%s: LOGP is in progress, ignore!", __func__);
3988 }
3989
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303990 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003991 }
3992
3993 if (wma->wow_nack) {
3994 WMA_LOGE("FW not ready to WOW");
3995 wmi_set_target_suspend(wma->wmi_handle, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303996 return QDF_STATUS_E_AGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003997 }
3998
3999 host_credits = wmi_get_host_credits(wma->wmi_handle);
4000 wmi_pending_cmds = wmi_get_pending_cmds(wma->wmi_handle);
4001
4002 if (host_credits < WMI_WOW_REQUIRED_CREDITS) {
4003 WMA_LOGE("%s: No Credits after HTC ACK:%d, pending_cmds:%d, "
4004 "cannot resume back", __func__, host_credits,
4005 wmi_pending_cmds);
4006 htc_dump_counter_info(wma->htc_handle);
Prashanth Bhatta9e143052015-12-04 11:56:47 -08004007 if (!cds_is_driver_recovering())
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304008 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004009 else
4010 WMA_LOGE("%s: SSR in progress, ignore no credit issue",
4011 __func__);
4012 }
4013
4014 WMA_LOGD("WOW enabled successfully in fw: credits:%d"
4015 "pending_cmds: %d", host_credits, wmi_pending_cmds);
4016
Anurag Chouhan6d760662016-02-20 16:05:43 +05304017 scn = cds_get_context(QDF_MODULE_ID_HIF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004018
4019 if (scn == NULL) {
4020 WMA_LOGE("%s: Failed to get HIF context", __func__);
Dustin Brown18179842016-09-02 15:41:58 -07004021 wmi_set_target_suspend(wma->wmi_handle, false);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304022 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304023 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004024 }
4025
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004026 wma->wow.wow_enable_cmd_sent = true;
4027
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304028 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004029
4030error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304031 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004032}
4033
4034/**
4035 * wma_resume_req() - clear configured wow patterns in fw
4036 * @wma: wma handle
Houston Hoffmana76591b2015-11-10 16:52:05 -08004037 * @type: type of suspend
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004038 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304039 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004040 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05304041QDF_STATUS wma_resume_req(tp_wma_handle wma, enum qdf_suspend_type type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004042{
Anurag Chouhan6d760662016-02-20 16:05:43 +05304043 if (type == QDF_SYSTEM_SUSPEND) {
Houston Hoffmana76591b2015-11-10 16:52:05 -08004044 wma->no_of_resume_ind++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004045
Houston Hoffmana76591b2015-11-10 16:52:05 -08004046 if (wma->no_of_resume_ind < wma_get_vdev_count(wma))
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304047 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004048
Houston Hoffmana76591b2015-11-10 16:52:05 -08004049 wma->no_of_resume_ind = 0;
4050 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004051
4052 /* Reset the DTIM Parameters */
4053 wma_set_resume_dtim(wma);
4054 /* need to reset if hif_pci_suspend_fails */
4055 wma_set_wow_bus_suspend(wma, 0);
4056 /* unpause the vdev if left paused and hif_pci_suspend fails */
4057 wma_unpause_vdev(wma);
4058
Houston Hoffman1460fa32015-11-18 02:36:30 -08004059 wmi_set_runtime_pm_inprogress(wma->wmi_handle, false);
4060
Houston Hoffmanc45db892015-11-13 19:59:25 -08004061 if (type == QDF_RUNTIME_SUSPEND)
4062 qdf_runtime_pm_allow_suspend(wma->wma_runtime_resume_lock);
4063
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304064 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004065}
4066
4067/**
4068 * wma_wow_delete_pattern() - delete wow pattern in target
4069 * @wma: wma handle
4070 * @ptrn_id: pattern id
4071 * @vdev_id: vdev id
4072 * @user: true for user pattern and false for default pattern
4073 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304074 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004075 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304076static QDF_STATUS wma_wow_delete_pattern(tp_wma_handle wma, uint8_t ptrn_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004077 uint8_t vdev_id, bool user)
4078{
Govind Singhaa64c242016-03-08 11:31:49 +05304079
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004080 struct wma_txrx_node *iface;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004081 int ret;
4082
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004083 iface = &wma->interfaces[vdev_id];
Govind Singhaa64c242016-03-08 11:31:49 +05304084 ret = wmi_unified_wow_delete_pattern_cmd(wma->wmi_handle, ptrn_id,
4085 vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004086 if (ret) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304087 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004088 }
4089
4090 if (user)
4091 iface->num_wow_user_patterns--;
4092
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304093 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004094}
4095
4096/**
4097 * wma_wow_add_pattern() - add wow pattern in target
4098 * @wma: wma handle
4099 * @ptrn: wow pattern
4100 *
4101 * This function does following:
4102 * 1) Delete all default patterns of the vdev
4103 * 2) Add received wow patterns for given vdev in target.
4104 *
4105 * Target is responsible for caching wow patterns accross multiple
4106 * suspend/resumes until the pattern is deleted by user
4107 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304108 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004109 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304110QDF_STATUS wma_wow_add_pattern(tp_wma_handle wma, struct wow_add_pattern *ptrn)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004111{
4112 uint8_t id;
4113 uint8_t bit_to_check, pos;
4114 struct wma_txrx_node *iface;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304115 QDF_STATUS ret = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004116 uint8_t new_mask[SIR_WOWL_BCAST_PATTERN_MAX_SIZE];
4117
4118 if (ptrn->session_id > wma->max_bssid) {
4119 WMA_LOGE("Invalid vdev id (%d)", ptrn->session_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304120 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004121 }
4122
4123 iface = &wma->interfaces[ptrn->session_id];
4124
4125 /* clear all default patterns cofigured by wma */
4126 for (id = 0; id < iface->num_wow_default_patterns; id++)
4127 wma_wow_delete_pattern(wma, id, ptrn->session_id, false);
4128
4129 iface->num_wow_default_patterns = 0;
4130
4131 WMA_LOGI("Add user passed wow pattern id %d vdev id %d",
4132 ptrn->pattern_id, ptrn->session_id);
4133 /*
4134 * Convert received pattern mask value from bit representation
4135 * to byte representation.
4136 *
4137 * For example, received value from umac,
4138 *
4139 * Mask value : A1 (equivalent binary is "1010 0001")
4140 * Pattern value : 12:00:13:00:00:00:00:44
4141 *
4142 * The value which goes to FW after the conversion from this
4143 * function (1 in mask value will become FF and 0 will
4144 * become 00),
4145 *
4146 * Mask value : FF:00:FF:00:0:00:00:FF
4147 * Pattern value : 12:00:13:00:00:00:00:44
4148 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304149 qdf_mem_zero(new_mask, sizeof(new_mask));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004150 for (pos = 0; pos < ptrn->pattern_size; pos++) {
4151 bit_to_check = (WMA_NUM_BITS_IN_BYTE - 1) -
4152 (pos % WMA_NUM_BITS_IN_BYTE);
4153 bit_to_check = 0x1 << bit_to_check;
4154 if (ptrn->pattern_mask[pos / WMA_NUM_BITS_IN_BYTE] &
4155 bit_to_check)
4156 new_mask[pos] = WMA_WOW_PTRN_MASK_VALID;
4157 }
4158
4159 ret = wma_send_wow_patterns_to_fw(wma, ptrn->session_id,
4160 ptrn->pattern_id,
4161 ptrn->pattern, ptrn->pattern_size,
4162 ptrn->pattern_byte_offset, new_mask,
4163 ptrn->pattern_size, true);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304164 if (ret != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004165 WMA_LOGE("Failed to add wow pattern %d", ptrn->pattern_id);
4166
4167 return ret;
4168}
4169
4170/**
4171 * wma_wow_delete_user_pattern() - delete user configured wow pattern in target
4172 * @wma: wma handle
4173 * @ptrn: wow pattern
4174 *
4175 * This function does following:
4176 * 1) Deletes a particular user configured wow pattern in target
4177 * 2) After deleting all user wow patterns add default wow patterns
4178 * specific to that vdev.
4179 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304180 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004181 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304182QDF_STATUS wma_wow_delete_user_pattern(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004183 struct wow_delete_pattern *pattern)
4184{
4185 struct wma_txrx_node *iface;
4186
4187 if (pattern->session_id > wma->max_bssid) {
4188 WMA_LOGE("Invalid vdev id %d", pattern->session_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304189 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004190 }
4191
4192 iface = &wma->interfaces[pattern->session_id];
4193 if (iface->num_wow_user_patterns <= 0) {
4194 WMA_LOGE("No valid user pattern. Num user pattern %u vdev %d",
4195 iface->num_wow_user_patterns, pattern->session_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304196 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004197 }
4198
4199 WMA_LOGI("Delete user passed wow pattern id %d total user pattern %d",
4200 pattern->pattern_id, iface->num_wow_user_patterns);
4201
4202 wma_wow_delete_pattern(wma, pattern->pattern_id,
4203 pattern->session_id, true);
4204
4205 /* configure default patterns once all user patterns are deleted */
4206 if (!iface->num_wow_user_patterns)
4207 wma_register_wow_default_patterns(wma, pattern->session_id);
4208
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304209 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004210}
4211
4212/**
4213 * wma_wow_enter() - store enable/disable status for pattern
4214 * @wma: wma handle
4215 * @info: wow parameters
4216 *
4217 * Records pattern enable/disable status locally. This choice will
4218 * take effect when the driver enter into suspend state.
4219 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304220 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004221 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304222QDF_STATUS wma_wow_enter(tp_wma_handle wma, tpSirHalWowlEnterParams info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004223{
4224 struct wma_txrx_node *iface;
4225
4226 WMA_LOGD("wow enable req received for vdev id: %d", info->sessionId);
4227
4228 if (info->sessionId > wma->max_bssid) {
4229 WMA_LOGE("Invalid vdev id (%d)", info->sessionId);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304230 qdf_mem_free(info);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304231 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004232 }
4233
4234 iface = &wma->interfaces[info->sessionId];
4235 iface->ptrn_match_enable = info->ucPatternFilteringEnable ?
4236 true : false;
4237 wma->wow.magic_ptrn_enable = info->ucMagicPktEnable ? true : false;
4238 wma->wow.deauth_enable = info->ucWowDeauthRcv ? true : false;
4239 wma->wow.disassoc_enable = info->ucWowDeauthRcv ? true : false;
4240 wma->wow.bmiss_enable = info->ucWowMaxMissedBeacons ? true : false;
4241
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304242 qdf_mem_free(info);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004243
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304244 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004245}
4246
4247/**
4248 * wma_wow_exit() - clear all wma states
4249 * @wma: wma handle
4250 * @info: wow params
4251 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304252 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004253 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304254QDF_STATUS wma_wow_exit(tp_wma_handle wma, tpSirHalWowlExitParams info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004255{
4256 struct wma_txrx_node *iface;
4257
4258 WMA_LOGD("wow disable req received for vdev id: %d", info->sessionId);
4259
4260 if (info->sessionId > wma->max_bssid) {
4261 WMA_LOGE("Invalid vdev id (%d)", info->sessionId);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304262 qdf_mem_free(info);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304263 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004264 }
4265
4266 iface = &wma->interfaces[info->sessionId];
4267 iface->ptrn_match_enable = false;
4268 wma->wow.magic_ptrn_enable = false;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304269 qdf_mem_free(info);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004270
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304271 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004272}
4273
4274/**
Houston Hoffmana76591b2015-11-10 16:52:05 -08004275 * wma_calculate_and_update_conn_state(): calculate each interfaces conn state
4276 * @wma: validated wma handle
4277 *
4278 * Identifies any vdev that is up and not in ap mode as connected.
4279 * stores this in the interfaces conn_state varible.
4280 */
4281void wma_calculate_and_update_conn_state(tp_wma_handle wma)
4282{
4283 int i;
4284 for (i = 0; i < wma->max_bssid; i++) {
4285 wma->interfaces[i].conn_state =
4286 !!(wma->interfaces[i].vdev_up &&
4287 !wma_is_vdev_in_ap_mode(wma, i));
4288 }
4289}
4290
4291/**
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004292 * wma_update_conn_state(): synchronize wma & hdd
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004293 * @wma: wma handle
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004294 * @conn_state: boolean array to populate
4295 * @len: validation parameter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004296 *
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004297 * populate interfaces conn_state with true if the interface
4298 * is a connected client and wow will configure a pattern.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004299 */
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004300void wma_update_conn_state(tp_wma_handle wma, uint32_t conn_mask)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004301{
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004302 int i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004303 for (i = 0; i < wma->max_bssid; i++) {
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004304 if (conn_mask & (1 << i))
4305 wma->interfaces[i].conn_state = true;
4306 else
4307 wma->interfaces[i].conn_state = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004308 }
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004309
4310 if (wma->wow.magic_ptrn_enable)
4311 return;
4312
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004313 for (i = 0; i < wma->max_bssid; i++) {
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004314 if (!wma->interfaces[i].ptrn_match_enable)
4315 wma->interfaces[i].conn_state = false;
4316 }
4317}
4318
4319/**
4320 * wma_is_beaconning_vdev_up(): check if a beaconning vdev is up
4321 * @wma: wma handle
4322 *
4323 * Return TRUE if beaconning vdev is up
4324 */
4325static inline
4326bool wma_is_beaconning_vdev_up(tp_wma_handle wma)
4327{
4328 int i;
4329 for (i = 0; i < wma->max_bssid; i++) {
4330 if (wma_is_vdev_in_beaconning_mode(wma, i)
4331 && wma->interfaces[i].vdev_up)
4332 return true;
4333 }
4334 return false;
4335}
4336
4337/**
4338 * wma_support_wow_for_beaconing: wow query for beaconning
4339 * @wma: wma handle
4340 *
4341 * Need to configure wow to enable beaconning offload when
4342 * a beaconing vdev is up and beaonning offload is configured.
4343 *
4344 * Return: true if we need to enable wow for beaconning offload
4345 */
4346static inline
4347bool wma_support_wow_for_beaconing(tp_wma_handle wma)
4348{
4349 if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
4350 WMI_SERVICE_BEACON_OFFLOAD)) {
4351 if (wma_is_beaconning_vdev_up(wma))
4352 return true;
4353 }
4354 return false;
4355}
4356
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004357#ifdef FEATURE_WLAN_SCAN_PNO
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004358/**
4359 * wma_is_pnoscan_in_progress(): check if a pnoscan is in progress
4360 * @wma: wma handle
4361 * @vdev_id: vdev_id
4362 *
4363 * Return: TRUE/FALSE
4364 */
4365static inline
4366bool wma_is_pnoscan_in_progress(tp_wma_handle wma, int vdev_id)
4367{
4368 return wma->interfaces[vdev_id].pno_in_progress;
4369}
Houston Hoffman345fa402015-12-16 11:28:51 -08004370
4371/**
4372 * wma_is_pnoscan_match_found(): check if a scan match was found
4373 * @wma: wma handle
4374 * @vdev_id: vdev_id
4375 *
4376 * Return: TRUE/FALSE
4377 */
4378static inline
4379bool wma_is_pnoscan_match_found(tp_wma_handle wma, int vdev_id)
4380{
4381 return wma->interfaces[vdev_id].nlo_match_evt_received;
4382}
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004383#else
4384/**
4385 * wma_is_pnoscan_in_progress(): dummy
4386 *
Houston Hoffman345fa402015-12-16 11:28:51 -08004387 * Return: False since no pnoscan cannot be in progress
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004388 * when feature flag is not defined.
4389 */
4390bool wma_is_pnoscan_in_progress(tp_wma_handle wma, int vdev_id)
4391{
4392 return FALSE;
4393}
Houston Hoffman345fa402015-12-16 11:28:51 -08004394
4395/**
4396 * wma_is_pnoscan_match_found(): dummy
4397 * @wma: wma handle
4398 * @vdev_id: vdev_id
4399 *
4400 * Return: False since no pnoscan cannot occur
4401 * when feature flag is not defined.
4402 */
4403static inline
4404bool wma_is_pnoscan_match_found(tp_wma_handle wma, int vdev_id)
4405{
4406 return FALSE;
4407}
Houston Hoffman61667962015-12-15 20:15:41 -08004408#endif
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004409
4410#ifdef FEATURE_WLAN_EXTSCAN
4411static inline
4412/**
4413 * wma_is_extscan_in_progress(): check if an extscan is in progress
4414 * @wma: wma handle
4415 * @vdev_id: vdev_id
4416 *
4417 * Return: TRUE/FALSvE
4418 */
4419bool wma_is_extscan_in_progress(tp_wma_handle wma, int vdev_id)
4420{
4421 return wma->interfaces[vdev_id].extscan_in_progress;
4422}
4423#else
4424/**
4425 * wma_is_extscan_in_progress(): dummy
4426 *
4427 * Return: False since no extscan can be in progress
4428 * when feature flag is not defined.
4429 */
4430bool wma_is_extscan_in_progress(tp_wma_handle wma, int vdev_id)
4431{
4432 return false;
4433}
4434#endif
4435
4436/**
Peng Xu8fdaa492016-06-22 10:20:47 -07004437 * wma_is_p2plo_in_progress(): check if P2P listen offload is in progress
4438 * @wma: wma handle
4439 * @vdev_id: vdev_id
4440 *
4441 * This function is to check if p2p listen offload is in progress,
4442 * true: p2p listen offload in progress
4443 * false: otherwise
4444 *
4445 * Return: TRUE/FALSE
4446 */
4447static inline
4448bool wma_is_p2plo_in_progress(tp_wma_handle wma, int vdev_id)
4449{
4450 return wma->interfaces[vdev_id].p2p_lo_in_progress;
4451}
4452
Dustin Brown18179842016-09-02 15:41:58 -07004453#ifdef WLAN_FEATURE_LPSS
4454/**
4455 * wma_is_lpass_enabled() - check if lpass is enabled
4456 * @handle: Pointer to wma handle
4457 *
4458 * WoW is needed if LPASS or NaN feature is enabled in INI because
4459 * target can't wake up itself if its put in PDEV suspend when LPASS
4460 * or NaN features are supported
4461 *
4462 * Return: true if lpass is enabled else false
4463 */
4464bool static wma_is_lpass_enabled(tp_wma_handle wma)
4465{
4466 if (wma->is_lpass_enabled)
4467 return true;
4468 else
4469 return false;
4470}
4471#else
4472bool static wma_is_lpass_enabled(tp_wma_handle wma)
4473{
4474 return false;
4475}
4476#endif
4477
4478#ifdef WLAN_FEATURE_NAN
4479/**
4480 * wma_is_nan_enabled() - check if NaN is enabled
4481 * @handle: Pointer to wma handle
4482 *
4483 * WoW is needed if LPASS or NaN feature is enabled in INI because
4484 * target can't wake up itself if its put in PDEV suspend when LPASS
4485 * or NaN features are supported
4486 *
4487 * Return: true if NaN is enabled else false
4488 */
4489bool static wma_is_nan_enabled(tp_wma_handle wma)
4490{
4491 if (wma->is_nan_enabled)
4492 return true;
4493 else
4494 return false;
4495}
4496#else
4497bool static wma_is_nan_enabled(tp_wma_handle wma)
4498{
4499 return false;
4500}
4501#endif
4502
Peng Xu8fdaa492016-06-22 10:20:47 -07004503/**
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004504 * wma_is_wow_applicable(): should enable wow
4505 * @wma: wma handle
4506 *
4507 * Enable WOW if any one of the condition meets,
4508 * 1) Is any one of vdev in beaconning mode (in AP mode) ?
4509 * 2) Is any one of vdev in connected state (in STA mode) ?
4510 * 3) Is PNO in progress in any one of vdev ?
4511 * 4) Is Extscan in progress in any one of vdev ?
Peng Xu8fdaa492016-06-22 10:20:47 -07004512 * 5) Is P2P listen offload in any one of vdev?
Naveen Rawate82c1f32016-06-22 15:34:36 -07004513 * 6) Is any vdev in NAN data mode? BSS is already started at the
4514 * the time of device creation. It is ready to accept data
4515 * requests.
Dustin Brown18179842016-09-02 15:41:58 -07004516 * 7) If LPASS feature is enabled
4517 * 8) If NaN feature is enabled
Rajeev Kumaraea89632016-02-02 18:02:32 -08004518 * If none of above conditions is true then return false
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004519 *
Rajeev Kumaraea89632016-02-02 18:02:32 -08004520 * Return: true if wma needs to configure wow false otherwise.
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004521 */
Jeff Johnsonc4b47a92016-10-07 12:34:41 -07004522static bool wma_is_wow_applicable(tp_wma_handle wma)
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004523{
4524 int vdev_id;
4525 if (wma_support_wow_for_beaconing(wma)) {
4526 WMA_LOGD("vdev is in beaconning mode, enabling wow");
4527 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004528 }
4529
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004530 for (vdev_id = 0; vdev_id < wma->max_bssid; vdev_id++) {
4531 if (wma->interfaces[vdev_id].conn_state) {
4532 WMA_LOGD("STA is connected, enabling wow");
4533 return true;
4534 } else if (wma_is_pnoscan_in_progress(wma, vdev_id)) {
4535 WMA_LOGD("PNO is in progress, enabling wow");
4536 return true;
4537 } else if (wma_is_extscan_in_progress(wma, vdev_id)) {
4538 WMA_LOGD("EXT is in progress, enabling wow");
4539 return true;
Peng Xu8fdaa492016-06-22 10:20:47 -07004540 } else if (wma_is_p2plo_in_progress(wma, vdev_id)) {
4541 WMA_LOGD("P2P LO is in progress, enabling wow");
4542 return true;
Dustin Brown18179842016-09-02 15:41:58 -07004543 } else if (wma_is_lpass_enabled(wma)) {
4544 WMA_LOGD("LPASS is enabled, enabling WoW");
4545 return true;
4546 } else if (wma_is_nan_enabled(wma)) {
4547 WMA_LOGD("NAN is enabled, enabling WoW");
4548 return true;
4549 } else if (WMA_IS_VDEV_IN_NDI_MODE(wma->interfaces, vdev_id)) {
Naveen Rawate82c1f32016-06-22 15:34:36 -07004550 WMA_LOGD("vdev %d is in NAN data mode, enabling wow",
4551 vdev_id);
4552 return true;
4553 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004554 }
4555
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004556 WMA_LOGD("All vdev are in disconnected state and pno/extscan is not in progress, skipping wow");
Rajeev Kumaraea89632016-02-02 18:02:32 -08004557 return false;
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004558}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004559
Houston Hoffman345fa402015-12-16 11:28:51 -08004560/**
4561 * wma_configure_dynamic_wake_events(): configure dyanmic wake events
4562 * @wma: wma handle
4563 *
4564 * Some wake events need to be enabled dynamically. Controll those here.
4565 *
4566 * Return: none
4567 */
Jeff Johnsonc4b47a92016-10-07 12:34:41 -07004568static void wma_configure_dynamic_wake_events(tp_wma_handle wma)
Houston Hoffman345fa402015-12-16 11:28:51 -08004569{
4570 int vdev_id;
4571 int enable_mask;
4572 int disable_mask;
4573
4574 for (vdev_id = 0; vdev_id < wma->max_bssid; vdev_id++) {
4575 enable_mask = 0;
4576 disable_mask = 0;
4577
4578 if (wma_is_pnoscan_in_progress(wma, vdev_id)) {
4579 if (wma_is_pnoscan_match_found(wma, vdev_id))
4580 enable_mask |=
4581 (1 << WOW_NLO_SCAN_COMPLETE_EVENT);
4582 else
4583 disable_mask |=
4584 (1 << WOW_NLO_SCAN_COMPLETE_EVENT);
4585 }
4586
4587 if (enable_mask != 0)
4588 wma_enable_disable_wakeup_event(wma, vdev_id,
4589 enable_mask, true);
4590 if (disable_mask != 0)
4591 wma_enable_disable_wakeup_event(wma, vdev_id,
4592 disable_mask, false);
4593 }
4594}
4595
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004596#ifdef FEATURE_WLAN_LPHB
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004597/**
4598 * wma_apply_lphb(): apply cached LPHB settings
4599 * @wma: wma handle
4600 *
4601 * LPHB cache, if any item was enabled, should be
4602 * applied.
4603 */
4604static inline
4605void wma_apply_lphb(tp_wma_handle wma)
4606{
4607 int i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004608 WMA_LOGD("%s: checking LPHB cache", __func__);
4609 for (i = 0; i < 2; i++) {
4610 if (wma->wow.lphb_cache[i].params.lphbEnableReq.enable) {
4611 WMA_LOGD("%s: LPHB cache for item %d is marked as enable",
4612 __func__, i + 1);
4613 wma_lphb_conf_hbenable(wma, &(wma->wow.lphb_cache[i]),
4614 false);
4615 }
4616 }
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004617}
4618#else
4619void wma_apply_lphb(tp_wma_handle wma) {}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004620#endif /* FEATURE_WLAN_LPHB */
4621
Houston Hoffmana76591b2015-11-10 16:52:05 -08004622static void wma_notify_suspend_req_procesed(tp_wma_handle wma,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304623 enum qdf_suspend_type type)
Houston Hoffmana76591b2015-11-10 16:52:05 -08004624{
Anurag Chouhan6d760662016-02-20 16:05:43 +05304625 if (type == QDF_SYSTEM_SUSPEND)
Houston Hoffmana76591b2015-11-10 16:52:05 -08004626 wma_send_status_to_suspend_ind(wma, true);
Anurag Chouhan6d760662016-02-20 16:05:43 +05304627 else if (type == QDF_RUNTIME_SUSPEND)
Anurag Chouhance0dc992016-02-16 18:18:03 +05304628 qdf_event_set(&wma->runtime_suspend);
Houston Hoffmana76591b2015-11-10 16:52:05 -08004629}
4630
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004631/**
4632 * wma_suspend_req() - Handles suspend indication request received from umac.
4633 * @wma: wma handle
Houston Hoffmana76591b2015-11-10 16:52:05 -08004634 * @type: type of suspend
4635 *
4636 * The type controlls how we notify the indicator that the indication has
4637 * been processed
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004638 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304639 * Return: QDF status
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004640 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05304641QDF_STATUS wma_suspend_req(tp_wma_handle wma, enum qdf_suspend_type type)
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004642{
Anurag Chouhan6d760662016-02-20 16:05:43 +05304643 if (type == QDF_RUNTIME_SUSPEND)
Houston Hoffman1460fa32015-11-18 02:36:30 -08004644 wmi_set_runtime_pm_inprogress(wma->wmi_handle, true);
4645
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004646 if (wma_is_wow_applicable(wma)) {
Dustin Brown2d228232016-09-22 15:06:19 -07004647 WMA_LOGI("WOW Suspend");
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004648 wma_apply_lphb(wma);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004649
Houston Hoffman345fa402015-12-16 11:28:51 -08004650 wma_configure_dynamic_wake_events(wma);
4651
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004652 wma->wow.wow_enable = true;
4653 wma->wow.wow_enable_cmd_sent = false;
4654 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004655
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004656 /* Set the Suspend DTIM Parameters */
4657 wma_set_suspend_dtim(wma);
Houston Hoffmana76591b2015-11-10 16:52:05 -08004658
4659 wma_notify_suspend_req_procesed(wma, type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004660
4661 /* to handle race between hif_pci_suspend and
4662 * unpause/pause tx handler
4663 */
4664 wma_set_wow_bus_suspend(wma, 1);
4665
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304666 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004667}
4668
4669/**
4670 * wma_send_host_wakeup_ind_to_fw() - send wakeup ind to fw
4671 * @wma: wma handle
4672 *
4673 * Sends host wakeup indication to FW. On receiving this indication,
4674 * FW will come out of WOW.
4675 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304676 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004677 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304678static QDF_STATUS wma_send_host_wakeup_ind_to_fw(tp_wma_handle wma)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004679{
Anurag Chouhance0dc992016-02-16 18:18:03 +05304680 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004681 int ret;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304682 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004683 if (NULL == pMac) {
4684 WMA_LOGE("%s: Unable to get PE context", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304685 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004686 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004687
Anurag Chouhance0dc992016-02-16 18:18:03 +05304688 qdf_event_reset(&wma->wma_resume_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004689
Govind Singhaa64c242016-03-08 11:31:49 +05304690 ret = wmi_unified_host_wakeup_ind_to_fw_cmd(wma->wmi_handle);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004691 if (ret) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304692 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004693 }
4694
4695 WMA_LOGD("Host wakeup indication sent to fw");
4696
Anurag Chouhance0dc992016-02-16 18:18:03 +05304697 qdf_status = qdf_wait_single_event(&(wma->wma_resume_event),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004698 WMA_RESUME_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05304699 if (QDF_STATUS_SUCCESS != qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004700 WMA_LOGP("%s: Timeout waiting for resume event from FW",
4701 __func__);
4702 WMA_LOGP("%s: Pending commands %d credits %d", __func__,
4703 wmi_get_pending_cmds(wma->wmi_handle),
4704 wmi_get_host_credits(wma->wmi_handle));
Prashanth Bhatta9e143052015-12-04 11:56:47 -08004705 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004706 if (pMac->sme.enableSelfRecovery) {
Mukul Sharmab7b575b2016-10-02 23:37:07 +05304707 cds_trigger_recovery(false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004708 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304709 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004710 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004711 } else {
4712 WMA_LOGE("%s: SSR in progress, ignore resume timeout",
4713 __func__);
4714 }
4715 } else {
4716 WMA_LOGD("Host wakeup received");
4717 }
4718
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304719 if (QDF_STATUS_SUCCESS == qdf_status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004720 wmi_set_target_suspend(wma->wmi_handle, false);
4721
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304722 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004723}
4724
4725/**
4726 * wma_disable_wow_in_fw() - Disable wow in PCIe resume context.
4727 * @handle: wma handle
4728 *
4729 * Return: 0 for success or error code
4730 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304731QDF_STATUS wma_disable_wow_in_fw(WMA_HANDLE handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004732{
4733 tp_wma_handle wma = handle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304734 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004735
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004736 ret = wma_send_host_wakeup_ind_to_fw(wma);
4737
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304738 if (ret != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004739 return ret;
4740
4741 wma->wow.wow_enable = false;
4742 wma->wow.wow_enable_cmd_sent = false;
4743
4744 /* To allow the tx pause/unpause events */
4745 wma_set_wow_bus_suspend(wma, 0);
4746 /* Unpause the vdev as we are resuming */
4747 wma_unpause_vdev(wma);
4748
4749 return ret;
4750}
4751
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004752
4753/**
4754 * wma_is_wow_mode_selected() - check if wow needs to be enabled in fw
4755 * @handle: Pointer to wma handle
4756 *
4757 * If lpass is enabled then always do wow else check wow_enable config
4758 *
4759 * Return: true is wow mode is needed else false
4760 */
Houston Hoffmana76591b2015-11-10 16:52:05 -08004761bool wma_is_wow_mode_selected(WMA_HANDLE handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004762{
4763 tp_wma_handle wma = (tp_wma_handle) handle;
Dustin Brown18179842016-09-02 15:41:58 -07004764 WMA_LOGD("WoW enable %d", wma->wow.wow_enable);
4765 return wma->wow.wow_enable;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004766}
4767
4768/**
4769 * wma_del_ts_req() - send DELTS request to fw
4770 * @wma: wma handle
4771 * @msg: delts params
4772 *
4773 * Return: none
4774 */
4775void wma_del_ts_req(tp_wma_handle wma, tDelTsParams *msg)
4776{
Govind Singhaa64c242016-03-08 11:31:49 +05304777 if (wmi_unified_del_ts_cmd(wma->wmi_handle,
4778 msg->sessionId,
4779 TID_TO_WME_AC(msg->userPrio))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004780 WMA_LOGP("%s: Failed to send vdev DELTS command", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004781 }
Govind Singhaa64c242016-03-08 11:31:49 +05304782
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004783#ifdef WLAN_FEATURE_ROAM_OFFLOAD
4784 if (msg->setRICparams == true)
4785 wma_set_ric_req(wma, msg, false);
4786#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
4787
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304788 qdf_mem_free(msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004789}
4790
4791/**
4792 * wma_aggr_qos_req() - send aggr qos request to fw
4793 * @wma: handle to wma
4794 * @pAggrQosRspMsg - combined struct for all ADD_TS requests.
4795 *
4796 * A function to handle WMA_AGGR_QOS_REQ. This will send out
4797 * ADD_TS requestes to firmware in loop for all the ACs with
4798 * active flow.
4799 *
4800 * Return: none
4801 */
4802void wma_aggr_qos_req(tp_wma_handle wma,
4803 tAggrAddTsParams *pAggrQosRspMsg)
4804{
Govind Singhaa64c242016-03-08 11:31:49 +05304805 wmi_unified_aggr_qos_cmd(wma->wmi_handle,
4806 (struct aggr_add_ts_param *)pAggrQosRspMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004807 /* send reponse to upper layers from here only. */
4808 wma_send_msg(wma, WMA_AGGR_QOS_RSP, pAggrQosRspMsg, 0);
4809}
4810
Mahesh Kumar Kalikot Veetil40575112016-09-09 16:57:08 -07004811#ifdef FEATURE_WLAN_ESE
4812/**
4813 * wma_set_tsm_interval() - Set TSM interval
4814 * @req: pointer to ADDTS request
4815 *
4816 * Return: QDF_STATUS_E_FAILURE or QDF_STATUS_SUCCESS
4817 */
4818static QDF_STATUS wma_set_tsm_interval(tAddTsParams *req)
4819{
4820 /*
4821 * msmt_interval is in unit called TU (1 TU = 1024 us)
4822 * max value of msmt_interval cannot make resulting
4823 * interval_milliseconds overflow 32 bit
4824 *
4825 */
4826 uint32_t interval_milliseconds;
Leo Chang96464902016-10-28 11:10:54 -07004827 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Mahesh Kumar Kalikot Veetil40575112016-09-09 16:57:08 -07004828 if (NULL == pdev) {
4829 WMA_LOGE("%s: Failed to get pdev", __func__);
4830 return QDF_STATUS_E_FAILURE;
4831 }
4832
4833 interval_milliseconds = (req->tsm_interval * 1024) / 1000;
4834
Leo Chang96464902016-10-28 11:10:54 -07004835 cdp_tx_set_compute_interval(cds_get_context(QDF_MODULE_ID_SOC),
4836 pdev, interval_milliseconds);
Mahesh Kumar Kalikot Veetil40575112016-09-09 16:57:08 -07004837 return QDF_STATUS_SUCCESS;
4838}
4839#else
4840static inline QDF_STATUS wma_set_tsm_interval(tAddTsParams *req)
4841{
4842 return QDF_STATUS_SUCCESS;
4843}
4844#endif /* FEATURE_WLAN_ESE */
4845
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004846/**
4847 * wma_add_ts_req() - send ADDTS request to fw
4848 * @wma: wma handle
4849 * @msg: ADDTS params
4850 *
4851 * Return: none
4852 */
4853void wma_add_ts_req(tp_wma_handle wma, tAddTsParams *msg)
4854{
Govind Singhaa64c242016-03-08 11:31:49 +05304855 struct add_ts_param cmd = {0};
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304856 msg->status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004857
Mahesh Kumar Kalikot Veetil40575112016-09-09 16:57:08 -07004858 if (wma_set_tsm_interval(msg) == QDF_STATUS_SUCCESS) {
Govind Singhaa64c242016-03-08 11:31:49 +05304859
Mahesh Kumar Kalikot Veetil40575112016-09-09 16:57:08 -07004860 cmd.sme_session_id = msg->sme_session_id;
4861 cmd.tspec.tsinfo.traffic.userPrio =
Govind Singhaa64c242016-03-08 11:31:49 +05304862 TID_TO_WME_AC(msg->tspec.tsinfo.traffic.userPrio);
Mahesh Kumar Kalikot Veetil40575112016-09-09 16:57:08 -07004863 cmd.tspec.mediumTime = msg->tspec.mediumTime;
4864 if (wmi_unified_add_ts_cmd(wma->wmi_handle, &cmd))
4865 msg->status = QDF_STATUS_E_FAILURE;
Govind Singhaa64c242016-03-08 11:31:49 +05304866
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004867#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Mahesh Kumar Kalikot Veetil40575112016-09-09 16:57:08 -07004868 if (msg->setRICparams == true)
4869 wma_set_ric_req(wma, msg, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004870#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
4871
Mahesh Kumar Kalikot Veetil40575112016-09-09 16:57:08 -07004872 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004873 wma_send_msg(wma, WMA_ADD_TS_RSP, msg, 0);
4874}
4875
4876/**
4877 * wma_enable_disable_packet_filter() - enable/disable packet filter in target
4878 * @wma: Pointer to wma handle
4879 * @vdev_id: vdev id
4880 * @enable: Flag to enable/disable packet filter
4881 *
4882 * Return: 0 for success or error code
4883 */
4884static int wma_enable_disable_packet_filter(tp_wma_handle wma,
4885 uint8_t vdev_id, bool enable)
4886{
Govind Singhaa64c242016-03-08 11:31:49 +05304887 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004888
Govind Singhaa64c242016-03-08 11:31:49 +05304889 ret = wmi_unified_enable_disable_packet_filter_cmd(wma->wmi_handle,
4890 vdev_id, enable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004891 if (ret)
4892 WMA_LOGE("Failed to send packet filter wmi cmd to fw");
4893
4894 return ret;
4895}
4896
4897/**
4898 * wma_config_packet_filter() - configure packet filter in target
4899 * @wma: Pointer to wma handle
4900 * @vdev_id: vdev id
4901 * @rcv_filter_param: Packet filter parameters
4902 * @filter_id: Filter id
4903 * @enable: Flag to add/delete packet filter configuration
4904 *
4905 * Return: 0 for success or error code
4906 */
4907static int wma_config_packet_filter(tp_wma_handle wma,
4908 uint8_t vdev_id, tSirRcvPktFilterCfgType *rcv_filter_param,
4909 uint8_t filter_id, bool enable)
4910{
Govind Singhaa64c242016-03-08 11:31:49 +05304911 int err;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004912
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004913 /* send the command along with data */
Govind Singhaa64c242016-03-08 11:31:49 +05304914 err = wmi_unified_config_packet_filter_cmd(wma->wmi_handle,
4915 vdev_id, (struct rcv_pkt_filter_config *)rcv_filter_param,
4916 filter_id, enable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004917 if (err) {
4918 WMA_LOGE("Failed to send pkt_filter cmd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004919 return -EIO;
4920 }
4921
4922 /* Enable packet filter */
4923 if (enable)
4924 wma_enable_disable_packet_filter(wma, vdev_id, true);
4925
4926 return 0;
4927}
4928
4929/**
4930 * wma_process_receive_filter_set_filter_req() - enable packet filter
4931 * @wma_handle: wma handle
4932 * @rcv_filter_param: filter params
4933 *
4934 * Return: 0 for success or error code
4935 */
4936int wma_process_receive_filter_set_filter_req(tp_wma_handle wma,
4937 tSirRcvPktFilterCfgType *rcv_filter_param)
4938{
4939 int ret = 0;
4940 uint8_t vdev_id;
4941
4942 /* Get the vdev id */
Srinivas Girigowda98530492015-11-20 17:39:24 -08004943 if (!wma_find_vdev_by_bssid(wma,
4944 rcv_filter_param->bssid.bytes, &vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004945 WMA_LOGE("vdev handle is invalid for %pM",
Srinivas Girigowda98530492015-11-20 17:39:24 -08004946 rcv_filter_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004947 return -EINVAL;
4948 }
4949
4950 ret = wma_config_packet_filter(wma, vdev_id, rcv_filter_param,
4951 rcv_filter_param->filterId, true);
4952
4953 return ret;
4954}
4955
4956/**
4957 * wma_process_receive_filter_clear_filter_req() - disable packet filter
4958 * @wma_handle: wma handle
4959 * @rcv_clear_param: filter params
4960 *
4961 * Return: 0 for success or error code
4962 */
4963int wma_process_receive_filter_clear_filter_req(tp_wma_handle wma,
4964 tSirRcvFltPktClearParam *rcv_clear_param)
4965{
4966 int ret = 0;
4967 uint8_t vdev_id;
4968
4969 /* Get the vdev id */
Srinivas Girigowda98530492015-11-20 17:39:24 -08004970 if (!wma_find_vdev_by_bssid(wma,
4971 rcv_clear_param->bssid.bytes, &vdev_id)) {
4972 WMA_LOGE("vdev handle is invalid for %pM",
4973 rcv_clear_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004974 return -EINVAL;
4975 }
4976
4977 ret = wma_config_packet_filter(wma, vdev_id, NULL,
4978 rcv_clear_param->filterId, false);
4979
4980 return ret;
4981}
4982
4983#ifdef FEATURE_WLAN_ESE
4984
4985#define TSM_DELAY_HISTROGRAM_BINS 4
4986/**
4987 * wma_process_tsm_stats_req() - process tsm stats request
4988 * @wma_handler - handle to wma
4989 * @pTsmStatsMsg - TSM stats struct that needs to be populated and
4990 * passed in message.
4991 *
4992 * A parallel function to WMA_ProcessTsmStatsReq for pronto. This
4993 * function fetches stats from data path APIs and post
4994 * WMA_TSM_STATS_RSP msg back to LIM.
4995 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304996 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004997 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304998QDF_STATUS wma_process_tsm_stats_req(tp_wma_handle wma_handler,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004999 void *pTsmStatsMsg)
5000{
5001 uint8_t counter;
5002 uint32_t queue_delay_microsec = 0;
5003 uint32_t tx_delay_microsec = 0;
5004 uint16_t packet_count = 0;
5005 uint16_t packet_loss_count = 0;
5006 tpAniTrafStrmMetrics pTsmMetric = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005007 tpAniGetTsmStatsReq pStats = (tpAniGetTsmStatsReq) pTsmStatsMsg;
5008 tpAniGetTsmStatsRsp pTsmRspParams = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005009 int tid = pStats->tid;
5010 /*
5011 * The number of histrogram bin report by data path api are different
5012 * than required by TSM, hence different (6) size array used
5013 */
5014 uint16_t bin_values[QCA_TX_DELAY_HIST_REPORT_BINS] = { 0, };
Leo Chang96464902016-10-28 11:10:54 -07005015 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
5016 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005017
5018 if (NULL == pdev) {
5019 WMA_LOGE("%s: Failed to get pdev", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305020 qdf_mem_free(pTsmStatsMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305021 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005022 }
5023
5024 /* get required values from data path APIs */
Leo Chang96464902016-10-28 11:10:54 -07005025 cdp_tx_delay(soc, pdev, &queue_delay_microsec, &tx_delay_microsec, tid);
5026 cdp_tx_delay_hist(soc, pdev, bin_values, tid);
5027 cdp_tx_packet_count(soc, pdev, &packet_count, &packet_loss_count, tid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005028
Srinivas Girigowda515a9ef2015-12-11 11:00:48 -08005029 pTsmRspParams = qdf_mem_malloc(sizeof(*pTsmRspParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005030 if (NULL == pTsmRspParams) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305031 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305032 "%s: QDF MEM Alloc Failure", __func__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305033 QDF_ASSERT(0);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305034 qdf_mem_free(pTsmStatsMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305035 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005036 }
5037 pTsmRspParams->staId = pStats->staId;
5038 pTsmRspParams->rc = eSIR_FAILURE;
5039 pTsmRspParams->tsmStatsReq = pStats;
5040 pTsmMetric = &pTsmRspParams->tsmMetrics;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005041 /* populate pTsmMetric */
5042 pTsmMetric->UplinkPktQueueDly = queue_delay_microsec;
5043 /* store only required number of bin values */
5044 for (counter = 0; counter < TSM_DELAY_HISTROGRAM_BINS; counter++) {
5045 pTsmMetric->UplinkPktQueueDlyHist[counter] =
5046 bin_values[counter];
5047 }
5048 pTsmMetric->UplinkPktTxDly = tx_delay_microsec;
5049 pTsmMetric->UplinkPktLoss = packet_loss_count;
5050 pTsmMetric->UplinkPktCount = packet_count;
5051
5052 /*
5053 * No need to populate roaming delay and roaming count as they are
5054 * being populated just before sending IAPP frame out
5055 */
5056 /* post this message to LIM/PE */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005057 wma_send_msg(wma_handler, WMA_TSM_STATS_RSP, (void *)pTsmRspParams, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305058 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005059}
5060
5061#endif /* FEATURE_WLAN_ESE */
5062
5063/**
5064 * wma_add_clear_mcbc_filter() - set mcast filter command to fw
5065 * @wma_handle: wma handle
5066 * @vdev_id: vdev id
5067 * @multicastAddr: mcast address
5068 * @clearList: clear list flag
5069 *
5070 * Return: 0 for success or error code
5071 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05305072static QDF_STATUS wma_add_clear_mcbc_filter(tp_wma_handle wma_handle,
5073 uint8_t vdev_id,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305074 struct qdf_mac_addr multicast_addr,
Srinivas Girigowda98530492015-11-20 17:39:24 -08005075 bool clearList)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005076{
Himanshu Agarwal44195412016-03-09 13:03:54 +05305077 return wmi_unified_add_clear_mcbc_filter_cmd(wma_handle->wmi_handle,
5078 vdev_id, multicast_addr, clearList);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005079}
5080
5081/**
Rajeev Kumaref96e152016-04-15 18:10:33 -07005082 * wma_config_enhance_multicast_offload() - config enhance multicast offload
5083 * @wma_handle: wma handle
5084 * @vdev_id: vdev id
5085 * @action: enable or disable enhance multicast offload
5086 *
5087 * Return: none
5088 */
5089static void wma_config_enhance_multicast_offload(tp_wma_handle wma_handle,
5090 uint8_t vdev_id,
5091 uint8_t action)
5092{
5093 int status;
5094 wmi_buf_t buf;
5095 wmi_config_enhanced_mcast_filter_cmd_fixed_param *cmd;
5096
5097 buf = wmi_buf_alloc(wma_handle->wmi_handle, sizeof(*cmd));
5098 if (!buf) {
5099 WMA_LOGE("Failed to allocate buffer to send set key cmd");
5100 return;
5101 }
5102
5103 cmd = (wmi_config_enhanced_mcast_filter_cmd_fixed_param *)
5104 wmi_buf_data(buf);
5105
5106 WMITLV_SET_HDR(&cmd->tlv_header,
5107 WMITLV_TAG_STRUC_wmi_config_enhanced_mcast_filter_fixed_param,
5108 WMITLV_GET_STRUCT_TLVLEN(wmi_config_enhanced_mcast_filter_cmd_fixed_param));
5109
5110 cmd->vdev_id = vdev_id;
5111 cmd->enable = ((0 == action) ? ENHANCED_MCAST_FILTER_DISABLED :
5112 ENHANCED_MCAST_FILTER_ENABLED);
5113
5114 WMA_LOGD("%s: config enhance multicast offload action %d for vdev %d",
5115 __func__, action, vdev_id);
5116
5117 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
5118 sizeof(*cmd), WMI_CONFIG_ENHANCED_MCAST_FILTER_CMDID);
5119 if (status) {
5120 qdf_nbuf_free(buf);
5121 WMA_LOGE("%s:Failed to send WMI_CONFIG_ENHANCED_MCAST_FILTER_CMDID",
5122 __func__);
5123 }
5124
5125 return;
5126}
5127
5128/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005129 * wma_process_mcbc_set_filter_req() - process mcbc set filter request
5130 * @wma_handle: wma handle
5131 * @mcbc_param: mcbc params
5132 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305133 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005134 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305135QDF_STATUS wma_process_mcbc_set_filter_req(tp_wma_handle wma_handle,
Anurag Chouhance0dc992016-02-16 18:18:03 +05305136 tSirRcvFltMcAddrList *mcbc_param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005137{
5138 uint8_t vdev_id = 0;
5139 int i;
5140
5141 if (mcbc_param->ulMulticastAddrCnt <= 0) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08005142 WMA_LOGW("Number of multicast addresses is 0");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305143 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005144 }
5145
Srinivas Girigowda98530492015-11-20 17:39:24 -08005146 if (!wma_find_vdev_by_addr(wma_handle,
5147 mcbc_param->self_macaddr.bytes, &vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005148 WMA_LOGE("%s: Failed to find vdev id for %pM", __func__,
Srinivas Girigowda98530492015-11-20 17:39:24 -08005149 mcbc_param->bssid.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305150 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005151 }
Rajeev Kumaref96e152016-04-15 18:10:33 -07005152
5153 /*
5154 * Configure enhance multicast offload feature for filtering out
5155 * multicast IP data packets transmitted using unicast MAC address
5156 */
5157 if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap,
5158 WMI_SERVICE_ENHANCED_MCAST_FILTER)) {
5159 WMA_LOGD("%s: FW supports enhance multicast offload", __func__);
5160 wma_config_enhance_multicast_offload(wma_handle, vdev_id,
5161 mcbc_param->action);
5162 } else {
5163 WMA_LOGD("%s: FW does not support enhance multicast offload",
5164 __func__);
5165 }
5166
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005167 /* set mcbc_param->action to clear MCList and reset
5168 * to configure the MCList in FW
5169 */
5170
5171 for (i = 0; i < mcbc_param->ulMulticastAddrCnt; i++) {
5172 wma_add_clear_mcbc_filter(wma_handle, vdev_id,
5173 mcbc_param->multicastAddr[i],
5174 (mcbc_param->action == 0));
5175 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305176 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005177}
5178
5179#ifdef WLAN_FEATURE_GTK_OFFLOAD
5180#define GTK_OFFLOAD_ENABLE 0
5181#define GTK_OFFLOAD_DISABLE 1
5182
5183/**
5184 * wma_gtk_offload_status_event() - GTK offload status event handler
5185 * @handle: wma handle
5186 * @event: event buffer
5187 * @len: buffer length
5188 *
5189 * Return: 0 for success or error code
5190 */
5191int wma_gtk_offload_status_event(void *handle, uint8_t *event,
5192 uint32_t len)
5193{
5194 tp_wma_handle wma = (tp_wma_handle) handle;
5195 WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param *status;
5196 WMI_GTK_OFFLOAD_STATUS_EVENTID_param_tlvs *param_buf;
5197 tpSirGtkOffloadGetInfoRspParams resp;
5198 cds_msg_t cds_msg;
5199 uint8_t *bssid;
5200
5201 WMA_LOGD("%s Enter", __func__);
5202
5203 param_buf = (WMI_GTK_OFFLOAD_STATUS_EVENTID_param_tlvs *) event;
5204 if (!param_buf) {
5205 WMA_LOGE("param_buf is NULL");
5206 return -EINVAL;
5207 }
5208
5209 status = (WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param *) param_buf->fixed_param;
5210
5211 if (len < sizeof(WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param)) {
5212 WMA_LOGE("Invalid length for GTK status");
5213 return -EINVAL;
5214 }
5215 bssid = wma_find_bssid_by_vdev_id(wma, status->vdev_id);
5216 if (!bssid) {
5217 WMA_LOGE("invalid bssid for vdev id %d", status->vdev_id);
5218 return -ENOENT;
5219 }
5220
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305221 resp = qdf_mem_malloc(sizeof(*resp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005222 if (!resp) {
5223 WMA_LOGE("%s: Failed to alloc response", __func__);
5224 return -ENOMEM;
5225 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305226 qdf_mem_zero(resp, sizeof(*resp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005227 resp->mesgType = eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP;
5228 resp->mesgLen = sizeof(*resp);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305229 resp->ulStatus = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005230 resp->ulTotalRekeyCount = status->refresh_cnt;
5231 /* TODO: Is the total rekey count and GTK rekey count same? */
5232 resp->ulGTKRekeyCount = status->refresh_cnt;
5233
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305234 qdf_mem_copy(&resp->ullKeyReplayCounter, &status->replay_counter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005235 GTK_REPLAY_COUNTER_BYTES);
5236
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305237 qdf_mem_copy(resp->bssid.bytes, bssid, IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005238
5239#ifdef IGTK_OFFLOAD
5240 /* TODO: Is the refresh count same for GTK and IGTK? */
5241 resp->ulIGTKRekeyCount = status->refresh_cnt;
5242#endif /* IGTK_OFFLOAD */
5243
5244 cds_msg.type = eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP;
5245 cds_msg.bodyptr = (void *)resp;
5246 cds_msg.bodyval = 0;
5247
Krunal Soni66c113f2016-12-21 16:46:47 -08005248 if (cds_mq_post_message(QDF_MODULE_ID_SME, (cds_msg_t *) &cds_msg)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305249 != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005250 WMA_LOGE("Failed to post GTK response to SME");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305251 qdf_mem_free(resp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005252 return -EINVAL;
5253 }
5254
5255 WMA_LOGD("GTK: got target status with replay counter "
5256 "%02x%02x%02x%02x%02x%02x%02x%02x. vdev %d "
5257 "Refresh GTK %d times exchanges since last set operation",
5258 status->replay_counter[0],
5259 status->replay_counter[1],
5260 status->replay_counter[2],
5261 status->replay_counter[3],
5262 status->replay_counter[4],
5263 status->replay_counter[5],
5264 status->replay_counter[6],
5265 status->replay_counter[7],
5266 status->vdev_id, status->refresh_cnt);
5267
5268 WMA_LOGD("%s Exit", __func__);
5269
5270 return 0;
5271}
5272
5273/**
5274 * wma_send_gtk_offload_req() - send GTK offload command to fw
5275 * @wma: wma handle
5276 * @vdev_id: vdev id
5277 * @params: GTK offload parameters
5278 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305279 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005280 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305281static QDF_STATUS wma_send_gtk_offload_req(tp_wma_handle wma, uint8_t vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005282 tpSirGtkOffloadParams params)
5283{
Himanshu Agarwal44195412016-03-09 13:03:54 +05305284 struct gtk_offload_params offload_params = {0};
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305285 QDF_STATUS status = QDF_STATUS_SUCCESS;
Himanshu Agarwal44195412016-03-09 13:03:54 +05305286 bool enable_offload;
5287 uint32_t gtk_offload_opcode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005288
5289 WMA_LOGD("%s Enter", __func__);
5290
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005291 /* Request target to enable GTK offload */
5292 if (params->ulFlags == GTK_OFFLOAD_ENABLE) {
Himanshu Agarwal44195412016-03-09 13:03:54 +05305293 gtk_offload_opcode = GTK_OFFLOAD_ENABLE_OPCODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005294 wma->wow.gtk_err_enable[vdev_id] = true;
5295
5296 /* Copy the keys and replay counter */
Himanshu Agarwal44195412016-03-09 13:03:54 +05305297 qdf_mem_copy(offload_params.aKCK, params->aKCK,
5298 GTK_OFFLOAD_KCK_BYTES);
5299 qdf_mem_copy(offload_params.aKEK, params->aKEK,
5300 GTK_OFFLOAD_KEK_BYTES);
5301 qdf_mem_copy(&offload_params.ullKeyReplayCounter,
5302 &params->ullKeyReplayCounter, GTK_REPLAY_COUNTER_BYTES);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005303 } else {
5304 wma->wow.gtk_err_enable[vdev_id] = false;
Himanshu Agarwal44195412016-03-09 13:03:54 +05305305 gtk_offload_opcode = GTK_OFFLOAD_DISABLE_OPCODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005306 }
5307
Himanshu Agarwal44195412016-03-09 13:03:54 +05305308 enable_offload = params->ulFlags;
5309
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005310 /* send the wmi command */
Himanshu Agarwal44195412016-03-09 13:03:54 +05305311 status = wmi_unified_send_gtk_offload_cmd(wma->wmi_handle,
5312 vdev_id, &offload_params,
5313 enable_offload,
5314 gtk_offload_opcode);
5315 if (QDF_IS_STATUS_ERROR(status))
5316 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005317
Himanshu Agarwal44195412016-03-09 13:03:54 +05305318 WMA_LOGD("VDEVID: %d, GTK_FLAGS: x%x", vdev_id, gtk_offload_opcode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005319out:
5320 WMA_LOGD("%s Exit", __func__);
5321 return status;
5322}
5323
5324/**
5325 * wma_process_gtk_offload_req() - process GTK offload req from umac
5326 * @handle: wma handle
5327 * @params: GTK offload params
5328 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305329 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005330 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305331QDF_STATUS wma_process_gtk_offload_req(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005332 tpSirGtkOffloadParams params)
5333{
5334 uint8_t vdev_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305335 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005336
5337 WMA_LOGD("%s Enter", __func__);
5338
5339 /* Get the vdev id */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08005340 if (!wma_find_vdev_by_bssid(wma, params->bssid.bytes, &vdev_id)) {
5341 WMA_LOGE("vdev handle is invalid for %pM", params->bssid.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305342 status = QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005343 goto out;
5344 }
5345
5346 /* Validate vdev id */
Naveen Rawate9fb4ce2016-06-27 15:36:10 -07005347 if (vdev_id >= WMA_MAX_SUPPORTED_BSS) {
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08005348 WMA_LOGE("invalid vdev_id %d for %pM", vdev_id,
5349 params->bssid.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305350 status = QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005351 goto out;
5352 }
5353
5354 if ((params->ulFlags == GTK_OFFLOAD_ENABLE) &&
5355 (wma->wow.gtk_err_enable[vdev_id] == true)) {
5356 WMA_LOGE("%s GTK Offload already enabled. Disable it first "
5357 "vdev_id %d", __func__, vdev_id);
5358 params->ulFlags = GTK_OFFLOAD_DISABLE;
5359 status = wma_send_gtk_offload_req(wma, vdev_id, params);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305360 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005361 WMA_LOGE("%s Failed to disable GTK Offload", __func__);
5362 goto out;
5363 }
5364 WMA_LOGD("%s Enable GTK Offload again with updated inputs",
5365 __func__);
5366 params->ulFlags = GTK_OFFLOAD_ENABLE;
5367 }
5368 status = wma_send_gtk_offload_req(wma, vdev_id, params);
5369out:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305370 qdf_mem_free(params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005371 WMA_LOGD("%s Exit", __func__);
5372 return status;
5373}
5374
5375/**
5376 * wma_process_gtk_offload_getinfo_req() - send GTK offload cmd to fw
5377 * @wma: wma handle
5378 * @params: GTK offload params
5379 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305380 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005381 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305382QDF_STATUS wma_process_gtk_offload_getinfo_req(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005383 tpSirGtkOffloadGetInfoRspParams params)
5384{
5385 uint8_t vdev_id;
Himanshu Agarwal44195412016-03-09 13:03:54 +05305386 uint64_t offload_req_opcode;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305387 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005388
5389 WMA_LOGD("%s Enter", __func__);
5390
5391 /* Get the vdev id */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08005392 if (!wma_find_vdev_by_bssid(wma, params->bssid.bytes, &vdev_id)) {
5393 WMA_LOGE("vdev handle is invalid for %pM", params->bssid.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305394 status = QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005395 goto out;
5396 }
5397
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005398 /* Request for GTK offload status */
Himanshu Agarwal44195412016-03-09 13:03:54 +05305399 offload_req_opcode = GTK_OFFLOAD_REQUEST_STATUS_OPCODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005400
5401 /* send the wmi command */
Himanshu Agarwal44195412016-03-09 13:03:54 +05305402 status = wmi_unified_process_gtk_offload_getinfo_cmd(wma->wmi_handle,
5403 vdev_id, offload_req_opcode);
5404
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005405out:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305406 qdf_mem_free(params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005407 WMA_LOGD("%s Exit", __func__);
5408 return status;
5409}
5410#endif /* WLAN_FEATURE_GTK_OFFLOAD */
5411
5412/**
5413 * wma_enable_arp_ns_offload() - enable ARP NS offload
5414 * @wma: wma handle
5415 * @tpSirHostOffloadReq: offload request
Mukul Sharma8d2d9ec2016-09-08 13:05:35 +05305416 * @config_arp: config arp flag
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005417 *
5418 * To configure ARP NS off load data to firmware
5419 * when target goes to wow mode.
5420 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305421 * Return: QDF Status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005422 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305423QDF_STATUS wma_enable_arp_ns_offload(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005424 tpSirHostOffloadReq
Mukul Sharma8d2d9ec2016-09-08 13:05:35 +05305425 offload_req, bool config_arp)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005426{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005427 int32_t res;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005428 uint8_t vdev_id;
Mukul Sharma8d2d9ec2016-09-08 13:05:35 +05305429 tpSirHostOffloadReq ns_offload_req;
5430 tpSirHostOffloadReq arp_offload_req;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005431
5432 /* Get the vdev id */
Mukul Sharma8d2d9ec2016-09-08 13:05:35 +05305433 if (!wma_find_vdev_by_bssid(wma, offload_req->bssid.bytes,
Srinivas Girigowdab084b552015-11-24 12:39:12 -08005434 &vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005435 WMA_LOGE("vdev handle is invalid for %pM",
Mukul Sharma8d2d9ec2016-09-08 13:05:35 +05305436 offload_req->bssid.bytes);
5437 qdf_mem_free(offload_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305438 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005439 }
5440
5441 if (!wma->interfaces[vdev_id].vdev_up) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005442 WMA_LOGE("vdev %d is not up skipping arp/ns offload", vdev_id);
Mukul Sharma8d2d9ec2016-09-08 13:05:35 +05305443 qdf_mem_free(offload_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305444 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005445 }
5446
Mukul Sharma8d2d9ec2016-09-08 13:05:35 +05305447 /*
5448 * config_arp is true means arp request comes from upper layer
5449 * Hence ns request need to used from wma cached request.
5450 */
5451 if (config_arp) {
5452 arp_offload_req = offload_req;
5453 ns_offload_req = &wma->interfaces[vdev_id].ns_offload_req;
5454 WMA_LOGD(" %s: ARP Offload vdev_id: %d enable: %d",
5455 __func__, vdev_id,
5456 offload_req->enableOrDisable);
5457 } else {
5458 ns_offload_req = offload_req;
5459 arp_offload_req = &wma->interfaces[vdev_id].arp_offload_req;
5460 WMA_LOGD(" %s: NS Offload vdev_id: %d enable: %d ns_count: %u",
5461 __func__, vdev_id,
5462 offload_req->enableOrDisable,
5463 offload_req->num_ns_offload_count);
5464 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005465
Govind Singhaa64c242016-03-08 11:31:49 +05305466 res = wmi_unified_enable_arp_ns_offload_cmd(wma->wmi_handle,
Mukul Sharma8d2d9ec2016-09-08 13:05:35 +05305467 (struct host_offload_req_param *)arp_offload_req,
5468 (struct host_offload_req_param *)ns_offload_req,
5469 config_arp,
5470 vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005471 if (res) {
5472 WMA_LOGE("Failed to enable ARP NDP/NSffload");
Mukul Sharma8d2d9ec2016-09-08 13:05:35 +05305473 qdf_mem_free(offload_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305474 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005475 }
5476
Mukul Sharma8d2d9ec2016-09-08 13:05:35 +05305477 if (config_arp) {
5478 qdf_mem_copy(&wma->interfaces[vdev_id].arp_offload_req,
5479 offload_req,
5480 sizeof(wma->interfaces[vdev_id].arp_offload_req));
5481 } else {
5482 qdf_mem_copy(&wma->interfaces[vdev_id].ns_offload_req,
5483 offload_req,
5484 sizeof(wma->interfaces[vdev_id].ns_offload_req));
5485 }
5486
5487 qdf_mem_free(offload_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305488 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005489}
5490
Mukul Sharma8d2d9ec2016-09-08 13:05:35 +05305491
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005492/**
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08005493 * wma_process_cesium_enable_ind() - enables cesium functionality in target
5494 * @wma: wma handle
5495 *
5496 * Return: QDF status
5497 */
5498QDF_STATUS wma_process_cesium_enable_ind(tp_wma_handle wma)
5499{
5500 QDF_STATUS ret;
5501 int32_t vdev_id;
5502
5503 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
5504 if (vdev_id < 0) {
5505 WMA_LOGE("%s: IBSS vdev does not exist could not enable cesium",
5506 __func__);
5507 return QDF_STATUS_E_FAILURE;
5508 }
5509
5510 /* Send enable cesium command to target */
5511 WMA_LOGE("Enable cesium in target for vdevId %d ", vdev_id);
5512 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
5513 WMI_VDEV_PARAM_ENABLE_RMC, 1);
5514 if (ret) {
5515 WMA_LOGE("Enable cesium failed for vdevId %d", vdev_id);
5516 return QDF_STATUS_E_FAILURE;
5517 }
5518 return QDF_STATUS_SUCCESS;
5519}
5520
5521/**
5522 * wma_process_get_peer_info_req() - sends get peer info cmd to target
5523 * @wma: wma handle
5524 * @preq: get peer info request
5525 *
5526 * Return: QDF status
5527 */
5528QDF_STATUS wma_process_get_peer_info_req
5529 (tp_wma_handle wma, tSirIbssGetPeerInfoReqParams *pReq)
5530{
5531 int32_t ret;
5532 uint8_t *p;
5533 uint16_t len;
5534 wmi_buf_t buf;
5535 int32_t vdev_id;
Leo Chang96464902016-10-28 11:10:54 -07005536 void *pdev;
5537 void *peer;
5538 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08005539 uint8_t peer_mac[IEEE80211_ADDR_LEN];
Leo Chang96464902016-10-28 11:10:54 -07005540 uint8_t *peer_mac_raw;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08005541 wmi_peer_info_req_cmd_fixed_param *p_get_peer_info_cmd;
5542 uint8_t bcast_mac[IEEE80211_ADDR_LEN] = { 0xff, 0xff, 0xff,
5543 0xff, 0xff, 0xff };
5544
Nishank Aggarwala13b61d2016-12-01 12:53:58 +05305545 if (NULL == soc) {
5546 WMA_LOGE("%s: SOC context is NULL", __func__);
5547 return QDF_STATUS_E_FAILURE;
5548 }
5549
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08005550 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
5551 if (vdev_id < 0) {
5552 WMA_LOGE("%s: IBSS vdev does not exist could not get peer info",
5553 __func__);
5554 return QDF_STATUS_E_FAILURE;
5555 }
5556
5557 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
5558 if (NULL == pdev) {
5559 WMA_LOGE("%s: Failed to get pdev context", __func__);
5560 return QDF_STATUS_E_FAILURE;
5561 }
5562
5563 if (0xFF == pReq->staIdx) {
5564 /*get info for all peers */
5565 qdf_mem_copy(peer_mac, bcast_mac, IEEE80211_ADDR_LEN);
5566 } else {
5567 /*get info for a single peer */
Leo Chang96464902016-10-28 11:10:54 -07005568 peer = cdp_peer_find_by_local_id(soc, pdev, pReq->staIdx);
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08005569 if (!peer) {
5570 WMA_LOGE("%s: Failed to get peer handle using peer id %d",
5571 __func__, pReq->staIdx);
5572 return QDF_STATUS_E_FAILURE;
5573 }
Leo Chang96464902016-10-28 11:10:54 -07005574 peer_mac_raw = cdp_peer_get_peer_mac_addr(soc, peer);
Nishank Aggarwala13b61d2016-12-01 12:53:58 +05305575 if (peer_mac_raw == NULL) {
5576 WMA_LOGE("peer_mac_raw is NULL");
5577 return QDF_STATUS_E_FAILURE;
5578 }
5579
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08005580 WMA_LOGE("%s: staIdx %d peer mac: 0x%2x:0x%2x:0x%2x:0x%2x:0x%2x:0x%2x",
Leo Chang96464902016-10-28 11:10:54 -07005581 __func__, pReq->staIdx, peer_mac_raw[0],
5582 peer_mac_raw[1], peer_mac_raw[2],
5583 peer_mac_raw[3], peer_mac_raw[4],
5584 peer_mac_raw[5]);
5585 qdf_mem_copy(peer_mac, peer_mac_raw, IEEE80211_ADDR_LEN);
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08005586 }
5587
5588 len = sizeof(wmi_peer_info_req_cmd_fixed_param);
5589 buf = wmi_buf_alloc(wma->wmi_handle, len);
5590 if (!buf) {
5591 WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__);
5592 return QDF_STATUS_E_FAILURE;
5593 }
5594
5595 p = (uint8_t *) wmi_buf_data(buf);
5596 qdf_mem_zero(p, len);
5597 p_get_peer_info_cmd = (wmi_peer_info_req_cmd_fixed_param *) p;
5598
5599 WMITLV_SET_HDR(&p_get_peer_info_cmd->tlv_header,
5600 WMITLV_TAG_STRUC_wmi_peer_info_req_cmd_fixed_param,
5601 WMITLV_GET_STRUCT_TLVLEN
5602 (wmi_peer_info_req_cmd_fixed_param));
5603
5604 p_get_peer_info_cmd->vdev_id = vdev_id;
5605 WMI_CHAR_ARRAY_TO_MAC_ADDR(peer_mac,
5606 &p_get_peer_info_cmd->peer_mac_address);
5607
5608 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
5609 WMI_PEER_INFO_REQ_CMDID);
Dustin Brown2afb6f52016-12-02 14:47:48 -08005610 if (ret != QDF_STATUS_SUCCESS)
5611 wmi_buf_free(buf);
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08005612
5613 WMA_LOGE("IBSS get peer info cmd sent len: %d, vdev %d"
5614 " command id: %d, status: %d", len,
Dustin Brownecfae9a2016-11-15 13:01:39 -08005615 vdev_id, WMI_PEER_INFO_REQ_CMDID, ret);
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08005616
5617 return QDF_STATUS_SUCCESS;
5618}
5619
5620/**
5621 * wma_process_tx_fail_monitor_ind() - sends tx fail monitor cmd to target
5622 * @wma: wma handle
5623 * @pReq: tx fail monitor command params
5624 *
5625 * Return: QDF status
5626 */
5627QDF_STATUS wma_process_tx_fail_monitor_ind
5628 (tp_wma_handle wma, tAniTXFailMonitorInd *pReq)
5629{
5630 QDF_STATUS ret;
5631 int32_t vdev_id;
5632
5633 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
5634 if (vdev_id < 0) {
5635 WMA_LOGE("%s: IBSS vdev does not exist could not send fast tx fail"
5636 " monitor indication message to target", __func__);
5637 return QDF_STATUS_E_FAILURE;
5638 }
5639
5640 /* Send enable cesium command to target */
5641 WMA_LOGE("send fast tx fail monitor ind cmd target for vdevId %d val %d",
5642 vdev_id, pReq->tx_fail_count);
5643
5644 if (0 == pReq->tx_fail_count) {
5645 wma->hddTxFailCb = NULL;
5646 } else {
5647 wma->hddTxFailCb = pReq->txFailIndCallback;
5648 }
5649 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
5650 WMI_VDEV_PARAM_SET_IBSS_TX_FAIL_CNT_THR,
5651 pReq->tx_fail_count);
5652 if (ret) {
5653 WMA_LOGE("tx fail monitor failed for vdevId %d", vdev_id);
5654 return QDF_STATUS_E_FAILURE;
5655 }
5656
5657 return QDF_STATUS_SUCCESS;
5658}
5659
5660/**
5661 * wma_process_rmc_enable_ind() - enables RMC functionality in target
5662 * @wma: wma handle
5663 *
5664 * Return: QDF status
5665 */
5666QDF_STATUS wma_process_rmc_enable_ind(tp_wma_handle wma)
5667{
5668 int ret;
5669 uint8_t *p;
5670 uint16_t len;
5671 wmi_buf_t buf;
5672 int32_t vdev_id;
5673 wmi_rmc_set_mode_cmd_fixed_param *p_rmc_enable_cmd;
5674
5675 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
5676 if (vdev_id < 0) {
5677 WMA_LOGE("%s: IBSS vdev does not exist could not enable RMC",
5678 __func__);
5679 return QDF_STATUS_E_FAILURE;
5680 }
5681
5682 len = sizeof(wmi_rmc_set_mode_cmd_fixed_param);
5683 buf = wmi_buf_alloc(wma->wmi_handle, len);
5684 if (!buf) {
5685 WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__);
5686 return QDF_STATUS_E_FAILURE;
5687 }
5688
5689 p = (uint8_t *) wmi_buf_data(buf);
5690 qdf_mem_zero(p, len);
5691 p_rmc_enable_cmd = (wmi_rmc_set_mode_cmd_fixed_param *) p;
5692
5693 WMITLV_SET_HDR(&p_rmc_enable_cmd->tlv_header,
5694 WMITLV_TAG_STRUC_wmi_rmc_set_mode_cmd_fixed_param,
5695 WMITLV_GET_STRUCT_TLVLEN
5696 (wmi_rmc_set_mode_cmd_fixed_param));
5697
5698 p_rmc_enable_cmd->vdev_id = vdev_id;
5699 p_rmc_enable_cmd->enable_rmc = WMI_RMC_MODE_ENABLED;
5700
5701 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
5702 WMI_RMC_SET_MODE_CMDID);
Dustin Brown2afb6f52016-12-02 14:47:48 -08005703 if (ret != QDF_STATUS_SUCCESS)
5704 wmi_buf_free(buf);
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08005705
5706 WMA_LOGE("Enable RMC cmd sent len: %d, vdev %d" " command id: %d,"
Dustin Brownecfae9a2016-11-15 13:01:39 -08005707 " status: %d", len, vdev_id, WMI_RMC_SET_MODE_CMDID, ret);
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08005708
5709 return QDF_STATUS_SUCCESS;
5710}
5711
5712/**
5713 * wma_process_rmc_disable_ind() - disables rmc functionality in target
5714 * @wma: wma handle
5715 *
5716 * Return: QDF status
5717 */
5718QDF_STATUS wma_process_rmc_disable_ind(tp_wma_handle wma)
5719{
5720 int ret;
5721 uint8_t *p;
5722 uint16_t len;
5723 wmi_buf_t buf;
5724 int32_t vdev_id;
5725 wmi_rmc_set_mode_cmd_fixed_param *p_rmc_disable_cmd;
5726
5727 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
5728 if (vdev_id < 0) {
5729 WMA_LOGE("%s: IBSS vdev does not exist could not disable RMC",
5730 __func__);
5731 return QDF_STATUS_E_FAILURE;
5732 }
5733
5734 len = sizeof(wmi_rmc_set_mode_cmd_fixed_param);
5735 buf = wmi_buf_alloc(wma->wmi_handle, len);
5736 if (!buf) {
5737 WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__);
5738 return QDF_STATUS_E_FAILURE;
5739 }
5740
5741 p = (uint8_t *) wmi_buf_data(buf);
5742 qdf_mem_zero(p, len);
5743 p_rmc_disable_cmd = (wmi_rmc_set_mode_cmd_fixed_param *) p;
5744
5745 WMITLV_SET_HDR(&p_rmc_disable_cmd->tlv_header,
5746 WMITLV_TAG_STRUC_wmi_rmc_set_mode_cmd_fixed_param,
5747 WMITLV_GET_STRUCT_TLVLEN
5748 (wmi_rmc_set_mode_cmd_fixed_param));
5749
5750 p_rmc_disable_cmd->vdev_id = vdev_id;
5751 p_rmc_disable_cmd->enable_rmc = WMI_RMC_MODE_DISABLED;
5752
5753 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
5754 WMI_RMC_SET_MODE_CMDID);
Dustin Brown2afb6f52016-12-02 14:47:48 -08005755 if (ret != QDF_STATUS_SUCCESS)
5756 wmi_buf_free(buf);
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08005757
5758 WMA_LOGE("Disable RMC cmd sent len: %d, vdev %d" " command id: %d,"
Dustin Brownecfae9a2016-11-15 13:01:39 -08005759 " status: %d", len, vdev_id, WMI_RMC_SET_MODE_CMDID, ret);
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08005760
5761 return QDF_STATUS_SUCCESS;
5762}
5763
5764/**
5765 * wma_process_rmc_action_period_ind() - sends RMC action period to target
5766 * @wma: wma handle
5767 *
5768 * Return: QDF status
5769 */
5770QDF_STATUS wma_process_rmc_action_period_ind(tp_wma_handle wma)
5771{
5772 int ret;
5773 uint8_t *p;
5774 uint16_t len;
Dustin Brownecfae9a2016-11-15 13:01:39 -08005775 uint32_t periodicity_msec;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08005776 wmi_buf_t buf;
5777 int32_t vdev_id;
5778 wmi_rmc_set_action_period_cmd_fixed_param *p_rmc_cmd;
5779 struct sAniSirGlobal *mac = cds_get_context(QDF_MODULE_ID_PE);
5780
5781 if (NULL == mac) {
5782 WMA_LOGE("%s: MAC mac does not exist", __func__);
5783 return QDF_STATUS_E_FAILURE;
5784 }
5785
5786 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
5787 if (vdev_id < 0) {
5788 WMA_LOGE("%s: IBSS vdev does not exist could not send"
5789 " RMC action period to target", __func__);
5790 return QDF_STATUS_E_FAILURE;
5791 }
5792
5793 len = sizeof(wmi_rmc_set_action_period_cmd_fixed_param);
5794 buf = wmi_buf_alloc(wma->wmi_handle, len);
5795 if (!buf) {
5796 WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__);
5797 return QDF_STATUS_E_FAILURE;
5798 }
5799
5800 p = (uint8_t *) wmi_buf_data(buf);
5801 qdf_mem_zero(p, len);
5802 p_rmc_cmd = (wmi_rmc_set_action_period_cmd_fixed_param *) p;
5803
5804 WMITLV_SET_HDR(&p_rmc_cmd->tlv_header,
5805 WMITLV_TAG_STRUC_wmi_rmc_set_action_period_cmd_fixed_param,
5806 WMITLV_GET_STRUCT_TLVLEN
5807 (wmi_rmc_set_action_period_cmd_fixed_param));
5808
Dustin Brownecfae9a2016-11-15 13:01:39 -08005809 if (wlan_cfg_get_int(mac, WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY,
5810 &periodicity_msec) != eSIR_SUCCESS) {
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08005811 WMA_LOGE("Failed to get value for RMC action period using default");
Dustin Brownecfae9a2016-11-15 13:01:39 -08005812 periodicity_msec = WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_STADEF;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08005813 }
5814
5815 p_rmc_cmd->vdev_id = vdev_id;
Dustin Brownecfae9a2016-11-15 13:01:39 -08005816 p_rmc_cmd->periodicity_msec = periodicity_msec;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08005817
5818 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
5819 WMI_RMC_SET_ACTION_PERIOD_CMDID);
Dustin Brown2afb6f52016-12-02 14:47:48 -08005820 if (ret != QDF_STATUS_SUCCESS)
5821 wmi_buf_free(buf);
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08005822
5823 WMA_LOGE("RMC action period %d cmd sent len: %d, vdev %d"
Dustin Brownecfae9a2016-11-15 13:01:39 -08005824 " command id: %d, status: %d", periodicity_msec,
5825 len, vdev_id, WMI_RMC_SET_ACTION_PERIOD_CMDID, ret);
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08005826
5827 return QDF_STATUS_SUCCESS;
5828}
5829
5830/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005831 * wma_process_add_periodic_tx_ptrn_ind - add periodic tx ptrn
5832 * @handle: wma handle
5833 * @pAddPeriodicTxPtrnParams: tx ptrn params
5834 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305835 * Retrun: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005836 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305837QDF_STATUS wma_process_add_periodic_tx_ptrn_ind(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005838 tSirAddPeriodicTxPtrn *
5839 pAddPeriodicTxPtrnParams)
5840{
5841 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Mohit Khanna0fe61672016-05-19 16:53:39 -07005842 struct periodic_tx_pattern *params_ptr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005843 uint8_t vdev_id;
Mohit Khanna0fe61672016-05-19 16:53:39 -07005844 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005845
5846 if (!wma_handle || !wma_handle->wmi_handle) {
5847 WMA_LOGE("%s: WMA is closed, can not issue fw add pattern cmd",
5848 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305849 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005850 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005851
Mohit Khanna0fe61672016-05-19 16:53:39 -07005852 params_ptr = qdf_mem_malloc(sizeof(*params_ptr));
5853
5854 if (!params_ptr) {
5855 WMA_LOGE(
5856 "%s: unable to allocate memory for periodic_tx_pattern",
5857 __func__);
5858 return QDF_STATUS_E_NOMEM;
5859 }
5860
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005861 if (!wma_find_vdev_by_addr(wma_handle,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005862 pAddPeriodicTxPtrnParams->mac_address.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005863 &vdev_id)) {
5864 WMA_LOGE("%s: Failed to find vdev id for %pM", __func__,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005865 pAddPeriodicTxPtrnParams->mac_address.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305866 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005867 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005868
Mohit Khanna0fe61672016-05-19 16:53:39 -07005869 params_ptr->ucPtrnId = pAddPeriodicTxPtrnParams->ucPtrnId;
5870 params_ptr->ucPtrnSize = pAddPeriodicTxPtrnParams->ucPtrnSize;
5871 params_ptr->usPtrnIntervalMs =
5872 pAddPeriodicTxPtrnParams->usPtrnIntervalMs;
5873 qdf_mem_copy(&params_ptr->mac_address,
Himanshu Agarwal44195412016-03-09 13:03:54 +05305874 &pAddPeriodicTxPtrnParams->mac_address,
5875 sizeof(struct qdf_mac_addr));
Mohit Khanna0fe61672016-05-19 16:53:39 -07005876 qdf_mem_copy(params_ptr->ucPattern,
5877 pAddPeriodicTxPtrnParams->ucPattern,
5878 params_ptr->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005879
Mohit Khanna0fe61672016-05-19 16:53:39 -07005880 status = wmi_unified_process_add_periodic_tx_ptrn_cmd(
5881 wma_handle->wmi_handle, params_ptr, vdev_id);
5882
5883 qdf_mem_free(params_ptr);
5884 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005885}
5886
5887/**
5888 * wma_process_del_periodic_tx_ptrn_ind - del periodic tx ptrn
5889 * @handle: wma handle
5890 * @pDelPeriodicTxPtrnParams: tx ptrn params
5891 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305892 * Retrun: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005893 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305894QDF_STATUS wma_process_del_periodic_tx_ptrn_ind(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005895 tSirDelPeriodicTxPtrn *
5896 pDelPeriodicTxPtrnParams)
5897{
5898 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005899 uint8_t vdev_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005900
5901 if (!wma_handle || !wma_handle->wmi_handle) {
5902 WMA_LOGE("%s: WMA is closed, can not issue Del Pattern cmd",
5903 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305904 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005905 }
Himanshu Agarwal44195412016-03-09 13:03:54 +05305906
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005907 if (!wma_find_vdev_by_addr(wma_handle,
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08005908 pDelPeriodicTxPtrnParams->mac_address.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005909 &vdev_id)) {
5910 WMA_LOGE("%s: Failed to find vdev id for %pM", __func__,
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08005911 pDelPeriodicTxPtrnParams->mac_address.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305912 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005913 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005914
Himanshu Agarwal44195412016-03-09 13:03:54 +05305915 return wmi_unified_process_del_periodic_tx_ptrn_cmd(
5916 wma_handle->wmi_handle, vdev_id,
5917 pDelPeriodicTxPtrnParams->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005918}
5919
5920#ifdef WLAN_FEATURE_STATS_EXT
5921/**
5922 * wma_stats_ext_req() - request ext stats from fw
5923 * @wma_ptr: wma handle
5924 * @preq: stats ext params
5925 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305926 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005927 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305928QDF_STATUS wma_stats_ext_req(void *wma_ptr, tpStatsExtRequest preq)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005929{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005930 tp_wma_handle wma = (tp_wma_handle) wma_ptr;
Krishna Kumaar Natarajan1b909d72016-06-06 15:02:18 -07005931 struct stats_ext_params *params;
5932 size_t params_len;
5933 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005934
Himanshu Agarwal44195412016-03-09 13:03:54 +05305935 if (!wma) {
5936 WMA_LOGE("%s: wma handle is NULL", __func__);
5937 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005938 }
5939
Krishna Kumaar Natarajan1b909d72016-06-06 15:02:18 -07005940 params_len = sizeof(*params) + preq->request_data_len;
5941 params = qdf_mem_malloc(params_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005942
Krishna Kumaar Natarajan1b909d72016-06-06 15:02:18 -07005943 if (params == NULL) {
5944 WMA_LOGE(FL("memory allocation failed"));
5945 return QDF_STATUS_E_NOMEM;
5946 }
5947
5948 params->vdev_id = preq->vdev_id;
5949 params->request_data_len = preq->request_data_len;
5950 if (preq->request_data_len > 0)
5951 qdf_mem_copy(params->request_data, preq->request_data,
5952 params->request_data_len);
5953
5954 status = wmi_unified_stats_ext_req_cmd(wma->wmi_handle, params);
5955 qdf_mem_free(params);
5956
5957 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005958}
5959
5960#endif /* WLAN_FEATURE_STATS_EXT */
5961
5962#ifdef WLAN_FEATURE_EXTWOW_SUPPORT
5963/**
5964 * wma_send_status_of_ext_wow() - send ext wow status to SME
5965 * @wma: wma handle
5966 * @status: status
5967 *
5968 * Return: none
5969 */
5970static void wma_send_status_of_ext_wow(tp_wma_handle wma, bool status)
5971{
5972 tSirReadyToExtWoWInd *ready_to_extwow;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305973 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005974 cds_msg_t cds_msg;
5975 uint8_t len;
5976
5977 WMA_LOGD("Posting ready to suspend indication to umac");
5978
5979 len = sizeof(tSirReadyToExtWoWInd);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305980 ready_to_extwow = (tSirReadyToExtWoWInd *) qdf_mem_malloc(len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005981
5982 if (NULL == ready_to_extwow) {
5983 WMA_LOGE("%s: Memory allocation failure", __func__);
5984 return;
5985 }
5986
5987 ready_to_extwow->mesgType = eWNI_SME_READY_TO_EXTWOW_IND;
5988 ready_to_extwow->mesgLen = len;
5989 ready_to_extwow->status = status;
5990
5991 cds_msg.type = eWNI_SME_READY_TO_EXTWOW_IND;
5992 cds_msg.bodyptr = (void *)ready_to_extwow;
5993 cds_msg.bodyval = 0;
5994
Krunal Soni66c113f2016-12-21 16:46:47 -08005995 vstatus = cds_mq_post_message(QDF_MODULE_ID_SME, &cds_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305996 if (vstatus != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005997 WMA_LOGE("Failed to post ready to suspend");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305998 qdf_mem_free(ready_to_extwow);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005999 }
6000}
6001
6002/**
6003 * wma_enable_ext_wow() - enable ext wow in fw
6004 * @wma: wma handle
6005 * @params: ext wow params
6006 *
6007 * Return:0 for success or error code
6008 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05306009QDF_STATUS wma_enable_ext_wow(tp_wma_handle wma, tpSirExtWoWParams params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006010{
Himanshu Agarwal44195412016-03-09 13:03:54 +05306011 struct ext_wow_params wow_params = {0};
6012 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006013
Himanshu Agarwal44195412016-03-09 13:03:54 +05306014 if (!wma) {
6015 WMA_LOGE("%s: wma handle is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306016 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006017 }
6018
Himanshu Agarwal44195412016-03-09 13:03:54 +05306019 wow_params.vdev_id = params->vdev_id;
6020 wow_params.type = (enum wmi_ext_wow_type) params->type;
6021 wow_params.wakeup_pin_num = params->wakeup_pin_num;
6022
6023 status = wmi_unified_enable_ext_wow_cmd(wma->wmi_handle,
6024 &wow_params);
6025 if (QDF_IS_STATUS_ERROR(status))
6026 return status;
6027
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006028 wma_send_status_of_ext_wow(wma, true);
Himanshu Agarwal44195412016-03-09 13:03:54 +05306029 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006030
6031}
6032
6033/**
6034 * wma_set_app_type1_params_in_fw() - set app type1 params in fw
6035 * @wma: wma handle
6036 * @appType1Params: app type1 params
6037 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306038 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006039 */
6040int wma_set_app_type1_params_in_fw(tp_wma_handle wma,
6041 tpSirAppType1Params appType1Params)
6042{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006043 int ret;
6044
Govind Singhaa64c242016-03-08 11:31:49 +05306045 ret = wmi_unified_app_type1_params_in_fw_cmd(wma->wmi_handle,
6046 (struct app_type1_params *)appType1Params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006047 if (ret) {
6048 WMA_LOGE("%s: Failed to set APP TYPE1 PARAMS", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306049 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006050 }
6051
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306052 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006053}
6054
6055/**
6056 * wma_set_app_type2_params_in_fw() - set app type2 params in fw
6057 * @wma: wma handle
6058 * @appType2Params: app type2 params
6059 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306060 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006061 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05306062QDF_STATUS wma_set_app_type2_params_in_fw(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006063 tpSirAppType2Params appType2Params)
6064{
Himanshu Agarwal44195412016-03-09 13:03:54 +05306065 struct app_type2_params params = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006066
Himanshu Agarwal44195412016-03-09 13:03:54 +05306067 if (!wma) {
6068 WMA_LOGE("%s: wma handle is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306069 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006070 }
6071
Himanshu Agarwal44195412016-03-09 13:03:54 +05306072 params.vdev_id = appType2Params->vdev_id;
6073 params.rc4_key_len = appType2Params->rc4_key_len;
6074 qdf_mem_copy(params.rc4_key, appType2Params->rc4_key, 16);
6075 params.ip_id = appType2Params->ip_id;
6076 params.ip_device_ip = appType2Params->ip_device_ip;
6077 params.ip_server_ip = appType2Params->ip_server_ip;
6078 params.tcp_src_port = appType2Params->tcp_src_port;
6079 params.tcp_dst_port = appType2Params->tcp_dst_port;
6080 params.tcp_seq = appType2Params->tcp_seq;
6081 params.tcp_ack_seq = appType2Params->tcp_ack_seq;
6082 params.keepalive_init = appType2Params->keepalive_init;
6083 params.keepalive_min = appType2Params->keepalive_min;
6084 params.keepalive_max = appType2Params->keepalive_max;
6085 params.keepalive_inc = appType2Params->keepalive_inc;
6086 params.tcp_tx_timeout_val = appType2Params->tcp_tx_timeout_val;
6087 params.tcp_rx_timeout_val = appType2Params->tcp_rx_timeout_val;
6088 qdf_mem_copy(&params.gateway_mac, &appType2Params->gateway_mac,
6089 sizeof(struct qdf_mac_addr));
6090
6091 return wmi_unified_set_app_type2_params_in_fw_cmd(wma->wmi_handle,
6092 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006093
6094}
6095#endif /* WLAN_FEATURE_EXTWOW_SUPPORT */
6096
6097#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
6098/**
6099 * wma_auto_shutdown_event_handler() - process auto shutdown timer trigger
6100 * @handle: wma handle
6101 * @event: event buffer
6102 * @len: buffer length
6103 *
6104 * Return: 0 for success or error code
6105 */
6106int wma_auto_shutdown_event_handler(void *handle, uint8_t *event,
6107 uint32_t len)
6108{
6109 wmi_host_auto_shutdown_event_fixed_param *wmi_auto_sh_evt;
6110 WMI_HOST_AUTO_SHUTDOWN_EVENTID_param_tlvs *param_buf =
6111 (WMI_HOST_AUTO_SHUTDOWN_EVENTID_param_tlvs *)
6112 event;
6113
6114 if (!param_buf || !param_buf->fixed_param) {
6115 WMA_LOGE("%s:%d: Invalid Auto shutdown timer evt", __func__,
6116 __LINE__);
6117 return -EINVAL;
6118 }
6119
6120 wmi_auto_sh_evt = param_buf->fixed_param;
6121
6122 if (wmi_auto_sh_evt->shutdown_reason
6123 != WMI_HOST_AUTO_SHUTDOWN_REASON_TIMER_EXPIRY) {
6124 WMA_LOGE("%s:%d: Invalid Auto shutdown timer evt", __func__,
6125 __LINE__);
6126 return -EINVAL;
6127 }
6128
6129 WMA_LOGD("%s:%d: Auto Shutdown Evt: %d", __func__, __LINE__,
6130 wmi_auto_sh_evt->shutdown_reason);
6131 return wma_post_auto_shutdown_msg();
6132}
6133
6134/**
6135 * wma_set_auto_shutdown_timer_req() - sets auto shutdown timer in firmware
6136 * @wma: wma handle
6137 * @auto_sh_cmd: auto shutdown timer value
6138 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306139 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006140 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306141QDF_STATUS wma_set_auto_shutdown_timer_req(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006142 tSirAutoShutdownCmdParams *
6143 auto_sh_cmd)
6144{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006145 if (auto_sh_cmd == NULL) {
6146 WMA_LOGE("%s : Invalid Autoshutdown cfg cmd", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306147 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006148 }
6149
Himanshu Agarwal44195412016-03-09 13:03:54 +05306150 return wmi_unified_set_auto_shutdown_timer_cmd(wma_handle->wmi_handle,
6151 auto_sh_cmd->timer_val);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006152}
6153#endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
6154
6155#ifdef WLAN_FEATURE_NAN
6156/**
6157 * wma_nan_req() - to send nan request to target
6158 * @wma: wma_handle
6159 * @nan_req: request data which will be non-null
6160 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306161 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006162 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306163QDF_STATUS wma_nan_req(void *wma_ptr, tpNanRequest nan_req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006164{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006165 tp_wma_handle wma_handle = (tp_wma_handle) wma_ptr;
Krishna Kumaar Natarajan1b909d72016-06-06 15:02:18 -07006166 struct nan_req_params *params;
6167 size_t params_len;
6168 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006169
Himanshu Agarwal44195412016-03-09 13:03:54 +05306170 if (!wma_handle) {
6171 WMA_LOGE("%s: wma handle is NULL", __func__);
6172 return QDF_STATUS_E_FAILURE;
6173 }
Krishna Kumaar Natarajan1b909d72016-06-06 15:02:18 -07006174
6175 params_len = sizeof(*params) + nan_req->request_data_len;
6176 params = qdf_mem_malloc(params_len);
6177
6178 if (params == NULL) {
6179 WMA_LOGE(FL("memory allocation failed"));
6180 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006181 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006182
Krishna Kumaar Natarajan1b909d72016-06-06 15:02:18 -07006183 params->request_data_len = nan_req->request_data_len;
6184 if (params->request_data_len > 0)
6185 qdf_mem_copy(params->request_data, nan_req->request_data,
6186 params->request_data_len);
Himanshu Agarwal44195412016-03-09 13:03:54 +05306187
Krishna Kumaar Natarajan1b909d72016-06-06 15:02:18 -07006188 status = wmi_unified_nan_req_cmd(wma_handle->wmi_handle, params);
6189 qdf_mem_free(params);
6190
6191 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006192}
6193#endif /* WLAN_FEATURE_NAN */
6194
6195#ifdef DHCP_SERVER_OFFLOAD
6196/**
6197 * wma_process_dhcpserver_offload() - enable DHCP server offload
6198 * @wma_handle: wma handle
6199 * @pDhcpSrvOffloadInfo: DHCP server offload info
6200 *
6201 * Return: 0 for success or error code
6202 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05306203QDF_STATUS wma_process_dhcpserver_offload(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006204 tSirDhcpSrvOffloadInfo *
6205 pDhcpSrvOffloadInfo)
6206{
Himanshu Agarwal44195412016-03-09 13:03:54 +05306207 struct dhcp_offload_info_params params = {0};
6208 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006209
Himanshu Agarwal44195412016-03-09 13:03:54 +05306210 if (!wma_handle) {
6211 WMA_LOGE("%s: wma handle is NULL", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006212 return -EIO;
6213 }
Himanshu Agarwal44195412016-03-09 13:03:54 +05306214
6215 params.vdev_id = pDhcpSrvOffloadInfo->vdev_id;
6216 params.dhcpSrvOffloadEnabled =
6217 pDhcpSrvOffloadInfo->dhcpSrvOffloadEnabled;
6218 params.dhcpClientNum = pDhcpSrvOffloadInfo->dhcpClientNum;
6219 params.dhcpSrvIP = pDhcpSrvOffloadInfo->;
6220
6221 status = wmi_unified_process_dhcpserver_offload_cmd(
6222 wma_handle->wmi_handle, &params);
6223 if (QDF_IS_STATUS_ERROR(status))
6224 return status;
6225
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006226 WMA_LOGD("Set dhcp server offload to vdevId %d",
6227 pDhcpSrvOffloadInfo->vdev_id);
Himanshu Agarwal44195412016-03-09 13:03:54 +05306228 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006229}
6230#endif /* DHCP_SERVER_OFFLOAD */
6231
6232#ifdef WLAN_FEATURE_GPIO_LED_FLASHING
6233/**
6234 * wma_set_led_flashing() - set led flashing in fw
6235 * @wma_handle: wma handle
6236 * @flashing: flashing request
6237 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306238 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006239 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306240QDF_STATUS wma_set_led_flashing(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006241 tSirLedFlashingReq *flashing)
6242{
Govind Singhaa64c242016-03-08 11:31:49 +05306243 struct flashing_req_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006244
6245 if (!wma_handle || !wma_handle->wmi_handle) {
6246 WMA_LOGE(FL("WMA is closed, can not issue cmd"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306247 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006248 }
6249 if (!flashing) {
6250 WMA_LOGE(FL("invalid parameter: flashing"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306251 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006252 }
Govind Singhaa64c242016-03-08 11:31:49 +05306253 cmd.req_id = flashing->reqId;
6254 cmd.pattern_id = flashing->pattern_id;
6255 cmd.led_x0 = flashing->led_x0;
6256 cmd.led_x1 = flashing->led_x1;
6257 status = wmi_unified_set_led_flashing_cmd(wma_handle->wmi_handle,
6258 &cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006259 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306260 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006261 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306262 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006263}
6264#endif /* WLAN_FEATURE_GPIO_LED_FLASHING */
6265
6266#ifdef FEATURE_WLAN_CH_AVOID
6267/**
6268 * wma_channel_avoid_evt_handler() - process channel to avoid event from FW.
6269 * @handle: wma handle
6270 * @event: event buffer
6271 * @len: buffer length
6272 *
6273 * Return: 0 for success or error code
6274 */
6275int wma_channel_avoid_evt_handler(void *handle, uint8_t *event,
6276 uint32_t len)
6277{
6278 wmi_avoid_freq_ranges_event_fixed_param *afr_fixed_param;
6279 wmi_avoid_freq_range_desc *afr_desc;
6280 uint32_t num_freq_ranges, freq_range_idx;
6281 tSirChAvoidIndType *sca_indication;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306282 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006283 cds_msg_t sme_msg = { 0 };
6284 WMI_WLAN_FREQ_AVOID_EVENTID_param_tlvs *param_buf =
6285 (WMI_WLAN_FREQ_AVOID_EVENTID_param_tlvs *) event;
6286
6287 if (!param_buf) {
6288 WMA_LOGE("Invalid channel avoid event buffer");
6289 return -EINVAL;
6290 }
6291
6292 afr_fixed_param = param_buf->fixed_param;
6293 if (!afr_fixed_param) {
6294 WMA_LOGE("Invalid channel avoid event fixed param buffer");
6295 return -EINVAL;
6296 }
6297
6298 num_freq_ranges =
6299 (afr_fixed_param->num_freq_ranges >
6300 SIR_CH_AVOID_MAX_RANGE) ? SIR_CH_AVOID_MAX_RANGE :
6301 afr_fixed_param->num_freq_ranges;
6302
6303 WMA_LOGD("Channel avoid event received with %d ranges",
6304 num_freq_ranges);
6305 for (freq_range_idx = 0; freq_range_idx < num_freq_ranges;
6306 freq_range_idx++) {
6307 afr_desc = (wmi_avoid_freq_range_desc *)
6308 ((void *)param_buf->avd_freq_range +
6309 freq_range_idx * sizeof(wmi_avoid_freq_range_desc));
6310
6311 WMA_LOGD("range %d: tlv id = %u, start freq = %u, end freq = %u",
6312 freq_range_idx, afr_desc->tlv_header, afr_desc->start_freq,
6313 afr_desc->end_freq);
6314 }
6315
6316 sca_indication = (tSirChAvoidIndType *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306317 qdf_mem_malloc(sizeof(tSirChAvoidIndType));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006318 if (!sca_indication) {
6319 WMA_LOGE("Invalid channel avoid indication buffer");
6320 return -EINVAL;
6321 }
6322
6323 sca_indication->avoid_range_count = num_freq_ranges;
6324 for (freq_range_idx = 0; freq_range_idx < num_freq_ranges;
6325 freq_range_idx++) {
6326 afr_desc = (wmi_avoid_freq_range_desc *)
6327 ((void *)param_buf->avd_freq_range +
6328 freq_range_idx * sizeof(wmi_avoid_freq_range_desc));
6329 sca_indication->avoid_freq_range[freq_range_idx].start_freq =
6330 afr_desc->start_freq;
6331 sca_indication->avoid_freq_range[freq_range_idx].end_freq =
6332 afr_desc->end_freq;
6333 }
6334
6335 sme_msg.type = eWNI_SME_CH_AVOID_IND;
6336 sme_msg.bodyptr = sca_indication;
6337 sme_msg.bodyval = 0;
6338
Anurag Chouhan6d760662016-02-20 16:05:43 +05306339 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306340 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006341 WMA_LOGE("Fail to post eWNI_SME_CH_AVOID_IND msg to SME");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306342 qdf_mem_free(sca_indication);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006343 return -EINVAL;
6344 }
6345
6346 return 0;
6347}
6348
6349/**
6350 * wma_process_ch_avoid_update_req() - handles channel avoid update request
6351 * @wma_handle: wma handle
6352 * @ch_avoid_update_req: channel avoid update params
6353 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306354 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006355 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306356QDF_STATUS wma_process_ch_avoid_update_req(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006357 tSirChAvoidUpdateReq *
6358 ch_avoid_update_req)
6359{
Himanshu Agarwal44195412016-03-09 13:03:54 +05306360 QDF_STATUS status;
6361 if (!wma_handle) {
6362 WMA_LOGE("%s: wma handle is NULL", __func__);
6363 return QDF_STATUS_E_FAILURE;
6364 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006365 if (ch_avoid_update_req == NULL) {
6366 WMA_LOGE("%s : ch_avoid_update_req is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306367 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006368 }
6369
6370 WMA_LOGI("%s: WMA --> WMI_CHAN_AVOID_UPDATE", __func__);
6371
Himanshu Agarwal44195412016-03-09 13:03:54 +05306372 status = wmi_unified_process_ch_avoid_update_cmd(
6373 wma_handle->wmi_handle);
6374 if (QDF_IS_STATUS_ERROR(status))
6375 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006376
6377 WMA_LOGI("%s: WMA --> WMI_CHAN_AVOID_UPDATE sent through WMI",
6378 __func__);
Himanshu Agarwal44195412016-03-09 13:03:54 +05306379 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006380}
6381#endif /* FEATURE_WLAN_CH_AVOID */
6382
6383/**
6384 * wma_set_reg_domain() - set reg domain
6385 * @clientCtxt: client context
6386 * @regId: reg id
6387 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306388 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006389 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306390QDF_STATUS wma_set_reg_domain(void *clientCtxt, v_REGDOMAIN_t regId)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006391{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306392 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006393 cds_set_reg_domain(clientCtxt, regId))
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306394 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006395
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306396 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006397}
6398
6399/**
6400 * wma_send_regdomain_info_to_fw() - send regdomain info to fw
6401 * @reg_dmn: reg domain
6402 * @regdmn2G: 2G reg domain
6403 * @regdmn5G: 5G reg domain
6404 * @ctl2G: 2G test limit
6405 * @ctl5G: 5G test limit
6406 *
6407 * Return: none
6408 */
6409void wma_send_regdomain_info_to_fw(uint32_t reg_dmn, uint16_t regdmn2G,
6410 uint16_t regdmn5G, int8_t ctl2G,
6411 int8_t ctl5G)
6412{
Anurag Chouhan6d760662016-02-20 16:05:43 +05306413 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006414 int32_t cck_mask_val = 0;
Govind Singhd76a5b02016-03-08 15:12:14 +05306415 struct pdev_params pdev_param = {0};
Himanshu Agarwal44195412016-03-09 13:03:54 +05306416 QDF_STATUS ret = QDF_STATUS_SUCCESS;
6417 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006418
6419 if (NULL == wma) {
6420 WMA_LOGE("%s: wma context is NULL", __func__);
6421 return;
6422 }
6423
Himanshu Agarwal44195412016-03-09 13:03:54 +05306424 status = wmi_unified_send_regdomain_info_to_fw_cmd(wma->wmi_handle,
6425 reg_dmn, regdmn2G, regdmn5G, ctl2G, ctl5G);
6426 if (status == QDF_STATUS_E_NOMEM)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006427 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006428
Amar Singhal5f997862016-08-24 13:17:50 -07006429 if ((((reg_dmn & ~CTRY_FLAG) == CTRY_JAPAN14) ||
6430 ((reg_dmn & ~CTRY_FLAG) == CTRY_KOREA_ROC)) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006431 (true == wma->tx_chain_mask_cck))
6432 cck_mask_val = 1;
6433
6434 cck_mask_val |= (wma->self_gen_frm_pwr << 16);
Govind Singhd76a5b02016-03-08 15:12:14 +05306435 pdev_param.param_id = WMI_PDEV_PARAM_TX_CHAIN_MASK_CCK;
6436 pdev_param.param_value = cck_mask_val;
6437 ret = wmi_unified_pdev_param_send(wma->wmi_handle,
6438 &pdev_param,
6439 WMA_WILDCARD_PDEV_ID);
6440
Himanshu Agarwal44195412016-03-09 13:03:54 +05306441 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006442 WMA_LOGE("failed to set PDEV tx_chain_mask_cck %d",
6443 ret);
6444
6445 return;
6446}
6447
6448/**
Houston Hoffmana76591b2015-11-10 16:52:05 -08006449 * wma_post_runtime_resume_msg() - post the resume request
6450 * @handle: validated wma handle
6451 *
6452 * request the MC thread unpaus the vdev and set resume dtim
6453 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306454 * Return: qdf status of the mq post
Houston Hoffmana76591b2015-11-10 16:52:05 -08006455 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306456static QDF_STATUS wma_post_runtime_resume_msg(WMA_HANDLE handle)
Houston Hoffmana76591b2015-11-10 16:52:05 -08006457{
6458 cds_msg_t resume_msg;
Houston Hoffmanc45db892015-11-13 19:59:25 -08006459 QDF_STATUS status;
6460 tp_wma_handle wma = (tp_wma_handle) handle;
6461
6462 qdf_runtime_pm_prevent_suspend(wma->wma_runtime_resume_lock);
Houston Hoffmana76591b2015-11-10 16:52:05 -08006463
6464 resume_msg.bodyptr = NULL;
6465 resume_msg.type = WMA_RUNTIME_PM_RESUME_IND;
Houston Hoffmanc45db892015-11-13 19:59:25 -08006466
6467 status = cds_mq_post_message(QDF_MODULE_ID_WMA, &resume_msg);
6468
6469 if (!QDF_IS_STATUS_SUCCESS(status)) {
6470 WMA_LOGE("Failed to post Runtime PM Resume IND to VOS");
6471 qdf_runtime_pm_allow_suspend(wma->wma_runtime_resume_lock);
6472 }
6473
6474 return status;
Houston Hoffmana76591b2015-11-10 16:52:05 -08006475}
6476
6477/**
6478 * wma_post_runtime_suspend_msg() - post the suspend request
6479 * @handle: validated wma handle
6480 *
6481 * Requests for offloads to be configured for runtime suspend
6482 * on the MC thread
6483 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306484 * Return QDF_STATUS_E_AGAIN in case of timeout or QDF_STATUS_SUCCESS
Houston Hoffmana76591b2015-11-10 16:52:05 -08006485 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306486static QDF_STATUS wma_post_runtime_suspend_msg(WMA_HANDLE handle)
Houston Hoffmana76591b2015-11-10 16:52:05 -08006487{
6488 cds_msg_t cds_msg;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306489 QDF_STATUS qdf_status;
Houston Hoffmana76591b2015-11-10 16:52:05 -08006490 tp_wma_handle wma = (tp_wma_handle) handle;
6491
Anurag Chouhance0dc992016-02-16 18:18:03 +05306492 qdf_event_reset(&wma->runtime_suspend);
Houston Hoffmana76591b2015-11-10 16:52:05 -08006493
6494 cds_msg.bodyptr = NULL;
6495 cds_msg.type = WMA_RUNTIME_PM_SUSPEND_IND;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306496 qdf_status = cds_mq_post_message(QDF_MODULE_ID_WMA, &cds_msg);
Houston Hoffmana76591b2015-11-10 16:52:05 -08006497
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306498 if (qdf_status != QDF_STATUS_SUCCESS)
Houston Hoffmana76591b2015-11-10 16:52:05 -08006499 goto failure;
6500
Anurag Chouhance0dc992016-02-16 18:18:03 +05306501 if (qdf_wait_single_event(&wma->runtime_suspend,
Houston Hoffmana76591b2015-11-10 16:52:05 -08006502 WMA_TGT_SUSPEND_COMPLETE_TIMEOUT) !=
Anurag Chouhance0dc992016-02-16 18:18:03 +05306503 QDF_STATUS_SUCCESS) {
Houston Hoffmana76591b2015-11-10 16:52:05 -08006504 WMA_LOGE("Failed to get runtime suspend event");
Houston Hoffmanc45db892015-11-13 19:59:25 -08006505 goto msg_timed_out;
Houston Hoffmana76591b2015-11-10 16:52:05 -08006506 }
6507
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306508 return QDF_STATUS_SUCCESS;
Houston Hoffmana76591b2015-11-10 16:52:05 -08006509
Houston Hoffmanc45db892015-11-13 19:59:25 -08006510msg_timed_out:
6511 wma_post_runtime_resume_msg(wma);
Houston Hoffmana76591b2015-11-10 16:52:05 -08006512failure:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306513 return QDF_STATUS_E_AGAIN;
Houston Hoffmana76591b2015-11-10 16:52:05 -08006514}
6515
6516/**
6517 * __wma_bus_suspend(): handles bus suspend for wma
6518 * @type: is this suspend part of runtime suspend or system suspend?
Dustin Browne70fd972016-11-10 11:17:40 -08006519 * @wow_flags: bitmap of WMI WOW flags to pass to FW
Houston Hoffmana76591b2015-11-10 16:52:05 -08006520 *
6521 * Bails if a scan is in progress.
6522 * Calls the appropriate handlers based on configuration and event.
6523 *
6524 * Return: 0 for success or error code
6525 */
Dustin Browne70fd972016-11-10 11:17:40 -08006526static int __wma_bus_suspend(enum qdf_suspend_type type, uint32_t wow_flags)
Houston Hoffmana76591b2015-11-10 16:52:05 -08006527{
Anurag Chouhan6d760662016-02-20 16:05:43 +05306528 WMA_HANDLE handle = cds_get_context(QDF_MODULE_ID_WMA);
Houston Hoffmana76591b2015-11-10 16:52:05 -08006529 if (NULL == handle) {
6530 WMA_LOGE("%s: wma context is NULL", __func__);
6531 return -EFAULT;
6532 }
6533
6534 if (wma_check_scan_in_progress(handle)) {
6535 WMA_LOGE("%s: Scan in progress. Aborting suspend", __func__);
6536 return -EBUSY;
6537 }
6538
Anurag Chouhan6d760662016-02-20 16:05:43 +05306539 if (type == QDF_RUNTIME_SUSPEND) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306540 QDF_STATUS status = wma_post_runtime_suspend_msg(handle);
Houston Hoffmana76591b2015-11-10 16:52:05 -08006541 if (status)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306542 return qdf_status_to_os_return(status);
Houston Hoffmana76591b2015-11-10 16:52:05 -08006543 }
6544
Anurag Chouhan6d760662016-02-20 16:05:43 +05306545 if (type == QDF_SYSTEM_SUSPEND)
Dustin Brown2d228232016-09-22 15:06:19 -07006546 WMA_LOGI("%s: wow mode selected %d", __func__,
Houston Hoffmana76591b2015-11-10 16:52:05 -08006547 wma_is_wow_mode_selected(handle));
6548
6549 if (wma_is_wow_mode_selected(handle)) {
Dustin Browne70fd972016-11-10 11:17:40 -08006550 QDF_STATUS status = wma_enable_wow_in_fw(handle, wow_flags);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306551 return qdf_status_to_os_return(status);
Houston Hoffmana76591b2015-11-10 16:52:05 -08006552 }
6553
6554 return wma_suspend_target(handle, 0);
6555}
6556
6557/**
6558 * wma_runtime_suspend() - handles runtime suspend request from hdd
Dustin Browne70fd972016-11-10 11:17:40 -08006559 * @wow_flags: bitmap of WMI WOW flags to pass to FW
Houston Hoffmana76591b2015-11-10 16:52:05 -08006560 *
6561 * Calls the appropriate handler based on configuration and event.
6562 * Last busy marking should prevent race conditions between processing
6563 * of asyncronous fw events and the running of runtime suspend.
6564 * (eg. last busy marking should guarantee that any auth requests have
6565 * been processed)
6566 * Events comming from the host are not protected, but aren't expected
6567 * to be an issue.
6568 *
6569 * Return: 0 for success or error code
6570 */
Dustin Browne70fd972016-11-10 11:17:40 -08006571int wma_runtime_suspend(uint32_t wow_flags)
Houston Hoffmana76591b2015-11-10 16:52:05 -08006572{
Dustin Browne70fd972016-11-10 11:17:40 -08006573 return __wma_bus_suspend(QDF_RUNTIME_SUSPEND, wow_flags);
Houston Hoffmana76591b2015-11-10 16:52:05 -08006574}
6575
6576/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006577 * wma_bus_suspend() - handles bus suspend request from hdd
Dustin Browne70fd972016-11-10 11:17:40 -08006578 * @wow_flags: bitmap of WMI WOW flags to pass to FW
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006579 *
6580 * Calls the appropriate handler based on configuration and event
6581 *
6582 * Return: 0 for success or error code
6583 */
Dustin Browne70fd972016-11-10 11:17:40 -08006584int wma_bus_suspend(uint32_t wow_flags)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006585{
Houston Hoffmana76591b2015-11-10 16:52:05 -08006586
Dustin Browne70fd972016-11-10 11:17:40 -08006587 return __wma_bus_suspend(QDF_SYSTEM_SUSPEND, wow_flags);
Houston Hoffmana76591b2015-11-10 16:52:05 -08006588}
6589
6590/**
6591 * __wma_bus_resume() - bus resume for wma
6592 *
6593 * does the part of the bus resume common to bus and system suspend
6594 *
6595 * Return: os error code.
6596 */
Jeff Johnsonc4b47a92016-10-07 12:34:41 -07006597static int __wma_bus_resume(WMA_HANDLE handle)
Houston Hoffmana76591b2015-11-10 16:52:05 -08006598{
6599 bool wow_mode = wma_is_wow_mode_selected(handle);
Rajeev Kumar4c426622016-08-25 14:51:42 -07006600 tp_wma_handle wma = handle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306601 QDF_STATUS status;
Houston Hoffmana76591b2015-11-10 16:52:05 -08006602
Dustin Brown2d228232016-09-22 15:06:19 -07006603 WMA_LOGI("%s: wow mode %d", __func__, wow_mode);
Houston Hoffmana76591b2015-11-10 16:52:05 -08006604
Rajeev Kumar4c426622016-08-25 14:51:42 -07006605 wma->wow_initial_wake_up = false;
6606
Houston Hoffmana76591b2015-11-10 16:52:05 -08006607 if (!wow_mode)
Rajeev Kumar9be537e2016-04-25 17:35:33 -07006608 return qdf_status_to_os_return(wma_resume_target(handle));
Houston Hoffmana76591b2015-11-10 16:52:05 -08006609
6610 status = wma_disable_wow_in_fw(handle);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306611 return qdf_status_to_os_return(status);
Houston Hoffmana76591b2015-11-10 16:52:05 -08006612}
6613
6614/**
6615 * wma_runtime_resume() - do the runtime resume operation for wma
6616 *
6617 * Return: os error code.
6618 */
6619int wma_runtime_resume(void)
6620{
6621 int ret;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306622 QDF_STATUS status;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306623 WMA_HANDLE handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006624 if (NULL == handle) {
6625 WMA_LOGE("%s: wma context is NULL", __func__);
6626 return -EFAULT;
6627 }
6628
Houston Hoffmana76591b2015-11-10 16:52:05 -08006629 ret = __wma_bus_resume(handle);
6630 if (ret)
6631 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006632
Houston Hoffmana76591b2015-11-10 16:52:05 -08006633 status = wma_post_runtime_resume_msg(handle);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306634 return qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006635}
6636
6637/**
6638 * wma_bus_resume() - handles bus resume request from hdd
6639 * @handle: valid wma handle
6640 *
6641 * Calls the appropriate handler based on configuration
6642 *
6643 * Return: 0 for success or error code
6644 */
6645int wma_bus_resume(void)
6646{
Anurag Chouhan6d760662016-02-20 16:05:43 +05306647 WMA_HANDLE handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006648 if (NULL == handle) {
6649 WMA_LOGE("%s: wma context is NULL", __func__);
6650 return -EFAULT;
6651 }
6652
Houston Hoffmana76591b2015-11-10 16:52:05 -08006653 return __wma_bus_resume(handle);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006654}
6655
6656/**
Manjunathappa Prakash7b67e622016-04-12 15:18:45 +05306657 * wma_suspend_target_timeout() - Handles the target suspend timeout
6658 * @is_self_recovery_enabled: Is self recovery enabled or not
6659 *
6660 * Return: NONE
6661 */
6662#ifdef QCA_WIFI_3_0_ADRASTEA
6663static inline void wma_suspend_target_timeout(bool is_self_recovery_enabled)
6664{
6665 if (cds_is_driver_recovering()) {
6666 WMA_LOGE("%s: recovery is in progress, ignore!", __func__);
6667 } else {
6668 if (is_self_recovery_enabled) {
Mukul Sharmab7b575b2016-10-02 23:37:07 +05306669 cds_trigger_recovery(false);
Manjunathappa Prakash7b67e622016-04-12 15:18:45 +05306670 } else {
6671 QDF_BUG(0);
6672 }
6673 }
6674}
6675#else /* ROME chipset */
6676static inline void wma_suspend_target_timeout(bool is_self_recovery_enabled)
6677{
6678 if (cds_is_load_or_unload_in_progress() || cds_is_driver_recovering()) {
6679 WMA_LOGE("%s: Unloading/Loading/recovery is in progress, Ignore!",
6680 __func__);
6681 } else {
6682 if (is_self_recovery_enabled) {
Mukul Sharmab7b575b2016-10-02 23:37:07 +05306683 cds_trigger_recovery(false);
Manjunathappa Prakash7b67e622016-04-12 15:18:45 +05306684 } else {
6685 QDF_BUG(0);
6686 }
6687 }
6688}
6689#endif
6690
6691/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006692 * wma_suspend_target() - suspend target
6693 * @handle: wma handle
6694 * @disable_target_intr: disable target interrupt
6695 *
Govind Singhd76a5b02016-03-08 15:12:14 +05306696 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006697 */
Govind Singhd76a5b02016-03-08 15:12:14 +05306698QDF_STATUS wma_suspend_target(WMA_HANDLE handle, int disable_target_intr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006699{
6700 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhd76a5b02016-03-08 15:12:14 +05306701 QDF_STATUS status;
6702 struct suspend_params param = {0};
6703
Anurag Chouhan6d760662016-02-20 16:05:43 +05306704 tpAniSirGlobal pmac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006705
6706 if (!wma_handle || !wma_handle->wmi_handle) {
6707 WMA_LOGE("WMA is closed. can not issue suspend cmd");
Govind Singhd76a5b02016-03-08 15:12:14 +05306708 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006709 }
Yue Mae1a85f32015-10-20 18:12:45 -07006710
Yue Mae1a85f32015-10-20 18:12:45 -07006711 if (NULL == pmac) {
6712 WMA_LOGE("%s: Unable to get PE context", __func__);
Govind Singhd76a5b02016-03-08 15:12:14 +05306713 return QDF_STATUS_E_INVAL;
Yue Mae1a85f32015-10-20 18:12:45 -07006714 }
Houston Hoffman52ec6692016-04-21 16:36:45 -07006715
Anurag Chouhance0dc992016-02-16 18:18:03 +05306716 qdf_event_reset(&wma_handle->target_suspend);
Govind Singhd76a5b02016-03-08 15:12:14 +05306717 param.disable_target_intr = disable_target_intr;
6718 status = wmi_unified_suspend_send(wma_handle->wmi_handle,
6719 &param,
6720 WMA_WILDCARD_PDEV_ID);
6721 if (QDF_IS_STATUS_ERROR(status))
6722 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006723
6724 wmi_set_target_suspend(wma_handle->wmi_handle, true);
6725
Anurag Chouhance0dc992016-02-16 18:18:03 +05306726 if (qdf_wait_single_event(&wma_handle->target_suspend,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006727 WMA_TGT_SUSPEND_COMPLETE_TIMEOUT)
Anurag Chouhance0dc992016-02-16 18:18:03 +05306728 != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006729 WMA_LOGE("Failed to get ACK from firmware for pdev suspend");
6730 wmi_set_target_suspend(wma_handle->wmi_handle, false);
Manjunathappa Prakash7b67e622016-04-12 15:18:45 +05306731 wma_suspend_target_timeout(pmac->sme.enableSelfRecovery);
Govind Singhd76a5b02016-03-08 15:12:14 +05306732 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006733 }
6734
Govind Singhd76a5b02016-03-08 15:12:14 +05306735 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006736}
6737
6738/**
6739 * wma_target_suspend_acknowledge() - update target susspend status
Houston Hoffmana769ed32016-04-14 17:02:51 -07006740 * @context: HTC_INIT_INFO->context
6741 * @wow_nack: true when wow is rejected
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006742 *
6743 * Return: none
6744 */
Houston Hoffmana769ed32016-04-14 17:02:51 -07006745void wma_target_suspend_acknowledge(void *context, bool wow_nack)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006746{
Anurag Chouhan6d760662016-02-20 16:05:43 +05306747 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006748
6749 if (NULL == wma) {
6750 WMA_LOGE("%s: wma is NULL", __func__);
6751 return;
6752 }
6753
6754 wma->wow_nack = wow_nack;
Anurag Chouhance0dc992016-02-16 18:18:03 +05306755 qdf_event_set(&wma->target_suspend);
Komal Seelam498a0cd2016-09-12 10:29:02 +05306756 if (wow_nack && !wmi_get_runtime_pm_inprogress(wma->wmi_handle)) {
Anurag Chouhan01cfa4e2016-09-04 15:10:49 +05306757 cds_host_diag_log_work(&wma->wow_wake_lock,
6758 WMA_WAKE_LOCK_TIMEOUT,
6759 WIFI_POWER_EVENT_WAKELOCK_WOW);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306760 qdf_wake_lock_timeout_acquire(&wma->wow_wake_lock,
Anurag Chouhan01cfa4e2016-09-04 15:10:49 +05306761 WMA_WAKE_LOCK_TIMEOUT);
6762 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006763}
6764
6765/**
Rajeev Kumar4c426622016-08-25 14:51:42 -07006766 * wma_handle_initial_wake_up() - handle inital wake up
6767 *
6768 * Return: none
6769 */
6770void wma_handle_initial_wake_up(void)
6771{
6772 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
6773
6774 if (NULL == wma) {
6775 WMA_LOGE("%s: wma is NULL", __func__);
6776 return;
6777 }
6778
6779 wma->wow_initial_wake_up = true;
6780}
6781
6782/**
6783 * wma_is_target_wake_up_received() - check for initial wake up
6784 *
6785 * Check if target initial wake up is received and fail PM suspend gracefully
6786 *
6787 * Return: -EAGAIN if initial wake up is received else 0
6788 */
6789int wma_is_target_wake_up_received(void)
6790{
6791 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
6792
6793 if (NULL == wma) {
6794 WMA_LOGE("%s: wma is NULL", __func__);
6795 return -EAGAIN;
6796 }
6797
6798 if (wma->wow_initial_wake_up) {
6799 WMA_LOGE("Target initial wake up received try again");
6800 return -EAGAIN;
Rajeev Kumar4c426622016-08-25 14:51:42 -07006801 }
Rajeev Kumar99805a72016-08-29 13:53:52 -07006802
6803 return 0;
6804}
6805
6806/**
6807 * wma_clear_target_wake_up() - clear initial wake up
6808 *
6809 * Clear target initial wake up reason
6810 *
6811 * Return: 0 for success and negative error code for failure
6812 */
6813int wma_clear_target_wake_up(void)
6814{
6815 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
6816
6817 if (NULL == wma) {
6818 WMA_LOGE("%s: wma is NULL", __func__);
6819 return -EFAULT;
6820 }
6821
6822 wma->wow_initial_wake_up = false;
6823
6824 return 0;
Rajeev Kumar4c426622016-08-25 14:51:42 -07006825}
6826
6827/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006828 * wma_resume_target() - resume target
6829 * @handle: wma handle
6830 *
Govind Singhd76a5b02016-03-08 15:12:14 +05306831 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006832 */
Govind Singhd76a5b02016-03-08 15:12:14 +05306833QDF_STATUS wma_resume_target(WMA_HANDLE handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006834{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006835 tp_wma_handle wma = (tp_wma_handle) handle;
Anurag Chouhance0dc992016-02-16 18:18:03 +05306836 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306837 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006838 if (NULL == pMac) {
6839 WMA_LOGE("%s: Unable to get PE context", __func__);
Govind Singhd76a5b02016-03-08 15:12:14 +05306840 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006841 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006842
Anurag Chouhance0dc992016-02-16 18:18:03 +05306843 qdf_event_reset(&wma->wma_resume_event);
Govind Singhd76a5b02016-03-08 15:12:14 +05306844 qdf_status = wmi_unified_resume_send(wma->wmi_handle,
6845 WMA_WILDCARD_PDEV_ID);
6846 if (QDF_IS_STATUS_ERROR(qdf_status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006847 WMA_LOGE("Failed to send WMI_PDEV_RESUME_CMDID command");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006848
Anurag Chouhance0dc992016-02-16 18:18:03 +05306849 qdf_status = qdf_wait_single_event(&(wma->wma_resume_event),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006850 WMA_RESUME_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05306851 if (QDF_STATUS_SUCCESS != qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006852 WMA_LOGP("%s: Timeout waiting for resume event from FW",
6853 __func__);
6854 WMA_LOGP("%s: Pending commands %d credits %d", __func__,
6855 wmi_get_pending_cmds(wma->wmi_handle),
6856 wmi_get_host_credits(wma->wmi_handle));
Prashanth Bhatta9e143052015-12-04 11:56:47 -08006857 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006858 if (pMac->sme.enableSelfRecovery) {
Mukul Sharmab7b575b2016-10-02 23:37:07 +05306859 cds_trigger_recovery(false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006860 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306861 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006862 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006863 } else {
6864 WMA_LOGE("%s: SSR in progress, ignore resume timeout",
6865 __func__);
6866 }
6867 } else {
6868 WMA_LOGD("Host wakeup received");
6869 }
6870
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306871 if (QDF_STATUS_SUCCESS == qdf_status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006872 wmi_set_target_suspend(wma->wmi_handle, false);
6873
Houston Hoffman52ec6692016-04-21 16:36:45 -07006874 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006875}
6876
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006877#ifdef FEATURE_WLAN_TDLS
6878/**
6879 * wma_tdls_event_handler() - handle TDLS event
6880 * @handle: wma handle
6881 * @event: event buffer
6882 * @len: buffer length
6883 *
6884 * Return: 0 for success or error code
6885 */
6886int wma_tdls_event_handler(void *handle, uint8_t *event, uint32_t len)
6887{
6888 tp_wma_handle wma = (tp_wma_handle) handle;
6889 WMI_TDLS_PEER_EVENTID_param_tlvs *param_buf = NULL;
6890 wmi_tdls_peer_event_fixed_param *peer_event = NULL;
6891 tSirTdlsEventnotify *tdls_event;
6892
6893 if (!event) {
6894 WMA_LOGE("%s: event param null", __func__);
6895 return -EINVAL;
6896 }
6897
6898 param_buf = (WMI_TDLS_PEER_EVENTID_param_tlvs *) event;
6899 if (!param_buf) {
6900 WMA_LOGE("%s: received null buf from target", __func__);
6901 return -EINVAL;
6902 }
6903
6904 peer_event = param_buf->fixed_param;
6905 if (!peer_event) {
6906 WMA_LOGE("%s: received null event data from target", __func__);
6907 return -EINVAL;
6908 }
6909
6910 tdls_event = (tSirTdlsEventnotify *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306911 qdf_mem_malloc(sizeof(*tdls_event));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006912 if (!tdls_event) {
6913 WMA_LOGE("%s: failed to allocate memory for tdls_event",
6914 __func__);
6915 return -ENOMEM;
6916 }
6917
6918 tdls_event->sessionId = peer_event->vdev_id;
6919 WMI_MAC_ADDR_TO_CHAR_ARRAY(&peer_event->peer_macaddr,
Srinivas Girigowda4f593792015-11-19 15:33:42 -08006920 tdls_event->peermac.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006921
6922 switch (peer_event->peer_status) {
6923 case WMI_TDLS_SHOULD_DISCOVER:
6924 tdls_event->messageType = WMA_TDLS_SHOULD_DISCOVER_CMD;
6925 break;
6926 case WMI_TDLS_SHOULD_TEARDOWN:
6927 tdls_event->messageType = WMA_TDLS_SHOULD_TEARDOWN_CMD;
6928 break;
6929 case WMI_TDLS_PEER_DISCONNECTED:
6930 tdls_event->messageType = WMA_TDLS_PEER_DISCONNECTED_CMD;
6931 break;
Kabilan Kannan14ec97f2016-05-16 23:48:25 -07006932 case WMI_TDLS_CONNECTION_TRACKER_NOTIFICATION:
6933 tdls_event->messageType =
6934 WMA_TDLS_CONNECTION_TRACKER_NOTIFICATION_CMD;
6935 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006936 default:
Yingying Tangaafa8e92016-09-29 16:09:00 +08006937 qdf_mem_free(tdls_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006938 WMA_LOGE("%s: Discarding unknown tdls event(%d) from target",
6939 __func__, peer_event->peer_status);
6940 return -EINVAL;
6941 }
6942
6943 switch (peer_event->peer_reason) {
6944 case WMI_TDLS_TEARDOWN_REASON_TX:
6945 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_TX;
6946 break;
6947 case WMI_TDLS_TEARDOWN_REASON_RSSI:
6948 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_RSSI;
6949 break;
6950 case WMI_TDLS_TEARDOWN_REASON_SCAN:
6951 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_SCAN;
6952 break;
6953 case WMI_TDLS_DISCONNECTED_REASON_PEER_DELETE:
6954 tdls_event->peer_reason =
6955 eWNI_TDLS_DISCONNECTED_REASON_PEER_DELETE;
6956 break;
6957 case WMI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT:
6958 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT;
6959 break;
6960 case WMI_TDLS_TEARDOWN_REASON_BAD_PTR:
6961 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_BAD_PTR;
6962 break;
6963 case WMI_TDLS_TEARDOWN_REASON_NO_RESPONSE:
6964 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_NO_RESPONSE;
6965 break;
Kabilan Kannan14ec97f2016-05-16 23:48:25 -07006966 case WMI_TDLS_ENTER_BUF_STA:
6967 tdls_event->peer_reason = eWNI_TDLS_PEER_ENTER_BUF_STA;
6968 break;
6969 case WMI_TDLS_EXIT_BUF_STA:
6970 tdls_event->peer_reason = eWNI_TDLS_PEER_EXIT_BUF_STA;
6971 break;
6972 case WMI_TDLS_ENTER_BT_BUSY_MODE:
6973 tdls_event->peer_reason = eWNI_TDLS_ENTER_BT_BUSY_MODE;
6974 break;
6975 case WMI_TDLS_EXIT_BT_BUSY_MODE:
6976 tdls_event->peer_reason = eWNI_TDLS_EXIT_BT_BUSY_MODE;
6977 break;
Kabilan Kannan21eafc22016-11-04 16:33:52 -07006978 case WMI_TDLS_SCAN_STARTED_EVENT:
6979 tdls_event->peer_reason = eWMI_TDLS_SCAN_STARTED_EVENT;
6980 break;
6981 case WMI_TDLS_SCAN_COMPLETED_EVENT:
6982 tdls_event->peer_reason = eWMI_TDLS_SCAN_COMPLETED_EVENT;
6983 break;
6984
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006985 default:
Yingying Tangaafa8e92016-09-29 16:09:00 +08006986 qdf_mem_free(tdls_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006987 WMA_LOGE("%s: unknown reason(%d) in tdls event(%d) from target",
6988 __func__, peer_event->peer_reason,
6989 peer_event->peer_status);
6990 return -EINVAL;
6991 }
6992
6993 WMA_LOGD("%s: sending msg to umac, messageType: 0x%x, "
6994 "for peer: %pM, reason: %d, smesessionId: %d",
Srinivas Girigowda4f593792015-11-19 15:33:42 -08006995 __func__, tdls_event->messageType, tdls_event->peermac.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006996 tdls_event->peer_reason, tdls_event->sessionId);
6997
6998 wma_send_msg(wma, tdls_event->messageType, (void *)tdls_event, 0);
6999 return 0;
7000}
7001
7002/**
7003 * wma_set_tdls_offchan_mode() - set tdls off channel mode
7004 * @handle: wma handle
7005 * @chan_switch_params: Pointer to tdls channel switch parameter structure
7006 *
7007 * This function sets tdls off channel mode
7008 *
7009 * Return: 0 on success; Negative errno otherwise
7010 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05307011QDF_STATUS wma_set_tdls_offchan_mode(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007012 tdls_chan_switch_params *chan_switch_params)
7013{
7014 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Himanshu Agarwal44195412016-03-09 13:03:54 +05307015 struct tdls_channel_switch_params params = {0};
7016 QDF_STATUS ret = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007017
7018 if (!wma_handle || !wma_handle->wmi_handle) {
7019 WMA_LOGE(FL(
7020 "WMA is closed, can not issue tdls off channel cmd"
7021 ));
7022 ret = -EINVAL;
7023 goto end;
7024 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007025
Himanshu Agarwal44195412016-03-09 13:03:54 +05307026 params.vdev_id = chan_switch_params->vdev_id;
7027 params.tdls_off_ch_bw_offset =
7028 chan_switch_params->tdls_off_ch_bw_offset;
7029 params.tdls_off_ch = chan_switch_params->tdls_off_ch;
7030 params.tdls_sw_mode = chan_switch_params->tdls_sw_mode;
7031 params.oper_class = chan_switch_params->oper_class;
7032 params.is_responder = chan_switch_params->is_responder;
7033 qdf_mem_copy(params.peer_mac_addr, chan_switch_params->peer_mac_addr,
Krunal Soniab793342016-04-22 18:43:20 -07007034 IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007035
Himanshu Agarwal44195412016-03-09 13:03:54 +05307036 ret = wmi_unified_set_tdls_offchan_mode_cmd(wma_handle->wmi_handle,
7037 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007038
7039end:
7040 if (chan_switch_params)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307041 qdf_mem_free(chan_switch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007042 return ret;
7043}
7044
7045/**
7046 * wma_update_fw_tdls_state() - send enable/disable tdls for a vdev
7047 * @wma: wma handle
7048 * @pwmaTdlsparams: TDLS params
7049 *
7050 * Return: 0 for sucess or error code
7051 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05307052QDF_STATUS wma_update_fw_tdls_state(WMA_HANDLE handle, void *pwmaTdlsparams)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007053{
7054 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007055 t_wma_tdls_mode tdls_mode;
7056 t_wma_tdls_params *wma_tdls = (t_wma_tdls_params *) pwmaTdlsparams;
Himanshu Agarwal44195412016-03-09 13:03:54 +05307057 struct wmi_tdls_params params = {0};
7058 QDF_STATUS ret = QDF_STATUS_SUCCESS;
7059 uint8_t tdls_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007060
7061 if (!wma_handle || !wma_handle->wmi_handle) {
7062 WMA_LOGE("%s: WMA is closed, can not issue fw tdls state cmd",
7063 __func__);
7064 ret = -EINVAL;
7065 goto end_fw_tdls_state;
7066 }
7067
Himanshu Agarwal44195412016-03-09 13:03:54 +05307068 params.tdls_state = wma_tdls->tdls_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007069 tdls_mode = wma_tdls->tdls_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007070
7071 if (WMA_TDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == tdls_mode) {
Himanshu Agarwal44195412016-03-09 13:03:54 +05307072 tdls_state = WMI_TDLS_ENABLE_PASSIVE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007073 } else if (WMA_TDLS_SUPPORT_ENABLED == tdls_mode) {
Kabilan Kannan14ec97f2016-05-16 23:48:25 -07007074 tdls_state = WMI_TDLS_ENABLE_CONNECTION_TRACKER_IN_HOST;
Kabilan Kannan421714b2015-11-23 04:44:59 -08007075 } else if (WMA_TDLS_SUPPORT_ACTIVE_EXTERNAL_CONTROL == tdls_mode) {
Kabilan Kannan14ec97f2016-05-16 23:48:25 -07007076 tdls_state = WMI_TDLS_ENABLE_CONNECTION_TRACKER_IN_HOST;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007077 } else {
Himanshu Agarwal44195412016-03-09 13:03:54 +05307078 tdls_state = WMI_TDLS_DISABLE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007079 }
7080
Himanshu Agarwal44195412016-03-09 13:03:54 +05307081 params.vdev_id = wma_tdls->vdev_id;
7082 params.notification_interval_ms = wma_tdls->notification_interval_ms;
7083 params.tx_discovery_threshold = wma_tdls->tx_discovery_threshold;
7084 params.tx_teardown_threshold = wma_tdls->tx_teardown_threshold;
7085 params.rssi_teardown_threshold = wma_tdls->rssi_teardown_threshold;
7086 params.rssi_delta = wma_tdls->rssi_delta;
7087 params.tdls_options = wma_tdls->tdls_options;
7088 params.peer_traffic_ind_window = wma_tdls->peer_traffic_ind_window;
7089 params.peer_traffic_response_timeout =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007090 wma_tdls->peer_traffic_response_timeout;
Himanshu Agarwal44195412016-03-09 13:03:54 +05307091 params.puapsd_mask = wma_tdls->puapsd_mask;
7092 params.puapsd_inactivity_time = wma_tdls->puapsd_inactivity_time;
7093 params.puapsd_rx_frame_threshold =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007094 wma_tdls->puapsd_rx_frame_threshold;
Himanshu Agarwal44195412016-03-09 13:03:54 +05307095 params.teardown_notification_ms =
Kabilan Kannanca670be2015-11-23 01:56:12 -08007096 wma_tdls->teardown_notification_ms;
Himanshu Agarwal44195412016-03-09 13:03:54 +05307097 params.tdls_peer_kickout_threshold =
Kabilan Kannan421714b2015-11-23 04:44:59 -08007098 wma_tdls->tdls_peer_kickout_threshold;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007099
Himanshu Agarwal44195412016-03-09 13:03:54 +05307100 ret = wmi_unified_update_fw_tdls_state_cmd(wma_handle->wmi_handle,
7101 &params, tdls_state);
7102 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007103 goto end_fw_tdls_state;
Himanshu Agarwal44195412016-03-09 13:03:54 +05307104
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007105 WMA_LOGD("%s: vdev_id %d", __func__, wma_tdls->vdev_id);
7106
7107end_fw_tdls_state:
7108 if (pwmaTdlsparams)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307109 qdf_mem_free(pwmaTdlsparams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007110 return ret;
7111}
7112
7113/**
7114 * wma_update_tdls_peer_state() - update TDLS peer state
7115 * @handle: wma handle
7116 * @peerStateParams: TDLS peer state params
7117 *
7118 * Return: 0 for success or error code
7119 */
7120int wma_update_tdls_peer_state(WMA_HANDLE handle,
7121 tTdlsPeerStateParams *peerStateParams)
7122{
7123 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007124 uint32_t i;
Leo Chang96464902016-10-28 11:10:54 -07007125 void *pdev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007126 uint8_t peer_id;
Leo Chang96464902016-10-28 11:10:54 -07007127 void *peer;
7128 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07007129 uint8_t *peer_mac_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007130 int ret = 0;
Kabilan Kannanc89fe712016-07-21 06:57:12 -07007131 uint32_t *ch_mhz = NULL;
Poddar, Siddarth5a91f5b2016-04-28 12:24:10 +05307132 bool restore_last_peer = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007133
7134 if (!wma_handle || !wma_handle->wmi_handle) {
7135 WMA_LOGE("%s: WMA is closed, can not issue cmd", __func__);
7136 ret = -EINVAL;
7137 goto end_tdls_peer_state;
7138 }
7139
Nishank Aggarwala13b61d2016-12-01 12:53:58 +05307140 if (!soc) {
7141 WMA_LOGE("%s: SOC context is NULL", __func__);
7142 ret = -EINVAL;
7143 goto end_tdls_peer_state;
7144 }
7145
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007146 /* peer capability info is valid only when peer state is connected */
7147 if (WMA_TDLS_PEER_STATE_CONNECTED != peerStateParams->peerState) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307148 qdf_mem_zero(&peerStateParams->peerCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007149 sizeof(tTdlsPeerCapParams));
7150 }
7151
Kabilan Kannanc89fe712016-07-21 06:57:12 -07007152 if (peerStateParams->peerCap.peerChanLen) {
7153 ch_mhz = qdf_mem_malloc(sizeof(uint32_t) *
7154 peerStateParams->peerCap.peerChanLen);
7155 if (ch_mhz == NULL) {
7156 WMA_LOGE("%s: memory allocation failed", __func__);
7157 ret = -ENOMEM;
7158 goto end_tdls_peer_state;
7159 }
Naveen Rawat35804772016-06-27 15:40:28 -07007160 }
7161
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007162 for (i = 0; i < peerStateParams->peerCap.peerChanLen; ++i) {
Govind Singhaa64c242016-03-08 11:31:49 +05307163 ch_mhz[i] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007164 cds_chan_to_freq(peerStateParams->peerCap.peerChan[i].
7165 chanId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007166 }
7167
Govind Singhaa64c242016-03-08 11:31:49 +05307168 if (wmi_unified_update_tdls_peer_state_cmd(wma_handle->wmi_handle,
7169 (struct tdls_peer_state_params *)peerStateParams,
7170 ch_mhz)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007171 WMA_LOGE("%s: failed to send tdls peer update state command",
7172 __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007173 ret = -EIO;
7174 goto end_tdls_peer_state;
7175 }
7176
7177 /* in case of teardown, remove peer from fw */
7178 if (WMA_TDLS_PEER_STATE_TEARDOWN == peerStateParams->peerState) {
Anurag Chouhan6d760662016-02-20 16:05:43 +05307179 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007180 if (!pdev) {
7181 WMA_LOGE("%s: Failed to find pdev", __func__);
7182 ret = -EIO;
7183 goto end_tdls_peer_state;
7184 }
7185
Leo Chang96464902016-10-28 11:10:54 -07007186 peer = cdp_peer_find_by_addr(soc, pdev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007187 peerStateParams->peerMacAddr,
7188 &peer_id);
7189 if (!peer) {
7190 WMA_LOGE("%s: Failed to get peer handle using peer mac %pM",
7191 __func__, peerStateParams->peerMacAddr);
7192 ret = -EIO;
7193 goto end_tdls_peer_state;
7194 }
Leo Chang96464902016-10-28 11:10:54 -07007195 peer_mac_addr = cdp_peer_get_peer_mac_addr(soc, peer);
Nishank Aggarwala13b61d2016-12-01 12:53:58 +05307196 if (peer_mac_addr == NULL) {
7197 WMA_LOGE("peer_mac_addr is NULL");
7198 ret = -EIO;
7199 goto end_tdls_peer_state;
7200 }
7201
Leo Chang96464902016-10-28 11:10:54 -07007202 restore_last_peer = cdp_peer_is_vdev_restore_last_peer(
7203 soc, peer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007204
7205 WMA_LOGD("%s: calling wma_remove_peer for peer " MAC_ADDRESS_STR
7206 " vdevId: %d", __func__,
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07007207 MAC_ADDR_ARRAY(peer_mac_addr),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007208 peerStateParams->vdevId);
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07007209 wma_remove_peer(wma_handle, peer_mac_addr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007210 peerStateParams->vdevId, peer, false);
Leo Chang96464902016-10-28 11:10:54 -07007211 cdp_peer_update_last_real_peer(soc, pdev, peer, &peer_id,
Poddar, Siddarth5a91f5b2016-04-28 12:24:10 +05307212 restore_last_peer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007213 }
7214
7215end_tdls_peer_state:
Kabilan Kannanc89fe712016-07-21 06:57:12 -07007216 if (ch_mhz)
7217 qdf_mem_free(ch_mhz);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007218 if (peerStateParams)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307219 qdf_mem_free(peerStateParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007220 return ret;
7221}
7222#endif /* FEATURE_WLAN_TDLS */
7223
7224
7225/**
7226 * wma_dfs_attach() - Attach DFS methods to the umac state.
7227 * @dfs_ic: ieee80211com ptr
7228 *
7229 * Return: Return ieee80211com ptr with updated info
7230 */
7231struct ieee80211com *wma_dfs_attach(struct ieee80211com *dfs_ic)
7232{
7233 /*Allocate memory for dfs_ic before passing it up to dfs_attach() */
7234 dfs_ic = (struct ieee80211com *)
7235 os_malloc(NULL, sizeof(struct ieee80211com), GFP_ATOMIC);
7236 if (dfs_ic == NULL) {
7237 WMA_LOGE("%s:Allocation of dfs_ic failed %zu",
7238 __func__, sizeof(struct ieee80211com));
7239 return NULL;
7240 }
7241 OS_MEMZERO(dfs_ic, sizeof(struct ieee80211com));
7242 /* DFS pattern matching hooks */
7243 dfs_ic->ic_dfs_attach = ol_if_dfs_attach;
7244 dfs_ic->ic_dfs_disable = ol_if_dfs_disable;
7245 dfs_ic->ic_find_channel = ieee80211_find_channel;
7246 dfs_ic->ic_dfs_enable = ol_if_dfs_enable;
7247 dfs_ic->ic_ieee2mhz = ieee80211_ieee2mhz;
7248
7249 /* Hardware facing hooks */
7250 dfs_ic->ic_get_ext_busy = ol_if_dfs_get_ext_busy;
7251 dfs_ic->ic_get_mib_cycle_counts_pct =
7252 ol_if_dfs_get_mib_cycle_counts_pct;
7253 dfs_ic->ic_get_TSF64 = ol_if_get_tsf64;
7254
7255 /* NOL related hooks */
7256 dfs_ic->ic_dfs_usenol = ol_if_dfs_usenol;
7257 /*
7258 * Hooks from wma/dfs/ back
7259 * into the PE/SME
7260 * and shared DFS code
7261 */
7262 dfs_ic->ic_dfs_notify_radar = ieee80211_mark_dfs;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05307263 qdf_spinlock_create(&dfs_ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007264 /* Initializes DFS Data Structures and queues */
7265 dfs_attach(dfs_ic);
7266
7267 return dfs_ic;
7268}
7269
7270/**
7271 * wma_dfs_detach() - Detach DFS methods
7272 * @dfs_ic: ieee80211com ptr
7273 *
7274 * Return: none
7275 */
7276void wma_dfs_detach(struct ieee80211com *dfs_ic)
7277{
7278 dfs_detach(dfs_ic);
7279
Anurag Chouhana37b5b72016-02-21 14:53:42 +05307280 qdf_spinlock_destroy(&dfs_ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007281 if (NULL != dfs_ic->ic_curchan) {
7282 OS_FREE(dfs_ic->ic_curchan);
7283 dfs_ic->ic_curchan = NULL;
7284 }
7285
7286 OS_FREE(dfs_ic);
7287}
7288
7289/**
7290 * wma_dfs_configure() - configure dfs
7291 * @ic: ieee80211com ptr
7292 *
7293 * Configures Radar Filters during
7294 * vdev start/channel change/regulatory domain
7295 * change.This Configuration enables to program
7296 * the DFS pattern matching module.
7297 *
7298 * Return: none
7299 */
7300void wma_dfs_configure(struct ieee80211com *ic)
7301{
7302 struct ath_dfs_radar_tab_info rinfo;
7303 int dfsdomain;
7304 int radar_enabled_status = 0;
7305 if (ic == NULL) {
7306 WMA_LOGE("%s: DFS ic is Invalid", __func__);
7307 return;
7308 }
7309
7310 dfsdomain = ic->current_dfs_regdomain;
7311
7312 /* Fetch current radar patterns from the lmac */
7313 OS_MEMZERO(&rinfo, sizeof(rinfo));
7314
7315 /*
7316 * Look up the current DFS
7317 * regulatory domain and decide
7318 * which radar pulses to use.
7319 */
7320 switch (dfsdomain) {
Amar Singhala7bb01b2016-01-27 11:31:59 -08007321 case DFS_FCC_REGION:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007322 WMA_LOGI("%s: DFS-FCC domain", __func__);
Amar Singhala7bb01b2016-01-27 11:31:59 -08007323 rinfo.dfsdomain = DFS_FCC_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007324 rinfo.dfs_radars = dfs_fcc_radars;
Anurag Chouhan6d760662016-02-20 16:05:43 +05307325 rinfo.numradars = QDF_ARRAY_SIZE(dfs_fcc_radars);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007326 rinfo.b5pulses = dfs_fcc_bin5pulses;
Anurag Chouhan6d760662016-02-20 16:05:43 +05307327 rinfo.numb5radars = QDF_ARRAY_SIZE(dfs_fcc_bin5pulses);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007328 break;
Amar Singhala7bb01b2016-01-27 11:31:59 -08007329 case DFS_ETSI_REGION:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007330 WMA_LOGI("%s: DFS-ETSI domain", __func__);
Amar Singhala7bb01b2016-01-27 11:31:59 -08007331 rinfo.dfsdomain = DFS_ETSI_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007332 rinfo.dfs_radars = dfs_etsi_radars;
Anurag Chouhan6d760662016-02-20 16:05:43 +05307333 rinfo.numradars = QDF_ARRAY_SIZE(dfs_etsi_radars);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007334 rinfo.b5pulses = NULL;
7335 rinfo.numb5radars = 0;
7336 break;
Amar Singhala7bb01b2016-01-27 11:31:59 -08007337 case DFS_MKK_REGION:
7338 WMA_LOGI("%s: DFS-MKK domain", __func__);
7339 rinfo.dfsdomain = DFS_MKK_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007340 rinfo.dfs_radars = dfs_mkk4_radars;
Anurag Chouhan6d760662016-02-20 16:05:43 +05307341 rinfo.numradars = QDF_ARRAY_SIZE(dfs_mkk4_radars);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007342 rinfo.b5pulses = dfs_jpn_bin5pulses;
Anurag Chouhan6d760662016-02-20 16:05:43 +05307343 rinfo.numb5radars = QDF_ARRAY_SIZE(dfs_jpn_bin5pulses);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007344 break;
Arif Hussainaca67302016-07-28 17:25:00 -07007345 case DFS_CN_REGION:
7346 WMA_LOGI("%s: DFS-CN domain", __func__);
7347 rinfo.dfsdomain = DFS_CN_REGION;
7348 rinfo.dfs_radars = dfs_china_radars;
7349 rinfo.numradars = QDF_ARRAY_SIZE(dfs_china_radars);
7350 rinfo.b5pulses = NULL;
7351 rinfo.numb5radars = 0;
7352 break;
7353 case DFS_KR_REGION:
7354 WMA_LOGI("%s: DFS-KR domain", __func__);
7355 rinfo.dfsdomain = DFS_KR_REGION;
7356 rinfo.dfs_radars = dfs_korea_radars;
7357 rinfo.numradars = QDF_ARRAY_SIZE(dfs_korea_radars);
7358 rinfo.b5pulses = NULL;
7359 rinfo.numb5radars = 0;
7360 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007361 default:
7362 WMA_LOGI("%s: DFS-UNINT domain", __func__);
Amar Singhala7bb01b2016-01-27 11:31:59 -08007363 rinfo.dfsdomain = DFS_UNINIT_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007364 rinfo.dfs_radars = NULL;
7365 rinfo.numradars = 0;
7366 rinfo.b5pulses = NULL;
7367 rinfo.numb5radars = 0;
7368 break;
7369 }
7370
7371 rinfo.dfs_pri_multiplier = ic->dfs_pri_multiplier;
7372
7373 /*
7374 * Set the regulatory domain,
7375 * radar pulse table and enable
7376 * radar events if required.
7377 * dfs_radar_enable() returns
7378 * 0 on success and non-zero
7379 * failure.
7380 */
7381 radar_enabled_status = dfs_radar_enable(ic, &rinfo);
7382 if (radar_enabled_status != DFS_STATUS_SUCCESS) {
7383 WMA_LOGE("%s[%d]: DFS- Radar Detection Enabling Failed",
7384 __func__, __LINE__);
7385 }
7386}
7387
7388/**
7389 * wma_dfs_configure_channel() - configure DFS channel
7390 * @dfs_ic: ieee80211com ptr
Siddarth Poddar17dc4712016-03-09 16:30:27 +05307391 * @band_center_freq1: center frequency 1
7392 * @band_center_freq2: center frequency 2
7393 * (valid only for 11ac vht 80plus80 mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007394 * @ req: vdev start request
7395 *
7396 * Set the Channel parameters in to DFS module
7397 * Also,configure the DFS radar filters for
7398 * matching the DFS phyerrors.
7399 *
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05307400 * Return: dfs_ieee80211_channel / NULL for error
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007401 */
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05307402struct dfs_ieee80211_channel *wma_dfs_configure_channel(
7403 struct ieee80211com *dfs_ic,
Siddarth Poddar17dc4712016-03-09 16:30:27 +05307404 uint32_t band_center_freq1,
7405 uint32_t band_center_freq2,
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05307406 struct wma_vdev_start_req
7407 *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007408{
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08007409 uint8_t ext_channel;
7410
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007411 if (dfs_ic == NULL) {
7412 WMA_LOGE("%s: DFS ic is Invalid", __func__);
7413 return NULL;
7414 }
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05307415
7416 if (!dfs_ic->ic_curchan) {
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05307417 dfs_ic->ic_curchan = (struct dfs_ieee80211_channel *)os_malloc(
7418 NULL,
7419 sizeof(struct dfs_ieee80211_channel),
7420 GFP_ATOMIC);
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05307421 if (dfs_ic->ic_curchan == NULL) {
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05307422 WMA_LOGE(
7423 "%s: allocation of dfs_ic->ic_curchan failed %zu",
7424 __func__, sizeof(struct dfs_ieee80211_channel));
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05307425 return NULL;
7426 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007427 }
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05307428
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05307429 OS_MEMZERO(dfs_ic->ic_curchan, sizeof(struct dfs_ieee80211_channel));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007430
7431 dfs_ic->ic_curchan->ic_ieee = req->chan;
Siddarth Poddar17dc4712016-03-09 16:30:27 +05307432 dfs_ic->ic_curchan->ic_freq = cds_chan_to_freq(req->chan);
7433 dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg1 = band_center_freq1;
7434 dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg2 = band_center_freq2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007435 dfs_ic->ic_curchan->ic_pri_freq_center_freq_mhz_separation =
7436 dfs_ic->ic_curchan->ic_freq -
7437 dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg1;
7438
7439 if ((dfs_ic->ic_curchan->ic_ieee >= WMA_11A_CHANNEL_BEGIN) &&
7440 (dfs_ic->ic_curchan->ic_ieee <= WMA_11A_CHANNEL_END)) {
7441 dfs_ic->ic_curchan->ic_flags |= IEEE80211_CHAN_5GHZ;
7442 }
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08007443
7444 switch (req->chan_width) {
7445 case CH_WIDTH_20MHZ:
7446 dfs_ic->ic_curchan->ic_flags |=
7447 (req->vht_capable ? IEEE80211_CHAN_VHT20 :
7448 IEEE80211_CHAN_HT20);
7449 break;
7450 case CH_WIDTH_40MHZ:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007451 if (req->chan < req->ch_center_freq_seg0)
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08007452 dfs_ic->ic_curchan->ic_flags |=
7453 (req->vht_capable ?
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007454 IEEE80211_CHAN_VHT40PLUS :
7455 IEEE80211_CHAN_HT40PLUS);
7456 else
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08007457 dfs_ic->ic_curchan->ic_flags |=
7458 (req->vht_capable ?
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007459 IEEE80211_CHAN_VHT40MINUS :
7460 IEEE80211_CHAN_HT40MINUS);
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08007461 break;
7462 case CH_WIDTH_80MHZ:
7463 dfs_ic->ic_curchan->ic_flags |= IEEE80211_CHAN_VHT80;
7464 break;
7465 case CH_WIDTH_80P80MHZ:
Siddarth Poddar17dc4712016-03-09 16:30:27 +05307466 ext_channel = cds_freq_to_chan(band_center_freq2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007467 dfs_ic->ic_curchan->ic_flags |=
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08007468 IEEE80211_CHAN_VHT80P80;
7469 dfs_ic->ic_curchan->ic_freq_ext =
Siddarth Poddar17dc4712016-03-09 16:30:27 +05307470 band_center_freq2;
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08007471 dfs_ic->ic_curchan->ic_ieee_ext = ext_channel;
7472
7473 /* verify both the 80MHz are DFS bands or not */
Rajeev Kumara3f6c2d2016-04-15 12:47:41 -07007474 if ((CHANNEL_STATE_DFS ==
7475 cds_get_5g_bonded_channel_state(req->chan ,
7476 CH_WIDTH_80MHZ)) &&
7477 (CHANNEL_STATE_DFS == cds_get_5g_bonded_channel_state(
7478 ext_channel - WMA_80MHZ_START_CENTER_CH_DIFF,
7479 CH_WIDTH_80MHZ)))
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08007480 dfs_ic->ic_curchan->ic_80p80_both_dfs = true;
7481 break;
7482 case CH_WIDTH_160MHZ:
7483 dfs_ic->ic_curchan->ic_flags |=
7484 IEEE80211_CHAN_VHT160;
7485 break;
7486 default:
7487 WMA_LOGE(
7488 "%s: Recieved a wrong channel width %d",
7489 __func__, req->chan_width);
7490 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007491 }
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08007492
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007493 dfs_ic->ic_curchan->ic_flagext |= IEEE80211_CHAN_DFS;
7494
7495 if (req->oper_mode == BSS_OPERATIONAL_MODE_AP) {
7496 dfs_ic->ic_opmode = IEEE80211_M_HOSTAP;
7497 dfs_ic->vdev_id = req->vdev_id;
7498 }
7499
7500 dfs_ic->dfs_pri_multiplier = req->dfs_pri_multiplier;
7501
7502 /*
7503 * Configuring the DFS with current channel and the radar filters
7504 */
7505 wma_dfs_configure(dfs_ic);
7506 WMA_LOGI("%s: DFS- CHANNEL CONFIGURED", __func__);
7507 return dfs_ic->ic_curchan;
7508}
7509
7510
7511/**
7512 * wma_set_dfs_region() - set DFS region
7513 * @wma: wma handle
7514 *
7515 * Configure the DFS region for DFS radar filter initialization
7516 *
7517 * Return: none
7518 */
Amar Singhal604ba6cf2016-07-27 15:29:51 -07007519void wma_set_dfs_region(tp_wma_handle wma, enum dfs_region dfs_region)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007520{
Amar Singhal604ba6cf2016-07-27 15:29:51 -07007521 if (dfs_region >= DFS_UNDEF_REGION ||
7522 dfs_region == DFS_UNINIT_REGION)
7523
Amar Singhala7bb01b2016-01-27 11:31:59 -08007524 /* assign DFS_FCC_REGION as default region*/
7525 wma->dfs_ic->current_dfs_regdomain = DFS_FCC_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007526 else
7527 wma->dfs_ic->current_dfs_regdomain = dfs_region;
7528
7529 WMA_LOGI("%s: DFS Region Domain: %d", __func__,
7530 wma->dfs_ic->current_dfs_regdomain);
7531}
7532
7533/**
7534 * wma_get_channels() - prepare dfs radar channel list
7535 * @ichan: channel
7536 * @chan_list: return channel list
7537 *
7538 * Return: return number of channels
7539 */
Jeff Johnsonc4b47a92016-10-07 12:34:41 -07007540static int wma_get_channels(struct dfs_ieee80211_channel *ichan,
7541 struct wma_dfs_radar_channel_list *chan_list)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007542{
7543 uint8_t center_chan = cds_freq_to_chan(ichan->ic_vhtop_ch_freq_seg1);
Vishwajith Upendrabf673e72016-01-19 16:05:40 -08007544 int count = 0;
7545 int start_channel = 0;
7546 int loop;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007547
7548 chan_list->nchannels = 0;
7549
Vishwajith Upendrabf673e72016-01-19 16:05:40 -08007550 if (IEEE80211_IS_CHAN_11AC_VHT160(ichan)) {
Arif Hussaine69337b2016-08-01 12:28:35 -07007551
7552 /*
7553 * as per the latest draft for BSS bandwidth 160MHz,
7554 * channel frequency segment 2 represents the center
7555 * channel frequency.
7556 */
7557 if (ichan->ic_vhtop_ch_freq_seg2)
7558 center_chan =
7559 cds_freq_to_chan(ichan->ic_vhtop_ch_freq_seg2);
Vishwajith Upendrabf673e72016-01-19 16:05:40 -08007560 /*
7561 * In 160MHz channel width, need to
7562 * check if each of the 8 20MHz channel
7563 * is DFS before adding to the NOL list.
7564 * As it is possible that part of the
7565 * 160MHz can be Non-DFS channels.
7566 */
7567 start_channel = center_chan - WMA_160MHZ_START_CENTER_CH_DIFF;
7568 for (loop = 0; loop < WMA_DFS_MAX_20M_SUB_CH; loop++) {
7569 if (cds_get_channel_state(start_channel +
7570 (loop * WMA_NEXT_20MHZ_START_CH_DIFF)) ==
7571 CHANNEL_STATE_DFS) {
7572 chan_list->channels[count] = start_channel +
7573 (loop * WMA_NEXT_20MHZ_START_CH_DIFF);
7574 count++;
7575 }
7576 }
7577 chan_list->nchannels = count;
7578 } else if (IEEE80211_IS_CHAN_11AC_VHT80P80(ichan)) {
7579 chan_list->nchannels = 4;
7580 /*
7581 * If SAP is operating in 80p80 mode, either
7582 * one of the two 80 segments or both the 80
7583 * segments can be DFS channels, so need to
7584 * identify on which 80 segment radar has
7585 * been detected and only add those channels
7586 * to the NOL list. center frequency should be
7587 * based on the segment id passed as part of
7588 * channel information in radar indication.
7589 */
7590 if (ichan->ic_radar_found_segid == DFS_80P80_SEG1)
7591 center_chan =
7592 cds_freq_to_chan(ichan->ic_vhtop_ch_freq_seg2);
7593 chan_list->channels[0] = center_chan - 6;
7594 chan_list->channels[1] = center_chan - 2;
7595 chan_list->channels[2] = center_chan + 2;
7596 chan_list->channels[3] = center_chan + 6;
7597 } else if (IEEE80211_IS_CHAN_11AC_VHT80(ichan)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007598 chan_list->nchannels = 4;
7599 chan_list->channels[0] = center_chan - 6;
7600 chan_list->channels[1] = center_chan - 2;
7601 chan_list->channels[2] = center_chan + 2;
7602 chan_list->channels[3] = center_chan + 6;
7603 } else if (IEEE80211_IS_CHAN_11N_HT40(ichan) ||
7604 IEEE80211_IS_CHAN_11AC_VHT40(ichan)) {
7605 chan_list->nchannels = 2;
7606 chan_list->channels[0] = center_chan - 2;
7607 chan_list->channels[1] = center_chan + 2;
7608 } else {
7609 chan_list->nchannels = 1;
7610 chan_list->channels[0] = center_chan;
7611 }
7612
7613 return chan_list->nchannels;
7614}
7615
7616
7617/**
7618 * wma_dfs_indicate_radar() - Indicate Radar to SAP/HDD
7619 * @ic: ieee80211com ptr
7620 * @ichan: ieee 80211 channel
7621 *
7622 * Return: 0 for success or error code
7623 */
7624int wma_dfs_indicate_radar(struct ieee80211com *ic,
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05307625 struct dfs_ieee80211_channel *ichan)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007626{
7627 tp_wma_handle wma;
7628 void *hdd_ctx;
7629 struct wma_dfs_radar_indication *radar_event;
7630 struct wma_dfs_radar_ind wma_radar_event;
7631 tpAniSirGlobal pmac = NULL;
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05307632 bool indication_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007633
Anurag Chouhan6d760662016-02-20 16:05:43 +05307634 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007635 if (wma == NULL) {
7636 WMA_LOGE("%s: DFS- Invalid wma", __func__);
7637 return -ENOENT;
7638 }
7639
Anurag Chouhan6d760662016-02-20 16:05:43 +05307640 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007641 pmac = (tpAniSirGlobal)
Anurag Chouhan6d760662016-02-20 16:05:43 +05307642 cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007643
7644 if (!pmac) {
7645 WMA_LOGE("%s: Invalid MAC handle", __func__);
7646 return -ENOENT;
7647 }
7648
7649 if (wma->dfs_ic != ic) {
7650 WMA_LOGE("%s:DFS- Invalid WMA handle", __func__);
7651 return -ENOENT;
7652 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007653
7654 /*
7655 * Do not post multiple Radar events on the same channel.
7656 * But, when DFS test mode is enabled, allow multiple dfs
7657 * radar events to be posted on the same channel.
7658 */
Anurag Chouhana37b5b72016-02-21 14:53:42 +05307659 qdf_spin_lock_bh(&ic->chan_lock);
Edhar, Mahesh Kumar35d9b2e2015-10-26 17:06:23 +05307660 if (!pmac->sap.SapDfsInfo.disable_dfs_ch_switch)
7661 wma->dfs_ic->disable_phy_err_processing = true;
7662
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007663 if ((ichan->ic_ieee != (wma->dfs_ic->last_radar_found_chan)) ||
7664 (pmac->sap.SapDfsInfo.disable_dfs_ch_switch == true)) {
Kapil Gupta155748e2016-10-01 13:20:20 +05307665 radar_event = (struct wma_dfs_radar_indication *)
7666 qdf_mem_malloc(sizeof(struct wma_dfs_radar_indication));
7667 if (radar_event == NULL) {
7668 WMA_LOGE(FL("Failed to allocate memory for radar_event"));
Arif Hussain941630a2016-10-25 14:58:06 -07007669 qdf_spin_unlock_bh(&ic->chan_lock);
Kapil Gupta155748e2016-10-01 13:20:20 +05307670 return -ENOMEM;
7671 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007672 wma->dfs_ic->last_radar_found_chan = ichan->ic_ieee;
7673 /* Indicate the radar event to HDD to stop the netif Tx queues */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007674 wma_radar_event.chan_freq = ichan->ic_freq;
7675 wma_radar_event.dfs_radar_status = WMA_DFS_RADAR_FOUND;
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05307676 indication_status =
7677 wma->dfs_radar_indication_cb(hdd_ctx, &wma_radar_event);
7678 if (indication_status == false) {
7679 WMA_LOGE("%s:Application triggered channel switch in progress!.. drop radar event indiaction to SAP",
7680 __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307681 qdf_mem_free(radar_event);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05307682 qdf_spin_unlock_bh(&ic->chan_lock);
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05307683 return 0;
7684 }
7685
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007686 WMA_LOGE("%s:DFS- RADAR INDICATED TO HDD", __func__);
7687
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05307688 wma_radar_event.ieee_chan_number = ichan->ic_ieee;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007689 /*
7690 * Indicate to the radar event to SAP to
7691 * select a new channel and set CSA IE
7692 */
7693 radar_event->vdev_id = ic->vdev_id;
7694 wma_get_channels(ichan, &radar_event->chan_list);
7695 radar_event->dfs_radar_status = WMA_DFS_RADAR_FOUND;
7696 radar_event->use_nol = ic->ic_dfs_usenol(ic);
7697 wma_send_msg(wma, WMA_DFS_RADAR_IND, (void *)radar_event, 0);
7698 WMA_LOGE("%s:DFS- WMA_DFS_RADAR_IND Message Posted", __func__);
7699 }
Anurag Chouhana37b5b72016-02-21 14:53:42 +05307700 qdf_spin_unlock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007701
7702 return 0;
7703}
7704
7705#ifdef WLAN_FEATURE_MEMDUMP
7706/*
7707 * wma_process_fw_mem_dump_req() - Function to request fw memory dump from
7708 * firmware
7709 * @wma: Pointer to WMA handle
7710 * @mem_dump_req: Pointer for mem_dump_req
7711 *
7712 * This function sends memory dump request to firmware
7713 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307714 * Return: QDF_STATUS_SUCCESS for success otherwise failure
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007715 *
7716 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307717QDF_STATUS wma_process_fw_mem_dump_req(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007718 struct fw_dump_req *mem_dump_req)
7719{
Govind Singhaa64c242016-03-08 11:31:49 +05307720 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007721
7722 if (!mem_dump_req || !wma) {
7723 WMA_LOGE(FL("input pointer is NULL"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307724 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007725 }
7726
Govind Singhaa64c242016-03-08 11:31:49 +05307727 ret = wmi_unified_process_fw_mem_dump_cmd(wma->wmi_handle,
7728 (struct fw_dump_req_param *) mem_dump_req);
7729 if (ret)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307730 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007731
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307732 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007733}
7734
7735/**
7736 * wma_fw_mem_dump_rsp() - send fw mem dump response to SME
7737 *
7738 * @req_id - request id.
7739 * @status - copy status from the firmware.
7740 *
7741 * This function is called by the memory dump response handler to
7742 * indicate SME that firmware dump copy is complete
7743 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307744 * Return: QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007745 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307746static QDF_STATUS wma_fw_mem_dump_rsp(uint32_t req_id, uint32_t status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007747{
7748 struct fw_dump_rsp *dump_rsp;
7749 cds_msg_t sme_msg = {0};
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307750 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007751
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307752 dump_rsp = qdf_mem_malloc(sizeof(*dump_rsp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007753
7754 if (!dump_rsp) {
7755 WMA_LOGE(FL("Memory allocation failed."));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307756 qdf_status = QDF_STATUS_E_NOMEM;
7757 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007758 }
7759
7760 WMA_LOGI(FL("FW memory dump copy complete status: %d for request: %d"),
7761 status, req_id);
7762
7763 dump_rsp->request_id = req_id;
7764 dump_rsp->dump_complete = status;
7765
7766 sme_msg.type = eWNI_SME_FW_DUMP_IND;
7767 sme_msg.bodyptr = dump_rsp;
7768 sme_msg.bodyval = 0;
7769
Anurag Chouhan6d760662016-02-20 16:05:43 +05307770 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307771 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007772 WMA_LOGE(FL("Fail to post fw mem dump ind msg"));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307773 qdf_mem_free(dump_rsp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007774 }
7775
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307776 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007777}
7778
7779/**
7780 * wma_fw_mem_dump_event_handler() - handles fw memory dump event
7781 *
7782 * @handle: pointer to wma handle.
7783 * @cmd_param_info: pointer to TLV info received in the event.
7784 * @len: length of data in @cmd_param_info
7785 *
7786 * This function is a handler for firmware memory dump event.
7787 *
7788 * Return: integer (0 for success and error code otherwise)
7789 */
7790int wma_fw_mem_dump_event_handler(void *handle, u_int8_t *cmd_param_info,
7791 u_int32_t len)
7792{
7793 WMI_UPDATE_FW_MEM_DUMP_EVENTID_param_tlvs *param_buf;
7794 wmi_update_fw_mem_dump_fixed_param *event;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307795 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007796
7797 param_buf =
7798 (WMI_UPDATE_FW_MEM_DUMP_EVENTID_param_tlvs *) cmd_param_info;
7799 if (!param_buf) {
7800 WMA_LOGA("%s: Invalid stats event", __func__);
7801 return -EINVAL;
7802 }
7803
7804 event = param_buf->fixed_param;
7805
7806 status = wma_fw_mem_dump_rsp(event->request_id,
7807 event->fw_mem_dump_complete);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307808 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007809 WMA_LOGE("Error posting FW MEM DUMP RSP.");
7810 return -EINVAL;
7811 }
7812
7813 WMA_LOGI("FW MEM DUMP RSP posted successfully");
7814 return 0;
7815}
7816#endif /* WLAN_FEATURE_MEMDUMP */
7817
7818/*
7819 * wma_process_set_ie_info() - Function to send IE info to firmware
7820 * @wma: Pointer to WMA handle
7821 * @ie_data: Pointer for ie data
7822 *
7823 * This function sends IE information to firmware
7824 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307825 * Return: QDF_STATUS_SUCCESS for success otherwise failure
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007826 *
7827 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307828QDF_STATUS wma_process_set_ie_info(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007829 struct vdev_ie_info *ie_info)
7830{
Govind Singhaa64c242016-03-08 11:31:49 +05307831 struct vdev_ie_info_param cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007832 int ret;
7833
7834 if (!ie_info || !wma) {
7835 WMA_LOGE(FL("input pointer is NULL"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307836 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007837 }
7838
7839 /* Validate the input */
7840 if (ie_info->length <= 0) {
7841 WMA_LOGE(FL("Invalid IE length"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307842 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007843 }
7844
Govind Singhaa64c242016-03-08 11:31:49 +05307845 cmd.vdev_id = ie_info->vdev_id;
7846 cmd.ie_id = ie_info->ie_id;
7847 cmd.length = ie_info->length;
Naveen Rawat03e8d952016-08-01 15:22:20 -07007848 cmd.band = ie_info->band;
Govind Singhaa64c242016-03-08 11:31:49 +05307849 cmd.data = ie_info->data;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05307850 cmd.ie_source = WMA_SET_VDEV_IE_SOURCE_HOST;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007851
Naveen Rawat03e8d952016-08-01 15:22:20 -07007852 WMA_LOGD(FL("ie_id: %d, band: %d, len: %d"),
7853 ie_info->ie_id, ie_info->band, ie_info->length);
7854
7855 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_DEBUG,
7856 ie_info->data, ie_info->length);
7857
Govind Singhaa64c242016-03-08 11:31:49 +05307858 ret = wmi_unified_process_set_ie_info_cmd(wma->wmi_handle,
7859 &cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007860 return ret;
7861}
7862
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307863/**
7864 * wma_get_bpf_caps_event_handler() - Event handler for get bpf capability
7865 * @handle: WMA global handle
7866 * @cmd_param_info: command event data
7867 * @len: Length of @cmd_param_info
7868 *
7869 * Return: 0 on Success or Errno on failure
7870 */
7871int wma_get_bpf_caps_event_handler(void *handle,
7872 u_int8_t *cmd_param_info,
7873 u_int32_t len)
7874{
7875 WMI_BPF_CAPABILIY_INFO_EVENTID_param_tlvs *param_buf;
7876 wmi_bpf_capability_info_evt_fixed_param *event;
7877 struct sir_bpf_get_offload *bpf_get_offload;
7878 tpAniSirGlobal pmac = (tpAniSirGlobal)cds_get_context(
7879 QDF_MODULE_ID_PE);
7880
7881 if (!pmac) {
7882 WMA_LOGE("%s: Invalid pmac", __func__);
7883 return -EINVAL;
7884 }
7885 if (!pmac->sme.pbpf_get_offload_cb) {
7886 WMA_LOGE("%s: Callback not registered", __func__);
7887 return -EINVAL;
7888 }
7889
7890 param_buf = (WMI_BPF_CAPABILIY_INFO_EVENTID_param_tlvs *)cmd_param_info;
7891 event = param_buf->fixed_param;
7892 bpf_get_offload = qdf_mem_malloc(sizeof(*bpf_get_offload));
7893
7894 if (!bpf_get_offload) {
7895 WMA_LOGP("%s: Memory allocation failed.", __func__);
7896 return -ENOMEM;
7897 }
7898
7899 bpf_get_offload->bpf_version = event->bpf_version;
7900 bpf_get_offload->max_bpf_filters = event->max_bpf_filters;
7901 bpf_get_offload->max_bytes_for_bpf_inst =
7902 event->max_bytes_for_bpf_inst;
7903 WMA_LOGD("%s: BPF capabilities version: %d max bpf filter size: %d",
7904 __func__, bpf_get_offload->bpf_version,
7905 bpf_get_offload->max_bytes_for_bpf_inst);
7906
7907 WMA_LOGD("%s: sending bpf capabilities event to hdd", __func__);
7908 pmac->sme.pbpf_get_offload_cb(pmac->hHdd, bpf_get_offload);
7909 qdf_mem_free(bpf_get_offload);
7910 return 0;
7911}
7912
7913/**
7914 * wma_get_bpf_capabilities - Send get bpf capability to firmware
7915 * @wma_handle: wma handle
7916 *
7917 * Return: QDF_STATUS enumeration.
7918 */
7919QDF_STATUS wma_get_bpf_capabilities(tp_wma_handle wma)
7920{
7921 QDF_STATUS status = QDF_STATUS_SUCCESS;
7922 wmi_bpf_get_capability_cmd_fixed_param *cmd;
7923 wmi_buf_t wmi_buf;
7924 uint32_t len;
7925 u_int8_t *buf_ptr;
7926
7927 if (!wma || !wma->wmi_handle) {
7928 WMA_LOGE(FL("WMA is closed, can not issue get BPF capab"));
7929 return QDF_STATUS_E_INVAL;
7930 }
7931
7932 if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
7933 WMI_SERVICE_BPF_OFFLOAD)) {
7934 WMA_LOGE(FL("BPF cababilities feature bit not enabled"));
7935 return QDF_STATUS_E_FAILURE;
7936 }
7937
7938 len = sizeof(*cmd);
7939 wmi_buf = wmi_buf_alloc(wma->wmi_handle, len);
7940 if (!wmi_buf) {
7941 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
7942 return QDF_STATUS_E_NOMEM;
7943 }
7944
7945 buf_ptr = (u_int8_t *) wmi_buf_data(wmi_buf);
7946 cmd = (wmi_bpf_get_capability_cmd_fixed_param *) buf_ptr;
7947 WMITLV_SET_HDR(&cmd->tlv_header,
7948 WMITLV_TAG_STRUC_wmi_bpf_get_capability_cmd_fixed_param,
7949 WMITLV_GET_STRUCT_TLVLEN(
7950 wmi_bpf_get_capability_cmd_fixed_param));
7951
7952 if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len,
7953 WMI_BPF_GET_CAPABILITY_CMDID)) {
7954 WMA_LOGE(FL("Failed to send BPF capability command"));
7955 wmi_buf_free(wmi_buf);
7956 return QDF_STATUS_E_FAILURE;
7957 }
7958 return status;
7959}
7960
7961/**
7962 * wma_set_bpf_instructions - Set bpf instructions to firmware
7963 * @wma: wma handle
7964 * @bpf_set_offload: Bpf offload information to set to firmware
7965 *
7966 * Return: QDF_STATUS enumeration
7967 */
7968QDF_STATUS wma_set_bpf_instructions(tp_wma_handle wma,
7969 struct sir_bpf_set_offload *bpf_set_offload)
7970{
7971 wmi_bpf_set_vdev_instructions_cmd_fixed_param *cmd;
7972 wmi_buf_t wmi_buf;
7973 uint32_t len = 0, len_aligned = 0;
7974 u_int8_t *buf_ptr;
7975
7976 if (!wma || !wma->wmi_handle) {
7977 WMA_LOGE("%s: WMA is closed, can not issue set BPF capability",
7978 __func__);
7979 return QDF_STATUS_E_INVAL;
7980 }
7981
7982 if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
7983 WMI_SERVICE_BPF_OFFLOAD)) {
7984 WMA_LOGE(FL("BPF offload feature Disabled"));
7985 return QDF_STATUS_E_NOSUPPORT;
7986 }
7987
7988 if (bpf_set_offload->total_length) {
7989 len_aligned = roundup(bpf_set_offload->current_length,
7990 sizeof(A_UINT32));
7991 len = len_aligned + WMI_TLV_HDR_SIZE;
7992 }
7993
7994 len += sizeof(*cmd);
7995 wmi_buf = wmi_buf_alloc(wma->wmi_handle, len);
7996 if (!wmi_buf) {
7997 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
7998 return QDF_STATUS_E_NOMEM;
7999 }
8000
8001 buf_ptr = (u_int8_t *) wmi_buf_data(wmi_buf);
8002 cmd = (wmi_bpf_set_vdev_instructions_cmd_fixed_param *) buf_ptr;
8003
8004 WMITLV_SET_HDR(&cmd->tlv_header,
8005 WMITLV_TAG_STRUC_wmi_bpf_set_vdev_instructions_cmd_fixed_param,
8006 WMITLV_GET_STRUCT_TLVLEN(
8007 wmi_bpf_set_vdev_instructions_cmd_fixed_param));
8008 cmd->vdev_id = bpf_set_offload->session_id;
8009 cmd->filter_id = bpf_set_offload->filter_id;
8010 cmd->total_length = bpf_set_offload->total_length;
8011 cmd->current_offset = bpf_set_offload->current_offset;
8012 cmd->current_length = bpf_set_offload->current_length;
8013
8014 if (bpf_set_offload->total_length) {
8015 buf_ptr +=
8016 sizeof(wmi_bpf_set_vdev_instructions_cmd_fixed_param);
8017 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, len_aligned);
8018 buf_ptr += WMI_TLV_HDR_SIZE;
8019 qdf_mem_copy(buf_ptr, bpf_set_offload->program,
8020 bpf_set_offload->current_length);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308021 }
8022
8023 if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len,
8024 WMI_BPF_SET_VDEV_INSTRUCTIONS_CMDID)) {
8025 WMA_LOGE(FL("Failed to send config bpf instructions command"));
8026 wmi_buf_free(wmi_buf);
8027 return QDF_STATUS_E_FAILURE;
8028 }
8029 return QDF_STATUS_SUCCESS;
8030}
Peng Xu8fdaa492016-06-22 10:20:47 -07008031
8032/**
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05308033 * wma_set_tx_rx_aggregation_size() - sets tx rx aggregation sizes
8034 * @tx_rx_aggregation_size: aggregation size parameters
8035 *
8036 * This function sets tx rx aggregation sizes
8037 *
8038 * Return: VOS_STATUS_SUCCESS on success, error number otherwise
8039 */
8040QDF_STATUS wma_set_tx_rx_aggregation_size(
8041 struct sir_set_tx_rx_aggregation_size *tx_rx_aggregation_size)
8042{
8043 tp_wma_handle wma_handle;
8044 wmi_vdev_set_custom_aggr_size_cmd_fixed_param *cmd;
8045 int32_t len;
8046 wmi_buf_t buf;
8047 u_int8_t *buf_ptr;
8048 int ret;
8049
8050 wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
8051
8052 if (!tx_rx_aggregation_size) {
8053 WMA_LOGE("%s: invalid pointer", __func__);
8054 return QDF_STATUS_E_INVAL;
8055 }
8056
8057 if (!wma_handle) {
8058 WMA_LOGE("%s: WMA context is invald!", __func__);
8059 return QDF_STATUS_E_INVAL;
8060 }
8061
8062 len = sizeof(*cmd);
8063 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
8064
8065 if (!buf) {
8066 WMA_LOGE("%s: Failed allocate wmi buffer", __func__);
8067 return QDF_STATUS_E_NOMEM;
8068 }
8069
8070 buf_ptr = (u_int8_t *) wmi_buf_data(buf);
8071 cmd = (wmi_vdev_set_custom_aggr_size_cmd_fixed_param *) buf_ptr;
8072
8073 WMITLV_SET_HDR(&cmd->tlv_header,
8074 WMITLV_TAG_STRUC_wmi_vdev_set_custom_aggr_size_cmd_fixed_param,
8075 WMITLV_GET_STRUCT_TLVLEN(
8076 wmi_vdev_set_custom_aggr_size_cmd_fixed_param));
8077
8078 cmd->vdev_id = tx_rx_aggregation_size->vdev_id;
8079 cmd->tx_aggr_size = tx_rx_aggregation_size->tx_aggregation_size;
8080 cmd->rx_aggr_size = tx_rx_aggregation_size->rx_aggregation_size;
8081
8082 WMA_LOGI("tx aggr: %d rx aggr: %d vdev: %d",
8083 cmd->tx_aggr_size, cmd->rx_aggr_size, cmd->vdev_id);
8084
8085 ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
8086 WMI_VDEV_SET_CUSTOM_AGGR_SIZE_CMDID);
8087 if (ret) {
8088 WMA_LOGE("%s: Failed to send aggregation size command",
8089 __func__);
8090 wmi_buf_free(buf);
8091 return QDF_STATUS_E_FAILURE;
8092 }
8093
8094 return QDF_STATUS_SUCCESS;
8095}
8096
8097/**
Peng Xu8fdaa492016-06-22 10:20:47 -07008098 * wma_p2p_lo_start() - P2P listen offload start
8099 * @params: p2p listen offload parameters
8100 *
8101 * This function sends WMI command to start P2P listen offload.
8102 *
8103 * Return: QDF_STATUS enumeration
8104 */
8105QDF_STATUS wma_p2p_lo_start(struct sir_p2p_lo_start *params)
8106{
8107 wmi_buf_t buf;
8108 wmi_p2p_lo_start_cmd_fixed_param *cmd;
8109 int32_t len = sizeof(*cmd);
8110 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
8111 uint8_t *buf_ptr;
8112 int ret;
Peng Xu4225c152016-07-14 21:18:14 -07008113 int device_types_len_aligned, probe_resp_len_aligned;
Peng Xu8fdaa492016-06-22 10:20:47 -07008114
8115 if (NULL == wma) {
8116 WMA_LOGE("%s: wma context is NULL", __func__);
8117 return QDF_STATUS_E_INVAL;
8118 }
8119
Peng Xu4225c152016-07-14 21:18:14 -07008120 device_types_len_aligned = qdf_roundup(params->dev_types_len,
8121 sizeof(A_UINT32));
8122 probe_resp_len_aligned = qdf_roundup(params->probe_resp_len,
8123 sizeof(A_UINT32));
8124
8125 len += 2 * WMI_TLV_HDR_SIZE + device_types_len_aligned +
8126 probe_resp_len_aligned;
Peng Xu8fdaa492016-06-22 10:20:47 -07008127
8128 buf = wmi_buf_alloc(wma->wmi_handle, len);
8129 if (!buf) {
8130 WMA_LOGP("%s: failed to allocate memory for p2p lo start",
8131 __func__);
8132 return QDF_STATUS_E_NOMEM;
8133 }
8134
8135 cmd = (wmi_p2p_lo_start_cmd_fixed_param *)wmi_buf_data(buf);
8136 buf_ptr = (uint8_t *) wmi_buf_data(buf);
8137
8138 WMITLV_SET_HDR(&cmd->tlv_header,
8139 WMITLV_TAG_STRUC_wmi_p2p_lo_start_cmd_fixed_param,
8140 WMITLV_GET_STRUCT_TLVLEN(
8141 wmi_p2p_lo_start_cmd_fixed_param));
8142
8143 cmd->vdev_id = params->vdev_id;
8144 cmd->ctl_flags = params->ctl_flags;
8145 cmd->channel = params->freq;
8146 cmd->period = params->period;
8147 cmd->interval = params->interval;
8148 cmd->count = params->count;
Peng Xu4225c152016-07-14 21:18:14 -07008149 cmd->device_types_len = params->dev_types_len;
8150 cmd->prob_resp_len = params->probe_resp_len;
Peng Xu8fdaa492016-06-22 10:20:47 -07008151
8152 buf_ptr += sizeof(wmi_p2p_lo_start_cmd_fixed_param);
8153 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE,
Peng Xu4225c152016-07-14 21:18:14 -07008154 device_types_len_aligned);
Peng Xu8fdaa492016-06-22 10:20:47 -07008155 buf_ptr += WMI_TLV_HDR_SIZE;
8156 qdf_mem_copy(buf_ptr, params->device_types, params->dev_types_len);
8157
Peng Xu4225c152016-07-14 21:18:14 -07008158 buf_ptr += device_types_len_aligned;
8159 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, probe_resp_len_aligned);
Peng Xu8fdaa492016-06-22 10:20:47 -07008160 buf_ptr += WMI_TLV_HDR_SIZE;
8161 qdf_mem_copy(buf_ptr, params->probe_resp_tmplt, params->probe_resp_len);
8162
8163 WMA_LOGI("%s: Sending WMI_P2P_LO_START command, channel=%d, period=%d, interval=%d, count=%d",
8164 __func__, cmd->channel, cmd->period,
8165 cmd->interval, cmd->count);
8166
8167 ret = wmi_unified_cmd_send(wma->wmi_handle,
8168 buf, len,
8169 WMI_P2P_LISTEN_OFFLOAD_START_CMDID);
8170 if (ret) {
8171 WMA_LOGE("Failed to send p2p lo start: %d", ret);
8172 wmi_buf_free(buf);
8173 }
8174
8175 WMA_LOGI("%s: Successfully sent WMI_P2P_LO_START", __func__);
8176 wma->interfaces[params->vdev_id].p2p_lo_in_progress = true;
8177
8178 return ret;
8179}
8180
8181/**
8182 * wma_p2p_lo_stop() - P2P listen offload stop
8183 * @vdev_id: vdev identifier
8184 *
8185 * This function sends WMI command to stop P2P listen offload.
8186 *
8187 * Return: QDF_STATUS enumeration
8188 */
8189QDF_STATUS wma_p2p_lo_stop(u_int32_t vdev_id)
8190{
8191 wmi_buf_t buf;
8192 wmi_p2p_lo_stop_cmd_fixed_param *cmd;
8193 int32_t len;
8194 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
8195 int ret;
8196
8197 if (NULL == wma) {
8198 WMA_LOGE("%s: wma context is NULL", __func__);
8199 return QDF_STATUS_E_INVAL;
8200 }
8201
8202 len = sizeof(*cmd);
8203 buf = wmi_buf_alloc(wma->wmi_handle, len);
8204 if (!buf) {
8205 WMA_LOGP("%s: failed to allocate memory for p2p lo stop",
8206 __func__);
8207 return QDF_STATUS_E_NOMEM;
8208 }
8209 cmd = (wmi_p2p_lo_stop_cmd_fixed_param *)wmi_buf_data(buf);
8210
8211 WMITLV_SET_HDR(&cmd->tlv_header,
8212 WMITLV_TAG_STRUC_wmi_p2p_lo_stop_cmd_fixed_param,
8213 WMITLV_GET_STRUCT_TLVLEN(
8214 wmi_p2p_lo_stop_cmd_fixed_param));
8215
8216 cmd->vdev_id = vdev_id;
8217
8218 WMA_LOGI("%s: Sending WMI_P2P_LO_STOP command", __func__);
8219
8220 ret = wmi_unified_cmd_send(wma->wmi_handle,
8221 buf, len,
8222 WMI_P2P_LISTEN_OFFLOAD_STOP_CMDID);
8223 if (ret) {
8224 WMA_LOGE("Failed to send p2p lo stop: %d", ret);
8225 wmi_buf_free(buf);
8226 }
8227
8228 WMA_LOGI("%s: Successfully sent WMI_P2P_LO_STOP", __func__);
8229 wma->interfaces[vdev_id].p2p_lo_in_progress = false;
8230
8231 return ret;
8232}
8233
8234/**
8235 * wma_p2p_lo_event_handler() - p2p lo event
8236 * @handle: the WMA handle
8237 * @event_buf: buffer with the event parameters
8238 * @len: length of the buffer
8239 *
8240 * This function receives P2P listen offload stop event from FW and
8241 * pass the event information to upper layer.
8242 *
8243 * Return: 0 on success
8244 */
8245int wma_p2p_lo_event_handler(void *handle, uint8_t *event_buf,
8246 uint32_t len)
8247{
8248 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
8249 struct sir_p2p_lo_event *event;
8250 WMI_P2P_LISTEN_OFFLOAD_STOPPED_EVENTID_param_tlvs *param_tlvs;
8251 wmi_p2p_lo_stopped_event_fixed_param *fix_param;
8252 tpAniSirGlobal p_mac = cds_get_context(QDF_MODULE_ID_PE);
8253
Varun Reddy Yeturuc48ad6e2016-09-09 14:31:58 -07008254 if (!wma) {
8255 WMA_LOGE("%s: Invalid WMA Context", __func__);
8256 return -EINVAL;
8257 }
8258
Peng Xu8fdaa492016-06-22 10:20:47 -07008259 if (!p_mac) {
8260 WMA_LOGE("%s: Invalid p_mac", __func__);
8261 return -EINVAL;
8262 }
8263
8264 if (!p_mac->sme.p2p_lo_event_callback) {
8265 WMA_LOGE("%s: Callback not registered", __func__);
8266 return -EINVAL;
8267 }
8268
8269 param_tlvs = (WMI_P2P_LISTEN_OFFLOAD_STOPPED_EVENTID_param_tlvs *)
8270 event_buf;
8271 fix_param = param_tlvs->fixed_param;
8272 event = qdf_mem_malloc(sizeof(*event));
8273 if (event == NULL) {
8274 WMA_LOGE("Event allocation failed");
8275 return -ENOMEM;
8276 }
8277 event->vdev_id = fix_param->vdev_id;
8278 event->reason_code = fix_param->reason;
8279
8280 p_mac->sme.p2p_lo_event_callback(p_mac->hHdd, event);
8281
8282 wma->interfaces[event->vdev_id].p2p_lo_in_progress = false;
8283
8284 return 0;
8285}
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308286
8287/**
8288 * wma_get_wakelock_stats() - Collects wake lock stats
8289 * @wake_lock_stats: wakelock structure to be filled
8290 *
8291 * This function collects wake lock stats
8292 *
8293 * Return: VOS_STATUS_SUCCESS on success, error number otherwise
8294 */
8295QDF_STATUS wma_get_wakelock_stats(struct sir_wake_lock_stats *wake_lock_stats)
8296{
8297 tp_wma_handle wma_handle;
8298
8299 wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
8300
8301 if (!wake_lock_stats) {
8302 WMA_LOGE("%s: invalid pointer", __func__);
8303 return QDF_STATUS_E_INVAL;
8304 }
8305
8306 if (!wma_handle) {
8307 WMA_LOGE("%s: WMA context is invalid!", __func__);
8308 return QDF_STATUS_E_INVAL;
8309 }
8310
8311 wake_lock_stats->wow_ucast_wake_up_count =
8312 wma_handle->wow_ucast_wake_up_count;
8313 wake_lock_stats->wow_bcast_wake_up_count =
8314 wma_handle->wow_bcast_wake_up_count;
8315 wake_lock_stats->wow_ipv4_mcast_wake_up_count =
8316 wma_handle->wow_ipv4_mcast_wake_up_count;
8317 wake_lock_stats->wow_ipv6_mcast_wake_up_count =
8318 wma_handle->wow_ipv6_mcast_wake_up_count;
8319 wake_lock_stats->wow_ipv6_mcast_ra_stats =
8320 wma_handle->wow_ipv6_mcast_ra_stats;
8321 wake_lock_stats->wow_ipv6_mcast_ns_stats =
8322 wma_handle->wow_ipv6_mcast_ns_stats;
8323 wake_lock_stats->wow_ipv6_mcast_na_stats =
8324 wma_handle->wow_ipv6_mcast_na_stats;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308325 wake_lock_stats->wow_icmpv4_count = wma_handle->wow_icmpv4_count;
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308326 wake_lock_stats->wow_icmpv6_count =
8327 wma_handle->wow_icmpv6_count;
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308328 wake_lock_stats->wow_rssi_breach_wake_up_count =
8329 wma_handle->wow_rssi_breach_wake_up_count;
8330 wake_lock_stats->wow_low_rssi_wake_up_count =
8331 wma_handle->wow_low_rssi_wake_up_count;
8332 wake_lock_stats->wow_gscan_wake_up_count =
8333 wma_handle->wow_gscan_wake_up_count;
8334 wake_lock_stats->wow_pno_complete_wake_up_count =
8335 wma_handle->wow_pno_complete_wake_up_count;
8336 wake_lock_stats->wow_pno_match_wake_up_count =
8337 wma_handle->wow_pno_match_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308338
8339 return QDF_STATUS_SUCCESS;
8340}
Anurag Chouhanbf5e0e22016-09-12 12:54:09 +05308341
8342/**
8343 * wma_process_fw_test_cmd() - send unit test command to fw.
8344 * @handle: wma handle
8345 * @wma_fwtest: fw test command
8346 *
8347 * This function send fw test command to fw.
8348 *
8349 * Return: none
8350 */
8351void wma_process_fw_test_cmd(WMA_HANDLE handle,
8352 struct set_fwtest_params *wma_fwtest)
8353{
8354 tp_wma_handle wma_handle = (tp_wma_handle) handle;
8355
8356 if (!wma_handle || !wma_handle->wmi_handle) {
8357 WMA_LOGE("%s: WMA is closed, can not issue fw test cmd",
8358 __func__);
8359 return;
8360 }
8361
8362 if (wmi_unified_fw_test_cmd(wma_handle->wmi_handle,
8363 (struct set_fwtest_params *)wma_fwtest)) {
8364 WMA_LOGE("%s: Failed to issue fw test cmd",
8365 __func__);
8366 return;
8367 }
8368}
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05308369
8370/**
8371 * wma_enable_disable_caevent_ind() - Issue WMI command to enable or
8372 * disable ca event indication
8373 * @wma: wma handler
8374 * @val: boolean value true or false
8375 *
8376 * Return: QDF_STATUS
8377 */
8378QDF_STATUS wma_enable_disable_caevent_ind(tp_wma_handle wma, uint8_t val)
8379{
8380 WMI_CHAN_AVOID_RPT_ALLOW_CMD_fixed_param *cmd;
8381 wmi_buf_t wmi_buf;
8382 uint8_t *buf_ptr;
8383 uint32_t len;
8384
8385 if (!wma || !wma->wmi_handle) {
8386 WMA_LOGE(FL("WMA is closed, can not issue set/clear CA"));
8387 return QDF_STATUS_E_INVAL;
8388 }
8389
8390 len = sizeof(*cmd);
8391 wmi_buf = wmi_buf_alloc(wma->wmi_handle, len);
8392 if (!wmi_buf) {
8393 WMA_LOGE(FL("wmi_buf_alloc failed"));
8394 return QDF_STATUS_E_NOMEM;
8395 }
8396 buf_ptr = (uint8_t *) wmi_buf_data(wmi_buf);
8397 cmd = (WMI_CHAN_AVOID_RPT_ALLOW_CMD_fixed_param *) buf_ptr;
8398 WMITLV_SET_HDR(&cmd->tlv_header,
8399 WMITLV_TAG_STRUC_WMI_CHAN_AVOID_RPT_ALLOW_CMD_fixed_param,
8400 WMITLV_GET_STRUCT_TLVLEN(
8401 WMI_CHAN_AVOID_RPT_ALLOW_CMD_fixed_param));
8402 cmd->rpt_allow = val;
8403 if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len,
8404 WMI_CHAN_AVOID_RPT_ALLOW_CMDID)) {
8405 WMA_LOGE(FL("Failed to send enable/disable CA event command"));
8406 wmi_buf_free(wmi_buf);
8407 return QDF_STATUS_E_FAILURE;
8408 }
8409
8410 return QDF_STATUS_SUCCESS;
8411}
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +05308412
Padma, Santhosh Kumar72e7aec2016-10-12 17:23:44 +05308413#ifdef WLAN_FEATURE_DISA
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +05308414/**
8415 * wma_encrypt_decrypt_msg() -
8416 * @encrypt_decrypt_params: encryption/decryption params
8417 * @data_len: data length
8418 * @encrypt_decrypt_cb: encrypt/decrypt callback
8419 *
8420 * This function sends WMI command to check encryption/decryption engine.
8421 *
8422 * Return: QDF_STATUS enumeration
8423 */
8424QDF_STATUS wma_encrypt_decrypt_msg(WMA_HANDLE handle,
8425 struct encrypt_decrypt_req_params *encrypt_decrypt_params)
8426{
8427 int ret;
8428 tp_wma_handle wma = (tp_wma_handle) handle;
8429
8430 if (!wma || !wma->wmi_handle) {
8431 WMA_LOGE("%s: WMA is closed, can not issue encrypt/decrypt msg",
8432 __func__);
8433 return QDF_STATUS_E_INVAL;
8434 }
8435
8436 if (encrypt_decrypt_params == NULL) {
8437 WMA_LOGE("%s: encrypt/decrypt ptr NULL",
8438 __func__);
8439 return QDF_STATUS_E_INVAL;
8440 }
8441
8442 ret = wmi_unified_encrypt_decrypt_send_cmd(wma->wmi_handle,
8443 encrypt_decrypt_params);
8444
8445 return ret;
8446}
8447
8448/**
8449 * wma_encrypt_decrypt_msg_handler() - handle encrypt/decrypt data
8450 * indicated by FW
8451 * @handle: wma context
8452 * @data: event buffer
8453 * @data len: length of event buffer
8454 *
8455 * Return: 0 on success
8456 */
8457int wma_encrypt_decrypt_msg_handler(void *handle, uint8_t *data,
8458 uint32_t data_len)
8459{
8460 WMI_VDEV_ENCRYPT_DECRYPT_DATA_RESP_EVENTID_param_tlvs *param_buf;
8461 wmi_vdev_encrypt_decrypt_data_resp_event_fixed_param *data_event;
8462 struct sir_encrypt_decrypt_rsp_params encrypt_decrypt_rsp_params;
8463 tp_wma_handle wma = handle;
8464 u_int8_t *buf_ptr;
8465 tpAniSirGlobal pmac;
8466
8467 if (data == NULL) {
8468 WMA_LOGE("%s: invalid pointer", __func__);
8469 return -EINVAL;
8470 }
8471
8472 if (wma == NULL) {
8473 WMA_LOGE("%s: wma context is NULL", __func__);
8474 return -EINVAL;
8475 }
8476
8477 WMA_LOGE("%s: received WMI_VDEV_ENCRYPT_DECRYPT_DATA_RESP_EVENTID ",
8478 __func__);
8479
8480 pmac = (tpAniSirGlobal)cds_get_context(QDF_MODULE_ID_PE);
8481
8482 if (!pmac) {
8483 WMA_LOGE("%s: Invalid pmac", __func__);
8484 return -EINVAL;
8485 }
8486 if (!pmac->sme.encrypt_decrypt_cb) {
8487 WMA_LOGE("%s: Callback not registered", __func__);
8488 return -EINVAL;
8489 }
8490
8491 param_buf =
8492 (WMI_VDEV_ENCRYPT_DECRYPT_DATA_RESP_EVENTID_param_tlvs *)data;
8493 if (!param_buf) {
8494 WMA_LOGE("%s: Invalid response data buf", __func__);
8495 return -EINVAL;
8496 }
8497
8498 data_event = param_buf->fixed_param;
8499
8500 encrypt_decrypt_rsp_params.vdev_id = data_event->vdev_id;
8501 encrypt_decrypt_rsp_params.status = data_event->status;
8502 encrypt_decrypt_rsp_params.data_length = data_event->data_length;
8503
8504 if (encrypt_decrypt_rsp_params.data_length) {
8505 buf_ptr =
8506 (uint8_t *)data_event +
8507 sizeof(
8508 wmi_vdev_encrypt_decrypt_data_resp_event_fixed_param) +
8509 WMI_TLV_HDR_SIZE;
8510
8511 encrypt_decrypt_rsp_params.data = buf_ptr;
8512 }
8513
8514 pmac->sme.encrypt_decrypt_cb(pmac->hHdd, &encrypt_decrypt_rsp_params);
8515
8516 return 0;
8517}
Padma, Santhosh Kumar72e7aec2016-10-12 17:23:44 +05308518#endif
Sridhar Selvarajdc400d22016-10-18 17:18:03 +05308519
8520/**
8521 * wma_unified_power_debug_stats_event_handler() - WMA handler function to
8522 * handle Power stats event from firmware
8523 * @handle: Pointer to wma handle
8524 * @cmd_param_info: Pointer to Power stats event TLV
8525 * @len: Length of the cmd_param_info
8526 *
8527 * Return: 0 on success, error number otherwise
8528 */
8529#ifdef WLAN_POWER_DEBUGFS
8530int wma_unified_power_debug_stats_event_handler(void *handle,
8531 uint8_t *cmd_param_info, uint32_t len)
8532{
8533 WMI_PDEV_CHIP_POWER_STATS_EVENTID_param_tlvs *param_tlvs;
8534 struct power_stats_response *power_stats_results;
8535 wmi_pdev_chip_power_stats_event_fixed_param *param_buf;
8536 uint32_t power_stats_len, stats_registers_len, *debug_registers;
8537
8538 tpAniSirGlobal mac = (tpAniSirGlobal)cds_get_context(QDF_MODULE_ID_PE);
8539 param_tlvs =
8540 (WMI_PDEV_CHIP_POWER_STATS_EVENTID_param_tlvs *) cmd_param_info;
8541
8542 param_buf = (wmi_pdev_chip_power_stats_event_fixed_param *)
8543 param_tlvs->fixed_param;
8544 if (!mac || !mac->sme.power_stats_resp_callback) {
8545 WMA_LOGD("%s: NULL mac ptr or HDD callback is null", __func__);
8546 return -EINVAL;
8547 }
8548
8549 if (!param_buf) {
8550 WMA_LOGD("%s: NULL power stats event fixed param", __func__);
8551 return -EINVAL;
8552 }
8553
8554 debug_registers = param_tlvs->debug_registers;
8555 stats_registers_len =
8556 (sizeof(uint32_t) * param_buf->num_debug_register);
8557 power_stats_len = stats_registers_len + sizeof(*power_stats_results);
8558 power_stats_results = qdf_mem_malloc(power_stats_len);
8559 if (!power_stats_results) {
8560 WMA_LOGD("%s: could not allocate mem for power stats results",
8561 __func__);
8562 return -ENOMEM;
8563 }
8564 WMA_LOGD("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",
8565 param_buf->cumulative_sleep_time_ms,
8566 param_buf->cumulative_total_on_time_ms,
8567 param_buf->deep_sleep_enter_counter,
8568 param_buf->last_deep_sleep_enter_tstamp_ms,
8569 param_buf->debug_register_fmt,
8570 param_buf->num_debug_register);
8571
8572 power_stats_results->cumulative_sleep_time_ms
8573 = param_buf->cumulative_sleep_time_ms;
8574 power_stats_results->cumulative_total_on_time_ms
8575 = param_buf->cumulative_total_on_time_ms;
8576 power_stats_results->deep_sleep_enter_counter
8577 = param_buf->deep_sleep_enter_counter;
8578 power_stats_results->last_deep_sleep_enter_tstamp_ms
8579 = param_buf->last_deep_sleep_enter_tstamp_ms;
8580 power_stats_results->debug_register_fmt
8581 = param_buf->debug_register_fmt;
8582 power_stats_results->num_debug_register
8583 = param_buf->num_debug_register;
8584
8585 power_stats_results->debug_registers
8586 = (uint32_t *)(power_stats_results + 1);
8587
8588 qdf_mem_copy(power_stats_results->debug_registers,
8589 debug_registers, stats_registers_len);
8590
8591 mac->sme.power_stats_resp_callback(power_stats_results,
8592 mac->sme.power_debug_stats_context);
8593 qdf_mem_free(power_stats_results);
8594 return 0;
8595}
8596#else
8597int wma_unified_power_debug_stats_event_handler(void *handle,
8598 uint8_t *cmd_param_info, uint32_t len)
8599{
8600 return 0;
8601}
8602#endif