blob: 7850fa73b9031d99002767e2d55a02045b4ecf25 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Ryan Hsuf75bd242015-12-17 12:22:02 -08002 * Copyright (c) 2013-2016 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 "ol_txrx_ctrl_api.h"
48#include <cdp_txrx_tx_delay.h>
Manjunathappa Prakash3454fd62016-04-01 08:52:06 -070049#include <cdp_txrx_peer_ops.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080050
Nirav Shahcbc6d722016-03-01 16:24:53 +053051#include "qdf_nbuf.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053052#include "qdf_types.h"
Anurag Chouhan600c3a02016-03-01 10:33:54 +053053#include "qdf_mem.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080054#include "ol_txrx_peer_find.h"
55
56#include "wma_types.h"
57#include "lim_api.h"
58#include "lim_session_utils.h"
59
60#include "cds_utils.h"
61
62#if !defined(REMOVE_PKT_LOG)
63#include "pktlog_ac.h"
64#endif /* REMOVE_PKT_LOG */
65
66#include "dbglog_host.h"
67#include "csr_api.h"
68#include "ol_fw.h"
69
70#include "dfs.h"
71#include "radar_filters.h"
72#include "wma_internal.h"
Poddar, Siddarth5a91f5b2016-04-28 12:24:10 +053073#include "ol_txrx.h"
Naveen Rawate82c1f32016-06-22 15:34:36 -070074#include "wma_nan_datapath.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080075
76#ifndef ARRAY_LENGTH
77#define ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0]))
78#endif
79
80#define WMA_WOW_STA_WAKE_UP_EVENTS ((1 << WOW_CSA_IE_EVENT) |\
81 (1 << WOW_CLIENT_KICKOUT_EVENT) |\
82 (1 << WOW_PATTERN_MATCH_EVENT) |\
83 (1 << WOW_MAGIC_PKT_RECVD_EVENT) |\
84 (1 << WOW_DEAUTH_RECVD_EVENT) |\
85 (1 << WOW_DISASSOC_RECVD_EVENT) |\
86 (1 << WOW_BMISS_EVENT) |\
87 (1 << WOW_GTK_ERR_EVENT) |\
88 (1 << WOW_BETTER_AP_EVENT) |\
89 (1 << WOW_HTT_EVENT) |\
90 (1 << WOW_RA_MATCH_EVENT) |\
91 (1 << WOW_NLO_DETECTED_EVENT) |\
Selvaraj, Sridhar172cabc2016-07-05 15:19:24 +053092 (1 << WOW_EXTSCAN_EVENT)) |\
93 (1 << WOW_OEM_RESPONSE_EVENT)\
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080094
95#define WMA_WOW_SAP_WAKE_UP_EVENTS ((1 << WOW_PROBE_REQ_WPS_IE_EVENT) |\
96 (1 << WOW_PATTERN_MATCH_EVENT) |\
97 (1 << WOW_AUTH_REQ_EVENT) |\
98 (1 << WOW_ASSOC_REQ_EVENT) |\
99 (1 << WOW_DEAUTH_RECVD_EVENT) |\
100 (1 << WOW_DISASSOC_RECVD_EVENT) |\
101 (1 << WOW_HTT_EVENT))\
102
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +0530103/**
104 * WMA_SET_VDEV_IE_SOURCE_HOST - Flag to identify the source of VDEV SET IE
105 * command. The value is 0x0 for the VDEV SET IE WMI commands from mobile
106 * MCL platform.
107 */
108#define WMA_SET_VDEV_IE_SOURCE_HOST 0x0
109
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800110static const uint8_t arp_ptrn[] = {0x08, 0x06};
111static const uint8_t arp_mask[] = {0xff, 0xff};
112static const uint8_t ns_ptrn[] = {0x86, 0xDD};
113static const uint8_t discvr_ptrn[] = {0xe0, 0x00, 0x00, 0xf8};
114static const uint8_t discvr_mask[] = {0xf0, 0x00, 0x00, 0xf8};
115
116#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
117/**
118 * wma_post_auto_shutdown_msg() - to post auto shutdown event to sme
119 *
120 * Return: 0 for success or error code
121 */
122static int wma_post_auto_shutdown_msg(void)
123{
124 tSirAutoShutdownEvtParams *auto_sh_evt;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530125 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800126 cds_msg_t sme_msg = { 0 };
127
128 auto_sh_evt = (tSirAutoShutdownEvtParams *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530129 qdf_mem_malloc(sizeof(tSirAutoShutdownEvtParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800130 if (!auto_sh_evt) {
131 WMA_LOGE(FL("No Mem"));
132 return -ENOMEM;
133 }
134
135 auto_sh_evt->shutdown_reason =
136 WMI_HOST_AUTO_SHUTDOWN_REASON_TIMER_EXPIRY;
137 sme_msg.type = eWNI_SME_AUTO_SHUTDOWN_IND;
138 sme_msg.bodyptr = auto_sh_evt;
139 sme_msg.bodyval = 0;
140
Anurag Chouhan6d760662016-02-20 16:05:43 +0530141 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530142 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800143 WMA_LOGE("Fail to post eWNI_SME_AUTO_SHUTDOWN_IND msg to SME");
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530144 qdf_mem_free(auto_sh_evt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800145 return -EINVAL;
146 }
147
148 return 0;
149}
150#endif
151/**
152 * wma_send_snr_request() - send request to fw to get RSSI stats
153 * @wma_handle: wma handle
154 * @pGetRssiReq: get RSSI request
155 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530156 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800157 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530158QDF_STATUS wma_send_snr_request(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800159 void *pGetRssiReq)
160{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800161 tAniGetRssiReq *pRssiBkUp = NULL;
162
163 /* command is in progess */
164 if (NULL != wma_handle->pGetRssiReq)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530165 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800166
167 /* create a copy of csrRssiCallback to send rssi value
168 * after wmi event
169 */
170 if (pGetRssiReq) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530171 pRssiBkUp = qdf_mem_malloc(sizeof(tAniGetRssiReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800172 if (!pRssiBkUp) {
173 WMA_LOGE("Failed to allocate memory for tAniGetRssiReq");
174 wma_handle->pGetRssiReq = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530175 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800176 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530177 qdf_mem_set(pRssiBkUp, sizeof(tAniGetRssiReq), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800178 pRssiBkUp->sessionId =
179 ((tAniGetRssiReq *) pGetRssiReq)->sessionId;
180 pRssiBkUp->rssiCallback =
181 ((tAniGetRssiReq *) pGetRssiReq)->rssiCallback;
182 pRssiBkUp->pDevContext =
183 ((tAniGetRssiReq *) pGetRssiReq)->pDevContext;
184 wma_handle->pGetRssiReq = (void *)pRssiBkUp;
185 }
186
Govind Singhaa64c242016-03-08 11:31:49 +0530187 if (wmi_unified_snr_request_cmd(wma_handle->wmi_handle)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800188 WMA_LOGE("Failed to send host stats request to fw");
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530189 qdf_mem_free(pRssiBkUp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800190 wma_handle->pGetRssiReq = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530191 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800192 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530193 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800194}
195
196/**
197 * wma_get_snr() - get RSSI from fw
198 * @psnr_req: request params
199 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530200 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800201 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530202QDF_STATUS wma_get_snr(tAniGetSnrReq *psnr_req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800203{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800204 tAniGetSnrReq *psnr_req_bkp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800205 tp_wma_handle wma_handle = NULL;
206 struct wma_txrx_node *intr;
207
Anurag Chouhan6d760662016-02-20 16:05:43 +0530208 wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800209
210 if (NULL == wma_handle) {
211 WMA_LOGE("%s : Failed to get wma_handle", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530212 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800213 }
214
215 intr = &wma_handle->interfaces[psnr_req->sessionId];
216 /* command is in progess */
217 if (NULL != intr->psnr_req) {
218 WMA_LOGE("%s : previous snr request is pending", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530219 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800220 }
221
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530222 psnr_req_bkp = qdf_mem_malloc(sizeof(tAniGetSnrReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800223 if (!psnr_req_bkp) {
224 WMA_LOGE("Failed to allocate memory for tAniGetSnrReq");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530225 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800226 }
227
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530228 qdf_mem_set(psnr_req_bkp, sizeof(tAniGetSnrReq), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800229 psnr_req_bkp->staId = psnr_req->staId;
230 psnr_req_bkp->pDevContext = psnr_req->pDevContext;
231 psnr_req_bkp->snrCallback = psnr_req->snrCallback;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800232 intr->psnr_req = (void *)psnr_req_bkp;
Govind Singhaa64c242016-03-08 11:31:49 +0530233
234 if (wmi_unified_snr_cmd(wma_handle->wmi_handle,
235 psnr_req->sessionId)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800236 WMA_LOGE("Failed to send host stats request to fw");
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530237 qdf_mem_free(psnr_req_bkp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800238 intr->psnr_req = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530239 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800240 }
241
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530242 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800243}
244
245/**
246 * wma_process_link_status_req() - process link status request from UMAC
247 * @wma: wma handle
248 * @pGetLinkStatus: get link params
249 *
250 * Return: none
251 */
252void wma_process_link_status_req(tp_wma_handle wma,
253 tAniGetLinkStatus *pGetLinkStatus)
254{
Govind Singhaa64c242016-03-08 11:31:49 +0530255 struct link_status_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800256 struct wma_txrx_node *iface =
257 &wma->interfaces[pGetLinkStatus->sessionId];
258
259 if (iface->plink_status_req) {
260 WMA_LOGE("%s:previous link status request is pending,deleting the new request",
261 __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530262 qdf_mem_free(pGetLinkStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800263 return;
264 }
265
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800266 iface->plink_status_req = pGetLinkStatus;
Govind Singhaa64c242016-03-08 11:31:49 +0530267 cmd.session_id = pGetLinkStatus->sessionId;
268 if (wmi_unified_link_status_req_cmd(wma->wmi_handle, &cmd)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800269 WMA_LOGE("Failed to send WMI link status request to fw");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800270 iface->plink_status_req = NULL;
271 goto end;
272 }
273
274 return;
275
276end:
277 wma_post_link_status(pGetLinkStatus, LINK_STATUS_LEGACY);
278}
279
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700280#ifdef WLAN_FEATURE_TSF
281/**
282 * wma_vdev_tsf_handler() - handle tsf event indicated by FW
283 * @handle: wma context
284 * @data: event buffer
285 * @data len: length of event buffer
286 *
287 * Return: 0 on success
288 */
289int wma_vdev_tsf_handler(void *handle, uint8_t *data, uint32_t data_len)
290{
291 cds_msg_t tsf_msg = {0};
292 WMI_VDEV_TSF_REPORT_EVENTID_param_tlvs *param_buf;
293 wmi_vdev_tsf_report_event_fixed_param *tsf_event;
294 struct stsf *ptsf;
295
296 if (data == NULL) {
297 WMA_LOGE("%s: invalid pointer", __func__);
298 return -EINVAL;
299 }
300 ptsf = qdf_mem_malloc(sizeof(*ptsf));
301 if (NULL == ptsf) {
302 WMA_LOGE("%s: failed to allocate tsf data structure", __func__);
303 return -ENOMEM;
304 }
305
306 param_buf = (WMI_VDEV_TSF_REPORT_EVENTID_param_tlvs *)data;
307 tsf_event = param_buf->fixed_param;
308
309 ptsf->vdev_id = tsf_event->vdev_id;
310 ptsf->tsf_low = tsf_event->tsf_low;
311 ptsf->tsf_high = tsf_event->tsf_high;
Manikandan Mohan5356c2b2016-04-03 15:51:35 -0700312 ptsf->soc_timer_low = tsf_event->qtimer_low;
313 ptsf->soc_timer_high = tsf_event->qtimer_high;
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700314
315 WMA_LOGD("%s: receive WMI_VDEV_TSF_REPORT_EVENTID ", __func__);
316 WMA_LOGD("%s: vdev_id = %u,tsf_low =%u, tsf_high = %u", __func__,
317 ptsf->vdev_id, ptsf->tsf_low, ptsf->tsf_high);
318
319 tsf_msg.type = eWNI_SME_TSF_EVENT;
320 tsf_msg.bodyptr = ptsf;
321 tsf_msg.bodyval = 0;
322
323 if (QDF_STATUS_SUCCESS !=
324 cds_mq_post_message(CDS_MQ_ID_SME, &tsf_msg)) {
325
326 WMA_LOGP("%s: Failed to post eWNI_SME_TSF_EVENT", __func__);
327 qdf_mem_free(ptsf);
328 return -EINVAL;
329 }
330 return 0;
331}
332
Manikandan Mohan5356c2b2016-04-03 15:51:35 -0700333#ifdef QCA_WIFI_3_0
334#define TSF_FW_ACTION_CMD TSF_TSTAMP_QTIMER_CAPTURE_REQ
335#else
336#define TSF_FW_ACTION_CMD TSF_TSTAMP_CAPTURE_REQ
337#endif
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700338/**
339 * wma_capture_tsf() - send wmi to fw to capture tsf
340 * @wma_handle: wma handler
341 * @vdev_id: vdev id
342 *
343 * Return: wmi send state
344 */
345QDF_STATUS wma_capture_tsf(tp_wma_handle wma_handle, uint32_t vdev_id)
346{
347 QDF_STATUS status = QDF_STATUS_SUCCESS;
348 wmi_buf_t buf;
349 wmi_vdev_tsf_tstamp_action_cmd_fixed_param *cmd;
350 int ret;
351 int len = sizeof(*cmd);
352
353 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
354 if (!buf) {
355 WMA_LOGP("%s: failed to allocate memory for cap tsf cmd",
356 __func__);
357 return QDF_STATUS_E_NOMEM;
358 }
359
360 cmd = (wmi_vdev_tsf_tstamp_action_cmd_fixed_param *) wmi_buf_data(buf);
361 cmd->vdev_id = vdev_id;
Manikandan Mohan5356c2b2016-04-03 15:51:35 -0700362 cmd->tsf_action = TSF_FW_ACTION_CMD;
363 WMA_LOGD("%s :vdev_id %u, tsf_cmd: %d", __func__, cmd->vdev_id,
364 cmd->tsf_action);
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700365
366 WMITLV_SET_HDR(&cmd->tlv_header,
367 WMITLV_TAG_STRUC_wmi_vdev_tsf_tstamp_action_cmd_fixed_param,
368 WMITLV_GET_STRUCT_TLVLEN(
369 wmi_vdev_tsf_tstamp_action_cmd_fixed_param));
370
371 ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
372 WMI_VDEV_TSF_TSTAMP_ACTION_CMDID);
373 if (ret != EOK) {
374 WMA_LOGE("wmi_unified_cmd_send returned Error %d", status);
375 status = QDF_STATUS_E_FAILURE;
376 goto error;
377 }
378
379 return QDF_STATUS_SUCCESS;
380
381error:
382 if (buf)
383 wmi_buf_free(buf);
384 return status;
385}
386
387/**
388 * wma_reset_tsf_gpio() - send wmi to fw to reset GPIO
389 * @wma_handle: wma handler
390 * @vdev_id: vdev id
391 *
392 * Return: wmi send state
393 */
394QDF_STATUS wma_reset_tsf_gpio(tp_wma_handle wma_handle, uint32_t vdev_id)
395{
396 QDF_STATUS status = QDF_STATUS_SUCCESS;
397 wmi_buf_t buf;
398 wmi_vdev_tsf_tstamp_action_cmd_fixed_param *cmd;
399 int ret;
400 int len = sizeof(*cmd);
401 uint8_t *buf_ptr;
402
403 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
404 if (!buf) {
405 WMA_LOGP("%s: failed to allocate memory for reset tsf gpio",
406 __func__);
407 return QDF_STATUS_E_NOMEM;
408 }
409
410 buf_ptr = (uint8_t *) wmi_buf_data(buf);
411 cmd = (wmi_vdev_tsf_tstamp_action_cmd_fixed_param *) buf_ptr;
412 cmd->vdev_id = vdev_id;
413 cmd->tsf_action = TSF_TSTAMP_CAPTURE_RESET;
414
415 WMA_LOGD("%s :vdev_id %u, TSF_TSTAMP_CAPTURE_RESET", __func__,
416 cmd->vdev_id);
417
418 WMITLV_SET_HDR(&cmd->tlv_header,
419 WMITLV_TAG_STRUC_wmi_vdev_tsf_tstamp_action_cmd_fixed_param,
420 WMITLV_GET_STRUCT_TLVLEN(
421 wmi_vdev_tsf_tstamp_action_cmd_fixed_param));
422
423 ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
424 WMI_VDEV_TSF_TSTAMP_ACTION_CMDID);
425
426 if (ret != EOK) {
427 WMA_LOGE("wmi_unified_cmd_send returned Error %d", status);
428 status = QDF_STATUS_E_FAILURE;
429 goto error;
430 }
431 return QDF_STATUS_SUCCESS;
432
433error:
434 if (buf)
435 wmi_buf_free(buf);
436 return status;
437}
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700438
Manikandan Mohan976e7562016-03-15 16:33:31 -0700439/**
440 * wma_set_tsf_gpio_pin() - send wmi cmd to configure gpio pin
441 * @handle: wma handler
442 * @pin: GPIO pin id
443 *
444 * Return: QDF_STATUS
445 */
446QDF_STATUS wma_set_tsf_gpio_pin(WMA_HANDLE handle, uint32_t pin)
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700447{
Manikandan Mohan976e7562016-03-15 16:33:31 -0700448 tp_wma_handle wma = (tp_wma_handle)handle;
449 struct pdev_params pdev_param = {0};
450 int32_t ret;
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700451
Manikandan Mohan976e7562016-03-15 16:33:31 -0700452 if (!wma || !wma->wmi_handle) {
453 WMA_LOGE("%s: WMA is closed, can not set gpio", __func__);
454 return QDF_STATUS_E_INVAL;
455 }
456
457 WMA_LOGD("%s: set tsf gpio pin: %d", __func__, pin);
458
459 pdev_param.param_id = WMI_PDEV_PARAM_WNTS_CONFIG;
460 pdev_param.param_value = pin;
461 ret = wmi_unified_pdev_param_send(wma->wmi_handle,
462 &pdev_param,
463 WMA_WILDCARD_PDEV_ID);
464 if (ret) {
465 WMA_LOGE("%s: Failed to set tsf gpio pin (%d)", __func__, ret);
466 return QDF_STATUS_E_FAILURE;
467 }
468 return QDF_STATUS_SUCCESS;
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700469}
470#endif
471
Manikandan Mohan80dea792016-04-28 16:36:48 -0700472/**
473 * wma_set_wisa_params(): Set WISA features related params in FW
474 * @wma_handle: WMA handle
475 * @wisa: Pointer to WISA param struct
476 *
477 * Return: CDF status
478 */
479QDF_STATUS wma_set_wisa_params(tp_wma_handle wma_handle,
480 struct sir_wisa_params *wisa)
481{
482 QDF_STATUS status = QDF_STATUS_SUCCESS;
483 wmi_buf_t buf;
484 wmi_vdev_wisa_cmd_fixed_param *cmd;
485 int ret, len = sizeof(*cmd);
486
487 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
488 if (!buf) {
489 WMA_LOGP("%s: failed to allocate memory for WISA params",
490 __func__);
491 return QDF_STATUS_E_NOMEM;
492 }
493
494 cmd = (wmi_vdev_wisa_cmd_fixed_param *) wmi_buf_data(buf);
495 cmd->wisa_mode = wisa->mode;
496 cmd->vdev_id = wisa->vdev_id;
497
498 WMITLV_SET_HDR(&cmd->tlv_header,
499 WMITLV_TAG_STRUC_wmi_vdev_wisa_cmd_fixed_param,
500 WMITLV_GET_STRUCT_TLVLEN(
501 wmi_vdev_wisa_cmd_fixed_param));
502
503 ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
504 WMI_VDEV_WISA_CMDID);
505 if (ret != EOK) {
506 WMA_LOGE("wmi_unified_cmd_send returned Error %d", status);
507 status = QDF_STATUS_E_FAILURE;
508 goto error;
509 }
510 return QDF_STATUS_SUCCESS;
511
512error:
513 wmi_buf_free(buf);
514 return status;
515}
516
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800517#ifdef FEATURE_WLAN_LPHB
518/**
519 * wma_lphb_conf_hbenable() - enable command of LPHB configuration requests
520 * @wma_handle: WMA handle
521 * @lphb_conf_req: configuration info
522 * @by_user: whether this call is from user or cached resent
523 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530524 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800525 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530526QDF_STATUS wma_lphb_conf_hbenable(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800527 tSirLPHBReq *lphb_conf_req, bool by_user)
528{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530529 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800530 int status = 0;
531 tSirLPHBEnableStruct *ts_lphb_enable;
Govind Singhaa64c242016-03-08 11:31:49 +0530532 wmi_hb_set_enable_cmd_fixed_param hb_enable_fp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800533 int i;
534
535 if (lphb_conf_req == NULL) {
536 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530537 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800538 }
539
540 ts_lphb_enable = &(lphb_conf_req->params.lphbEnableReq);
541 WMA_LOGI("%s: WMA --> WMI_HB_SET_ENABLE enable=%d, item=%d, session=%d",
542 __func__,
543 ts_lphb_enable->enable,
544 ts_lphb_enable->item, ts_lphb_enable->session);
545
546 if ((ts_lphb_enable->item != 1) && (ts_lphb_enable->item != 2)) {
547 WMA_LOGE("%s : LPHB configuration wrong item %d",
548 __func__, ts_lphb_enable->item);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530549 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800550 }
551
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800552
553 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530554 hb_enable_fp.vdev_id = ts_lphb_enable->session;
555 hb_enable_fp.enable = ts_lphb_enable->enable;
556 hb_enable_fp.item = ts_lphb_enable->item;
557 hb_enable_fp.session = ts_lphb_enable->session;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800558
Govind Singhaa64c242016-03-08 11:31:49 +0530559 status = wmi_unified_lphb_config_hbenable_cmd(wma_handle->wmi_handle,
560 &hb_enable_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800561 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530562 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800563 goto error;
564 }
565
566 if (by_user) {
567 /* target already configured, now cache command status */
568 if (ts_lphb_enable->enable) {
569 i = ts_lphb_enable->item - 1;
570 wma_handle->wow.lphb_cache[i].cmd
571 = LPHB_SET_EN_PARAMS_INDID;
572 wma_handle->wow.lphb_cache[i].params.lphbEnableReq.
573 enable = ts_lphb_enable->enable;
574 wma_handle->wow.lphb_cache[i].params.lphbEnableReq.
575 item = ts_lphb_enable->item;
576 wma_handle->wow.lphb_cache[i].params.lphbEnableReq.
577 session = ts_lphb_enable->session;
578
579 WMA_LOGI("%s: cached LPHB status in WMA context for item %d",
580 __func__, i);
581 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530582 qdf_mem_zero((void *)&wma_handle->wow.lphb_cache,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800583 sizeof(wma_handle->wow.lphb_cache));
584 WMA_LOGI("%s: cleared all cached LPHB status in WMA context",
585 __func__);
586 }
587 }
588
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530589 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800590error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530591 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800592}
593
594/**
595 * wma_lphb_conf_tcp_params() - set tcp params of LPHB configuration requests
596 * @wma_handle: wma handle
597 * @lphb_conf_req: lphb config request
598 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530599 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800600 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530601QDF_STATUS wma_lphb_conf_tcp_params(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800602 tSirLPHBReq *lphb_conf_req)
603{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530604 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800605 int status = 0;
606 tSirLPHBTcpParamStruct *ts_lphb_tcp_param;
Govind Singhaa64c242016-03-08 11:31:49 +0530607 wmi_hb_set_tcp_params_cmd_fixed_param hb_tcp_params_fp = {0};
608
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800609
610 if (lphb_conf_req == NULL) {
611 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530612 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800613 }
614
615 ts_lphb_tcp_param = &(lphb_conf_req->params.lphbTcpParamReq);
Srinivas Girigowda9dc32cf2015-11-19 14:47:04 -0800616 WMA_LOGI("%s: WMA --> WMI_HB_SET_TCP_PARAMS srv_ip=%08x, "
617 "dev_ip=%08x, src_port=%d, dst_port=%d, timeout=%d, "
618 "session=%d, gateway_mac="MAC_ADDRESS_STR", timePeriodSec=%d, "
619 "tcpSn=%d", __func__, ts_lphb_tcp_param->srv_ip,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800620 ts_lphb_tcp_param->dev_ip, ts_lphb_tcp_param->src_port,
621 ts_lphb_tcp_param->dst_port, ts_lphb_tcp_param->timeout,
Srinivas Girigowda9dc32cf2015-11-19 14:47:04 -0800622 ts_lphb_tcp_param->session,
623 MAC_ADDR_ARRAY(ts_lphb_tcp_param->gateway_mac.bytes),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800624 ts_lphb_tcp_param->timePeriodSec, ts_lphb_tcp_param->tcpSn);
625
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800626 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530627 hb_tcp_params_fp.vdev_id = ts_lphb_tcp_param->session;
628 hb_tcp_params_fp.srv_ip = ts_lphb_tcp_param->srv_ip;
629 hb_tcp_params_fp.dev_ip = ts_lphb_tcp_param->dev_ip;
630 hb_tcp_params_fp.seq = ts_lphb_tcp_param->tcpSn;
631 hb_tcp_params_fp.src_port = ts_lphb_tcp_param->src_port;
632 hb_tcp_params_fp.dst_port = ts_lphb_tcp_param->dst_port;
633 hb_tcp_params_fp.interval = ts_lphb_tcp_param->timePeriodSec;
634 hb_tcp_params_fp.timeout = ts_lphb_tcp_param->timeout;
635 hb_tcp_params_fp.session = ts_lphb_tcp_param->session;
Srinivas Girigowda9dc32cf2015-11-19 14:47:04 -0800636 WMI_CHAR_ARRAY_TO_MAC_ADDR(ts_lphb_tcp_param->gateway_mac.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +0530637 &hb_tcp_params_fp.gateway_mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800638
Govind Singhaa64c242016-03-08 11:31:49 +0530639 status = wmi_unified_lphb_config_tcp_params_cmd(wma_handle->wmi_handle,
640 &hb_tcp_params_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800641 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530642 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800643 goto error;
644 }
645
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530646 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800647error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530648 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800649}
650
651/**
652 * wma_lphb_conf_tcp_pkt_filter() - configure tcp packet filter command of LPHB
653 * @wma_handle: wma handle
654 * @lphb_conf_req: lphb config request
655 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530656 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800657 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530658QDF_STATUS wma_lphb_conf_tcp_pkt_filter(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800659 tSirLPHBReq *lphb_conf_req)
660{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530661 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800662 int status = 0;
663 tSirLPHBTcpFilterStruct *ts_lphb_tcp_filter;
Govind Singhaa64c242016-03-08 11:31:49 +0530664 wmi_hb_set_tcp_pkt_filter_cmd_fixed_param hb_tcp_filter_fp = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800665
666 if (lphb_conf_req == NULL) {
667 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530668 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800669 }
670
671 ts_lphb_tcp_filter = &(lphb_conf_req->params.lphbTcpFilterReq);
672 WMA_LOGI("%s: WMA --> WMI_HB_SET_TCP_PKT_FILTER length=%d, offset=%d, session=%d, "
673 "filter=%2x:%2x:%2x:%2x:%2x:%2x ...", __func__,
674 ts_lphb_tcp_filter->length, ts_lphb_tcp_filter->offset,
675 ts_lphb_tcp_filter->session, ts_lphb_tcp_filter->filter[0],
676 ts_lphb_tcp_filter->filter[1], ts_lphb_tcp_filter->filter[2],
677 ts_lphb_tcp_filter->filter[3], ts_lphb_tcp_filter->filter[4],
678 ts_lphb_tcp_filter->filter[5]);
679
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800680 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530681 hb_tcp_filter_fp.vdev_id = ts_lphb_tcp_filter->session;
682 hb_tcp_filter_fp.length = ts_lphb_tcp_filter->length;
683 hb_tcp_filter_fp.offset = ts_lphb_tcp_filter->offset;
684 hb_tcp_filter_fp.session = ts_lphb_tcp_filter->session;
685 memcpy((void *)&hb_tcp_filter_fp.filter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800686 (void *)&ts_lphb_tcp_filter->filter,
687 WMI_WLAN_HB_MAX_FILTER_SIZE);
688
Govind Singhaa64c242016-03-08 11:31:49 +0530689 status = wmi_unified_lphb_config_tcp_pkt_filter_cmd(wma_handle->wmi_handle,
690 &hb_tcp_filter_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800691 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530692 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800693 goto error;
694 }
695
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530696 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800697error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530698 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800699}
700
701/**
702 * wma_lphb_conf_udp_params() - configure udp param command of LPHB
703 * @wma_handle: wma handle
704 * @lphb_conf_req: lphb config request
705 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530706 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800707 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530708QDF_STATUS wma_lphb_conf_udp_params(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800709 tSirLPHBReq *lphb_conf_req)
710{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530711 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800712 int status = 0;
713 tSirLPHBUdpParamStruct *ts_lphb_udp_param;
Govind Singhaa64c242016-03-08 11:31:49 +0530714 wmi_hb_set_udp_params_cmd_fixed_param hb_udp_params_fp = {0};
715
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800716
717 if (lphb_conf_req == NULL) {
718 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530719 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800720 }
721
722 ts_lphb_udp_param = &(lphb_conf_req->params.lphbUdpParamReq);
723 WMA_LOGI("%s: WMA --> WMI_HB_SET_UDP_PARAMS srv_ip=%d, dev_ip=%d, src_port=%d, "
724 "dst_port=%d, interval=%d, timeout=%d, session=%d, "
Srinivas Girigowda9eddfda2015-11-19 14:38:02 -0800725 "gateway_mac="MAC_ADDRESS_STR, __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800726 ts_lphb_udp_param->srv_ip, ts_lphb_udp_param->dev_ip,
727 ts_lphb_udp_param->src_port, ts_lphb_udp_param->dst_port,
728 ts_lphb_udp_param->interval, ts_lphb_udp_param->timeout,
Srinivas Girigowda9eddfda2015-11-19 14:38:02 -0800729 ts_lphb_udp_param->session,
730 MAC_ADDR_ARRAY(ts_lphb_udp_param->gateway_mac.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800731
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800732
733 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530734 hb_udp_params_fp.vdev_id = ts_lphb_udp_param->session;
735 hb_udp_params_fp.srv_ip = ts_lphb_udp_param->srv_ip;
736 hb_udp_params_fp.dev_ip = ts_lphb_udp_param->dev_ip;
737 hb_udp_params_fp.src_port = ts_lphb_udp_param->src_port;
738 hb_udp_params_fp.dst_port = ts_lphb_udp_param->dst_port;
739 hb_udp_params_fp.interval = ts_lphb_udp_param->interval;
740 hb_udp_params_fp.timeout = ts_lphb_udp_param->timeout;
741 hb_udp_params_fp.session = ts_lphb_udp_param->session;
Srinivas Girigowda9eddfda2015-11-19 14:38:02 -0800742 WMI_CHAR_ARRAY_TO_MAC_ADDR(ts_lphb_udp_param->gateway_mac.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +0530743 &hb_udp_params_fp.gateway_mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800744
Govind Singhaa64c242016-03-08 11:31:49 +0530745 status = wmi_unified_lphb_config_udp_params_cmd(wma_handle->wmi_handle,
746 &hb_udp_params_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800747 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530748 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800749 goto error;
750 }
751
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530752 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800753error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530754 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800755}
756
757/**
758 * wma_lphb_conf_udp_pkt_filter() - configure udp pkt filter command of LPHB
759 * @wma_handle: wma handle
760 * @lphb_conf_req: lphb config request
761 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530762 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800763 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530764QDF_STATUS wma_lphb_conf_udp_pkt_filter(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800765 tSirLPHBReq *lphb_conf_req)
766{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530767 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800768 int status = 0;
769 tSirLPHBUdpFilterStruct *ts_lphb_udp_filter;
Govind Singhaa64c242016-03-08 11:31:49 +0530770 wmi_hb_set_udp_pkt_filter_cmd_fixed_param hb_udp_filter_fp = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800771
772 if (lphb_conf_req == NULL) {
773 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530774 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800775 }
776
777 ts_lphb_udp_filter = &(lphb_conf_req->params.lphbUdpFilterReq);
778 WMA_LOGI("%s: WMA --> WMI_HB_SET_UDP_PKT_FILTER length=%d, offset=%d, session=%d, "
779 "filter=%2x:%2x:%2x:%2x:%2x:%2x ...", __func__,
780 ts_lphb_udp_filter->length, ts_lphb_udp_filter->offset,
781 ts_lphb_udp_filter->session, ts_lphb_udp_filter->filter[0],
782 ts_lphb_udp_filter->filter[1], ts_lphb_udp_filter->filter[2],
783 ts_lphb_udp_filter->filter[3], ts_lphb_udp_filter->filter[4],
784 ts_lphb_udp_filter->filter[5]);
785
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800786
787 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530788 hb_udp_filter_fp.vdev_id = ts_lphb_udp_filter->session;
789 hb_udp_filter_fp.length = ts_lphb_udp_filter->length;
790 hb_udp_filter_fp.offset = ts_lphb_udp_filter->offset;
791 hb_udp_filter_fp.session = ts_lphb_udp_filter->session;
792 memcpy((void *)&hb_udp_filter_fp.filter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800793 (void *)&ts_lphb_udp_filter->filter,
794 WMI_WLAN_HB_MAX_FILTER_SIZE);
795
Govind Singhaa64c242016-03-08 11:31:49 +0530796 status = wmi_unified_lphb_config_udp_pkt_filter_cmd(wma_handle->wmi_handle,
797 &hb_udp_filter_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800798 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530799 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800800 goto error;
801 }
802
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530803 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800804error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530805 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800806}
807
808/**
809 * wma_process_lphb_conf_req() - handle LPHB configuration requests
810 * @wma_handle: wma handle
811 * @lphb_conf_req: lphb config request
812 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530813 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800814 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530815QDF_STATUS wma_process_lphb_conf_req(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800816 tSirLPHBReq *lphb_conf_req)
817{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530818 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800819
820 if (lphb_conf_req == NULL) {
821 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530822 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800823 }
824
825 WMA_LOGI("%s : LPHB configuration cmd id is %d", __func__,
826 lphb_conf_req->cmd);
827 switch (lphb_conf_req->cmd) {
828 case LPHB_SET_EN_PARAMS_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530829 qdf_status = wma_lphb_conf_hbenable(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800830 lphb_conf_req, true);
831 break;
832
833 case LPHB_SET_TCP_PARAMS_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530834 qdf_status = wma_lphb_conf_tcp_params(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800835 lphb_conf_req);
836 break;
837
838 case LPHB_SET_TCP_PKT_FILTER_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530839 qdf_status = wma_lphb_conf_tcp_pkt_filter(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800840 lphb_conf_req);
841 break;
842
843 case LPHB_SET_UDP_PARAMS_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530844 qdf_status = wma_lphb_conf_udp_params(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800845 lphb_conf_req);
846 break;
847
848 case LPHB_SET_UDP_PKT_FILTER_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530849 qdf_status = wma_lphb_conf_udp_pkt_filter(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800850 lphb_conf_req);
851 break;
852
853 case LPHB_SET_NETWORK_INFO_INDID:
854 default:
855 break;
856 }
857
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530858 qdf_mem_free(lphb_conf_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530859 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800860}
861#endif /* FEATURE_WLAN_LPHB */
862
863/**
864 * wma_process_dhcp_ind() - process dhcp indication from SME
865 * @wma_handle: wma handle
866 * @ta_dhcp_ind: DHCP indication
867 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530868 * Return: QDF Status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800869 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530870QDF_STATUS wma_process_dhcp_ind(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800871 tAniDHCPInd *ta_dhcp_ind)
872{
873 uint8_t vdev_id;
874 int status = 0;
Govind Singhaa64c242016-03-08 11:31:49 +0530875 wmi_peer_set_param_cmd_fixed_param peer_set_param_fp = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800876
877 if (!ta_dhcp_ind) {
878 WMA_LOGE("%s : DHCP indication is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530879 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800880 }
881
Srinivas Girigowda296105a2015-09-24 16:31:16 -0700882 if (!wma_find_vdev_by_addr(wma_handle,
883 ta_dhcp_ind->adapterMacAddr.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800884 &vdev_id)) {
885 WMA_LOGE("%s: Failed to find vdev id for DHCP indication",
886 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530887 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800888 }
889
890 WMA_LOGI("%s: WMA --> WMI_PEER_SET_PARAM triggered by DHCP, "
891 "msgType=%s,"
892 "device_mode=%d, macAddr=" MAC_ADDRESS_STR,
893 __func__,
894 ta_dhcp_ind->msgType == WMA_DHCP_START_IND ?
895 "WMA_DHCP_START_IND" : "WMA_DHCP_STOP_IND",
896 ta_dhcp_ind->device_mode,
Srinivas Girigowda296105a2015-09-24 16:31:16 -0700897 MAC_ADDR_ARRAY(ta_dhcp_ind->peerMacAddr.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800898
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800899 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530900 peer_set_param_fp.vdev_id = vdev_id;
901 peer_set_param_fp.param_id = WMI_PEER_CRIT_PROTO_HINT_ENABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800902 if (WMA_DHCP_START_IND == ta_dhcp_ind->msgType)
Govind Singhaa64c242016-03-08 11:31:49 +0530903 peer_set_param_fp.param_value = 1;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800904 else
Govind Singhaa64c242016-03-08 11:31:49 +0530905 peer_set_param_fp.param_value = 0;
Srinivas Girigowda296105a2015-09-24 16:31:16 -0700906 WMI_CHAR_ARRAY_TO_MAC_ADDR(ta_dhcp_ind->peerMacAddr.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +0530907 &peer_set_param_fp.peer_macaddr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800908
Govind Singhaa64c242016-03-08 11:31:49 +0530909 status = wmi_unified_process_dhcp_ind(wma_handle->wmi_handle,
910 &peer_set_param_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800911 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530912 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800913 }
914
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530915 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800916}
917
918/**
Amar Singhal046eb8a2016-05-05 12:50:15 -0700919 * wma_chan_phy__mode() - get WLAN_PHY_MODE for channel
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800920 * @chan: channel number
Amar Singhal046eb8a2016-05-05 12:50:15 -0700921 * @chan_width: maximum channel width possible
922 * @dot11_mode: maximum phy_mode possible
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800923 *
Amar Singhal046eb8a2016-05-05 12:50:15 -0700924 * Return: return WLAN_PHY_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800925 */
Amar Singhal046eb8a2016-05-05 12:50:15 -0700926WLAN_PHY_MODE wma_chan_phy_mode(u8 chan, enum phy_ch_width chan_width,
927 u8 dot11_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800928{
929 WLAN_PHY_MODE phymode = MODE_UNKNOWN;
Amar Singhal046eb8a2016-05-05 12:50:15 -0700930 uint16_t bw_val = cds_bw_value(chan_width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800931
Amar Singhal046eb8a2016-05-05 12:50:15 -0700932 if (CDS_IS_CHANNEL_24GHZ(chan)) {
933 if (((CH_WIDTH_5MHZ == chan_width) ||
934 (CH_WIDTH_10MHZ == chan_width)) &&
935 ((WNI_CFG_DOT11_MODE_11B == dot11_mode) ||
936 (WNI_CFG_DOT11_MODE_11G == dot11_mode) ||
937 (WNI_CFG_DOT11_MODE_11N == dot11_mode) ||
938 (WNI_CFG_DOT11_MODE_ALL == dot11_mode) ||
939 (WNI_CFG_DOT11_MODE_11AC == dot11_mode)))
940 phymode = MODE_11G;
941 else {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800942 switch (dot11_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800943 case WNI_CFG_DOT11_MODE_11B:
Amar Singhal046eb8a2016-05-05 12:50:15 -0700944 if ((20 == bw_val) ||
945 (40 == bw_val))
946 phymode = MODE_11B;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800947 break;
948 case WNI_CFG_DOT11_MODE_11G:
Amar Singhal046eb8a2016-05-05 12:50:15 -0700949 if ((20 == bw_val) ||
950 (40 == bw_val))
951 phymode = MODE_11G;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800952 break;
953 case WNI_CFG_DOT11_MODE_11G_ONLY:
Amar Singhal046eb8a2016-05-05 12:50:15 -0700954 if ((20 == bw_val) ||
955 (40 == bw_val))
956 phymode = MODE_11GONLY;
957 break;
958 case WNI_CFG_DOT11_MODE_11N:
959 case WNI_CFG_DOT11_MODE_11N_ONLY:
960 if (20 == bw_val)
961 phymode = MODE_11NG_HT20;
962 else if (40 == bw_val)
963 phymode = MODE_11NG_HT40;
964 break;
965 case WNI_CFG_DOT11_MODE_ALL:
966 case WNI_CFG_DOT11_MODE_11AC:
967 case WNI_CFG_DOT11_MODE_11AC_ONLY:
968 if (20 == bw_val)
969 phymode = MODE_11AC_VHT20_2G;
970 else if (40 == bw_val)
971 phymode = MODE_11AC_VHT40_2G;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800972 break;
973 default:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800974 break;
975 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800976 }
Amar Singhal046eb8a2016-05-05 12:50:15 -0700977 } else if (CDS_IS_CHANNEL_DSRC(chan))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800978 phymode = MODE_11A;
Amar Singhal046eb8a2016-05-05 12:50:15 -0700979 else {
980 if (((CH_WIDTH_5MHZ == chan_width) ||
981 (CH_WIDTH_10MHZ == chan_width)) &&
982 ((WNI_CFG_DOT11_MODE_11A == dot11_mode) ||
983 (WNI_CFG_DOT11_MODE_11N == dot11_mode) ||
984 (WNI_CFG_DOT11_MODE_ALL == dot11_mode) ||
985 (WNI_CFG_DOT11_MODE_11AC == dot11_mode)))
986 phymode = MODE_11A;
987 else {
988 switch (dot11_mode) {
989 case WNI_CFG_DOT11_MODE_11A:
990 if (0 < bw_val)
991 phymode = MODE_11A;
992 break;
993 case WNI_CFG_DOT11_MODE_11N:
994 case WNI_CFG_DOT11_MODE_11N_ONLY:
995 if (20 == bw_val)
996 phymode = MODE_11NA_HT20;
997 else if (40 <= bw_val)
998 phymode = MODE_11NA_HT40;
999 break;
1000 case WNI_CFG_DOT11_MODE_ALL:
1001 case WNI_CFG_DOT11_MODE_11AC:
1002 case WNI_CFG_DOT11_MODE_11AC_ONLY:
1003 if (20 == bw_val)
1004 phymode = MODE_11AC_VHT20;
1005 else if (40 == bw_val)
1006 phymode = MODE_11AC_VHT40;
1007 else if (80 == bw_val)
1008 phymode = MODE_11AC_VHT80;
1009 else if (CH_WIDTH_160MHZ == chan_width)
1010 phymode = MODE_11AC_VHT160;
1011 else if (CH_WIDTH_80P80MHZ == chan_width)
1012 phymode = MODE_11AC_VHT80_80;
1013 break;
1014 default:
1015 break;
1016 }
1017 }
1018 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001019
Amar Singhal046eb8a2016-05-05 12:50:15 -07001020 WMA_LOGD("%s: phymode %d channel %d ch_width %d"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001021 "dot11_mode %d", __func__, phymode, chan,
Amar Singhal046eb8a2016-05-05 12:50:15 -07001022 chan_width, dot11_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001023
Amar Singhal046eb8a2016-05-05 12:50:15 -07001024 QDF_ASSERT(MODE_UNKNOWN != phymode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001025 return phymode;
1026}
1027
1028/**
1029 * wma_get_link_speed() -send command to get linkspeed
1030 * @handle: wma handle
1031 * @pLinkSpeed: link speed info
1032 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05301033 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001034 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301035QDF_STATUS wma_get_link_speed(WMA_HANDLE handle, tSirLinkSpeedInfo *pLinkSpeed)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001036{
1037 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhaa64c242016-03-08 11:31:49 +05301038 wmi_mac_addr peer_macaddr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001039
1040 if (!wma_handle || !wma_handle->wmi_handle) {
1041 WMA_LOGE("%s: WMA is closed, can not issue get link speed cmd",
1042 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301043 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001044 }
1045 if (!WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap,
1046 WMI_SERVICE_ESTIMATE_LINKSPEED)) {
1047 WMA_LOGE("%s: Linkspeed feature bit not enabled"
1048 " Sending value 0 as link speed.", __func__);
1049 wma_send_link_speed(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301050 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001051 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001052
1053 /* Copy the peer macaddress to the wma buffer */
Srinivas Girigowdadccab9a2015-11-19 14:31:14 -08001054 WMI_CHAR_ARRAY_TO_MAC_ADDR(pLinkSpeed->peer_macaddr.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +05301055 &peer_macaddr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001056
1057 WMA_LOGD("%s: pLinkSpeed->peerMacAddr: %pM, "
1058 "peer_macaddr.mac_addr31to0: 0x%x, peer_macaddr.mac_addr47to32: 0x%x",
Srinivas Girigowdadccab9a2015-11-19 14:31:14 -08001059 __func__, pLinkSpeed->peer_macaddr.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +05301060 peer_macaddr.mac_addr31to0,
1061 peer_macaddr.mac_addr47to32);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001062
Govind Singhaa64c242016-03-08 11:31:49 +05301063 if (wmi_unified_get_link_speed_cmd(wma_handle->wmi_handle,
1064 peer_macaddr)) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301065 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001066 }
Govind Singhaa64c242016-03-08 11:31:49 +05301067
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301068 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001069}
1070
Gupta, Kapil4cb1d7d2016-04-16 18:16:25 -07001071/**
1072* wma_add_beacon_filter() - Issue WMI command to set beacon filter
1073* @wma: wma handler
1074* @filter_params: beacon_filter_param to set
1075*
1076* Return: Return QDF_STATUS
1077*/
1078QDF_STATUS wma_add_beacon_filter(WMA_HANDLE handle,
1079 struct beacon_filter_param *filter_params)
1080{
1081 int i;
1082 wmi_buf_t wmi_buf;
1083 u_int8_t *buf;
1084 A_UINT32 *ie_map;
1085 int ret;
1086 tp_wma_handle wma = (tp_wma_handle) handle;
1087 wmi_add_bcn_filter_cmd_fixed_param *cmd;
1088 int len = sizeof(wmi_add_bcn_filter_cmd_fixed_param);
1089
1090 len += WMI_TLV_HDR_SIZE;
1091 len += BCN_FLT_MAX_ELEMS_IE_LIST*sizeof(A_UINT32);
1092
1093 if (!wma || !wma->wmi_handle) {
1094 WMA_LOGE("%s: WMA is closed, can not issue set beacon filter",
1095 __func__);
1096 return QDF_STATUS_E_INVAL;
1097 }
1098
1099 wmi_buf = wmi_buf_alloc(wma->wmi_handle, len);
1100 if (!wmi_buf) {
1101 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
1102 return QDF_STATUS_E_NOMEM;
1103 }
1104
1105 buf = (u_int8_t *) wmi_buf_data(wmi_buf);
1106
1107 cmd = (wmi_add_bcn_filter_cmd_fixed_param *)wmi_buf_data(wmi_buf);
1108 cmd->vdev_id = filter_params->vdev_id;
1109
1110 WMITLV_SET_HDR(&cmd->tlv_header,
1111 WMITLV_TAG_STRUC_wmi_add_bcn_filter_cmd_fixed_param,
1112 WMITLV_GET_STRUCT_TLVLEN(
1113 wmi_add_bcn_filter_cmd_fixed_param));
1114
1115 buf += sizeof(wmi_add_bcn_filter_cmd_fixed_param);
1116
1117 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_UINT32,
1118 (BCN_FLT_MAX_ELEMS_IE_LIST * sizeof(u_int32_t)));
1119
1120 ie_map = (A_UINT32 *)(buf + WMI_TLV_HDR_SIZE);
1121 for (i = 0; i < BCN_FLT_MAX_ELEMS_IE_LIST; i++) {
1122 ie_map[i] = filter_params->ie_map[i];
1123 WMA_LOGD("beacon filter ie map = %u", ie_map[i]);
1124 }
1125
1126 ret = wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len,
1127 WMI_ADD_BCN_FILTER_CMDID);
1128 if (ret) {
1129 WMA_LOGE("Failed to send wmi add beacon filter = %d",
1130 ret);
1131 wmi_buf_free(wmi_buf);
1132 return QDF_STATUS_E_FAILURE;
1133 }
1134 WMA_LOGD("added beacon filter = %d", ret);
1135
1136 return QDF_STATUS_SUCCESS;
1137}
1138
1139/**
1140* wma_remove_beacon_filter() - Issue WMI command to remove beacon filter
1141* @wma: wma handler
1142* @filter_params: beacon_filter_params
1143*
1144* Return: Return QDF_STATUS
1145*/
1146QDF_STATUS wma_remove_beacon_filter(WMA_HANDLE handle,
1147 struct beacon_filter_param *filter_params)
1148{
1149 wmi_buf_t buf;
1150 tp_wma_handle wma = (tp_wma_handle) handle;
1151 wmi_rmv_bcn_filter_cmd_fixed_param *cmd;
1152 int len = sizeof(wmi_rmv_bcn_filter_cmd_fixed_param);
1153 int ret;
1154
1155 if (!wma || !wma->wmi_handle) {
1156 WMA_LOGE("%s: WMA is closed, cannot issue remove beacon filter",
1157 __func__);
1158 return QDF_STATUS_E_INVAL;
1159 }
1160
1161 buf = wmi_buf_alloc(wma->wmi_handle, len);
1162 if (!buf) {
1163 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
1164 return QDF_STATUS_E_NOMEM;
1165 }
1166 cmd = (wmi_rmv_bcn_filter_cmd_fixed_param *)wmi_buf_data(buf);
1167 cmd->vdev_id = filter_params->vdev_id;
1168
1169 WMITLV_SET_HDR(&cmd->tlv_header,
1170 WMITLV_TAG_STRUC_wmi_rmv_bcn_filter_cmd_fixed_param,
1171 WMITLV_GET_STRUCT_TLVLEN(
1172 wmi_rmv_bcn_filter_cmd_fixed_param));
1173
1174 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
1175 WMI_RMV_BCN_FILTER_CMDID);
1176 if (ret) {
1177 WMA_LOGE("Failed to send wmi remove beacon filter = %d",
1178 ret);
1179 wmi_buf_free(buf);
1180 return QDF_STATUS_E_FAILURE;
1181 }
1182 WMA_LOGD("removed beacon filter = %d", ret);
1183
1184 return QDF_STATUS_SUCCESS;
1185}
1186
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05301187/**
1188 * wma_send_adapt_dwelltime_params() - send adaptive dwelltime configuration
1189 * params to firmware
1190 * @wma_handle: wma handler
1191 * @dwelltime_params: pointer to dwelltime_params
1192 *
1193 * Return: QDF_STATUS_SUCCESS on success and QDF failure reason code for failure
1194 */
1195QDF_STATUS wma_send_adapt_dwelltime_params(WMA_HANDLE handle,
1196 struct adaptive_dwelltime_params *dwelltime_params)
1197{
1198 tp_wma_handle wma_handle = (tp_wma_handle) handle;
1199 struct wmi_adaptive_dwelltime_params wmi_param = {0};
1200 int32_t err;
1201
1202 wmi_param.is_enabled = dwelltime_params->is_enabled;
1203 wmi_param.dwelltime_mode = dwelltime_params->dwelltime_mode;
1204 wmi_param.lpf_weight = dwelltime_params->lpf_weight;
1205 wmi_param.passive_mon_intval = dwelltime_params->passive_mon_intval;
1206 wmi_param.wifi_act_threshold = dwelltime_params->wifi_act_threshold;
1207 err = wmi_unified_send_adapt_dwelltime_params_cmd(wma_handle->
1208 wmi_handle, &wmi_param);
1209 if (err)
1210 return QDF_STATUS_E_FAILURE;
1211
1212 return QDF_STATUS_SUCCESS;
1213}
Gupta, Kapil4cb1d7d2016-04-16 18:16:25 -07001214
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001215#ifdef FEATURE_GREEN_AP
1216
1217/**
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001218 * wma_egap_info_status_event() - egap info status event
1219 * @handle: pointer to wma handler
1220 * @event: pointer to event
1221 * @len: len of the event
1222 *
1223 * Return: 0 for success, otherwise appropriate error code
1224 */
1225static int wma_egap_info_status_event(void *handle, u_int8_t *event,
1226 uint32_t len)
1227{
1228 WMI_TX_PAUSE_EVENTID_param_tlvs *param_buf;
1229 wmi_ap_ps_egap_info_event_fixed_param *egap_info_event;
1230 wmi_ap_ps_egap_info_chainmask_list *chainmask_event;
1231 u_int8_t *buf_ptr;
1232
1233 param_buf = (WMI_TX_PAUSE_EVENTID_param_tlvs *)event;
1234 if (!param_buf) {
1235 WMA_LOGE("Invalid EGAP Info status event buffer");
1236 return -EINVAL;
1237 }
1238
1239 egap_info_event = (wmi_ap_ps_egap_info_event_fixed_param *)
1240 param_buf->fixed_param;
1241 buf_ptr = (uint8_t *)egap_info_event;
1242 buf_ptr += sizeof(wmi_ap_ps_egap_info_event_fixed_param);
1243 chainmask_event = (wmi_ap_ps_egap_info_chainmask_list *)buf_ptr;
1244
1245 WMA_LOGI("mac_id: %d, status: %d, tx_mask: %x, rx_mask: %d",
1246 chainmask_event->mac_id,
1247 egap_info_event->status,
1248 chainmask_event->tx_chainmask,
1249 chainmask_event->rx_chainmask);
1250 return 0;
1251}
1252
1253/**
1254 * wma_send_egap_conf_params() - send wmi cmd of egap configuration params
1255 * @wma_handle: wma handler
1256 * @egap_params: pointer to egap_params
1257 *
1258 * Return: 0 for success, otherwise appropriate error code
1259 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301260QDF_STATUS wma_send_egap_conf_params(WMA_HANDLE handle,
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001261 struct egap_conf_params *egap_params)
1262{
1263 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhaa64c242016-03-08 11:31:49 +05301264 wmi_ap_ps_egap_param_cmd_fixed_param cmd = {0};
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001265 int32_t err;
1266
Govind Singhaa64c242016-03-08 11:31:49 +05301267 cmd.enable = egap_params->enable;
1268 cmd.inactivity_time = egap_params->inactivity_time;
1269 cmd.wait_time = egap_params->wait_time;
1270 cmd.flags = egap_params->flags;
1271 err = wmi_unified_egap_conf_params_cmd(wma_handle->wmi_handle, &cmd);
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001272 if (err) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301273 return QDF_STATUS_E_FAILURE;
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001274 }
Govind Singhaa64c242016-03-08 11:31:49 +05301275
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301276 return QDF_STATUS_SUCCESS;
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001277}
1278
1279/**
1280 * wma_setup_egap_support() - setup the EGAP support flag
1281 * @tgt_cfg: pointer to hdd target configuration
1282 * @egap_support: EGAP support flag
1283 *
1284 * Return: None
1285 */
1286void wma_setup_egap_support(struct wma_tgt_cfg *tgt_cfg, WMA_HANDLE handle)
1287{
1288 tp_wma_handle wma_handle = (tp_wma_handle) handle;
1289
1290 if (tgt_cfg && wma_handle)
1291 tgt_cfg->egap_support = wma_handle->egap_support;
1292}
1293
1294/**
1295 * wma_register_egap_event_handle() - register the EGAP event handle
1296 * @wma_handle: wma handler
1297 *
1298 * Return: None
1299 */
1300void wma_register_egap_event_handle(WMA_HANDLE handle)
1301{
1302 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhd76a5b02016-03-08 15:12:14 +05301303 QDF_STATUS status;
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001304
1305 if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap,
1306 WMI_SERVICE_EGAP)) {
1307 status = wmi_unified_register_event_handler(
1308 wma_handle->wmi_handle,
1309 WMI_AP_PS_EGAP_INFO_EVENTID,
Govind Singhd76a5b02016-03-08 15:12:14 +05301310 wma_egap_info_status_event,
1311 WMA_RX_SERIALIZER_CTX);
1312 if (QDF_IS_STATUS_ERROR(status)) {
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001313 WMA_LOGE("Failed to register Enhance Green AP event");
1314 wma_handle->egap_support = false;
1315 } else {
1316 WMA_LOGI("Set the Enhance Green AP event handler");
1317 wma_handle->egap_support = true;
1318 }
1319 } else
1320 wma_handle->egap_support = false;
1321}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001322#endif /* FEATURE_GREEN_AP */
1323
Govind Singha471e5e2015-10-12 17:11:14 +05301324/**
Govind Singhaa64c242016-03-08 11:31:49 +05301325 * wma_unified_fw_profiling_cmd() - send FW profiling cmd to WLAN FW
Govind Singha471e5e2015-10-12 17:11:14 +05301326 * @wma: wma handle
1327 * @cmd: Profiling command index
1328 * @value1: parameter1 value
1329 * @value2: parameter2 value
1330 *
1331 * Return: 0 for success else error code
1332 */
Govind Singhaa64c242016-03-08 11:31:49 +05301333QDF_STATUS wma_unified_fw_profiling_cmd(wmi_unified_t wmi_handle,
Govind Singha471e5e2015-10-12 17:11:14 +05301334 uint32_t cmd, uint32_t value1, uint32_t value2)
1335{
Govind Singha471e5e2015-10-12 17:11:14 +05301336 int ret;
Govind Singha471e5e2015-10-12 17:11:14 +05301337
Govind Singhaa64c242016-03-08 11:31:49 +05301338 ret = wmi_unified_fw_profiling_data_cmd(wmi_handle, cmd,
1339 value1, value2);
1340 if (ret) {
1341 WMA_LOGE("enable cmd Failed for id %d value %d",
1342 value1, value2);
1343 return ret;
Govind Singha471e5e2015-10-12 17:11:14 +05301344 }
1345
Govind Singhaa64c242016-03-08 11:31:49 +05301346 return QDF_STATUS_SUCCESS;
Govind Singha471e5e2015-10-12 17:11:14 +05301347}
1348
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001349#ifdef FEATURE_WLAN_LPHB
1350/**
1351 * wma_lphb_handler() - send LPHB indication to SME
1352 * @wma: wma handle
1353 * @event: event handler
1354 *
1355 * Return: 0 for success or error code
1356 */
1357static int wma_lphb_handler(tp_wma_handle wma, uint8_t *event)
1358{
1359 wmi_hb_ind_event_fixed_param *hb_fp;
1360 tSirLPHBInd *slphb_indication;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301361 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001362 cds_msg_t sme_msg = { 0 };
1363
1364 hb_fp = (wmi_hb_ind_event_fixed_param *) event;
1365 if (!hb_fp) {
1366 WMA_LOGE("Invalid wmi_hb_ind_event_fixed_param buffer");
1367 return -EINVAL;
1368 }
1369
1370 WMA_LOGD("lphb indication received with vdev_id=%d, session=%d, reason=%d",
1371 hb_fp->vdev_id, hb_fp->session, hb_fp->reason);
1372
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301373 slphb_indication = (tSirLPHBInd *) qdf_mem_malloc(sizeof(tSirLPHBInd));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001374
1375 if (!slphb_indication) {
1376 WMA_LOGE("Invalid LPHB indication buffer");
1377 return -ENOMEM;
1378 }
1379
1380 slphb_indication->sessionIdx = hb_fp->session;
1381 slphb_indication->protocolType = hb_fp->reason;
1382 slphb_indication->eventReason = hb_fp->reason;
1383
1384 sme_msg.type = eWNI_SME_LPHB_IND;
1385 sme_msg.bodyptr = slphb_indication;
1386 sme_msg.bodyval = 0;
1387
Anurag Chouhan6d760662016-02-20 16:05:43 +05301388 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301389 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001390 WMA_LOGE("Fail to post eWNI_SME_LPHB_IND msg to SME");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301391 qdf_mem_free(slphb_indication);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001392 return -EINVAL;
1393 }
1394
1395 return 0;
1396}
1397#endif /* FEATURE_WLAN_LPHB */
1398
1399#ifdef FEATURE_WLAN_RA_FILTERING
1400/**
1401 * wma_wow_sta_ra_filter() - set RA filter pattern in fw
1402 * @wma: wma handle
1403 * @vdev_id: vdev id
1404 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05301405 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001406 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301407static QDF_STATUS wma_wow_sta_ra_filter(tp_wma_handle wma, uint8_t vdev_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001408{
1409
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001410 struct wma_txrx_node *iface;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001411 int ret;
Govind Singhaa64c242016-03-08 11:31:49 +05301412 uint8_t default_pattern;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001413
1414 iface = &wma->interfaces[vdev_id];
1415
Govind Singhaa64c242016-03-08 11:31:49 +05301416 default_pattern = iface->num_wow_default_patterns++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001417
1418 WMA_LOGD("%s: send RA rate limit [%d] to fw vdev = %d", __func__,
1419 wma->RArateLimitInterval, vdev_id);
1420
Govind Singhaa64c242016-03-08 11:31:49 +05301421 ret = wmi_unified_wow_sta_ra_filter_cmd(wma->wmi_handle, vdev_id,
1422 default_pattern, wma->RArateLimitInterval);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001423 if (ret) {
1424 WMA_LOGE("%s: Failed to send RA rate limit to fw", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001425 iface->num_wow_default_patterns--;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301426 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001427 }
1428
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301429 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001430
1431}
1432#endif /* FEATURE_WLAN_RA_FILTERING */
1433
1434/**
1435 * wmi_unified_nat_keepalive_enable() - enable NAT keepalive filter
1436 * @wma: wma handle
1437 * @vdev_id: vdev id
1438 *
1439 * Return: 0 for success or error code
1440 */
1441int wmi_unified_nat_keepalive_enable(tp_wma_handle wma, uint8_t vdev_id)
1442{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001443
Govind Singhaa64c242016-03-08 11:31:49 +05301444 if (wmi_unified_nat_keepalive_en_cmd(wma->wmi_handle, vdev_id))
1445 return QDF_STATUS_E_FAILURE;
1446
1447 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001448}
1449
1450/**
Govind Singhd76a5b02016-03-08 15:12:14 +05301451 * wma_unified_csa_offload_enable() - sen CSA offload enable command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001452 * @wma: wma handle
1453 * @vdev_id: vdev id
1454 *
1455 * Return: 0 for success or error code
1456 */
Govind Singhd76a5b02016-03-08 15:12:14 +05301457int wma_unified_csa_offload_enable(tp_wma_handle wma, uint8_t vdev_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001458{
Govind Singhaa64c242016-03-08 11:31:49 +05301459 if (wmi_unified_csa_offload_enable(wma->wmi_handle,
1460 vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001461 WMA_LOGP("%s: Failed to send CSA offload enable command",
1462 __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001463 return -EIO;
1464 }
Govind Singhaa64c242016-03-08 11:31:49 +05301465
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001466 return 0;
1467}
1468
1469#ifdef WLAN_FEATURE_NAN
1470/**
1471 * wma_nan_rsp_event_handler() - Function is used to handle nan response
1472 * @handle: wma handle
1473 * @event_buf: event buffer
1474 * @len: length of buffer
1475 *
1476 * Return: 0 for success or error code
1477 */
1478int wma_nan_rsp_event_handler(void *handle, uint8_t *event_buf,
1479 uint32_t len)
1480{
1481 WMI_NAN_EVENTID_param_tlvs *param_buf;
1482 tSirNanEvent *nan_rsp_event;
1483 wmi_nan_event_hdr *nan_rsp_event_hdr;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301484 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001485 cds_msg_t cds_msg;
1486 uint8_t *buf_ptr;
1487 uint32_t alloc_len;
1488
1489 /*
1490 * This is how received event_buf looks like
1491 *
1492 * <-------------------- event_buf ----------------------------------->
1493 *
1494 * <--wmi_nan_event_hdr--><---WMI_TLV_HDR_SIZE---><----- data -------->
1495 *
1496 * +-----------+---------+-----------------------+--------------------+
1497 * | tlv_header| data_len| WMITLV_TAG_ARRAY_BYTE | nan_rsp_event_data |
1498 * +-----------+---------+-----------------------+--------------------+
1499 */
1500
1501 WMA_LOGD("%s: Posting NaN response event to SME", __func__);
1502 param_buf = (WMI_NAN_EVENTID_param_tlvs *) event_buf;
1503 if (!param_buf) {
1504 WMA_LOGE("%s: Invalid nan response event buf", __func__);
1505 return -EINVAL;
1506 }
1507 nan_rsp_event_hdr = param_buf->fixed_param;
1508 buf_ptr = (uint8_t *) nan_rsp_event_hdr;
1509 alloc_len = sizeof(tSirNanEvent);
1510 alloc_len += nan_rsp_event_hdr->data_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301511 nan_rsp_event = (tSirNanEvent *) qdf_mem_malloc(alloc_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001512 if (NULL == nan_rsp_event) {
1513 WMA_LOGE("%s: Memory allocation failure", __func__);
1514 return -ENOMEM;
1515 }
1516
1517 nan_rsp_event->event_data_len = nan_rsp_event_hdr->data_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301518 qdf_mem_copy(nan_rsp_event->event_data, buf_ptr +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001519 sizeof(wmi_nan_event_hdr) + WMI_TLV_HDR_SIZE,
1520 nan_rsp_event->event_data_len);
1521 cds_msg.type = eWNI_SME_NAN_EVENT;
1522 cds_msg.bodyptr = (void *)nan_rsp_event;
1523 cds_msg.bodyval = 0;
1524
1525 status = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301526 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001527 WMA_LOGE("%s: Failed to post NaN response event to SME",
1528 __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301529 qdf_mem_free(nan_rsp_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001530 return -EFAULT;
1531 }
1532 WMA_LOGD("%s: NaN response event Posted to SME", __func__);
1533 return 0;
1534}
Naveen Rawatc9f09522016-05-12 14:02:42 -07001535#else
1536int wma_nan_rsp_event_handler(void *handle, uint8_t *event_buf,
1537 uint32_t len)
1538{
1539 return 0;
1540}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001541#endif /* WLAN_FEATURE_NAN */
1542
1543/**
1544 * wma_csa_offload_handler() - CSA event handler
1545 * @handle: wma handle
1546 * @event: event buffer
1547 * @len: buffer length
1548 *
1549 * This event is sent by firmware when it receives CSA IE.
1550 *
1551 * Return: 0 for success or error code
1552 */
1553int wma_csa_offload_handler(void *handle, uint8_t *event, uint32_t len)
1554{
1555 tp_wma_handle wma = (tp_wma_handle) handle;
1556 WMI_CSA_HANDLING_EVENTID_param_tlvs *param_buf;
1557 wmi_csa_event_fixed_param *csa_event;
1558 uint8_t bssid[IEEE80211_ADDR_LEN];
1559 uint8_t vdev_id = 0;
1560 uint8_t cur_chan = 0;
1561 struct ieee80211_channelswitch_ie *csa_ie;
Chandrasekaran, Manishekar5c19dc52016-02-04 14:58:26 +05301562 struct csa_offload_params *csa_offload_event;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001563 struct ieee80211_extendedchannelswitch_ie *xcsa_ie;
1564 struct ieee80211_ie_wide_bw_switch *wb_ie;
1565 struct wma_txrx_node *intr = wma->interfaces;
1566
1567 param_buf = (WMI_CSA_HANDLING_EVENTID_param_tlvs *) event;
1568
1569 WMA_LOGD("%s: Enter", __func__);
1570 if (!param_buf) {
1571 WMA_LOGE("Invalid csa event buffer");
1572 return -EINVAL;
1573 }
1574 csa_event = param_buf->fixed_param;
1575 WMI_MAC_ADDR_TO_CHAR_ARRAY(&csa_event->i_addr2, &bssid[0]);
1576
1577 if (wma_find_vdev_by_bssid(wma, bssid, &vdev_id) == NULL) {
1578 WMA_LOGE("Invalid bssid received %s:%d", __func__, __LINE__);
1579 return -EINVAL;
1580 }
1581
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301582 csa_offload_event = qdf_mem_malloc(sizeof(*csa_offload_event));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001583 if (!csa_offload_event) {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05301584 WMA_LOGE("QDF MEM Alloc Failed for csa_offload_event");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001585 return -EINVAL;
1586 }
1587
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301588 qdf_mem_zero(csa_offload_event, sizeof(*csa_offload_event));
1589 qdf_mem_copy(csa_offload_event->bssId, &bssid, IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001590
1591 if (csa_event->ies_present_flag & WMI_CSA_IE_PRESENT) {
1592 csa_ie = (struct ieee80211_channelswitch_ie *)
1593 (&csa_event->csa_ie[0]);
1594 csa_offload_event->channel = csa_ie->newchannel;
Chandrasekaran, Manishekar5c19dc52016-02-04 14:58:26 +05301595 csa_offload_event->switch_mode = csa_ie->switchmode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001596 } else if (csa_event->ies_present_flag & WMI_XCSA_IE_PRESENT) {
1597 xcsa_ie = (struct ieee80211_extendedchannelswitch_ie *)
1598 (&csa_event->xcsa_ie[0]);
1599 csa_offload_event->channel = xcsa_ie->newchannel;
Chandrasekaran, Manishekar5c19dc52016-02-04 14:58:26 +05301600 csa_offload_event->switch_mode = xcsa_ie->switchmode;
Gupta, Kapil121bf212015-11-25 19:21:29 +05301601 csa_offload_event->new_op_class = xcsa_ie->newClass;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001602 } else {
1603 WMA_LOGE("CSA Event error: No CSA IE present");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301604 qdf_mem_free(csa_offload_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001605 return -EINVAL;
1606 }
1607
1608 if (csa_event->ies_present_flag & WMI_WBW_IE_PRESENT) {
1609 wb_ie = (struct ieee80211_ie_wide_bw_switch *)
1610 (&csa_event->wb_ie[0]);
1611 csa_offload_event->new_ch_width = wb_ie->new_ch_width;
1612 csa_offload_event->new_ch_freq_seg1 = wb_ie->new_ch_freq_seg1;
1613 csa_offload_event->new_ch_freq_seg2 = wb_ie->new_ch_freq_seg2;
1614 }
1615
1616 csa_offload_event->ies_present_flag = csa_event->ies_present_flag;
1617
1618 WMA_LOGD("CSA: New Channel = %d BSSID:%pM",
1619 csa_offload_event->channel, csa_offload_event->bssId);
1620
1621 cur_chan = cds_freq_to_chan(intr[vdev_id].mhz);
1622 /*
1623 * basic sanity check: requested channel should not be 0
1624 * and equal to home channel
1625 */
1626 if ((0 == csa_offload_event->channel) ||
1627 (cur_chan == csa_offload_event->channel)) {
1628 WMA_LOGE("CSA Event with channel %d. Ignore !!",
1629 csa_offload_event->channel);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301630 qdf_mem_free(csa_offload_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001631 return -EINVAL;
1632 }
1633 wma->interfaces[vdev_id].is_channel_switch = true;
1634 wma_send_msg(wma, WMA_CSA_OFFLOAD_EVENT, (void *)csa_offload_event, 0);
1635 return 0;
1636}
1637
1638#ifdef FEATURE_OEM_DATA_SUPPORT
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001639/**
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001640 * wma_oem_data_response_handler() - OEM data response event handler
1641 * @handle: wma handle
1642 * @datap: data ptr
1643 * @len: data length
1644 *
1645 * Return: 0 for success or error code
1646 */
1647int wma_oem_data_response_handler(void *handle,
1648 uint8_t *datap, uint32_t len)
1649{
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001650 WMI_OEM_RESPONSE_EVENTID_param_tlvs *param_buf;
1651 uint8_t *data;
1652 uint32_t datalen;
Krishna Kumaar Natarajanc1fa17d2016-08-03 14:19:20 -07001653 struct oem_data_rsp *oem_rsp;
Krishna Kumaar Natarajan73ea9f22016-06-30 18:38:47 -07001654 tpAniSirGlobal pmac = cds_get_context(QDF_MODULE_ID_PE);
1655
1656 if (!pmac) {
1657 WMA_LOGE(FL("Invalid pmac"));
1658 return -EINVAL;
1659 }
1660
Krishna Kumaar Natarajanbbbf2ef2016-08-03 14:06:26 -07001661 if (!pmac->sme.oem_data_rsp_callback) {
Krishna Kumaar Natarajan73ea9f22016-06-30 18:38:47 -07001662 WMA_LOGE(FL("Callback not registered"));
1663 return -EINVAL;
1664 }
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001665
1666 param_buf = (WMI_OEM_RESPONSE_EVENTID_param_tlvs *) datap;
1667 if (!param_buf) {
1668 WMA_LOGE(FL("Received NULL buf ptr from FW"));
1669 return -ENOMEM;
1670 }
1671
1672 data = param_buf->data;
1673 datalen = param_buf->num_data;
1674
1675 if (!data) {
1676 WMA_LOGE(FL("Received NULL data from FW"));
1677 return -EINVAL;
1678 }
1679
1680 if (datalen > OEM_DATA_RSP_SIZE) {
1681 WMA_LOGE(FL("Received data len %d exceeds max value %d"),
1682 datalen, OEM_DATA_RSP_SIZE);
1683 return -EINVAL;
1684 }
1685
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001686 oem_rsp = qdf_mem_malloc(sizeof(*oem_rsp));
1687 if (!oem_rsp) {
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001688 WMA_LOGE(FL("Failed to alloc oem_data_rsp"));
1689 return -ENOMEM;
1690 }
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001691 oem_rsp->rsp_len = datalen;
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001692 if (oem_rsp->rsp_len) {
Krishna Kumaar Natarajan73ea9f22016-06-30 18:38:47 -07001693 oem_rsp->data = qdf_mem_malloc(oem_rsp->rsp_len);
1694 if (!oem_rsp->data) {
1695 WMA_LOGE(FL("malloc failed for data"));
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001696 qdf_mem_free(oem_rsp);
1697 return -ENOMEM;
1698 }
1699 } else {
1700 WMA_LOGE(FL("Invalid rsp length: %d"),
1701 oem_rsp->rsp_len);
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001702 qdf_mem_free(oem_rsp);
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001703 return -EINVAL;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001704 }
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001705
Krishna Kumaar Natarajan73ea9f22016-06-30 18:38:47 -07001706 qdf_mem_copy(oem_rsp->data, data, datalen);
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001707
Krishna Kumaar Natarajan73ea9f22016-06-30 18:38:47 -07001708 WMA_LOGI(FL("Sending OEM_DATA_RSP(len: %d) to upper layer"), datalen);
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001709
Krishna Kumaar Natarajanbbbf2ef2016-08-03 14:06:26 -07001710 pmac->sme.oem_data_rsp_callback(oem_rsp);
Krishna Kumaar Natarajan73ea9f22016-06-30 18:38:47 -07001711
1712 if (oem_rsp->data)
1713 qdf_mem_free(oem_rsp->data);
1714 qdf_mem_free(oem_rsp);
1715
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001716 return 0;
1717}
1718
1719/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001720 * wma_start_oem_data_req() - start OEM data request to target
1721 * @wma_handle: wma handle
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -07001722 * @oem_data_req: start request params
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001723 *
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -07001724 * Return: QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001725 */
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -07001726QDF_STATUS wma_start_oem_data_req(tp_wma_handle wma_handle,
Krishna Kumaar Natarajanc1fa17d2016-08-03 14:19:20 -07001727 struct oem_data_req *oem_data_req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001728{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001729 int ret = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001730
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001731 WMA_LOGD(FL("Send OEM Data Request to target"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001732
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -07001733 if (!oem_data_req || !oem_data_req->data) {
1734 WMA_LOGE(FL("oem_data_req is null"));
1735 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001736 }
1737
1738 if (!wma_handle || !wma_handle->wmi_handle) {
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001739 WMA_LOGE(FL("WMA - closed, can not send Oem data request cmd"));
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -07001740 qdf_mem_free(oem_data_req->data);
1741 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001742 }
1743
Govind Singhaa64c242016-03-08 11:31:49 +05301744 ret = wmi_unified_start_oem_data_cmd(wma_handle->wmi_handle,
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -07001745 oem_data_req->data_len,
1746 oem_data_req->data);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001747
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -07001748 if (!QDF_IS_STATUS_SUCCESS(ret))
1749 WMA_LOGE(FL("wmi cmd send failed"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001750
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -07001751 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001752}
1753#endif /* FEATURE_OEM_DATA_SUPPORT */
1754
1755
1756/**
1757 * wma_unified_dfs_radar_rx_event_handler() - dfs radar rx event handler
1758 * @handle: wma handle
1759 * @data: data buffer
1760 * @datalen: data length
1761 *
1762 * WMI handler for WMI_DFS_RADAR_EVENTID
1763 * This handler is registered for handling
1764 * filtered DFS Phyerror. This handler is
1765 * will be invoked only when DFS Phyerr
1766 * filtering offload is enabled.
1767 *
1768 * Return: 1 for Success and 0 for error
1769 */
1770static int wma_unified_dfs_radar_rx_event_handler(void *handle,
1771 uint8_t *data,
1772 uint32_t datalen)
1773{
1774 tp_wma_handle wma = (tp_wma_handle) handle;
1775 struct ieee80211com *ic;
1776 struct ath_dfs *dfs;
1777 struct dfs_event *event;
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05301778 struct dfs_ieee80211_channel *chan;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001779 int empty;
1780 int do_check_chirp = 0;
1781 int is_hw_chirp = 0;
1782 int is_sw_chirp = 0;
1783 int is_pri = 0;
Vishwajith Upendrabf673e72016-01-19 16:05:40 -08001784 bool is_ch_dfs = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001785
1786 WMI_DFS_RADAR_EVENTID_param_tlvs *param_tlvs;
1787 wmi_dfs_radar_event_fixed_param *radar_event;
1788
1789 ic = wma->dfs_ic;
1790 if (NULL == ic) {
1791 WMA_LOGE("%s: dfs_ic is NULL ", __func__);
1792 return 0;
1793 }
1794
1795 dfs = (struct ath_dfs *)ic->ic_dfs;
1796 param_tlvs = (WMI_DFS_RADAR_EVENTID_param_tlvs *) data;
1797
1798 if (NULL == dfs) {
1799 WMA_LOGE("%s: dfs is NULL ", __func__);
1800 return 0;
1801 }
1802 /*
1803 * This parameter holds the number
1804 * of phyerror interrupts to the host
1805 * after the phyerrors have passed through
1806 * false detect filters in the firmware.
1807 */
1808 dfs->dfs_phyerr_count++;
1809
1810 if (!param_tlvs) {
1811 WMA_LOGE("%s: Received NULL data from FW", __func__);
1812 return 0;
1813 }
1814
1815 radar_event = param_tlvs->fixed_param;
1816
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301817 qdf_spin_lock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001818 chan = ic->ic_curchan;
Edhar, Mahesh Kumar35d9b2e2015-10-26 17:06:23 +05301819 if (ic->disable_phy_err_processing) {
1820 WMA_LOGD("%s: radar indication done,drop phyerror event",
1821 __func__);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301822 qdf_spin_unlock_bh(&ic->chan_lock);
Edhar, Mahesh Kumar35d9b2e2015-10-26 17:06:23 +05301823 return 0;
1824 }
1825
Vishwajith Upendrabf673e72016-01-19 16:05:40 -08001826 if (IEEE80211_IS_CHAN_11AC_VHT160(chan)) {
1827 is_ch_dfs = true;
1828 } else if (IEEE80211_IS_CHAN_11AC_VHT80P80(chan)) {
1829 if (cds_get_channel_state(chan->ic_ieee) == CHANNEL_STATE_DFS ||
1830 cds_get_channel_state(chan->ic_ieee_ext -
1831 WMA_80MHZ_START_CENTER_CH_DIFF) ==
1832 CHANNEL_STATE_DFS)
1833 is_ch_dfs = true;
1834 } else {
1835 if (cds_get_channel_state(chan->ic_ieee) == CHANNEL_STATE_DFS)
1836 is_ch_dfs = true;
1837 }
1838 if (!is_ch_dfs) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001839 WMA_LOGE
1840 ("%s: Invalid DFS Phyerror event. Channel=%d is Non-DFS",
1841 __func__, chan->ic_ieee);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301842 qdf_spin_unlock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001843 return 0;
1844 }
1845
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301846 qdf_spin_unlock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001847 dfs->ath_dfs_stats.total_phy_errors++;
1848
1849 if (dfs->dfs_caps.ath_chip_is_bb_tlv) {
1850 do_check_chirp = 1;
1851 is_pri = 1;
1852 is_hw_chirp = radar_event->pulse_is_chirp;
1853
1854 if ((uint32_t) dfs->dfs_phyerr_freq_min >
1855 radar_event->pulse_center_freq) {
1856 dfs->dfs_phyerr_freq_min =
1857 (int)radar_event->pulse_center_freq;
1858 }
1859
1860 if (dfs->dfs_phyerr_freq_max <
1861 (int)radar_event->pulse_center_freq) {
1862 dfs->dfs_phyerr_freq_max =
1863 (int)radar_event->pulse_center_freq;
1864 }
1865 }
1866
1867 /*
1868 * Now, add the parsed, checked and filtered
1869 * radar phyerror event radar pulse event list.
1870 * This event will then be processed by
1871 * dfs_radar_processevent() to see if the pattern
1872 * of pulses in radar pulse list match any radar
1873 * singnature in the current regulatory domain.
1874 */
1875
1876 ATH_DFSEVENTQ_LOCK(dfs);
1877 empty = STAILQ_EMPTY(&(dfs->dfs_eventq));
1878 ATH_DFSEVENTQ_UNLOCK(dfs);
1879 if (empty) {
1880 return 0;
1881 }
1882 /*
1883 * Add the event to the list, if there's space.
1884 */
1885 ATH_DFSEVENTQ_LOCK(dfs);
1886 event = STAILQ_FIRST(&(dfs->dfs_eventq));
1887 if (event == NULL) {
1888 ATH_DFSEVENTQ_UNLOCK(dfs);
1889 WMA_LOGE("%s: No more space left for queuing DFS Phyerror events",
1890 __func__);
1891 return 0;
1892 }
1893 STAILQ_REMOVE_HEAD(&(dfs->dfs_eventq), re_list);
1894 ATH_DFSEVENTQ_UNLOCK(dfs);
1895 dfs->dfs_phyerr_queued_count++;
1896 dfs->dfs_phyerr_w53_counter++;
1897 event->re_dur = (uint8_t) radar_event->pulse_duration;
1898 event->re_rssi = radar_event->rssi;
1899 event->re_ts = radar_event->pulse_detect_ts & DFS_TSMASK;
1900 event->re_full_ts = (((uint64_t) radar_event->upload_fullts_high) << 32)
1901 | radar_event->upload_fullts_low;
1902
1903 /*
1904 * Index of peak magnitude
1905 */
1906 event->sidx = radar_event->peak_sidx;
Kapil Guptae29ab4a2016-08-09 18:36:12 +05301907 event->re_flags = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001908
1909 /*
1910 * Handle chirp flags.
1911 */
1912 if (do_check_chirp) {
1913 event->re_flags |= DFS_EVENT_CHECKCHIRP;
1914 if (is_hw_chirp) {
1915 event->re_flags |= DFS_EVENT_HW_CHIRP;
1916 }
1917 if (is_sw_chirp) {
1918 event->re_flags |= DFS_EVENT_SW_CHIRP;
1919 }
1920 }
1921 /*
1922 * Correctly set which channel is being reported on
1923 */
1924 if (is_pri) {
1925 event->re_chanindex = (uint8_t) dfs->dfs_curchan_radindex;
1926 } else {
1927 if (dfs->dfs_extchan_radindex == -1) {
1928 WMA_LOGI("%s phyerr on ext channel", __func__);
1929 }
1930 event->re_chanindex = (uint8_t) dfs->dfs_extchan_radindex;
1931 WMA_LOGI("%s:New extension channel event is added to queue",
1932 __func__);
1933 }
1934
1935 ATH_DFSQ_LOCK(dfs);
1936
1937 STAILQ_INSERT_TAIL(&(dfs->dfs_radarq), event, re_list);
1938
1939 empty = STAILQ_EMPTY(&dfs->dfs_radarq);
1940
1941 ATH_DFSQ_UNLOCK(dfs);
1942
1943 if (!empty && !dfs->ath_radar_tasksched) {
1944 dfs->ath_radar_tasksched = 1;
1945 OS_SET_TIMER(&dfs->ath_dfs_task_timer, 0);
1946 }
1947
1948 return 1;
1949
1950}
1951
1952/**
1953 * wma_unified_phyerr_rx_event_handler() - phyerr event handler
1954 * @handle: wma handle
1955 * @data: data buffer
1956 * @datalen: buffer length
1957 *
1958 * WMI Handler for WMI_PHYERR_EVENTID event from firmware.
1959 * This handler is currently handling only DFS phy errors.
1960 * This handler will be invoked only when the DFS phyerror
1961 * filtering offload is disabled.
1962 *
1963 * Return: 1:Success, 0:Failure
1964 */
1965static int wma_unified_phyerr_rx_event_handler(void *handle,
1966 uint8_t *data, uint32_t datalen)
1967{
1968 tp_wma_handle wma = (tp_wma_handle) handle;
1969 WMI_PHYERR_EVENTID_param_tlvs *param_tlvs;
1970 wmi_comb_phyerr_rx_hdr *pe_hdr;
1971 uint8_t *bufp;
1972 wmi_single_phyerr_rx_event *ev;
1973 struct ieee80211com *ic = wma->dfs_ic;
Anurag Chouhan6d760662016-02-20 16:05:43 +05301974 qdf_size_t n;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001975 A_UINT64 tsf64 = 0;
1976 int phy_err_code = 0;
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08001977 A_UINT32 phy_err_mask = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001978 int error = 0;
1979 tpAniSirGlobal mac_ctx =
Anurag Chouhan6d760662016-02-20 16:05:43 +05301980 (tpAniSirGlobal)cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001981 bool enable_log = false;
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08001982 int max_dfs_buf_length = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001983
1984 if (NULL == mac_ctx) {
1985 WMA_LOGE("%s: mac_ctx is NULL", __func__);
1986 return 0;
1987 }
1988 enable_log = mac_ctx->sap.enable_dfs_phy_error_logs;
1989
1990 param_tlvs = (WMI_PHYERR_EVENTID_param_tlvs *) data;
1991
1992 if (!param_tlvs) {
1993 WMA_LOGE("%s: Received NULL data from FW", __func__);
1994 return 0;
1995 }
1996
1997 pe_hdr = param_tlvs->hdr;
1998 if (pe_hdr == NULL) {
1999 WMA_LOGE("%s: Received Data PE Header is NULL", __func__);
2000 return 0;
2001 }
2002
2003 /* Ensure it's at least the size of the header */
2004 if (datalen < sizeof(*pe_hdr)) {
2005 WMA_LOGE("%s: Expected minimum size %zu, received %d",
2006 __func__, sizeof(*pe_hdr), datalen);
2007 return 0;
2008 }
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002009 /*
2010 * The max buffer lenght is larger for DFS-3 than DFS-2.
2011 * So, accordingly use the correct max buffer size.
2012 */
2013 if (wma->hw_bd_id != WMI_HWBD_QCA6174)
2014 max_dfs_buf_length = DFS3_MAX_BUF_LENGTH;
2015 else
2016 max_dfs_buf_length = DFS_MAX_BUF_LENGTH;
2017
2018 if (pe_hdr->buf_len > max_dfs_buf_length) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002019 WMA_LOGE("%s: Received Invalid Phyerror event buffer length = %d"
2020 "Maximum allowed buf length = %d", __func__,
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002021 pe_hdr->buf_len, max_dfs_buf_length);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002022
2023 return 0;
2024 }
2025
2026 /*
2027 * Reconstruct the 64 bit event TSF. This isn't from the MAC, it's
2028 * at the time the event was sent to us, the TSF value will be
2029 * in the future.
2030 */
2031 tsf64 = pe_hdr->tsf_l32;
2032 tsf64 |= (((uint64_t) pe_hdr->tsf_u32) << 32);
2033
2034 /*
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002035 * Check the HW board ID to figure out
2036 * if DFS-3 is supported. In DFS-3
2037 * phyerror mask indicates the type of
2038 * phyerror, whereas in DFS-2 phyerrorcode
2039 * indicates the type of phyerror. If the
2040 * board is NOT WMI_HWBD_QCA6174, for now
2041 * assume that it supports DFS-3.
2042 */
2043 if (wma->hw_bd_id != WMI_HWBD_QCA6174) {
2044 phy_err_mask = pe_hdr->rsPhyErrMask0;
2045 WMA_LOGD("%s: DFS-3 phyerror mask = 0x%x",
2046 __func__, phy_err_mask);
2047 }
2048
2049 /*
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002050 * Loop over the bufp, extracting out phyerrors
2051 * wmi_unified_comb_phyerr_rx_event.bufp is a char pointer,
2052 * which isn't correct here - what we have received here
2053 * is an array of TLV-style PHY errors.
2054 */
2055 n = 0; /* Start just after the header */
2056 bufp = param_tlvs->bufp;
2057 while (n < pe_hdr->buf_len) {
2058 /* ensure there's at least space for the header */
2059 if ((pe_hdr->buf_len - n) < sizeof(ev->hdr)) {
2060 WMA_LOGE("%s: Not enough space.(datalen=%d, n=%zu, hdr=%zu bytes",
2061 __func__, pe_hdr->buf_len, n, sizeof(ev->hdr));
2062 error = 1;
2063 break;
2064 }
2065 /*
2066 * Obtain a pointer to the beginning of the current event.
2067 * data[0] is the beginning of the WMI payload.
2068 */
2069 ev = (wmi_single_phyerr_rx_event *) &bufp[n];
2070
2071 /*
2072 * Sanity check the buffer length of the event against
2073 * what we currently have.
2074 * Since buf_len is 32 bits, we check if it overflows
2075 * a large 32 bit value. It's not 0x7fffffff because
2076 * we increase n by (buf_len + sizeof(hdr)), which would
2077 * in itself cause n to overflow.
2078 * If "int" is 64 bits then this becomes a moot point.
2079 */
2080 if (ev->hdr.buf_len > 0x7f000000) {
2081 WMA_LOGE("%s:buf_len is garbage (0x%x)", __func__,
2082 ev->hdr.buf_len);
2083 error = 1;
2084 break;
2085 }
2086 if (n + ev->hdr.buf_len > pe_hdr->buf_len) {
2087 WMA_LOGE("%s: buf_len exceeds available space n=%zu,"
2088 "buf_len=%d, datalen=%d",
2089 __func__, n, ev->hdr.buf_len, pe_hdr->buf_len);
2090 error = 1;
2091 break;
2092 }
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002093 /*
2094 * If the board id is WMI_HWBD_QCA6174
2095 * then it supports only DFS-2. So, fetch
2096 * phyerror code in order to know the type
2097 * of phyerror.
2098 */
2099 if (wma->hw_bd_id == WMI_HWBD_QCA6174) {
2100 phy_err_code = WMI_UNIFIED_PHYERRCODE_GET(&ev->hdr);
2101 WMA_LOGD("%s: DFS-2 phyerror code = 0x%x",
2102 __func__, phy_err_code);
2103 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002104
2105 /*
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002106 * phy_err_code is set for DFS-2 and phy_err_mask
2107 * is set for DFS-3. Checking both to support
2108 * compatability for older platforms.
2109 * If the phyerror or phyerrmask category matches,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002110 * pass radar events to the dfs pattern matching code.
2111 * Don't pass radar events with no buffer payload.
2112 */
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002113 if (((phy_err_mask & WMI_PHY_ERROR_MASK0_RADAR) ||
2114 (phy_err_mask & WMI_PHY_ERROR_MASK0_FALSE_RADAR_EXT)) ||
2115 (phy_err_code == WMA_DFS2_PHYERROR_CODE ||
2116 phy_err_code == WMA_DFS2_FALSE_RADAR_EXT)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002117 if (ev->hdr.buf_len > 0) {
2118 /* Calling in to the DFS module to process the phyerr */
2119 dfs_process_phyerr(ic, &ev->bufp[0],
2120 ev->hdr.buf_len,
2121 WMI_UNIFIED_RSSI_COMB_GET
2122 (&ev->hdr) & 0xff,
2123 /* Extension RSSI */
2124 WMI_UNIFIED_RSSI_COMB_GET
2125 (&ev->hdr) & 0xff,
2126 ev->hdr.tsf_timestamp,
2127 tsf64, enable_log);
2128 }
2129 }
2130
2131 /*
2132 * Advance the buffer pointer to the next PHY error.
2133 * buflen is the length of this payload, so we need to
2134 * advance past the current header _AND_ the payload.
2135 */
2136 n += sizeof(*ev) + ev->hdr.buf_len;
2137
2138 } /*end while() */
2139 if (error)
2140 return 0;
2141 else
2142 return 1;
2143}
2144
2145/**
2146 * wma_register_dfs_event_handler() - register dfs event handler
2147 * @wma_handle: wma handle
2148 *
2149 * Register appropriate dfs phyerror event handler
2150 * based on phyerror filtering offload is enabled
2151 * or disabled.
2152 *
2153 * Return: none
2154 */
2155void wma_register_dfs_event_handler(tp_wma_handle wma_handle)
2156{
2157 if (NULL == wma_handle) {
2158 WMA_LOGE("%s:wma_handle is NULL", __func__);
2159 return;
2160 }
2161
2162 if (false == wma_handle->dfs_phyerr_filter_offload) {
2163 /*
2164 * Register the wma_unified_phyerr_rx_event_handler
2165 * for filtering offload disabled case to handle
2166 * the DFS phyerrors.
2167 */
2168 WMA_LOGD("%s:Phyerror Filtering offload is Disabled in ini",
2169 __func__);
2170 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Govind Singhd76a5b02016-03-08 15:12:14 +05302171 WMI_PHYERR_EVENTID,
2172 wma_unified_phyerr_rx_event_handler,
2173 WMA_RX_WORK_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002174 WMA_LOGD("%s: WMI_PHYERR_EVENTID event handler registered",
2175 __func__);
2176 } else {
2177 WMA_LOGD("%s:Phyerror Filtering offload is Enabled in ini",
2178 __func__);
2179 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Govind Singhd76a5b02016-03-08 15:12:14 +05302180 WMI_DFS_RADAR_EVENTID,
2181 wma_unified_dfs_radar_rx_event_handler,
2182 WMA_RX_WORK_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002183 WMA_LOGD("%s:WMI_DFS_RADAR_EVENTID event handler registered",
2184 __func__);
2185 }
2186
2187 return;
2188}
2189
2190
2191/**
2192 * wma_unified_dfs_phyerr_filter_offload_enable() - enable dfs phyerr filter
2193 * @wma_handle: wma handle
2194 *
2195 * Send WMI_DFS_PHYERR_FILTER_ENA_CMDID or
2196 * WMI_DFS_PHYERR_FILTER_DIS_CMDID command
2197 * to firmware based on phyerr filtering
2198 * offload status.
2199 *
2200 * Return: 1 success, 0 failure
2201 */
2202int
2203wma_unified_dfs_phyerr_filter_offload_enable(tp_wma_handle wma_handle)
2204{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002205 int ret;
2206
2207 if (NULL == wma_handle) {
2208 WMA_LOGE("%s:wma_handle is NULL", __func__);
2209 return 0;
2210 }
2211
Govind Singhaa64c242016-03-08 11:31:49 +05302212 ret = wmi_unified_dfs_phyerr_filter_offload_en_cmd(wma_handle->wmi_handle,
2213 wma_handle->dfs_phyerr_filter_offload);
2214 if (ret)
2215 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002216
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002217
Govind Singhaa64c242016-03-08 11:31:49 +05302218 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002219}
2220
2221#if !defined(REMOVE_PKT_LOG)
2222/**
2223 * wma_pktlog_wmi_send_cmd() - send pktlog enable/disable command to target
2224 * @handle: wma handle
2225 * @params: pktlog params
2226 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302227 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002228 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302229QDF_STATUS wma_pktlog_wmi_send_cmd(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002230 struct ath_pktlog_wmi_params *params)
2231{
2232 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhaa64c242016-03-08 11:31:49 +05302233 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002234
Govind Singhaa64c242016-03-08 11:31:49 +05302235 ret = wmi_unified_pktlog_wmi_send_cmd(wma_handle->wmi_handle,
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08002236 params->pktlog_event,
2237 params->cmd_id, params->user_triggered);
Govind Singhaa64c242016-03-08 11:31:49 +05302238 if (ret)
2239 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002240
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302241 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002242}
2243#endif /* REMOVE_PKT_LOG */
2244
2245static void wma_send_status_to_suspend_ind(tp_wma_handle wma, bool suspended)
2246{
2247 tSirReadyToSuspendInd *ready_to_suspend;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302248 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002249 cds_msg_t cds_msg;
2250 uint8_t len;
2251
2252 WMA_LOGD("Posting ready to suspend indication to umac");
2253
2254 len = sizeof(tSirReadyToSuspendInd);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302255 ready_to_suspend = (tSirReadyToSuspendInd *) qdf_mem_malloc(len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002256
2257 if (NULL == ready_to_suspend) {
2258 WMA_LOGE("%s: Memory allocation failure", __func__);
2259 return;
2260 }
2261
2262 ready_to_suspend->mesgType = eWNI_SME_READY_TO_SUSPEND_IND;
2263 ready_to_suspend->mesgLen = len;
2264 ready_to_suspend->suspended = suspended;
2265
2266 cds_msg.type = eWNI_SME_READY_TO_SUSPEND_IND;
2267 cds_msg.bodyptr = (void *)ready_to_suspend;
2268 cds_msg.bodyval = 0;
2269
2270 status = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302271 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002272 WMA_LOGE("Failed to post ready to suspend");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302273 qdf_mem_free(ready_to_suspend);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002274 }
2275}
2276
2277/**
2278 * wma_wow_wake_reason_str() - Converts wow wakeup reason code to text format
2279 * @wake_reason - WOW wake reason
2280 *
2281 * Return: reason code in string format
2282 */
2283static const u8 *wma_wow_wake_reason_str(A_INT32 wake_reason)
2284{
2285 switch (wake_reason) {
2286 case WOW_REASON_UNSPECIFIED:
2287 return "UNSPECIFIED";
2288 case WOW_REASON_NLOD:
2289 return "NLOD";
2290 case WOW_REASON_AP_ASSOC_LOST:
2291 return "AP_ASSOC_LOST";
2292 case WOW_REASON_LOW_RSSI:
2293 return "LOW_RSSI";
2294 case WOW_REASON_DEAUTH_RECVD:
2295 return "DEAUTH_RECVD";
2296 case WOW_REASON_DISASSOC_RECVD:
2297 return "DISASSOC_RECVD";
2298 case WOW_REASON_GTK_HS_ERR:
2299 return "GTK_HS_ERR";
2300 case WOW_REASON_EAP_REQ:
2301 return "EAP_REQ";
2302 case WOW_REASON_FOURWAY_HS_RECV:
2303 return "FOURWAY_HS_RECV";
2304 case WOW_REASON_TIMER_INTR_RECV:
2305 return "TIMER_INTR_RECV";
2306 case WOW_REASON_PATTERN_MATCH_FOUND:
2307 return "PATTERN_MATCH_FOUND";
2308 case WOW_REASON_RECV_MAGIC_PATTERN:
2309 return "RECV_MAGIC_PATTERN";
2310 case WOW_REASON_P2P_DISC:
2311 return "P2P_DISC";
2312#ifdef FEATURE_WLAN_LPHB
2313 case WOW_REASON_WLAN_HB:
2314 return "WLAN_HB";
2315#endif /* FEATURE_WLAN_LPHB */
2316
2317 case WOW_REASON_CSA_EVENT:
2318 return "CSA_EVENT";
2319 case WOW_REASON_PROBE_REQ_WPS_IE_RECV:
2320 return "PROBE_REQ_RECV";
2321 case WOW_REASON_AUTH_REQ_RECV:
2322 return "AUTH_REQ_RECV";
2323 case WOW_REASON_ASSOC_REQ_RECV:
2324 return "ASSOC_REQ_RECV";
2325 case WOW_REASON_HTT_EVENT:
2326 return "WOW_REASON_HTT_EVENT";
2327#ifdef FEATURE_WLAN_RA_FILTERING
2328 case WOW_REASON_RA_MATCH:
2329 return "WOW_REASON_RA_MATCH";
2330#endif /* FEATURE_WLAN_RA_FILTERING */
2331 case WOW_REASON_BEACON_RECV:
2332 return "WOW_REASON_IBSS_BEACON_RECV";
2333#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
2334 case WOW_REASON_HOST_AUTO_SHUTDOWN:
2335 return "WOW_REASON_HOST_AUTO_SHUTDOWN";
2336#endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
2337#ifdef WLAN_FEATURE_ROAM_OFFLOAD
2338 case WOW_REASON_ROAM_HO:
2339 return "WOW_REASON_ROAM_HO";
2340#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
2341#ifdef FEATURE_WLAN_EXTSCAN
2342 case WOW_REASON_EXTSCAN:
2343 return "WOW_REASON_EXTSCAN";
2344#endif
2345 case WOW_REASON_RSSI_BREACH_EVENT:
2346 return "WOW_REASON_RSSI_BREACH_EVENT";
Srinivas Girigowdae80cea92015-11-23 11:33:57 -08002347 case WOW_REASON_NLO_SCAN_COMPLETE:
2348 return "WOW_REASON_NLO_SCAN_COMPLETE";
Naveen Rawatc9f09522016-05-12 14:02:42 -07002349 case WOW_REASON_NAN_EVENT:
2350 return "WOW_REASON_NAN_EVENT";
Selvaraj, Sridhar172cabc2016-07-05 15:19:24 +05302351 case WOW_REASON_OEM_RESPONSE_EVENT:
2352 return "WOW_OEM_RESPONSE_EVENT";
Himanshu Agarwaldd356df2016-07-20 19:04:39 +05302353 case WOW_REASON_ASSOC_RES_RECV:
2354 return "ASSOC_RES_RECV";
2355 case WOW_REASON_REASSOC_REQ_RECV:
2356 return "REASSOC_REQ_RECV";
2357 case WOW_REASON_REASSOC_RES_RECV:
2358 return "REASSOC_RES_RECV";
2359 case WOW_REASON_ACTION_FRAME_RECV:
2360 return "ACTION_FRAME_RECV";
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05302361 case WOW_REASON_BPF_ALLOW:
2362 return "WOW_REASON_BPF_ALLOW";
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002363 }
2364 return "unknown";
2365}
2366
2367/**
2368 * wma_wow_wake_up_stats_display() - display wow wake up stats
2369 * @wma: Pointer to wma handle
2370 *
2371 * Return: none
2372 */
2373static void wma_wow_wake_up_stats_display(tp_wma_handle wma)
2374{
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05302375 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 -08002376 wma->wow_ucast_wake_up_count,
2377 wma->wow_bcast_wake_up_count,
2378 wma->wow_ipv4_mcast_wake_up_count,
2379 wma->wow_ipv6_mcast_wake_up_count,
2380 wma->wow_ipv6_mcast_ra_stats,
2381 wma->wow_ipv6_mcast_ns_stats,
2382 wma->wow_ipv6_mcast_na_stats,
2383 wma->wow_pno_match_wake_up_count,
2384 wma->wow_pno_complete_wake_up_count,
2385 wma->wow_gscan_wake_up_count,
2386 wma->wow_low_rssi_wake_up_count,
Selvaraj, Sridhar172cabc2016-07-05 15:19:24 +05302387 wma->wow_rssi_breach_wake_up_count,
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05302388 wma->wow_icmpv4_count,
Himanshu Agarwal4574e282016-08-10 15:22:45 +05302389 wma->wow_icmpv6_count,
Selvaraj, Sridhar172cabc2016-07-05 15:19:24 +05302390 wma->wow_oem_response_wake_up_count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002391
2392 return;
2393}
2394
2395/**
2396 * wma_wow_ipv6_mcast_stats() - ipv6 mcast wake up stats
2397 * @wma: Pointer to wma handle
2398 * @data: Pointer to pattern match data
2399 *
2400 * Return: none
2401 */
2402static void wma_wow_ipv6_mcast_stats(tp_wma_handle wma, uint8_t *data)
2403{
Himanshu Agarwal4574e282016-08-10 15:22:45 +05302404 static const uint8_t ipv6_ether_type[] = {0x86, 0xDD};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002405
Himanshu Agarwal4574e282016-08-10 15:22:45 +05302406 if (!memcmp(ipv6_ether_type, (data + WMA_ETHER_TYPE_OFFSET),
2407 sizeof(ipv6_ether_type))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002408 if (WMA_ICMP_V6_HEADER_TYPE ==
2409 *(data + WMA_ICMP_V6_HEADER_OFFSET)) {
Himanshu Agarwal4574e282016-08-10 15:22:45 +05302410 wma->wow_icmpv6_count++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002411 if (WMA_ICMP_V6_RA_TYPE ==
2412 *(data + WMA_ICMP_V6_TYPE_OFFSET))
2413 wma->wow_ipv6_mcast_ra_stats++;
2414 else if (WMA_ICMP_V6_NS_TYPE ==
2415 *(data + WMA_ICMP_V6_TYPE_OFFSET))
2416 wma->wow_ipv6_mcast_ns_stats++;
2417 else if (WMA_ICMP_V6_NA_TYPE ==
2418 *(data + WMA_ICMP_V6_TYPE_OFFSET))
2419 wma->wow_ipv6_mcast_na_stats++;
2420 else
2421 WMA_LOGA("ICMP V6 type : 0x%x",
2422 *(data + WMA_ICMP_V6_TYPE_OFFSET));
2423 } else {
2424 WMA_LOGA("ICMP_V6 header 0x%x",
2425 *(data + WMA_ICMP_V6_HEADER_OFFSET));
2426 }
2427 } else {
2428 WMA_LOGA("Ethertype x%x:0x%x",
2429 *(data + WMA_ETHER_TYPE_OFFSET),
2430 *(data + WMA_ETHER_TYPE_OFFSET + 1));
2431 }
2432
2433 return;
2434}
2435
2436/**
2437 * wma_wow_wake_up_stats() - maintain wow pattern match wake up stats
2438 * @wma: Pointer to wma handle
2439 * @data: Pointer to pattern match data
2440 * @len: Pattern match data length
2441 * @event: Wake up event
2442 *
2443 * Return: none
2444 */
2445static void wma_wow_wake_up_stats(tp_wma_handle wma, uint8_t *data,
2446 int32_t len, WOW_WAKE_REASON_TYPE event)
2447{
2448 switch (event) {
2449
Dustin Brown75d02342016-08-29 11:23:47 -07002450 case WOW_REASON_BPF_ALLOW:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002451 case WOW_REASON_PATTERN_MATCH_FOUND:
2452 if (WMA_BCAST_MAC_ADDR == *data) {
2453 wma->wow_bcast_wake_up_count++;
Himanshu Agarwal11a08c02016-08-10 15:39:54 +05302454 if (len >= WMA_IPV4_PROTO_GET_MIN_LEN &&
2455 qdf_nbuf_data_is_icmp_pkt(data))
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05302456 wma->wow_icmpv4_count++;
Himanshu Agarwal4574e282016-08-10 15:22:45 +05302457 else if ((len > WMA_ICMP_V6_TYPE_OFFSET) &&
2458 qdf_nbuf_data_is_icmpv6_pkt(data))
2459 wma->wow_icmpv6_count++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002460 } else if (WMA_MCAST_IPV4_MAC_ADDR == *data) {
2461 wma->wow_ipv4_mcast_wake_up_count++;
Himanshu Agarwal11a08c02016-08-10 15:39:54 +05302462 if (len >= WMA_IPV4_PROTO_GET_MIN_LEN &&
2463 WMA_ICMP_PROTOCOL == *(data + WMA_IPV4_PROTOCOL))
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05302464 wma->wow_icmpv4_count++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002465 } else if (WMA_MCAST_IPV6_MAC_ADDR == *data) {
2466 wma->wow_ipv6_mcast_wake_up_count++;
2467 if (len > WMA_ICMP_V6_TYPE_OFFSET)
2468 wma_wow_ipv6_mcast_stats(wma, data);
2469 else
2470 WMA_LOGA("ICMP_V6 data len %d", len);
2471 } else {
2472 wma->wow_ucast_wake_up_count++;
Himanshu Agarwal11a08c02016-08-10 15:39:54 +05302473 if (qdf_nbuf_data_is_ipv4_mcast_pkt(data))
2474 wma->wow_ipv4_mcast_wake_up_count++;
2475 else if (qdf_nbuf_data_is_ipv6_mcast_pkt(data))
2476 wma->wow_ipv6_mcast_wake_up_count++;
2477
2478 if (len >= WMA_IPV4_PROTO_GET_MIN_LEN &&
2479 qdf_nbuf_data_is_icmp_pkt(data))
2480 wma->wow_icmpv4_count++;
2481 else if (len > WMA_ICMP_V6_TYPE_OFFSET &&
Himanshu Agarwal4574e282016-08-10 15:22:45 +05302482 qdf_nbuf_data_is_icmpv6_pkt(data))
2483 wma->wow_icmpv6_count++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002484 }
2485 break;
2486
2487 case WOW_REASON_RA_MATCH:
Himanshu Agarwal4574e282016-08-10 15:22:45 +05302488 wma->wow_icmpv6_count++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002489 wma->wow_ipv6_mcast_ra_stats++;
Himanshu Agarwal4574e282016-08-10 15:22:45 +05302490 wma->wow_ipv6_mcast_wake_up_count++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002491 break;
2492
2493 case WOW_REASON_NLOD:
2494 wma->wow_pno_match_wake_up_count++;
2495 break;
2496
2497 case WOW_REASON_NLO_SCAN_COMPLETE:
2498 wma->wow_pno_complete_wake_up_count++;
2499 break;
2500
2501 case WOW_REASON_LOW_RSSI:
2502 wma->wow_low_rssi_wake_up_count++;
2503 break;
2504
2505 case WOW_REASON_EXTSCAN:
2506 wma->wow_gscan_wake_up_count++;
2507 break;
2508
2509 case WOW_REASON_RSSI_BREACH_EVENT:
2510 wma->wow_rssi_breach_wake_up_count++;
2511 break;
Selvaraj, Sridhar172cabc2016-07-05 15:19:24 +05302512 case WOW_REASON_OEM_RESPONSE_EVENT:
2513 wma->wow_oem_response_wake_up_count++;
2514 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002515
2516 default:
2517 WMA_LOGE("Unknown wake up reason");
2518 break;
2519 }
2520
2521 wma_wow_wake_up_stats_display(wma);
2522 return;
2523}
2524
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07002525#ifdef FEATURE_WLAN_EXTSCAN
2526/**
2527 * wma_extscan_get_eventid_from_tlvtag() - map tlv tag to corresponding event id
2528 * @tag: WMI TLV tag
2529 *
2530 * Return:
2531 * 0 if TLV tag is invalid
2532 * else return corresponding WMI event id
2533 */
2534static int wma_extscan_get_eventid_from_tlvtag(uint32_t tag)
2535{
2536 uint32_t event_id;
2537
2538 switch (tag) {
2539 case WMITLV_TAG_STRUC_wmi_extscan_start_stop_event_fixed_param:
2540 event_id = WMI_EXTSCAN_START_STOP_EVENTID;
2541 break;
2542
2543 case WMITLV_TAG_STRUC_wmi_extscan_operation_event_fixed_param:
2544 event_id = WMI_EXTSCAN_OPERATION_EVENTID;
2545 break;
2546
2547 case WMITLV_TAG_STRUC_wmi_extscan_table_usage_event_fixed_param:
2548 event_id = WMI_EXTSCAN_TABLE_USAGE_EVENTID;
2549 break;
2550
2551 case WMITLV_TAG_STRUC_wmi_extscan_cached_results_event_fixed_param:
2552 event_id = WMI_EXTSCAN_CACHED_RESULTS_EVENTID;
2553 break;
2554
2555 case WMITLV_TAG_STRUC_wmi_extscan_wlan_change_results_event_fixed_param:
2556 event_id = WMI_EXTSCAN_WLAN_CHANGE_RESULTS_EVENTID;
2557 break;
2558
2559 case WMITLV_TAG_STRUC_wmi_extscan_hotlist_match_event_fixed_param:
2560 event_id = WMI_EXTSCAN_HOTLIST_MATCH_EVENTID;
2561 break;
2562
2563 case WMITLV_TAG_STRUC_wmi_extscan_capabilities_event_fixed_param:
2564 event_id = WMI_EXTSCAN_CAPABILITIES_EVENTID;
2565 break;
2566
2567 case WMITLV_TAG_STRUC_wmi_extscan_hotlist_ssid_match_event_fixed_param:
2568 event_id = WMI_EXTSCAN_HOTLIST_SSID_MATCH_EVENTID;
2569 break;
2570
2571 default:
2572 event_id = 0;
2573 WMA_LOGE("%s: Unknown tag: %d", __func__, tag);
2574 break;
2575 }
2576
2577 WMA_LOGI("%s: For tag %d WMI event 0x%x", __func__, tag, event_id);
2578 return event_id;
2579}
2580#else
2581static int wma_extscan_get_eventid_from_tlvtag(uint32_t tag)
2582{
2583 return 0;
2584}
2585#endif
2586
2587/**
2588 * wow_get_wmi_eventid() - map reason or tlv tag to corresponding event id
2589 * @tag: WMI TLV tag
2590 * @reason: WOW reason
2591 *
2592 * WOW reason type is primarily used to find the ID. If there could be
2593 * multiple events that can be sent as a WOW event with same reason
2594 * then tlv tag is used to identify the corresponding event.
2595 *
2596 * Return:
2597 * 0 if TLV tag/reason is invalid
2598 * else return corresponding WMI event id
2599 */
2600static int wow_get_wmi_eventid(int32_t reason, uint32_t tag)
2601{
2602 uint32_t event_id;
2603
2604 switch (reason) {
2605 case WOW_REASON_NLO_SCAN_COMPLETE:
2606 event_id = WMI_NLO_SCAN_COMPLETE_EVENTID;
2607 break;
2608 case WOW_REASON_CSA_EVENT:
2609 event_id = WMI_CSA_HANDLING_EVENTID;
2610 break;
2611 case WOW_REASON_LOW_RSSI:
2612 event_id = WMI_ROAM_EVENTID;
2613 break;
2614 case WOW_REASON_CLIENT_KICKOUT_EVENT:
2615 event_id = WMI_PEER_STA_KICKOUT_EVENTID;
2616 break;
2617 case WOW_REASON_EXTSCAN:
2618 event_id = wma_extscan_get_eventid_from_tlvtag(tag);
2619 break;
2620 case WOW_REASON_RSSI_BREACH_EVENT:
2621 event_id = WMI_RSSI_BREACH_EVENTID;
2622 break;
2623 case WOW_REASON_NAN_EVENT:
2624 event_id = WMI_NAN_EVENTID;
2625 break;
Naveen Rawat17dccbe2016-08-23 17:09:04 -07002626 case WOW_REASON_NAN_DATA:
2627 event_id = wma_ndp_get_eventid_from_tlvtag(tag);
2628 break;
Selvaraj, Sridhar251761a2016-06-25 16:05:15 +05302629 case WOW_REASON_TDLS_CONN_TRACKER_EVENT:
2630 event_id = WOW_TDLS_CONN_TRACKER_EVENT;
2631 break;
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07002632 default:
2633 WMA_LOGD(FL("Unexpected WOW reason : %s(%d)"),
2634 wma_wow_wake_reason_str(reason), reason);
2635 event_id = 0;
2636 break;
2637 }
2638
2639 return event_id;
2640}
2641
2642/**
2643 * tlv_check_required() - tells whether to check the wow packet buffer
2644 * for proper TLV structure.
2645 * @reason: WOW reason
2646 *
2647 * In most cases, wow wake up event carries the actual event buffer in
2648 * wow_packet_buffer with some exceptions. This function is used to
2649 * determine when to check for the TLVs in wow_packet_buffer.
2650 *
2651 * Return: true if check is required and false otherwise.
2652 */
2653static bool tlv_check_required(int32_t reason)
2654{
2655 switch (reason) {
Krishna Kumaar Natarajane1a59832016-09-07 12:19:24 -07002656 case WOW_REASON_NLO_SCAN_COMPLETE:
2657 case WOW_REASON_CSA_EVENT:
2658 case WOW_REASON_LOW_RSSI:
2659 case WOW_REASON_CLIENT_KICKOUT_EVENT:
2660 case WOW_REASON_EXTSCAN:
2661 case WOW_REASON_RSSI_BREACH_EVENT:
2662 case WOW_REASON_NAN_EVENT:
2663 case WOW_REASON_NAN_DATA:
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07002664 return true;
Krishna Kumaar Natarajane1a59832016-09-07 12:19:24 -07002665 default:
2666 return false;
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07002667 }
2668}
2669
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002670/**
Himanshu Agarwal82de9042016-07-20 18:11:03 +05302671 * wma_pkt_proto_subtype_to_string() - to convert proto subtype
2672 * of data packet to string.
2673 * @proto_subtype: proto subtype for data packet
2674 *
2675 * This function returns the string for the proto subtype of
2676 * data packet.
2677 *
2678 * Return: string for proto subtype for data packet
2679 */
2680const char *
2681wma_pkt_proto_subtype_to_string(enum qdf_proto_subtype proto_subtype)
2682{
2683 switch (proto_subtype) {
2684 case QDF_PROTO_EAPOL_M1:
2685 return "EAPOL M1";
2686 case QDF_PROTO_EAPOL_M2:
2687 return "EAPOL M2";
2688 case QDF_PROTO_EAPOL_M3:
2689 return "EAPOL M3";
2690 case QDF_PROTO_EAPOL_M4:
2691 return "EAPOL M4";
2692 case QDF_PROTO_DHCP_DISCOVER:
2693 return "DHCP DISCOVER";
2694 case QDF_PROTO_DHCP_REQUEST:
2695 return "DHCP REQUEST";
2696 case QDF_PROTO_DHCP_OFFER:
2697 return "DHCP OFFER";
2698 case QDF_PROTO_DHCP_ACK:
2699 return "DHCP ACK";
2700 case QDF_PROTO_DHCP_NACK:
2701 return "DHCP NACK";
2702 case QDF_PROTO_DHCP_RELEASE:
2703 return "DHCP RELEASE";
2704 case QDF_PROTO_DHCP_INFORM:
2705 return "DHCP INFORM";
2706 case QDF_PROTO_DHCP_DECLINE:
2707 return "DHCP DECLINE";
2708 case QDF_PROTO_ARP_REQ:
2709 return "ARP REQUEST";
2710 case QDF_PROTO_ARP_RES:
2711 return "ARP RESPONSE";
2712 case QDF_PROTO_ICMP_REQ:
2713 return "ICMP REQUEST";
2714 case QDF_PROTO_ICMP_RES:
2715 return "ICMP RESPONSE";
2716 case QDF_PROTO_ICMPV6_REQ:
2717 return "ICMPV6 REQUEST";
2718 case QDF_PROTO_ICMPV6_RES:
2719 return "ICMPV6 RESPONSE";
2720 case QDF_PROTO_IPV4_UDP:
2721 return "IPV4 UDP Packet";
2722 case QDF_PROTO_IPV4_TCP:
2723 return "IPV4 TCP Packet";
2724 case QDF_PROTO_IPV6_UDP:
2725 return "IPV6 UDP Packet";
2726 case QDF_PROTO_IPV6_TCP:
2727 return "IPV6 TCP Packet";
2728 default:
2729 return "Invalid Packet";
2730 }
2731}
2732
2733/**
2734 * wma_wow_get_pkt_proto_subtype() - get the proto subtype
2735 * of the packet.
2736 * @data: Pointer to data buffer
2737 * @len: length of the data buffer
2738 *
2739 * This function gives the proto subtype of the packet.
2740 *
2741 * Return: proto subtype of the packet.
2742 */
2743static enum qdf_proto_subtype
2744wma_wow_get_pkt_proto_subtype(uint8_t *data,
2745 uint32_t len)
2746{
Himanshu Agarwalec51a5a2016-07-20 19:47:26 +05302747 uint16_t ether_type = (uint16_t)(*(uint16_t *)(data +
2748 QDF_NBUF_TRAC_ETH_TYPE_OFFSET));
2749
2750 WMA_LOGE("Ether Type: 0x%04x",
2751 ani_cpu_to_be16(ether_type));
2752
2753 if (QDF_NBUF_TRAC_EAPOL_ETH_TYPE ==
2754 ani_cpu_to_be16(ether_type)) {
2755 if (len >= WMA_EAPOL_SUBTYPE_GET_MIN_LEN)
2756 return qdf_nbuf_data_get_eapol_subtype(data);
2757 QDF_TRACE(QDF_MODULE_ID_WMA,
2758 QDF_TRACE_LEVEL_ERROR, "EAPOL Packet");
2759 return QDF_PROTO_INVALID;
2760 } else if (QDF_NBUF_TRAC_ARP_ETH_TYPE ==
2761 ani_cpu_to_be16(ether_type)) {
2762 if (len >= WMA_ARP_SUBTYPE_GET_MIN_LEN)
2763 return qdf_nbuf_data_get_arp_subtype(data);
2764 QDF_TRACE(QDF_MODULE_ID_WMA,
2765 QDF_TRACE_LEVEL_ERROR, "ARP Packet");
2766 return QDF_PROTO_INVALID;
2767 } else if (QDF_NBUF_TRAC_IPV4_ETH_TYPE ==
2768 ani_cpu_to_be16(ether_type)) {
2769 if (len >= WMA_IPV4_PROTO_GET_MIN_LEN) {
2770 uint8_t proto_type;
2771
2772 proto_type = qdf_nbuf_data_get_ipv4_proto(data);
2773 WMA_LOGE("IPV4_proto_type: %u", proto_type);
2774 if (proto_type == QDF_NBUF_TRAC_ICMP_TYPE) {
2775 if (len >= WMA_ICMP_SUBTYPE_GET_MIN_LEN)
2776 return qdf_nbuf_data_get_icmp_subtype(
2777 data);
2778 QDF_TRACE(QDF_MODULE_ID_WMA,
2779 QDF_TRACE_LEVEL_ERROR, "ICMP Packet");
2780 return QDF_PROTO_INVALID;
2781 } else if (proto_type == QDF_NBUF_TRAC_UDP_TYPE) {
2782 if (len >= WMA_IS_DHCP_GET_MIN_LEN) {
2783 if (qdf_nbuf_data_is_ipv4_dhcp_pkt(data)) {
2784 if (len >=
2785 WMA_DHCP_SUBTYPE_GET_MIN_LEN)
2786 return qdf_nbuf_data_get_dhcp_subtype(data);
2787 QDF_TRACE(QDF_MODULE_ID_WMA,
2788 QDF_TRACE_LEVEL_ERROR,
2789 "DHCP Packet");
2790 return QDF_PROTO_INVALID;
2791 }
2792 }
2793 return QDF_PROTO_IPV4_UDP;
2794 } else if (proto_type == QDF_NBUF_TRAC_TCP_TYPE) {
2795 return QDF_PROTO_IPV4_TCP;
2796 }
Himanshu Agarwal82de9042016-07-20 18:11:03 +05302797 }
Himanshu Agarwalec51a5a2016-07-20 19:47:26 +05302798 QDF_TRACE(QDF_MODULE_ID_WMA,
2799 QDF_TRACE_LEVEL_ERROR, "IPV4 Packet");
2800 return QDF_PROTO_INVALID;
2801 } else if (QDF_NBUF_TRAC_IPV6_ETH_TYPE ==
2802 ani_cpu_to_be16(ether_type)) {
2803 if (len >= WMA_IPV6_PROTO_GET_MIN_LEN) {
2804 uint8_t proto_type;
2805
2806 proto_type = qdf_nbuf_data_get_ipv6_proto(data);
2807 WMA_LOGE("IPV6_proto_type: %u", proto_type);
2808 if (proto_type == QDF_NBUF_TRAC_ICMPV6_TYPE) {
2809 if (len >= WMA_ICMPV6_SUBTYPE_GET_MIN_LEN)
2810 return qdf_nbuf_data_get_icmpv6_subtype(
2811 data);
2812 QDF_TRACE(QDF_MODULE_ID_WMA,
2813 QDF_TRACE_LEVEL_ERROR, "ICMPV6 Packet");
2814 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 Agarwalec51a5a2016-07-20 19:47:26 +05302821 QDF_TRACE(QDF_MODULE_ID_WMA,
2822 QDF_TRACE_LEVEL_ERROR, "IPV6 Packet");
2823 return QDF_PROTO_INVALID;
Himanshu Agarwal82de9042016-07-20 18:11:03 +05302824 }
2825
2826 return QDF_PROTO_INVALID;
2827}
2828
2829/**
2830 * wma_wow_parse_data_pkt_buffer() - API to parse data buffer for data
2831 * packet that resulted in WOW wakeup.
2832 * @data: Pointer to data buffer
2833 * @buf_len: data buffer length
2834 *
2835 * This function parses the data buffer received (first few bytes of
2836 * skb->data) to get informaton like src mac addr, dst mac addr, packet
2837 * len, seq_num, etc.
2838 *
2839 * Return: void
2840 */
2841static void wma_wow_parse_data_pkt_buffer(uint8_t *data,
2842 uint32_t buf_len)
2843{
2844 enum qdf_proto_subtype proto_subtype;
2845 uint16_t pkt_len, key_len, seq_num;
Himanshu Agarwalec51a5a2016-07-20 19:47:26 +05302846 uint16_t src_port, dst_port;
Himanshu Agarwal82de9042016-07-20 18:11:03 +05302847 uint32_t transaction_id, tcp_seq_num;
2848
Himanshu Agarwalf9515002016-07-20 19:09:10 +05302849 WMA_LOGD("wow_buf_pkt_len: %u", buf_len);
Himanshu Agarwalec51a5a2016-07-20 19:47:26 +05302850 if (buf_len >= QDF_NBUF_TRAC_IPV4_OFFSET)
Himanshu Agarwal82de9042016-07-20 18:11:03 +05302851 WMA_LOGE("Src_mac: " MAC_ADDRESS_STR " Dst_mac: " MAC_ADDRESS_STR,
Rakesh Sunki88d9c5a2016-08-25 12:48:12 -07002852 MAC_ADDR_ARRAY(data + QDF_NBUF_SRC_MAC_OFFSET),
2853 MAC_ADDR_ARRAY(data + QDF_NBUF_DEST_MAC_OFFSET));
Himanshu Agarwal82de9042016-07-20 18:11:03 +05302854 else
2855 goto end;
2856
2857 proto_subtype = wma_wow_get_pkt_proto_subtype(data, buf_len);
2858 switch (proto_subtype) {
2859 case QDF_PROTO_EAPOL_M1:
2860 case QDF_PROTO_EAPOL_M2:
2861 case QDF_PROTO_EAPOL_M3:
2862 case QDF_PROTO_EAPOL_M4:
2863 WMA_LOGE("WOW Wakeup: %s rcvd",
2864 wma_pkt_proto_subtype_to_string(proto_subtype));
2865 if (buf_len >= WMA_EAPOL_INFO_GET_MIN_LEN) {
2866 pkt_len = (uint16_t)(*(uint16_t *)(data +
2867 EAPOL_PKT_LEN_OFFSET));
2868 key_len = (uint16_t)(*(uint16_t *)(data +
2869 EAPOL_KEY_LEN_OFFSET));
Himanshu Agarwalf9515002016-07-20 19:09:10 +05302870 WMA_LOGE("Pkt_len: %u, Key_len: %u",
Himanshu Agarwal82de9042016-07-20 18:11:03 +05302871 ani_cpu_to_be16(pkt_len),
2872 ani_cpu_to_be16(key_len));
2873 }
2874 break;
2875
2876 case QDF_PROTO_DHCP_DISCOVER:
2877 case QDF_PROTO_DHCP_REQUEST:
2878 case QDF_PROTO_DHCP_OFFER:
2879 case QDF_PROTO_DHCP_ACK:
2880 case QDF_PROTO_DHCP_NACK:
2881 case QDF_PROTO_DHCP_RELEASE:
2882 case QDF_PROTO_DHCP_INFORM:
2883 case QDF_PROTO_DHCP_DECLINE:
2884 WMA_LOGE("WOW Wakeup: %s rcvd",
2885 wma_pkt_proto_subtype_to_string(proto_subtype));
2886 if (buf_len >= WMA_DHCP_INFO_GET_MIN_LEN) {
2887 pkt_len = (uint16_t)(*(uint16_t *)(data +
2888 DHCP_PKT_LEN_OFFSET));
2889 transaction_id = (uint32_t)(*(uint32_t *)(data +
2890 DHCP_TRANSACTION_ID_OFFSET));
Himanshu Agarwalf9515002016-07-20 19:09:10 +05302891 WMA_LOGE("Pkt_len: %u, Transaction_id: %u",
Himanshu Agarwal82de9042016-07-20 18:11:03 +05302892 ani_cpu_to_be16(pkt_len),
2893 ani_cpu_to_be16(transaction_id));
2894 }
2895 break;
2896
2897 case QDF_PROTO_ARP_REQ:
2898 case QDF_PROTO_ARP_RES:
2899 WMA_LOGE("WOW Wakeup: %s rcvd",
2900 wma_pkt_proto_subtype_to_string(proto_subtype));
2901 break;
2902
2903 case QDF_PROTO_ICMP_REQ:
2904 case QDF_PROTO_ICMP_RES:
2905 WMA_LOGE("WOW Wakeup: %s rcvd",
2906 wma_pkt_proto_subtype_to_string(proto_subtype));
2907 if (buf_len >= WMA_IPV4_PKT_INFO_GET_MIN_LEN) {
2908 pkt_len = (uint16_t)(*(uint16_t *)(data +
2909 IPV4_PKT_LEN_OFFSET));
2910 seq_num = (uint16_t)(*(uint16_t *)(data +
2911 ICMP_SEQ_NUM_OFFSET));
Himanshu Agarwalf9515002016-07-20 19:09:10 +05302912 WMA_LOGE("Pkt_len: %u, Seq_num: %u",
Himanshu Agarwal82de9042016-07-20 18:11:03 +05302913 ani_cpu_to_be16(pkt_len),
2914 ani_cpu_to_be16(seq_num));
2915 }
2916 break;
2917
2918 case QDF_PROTO_ICMPV6_REQ:
2919 case QDF_PROTO_ICMPV6_RES:
2920 WMA_LOGE("WOW Wakeup: %s rcvd",
2921 wma_pkt_proto_subtype_to_string(proto_subtype));
2922 if (buf_len >= WMA_IPV6_PKT_INFO_GET_MIN_LEN) {
2923 pkt_len = (uint16_t)(*(uint16_t *)(data +
2924 IPV6_PKT_LEN_OFFSET));
2925 seq_num = (uint16_t)(*(uint16_t *)(data +
2926 ICMPV6_SEQ_NUM_OFFSET));
Himanshu Agarwalf9515002016-07-20 19:09:10 +05302927 WMA_LOGE("Pkt_len: %u, Seq_num: %u",
Himanshu Agarwal82de9042016-07-20 18:11:03 +05302928 ani_cpu_to_be16(pkt_len),
2929 ani_cpu_to_be16(seq_num));
2930 }
2931 break;
2932
2933 case QDF_PROTO_IPV4_UDP:
2934 case QDF_PROTO_IPV4_TCP:
2935 WMA_LOGE("WOW Wakeup: %s rcvd",
2936 wma_pkt_proto_subtype_to_string(proto_subtype));
2937 if (buf_len >= WMA_IPV4_PKT_INFO_GET_MIN_LEN) {
2938 pkt_len = (uint16_t)(*(uint16_t *)(data +
2939 IPV4_PKT_LEN_OFFSET));
Himanshu Agarwalec51a5a2016-07-20 19:47:26 +05302940 src_port = (uint16_t)(*(uint16_t *)(data +
2941 IPV4_SRC_PORT_OFFSET));
2942 dst_port = (uint16_t)(*(uint16_t *)(data +
2943 IPV4_DST_PORT_OFFSET));
Himanshu Agarwalf9515002016-07-20 19:09:10 +05302944 WMA_LOGE("Pkt_len: %u",
Himanshu Agarwal82de9042016-07-20 18:11:03 +05302945 ani_cpu_to_be16(pkt_len));
Himanshu Agarwalec51a5a2016-07-20 19:47:26 +05302946 WMA_LOGE("src_port: %u, dst_port: %u",
2947 ani_cpu_to_be16(src_port),
2948 ani_cpu_to_be16(dst_port));
Himanshu Agarwal82de9042016-07-20 18:11:03 +05302949 if (proto_subtype == QDF_PROTO_IPV4_TCP) {
2950 tcp_seq_num = (uint32_t)(*(uint32_t *)(data +
2951 IPV4_TCP_SEQ_NUM_OFFSET));
Himanshu Agarwalf9515002016-07-20 19:09:10 +05302952 WMA_LOGE("TCP_seq_num: %u",
Himanshu Agarwal82de9042016-07-20 18:11:03 +05302953 ani_cpu_to_be16(tcp_seq_num));
2954 }
2955 }
2956 break;
2957
2958 case QDF_PROTO_IPV6_UDP:
2959 case QDF_PROTO_IPV6_TCP:
2960 WMA_LOGE("WOW Wakeup: %s rcvd",
2961 wma_pkt_proto_subtype_to_string(proto_subtype));
2962 if (buf_len >= WMA_IPV6_PKT_INFO_GET_MIN_LEN) {
2963 pkt_len = (uint16_t)(*(uint16_t *)(data +
2964 IPV6_PKT_LEN_OFFSET));
Himanshu Agarwalec51a5a2016-07-20 19:47:26 +05302965 src_port = (uint16_t)(*(uint16_t *)(data +
2966 IPV6_SRC_PORT_OFFSET));
2967 dst_port = (uint16_t)(*(uint16_t *)(data +
2968 IPV6_DST_PORT_OFFSET));
Himanshu Agarwalf9515002016-07-20 19:09:10 +05302969 WMA_LOGE("Pkt_len: %u",
Himanshu Agarwal82de9042016-07-20 18:11:03 +05302970 ani_cpu_to_be16(pkt_len));
Himanshu Agarwalec51a5a2016-07-20 19:47:26 +05302971 WMA_LOGE("src_port: %u, dst_port: %u",
2972 ani_cpu_to_be16(src_port),
2973 ani_cpu_to_be16(dst_port));
Himanshu Agarwal82de9042016-07-20 18:11:03 +05302974 if (proto_subtype == QDF_PROTO_IPV6_TCP) {
2975 tcp_seq_num = (uint32_t)(*(uint32_t *)(data +
2976 IPV6_TCP_SEQ_NUM_OFFSET));
Himanshu Agarwalf9515002016-07-20 19:09:10 +05302977 WMA_LOGE("TCP_seq_num: %u",
Himanshu Agarwal82de9042016-07-20 18:11:03 +05302978 ani_cpu_to_be16(tcp_seq_num));
2979 }
2980 }
2981 break;
2982
2983 default:
2984end:
Rajeev Kumar6f16cee2016-09-09 14:45:36 -07002985 WMA_LOGD("wow_buf_pkt_len: %u", buf_len);
Himanshu Agarwal82de9042016-07-20 18:11:03 +05302986 break;
2987 }
2988}
2989
2990/**
Himanshu Agarwaldd356df2016-07-20 19:04:39 +05302991 * wma_wow_dump_mgmt_buffer() - API to parse data buffer for mgmt.
2992 * packet that resulted in WOW wakeup.
2993 * @wow_packet_buffer: Pointer to data buffer
2994 * @buf_len: length of data buffer
2995 *
2996 * This function parses the data buffer received (802.11 header)
2997 * to get informaton like src mac addr, dst mac addr, seq_num,
2998 * frag_num, etc.
2999 *
3000 * Return: void
3001 */
3002static void wma_wow_dump_mgmt_buffer(uint8_t *wow_packet_buffer,
3003 uint32_t buf_len)
3004{
3005 struct ieee80211_frame_addr4 *wh;
3006
Himanshu Agarwalf9515002016-07-20 19:09:10 +05303007 WMA_LOGD("wow_buf_pkt_len: %u", buf_len);
Himanshu Agarwaldd356df2016-07-20 19:04:39 +05303008 wh = (struct ieee80211_frame_addr4 *)
3009 (wow_packet_buffer + 4);
3010 if (buf_len >= sizeof(struct ieee80211_frame)) {
3011 uint8_t to_from_ds, frag_num;
3012 uint32_t seq_num;
3013
3014 WMA_LOGE("RA: " MAC_ADDRESS_STR " TA: " MAC_ADDRESS_STR,
3015 MAC_ADDR_ARRAY(wh->i_addr1),
3016 MAC_ADDR_ARRAY(wh->i_addr2));
3017
Himanshu Agarwalf9515002016-07-20 19:09:10 +05303018 WMA_LOGE("TO_DS: %u, FROM_DS: %u",
Himanshu Agarwaldd356df2016-07-20 19:04:39 +05303019 wh->i_fc[1] & IEEE80211_FC1_DIR_TODS,
3020 wh->i_fc[1] & IEEE80211_FC1_DIR_FROMDS);
3021
3022 to_from_ds = wh->i_fc[1] & IEEE80211_FC1_DIR_DSTODS;
3023
3024 switch (to_from_ds) {
3025 case IEEE80211_NO_DS:
3026 WMA_LOGE("BSSID: " MAC_ADDRESS_STR,
3027 MAC_ADDR_ARRAY(wh->i_addr3));
3028 break;
3029 case IEEE80211_TO_DS:
3030 WMA_LOGE("DA: " MAC_ADDRESS_STR,
3031 MAC_ADDR_ARRAY(wh->i_addr3));
3032 break;
3033 case IEEE80211_FROM_DS:
3034 WMA_LOGE("SA: " MAC_ADDRESS_STR,
3035 MAC_ADDR_ARRAY(wh->i_addr3));
3036 break;
3037 case IEEE80211_DS_TO_DS:
3038 if (buf_len >= sizeof(struct ieee80211_frame_addr4))
3039 WMA_LOGE("DA: " MAC_ADDRESS_STR " SA: "
3040 MAC_ADDRESS_STR,
3041 MAC_ADDR_ARRAY(wh->i_addr3),
3042 MAC_ADDR_ARRAY(wh->i_addr4));
3043 break;
3044 }
3045
3046 seq_num = (((*(uint16_t *)wh->i_seq) &
3047 IEEE80211_SEQ_SEQ_MASK) >>
3048 IEEE80211_SEQ_SEQ_SHIFT);
3049 frag_num = (((*(uint16_t *)wh->i_seq) &
3050 IEEE80211_SEQ_FRAG_MASK) >>
3051 IEEE80211_SEQ_FRAG_SHIFT);
3052
Himanshu Agarwalf9515002016-07-20 19:09:10 +05303053 WMA_LOGE("SEQ_NUM: %u, FRAG_NUM: %u",
Himanshu Agarwaldd356df2016-07-20 19:04:39 +05303054 seq_num, frag_num);
3055 } else {
3056 WMA_LOGE("Insufficient buffer length for mgmt. packet");
3057 }
3058}
3059
3060/**
3061 * wma_wow_get_wakelock_duration() - return the wakelock duration
3062 * for some mgmt packets received.
3063 * @wake_reason: wow wakeup reason
3064 *
3065 * This function returns the wakelock duration for some mgmt packets
3066 * received while in wow suspend.
3067 *
3068 * Return: wakelock duration
3069 */
3070static uint32_t wma_wow_get_wakelock_duration(int wake_reason)
3071{
3072 uint32_t wake_lock_duration = 0;
3073
3074 switch (wake_reason) {
3075 case WOW_REASON_AUTH_REQ_RECV:
3076 wake_lock_duration = WMA_AUTH_REQ_RECV_WAKE_LOCK_TIMEOUT;
3077 break;
3078 case WOW_REASON_ASSOC_REQ_RECV:
3079 wake_lock_duration = WMA_ASSOC_REQ_RECV_WAKE_LOCK_DURATION;
3080 break;
3081 case WOW_REASON_DEAUTH_RECVD:
3082 wake_lock_duration = WMA_DEAUTH_RECV_WAKE_LOCK_DURATION;
3083 break;
3084 case WOW_REASON_DISASSOC_RECVD:
3085 wake_lock_duration = WMA_DISASSOC_RECV_WAKE_LOCK_DURATION;
3086 break;
3087 default:
3088 break;
3089 }
3090
3091 return wake_lock_duration;
3092}
3093
3094/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003095 * wma_wow_wakeup_host_event() - wakeup host event handler
3096 * @handle: wma handle
3097 * @event: event data
3098 * @len: buffer length
3099 *
3100 * Handler to catch wow wakeup host event. This event will have
3101 * reason why the firmware has woken the host.
3102 *
3103 * Return: 0 for success or error
3104 */
3105int wma_wow_wakeup_host_event(void *handle, uint8_t *event,
3106 uint32_t len)
3107{
3108 tp_wma_handle wma = (tp_wma_handle) handle;
3109 WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *param_buf;
3110 WOW_EVENT_INFO_fixed_param *wake_info;
3111#ifdef FEATURE_WLAN_SCAN_PNO
3112 struct wma_txrx_node *node;
3113#endif /* FEATURE_WLAN_SCAN_PNO */
3114 uint32_t wake_lock_duration = 0;
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07003115 void *wmi_cmd_struct_ptr = NULL;
3116 uint32_t tlv_hdr, tag, wow_buf_pkt_len = 0, event_id = 0;
3117 int tlv_ok_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003118
3119 param_buf = (WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *) event;
3120 if (!param_buf) {
3121 WMA_LOGE("Invalid wow wakeup host event buf");
3122 return -EINVAL;
3123 }
3124
3125 wake_info = param_buf->fixed_param;
3126
Srinivas Girigowdae1e69132016-08-23 06:51:58 +05303127 if ((wake_info->wake_reason != WOW_REASON_UNSPECIFIED) ||
3128 (wake_info->wake_reason == WOW_REASON_UNSPECIFIED &&
Nitesh Shahd732f742016-08-23 08:07:09 +05303129 !wmi_get_runtime_pm_inprogress(wma->wmi_handle))) {
Srinivas Girigowdae1e69132016-08-23 06:51:58 +05303130 WMA_LOGA("WOW wakeup host event received (reason: %s(%d)) for vdev %d",
3131 wma_wow_wake_reason_str(wake_info->wake_reason),
3132 wake_info->wake_reason, wake_info->vdev_id);
Nitesh Shahd732f742016-08-23 08:07:09 +05303133 qdf_wow_wakeup_host_event(wake_info->wake_reason);
3134 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003135
Anurag Chouhance0dc992016-02-16 18:18:03 +05303136 qdf_event_set(&wma->wma_resume_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003137
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07003138 if (param_buf->wow_packet_buffer &&
3139 tlv_check_required(wake_info->wake_reason)) {
3140 /*
3141 * In case of wow_packet_buffer, first 4 bytes is the length.
3142 * Following the length is the actual buffer.
3143 */
3144 wow_buf_pkt_len = *(uint32_t *)param_buf->wow_packet_buffer;
3145 tlv_hdr = WMITLV_GET_HDR(
3146 (uint8_t *)param_buf->wow_packet_buffer + 4);
3147
3148 tag = WMITLV_GET_TLVTAG(tlv_hdr);
3149 event_id = wow_get_wmi_eventid(wake_info->wake_reason, tag);
3150 if (!event_id) {
3151 WMA_LOGE(FL("Unable to find matching ID"));
3152 return -EINVAL;
3153 }
3154
3155 tlv_ok_status = wmitlv_check_and_pad_event_tlvs(
3156 handle, param_buf->wow_packet_buffer + 4,
3157 wow_buf_pkt_len, event_id,
3158 &wmi_cmd_struct_ptr);
3159
3160 if (tlv_ok_status != 0) {
3161 WMA_LOGE(FL("Invalid TLVs, Length:%d event_id:%d status: %d"),
3162 wow_buf_pkt_len, event_id, tlv_ok_status);
3163 return -EINVAL;
3164 }
3165 }
3166
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003167 switch (wake_info->wake_reason) {
3168 case WOW_REASON_AUTH_REQ_RECV:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003169 case WOW_REASON_ASSOC_REQ_RECV:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003170 case WOW_REASON_DEAUTH_RECVD:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003171 case WOW_REASON_DISASSOC_RECVD:
Himanshu Agarwaldd356df2016-07-20 19:04:39 +05303172 case WOW_REASON_ASSOC_RES_RECV:
3173 case WOW_REASON_REASSOC_REQ_RECV:
3174 case WOW_REASON_REASSOC_RES_RECV:
3175 case WOW_REASON_BEACON_RECV:
3176 case WOW_REASON_ACTION_FRAME_RECV:
3177 wake_lock_duration =
3178 wma_wow_get_wakelock_duration(wake_info->wake_reason);
3179 if (param_buf->wow_packet_buffer) {
3180 /* First 4-bytes of wow_packet_buffer is the length */
3181 qdf_mem_copy((uint8_t *) &wow_buf_pkt_len,
3182 param_buf->wow_packet_buffer, 4);
3183 if (wow_buf_pkt_len)
3184 wma_wow_dump_mgmt_buffer(
3185 param_buf->wow_packet_buffer,
3186 wow_buf_pkt_len);
3187 else
3188 WMA_LOGE("wow packet buffer is empty");
3189 } else {
3190 WMA_LOGE("No wow packet buffer present");
3191 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003192 break;
3193
3194 case WOW_REASON_AP_ASSOC_LOST:
3195 wake_lock_duration = WMA_BMISS_EVENT_WAKE_LOCK_DURATION;
3196 WMA_LOGA("Beacon miss indication on vdev %x",
3197 wake_info->vdev_id);
3198 wma_beacon_miss_handler(wma, wake_info->vdev_id);
3199 break;
3200#ifdef FEATURE_WLAN_RA_FILTERING
3201 case WOW_REASON_RA_MATCH:
3202 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_RA_MATCH);
3203 break;
3204#endif /* FEATURE_WLAN_RA_FILTERING */
3205#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
3206 case WOW_REASON_HOST_AUTO_SHUTDOWN:
3207 wake_lock_duration = WMA_AUTO_SHUTDOWN_WAKE_LOCK_DURATION;
3208 WMA_LOGA("Received WOW Auto Shutdown trigger in suspend");
3209 if (wma_post_auto_shutdown_msg())
3210 return -EINVAL;
3211 break;
3212#endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
3213#ifdef FEATURE_WLAN_SCAN_PNO
3214 case WOW_REASON_NLOD:
3215 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_NLOD);
3216 node = &wma->interfaces[wake_info->vdev_id];
3217 if (node) {
3218 WMA_LOGD("NLO match happened");
3219 node->nlo_match_evt_received = true;
Anurag Chouhan01cfa4e2016-09-04 15:10:49 +05303220 cds_host_diag_log_work(&wma->pno_wake_lock,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003221 WMA_PNO_MATCH_WAKE_LOCK_TIMEOUT,
3222 WIFI_POWER_EVENT_WAKELOCK_PNO);
Anurag Chouhan01cfa4e2016-09-04 15:10:49 +05303223 qdf_wake_lock_timeout_acquire(&wma->pno_wake_lock,
3224 WMA_PNO_MATCH_WAKE_LOCK_TIMEOUT);
Srinivas Girigowdae80cea92015-11-23 11:33:57 -08003225 }
3226 break;
3227
3228 case WOW_REASON_NLO_SCAN_COMPLETE:
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07003229 WMA_LOGD("Host woken up due to pno scan complete reason");
3230 if (param_buf->wow_packet_buffer)
3231 wma_nlo_scan_cmp_evt_handler(handle,
3232 wmi_cmd_struct_ptr, wow_buf_pkt_len);
3233 else
3234 WMA_LOGD("No wow_packet_buffer present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003235 break;
3236#endif /* FEATURE_WLAN_SCAN_PNO */
3237
3238 case WOW_REASON_CSA_EVENT:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003239 WMA_LOGD("Host woken up because of CSA IE");
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07003240 wma_csa_offload_handler(handle, wmi_cmd_struct_ptr,
3241 wow_buf_pkt_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003242 break;
3243
3244#ifdef FEATURE_WLAN_LPHB
3245 case WOW_REASON_WLAN_HB:
3246 wma_lphb_handler(wma, (uint8_t *) param_buf->hb_indevt);
3247 break;
3248#endif /* FEATURE_WLAN_LPHB */
3249
3250 case WOW_REASON_HTT_EVENT:
3251 break;
Dustin Brown75d02342016-08-29 11:23:47 -07003252
3253 case WOW_REASON_BPF_ALLOW:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003254 case WOW_REASON_PATTERN_MATCH_FOUND:
3255 wma_wow_wake_up_stats_display(wma);
3256 WMA_LOGD("Wake up for Rx packet, dump starting from ethernet hdr");
3257 if (param_buf->wow_packet_buffer) {
3258 /* First 4-bytes of wow_packet_buffer is the length */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303259 qdf_mem_copy((uint8_t *) &wow_buf_pkt_len,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003260 param_buf->wow_packet_buffer, 4);
Himanshu Agarwal82de9042016-07-20 18:11:03 +05303261 if (wow_buf_pkt_len) {
3262 uint8_t *data;
3263
3264 wma_wow_wake_up_stats(wma,
3265 param_buf->wow_packet_buffer + 4,
3266 wow_buf_pkt_len,
3267 WOW_REASON_PATTERN_MATCH_FOUND);
3268 qdf_trace_hex_dump(QDF_MODULE_ID_WMA,
3269 QDF_TRACE_LEVEL_DEBUG,
3270 param_buf->wow_packet_buffer + 4,
3271 wow_buf_pkt_len);
3272
3273 data = (uint8_t *)
3274 (param_buf->wow_packet_buffer + 4);
3275 wma_wow_parse_data_pkt_buffer(data,
3276 wow_buf_pkt_len);
3277 } else {
3278 WMA_LOGE("wow packet buffer is empty");
3279 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003280 } else {
3281 WMA_LOGE("No wow packet buffer present");
3282 }
3283 break;
3284
3285 case WOW_REASON_LOW_RSSI:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003286 /* WOW_REASON_LOW_RSSI is used for all roaming events.
3287 * WMI_ROAM_REASON_BETTER_AP, WMI_ROAM_REASON_BMISS,
3288 * WMI_ROAM_REASON_SUITABLE_AP will be handled by
3289 * wma_roam_event_callback().
3290 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003291 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_LOW_RSSI);
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07003292 WMA_LOGD("Host woken up because of roam event");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003293 if (param_buf->wow_packet_buffer) {
3294 /* Roam event is embedded in wow_packet_buffer */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003295 WMA_LOGD("wow_packet_buffer dump");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303296 qdf_trace_hex_dump(QDF_MODULE_ID_WMA,
3297 QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003298 param_buf->wow_packet_buffer,
3299 wow_buf_pkt_len);
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07003300 wma_roam_event_callback(handle, wmi_cmd_struct_ptr,
3301 wow_buf_pkt_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003302 } else {
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07003303 /*
3304 * No wow_packet_buffer means a better AP beacon
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003305 * will follow in a later event.
3306 */
3307 WMA_LOGD("Host woken up because of better AP beacon");
3308 }
3309 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003310 case WOW_REASON_CLIENT_KICKOUT_EVENT:
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07003311 WMA_LOGD("Host woken up because of sta_kickout event");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003312 if (param_buf->wow_packet_buffer) {
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07003313 WMA_LOGD("wow_packet_buffer dump");
3314 qdf_trace_hex_dump(QDF_MODULE_ID_WMA,
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303315 QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003316 param_buf->wow_packet_buffer, wow_buf_pkt_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003317 wma_peer_sta_kickout_event_handler(handle,
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07003318 wmi_cmd_struct_ptr, wow_buf_pkt_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003319 } else {
3320 WMA_LOGD("No wow_packet_buffer present");
3321 }
3322 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003323#ifdef FEATURE_WLAN_EXTSCAN
3324 case WOW_REASON_EXTSCAN:
3325 WMA_LOGD("Host woken up because of extscan reason");
3326 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_EXTSCAN);
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07003327 if (param_buf->wow_packet_buffer)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003328 wma_extscan_wow_event_callback(handle,
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07003329 wmi_cmd_struct_ptr, wow_buf_pkt_len);
3330 else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003331 WMA_LOGE("wow_packet_buffer is empty");
3332 break;
3333#endif
3334 case WOW_REASON_RSSI_BREACH_EVENT:
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07003335 wma_wow_wake_up_stats(wma, NULL, 0,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003336 WOW_REASON_RSSI_BREACH_EVENT);
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07003337 WMA_LOGD("Host woken up because of rssi breach reason");
3338 /* rssi breach event is embedded in wow_packet_buffer */
3339 if (param_buf->wow_packet_buffer)
3340 wma_rssi_breached_event_handler(handle,
3341 wmi_cmd_struct_ptr, wow_buf_pkt_len);
3342 else
3343 WMA_LOGD("No wow_packet_buffer present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003344 break;
Naveen Rawatc9f09522016-05-12 14:02:42 -07003345 case WOW_REASON_NAN_EVENT:
3346 WMA_LOGA("Host woken up due to NAN event reason");
3347 wma_nan_rsp_event_handler(handle,
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07003348 wmi_cmd_struct_ptr, wow_buf_pkt_len);
Naveen Rawatc9f09522016-05-12 14:02:42 -07003349 break;
Naveen Rawate82c1f32016-06-22 15:34:36 -07003350 case WOW_REASON_NAN_DATA:
3351 WMA_LOGD(FL("Host woken up for NAN data path event from FW"));
3352 if (param_buf->wow_packet_buffer) {
Naveen Rawat17dccbe2016-08-23 17:09:04 -07003353 wma_ndp_wow_event_callback(handle, wmi_cmd_struct_ptr,
3354 wow_buf_pkt_len, event_id);
Naveen Rawate82c1f32016-06-22 15:34:36 -07003355 } else {
3356 WMA_LOGE(FL("wow_packet_buffer is empty"));
3357 }
3358 break;
Selvaraj, Sridhar172cabc2016-07-05 15:19:24 +05303359 case WOW_REASON_OEM_RESPONSE_EVENT:
3360 wma_wow_wake_up_stats(wma, NULL, 0,
3361 WOW_REASON_OEM_RESPONSE_EVENT);
3362 /*
3363 * Actual OEM Response event will follow after this
3364 * WOW Wakeup event
3365 */
3366 WMA_LOGD(FL("Host woken up for OEM Response event"));
3367 break;
Selvaraj, Sridhar251761a2016-06-25 16:05:15 +05303368#ifdef FEATURE_WLAN_TDLS
3369 case WOW_REASON_TDLS_CONN_TRACKER_EVENT:
3370 WMA_LOGD("Host woken up because of TDLS event");
3371 if (param_buf->wow_packet_buffer)
3372 wma_tdls_event_handler(handle,
3373 wmi_cmd_struct_ptr, wow_buf_pkt_len);
3374 else
3375 WMA_LOGD("No wow_packet_buffer present");
3376 break;
3377#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003378 default:
3379 break;
3380 }
3381
3382 if (wake_lock_duration) {
Anurag Chouhan01cfa4e2016-09-04 15:10:49 +05303383 cds_host_diag_log_work(&wma->wow_wake_lock,
3384 wake_lock_duration,
3385 WIFI_POWER_EVENT_WAKELOCK_WOW);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303386 qdf_wake_lock_timeout_acquire(&wma->wow_wake_lock,
Anurag Chouhan01cfa4e2016-09-04 15:10:49 +05303387 wake_lock_duration);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003388 WMA_LOGA("Holding %d msec wake_lock", wake_lock_duration);
3389 }
3390
Rajeev Kumar2c892fe2016-08-24 16:17:16 -07003391 if (wmi_cmd_struct_ptr)
3392 wmitlv_free_allocated_event_tlvs(event_id, &wmi_cmd_struct_ptr);
3393
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003394 return 0;
3395}
3396
3397/**
3398 * wma_pdev_resume_event_handler() - PDEV resume event handler
3399 * @handle: wma handle
3400 * @event: event data
3401 * @len: buffer length
3402 *
3403 * Return: 0 for success or error
3404 */
3405int wma_pdev_resume_event_handler(void *handle, uint8_t *event, uint32_t len)
3406{
3407 tp_wma_handle wma = (tp_wma_handle) handle;
3408
3409 WMA_LOGA("Received PDEV resume event");
3410
Anurag Chouhance0dc992016-02-16 18:18:03 +05303411 qdf_event_set(&wma->wma_resume_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003412
3413 return 0;
3414}
3415/**
3416 * wma_set_wow_bus_suspend() - set suspend flag
3417 * @wma: wma handle
3418 * @val: value
3419 *
3420 * Return: none
3421 */
3422static inline void wma_set_wow_bus_suspend(tp_wma_handle wma, int val)
3423{
3424
Anurag Chouhan8e0ccd32016-02-19 15:30:20 +05303425 qdf_atomic_set(&wma->is_wow_bus_suspended, val);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003426}
3427
3428
3429
3430/**
3431 * wma_add_wow_wakeup_event() - Configures wow wakeup events.
3432 * @wma: wma handle
3433 * @vdev_id: vdev id
3434 * @bitmap: Event bitmap
3435 * @enable: enable/disable
3436 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303437 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003438 */
Naveen Rawate82c1f32016-06-22 15:34:36 -07003439QDF_STATUS wma_add_wow_wakeup_event(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003440 uint32_t vdev_id,
3441 uint32_t bitmap,
3442 bool enable)
3443{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003444 int ret;
3445
Govind Singhaa64c242016-03-08 11:31:49 +05303446 ret = wmi_unified_add_wow_wakeup_event_cmd(wma->wmi_handle, vdev_id,
Rajeev Kumar4002e5b2016-06-22 12:01:15 -07003447 bitmap, enable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003448 if (ret) {
3449 WMA_LOGE("Failed to config wow wakeup event");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303450 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003451 }
3452
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303453 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003454}
3455
3456/**
3457 * wma_send_wow_patterns_to_fw() - Sends WOW patterns to FW.
3458 * @wma: wma handle
3459 * @vdev_id: vdev id
3460 * @ptrn_id: pattern id
3461 * @ptrn: pattern
3462 * @ptrn_len: pattern length
3463 * @ptrn_offset: pattern offset
3464 * @mask: mask
3465 * @mask_len: mask length
3466 * @user: true for user configured pattern and false for default pattern
3467 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303468 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003469 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303470static QDF_STATUS wma_send_wow_patterns_to_fw(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003471 uint8_t vdev_id, uint8_t ptrn_id,
3472 const uint8_t *ptrn, uint8_t ptrn_len,
3473 uint8_t ptrn_offset, const uint8_t *mask,
3474 uint8_t mask_len, bool user)
3475{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003476 struct wma_txrx_node *iface;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003477 int ret;
3478
3479 iface = &wma->interfaces[vdev_id];
Govind Singhaa64c242016-03-08 11:31:49 +05303480 ret = wmi_unified_wow_patterns_to_fw_cmd(wma->wmi_handle,
3481 vdev_id, ptrn_id, ptrn,
3482 ptrn_len, ptrn_offset, mask,
Rajeev Kumar25a0b212016-09-16 13:29:43 -07003483 mask_len, user, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003484 if (ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003485 if (!user)
3486 iface->num_wow_default_patterns--;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303487 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003488 }
3489
3490 if (user)
3491 iface->num_wow_user_patterns++;
3492
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303493 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003494}
3495
3496/**
3497 * wma_wow_ap() - set WOW patterns in ap mode
3498 * @wma: wma handle
3499 * @vdev_id: vdev id
3500 *
3501 * Configures default WOW pattern for the given vdev_id which is in AP mode.
3502 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303503 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003504 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303505static QDF_STATUS wma_wow_ap(tp_wma_handle wma, uint8_t vdev_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003506{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303507 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003508 uint8_t arp_offset = 20;
3509 uint8_t mac_mask[IEEE80211_ADDR_LEN];
Rajeev Kumar25a0b212016-09-16 13:29:43 -07003510 struct wma_txrx_node *iface = &wma->interfaces[vdev_id];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003511
Rajeev Kumar25a0b212016-09-16 13:29:43 -07003512 /*
3513 * Setup unicast pkt pattern
3514 * WoW pattern id should be unique for each vdev
3515 * WoW pattern id can be same on 2 different VDEVs
3516 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303517 qdf_mem_set(&mac_mask, IEEE80211_ADDR_LEN, 0xFF);
Rajeev Kumar25a0b212016-09-16 13:29:43 -07003518 ret = wma_send_wow_patterns_to_fw(wma, vdev_id,
3519 iface->num_wow_default_patterns++,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003520 wma->interfaces[vdev_id].addr,
3521 IEEE80211_ADDR_LEN, 0, mac_mask,
3522 IEEE80211_ADDR_LEN, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303523 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003524 WMA_LOGE("Failed to add WOW unicast pattern ret %d", ret);
3525 return ret;
3526 }
3527
3528 /*
3529 * Setup all ARP pkt pattern. This is dummy pattern hence the length
Rajeev Kumar25a0b212016-09-16 13:29:43 -07003530 * is zero. Pattern ID should be unique per vdev.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003531 */
Rajeev Kumar25a0b212016-09-16 13:29:43 -07003532 ret = wma_send_wow_patterns_to_fw(wma, vdev_id,
3533 iface->num_wow_default_patterns++,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003534 arp_ptrn, 0, arp_offset, arp_mask, 0, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303535 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003536 WMA_LOGE("Failed to add WOW ARP pattern ret %d", ret);
3537 return ret;
3538 }
3539
3540 return ret;
3541}
3542
3543/**
Komal Seelam9764a842016-05-24 11:07:23 +05303544 * wma_configure_wow_ssdp() - API to configure WoW SSDP
3545 * @wma: WMA Handle
3546 * @vdev_id: Vdev Id
3547 *
3548 * API to configure SSDP pattern as WoW pattern
3549 *
3550 * Return: Success/Failure
3551 */
3552static QDF_STATUS wma_configure_wow_ssdp(tp_wma_handle wma, uint8_t vdev_id)
3553{
3554 QDF_STATUS status = QDF_STATUS_SUCCESS;
3555 uint8_t discvr_offset = 30;
Rajeev Kumar25a0b212016-09-16 13:29:43 -07003556 struct wma_txrx_node *iface = &wma->interfaces[vdev_id];
Komal Seelam9764a842016-05-24 11:07:23 +05303557
Rajeev Kumar25a0b212016-09-16 13:29:43 -07003558 /*
3559 * WoW pattern ID should be unique for each vdev
3560 * Different WoW patterns can use same pattern ID
3561 */
3562 status = wma_send_wow_patterns_to_fw(wma, vdev_id,
3563 iface->num_wow_default_patterns++,
Komal Seelam9764a842016-05-24 11:07:23 +05303564 discvr_ptrn, sizeof(discvr_ptrn), discvr_offset,
3565 discvr_mask, sizeof(discvr_ptrn), false);
3566
3567 if (status != QDF_STATUS_SUCCESS)
3568 WMA_LOGE("Failed to add WOW mDNS/SSDP/LLMNR pattern");
3569
3570 return status;
3571}
3572
3573/**
3574 * wma_configure_mc_ssdp() - API to configure SSDP address as MC list
3575 * @wma: WMA Handle
3576 * @vdev_id: Vdev Id
3577 *
3578 * SSDP address 239.255.255.250 is converted to Multicast Mac address
3579 * and configure it to FW. Firmware will apply this pattern on the incoming
3580 * packets to filter them out during chatter/wow mode.
3581 *
3582 * Return: Success/Failure
3583 */
3584static QDF_STATUS wma_configure_mc_ssdp(tp_wma_handle wma, uint8_t vdev_id)
3585{
3586 WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param *cmd;
3587 wmi_buf_t buf;
3588 const tSirMacAddr ssdp_addr = {0x01, 0x00, 0x5e, 0x7f, 0xff, 0xfa};
3589 int ret;
3590 WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param fixed_param;
3591 uint32_t tag =
3592 WMITLV_TAG_STRUC_WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param;
3593
3594 buf = wmi_buf_alloc(wma->wmi_handle, sizeof(*cmd));
3595 if (!buf) {
3596 WMA_LOGE("%s No Memory for MC address", __func__);
3597 return QDF_STATUS_E_NOMEM;
3598 }
3599
3600 cmd = (WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param *) wmi_buf_data(buf);
3601
3602 WMITLV_SET_HDR(&cmd->tlv_header, tag,
3603 WMITLV_GET_STRUCT_TLVLEN(fixed_param));
3604
3605 cmd->action = WMI_MCAST_FILTER_SET;
3606 cmd->vdev_id = vdev_id;
3607 WMI_CHAR_ARRAY_TO_MAC_ADDR(ssdp_addr, &cmd->mcastbdcastaddr);
3608 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, sizeof(*cmd),
3609 WMI_SET_MCASTBCAST_FILTER_CMDID);
3610 if (ret != QDF_STATUS_SUCCESS) {
3611 WMA_LOGE("%s Failed to configure FW with SSDP MC address",
3612 __func__);
3613 wmi_buf_free(buf);
3614 return QDF_STATUS_E_FAILURE;
3615 }
3616
3617 return QDF_STATUS_SUCCESS;
3618}
3619
3620/**
3621 * wma_configure_ssdp() - API to Configure SSDP pattern to FW
3622 * @wma: WMA Handle
3623 * @vdev_id: VDEV ID
3624 *
3625 * Setup multicast pattern for mDNS 224.0.0.251, SSDP 239.255.255.250 and LLMNR
3626 * 224.0.0.252
3627 *
3628 * Return: Success/Failure.
3629 */
3630static QDF_STATUS wma_configure_ssdp(tp_wma_handle wma, uint8_t vdev_id)
3631{
3632 if (!wma->ssdp) {
3633 WMA_LOGD("mDNS, SSDP, LLMNR patterns are disabled from ini");
3634 return QDF_STATUS_SUCCESS;
3635 }
3636
3637 WMA_LOGD("%s, enable_mc_list:%d", __func__, wma->enable_mc_list);
3638
3639 if (wma->enable_mc_list)
3640 return wma_configure_mc_ssdp(wma, vdev_id);
3641
3642 return wma_configure_wow_ssdp(wma, vdev_id);
3643}
3644
3645/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003646 * wma_wow_sta() - set WOW patterns in sta mode
3647 * @wma: wma handle
3648 * @vdev_id: vdev id
3649 *
3650 * Configures default WOW pattern for the given vdev_id which is in sta mode.
3651 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303652 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003653 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303654static QDF_STATUS wma_wow_sta(tp_wma_handle wma, uint8_t vdev_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003655{
3656 uint8_t arp_offset = 12;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003657 uint8_t mac_mask[IEEE80211_ADDR_LEN];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303658 QDF_STATUS ret = QDF_STATUS_SUCCESS;
Rajeev Kumar25a0b212016-09-16 13:29:43 -07003659 struct wma_txrx_node *iface = &wma->interfaces[vdev_id];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003660
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303661 qdf_mem_set(&mac_mask, IEEE80211_ADDR_LEN, 0xFF);
Rajeev Kumar25a0b212016-09-16 13:29:43 -07003662 /*
3663 * Set up unicast wow pattern
3664 * WoW pattern ID should be unique for each vdev
3665 * Different WoW patterns can use same pattern ID
3666 */
3667 ret = wma_send_wow_patterns_to_fw(wma, vdev_id,
3668 iface->num_wow_default_patterns++,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003669 wma->interfaces[vdev_id].addr,
3670 IEEE80211_ADDR_LEN, 0, mac_mask,
3671 IEEE80211_ADDR_LEN, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303672 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003673 WMA_LOGE("Failed to add WOW unicast pattern ret %d", ret);
3674 return ret;
3675 }
3676
Komal Seelam9764a842016-05-24 11:07:23 +05303677 ret = wma_configure_ssdp(wma, vdev_id);
3678 if (ret != QDF_STATUS_SUCCESS)
3679 WMA_LOGE("Failed to configure SSDP patterns to FW");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003680
3681 /* when arp offload or ns offloaded is disabled
3682 * from ini file, configure broad cast arp pattern
3683 * to fw, so that host can wake up
3684 */
3685 if (!(wma->ol_ini_info & 0x1)) {
3686 /* Setup all ARP pkt pattern */
Rajeev Kumar25a0b212016-09-16 13:29:43 -07003687 WMA_LOGI("ARP offload is disabled in INI enable WoW for ARP");
3688 ret = wma_send_wow_patterns_to_fw(wma, vdev_id,
3689 iface->num_wow_default_patterns++,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003690 arp_ptrn, sizeof(arp_ptrn), arp_offset,
3691 arp_mask, sizeof(arp_mask), false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303692 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003693 WMA_LOGE("Failed to add WOW ARP pattern");
3694 return ret;
3695 }
3696 }
3697
3698 /* for NS or NDP offload packets */
3699 if (!(wma->ol_ini_info & 0x2)) {
3700 /* Setup all NS pkt pattern */
Rajeev Kumar25a0b212016-09-16 13:29:43 -07003701 WMA_LOGI("NS offload is disabled in INI enable WoW for NS");
3702 ret = wma_send_wow_patterns_to_fw(wma, vdev_id,
3703 iface->num_wow_default_patterns++,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003704 ns_ptrn, sizeof(arp_ptrn), arp_offset,
3705 arp_mask, sizeof(arp_mask), false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303706 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003707 WMA_LOGE("Failed to add WOW NS pattern");
3708 return ret;
3709 }
3710 }
3711
3712 return ret;
3713}
3714
3715/**
3716 * wma_register_wow_default_patterns() - register default wow patterns with fw
3717 * @handle: Pointer to wma handle
3718 * @vdev_id: vdev id
3719 *
3720 * WoW default wake up pattern rule is:
3721 * - For STA & P2P CLI mode register for same STA specific wow patterns
3722 * - For SAP/P2P GO & IBSS mode register for same SAP specific wow patterns
3723 *
3724 * Return: none
3725 */
3726void wma_register_wow_default_patterns(WMA_HANDLE handle, uint8_t vdev_id)
3727{
3728 tp_wma_handle wma = handle;
3729 struct wma_txrx_node *iface;
3730
3731 if (vdev_id > wma->max_bssid) {
3732 WMA_LOGE("Invalid vdev id %d", vdev_id);
3733 return;
3734 }
3735 iface = &wma->interfaces[vdev_id];
3736
3737 if (iface->ptrn_match_enable) {
Houston Hoffman79b4af22015-10-06 12:01:08 -07003738 if (wma_is_vdev_in_beaconning_mode(wma, vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003739 /* Configure SAP/GO/IBSS mode default wow patterns */
3740 WMA_LOGI("Config SAP specific default wow patterns vdev_id %d",
3741 vdev_id);
3742 wma_wow_ap(wma, vdev_id);
3743 } else {
3744 /* Configure STA/P2P CLI mode default wow patterns */
3745 WMA_LOGI("Config STA specific default wow patterns vdev_id %d",
3746 vdev_id);
3747 wma_wow_sta(wma, vdev_id);
3748 if (wma->IsRArateLimitEnabled) {
3749 WMA_LOGI("Config STA RA limit wow patterns vdev_id %d",
3750 vdev_id);
3751 wma_wow_sta_ra_filter(wma, vdev_id);
3752 }
3753 }
3754 }
3755
3756 return;
3757}
3758
3759/**
3760 * wma_register_wow_wakeup_events() - register vdev specific wake events with fw
3761 * @handle: Pointer to wma handle
3762 * @vdev_id: vdev Id
3763 * @vdev_type: vdev type
3764 * @vdev_subtype: vdev sub type
3765 *
3766 * WoW wake up event rule is following:
3767 * 1) STA mode and P2P CLI mode wake up events are same
3768 * 2) SAP mode and P2P GO mode wake up events are same
3769 * 3) IBSS mode wake events are same as STA mode plus WOW_BEACON_EVENT
3770 *
3771 * Return: none
3772 */
3773void wma_register_wow_wakeup_events(WMA_HANDLE handle,
3774 uint8_t vdev_id,
3775 uint8_t vdev_type,
3776 uint8_t vdev_subtype)
3777{
3778 tp_wma_handle wma = handle;
3779 uint32_t event_bitmap;
3780
3781 WMA_LOGI("vdev_type %d vdev_subtype %d vdev_id %d", vdev_type,
3782 vdev_subtype, vdev_id);
3783
3784 if ((WMI_VDEV_TYPE_STA == vdev_type) ||
3785 ((WMI_VDEV_TYPE_AP == vdev_type) &&
3786 (WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE == vdev_subtype))) {
3787 /* Configure STA/P2P CLI mode specific default wake up events */
3788 event_bitmap = WMA_WOW_STA_WAKE_UP_EVENTS;
3789 WMA_LOGI("STA specific default wake up event 0x%x vdev id %d",
3790 event_bitmap, vdev_id);
3791 } else if (WMI_VDEV_TYPE_IBSS == vdev_type) {
3792 /* Configure IBSS mode specific default wake up events */
3793 event_bitmap = (WMA_WOW_STA_WAKE_UP_EVENTS |
3794 (1 << WOW_BEACON_EVENT));
3795 WMA_LOGI("IBSS specific default wake up event 0x%x vdev id %d",
3796 event_bitmap, vdev_id);
3797 } else if (WMI_VDEV_TYPE_AP == vdev_type) {
3798 /* Configure SAP/GO mode specific default wake up events */
3799 event_bitmap = WMA_WOW_SAP_WAKE_UP_EVENTS;
3800 WMA_LOGI("SAP specific default wake up event 0x%x vdev id %d",
3801 event_bitmap, vdev_id);
Naveen Rawate82c1f32016-06-22 15:34:36 -07003802 } else if (WMI_VDEV_TYPE_NDI == vdev_type) {
3803 /*
3804 * Configure NAN data path specific default wake up events.
3805 * Following routine sends the command to firmware.
3806 */
3807 wma_ndp_add_wow_wakeup_event(wma, vdev_id);
3808 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003809 } else {
3810 WMA_LOGE("unknown type %d subtype %d", vdev_type, vdev_subtype);
3811 return;
3812 }
3813
3814 wma_add_wow_wakeup_event(wma, vdev_id, event_bitmap, true);
3815
3816 return;
3817}
3818
3819/**
3820 * wma_enable_disable_wakeup_event() - Configures wow wakeup events
3821 * @wma: wma handle
3822 * @vdev_id: vdev id
3823 * @bitmap: Event bitmap
3824 * @enable: enable/disable
3825 *
3826 * Return: none
3827 */
3828void wma_enable_disable_wakeup_event(WMA_HANDLE handle,
3829 uint32_t vdev_id,
3830 uint32_t bitmap,
3831 bool enable)
3832{
3833 tp_wma_handle wma = handle;
3834
3835 WMA_LOGI("vdev_id %d wake up event 0x%x enable %d",
3836 vdev_id, bitmap, enable);
3837 wma_add_wow_wakeup_event(wma, vdev_id, bitmap, enable);
3838}
3839
3840/**
3841 * wma_enable_wow_in_fw() - wnable wow in fw
3842 * @wma: wma handle
3843 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303844 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003845 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303846QDF_STATUS wma_enable_wow_in_fw(WMA_HANDLE handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003847{
3848 tp_wma_handle wma = handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003849 int ret;
Komal Seelam3d202862016-02-24 18:43:24 +05303850 struct hif_opaque_softc *scn;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003851 int host_credits;
3852 int wmi_pending_cmds;
Govind Singhd76a5b02016-03-08 15:12:14 +05303853 struct wow_cmd_params param = {0};
3854
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003855#ifdef CONFIG_CNSS
Anurag Chouhan6d760662016-02-20 16:05:43 +05303856 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003857
3858 if (NULL == pMac) {
3859 WMA_LOGE("%s: Unable to get PE context", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303860 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003861 }
3862#endif /* CONFIG_CNSS */
3863
Anurag Chouhance0dc992016-02-16 18:18:03 +05303864 qdf_event_reset(&wma->target_suspend);
Houston Hoffmana769ed32016-04-14 17:02:51 -07003865 wma->wow_nack = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003866
3867 host_credits = wmi_get_host_credits(wma->wmi_handle);
3868 wmi_pending_cmds = wmi_get_pending_cmds(wma->wmi_handle);
3869
3870 WMA_LOGD("Credits:%d; Pending_Cmds: %d",
3871 host_credits, wmi_pending_cmds);
3872
3873 if (host_credits < WMI_WOW_REQUIRED_CREDITS) {
3874 WMA_LOGE("%s: Host Doesn't have enough credits to Post WMI_WOW_ENABLE_CMDID! "
3875 "Credits:%d, pending_cmds:%d\n", __func__, host_credits,
3876 wmi_pending_cmds);
3877#ifndef QCA_WIFI_3_0_EMU
3878 goto error;
3879#endif
3880 }
3881
Govind Singhd76a5b02016-03-08 15:12:14 +05303882 param.enable = true;
Houston Hoffman77f0e342016-07-25 13:28:10 -07003883 param.can_suspend_link = htc_can_suspend_link(wma->htc_handle);
Govind Singhd76a5b02016-03-08 15:12:14 +05303884 ret = wmi_unified_wow_enable_send(wma->wmi_handle, &param,
3885 WMA_WILDCARD_PDEV_ID);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003886 if (ret) {
3887 WMA_LOGE("Failed to enable wow in fw");
3888 goto error;
3889 }
3890
3891 wmi_set_target_suspend(wma->wmi_handle, true);
3892
Anurag Chouhance0dc992016-02-16 18:18:03 +05303893 if (qdf_wait_single_event(&wma->target_suspend,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003894 WMA_TGT_SUSPEND_COMPLETE_TIMEOUT)
Anurag Chouhance0dc992016-02-16 18:18:03 +05303895 != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003896 WMA_LOGE("Failed to receive WoW Enable Ack from FW");
3897 WMA_LOGE("Credits:%d; Pending_Cmds: %d",
3898 wmi_get_host_credits(wma->wmi_handle),
3899 wmi_get_pending_cmds(wma->wmi_handle));
Mukul Sharma93206a42016-09-03 16:18:10 +05303900 wmi_set_target_suspend(wma->wmi_handle, false);
Prashanth Bhatta9e143052015-12-04 11:56:47 -08003901 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003902#ifdef CONFIG_CNSS
Yue Ma455aff62015-10-20 18:29:16 -07003903 if (pMac->sme.enableSelfRecovery) {
3904 cds_trigger_recovery();
3905 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303906 QDF_BUG(0);
Yue Ma455aff62015-10-20 18:29:16 -07003907 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003908#else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303909 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003910#endif /* CONFIG_CNSS */
Yue Ma455aff62015-10-20 18:29:16 -07003911 } else {
3912 WMA_LOGE("%s: LOGP is in progress, ignore!", __func__);
3913 }
3914
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303915 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003916 }
3917
3918 if (wma->wow_nack) {
3919 WMA_LOGE("FW not ready to WOW");
3920 wmi_set_target_suspend(wma->wmi_handle, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303921 return QDF_STATUS_E_AGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003922 }
3923
3924 host_credits = wmi_get_host_credits(wma->wmi_handle);
3925 wmi_pending_cmds = wmi_get_pending_cmds(wma->wmi_handle);
3926
3927 if (host_credits < WMI_WOW_REQUIRED_CREDITS) {
3928 WMA_LOGE("%s: No Credits after HTC ACK:%d, pending_cmds:%d, "
3929 "cannot resume back", __func__, host_credits,
3930 wmi_pending_cmds);
3931 htc_dump_counter_info(wma->htc_handle);
Prashanth Bhatta9e143052015-12-04 11:56:47 -08003932 if (!cds_is_driver_recovering())
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303933 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003934 else
3935 WMA_LOGE("%s: SSR in progress, ignore no credit issue",
3936 __func__);
3937 }
3938
3939 WMA_LOGD("WOW enabled successfully in fw: credits:%d"
3940 "pending_cmds: %d", host_credits, wmi_pending_cmds);
3941
Anurag Chouhan6d760662016-02-20 16:05:43 +05303942 scn = cds_get_context(QDF_MODULE_ID_HIF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003943
3944 if (scn == NULL) {
3945 WMA_LOGE("%s: Failed to get HIF context", __func__);
Dustin Brown18179842016-09-02 15:41:58 -07003946 wmi_set_target_suspend(wma->wmi_handle, false);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303947 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303948 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003949 }
3950
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003951 wma->wow.wow_enable_cmd_sent = true;
3952
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303953 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003954
3955error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303956 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003957}
3958
3959/**
3960 * wma_resume_req() - clear configured wow patterns in fw
3961 * @wma: wma handle
Houston Hoffmana76591b2015-11-10 16:52:05 -08003962 * @type: type of suspend
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003963 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303964 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003965 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05303966QDF_STATUS wma_resume_req(tp_wma_handle wma, enum qdf_suspend_type type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003967{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303968 if (type == QDF_SYSTEM_SUSPEND) {
Houston Hoffmana76591b2015-11-10 16:52:05 -08003969 wma->no_of_resume_ind++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003970
Houston Hoffmana76591b2015-11-10 16:52:05 -08003971 if (wma->no_of_resume_ind < wma_get_vdev_count(wma))
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303972 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003973
Houston Hoffmana76591b2015-11-10 16:52:05 -08003974 wma->no_of_resume_ind = 0;
3975 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003976
3977 /* Reset the DTIM Parameters */
3978 wma_set_resume_dtim(wma);
3979 /* need to reset if hif_pci_suspend_fails */
3980 wma_set_wow_bus_suspend(wma, 0);
3981 /* unpause the vdev if left paused and hif_pci_suspend fails */
3982 wma_unpause_vdev(wma);
3983
Houston Hoffman1460fa32015-11-18 02:36:30 -08003984 wmi_set_runtime_pm_inprogress(wma->wmi_handle, false);
3985
Houston Hoffmanc45db892015-11-13 19:59:25 -08003986 if (type == QDF_RUNTIME_SUSPEND)
3987 qdf_runtime_pm_allow_suspend(wma->wma_runtime_resume_lock);
3988
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303989 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003990}
3991
3992/**
3993 * wma_wow_delete_pattern() - delete wow pattern in target
3994 * @wma: wma handle
3995 * @ptrn_id: pattern id
3996 * @vdev_id: vdev id
3997 * @user: true for user pattern and false for default pattern
3998 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303999 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004000 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304001static QDF_STATUS wma_wow_delete_pattern(tp_wma_handle wma, uint8_t ptrn_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004002 uint8_t vdev_id, bool user)
4003{
Govind Singhaa64c242016-03-08 11:31:49 +05304004
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004005 struct wma_txrx_node *iface;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004006 int ret;
4007
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004008 iface = &wma->interfaces[vdev_id];
Govind Singhaa64c242016-03-08 11:31:49 +05304009 ret = wmi_unified_wow_delete_pattern_cmd(wma->wmi_handle, ptrn_id,
4010 vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004011 if (ret) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304012 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004013 }
4014
4015 if (user)
4016 iface->num_wow_user_patterns--;
4017
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304018 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004019}
4020
4021/**
4022 * wma_wow_add_pattern() - add wow pattern in target
4023 * @wma: wma handle
4024 * @ptrn: wow pattern
4025 *
4026 * This function does following:
4027 * 1) Delete all default patterns of the vdev
4028 * 2) Add received wow patterns for given vdev in target.
4029 *
4030 * Target is responsible for caching wow patterns accross multiple
4031 * suspend/resumes until the pattern is deleted by user
4032 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304033 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004034 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304035QDF_STATUS wma_wow_add_pattern(tp_wma_handle wma, struct wow_add_pattern *ptrn)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004036{
4037 uint8_t id;
4038 uint8_t bit_to_check, pos;
4039 struct wma_txrx_node *iface;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304040 QDF_STATUS ret = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004041 uint8_t new_mask[SIR_WOWL_BCAST_PATTERN_MAX_SIZE];
4042
4043 if (ptrn->session_id > wma->max_bssid) {
4044 WMA_LOGE("Invalid vdev id (%d)", ptrn->session_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304045 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004046 }
4047
4048 iface = &wma->interfaces[ptrn->session_id];
4049
4050 /* clear all default patterns cofigured by wma */
4051 for (id = 0; id < iface->num_wow_default_patterns; id++)
4052 wma_wow_delete_pattern(wma, id, ptrn->session_id, false);
4053
4054 iface->num_wow_default_patterns = 0;
4055
4056 WMA_LOGI("Add user passed wow pattern id %d vdev id %d",
4057 ptrn->pattern_id, ptrn->session_id);
4058 /*
4059 * Convert received pattern mask value from bit representation
4060 * to byte representation.
4061 *
4062 * For example, received value from umac,
4063 *
4064 * Mask value : A1 (equivalent binary is "1010 0001")
4065 * Pattern value : 12:00:13:00:00:00:00:44
4066 *
4067 * The value which goes to FW after the conversion from this
4068 * function (1 in mask value will become FF and 0 will
4069 * become 00),
4070 *
4071 * Mask value : FF:00:FF:00:0:00:00:FF
4072 * Pattern value : 12:00:13:00:00:00:00:44
4073 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304074 qdf_mem_zero(new_mask, sizeof(new_mask));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004075 for (pos = 0; pos < ptrn->pattern_size; pos++) {
4076 bit_to_check = (WMA_NUM_BITS_IN_BYTE - 1) -
4077 (pos % WMA_NUM_BITS_IN_BYTE);
4078 bit_to_check = 0x1 << bit_to_check;
4079 if (ptrn->pattern_mask[pos / WMA_NUM_BITS_IN_BYTE] &
4080 bit_to_check)
4081 new_mask[pos] = WMA_WOW_PTRN_MASK_VALID;
4082 }
4083
4084 ret = wma_send_wow_patterns_to_fw(wma, ptrn->session_id,
4085 ptrn->pattern_id,
4086 ptrn->pattern, ptrn->pattern_size,
4087 ptrn->pattern_byte_offset, new_mask,
4088 ptrn->pattern_size, true);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304089 if (ret != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004090 WMA_LOGE("Failed to add wow pattern %d", ptrn->pattern_id);
4091
4092 return ret;
4093}
4094
4095/**
4096 * wma_wow_delete_user_pattern() - delete user configured wow pattern in target
4097 * @wma: wma handle
4098 * @ptrn: wow pattern
4099 *
4100 * This function does following:
4101 * 1) Deletes a particular user configured wow pattern in target
4102 * 2) After deleting all user wow patterns add default wow patterns
4103 * specific to that vdev.
4104 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304105 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004106 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304107QDF_STATUS wma_wow_delete_user_pattern(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004108 struct wow_delete_pattern *pattern)
4109{
4110 struct wma_txrx_node *iface;
4111
4112 if (pattern->session_id > wma->max_bssid) {
4113 WMA_LOGE("Invalid vdev id %d", pattern->session_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304114 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004115 }
4116
4117 iface = &wma->interfaces[pattern->session_id];
4118 if (iface->num_wow_user_patterns <= 0) {
4119 WMA_LOGE("No valid user pattern. Num user pattern %u vdev %d",
4120 iface->num_wow_user_patterns, pattern->session_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304121 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004122 }
4123
4124 WMA_LOGI("Delete user passed wow pattern id %d total user pattern %d",
4125 pattern->pattern_id, iface->num_wow_user_patterns);
4126
4127 wma_wow_delete_pattern(wma, pattern->pattern_id,
4128 pattern->session_id, true);
4129
4130 /* configure default patterns once all user patterns are deleted */
4131 if (!iface->num_wow_user_patterns)
4132 wma_register_wow_default_patterns(wma, pattern->session_id);
4133
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304134 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004135}
4136
4137/**
4138 * wma_wow_enter() - store enable/disable status for pattern
4139 * @wma: wma handle
4140 * @info: wow parameters
4141 *
4142 * Records pattern enable/disable status locally. This choice will
4143 * take effect when the driver enter into suspend state.
4144 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304145 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004146 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304147QDF_STATUS wma_wow_enter(tp_wma_handle wma, tpSirHalWowlEnterParams info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004148{
4149 struct wma_txrx_node *iface;
4150
4151 WMA_LOGD("wow enable req received for vdev id: %d", info->sessionId);
4152
4153 if (info->sessionId > wma->max_bssid) {
4154 WMA_LOGE("Invalid vdev id (%d)", info->sessionId);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304155 qdf_mem_free(info);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304156 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004157 }
4158
4159 iface = &wma->interfaces[info->sessionId];
4160 iface->ptrn_match_enable = info->ucPatternFilteringEnable ?
4161 true : false;
4162 wma->wow.magic_ptrn_enable = info->ucMagicPktEnable ? true : false;
4163 wma->wow.deauth_enable = info->ucWowDeauthRcv ? true : false;
4164 wma->wow.disassoc_enable = info->ucWowDeauthRcv ? true : false;
4165 wma->wow.bmiss_enable = info->ucWowMaxMissedBeacons ? true : false;
4166
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304167 qdf_mem_free(info);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004168
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304169 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004170}
4171
4172/**
4173 * wma_wow_exit() - clear all wma states
4174 * @wma: wma handle
4175 * @info: wow params
4176 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304177 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004178 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304179QDF_STATUS wma_wow_exit(tp_wma_handle wma, tpSirHalWowlExitParams info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004180{
4181 struct wma_txrx_node *iface;
4182
4183 WMA_LOGD("wow disable req received for vdev id: %d", info->sessionId);
4184
4185 if (info->sessionId > wma->max_bssid) {
4186 WMA_LOGE("Invalid vdev id (%d)", info->sessionId);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304187 qdf_mem_free(info);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304188 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004189 }
4190
4191 iface = &wma->interfaces[info->sessionId];
4192 iface->ptrn_match_enable = false;
4193 wma->wow.magic_ptrn_enable = false;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304194 qdf_mem_free(info);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004195
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304196 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004197}
4198
4199/**
Houston Hoffmana76591b2015-11-10 16:52:05 -08004200 * wma_calculate_and_update_conn_state(): calculate each interfaces conn state
4201 * @wma: validated wma handle
4202 *
4203 * Identifies any vdev that is up and not in ap mode as connected.
4204 * stores this in the interfaces conn_state varible.
4205 */
4206void wma_calculate_and_update_conn_state(tp_wma_handle wma)
4207{
4208 int i;
4209 for (i = 0; i < wma->max_bssid; i++) {
4210 wma->interfaces[i].conn_state =
4211 !!(wma->interfaces[i].vdev_up &&
4212 !wma_is_vdev_in_ap_mode(wma, i));
4213 }
4214}
4215
4216/**
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004217 * wma_update_conn_state(): synchronize wma & hdd
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004218 * @wma: wma handle
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004219 * @conn_state: boolean array to populate
4220 * @len: validation parameter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004221 *
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004222 * populate interfaces conn_state with true if the interface
4223 * is a connected client and wow will configure a pattern.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004224 */
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004225void wma_update_conn_state(tp_wma_handle wma, uint32_t conn_mask)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004226{
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004227 int i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004228 for (i = 0; i < wma->max_bssid; i++) {
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004229 if (conn_mask & (1 << i))
4230 wma->interfaces[i].conn_state = true;
4231 else
4232 wma->interfaces[i].conn_state = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004233 }
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004234
4235 if (wma->wow.magic_ptrn_enable)
4236 return;
4237
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004238 for (i = 0; i < wma->max_bssid; i++) {
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004239 if (!wma->interfaces[i].ptrn_match_enable)
4240 wma->interfaces[i].conn_state = false;
4241 }
4242}
4243
4244/**
4245 * wma_is_beaconning_vdev_up(): check if a beaconning vdev is up
4246 * @wma: wma handle
4247 *
4248 * Return TRUE if beaconning vdev is up
4249 */
4250static inline
4251bool wma_is_beaconning_vdev_up(tp_wma_handle wma)
4252{
4253 int i;
4254 for (i = 0; i < wma->max_bssid; i++) {
4255 if (wma_is_vdev_in_beaconning_mode(wma, i)
4256 && wma->interfaces[i].vdev_up)
4257 return true;
4258 }
4259 return false;
4260}
4261
4262/**
4263 * wma_support_wow_for_beaconing: wow query for beaconning
4264 * @wma: wma handle
4265 *
4266 * Need to configure wow to enable beaconning offload when
4267 * a beaconing vdev is up and beaonning offload is configured.
4268 *
4269 * Return: true if we need to enable wow for beaconning offload
4270 */
4271static inline
4272bool wma_support_wow_for_beaconing(tp_wma_handle wma)
4273{
4274 if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
4275 WMI_SERVICE_BEACON_OFFLOAD)) {
4276 if (wma_is_beaconning_vdev_up(wma))
4277 return true;
4278 }
4279 return false;
4280}
4281
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004282#ifdef FEATURE_WLAN_SCAN_PNO
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004283/**
4284 * wma_is_pnoscan_in_progress(): check if a pnoscan is in progress
4285 * @wma: wma handle
4286 * @vdev_id: vdev_id
4287 *
4288 * Return: TRUE/FALSE
4289 */
4290static inline
4291bool wma_is_pnoscan_in_progress(tp_wma_handle wma, int vdev_id)
4292{
4293 return wma->interfaces[vdev_id].pno_in_progress;
4294}
Houston Hoffman345fa402015-12-16 11:28:51 -08004295
4296/**
4297 * wma_is_pnoscan_match_found(): check if a scan match was found
4298 * @wma: wma handle
4299 * @vdev_id: vdev_id
4300 *
4301 * Return: TRUE/FALSE
4302 */
4303static inline
4304bool wma_is_pnoscan_match_found(tp_wma_handle wma, int vdev_id)
4305{
4306 return wma->interfaces[vdev_id].nlo_match_evt_received;
4307}
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004308#else
4309/**
4310 * wma_is_pnoscan_in_progress(): dummy
4311 *
Houston Hoffman345fa402015-12-16 11:28:51 -08004312 * Return: False since no pnoscan cannot be in progress
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004313 * when feature flag is not defined.
4314 */
4315bool wma_is_pnoscan_in_progress(tp_wma_handle wma, int vdev_id)
4316{
4317 return FALSE;
4318}
Houston Hoffman345fa402015-12-16 11:28:51 -08004319
4320/**
4321 * wma_is_pnoscan_match_found(): dummy
4322 * @wma: wma handle
4323 * @vdev_id: vdev_id
4324 *
4325 * Return: False since no pnoscan cannot occur
4326 * when feature flag is not defined.
4327 */
4328static inline
4329bool wma_is_pnoscan_match_found(tp_wma_handle wma, int vdev_id)
4330{
4331 return FALSE;
4332}
Houston Hoffman61667962015-12-15 20:15:41 -08004333#endif
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004334
4335#ifdef FEATURE_WLAN_EXTSCAN
4336static inline
4337/**
4338 * wma_is_extscan_in_progress(): check if an extscan is in progress
4339 * @wma: wma handle
4340 * @vdev_id: vdev_id
4341 *
4342 * Return: TRUE/FALSvE
4343 */
4344bool wma_is_extscan_in_progress(tp_wma_handle wma, int vdev_id)
4345{
4346 return wma->interfaces[vdev_id].extscan_in_progress;
4347}
4348#else
4349/**
4350 * wma_is_extscan_in_progress(): dummy
4351 *
4352 * Return: False since no extscan can be in progress
4353 * when feature flag is not defined.
4354 */
4355bool wma_is_extscan_in_progress(tp_wma_handle wma, int vdev_id)
4356{
4357 return false;
4358}
4359#endif
4360
4361/**
Peng Xu8fdaa492016-06-22 10:20:47 -07004362 * wma_is_p2plo_in_progress(): check if P2P listen offload is in progress
4363 * @wma: wma handle
4364 * @vdev_id: vdev_id
4365 *
4366 * This function is to check if p2p listen offload is in progress,
4367 * true: p2p listen offload in progress
4368 * false: otherwise
4369 *
4370 * Return: TRUE/FALSE
4371 */
4372static inline
4373bool wma_is_p2plo_in_progress(tp_wma_handle wma, int vdev_id)
4374{
4375 return wma->interfaces[vdev_id].p2p_lo_in_progress;
4376}
4377
Dustin Brown18179842016-09-02 15:41:58 -07004378#ifdef WLAN_FEATURE_LPSS
4379/**
4380 * wma_is_lpass_enabled() - check if lpass is enabled
4381 * @handle: Pointer to wma handle
4382 *
4383 * WoW is needed if LPASS or NaN feature is enabled in INI because
4384 * target can't wake up itself if its put in PDEV suspend when LPASS
4385 * or NaN features are supported
4386 *
4387 * Return: true if lpass is enabled else false
4388 */
4389bool static wma_is_lpass_enabled(tp_wma_handle wma)
4390{
4391 if (wma->is_lpass_enabled)
4392 return true;
4393 else
4394 return false;
4395}
4396#else
4397bool static wma_is_lpass_enabled(tp_wma_handle wma)
4398{
4399 return false;
4400}
4401#endif
4402
4403#ifdef WLAN_FEATURE_NAN
4404/**
4405 * wma_is_nan_enabled() - check if NaN is enabled
4406 * @handle: Pointer to wma handle
4407 *
4408 * WoW is needed if LPASS or NaN feature is enabled in INI because
4409 * target can't wake up itself if its put in PDEV suspend when LPASS
4410 * or NaN features are supported
4411 *
4412 * Return: true if NaN is enabled else false
4413 */
4414bool static wma_is_nan_enabled(tp_wma_handle wma)
4415{
4416 if (wma->is_nan_enabled)
4417 return true;
4418 else
4419 return false;
4420}
4421#else
4422bool static wma_is_nan_enabled(tp_wma_handle wma)
4423{
4424 return false;
4425}
4426#endif
4427
Peng Xu8fdaa492016-06-22 10:20:47 -07004428/**
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004429 * wma_is_wow_applicable(): should enable wow
4430 * @wma: wma handle
4431 *
4432 * Enable WOW if any one of the condition meets,
4433 * 1) Is any one of vdev in beaconning mode (in AP mode) ?
4434 * 2) Is any one of vdev in connected state (in STA mode) ?
4435 * 3) Is PNO in progress in any one of vdev ?
4436 * 4) Is Extscan in progress in any one of vdev ?
Peng Xu8fdaa492016-06-22 10:20:47 -07004437 * 5) Is P2P listen offload in any one of vdev?
Naveen Rawate82c1f32016-06-22 15:34:36 -07004438 * 6) Is any vdev in NAN data mode? BSS is already started at the
4439 * the time of device creation. It is ready to accept data
4440 * requests.
Dustin Brown18179842016-09-02 15:41:58 -07004441 * 7) If LPASS feature is enabled
4442 * 8) If NaN feature is enabled
Rajeev Kumaraea89632016-02-02 18:02:32 -08004443 * If none of above conditions is true then return false
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004444 *
Rajeev Kumaraea89632016-02-02 18:02:32 -08004445 * Return: true if wma needs to configure wow false otherwise.
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004446 */
4447bool wma_is_wow_applicable(tp_wma_handle wma)
4448{
4449 int vdev_id;
4450 if (wma_support_wow_for_beaconing(wma)) {
4451 WMA_LOGD("vdev is in beaconning mode, enabling wow");
4452 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004453 }
4454
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004455 for (vdev_id = 0; vdev_id < wma->max_bssid; vdev_id++) {
4456 if (wma->interfaces[vdev_id].conn_state) {
4457 WMA_LOGD("STA is connected, enabling wow");
4458 return true;
4459 } else if (wma_is_pnoscan_in_progress(wma, vdev_id)) {
4460 WMA_LOGD("PNO is in progress, enabling wow");
4461 return true;
4462 } else if (wma_is_extscan_in_progress(wma, vdev_id)) {
4463 WMA_LOGD("EXT is in progress, enabling wow");
4464 return true;
Peng Xu8fdaa492016-06-22 10:20:47 -07004465 } else if (wma_is_p2plo_in_progress(wma, vdev_id)) {
4466 WMA_LOGD("P2P LO is in progress, enabling wow");
4467 return true;
Dustin Brown18179842016-09-02 15:41:58 -07004468 } else if (wma_is_lpass_enabled(wma)) {
4469 WMA_LOGD("LPASS is enabled, enabling WoW");
4470 return true;
4471 } else if (wma_is_nan_enabled(wma)) {
4472 WMA_LOGD("NAN is enabled, enabling WoW");
4473 return true;
4474 } else if (WMA_IS_VDEV_IN_NDI_MODE(wma->interfaces, vdev_id)) {
Naveen Rawate82c1f32016-06-22 15:34:36 -07004475 WMA_LOGD("vdev %d is in NAN data mode, enabling wow",
4476 vdev_id);
4477 return true;
4478 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004479 }
4480
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004481 WMA_LOGD("All vdev are in disconnected state and pno/extscan is not in progress, skipping wow");
Rajeev Kumaraea89632016-02-02 18:02:32 -08004482 return false;
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004483}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004484
Houston Hoffman345fa402015-12-16 11:28:51 -08004485/**
4486 * wma_configure_dynamic_wake_events(): configure dyanmic wake events
4487 * @wma: wma handle
4488 *
4489 * Some wake events need to be enabled dynamically. Controll those here.
4490 *
4491 * Return: none
4492 */
4493void wma_configure_dynamic_wake_events(tp_wma_handle wma)
4494{
4495 int vdev_id;
4496 int enable_mask;
4497 int disable_mask;
4498
4499 for (vdev_id = 0; vdev_id < wma->max_bssid; vdev_id++) {
4500 enable_mask = 0;
4501 disable_mask = 0;
4502
4503 if (wma_is_pnoscan_in_progress(wma, vdev_id)) {
4504 if (wma_is_pnoscan_match_found(wma, vdev_id))
4505 enable_mask |=
4506 (1 << WOW_NLO_SCAN_COMPLETE_EVENT);
4507 else
4508 disable_mask |=
4509 (1 << WOW_NLO_SCAN_COMPLETE_EVENT);
4510 }
4511
4512 if (enable_mask != 0)
4513 wma_enable_disable_wakeup_event(wma, vdev_id,
4514 enable_mask, true);
4515 if (disable_mask != 0)
4516 wma_enable_disable_wakeup_event(wma, vdev_id,
4517 disable_mask, false);
4518 }
4519}
4520
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004521#ifdef FEATURE_WLAN_LPHB
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004522/**
4523 * wma_apply_lphb(): apply cached LPHB settings
4524 * @wma: wma handle
4525 *
4526 * LPHB cache, if any item was enabled, should be
4527 * applied.
4528 */
4529static inline
4530void wma_apply_lphb(tp_wma_handle wma)
4531{
4532 int i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004533 WMA_LOGD("%s: checking LPHB cache", __func__);
4534 for (i = 0; i < 2; i++) {
4535 if (wma->wow.lphb_cache[i].params.lphbEnableReq.enable) {
4536 WMA_LOGD("%s: LPHB cache for item %d is marked as enable",
4537 __func__, i + 1);
4538 wma_lphb_conf_hbenable(wma, &(wma->wow.lphb_cache[i]),
4539 false);
4540 }
4541 }
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004542}
4543#else
4544void wma_apply_lphb(tp_wma_handle wma) {}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004545#endif /* FEATURE_WLAN_LPHB */
4546
Houston Hoffmana76591b2015-11-10 16:52:05 -08004547static void wma_notify_suspend_req_procesed(tp_wma_handle wma,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304548 enum qdf_suspend_type type)
Houston Hoffmana76591b2015-11-10 16:52:05 -08004549{
Anurag Chouhan6d760662016-02-20 16:05:43 +05304550 if (type == QDF_SYSTEM_SUSPEND)
Houston Hoffmana76591b2015-11-10 16:52:05 -08004551 wma_send_status_to_suspend_ind(wma, true);
Anurag Chouhan6d760662016-02-20 16:05:43 +05304552 else if (type == QDF_RUNTIME_SUSPEND)
Anurag Chouhance0dc992016-02-16 18:18:03 +05304553 qdf_event_set(&wma->runtime_suspend);
Houston Hoffmana76591b2015-11-10 16:52:05 -08004554}
4555
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004556/**
4557 * wma_suspend_req() - Handles suspend indication request received from umac.
4558 * @wma: wma handle
Houston Hoffmana76591b2015-11-10 16:52:05 -08004559 * @type: type of suspend
4560 *
4561 * The type controlls how we notify the indicator that the indication has
4562 * been processed
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004563 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304564 * Return: QDF status
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004565 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05304566QDF_STATUS wma_suspend_req(tp_wma_handle wma, enum qdf_suspend_type type)
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004567{
Anurag Chouhan6d760662016-02-20 16:05:43 +05304568 if (type == QDF_RUNTIME_SUSPEND)
Houston Hoffman1460fa32015-11-18 02:36:30 -08004569 wmi_set_runtime_pm_inprogress(wma->wmi_handle, true);
4570
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004571 if (wma_is_wow_applicable(wma)) {
Dustin Brown2d228232016-09-22 15:06:19 -07004572 WMA_LOGI("WOW Suspend");
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004573 wma_apply_lphb(wma);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004574
Houston Hoffman345fa402015-12-16 11:28:51 -08004575 wma_configure_dynamic_wake_events(wma);
4576
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004577 wma->wow.wow_enable = true;
4578 wma->wow.wow_enable_cmd_sent = false;
4579 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004580
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004581 /* Set the Suspend DTIM Parameters */
4582 wma_set_suspend_dtim(wma);
Houston Hoffmana76591b2015-11-10 16:52:05 -08004583
4584 wma_notify_suspend_req_procesed(wma, type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004585
4586 /* to handle race between hif_pci_suspend and
4587 * unpause/pause tx handler
4588 */
4589 wma_set_wow_bus_suspend(wma, 1);
4590
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304591 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004592}
4593
4594/**
4595 * wma_send_host_wakeup_ind_to_fw() - send wakeup ind to fw
4596 * @wma: wma handle
4597 *
4598 * Sends host wakeup indication to FW. On receiving this indication,
4599 * FW will come out of WOW.
4600 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304601 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004602 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304603static QDF_STATUS wma_send_host_wakeup_ind_to_fw(tp_wma_handle wma)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004604{
Anurag Chouhance0dc992016-02-16 18:18:03 +05304605 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004606 int ret;
4607#ifdef CONFIG_CNSS
Anurag Chouhan6d760662016-02-20 16:05:43 +05304608 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004609 if (NULL == pMac) {
4610 WMA_LOGE("%s: Unable to get PE context", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304611 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004612 }
4613#endif /* CONFIG_CNSS */
4614
Anurag Chouhance0dc992016-02-16 18:18:03 +05304615 qdf_event_reset(&wma->wma_resume_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004616
Govind Singhaa64c242016-03-08 11:31:49 +05304617 ret = wmi_unified_host_wakeup_ind_to_fw_cmd(wma->wmi_handle);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004618 if (ret) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304619 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004620 }
4621
4622 WMA_LOGD("Host wakeup indication sent to fw");
4623
Anurag Chouhance0dc992016-02-16 18:18:03 +05304624 qdf_status = qdf_wait_single_event(&(wma->wma_resume_event),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004625 WMA_RESUME_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05304626 if (QDF_STATUS_SUCCESS != qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004627 WMA_LOGP("%s: Timeout waiting for resume event from FW",
4628 __func__);
4629 WMA_LOGP("%s: Pending commands %d credits %d", __func__,
4630 wmi_get_pending_cmds(wma->wmi_handle),
4631 wmi_get_host_credits(wma->wmi_handle));
Prashanth Bhatta9e143052015-12-04 11:56:47 -08004632 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004633#ifdef CONFIG_CNSS
4634 if (pMac->sme.enableSelfRecovery) {
4635 cds_trigger_recovery();
4636 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304637 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004638 }
4639#else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304640 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004641#endif /* CONFIG_CNSS */
4642 } else {
4643 WMA_LOGE("%s: SSR in progress, ignore resume timeout",
4644 __func__);
4645 }
4646 } else {
4647 WMA_LOGD("Host wakeup received");
4648 }
4649
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304650 if (QDF_STATUS_SUCCESS == qdf_status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004651 wmi_set_target_suspend(wma->wmi_handle, false);
4652
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304653 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004654}
4655
4656/**
4657 * wma_disable_wow_in_fw() - Disable wow in PCIe resume context.
4658 * @handle: wma handle
4659 *
4660 * Return: 0 for success or error code
4661 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304662QDF_STATUS wma_disable_wow_in_fw(WMA_HANDLE handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004663{
4664 tp_wma_handle wma = handle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304665 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004666
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004667 ret = wma_send_host_wakeup_ind_to_fw(wma);
4668
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304669 if (ret != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004670 return ret;
4671
4672 wma->wow.wow_enable = false;
4673 wma->wow.wow_enable_cmd_sent = false;
4674
4675 /* To allow the tx pause/unpause events */
4676 wma_set_wow_bus_suspend(wma, 0);
4677 /* Unpause the vdev as we are resuming */
4678 wma_unpause_vdev(wma);
4679
4680 return ret;
4681}
4682
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004683
4684/**
4685 * wma_is_wow_mode_selected() - check if wow needs to be enabled in fw
4686 * @handle: Pointer to wma handle
4687 *
4688 * If lpass is enabled then always do wow else check wow_enable config
4689 *
4690 * Return: true is wow mode is needed else false
4691 */
Houston Hoffmana76591b2015-11-10 16:52:05 -08004692bool wma_is_wow_mode_selected(WMA_HANDLE handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004693{
4694 tp_wma_handle wma = (tp_wma_handle) handle;
Dustin Brown18179842016-09-02 15:41:58 -07004695 WMA_LOGD("WoW enable %d", wma->wow.wow_enable);
4696 return wma->wow.wow_enable;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004697}
4698
4699/**
4700 * wma_del_ts_req() - send DELTS request to fw
4701 * @wma: wma handle
4702 * @msg: delts params
4703 *
4704 * Return: none
4705 */
4706void wma_del_ts_req(tp_wma_handle wma, tDelTsParams *msg)
4707{
Govind Singhaa64c242016-03-08 11:31:49 +05304708 if (wmi_unified_del_ts_cmd(wma->wmi_handle,
4709 msg->sessionId,
4710 TID_TO_WME_AC(msg->userPrio))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004711 WMA_LOGP("%s: Failed to send vdev DELTS command", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004712 }
Govind Singhaa64c242016-03-08 11:31:49 +05304713
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004714#ifdef WLAN_FEATURE_ROAM_OFFLOAD
4715 if (msg->setRICparams == true)
4716 wma_set_ric_req(wma, msg, false);
4717#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
4718
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304719 qdf_mem_free(msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004720}
4721
4722/**
4723 * wma_aggr_qos_req() - send aggr qos request to fw
4724 * @wma: handle to wma
4725 * @pAggrQosRspMsg - combined struct for all ADD_TS requests.
4726 *
4727 * A function to handle WMA_AGGR_QOS_REQ. This will send out
4728 * ADD_TS requestes to firmware in loop for all the ACs with
4729 * active flow.
4730 *
4731 * Return: none
4732 */
4733void wma_aggr_qos_req(tp_wma_handle wma,
4734 tAggrAddTsParams *pAggrQosRspMsg)
4735{
Govind Singhaa64c242016-03-08 11:31:49 +05304736 wmi_unified_aggr_qos_cmd(wma->wmi_handle,
4737 (struct aggr_add_ts_param *)pAggrQosRspMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004738 /* send reponse to upper layers from here only. */
4739 wma_send_msg(wma, WMA_AGGR_QOS_RSP, pAggrQosRspMsg, 0);
4740}
4741
Mahesh Kumar Kalikot Veetil40575112016-09-09 16:57:08 -07004742#ifdef FEATURE_WLAN_ESE
4743/**
4744 * wma_set_tsm_interval() - Set TSM interval
4745 * @req: pointer to ADDTS request
4746 *
4747 * Return: QDF_STATUS_E_FAILURE or QDF_STATUS_SUCCESS
4748 */
4749static QDF_STATUS wma_set_tsm_interval(tAddTsParams *req)
4750{
4751 /*
4752 * msmt_interval is in unit called TU (1 TU = 1024 us)
4753 * max value of msmt_interval cannot make resulting
4754 * interval_milliseconds overflow 32 bit
4755 *
4756 */
4757 uint32_t interval_milliseconds;
4758 ol_txrx_pdev_handle pdev = cds_get_context(QDF_MODULE_ID_TXRX);
4759 if (NULL == pdev) {
4760 WMA_LOGE("%s: Failed to get pdev", __func__);
4761 return QDF_STATUS_E_FAILURE;
4762 }
4763
4764 interval_milliseconds = (req->tsm_interval * 1024) / 1000;
4765
4766 ol_tx_set_compute_interval(pdev, interval_milliseconds);
4767 return QDF_STATUS_SUCCESS;
4768}
4769#else
4770static inline QDF_STATUS wma_set_tsm_interval(tAddTsParams *req)
4771{
4772 return QDF_STATUS_SUCCESS;
4773}
4774#endif /* FEATURE_WLAN_ESE */
4775
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004776/**
4777 * wma_add_ts_req() - send ADDTS request to fw
4778 * @wma: wma handle
4779 * @msg: ADDTS params
4780 *
4781 * Return: none
4782 */
4783void wma_add_ts_req(tp_wma_handle wma, tAddTsParams *msg)
4784{
Govind Singhaa64c242016-03-08 11:31:49 +05304785 struct add_ts_param cmd = {0};
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304786 msg->status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004787
Mahesh Kumar Kalikot Veetil40575112016-09-09 16:57:08 -07004788 if (wma_set_tsm_interval(msg) == QDF_STATUS_SUCCESS) {
Govind Singhaa64c242016-03-08 11:31:49 +05304789
Mahesh Kumar Kalikot Veetil40575112016-09-09 16:57:08 -07004790 cmd.sme_session_id = msg->sme_session_id;
4791 cmd.tspec.tsinfo.traffic.userPrio =
Govind Singhaa64c242016-03-08 11:31:49 +05304792 TID_TO_WME_AC(msg->tspec.tsinfo.traffic.userPrio);
Mahesh Kumar Kalikot Veetil40575112016-09-09 16:57:08 -07004793 cmd.tspec.mediumTime = msg->tspec.mediumTime;
4794 if (wmi_unified_add_ts_cmd(wma->wmi_handle, &cmd))
4795 msg->status = QDF_STATUS_E_FAILURE;
Govind Singhaa64c242016-03-08 11:31:49 +05304796
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004797#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Mahesh Kumar Kalikot Veetil40575112016-09-09 16:57:08 -07004798 if (msg->setRICparams == true)
4799 wma_set_ric_req(wma, msg, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004800#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
4801
Mahesh Kumar Kalikot Veetil40575112016-09-09 16:57:08 -07004802 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004803 wma_send_msg(wma, WMA_ADD_TS_RSP, msg, 0);
4804}
4805
4806/**
4807 * wma_enable_disable_packet_filter() - enable/disable packet filter in target
4808 * @wma: Pointer to wma handle
4809 * @vdev_id: vdev id
4810 * @enable: Flag to enable/disable packet filter
4811 *
4812 * Return: 0 for success or error code
4813 */
4814static int wma_enable_disable_packet_filter(tp_wma_handle wma,
4815 uint8_t vdev_id, bool enable)
4816{
Govind Singhaa64c242016-03-08 11:31:49 +05304817 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004818
Govind Singhaa64c242016-03-08 11:31:49 +05304819 ret = wmi_unified_enable_disable_packet_filter_cmd(wma->wmi_handle,
4820 vdev_id, enable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004821 if (ret)
4822 WMA_LOGE("Failed to send packet filter wmi cmd to fw");
4823
4824 return ret;
4825}
4826
4827/**
4828 * wma_config_packet_filter() - configure packet filter in target
4829 * @wma: Pointer to wma handle
4830 * @vdev_id: vdev id
4831 * @rcv_filter_param: Packet filter parameters
4832 * @filter_id: Filter id
4833 * @enable: Flag to add/delete packet filter configuration
4834 *
4835 * Return: 0 for success or error code
4836 */
4837static int wma_config_packet_filter(tp_wma_handle wma,
4838 uint8_t vdev_id, tSirRcvPktFilterCfgType *rcv_filter_param,
4839 uint8_t filter_id, bool enable)
4840{
Govind Singhaa64c242016-03-08 11:31:49 +05304841 int err;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004842
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004843 /* send the command along with data */
Govind Singhaa64c242016-03-08 11:31:49 +05304844 err = wmi_unified_config_packet_filter_cmd(wma->wmi_handle,
4845 vdev_id, (struct rcv_pkt_filter_config *)rcv_filter_param,
4846 filter_id, enable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004847 if (err) {
4848 WMA_LOGE("Failed to send pkt_filter cmd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004849 return -EIO;
4850 }
4851
4852 /* Enable packet filter */
4853 if (enable)
4854 wma_enable_disable_packet_filter(wma, vdev_id, true);
4855
4856 return 0;
4857}
4858
4859/**
4860 * wma_process_receive_filter_set_filter_req() - enable packet filter
4861 * @wma_handle: wma handle
4862 * @rcv_filter_param: filter params
4863 *
4864 * Return: 0 for success or error code
4865 */
4866int wma_process_receive_filter_set_filter_req(tp_wma_handle wma,
4867 tSirRcvPktFilterCfgType *rcv_filter_param)
4868{
4869 int ret = 0;
4870 uint8_t vdev_id;
4871
4872 /* Get the vdev id */
Srinivas Girigowda98530492015-11-20 17:39:24 -08004873 if (!wma_find_vdev_by_bssid(wma,
4874 rcv_filter_param->bssid.bytes, &vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004875 WMA_LOGE("vdev handle is invalid for %pM",
Srinivas Girigowda98530492015-11-20 17:39:24 -08004876 rcv_filter_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004877 return -EINVAL;
4878 }
4879
4880 ret = wma_config_packet_filter(wma, vdev_id, rcv_filter_param,
4881 rcv_filter_param->filterId, true);
4882
4883 return ret;
4884}
4885
4886/**
4887 * wma_process_receive_filter_clear_filter_req() - disable packet filter
4888 * @wma_handle: wma handle
4889 * @rcv_clear_param: filter params
4890 *
4891 * Return: 0 for success or error code
4892 */
4893int wma_process_receive_filter_clear_filter_req(tp_wma_handle wma,
4894 tSirRcvFltPktClearParam *rcv_clear_param)
4895{
4896 int ret = 0;
4897 uint8_t vdev_id;
4898
4899 /* Get the vdev id */
Srinivas Girigowda98530492015-11-20 17:39:24 -08004900 if (!wma_find_vdev_by_bssid(wma,
4901 rcv_clear_param->bssid.bytes, &vdev_id)) {
4902 WMA_LOGE("vdev handle is invalid for %pM",
4903 rcv_clear_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004904 return -EINVAL;
4905 }
4906
4907 ret = wma_config_packet_filter(wma, vdev_id, NULL,
4908 rcv_clear_param->filterId, false);
4909
4910 return ret;
4911}
4912
4913#ifdef FEATURE_WLAN_ESE
4914
4915#define TSM_DELAY_HISTROGRAM_BINS 4
4916/**
4917 * wma_process_tsm_stats_req() - process tsm stats request
4918 * @wma_handler - handle to wma
4919 * @pTsmStatsMsg - TSM stats struct that needs to be populated and
4920 * passed in message.
4921 *
4922 * A parallel function to WMA_ProcessTsmStatsReq for pronto. This
4923 * function fetches stats from data path APIs and post
4924 * WMA_TSM_STATS_RSP msg back to LIM.
4925 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304926 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004927 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304928QDF_STATUS wma_process_tsm_stats_req(tp_wma_handle wma_handler,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004929 void *pTsmStatsMsg)
4930{
4931 uint8_t counter;
4932 uint32_t queue_delay_microsec = 0;
4933 uint32_t tx_delay_microsec = 0;
4934 uint16_t packet_count = 0;
4935 uint16_t packet_loss_count = 0;
4936 tpAniTrafStrmMetrics pTsmMetric = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004937 tpAniGetTsmStatsReq pStats = (tpAniGetTsmStatsReq) pTsmStatsMsg;
4938 tpAniGetTsmStatsRsp pTsmRspParams = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004939 int tid = pStats->tid;
4940 /*
4941 * The number of histrogram bin report by data path api are different
4942 * than required by TSM, hence different (6) size array used
4943 */
4944 uint16_t bin_values[QCA_TX_DELAY_HIST_REPORT_BINS] = { 0, };
4945
Anurag Chouhan6d760662016-02-20 16:05:43 +05304946 ol_txrx_pdev_handle pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004947
4948 if (NULL == pdev) {
4949 WMA_LOGE("%s: Failed to get pdev", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304950 qdf_mem_free(pTsmStatsMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304951 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004952 }
4953
4954 /* get required values from data path APIs */
4955 ol_tx_delay(pdev, &queue_delay_microsec, &tx_delay_microsec, tid);
4956 ol_tx_delay_hist(pdev, bin_values, tid);
4957 ol_tx_packet_count(pdev, &packet_count, &packet_loss_count, tid);
4958
Srinivas Girigowda515a9ef2015-12-11 11:00:48 -08004959 pTsmRspParams = qdf_mem_malloc(sizeof(*pTsmRspParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004960 if (NULL == pTsmRspParams) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304961 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304962 "%s: QDF MEM Alloc Failure", __func__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304963 QDF_ASSERT(0);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304964 qdf_mem_free(pTsmStatsMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304965 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004966 }
4967 pTsmRspParams->staId = pStats->staId;
4968 pTsmRspParams->rc = eSIR_FAILURE;
4969 pTsmRspParams->tsmStatsReq = pStats;
4970 pTsmMetric = &pTsmRspParams->tsmMetrics;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004971 /* populate pTsmMetric */
4972 pTsmMetric->UplinkPktQueueDly = queue_delay_microsec;
4973 /* store only required number of bin values */
4974 for (counter = 0; counter < TSM_DELAY_HISTROGRAM_BINS; counter++) {
4975 pTsmMetric->UplinkPktQueueDlyHist[counter] =
4976 bin_values[counter];
4977 }
4978 pTsmMetric->UplinkPktTxDly = tx_delay_microsec;
4979 pTsmMetric->UplinkPktLoss = packet_loss_count;
4980 pTsmMetric->UplinkPktCount = packet_count;
4981
4982 /*
4983 * No need to populate roaming delay and roaming count as they are
4984 * being populated just before sending IAPP frame out
4985 */
4986 /* post this message to LIM/PE */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004987 wma_send_msg(wma_handler, WMA_TSM_STATS_RSP, (void *)pTsmRspParams, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304988 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004989}
4990
4991#endif /* FEATURE_WLAN_ESE */
4992
4993/**
4994 * wma_add_clear_mcbc_filter() - set mcast filter command to fw
4995 * @wma_handle: wma handle
4996 * @vdev_id: vdev id
4997 * @multicastAddr: mcast address
4998 * @clearList: clear list flag
4999 *
5000 * Return: 0 for success or error code
5001 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05305002static QDF_STATUS wma_add_clear_mcbc_filter(tp_wma_handle wma_handle,
5003 uint8_t vdev_id,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305004 struct qdf_mac_addr multicast_addr,
Srinivas Girigowda98530492015-11-20 17:39:24 -08005005 bool clearList)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005006{
Himanshu Agarwal44195412016-03-09 13:03:54 +05305007 return wmi_unified_add_clear_mcbc_filter_cmd(wma_handle->wmi_handle,
5008 vdev_id, multicast_addr, clearList);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005009}
5010
5011/**
Rajeev Kumaref96e152016-04-15 18:10:33 -07005012 * wma_config_enhance_multicast_offload() - config enhance multicast offload
5013 * @wma_handle: wma handle
5014 * @vdev_id: vdev id
5015 * @action: enable or disable enhance multicast offload
5016 *
5017 * Return: none
5018 */
5019static void wma_config_enhance_multicast_offload(tp_wma_handle wma_handle,
5020 uint8_t vdev_id,
5021 uint8_t action)
5022{
5023 int status;
5024 wmi_buf_t buf;
5025 wmi_config_enhanced_mcast_filter_cmd_fixed_param *cmd;
5026
5027 buf = wmi_buf_alloc(wma_handle->wmi_handle, sizeof(*cmd));
5028 if (!buf) {
5029 WMA_LOGE("Failed to allocate buffer to send set key cmd");
5030 return;
5031 }
5032
5033 cmd = (wmi_config_enhanced_mcast_filter_cmd_fixed_param *)
5034 wmi_buf_data(buf);
5035
5036 WMITLV_SET_HDR(&cmd->tlv_header,
5037 WMITLV_TAG_STRUC_wmi_config_enhanced_mcast_filter_fixed_param,
5038 WMITLV_GET_STRUCT_TLVLEN(wmi_config_enhanced_mcast_filter_cmd_fixed_param));
5039
5040 cmd->vdev_id = vdev_id;
5041 cmd->enable = ((0 == action) ? ENHANCED_MCAST_FILTER_DISABLED :
5042 ENHANCED_MCAST_FILTER_ENABLED);
5043
5044 WMA_LOGD("%s: config enhance multicast offload action %d for vdev %d",
5045 __func__, action, vdev_id);
5046
5047 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
5048 sizeof(*cmd), WMI_CONFIG_ENHANCED_MCAST_FILTER_CMDID);
5049 if (status) {
5050 qdf_nbuf_free(buf);
5051 WMA_LOGE("%s:Failed to send WMI_CONFIG_ENHANCED_MCAST_FILTER_CMDID",
5052 __func__);
5053 }
5054
5055 return;
5056}
5057
5058/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005059 * wma_process_mcbc_set_filter_req() - process mcbc set filter request
5060 * @wma_handle: wma handle
5061 * @mcbc_param: mcbc params
5062 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305063 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005064 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305065QDF_STATUS wma_process_mcbc_set_filter_req(tp_wma_handle wma_handle,
Anurag Chouhance0dc992016-02-16 18:18:03 +05305066 tSirRcvFltMcAddrList *mcbc_param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005067{
5068 uint8_t vdev_id = 0;
5069 int i;
5070
5071 if (mcbc_param->ulMulticastAddrCnt <= 0) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08005072 WMA_LOGW("Number of multicast addresses is 0");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305073 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005074 }
5075
Srinivas Girigowda98530492015-11-20 17:39:24 -08005076 if (!wma_find_vdev_by_addr(wma_handle,
5077 mcbc_param->self_macaddr.bytes, &vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005078 WMA_LOGE("%s: Failed to find vdev id for %pM", __func__,
Srinivas Girigowda98530492015-11-20 17:39:24 -08005079 mcbc_param->bssid.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305080 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005081 }
Rajeev Kumaref96e152016-04-15 18:10:33 -07005082
5083 /*
5084 * Configure enhance multicast offload feature for filtering out
5085 * multicast IP data packets transmitted using unicast MAC address
5086 */
5087 if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap,
5088 WMI_SERVICE_ENHANCED_MCAST_FILTER)) {
5089 WMA_LOGD("%s: FW supports enhance multicast offload", __func__);
5090 wma_config_enhance_multicast_offload(wma_handle, vdev_id,
5091 mcbc_param->action);
5092 } else {
5093 WMA_LOGD("%s: FW does not support enhance multicast offload",
5094 __func__);
5095 }
5096
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005097 /* set mcbc_param->action to clear MCList and reset
5098 * to configure the MCList in FW
5099 */
5100
5101 for (i = 0; i < mcbc_param->ulMulticastAddrCnt; i++) {
5102 wma_add_clear_mcbc_filter(wma_handle, vdev_id,
5103 mcbc_param->multicastAddr[i],
5104 (mcbc_param->action == 0));
5105 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305106 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005107}
5108
5109#ifdef WLAN_FEATURE_GTK_OFFLOAD
5110#define GTK_OFFLOAD_ENABLE 0
5111#define GTK_OFFLOAD_DISABLE 1
5112
5113/**
5114 * wma_gtk_offload_status_event() - GTK offload status event handler
5115 * @handle: wma handle
5116 * @event: event buffer
5117 * @len: buffer length
5118 *
5119 * Return: 0 for success or error code
5120 */
5121int wma_gtk_offload_status_event(void *handle, uint8_t *event,
5122 uint32_t len)
5123{
5124 tp_wma_handle wma = (tp_wma_handle) handle;
5125 WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param *status;
5126 WMI_GTK_OFFLOAD_STATUS_EVENTID_param_tlvs *param_buf;
5127 tpSirGtkOffloadGetInfoRspParams resp;
5128 cds_msg_t cds_msg;
5129 uint8_t *bssid;
5130
5131 WMA_LOGD("%s Enter", __func__);
5132
5133 param_buf = (WMI_GTK_OFFLOAD_STATUS_EVENTID_param_tlvs *) event;
5134 if (!param_buf) {
5135 WMA_LOGE("param_buf is NULL");
5136 return -EINVAL;
5137 }
5138
5139 status = (WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param *) param_buf->fixed_param;
5140
5141 if (len < sizeof(WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param)) {
5142 WMA_LOGE("Invalid length for GTK status");
5143 return -EINVAL;
5144 }
5145 bssid = wma_find_bssid_by_vdev_id(wma, status->vdev_id);
5146 if (!bssid) {
5147 WMA_LOGE("invalid bssid for vdev id %d", status->vdev_id);
5148 return -ENOENT;
5149 }
5150
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305151 resp = qdf_mem_malloc(sizeof(*resp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005152 if (!resp) {
5153 WMA_LOGE("%s: Failed to alloc response", __func__);
5154 return -ENOMEM;
5155 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305156 qdf_mem_zero(resp, sizeof(*resp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005157 resp->mesgType = eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP;
5158 resp->mesgLen = sizeof(*resp);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305159 resp->ulStatus = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005160 resp->ulTotalRekeyCount = status->refresh_cnt;
5161 /* TODO: Is the total rekey count and GTK rekey count same? */
5162 resp->ulGTKRekeyCount = status->refresh_cnt;
5163
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305164 qdf_mem_copy(&resp->ullKeyReplayCounter, &status->replay_counter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005165 GTK_REPLAY_COUNTER_BYTES);
5166
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305167 qdf_mem_copy(resp->bssid.bytes, bssid, IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005168
5169#ifdef IGTK_OFFLOAD
5170 /* TODO: Is the refresh count same for GTK and IGTK? */
5171 resp->ulIGTKRekeyCount = status->refresh_cnt;
5172#endif /* IGTK_OFFLOAD */
5173
5174 cds_msg.type = eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP;
5175 cds_msg.bodyptr = (void *)resp;
5176 cds_msg.bodyval = 0;
5177
5178 if (cds_mq_post_message(CDS_MQ_ID_SME, (cds_msg_t *) &cds_msg)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305179 != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005180 WMA_LOGE("Failed to post GTK response to SME");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305181 qdf_mem_free(resp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005182 return -EINVAL;
5183 }
5184
5185 WMA_LOGD("GTK: got target status with replay counter "
5186 "%02x%02x%02x%02x%02x%02x%02x%02x. vdev %d "
5187 "Refresh GTK %d times exchanges since last set operation",
5188 status->replay_counter[0],
5189 status->replay_counter[1],
5190 status->replay_counter[2],
5191 status->replay_counter[3],
5192 status->replay_counter[4],
5193 status->replay_counter[5],
5194 status->replay_counter[6],
5195 status->replay_counter[7],
5196 status->vdev_id, status->refresh_cnt);
5197
5198 WMA_LOGD("%s Exit", __func__);
5199
5200 return 0;
5201}
5202
5203/**
5204 * wma_send_gtk_offload_req() - send GTK offload command to fw
5205 * @wma: wma handle
5206 * @vdev_id: vdev id
5207 * @params: GTK offload parameters
5208 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305209 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005210 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305211static QDF_STATUS wma_send_gtk_offload_req(tp_wma_handle wma, uint8_t vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005212 tpSirGtkOffloadParams params)
5213{
Himanshu Agarwal44195412016-03-09 13:03:54 +05305214 struct gtk_offload_params offload_params = {0};
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305215 QDF_STATUS status = QDF_STATUS_SUCCESS;
Himanshu Agarwal44195412016-03-09 13:03:54 +05305216 bool enable_offload;
5217 uint32_t gtk_offload_opcode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005218
5219 WMA_LOGD("%s Enter", __func__);
5220
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005221 /* Request target to enable GTK offload */
5222 if (params->ulFlags == GTK_OFFLOAD_ENABLE) {
Himanshu Agarwal44195412016-03-09 13:03:54 +05305223 gtk_offload_opcode = GTK_OFFLOAD_ENABLE_OPCODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005224 wma->wow.gtk_err_enable[vdev_id] = true;
5225
5226 /* Copy the keys and replay counter */
Himanshu Agarwal44195412016-03-09 13:03:54 +05305227 qdf_mem_copy(offload_params.aKCK, params->aKCK,
5228 GTK_OFFLOAD_KCK_BYTES);
5229 qdf_mem_copy(offload_params.aKEK, params->aKEK,
5230 GTK_OFFLOAD_KEK_BYTES);
5231 qdf_mem_copy(&offload_params.ullKeyReplayCounter,
5232 &params->ullKeyReplayCounter, GTK_REPLAY_COUNTER_BYTES);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005233 } else {
5234 wma->wow.gtk_err_enable[vdev_id] = false;
Himanshu Agarwal44195412016-03-09 13:03:54 +05305235 gtk_offload_opcode = GTK_OFFLOAD_DISABLE_OPCODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005236 }
5237
Himanshu Agarwal44195412016-03-09 13:03:54 +05305238 enable_offload = params->ulFlags;
5239
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005240 /* send the wmi command */
Himanshu Agarwal44195412016-03-09 13:03:54 +05305241 status = wmi_unified_send_gtk_offload_cmd(wma->wmi_handle,
5242 vdev_id, &offload_params,
5243 enable_offload,
5244 gtk_offload_opcode);
5245 if (QDF_IS_STATUS_ERROR(status))
5246 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005247
Himanshu Agarwal44195412016-03-09 13:03:54 +05305248 WMA_LOGD("VDEVID: %d, GTK_FLAGS: x%x", vdev_id, gtk_offload_opcode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005249out:
5250 WMA_LOGD("%s Exit", __func__);
5251 return status;
5252}
5253
5254/**
5255 * wma_process_gtk_offload_req() - process GTK offload req from umac
5256 * @handle: wma handle
5257 * @params: GTK offload params
5258 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305259 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005260 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305261QDF_STATUS wma_process_gtk_offload_req(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005262 tpSirGtkOffloadParams params)
5263{
5264 uint8_t vdev_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305265 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005266
5267 WMA_LOGD("%s Enter", __func__);
5268
5269 /* Get the vdev id */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08005270 if (!wma_find_vdev_by_bssid(wma, params->bssid.bytes, &vdev_id)) {
5271 WMA_LOGE("vdev handle is invalid for %pM", params->bssid.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305272 status = QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005273 goto out;
5274 }
5275
5276 /* Validate vdev id */
Naveen Rawate9fb4ce2016-06-27 15:36:10 -07005277 if (vdev_id >= WMA_MAX_SUPPORTED_BSS) {
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08005278 WMA_LOGE("invalid vdev_id %d for %pM", vdev_id,
5279 params->bssid.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305280 status = QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005281 goto out;
5282 }
5283
5284 if ((params->ulFlags == GTK_OFFLOAD_ENABLE) &&
5285 (wma->wow.gtk_err_enable[vdev_id] == true)) {
5286 WMA_LOGE("%s GTK Offload already enabled. Disable it first "
5287 "vdev_id %d", __func__, vdev_id);
5288 params->ulFlags = GTK_OFFLOAD_DISABLE;
5289 status = wma_send_gtk_offload_req(wma, vdev_id, params);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305290 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005291 WMA_LOGE("%s Failed to disable GTK Offload", __func__);
5292 goto out;
5293 }
5294 WMA_LOGD("%s Enable GTK Offload again with updated inputs",
5295 __func__);
5296 params->ulFlags = GTK_OFFLOAD_ENABLE;
5297 }
5298 status = wma_send_gtk_offload_req(wma, vdev_id, params);
5299out:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305300 qdf_mem_free(params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005301 WMA_LOGD("%s Exit", __func__);
5302 return status;
5303}
5304
5305/**
5306 * wma_process_gtk_offload_getinfo_req() - send GTK offload cmd to fw
5307 * @wma: wma handle
5308 * @params: GTK offload params
5309 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305310 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005311 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305312QDF_STATUS wma_process_gtk_offload_getinfo_req(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005313 tpSirGtkOffloadGetInfoRspParams params)
5314{
5315 uint8_t vdev_id;
Himanshu Agarwal44195412016-03-09 13:03:54 +05305316 uint64_t offload_req_opcode;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305317 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005318
5319 WMA_LOGD("%s Enter", __func__);
5320
5321 /* Get the vdev id */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08005322 if (!wma_find_vdev_by_bssid(wma, params->bssid.bytes, &vdev_id)) {
5323 WMA_LOGE("vdev handle is invalid for %pM", params->bssid.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305324 status = QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005325 goto out;
5326 }
5327
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005328 /* Request for GTK offload status */
Himanshu Agarwal44195412016-03-09 13:03:54 +05305329 offload_req_opcode = GTK_OFFLOAD_REQUEST_STATUS_OPCODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005330
5331 /* send the wmi command */
Himanshu Agarwal44195412016-03-09 13:03:54 +05305332 status = wmi_unified_process_gtk_offload_getinfo_cmd(wma->wmi_handle,
5333 vdev_id, offload_req_opcode);
5334
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005335out:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305336 qdf_mem_free(params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005337 WMA_LOGD("%s Exit", __func__);
5338 return status;
5339}
5340#endif /* WLAN_FEATURE_GTK_OFFLOAD */
5341
5342/**
5343 * wma_enable_arp_ns_offload() - enable ARP NS offload
5344 * @wma: wma handle
5345 * @tpSirHostOffloadReq: offload request
Mukul Sharma8d2d9ec2016-09-08 13:05:35 +05305346 * @config_arp: config arp flag
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005347 *
5348 * To configure ARP NS off load data to firmware
5349 * when target goes to wow mode.
5350 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305351 * Return: QDF Status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005352 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305353QDF_STATUS wma_enable_arp_ns_offload(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005354 tpSirHostOffloadReq
Mukul Sharma8d2d9ec2016-09-08 13:05:35 +05305355 offload_req, bool config_arp)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005356{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005357 int32_t res;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005358 uint8_t vdev_id;
Mukul Sharma8d2d9ec2016-09-08 13:05:35 +05305359 tpSirHostOffloadReq ns_offload_req;
5360 tpSirHostOffloadReq arp_offload_req;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005361
5362 /* Get the vdev id */
Mukul Sharma8d2d9ec2016-09-08 13:05:35 +05305363 if (!wma_find_vdev_by_bssid(wma, offload_req->bssid.bytes,
Srinivas Girigowdab084b552015-11-24 12:39:12 -08005364 &vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005365 WMA_LOGE("vdev handle is invalid for %pM",
Mukul Sharma8d2d9ec2016-09-08 13:05:35 +05305366 offload_req->bssid.bytes);
5367 qdf_mem_free(offload_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305368 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005369 }
5370
5371 if (!wma->interfaces[vdev_id].vdev_up) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005372 WMA_LOGE("vdev %d is not up skipping arp/ns offload", vdev_id);
Mukul Sharma8d2d9ec2016-09-08 13:05:35 +05305373 qdf_mem_free(offload_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305374 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005375 }
5376
Mukul Sharma8d2d9ec2016-09-08 13:05:35 +05305377 /*
5378 * config_arp is true means arp request comes from upper layer
5379 * Hence ns request need to used from wma cached request.
5380 */
5381 if (config_arp) {
5382 arp_offload_req = offload_req;
5383 ns_offload_req = &wma->interfaces[vdev_id].ns_offload_req;
5384 WMA_LOGD(" %s: ARP Offload vdev_id: %d enable: %d",
5385 __func__, vdev_id,
5386 offload_req->enableOrDisable);
5387 } else {
5388 ns_offload_req = offload_req;
5389 arp_offload_req = &wma->interfaces[vdev_id].arp_offload_req;
5390 WMA_LOGD(" %s: NS Offload vdev_id: %d enable: %d ns_count: %u",
5391 __func__, vdev_id,
5392 offload_req->enableOrDisable,
5393 offload_req->num_ns_offload_count);
5394 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005395
Govind Singhaa64c242016-03-08 11:31:49 +05305396 res = wmi_unified_enable_arp_ns_offload_cmd(wma->wmi_handle,
Mukul Sharma8d2d9ec2016-09-08 13:05:35 +05305397 (struct host_offload_req_param *)arp_offload_req,
5398 (struct host_offload_req_param *)ns_offload_req,
5399 config_arp,
5400 vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005401 if (res) {
5402 WMA_LOGE("Failed to enable ARP NDP/NSffload");
Mukul Sharma8d2d9ec2016-09-08 13:05:35 +05305403 qdf_mem_free(offload_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305404 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005405 }
5406
Mukul Sharma8d2d9ec2016-09-08 13:05:35 +05305407 if (config_arp) {
5408 qdf_mem_copy(&wma->interfaces[vdev_id].arp_offload_req,
5409 offload_req,
5410 sizeof(wma->interfaces[vdev_id].arp_offload_req));
5411 } else {
5412 qdf_mem_copy(&wma->interfaces[vdev_id].ns_offload_req,
5413 offload_req,
5414 sizeof(wma->interfaces[vdev_id].ns_offload_req));
5415 }
5416
5417 qdf_mem_free(offload_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305418 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005419}
5420
Mukul Sharma8d2d9ec2016-09-08 13:05:35 +05305421
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005422/**
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08005423 * wma_process_cesium_enable_ind() - enables cesium functionality in target
5424 * @wma: wma handle
5425 *
5426 * Return: QDF status
5427 */
5428QDF_STATUS wma_process_cesium_enable_ind(tp_wma_handle wma)
5429{
5430 QDF_STATUS ret;
5431 int32_t vdev_id;
5432
5433 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
5434 if (vdev_id < 0) {
5435 WMA_LOGE("%s: IBSS vdev does not exist could not enable cesium",
5436 __func__);
5437 return QDF_STATUS_E_FAILURE;
5438 }
5439
5440 /* Send enable cesium command to target */
5441 WMA_LOGE("Enable cesium in target for vdevId %d ", vdev_id);
5442 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
5443 WMI_VDEV_PARAM_ENABLE_RMC, 1);
5444 if (ret) {
5445 WMA_LOGE("Enable cesium failed for vdevId %d", vdev_id);
5446 return QDF_STATUS_E_FAILURE;
5447 }
5448 return QDF_STATUS_SUCCESS;
5449}
5450
5451/**
5452 * wma_process_get_peer_info_req() - sends get peer info cmd to target
5453 * @wma: wma handle
5454 * @preq: get peer info request
5455 *
5456 * Return: QDF status
5457 */
5458QDF_STATUS wma_process_get_peer_info_req
5459 (tp_wma_handle wma, tSirIbssGetPeerInfoReqParams *pReq)
5460{
5461 int32_t ret;
5462 uint8_t *p;
5463 uint16_t len;
5464 wmi_buf_t buf;
5465 int32_t vdev_id;
5466 ol_txrx_pdev_handle pdev;
5467 struct ol_txrx_peer_t *peer;
5468 uint8_t peer_mac[IEEE80211_ADDR_LEN];
5469 wmi_peer_info_req_cmd_fixed_param *p_get_peer_info_cmd;
5470 uint8_t bcast_mac[IEEE80211_ADDR_LEN] = { 0xff, 0xff, 0xff,
5471 0xff, 0xff, 0xff };
5472
5473 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
5474 if (vdev_id < 0) {
5475 WMA_LOGE("%s: IBSS vdev does not exist could not get peer info",
5476 __func__);
5477 return QDF_STATUS_E_FAILURE;
5478 }
5479
5480 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
5481 if (NULL == pdev) {
5482 WMA_LOGE("%s: Failed to get pdev context", __func__);
5483 return QDF_STATUS_E_FAILURE;
5484 }
5485
5486 if (0xFF == pReq->staIdx) {
5487 /*get info for all peers */
5488 qdf_mem_copy(peer_mac, bcast_mac, IEEE80211_ADDR_LEN);
5489 } else {
5490 /*get info for a single peer */
5491 peer = ol_txrx_peer_find_by_local_id(pdev, pReq->staIdx);
5492 if (!peer) {
5493 WMA_LOGE("%s: Failed to get peer handle using peer id %d",
5494 __func__, pReq->staIdx);
5495 return QDF_STATUS_E_FAILURE;
5496 }
5497 WMA_LOGE("%s: staIdx %d peer mac: 0x%2x:0x%2x:0x%2x:0x%2x:0x%2x:0x%2x",
5498 __func__, pReq->staIdx, peer->mac_addr.raw[0],
5499 peer->mac_addr.raw[1], peer->mac_addr.raw[2],
5500 peer->mac_addr.raw[3], peer->mac_addr.raw[4],
5501 peer->mac_addr.raw[5]);
5502 qdf_mem_copy(peer_mac, peer->mac_addr.raw, IEEE80211_ADDR_LEN);
5503 }
5504
5505 len = sizeof(wmi_peer_info_req_cmd_fixed_param);
5506 buf = wmi_buf_alloc(wma->wmi_handle, len);
5507 if (!buf) {
5508 WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__);
5509 return QDF_STATUS_E_FAILURE;
5510 }
5511
5512 p = (uint8_t *) wmi_buf_data(buf);
5513 qdf_mem_zero(p, len);
5514 p_get_peer_info_cmd = (wmi_peer_info_req_cmd_fixed_param *) p;
5515
5516 WMITLV_SET_HDR(&p_get_peer_info_cmd->tlv_header,
5517 WMITLV_TAG_STRUC_wmi_peer_info_req_cmd_fixed_param,
5518 WMITLV_GET_STRUCT_TLVLEN
5519 (wmi_peer_info_req_cmd_fixed_param));
5520
5521 p_get_peer_info_cmd->vdev_id = vdev_id;
5522 WMI_CHAR_ARRAY_TO_MAC_ADDR(peer_mac,
5523 &p_get_peer_info_cmd->peer_mac_address);
5524
5525 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
5526 WMI_PEER_INFO_REQ_CMDID);
5527
5528 WMA_LOGE("IBSS get peer info cmd sent len: %d, vdev %d"
5529 " command id: %d, status: %d", len,
5530 p_get_peer_info_cmd->vdev_id, WMI_PEER_INFO_REQ_CMDID, ret);
5531
5532 return QDF_STATUS_SUCCESS;
5533}
5534
5535/**
5536 * wma_process_tx_fail_monitor_ind() - sends tx fail monitor cmd to target
5537 * @wma: wma handle
5538 * @pReq: tx fail monitor command params
5539 *
5540 * Return: QDF status
5541 */
5542QDF_STATUS wma_process_tx_fail_monitor_ind
5543 (tp_wma_handle wma, tAniTXFailMonitorInd *pReq)
5544{
5545 QDF_STATUS ret;
5546 int32_t vdev_id;
5547
5548 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
5549 if (vdev_id < 0) {
5550 WMA_LOGE("%s: IBSS vdev does not exist could not send fast tx fail"
5551 " monitor indication message to target", __func__);
5552 return QDF_STATUS_E_FAILURE;
5553 }
5554
5555 /* Send enable cesium command to target */
5556 WMA_LOGE("send fast tx fail monitor ind cmd target for vdevId %d val %d",
5557 vdev_id, pReq->tx_fail_count);
5558
5559 if (0 == pReq->tx_fail_count) {
5560 wma->hddTxFailCb = NULL;
5561 } else {
5562 wma->hddTxFailCb = pReq->txFailIndCallback;
5563 }
5564 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
5565 WMI_VDEV_PARAM_SET_IBSS_TX_FAIL_CNT_THR,
5566 pReq->tx_fail_count);
5567 if (ret) {
5568 WMA_LOGE("tx fail monitor failed for vdevId %d", vdev_id);
5569 return QDF_STATUS_E_FAILURE;
5570 }
5571
5572 return QDF_STATUS_SUCCESS;
5573}
5574
5575/**
5576 * wma_process_rmc_enable_ind() - enables RMC functionality in target
5577 * @wma: wma handle
5578 *
5579 * Return: QDF status
5580 */
5581QDF_STATUS wma_process_rmc_enable_ind(tp_wma_handle wma)
5582{
5583 int ret;
5584 uint8_t *p;
5585 uint16_t len;
5586 wmi_buf_t buf;
5587 int32_t vdev_id;
5588 wmi_rmc_set_mode_cmd_fixed_param *p_rmc_enable_cmd;
5589
5590 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
5591 if (vdev_id < 0) {
5592 WMA_LOGE("%s: IBSS vdev does not exist could not enable RMC",
5593 __func__);
5594 return QDF_STATUS_E_FAILURE;
5595 }
5596
5597 len = sizeof(wmi_rmc_set_mode_cmd_fixed_param);
5598 buf = wmi_buf_alloc(wma->wmi_handle, len);
5599 if (!buf) {
5600 WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__);
5601 return QDF_STATUS_E_FAILURE;
5602 }
5603
5604 p = (uint8_t *) wmi_buf_data(buf);
5605 qdf_mem_zero(p, len);
5606 p_rmc_enable_cmd = (wmi_rmc_set_mode_cmd_fixed_param *) p;
5607
5608 WMITLV_SET_HDR(&p_rmc_enable_cmd->tlv_header,
5609 WMITLV_TAG_STRUC_wmi_rmc_set_mode_cmd_fixed_param,
5610 WMITLV_GET_STRUCT_TLVLEN
5611 (wmi_rmc_set_mode_cmd_fixed_param));
5612
5613 p_rmc_enable_cmd->vdev_id = vdev_id;
5614 p_rmc_enable_cmd->enable_rmc = WMI_RMC_MODE_ENABLED;
5615
5616 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
5617 WMI_RMC_SET_MODE_CMDID);
5618
5619 WMA_LOGE("Enable RMC cmd sent len: %d, vdev %d" " command id: %d,"
5620 " status: %d", len, p_rmc_enable_cmd->vdev_id,
5621 WMI_RMC_SET_MODE_CMDID, ret);
5622
5623 return QDF_STATUS_SUCCESS;
5624}
5625
5626/**
5627 * wma_process_rmc_disable_ind() - disables rmc functionality in target
5628 * @wma: wma handle
5629 *
5630 * Return: QDF status
5631 */
5632QDF_STATUS wma_process_rmc_disable_ind(tp_wma_handle wma)
5633{
5634 int ret;
5635 uint8_t *p;
5636 uint16_t len;
5637 wmi_buf_t buf;
5638 int32_t vdev_id;
5639 wmi_rmc_set_mode_cmd_fixed_param *p_rmc_disable_cmd;
5640
5641 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
5642 if (vdev_id < 0) {
5643 WMA_LOGE("%s: IBSS vdev does not exist could not disable RMC",
5644 __func__);
5645 return QDF_STATUS_E_FAILURE;
5646 }
5647
5648 len = sizeof(wmi_rmc_set_mode_cmd_fixed_param);
5649 buf = wmi_buf_alloc(wma->wmi_handle, len);
5650 if (!buf) {
5651 WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__);
5652 return QDF_STATUS_E_FAILURE;
5653 }
5654
5655 p = (uint8_t *) wmi_buf_data(buf);
5656 qdf_mem_zero(p, len);
5657 p_rmc_disable_cmd = (wmi_rmc_set_mode_cmd_fixed_param *) p;
5658
5659 WMITLV_SET_HDR(&p_rmc_disable_cmd->tlv_header,
5660 WMITLV_TAG_STRUC_wmi_rmc_set_mode_cmd_fixed_param,
5661 WMITLV_GET_STRUCT_TLVLEN
5662 (wmi_rmc_set_mode_cmd_fixed_param));
5663
5664 p_rmc_disable_cmd->vdev_id = vdev_id;
5665 p_rmc_disable_cmd->enable_rmc = WMI_RMC_MODE_DISABLED;
5666
5667 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
5668 WMI_RMC_SET_MODE_CMDID);
5669
5670 WMA_LOGE("Disable RMC cmd sent len: %d, vdev %d" " command id: %d,"
5671 " status: %d", len, p_rmc_disable_cmd->vdev_id,
5672 WMI_RMC_SET_MODE_CMDID, ret);
5673
5674 return QDF_STATUS_SUCCESS;
5675}
5676
5677/**
5678 * wma_process_rmc_action_period_ind() - sends RMC action period to target
5679 * @wma: wma handle
5680 *
5681 * Return: QDF status
5682 */
5683QDF_STATUS wma_process_rmc_action_period_ind(tp_wma_handle wma)
5684{
5685 int ret;
5686 uint8_t *p;
5687 uint16_t len;
5688 uint32_t val;
5689 wmi_buf_t buf;
5690 int32_t vdev_id;
5691 wmi_rmc_set_action_period_cmd_fixed_param *p_rmc_cmd;
5692 struct sAniSirGlobal *mac = cds_get_context(QDF_MODULE_ID_PE);
5693
5694 if (NULL == mac) {
5695 WMA_LOGE("%s: MAC mac does not exist", __func__);
5696 return QDF_STATUS_E_FAILURE;
5697 }
5698
5699 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
5700 if (vdev_id < 0) {
5701 WMA_LOGE("%s: IBSS vdev does not exist could not send"
5702 " RMC action period to target", __func__);
5703 return QDF_STATUS_E_FAILURE;
5704 }
5705
5706 len = sizeof(wmi_rmc_set_action_period_cmd_fixed_param);
5707 buf = wmi_buf_alloc(wma->wmi_handle, len);
5708 if (!buf) {
5709 WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__);
5710 return QDF_STATUS_E_FAILURE;
5711 }
5712
5713 p = (uint8_t *) wmi_buf_data(buf);
5714 qdf_mem_zero(p, len);
5715 p_rmc_cmd = (wmi_rmc_set_action_period_cmd_fixed_param *) p;
5716
5717 WMITLV_SET_HDR(&p_rmc_cmd->tlv_header,
5718 WMITLV_TAG_STRUC_wmi_rmc_set_action_period_cmd_fixed_param,
5719 WMITLV_GET_STRUCT_TLVLEN
5720 (wmi_rmc_set_action_period_cmd_fixed_param));
5721
5722 if (wlan_cfg_get_int(mac, WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY, &val)
5723 != eSIR_SUCCESS) {
5724 WMA_LOGE("Failed to get value for RMC action period using default");
5725 val = WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_STADEF;
5726 }
5727
5728 p_rmc_cmd->vdev_id = vdev_id;
5729 p_rmc_cmd->periodicity_msec = val;
5730
5731 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
5732 WMI_RMC_SET_ACTION_PERIOD_CMDID);
5733
5734 WMA_LOGE("RMC action period %d cmd sent len: %d, vdev %d"
5735 " command id: %d, status: %d", p_rmc_cmd->periodicity_msec,
5736 len, p_rmc_cmd->vdev_id, WMI_RMC_SET_ACTION_PERIOD_CMDID, ret);
5737
5738 return QDF_STATUS_SUCCESS;
5739}
5740
5741/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005742 * wma_process_add_periodic_tx_ptrn_ind - add periodic tx ptrn
5743 * @handle: wma handle
5744 * @pAddPeriodicTxPtrnParams: tx ptrn params
5745 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305746 * Retrun: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005747 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305748QDF_STATUS wma_process_add_periodic_tx_ptrn_ind(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005749 tSirAddPeriodicTxPtrn *
5750 pAddPeriodicTxPtrnParams)
5751{
5752 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Mohit Khanna0fe61672016-05-19 16:53:39 -07005753 struct periodic_tx_pattern *params_ptr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005754 uint8_t vdev_id;
Mohit Khanna0fe61672016-05-19 16:53:39 -07005755 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005756
5757 if (!wma_handle || !wma_handle->wmi_handle) {
5758 WMA_LOGE("%s: WMA is closed, can not issue fw add pattern cmd",
5759 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305760 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005761 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005762
Mohit Khanna0fe61672016-05-19 16:53:39 -07005763 params_ptr = qdf_mem_malloc(sizeof(*params_ptr));
5764
5765 if (!params_ptr) {
5766 WMA_LOGE(
5767 "%s: unable to allocate memory for periodic_tx_pattern",
5768 __func__);
5769 return QDF_STATUS_E_NOMEM;
5770 }
5771
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005772 if (!wma_find_vdev_by_addr(wma_handle,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005773 pAddPeriodicTxPtrnParams->mac_address.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005774 &vdev_id)) {
5775 WMA_LOGE("%s: Failed to find vdev id for %pM", __func__,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005776 pAddPeriodicTxPtrnParams->mac_address.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305777 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005778 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005779
Mohit Khanna0fe61672016-05-19 16:53:39 -07005780 params_ptr->ucPtrnId = pAddPeriodicTxPtrnParams->ucPtrnId;
5781 params_ptr->ucPtrnSize = pAddPeriodicTxPtrnParams->ucPtrnSize;
5782 params_ptr->usPtrnIntervalMs =
5783 pAddPeriodicTxPtrnParams->usPtrnIntervalMs;
5784 qdf_mem_copy(&params_ptr->mac_address,
Himanshu Agarwal44195412016-03-09 13:03:54 +05305785 &pAddPeriodicTxPtrnParams->mac_address,
5786 sizeof(struct qdf_mac_addr));
Mohit Khanna0fe61672016-05-19 16:53:39 -07005787 qdf_mem_copy(params_ptr->ucPattern,
5788 pAddPeriodicTxPtrnParams->ucPattern,
5789 params_ptr->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005790
Mohit Khanna0fe61672016-05-19 16:53:39 -07005791 status = wmi_unified_process_add_periodic_tx_ptrn_cmd(
5792 wma_handle->wmi_handle, params_ptr, vdev_id);
5793
5794 qdf_mem_free(params_ptr);
5795 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005796}
5797
5798/**
5799 * wma_process_del_periodic_tx_ptrn_ind - del periodic tx ptrn
5800 * @handle: wma handle
5801 * @pDelPeriodicTxPtrnParams: tx ptrn params
5802 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305803 * Retrun: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005804 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305805QDF_STATUS wma_process_del_periodic_tx_ptrn_ind(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005806 tSirDelPeriodicTxPtrn *
5807 pDelPeriodicTxPtrnParams)
5808{
5809 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005810 uint8_t vdev_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005811
5812 if (!wma_handle || !wma_handle->wmi_handle) {
5813 WMA_LOGE("%s: WMA is closed, can not issue Del Pattern cmd",
5814 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305815 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005816 }
Himanshu Agarwal44195412016-03-09 13:03:54 +05305817
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005818 if (!wma_find_vdev_by_addr(wma_handle,
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08005819 pDelPeriodicTxPtrnParams->mac_address.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005820 &vdev_id)) {
5821 WMA_LOGE("%s: Failed to find vdev id for %pM", __func__,
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08005822 pDelPeriodicTxPtrnParams->mac_address.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305823 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005824 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005825
Himanshu Agarwal44195412016-03-09 13:03:54 +05305826 return wmi_unified_process_del_periodic_tx_ptrn_cmd(
5827 wma_handle->wmi_handle, vdev_id,
5828 pDelPeriodicTxPtrnParams->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005829}
5830
5831#ifdef WLAN_FEATURE_STATS_EXT
5832/**
5833 * wma_stats_ext_req() - request ext stats from fw
5834 * @wma_ptr: wma handle
5835 * @preq: stats ext params
5836 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305837 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005838 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305839QDF_STATUS wma_stats_ext_req(void *wma_ptr, tpStatsExtRequest preq)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005840{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005841 tp_wma_handle wma = (tp_wma_handle) wma_ptr;
Krishna Kumaar Natarajan1b909d72016-06-06 15:02:18 -07005842 struct stats_ext_params *params;
5843 size_t params_len;
5844 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005845
Himanshu Agarwal44195412016-03-09 13:03:54 +05305846 if (!wma) {
5847 WMA_LOGE("%s: wma handle is NULL", __func__);
5848 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005849 }
5850
Krishna Kumaar Natarajan1b909d72016-06-06 15:02:18 -07005851 params_len = sizeof(*params) + preq->request_data_len;
5852 params = qdf_mem_malloc(params_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005853
Krishna Kumaar Natarajan1b909d72016-06-06 15:02:18 -07005854 if (params == NULL) {
5855 WMA_LOGE(FL("memory allocation failed"));
5856 return QDF_STATUS_E_NOMEM;
5857 }
5858
5859 params->vdev_id = preq->vdev_id;
5860 params->request_data_len = preq->request_data_len;
5861 if (preq->request_data_len > 0)
5862 qdf_mem_copy(params->request_data, preq->request_data,
5863 params->request_data_len);
5864
5865 status = wmi_unified_stats_ext_req_cmd(wma->wmi_handle, params);
5866 qdf_mem_free(params);
5867
5868 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005869}
5870
5871#endif /* WLAN_FEATURE_STATS_EXT */
5872
5873#ifdef WLAN_FEATURE_EXTWOW_SUPPORT
5874/**
5875 * wma_send_status_of_ext_wow() - send ext wow status to SME
5876 * @wma: wma handle
5877 * @status: status
5878 *
5879 * Return: none
5880 */
5881static void wma_send_status_of_ext_wow(tp_wma_handle wma, bool status)
5882{
5883 tSirReadyToExtWoWInd *ready_to_extwow;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305884 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005885 cds_msg_t cds_msg;
5886 uint8_t len;
5887
5888 WMA_LOGD("Posting ready to suspend indication to umac");
5889
5890 len = sizeof(tSirReadyToExtWoWInd);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305891 ready_to_extwow = (tSirReadyToExtWoWInd *) qdf_mem_malloc(len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005892
5893 if (NULL == ready_to_extwow) {
5894 WMA_LOGE("%s: Memory allocation failure", __func__);
5895 return;
5896 }
5897
5898 ready_to_extwow->mesgType = eWNI_SME_READY_TO_EXTWOW_IND;
5899 ready_to_extwow->mesgLen = len;
5900 ready_to_extwow->status = status;
5901
5902 cds_msg.type = eWNI_SME_READY_TO_EXTWOW_IND;
5903 cds_msg.bodyptr = (void *)ready_to_extwow;
5904 cds_msg.bodyval = 0;
5905
5906 vstatus = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305907 if (vstatus != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005908 WMA_LOGE("Failed to post ready to suspend");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305909 qdf_mem_free(ready_to_extwow);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005910 }
5911}
5912
5913/**
5914 * wma_enable_ext_wow() - enable ext wow in fw
5915 * @wma: wma handle
5916 * @params: ext wow params
5917 *
5918 * Return:0 for success or error code
5919 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05305920QDF_STATUS wma_enable_ext_wow(tp_wma_handle wma, tpSirExtWoWParams params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005921{
Himanshu Agarwal44195412016-03-09 13:03:54 +05305922 struct ext_wow_params wow_params = {0};
5923 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005924
Himanshu Agarwal44195412016-03-09 13:03:54 +05305925 if (!wma) {
5926 WMA_LOGE("%s: wma handle is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305927 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005928 }
5929
Himanshu Agarwal44195412016-03-09 13:03:54 +05305930 wow_params.vdev_id = params->vdev_id;
5931 wow_params.type = (enum wmi_ext_wow_type) params->type;
5932 wow_params.wakeup_pin_num = params->wakeup_pin_num;
5933
5934 status = wmi_unified_enable_ext_wow_cmd(wma->wmi_handle,
5935 &wow_params);
5936 if (QDF_IS_STATUS_ERROR(status))
5937 return status;
5938
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005939 wma_send_status_of_ext_wow(wma, true);
Himanshu Agarwal44195412016-03-09 13:03:54 +05305940 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005941
5942}
5943
5944/**
5945 * wma_set_app_type1_params_in_fw() - set app type1 params in fw
5946 * @wma: wma handle
5947 * @appType1Params: app type1 params
5948 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305949 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005950 */
5951int wma_set_app_type1_params_in_fw(tp_wma_handle wma,
5952 tpSirAppType1Params appType1Params)
5953{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005954 int ret;
5955
Govind Singhaa64c242016-03-08 11:31:49 +05305956 ret = wmi_unified_app_type1_params_in_fw_cmd(wma->wmi_handle,
5957 (struct app_type1_params *)appType1Params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005958 if (ret) {
5959 WMA_LOGE("%s: Failed to set APP TYPE1 PARAMS", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305960 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005961 }
5962
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305963 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005964}
5965
5966/**
5967 * wma_set_app_type2_params_in_fw() - set app type2 params in fw
5968 * @wma: wma handle
5969 * @appType2Params: app type2 params
5970 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305971 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005972 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05305973QDF_STATUS wma_set_app_type2_params_in_fw(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005974 tpSirAppType2Params appType2Params)
5975{
Himanshu Agarwal44195412016-03-09 13:03:54 +05305976 struct app_type2_params params = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005977
Himanshu Agarwal44195412016-03-09 13:03:54 +05305978 if (!wma) {
5979 WMA_LOGE("%s: wma handle is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305980 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005981 }
5982
Himanshu Agarwal44195412016-03-09 13:03:54 +05305983 params.vdev_id = appType2Params->vdev_id;
5984 params.rc4_key_len = appType2Params->rc4_key_len;
5985 qdf_mem_copy(params.rc4_key, appType2Params->rc4_key, 16);
5986 params.ip_id = appType2Params->ip_id;
5987 params.ip_device_ip = appType2Params->ip_device_ip;
5988 params.ip_server_ip = appType2Params->ip_server_ip;
5989 params.tcp_src_port = appType2Params->tcp_src_port;
5990 params.tcp_dst_port = appType2Params->tcp_dst_port;
5991 params.tcp_seq = appType2Params->tcp_seq;
5992 params.tcp_ack_seq = appType2Params->tcp_ack_seq;
5993 params.keepalive_init = appType2Params->keepalive_init;
5994 params.keepalive_min = appType2Params->keepalive_min;
5995 params.keepalive_max = appType2Params->keepalive_max;
5996 params.keepalive_inc = appType2Params->keepalive_inc;
5997 params.tcp_tx_timeout_val = appType2Params->tcp_tx_timeout_val;
5998 params.tcp_rx_timeout_val = appType2Params->tcp_rx_timeout_val;
5999 qdf_mem_copy(&params.gateway_mac, &appType2Params->gateway_mac,
6000 sizeof(struct qdf_mac_addr));
6001
6002 return wmi_unified_set_app_type2_params_in_fw_cmd(wma->wmi_handle,
6003 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006004
6005}
6006#endif /* WLAN_FEATURE_EXTWOW_SUPPORT */
6007
6008#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
6009/**
6010 * wma_auto_shutdown_event_handler() - process auto shutdown timer trigger
6011 * @handle: wma handle
6012 * @event: event buffer
6013 * @len: buffer length
6014 *
6015 * Return: 0 for success or error code
6016 */
6017int wma_auto_shutdown_event_handler(void *handle, uint8_t *event,
6018 uint32_t len)
6019{
6020 wmi_host_auto_shutdown_event_fixed_param *wmi_auto_sh_evt;
6021 WMI_HOST_AUTO_SHUTDOWN_EVENTID_param_tlvs *param_buf =
6022 (WMI_HOST_AUTO_SHUTDOWN_EVENTID_param_tlvs *)
6023 event;
6024
6025 if (!param_buf || !param_buf->fixed_param) {
6026 WMA_LOGE("%s:%d: Invalid Auto shutdown timer evt", __func__,
6027 __LINE__);
6028 return -EINVAL;
6029 }
6030
6031 wmi_auto_sh_evt = param_buf->fixed_param;
6032
6033 if (wmi_auto_sh_evt->shutdown_reason
6034 != WMI_HOST_AUTO_SHUTDOWN_REASON_TIMER_EXPIRY) {
6035 WMA_LOGE("%s:%d: Invalid Auto shutdown timer evt", __func__,
6036 __LINE__);
6037 return -EINVAL;
6038 }
6039
6040 WMA_LOGD("%s:%d: Auto Shutdown Evt: %d", __func__, __LINE__,
6041 wmi_auto_sh_evt->shutdown_reason);
6042 return wma_post_auto_shutdown_msg();
6043}
6044
6045/**
6046 * wma_set_auto_shutdown_timer_req() - sets auto shutdown timer in firmware
6047 * @wma: wma handle
6048 * @auto_sh_cmd: auto shutdown timer value
6049 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306050 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006051 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306052QDF_STATUS wma_set_auto_shutdown_timer_req(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006053 tSirAutoShutdownCmdParams *
6054 auto_sh_cmd)
6055{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006056 if (auto_sh_cmd == NULL) {
6057 WMA_LOGE("%s : Invalid Autoshutdown cfg cmd", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306058 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006059 }
6060
Himanshu Agarwal44195412016-03-09 13:03:54 +05306061 return wmi_unified_set_auto_shutdown_timer_cmd(wma_handle->wmi_handle,
6062 auto_sh_cmd->timer_val);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006063}
6064#endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
6065
6066#ifdef WLAN_FEATURE_NAN
6067/**
6068 * wma_nan_req() - to send nan request to target
6069 * @wma: wma_handle
6070 * @nan_req: request data which will be non-null
6071 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306072 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006073 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306074QDF_STATUS wma_nan_req(void *wma_ptr, tpNanRequest nan_req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006075{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006076 tp_wma_handle wma_handle = (tp_wma_handle) wma_ptr;
Krishna Kumaar Natarajan1b909d72016-06-06 15:02:18 -07006077 struct nan_req_params *params;
6078 size_t params_len;
6079 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006080
Himanshu Agarwal44195412016-03-09 13:03:54 +05306081 if (!wma_handle) {
6082 WMA_LOGE("%s: wma handle is NULL", __func__);
6083 return QDF_STATUS_E_FAILURE;
6084 }
Krishna Kumaar Natarajan1b909d72016-06-06 15:02:18 -07006085
6086 params_len = sizeof(*params) + nan_req->request_data_len;
6087 params = qdf_mem_malloc(params_len);
6088
6089 if (params == NULL) {
6090 WMA_LOGE(FL("memory allocation failed"));
6091 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006092 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006093
Krishna Kumaar Natarajan1b909d72016-06-06 15:02:18 -07006094 params->request_data_len = nan_req->request_data_len;
6095 if (params->request_data_len > 0)
6096 qdf_mem_copy(params->request_data, nan_req->request_data,
6097 params->request_data_len);
Himanshu Agarwal44195412016-03-09 13:03:54 +05306098
Krishna Kumaar Natarajan1b909d72016-06-06 15:02:18 -07006099 status = wmi_unified_nan_req_cmd(wma_handle->wmi_handle, params);
6100 qdf_mem_free(params);
6101
6102 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006103}
6104#endif /* WLAN_FEATURE_NAN */
6105
6106#ifdef DHCP_SERVER_OFFLOAD
6107/**
6108 * wma_process_dhcpserver_offload() - enable DHCP server offload
6109 * @wma_handle: wma handle
6110 * @pDhcpSrvOffloadInfo: DHCP server offload info
6111 *
6112 * Return: 0 for success or error code
6113 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05306114QDF_STATUS wma_process_dhcpserver_offload(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006115 tSirDhcpSrvOffloadInfo *
6116 pDhcpSrvOffloadInfo)
6117{
Himanshu Agarwal44195412016-03-09 13:03:54 +05306118 struct dhcp_offload_info_params params = {0};
6119 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006120
Himanshu Agarwal44195412016-03-09 13:03:54 +05306121 if (!wma_handle) {
6122 WMA_LOGE("%s: wma handle is NULL", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006123 return -EIO;
6124 }
Himanshu Agarwal44195412016-03-09 13:03:54 +05306125
6126 params.vdev_id = pDhcpSrvOffloadInfo->vdev_id;
6127 params.dhcpSrvOffloadEnabled =
6128 pDhcpSrvOffloadInfo->dhcpSrvOffloadEnabled;
6129 params.dhcpClientNum = pDhcpSrvOffloadInfo->dhcpClientNum;
6130 params.dhcpSrvIP = pDhcpSrvOffloadInfo->;
6131
6132 status = wmi_unified_process_dhcpserver_offload_cmd(
6133 wma_handle->wmi_handle, &params);
6134 if (QDF_IS_STATUS_ERROR(status))
6135 return status;
6136
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006137 WMA_LOGD("Set dhcp server offload to vdevId %d",
6138 pDhcpSrvOffloadInfo->vdev_id);
Himanshu Agarwal44195412016-03-09 13:03:54 +05306139 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006140}
6141#endif /* DHCP_SERVER_OFFLOAD */
6142
6143#ifdef WLAN_FEATURE_GPIO_LED_FLASHING
6144/**
6145 * wma_set_led_flashing() - set led flashing in fw
6146 * @wma_handle: wma handle
6147 * @flashing: flashing request
6148 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306149 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006150 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306151QDF_STATUS wma_set_led_flashing(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006152 tSirLedFlashingReq *flashing)
6153{
Govind Singhaa64c242016-03-08 11:31:49 +05306154 struct flashing_req_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006155
6156 if (!wma_handle || !wma_handle->wmi_handle) {
6157 WMA_LOGE(FL("WMA is closed, can not issue cmd"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306158 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006159 }
6160 if (!flashing) {
6161 WMA_LOGE(FL("invalid parameter: flashing"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306162 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006163 }
Govind Singhaa64c242016-03-08 11:31:49 +05306164 cmd.req_id = flashing->reqId;
6165 cmd.pattern_id = flashing->pattern_id;
6166 cmd.led_x0 = flashing->led_x0;
6167 cmd.led_x1 = flashing->led_x1;
6168 status = wmi_unified_set_led_flashing_cmd(wma_handle->wmi_handle,
6169 &cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006170 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306171 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006172 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306173 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006174}
6175#endif /* WLAN_FEATURE_GPIO_LED_FLASHING */
6176
6177#ifdef FEATURE_WLAN_CH_AVOID
6178/**
6179 * wma_channel_avoid_evt_handler() - process channel to avoid event from FW.
6180 * @handle: wma handle
6181 * @event: event buffer
6182 * @len: buffer length
6183 *
6184 * Return: 0 for success or error code
6185 */
6186int wma_channel_avoid_evt_handler(void *handle, uint8_t *event,
6187 uint32_t len)
6188{
6189 wmi_avoid_freq_ranges_event_fixed_param *afr_fixed_param;
6190 wmi_avoid_freq_range_desc *afr_desc;
6191 uint32_t num_freq_ranges, freq_range_idx;
6192 tSirChAvoidIndType *sca_indication;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306193 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006194 cds_msg_t sme_msg = { 0 };
6195 WMI_WLAN_FREQ_AVOID_EVENTID_param_tlvs *param_buf =
6196 (WMI_WLAN_FREQ_AVOID_EVENTID_param_tlvs *) event;
6197
6198 if (!param_buf) {
6199 WMA_LOGE("Invalid channel avoid event buffer");
6200 return -EINVAL;
6201 }
6202
6203 afr_fixed_param = param_buf->fixed_param;
6204 if (!afr_fixed_param) {
6205 WMA_LOGE("Invalid channel avoid event fixed param buffer");
6206 return -EINVAL;
6207 }
6208
6209 num_freq_ranges =
6210 (afr_fixed_param->num_freq_ranges >
6211 SIR_CH_AVOID_MAX_RANGE) ? SIR_CH_AVOID_MAX_RANGE :
6212 afr_fixed_param->num_freq_ranges;
6213
6214 WMA_LOGD("Channel avoid event received with %d ranges",
6215 num_freq_ranges);
6216 for (freq_range_idx = 0; freq_range_idx < num_freq_ranges;
6217 freq_range_idx++) {
6218 afr_desc = (wmi_avoid_freq_range_desc *)
6219 ((void *)param_buf->avd_freq_range +
6220 freq_range_idx * sizeof(wmi_avoid_freq_range_desc));
6221
6222 WMA_LOGD("range %d: tlv id = %u, start freq = %u, end freq = %u",
6223 freq_range_idx, afr_desc->tlv_header, afr_desc->start_freq,
6224 afr_desc->end_freq);
6225 }
6226
6227 sca_indication = (tSirChAvoidIndType *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306228 qdf_mem_malloc(sizeof(tSirChAvoidIndType));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006229 if (!sca_indication) {
6230 WMA_LOGE("Invalid channel avoid indication buffer");
6231 return -EINVAL;
6232 }
6233
6234 sca_indication->avoid_range_count = num_freq_ranges;
6235 for (freq_range_idx = 0; freq_range_idx < num_freq_ranges;
6236 freq_range_idx++) {
6237 afr_desc = (wmi_avoid_freq_range_desc *)
6238 ((void *)param_buf->avd_freq_range +
6239 freq_range_idx * sizeof(wmi_avoid_freq_range_desc));
6240 sca_indication->avoid_freq_range[freq_range_idx].start_freq =
6241 afr_desc->start_freq;
6242 sca_indication->avoid_freq_range[freq_range_idx].end_freq =
6243 afr_desc->end_freq;
6244 }
6245
6246 sme_msg.type = eWNI_SME_CH_AVOID_IND;
6247 sme_msg.bodyptr = sca_indication;
6248 sme_msg.bodyval = 0;
6249
Anurag Chouhan6d760662016-02-20 16:05:43 +05306250 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306251 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006252 WMA_LOGE("Fail to post eWNI_SME_CH_AVOID_IND msg to SME");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306253 qdf_mem_free(sca_indication);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006254 return -EINVAL;
6255 }
6256
6257 return 0;
6258}
6259
6260/**
6261 * wma_process_ch_avoid_update_req() - handles channel avoid update request
6262 * @wma_handle: wma handle
6263 * @ch_avoid_update_req: channel avoid update params
6264 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306265 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006266 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306267QDF_STATUS wma_process_ch_avoid_update_req(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006268 tSirChAvoidUpdateReq *
6269 ch_avoid_update_req)
6270{
Himanshu Agarwal44195412016-03-09 13:03:54 +05306271 QDF_STATUS status;
6272 if (!wma_handle) {
6273 WMA_LOGE("%s: wma handle is NULL", __func__);
6274 return QDF_STATUS_E_FAILURE;
6275 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006276 if (ch_avoid_update_req == NULL) {
6277 WMA_LOGE("%s : ch_avoid_update_req is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306278 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006279 }
6280
6281 WMA_LOGI("%s: WMA --> WMI_CHAN_AVOID_UPDATE", __func__);
6282
Himanshu Agarwal44195412016-03-09 13:03:54 +05306283 status = wmi_unified_process_ch_avoid_update_cmd(
6284 wma_handle->wmi_handle);
6285 if (QDF_IS_STATUS_ERROR(status))
6286 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006287
6288 WMA_LOGI("%s: WMA --> WMI_CHAN_AVOID_UPDATE sent through WMI",
6289 __func__);
Himanshu Agarwal44195412016-03-09 13:03:54 +05306290 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006291}
6292#endif /* FEATURE_WLAN_CH_AVOID */
6293
6294/**
6295 * wma_set_reg_domain() - set reg domain
6296 * @clientCtxt: client context
6297 * @regId: reg id
6298 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306299 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006300 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306301QDF_STATUS wma_set_reg_domain(void *clientCtxt, v_REGDOMAIN_t regId)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006302{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306303 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006304 cds_set_reg_domain(clientCtxt, regId))
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306305 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006306
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306307 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006308}
6309
6310/**
6311 * wma_send_regdomain_info_to_fw() - send regdomain info to fw
6312 * @reg_dmn: reg domain
6313 * @regdmn2G: 2G reg domain
6314 * @regdmn5G: 5G reg domain
6315 * @ctl2G: 2G test limit
6316 * @ctl5G: 5G test limit
6317 *
6318 * Return: none
6319 */
6320void wma_send_regdomain_info_to_fw(uint32_t reg_dmn, uint16_t regdmn2G,
6321 uint16_t regdmn5G, int8_t ctl2G,
6322 int8_t ctl5G)
6323{
Anurag Chouhan6d760662016-02-20 16:05:43 +05306324 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006325 int32_t cck_mask_val = 0;
Govind Singhd76a5b02016-03-08 15:12:14 +05306326 struct pdev_params pdev_param = {0};
Himanshu Agarwal44195412016-03-09 13:03:54 +05306327 QDF_STATUS ret = QDF_STATUS_SUCCESS;
6328 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006329
6330 if (NULL == wma) {
6331 WMA_LOGE("%s: wma context is NULL", __func__);
6332 return;
6333 }
6334
Himanshu Agarwal44195412016-03-09 13:03:54 +05306335 status = wmi_unified_send_regdomain_info_to_fw_cmd(wma->wmi_handle,
6336 reg_dmn, regdmn2G, regdmn5G, ctl2G, ctl5G);
6337 if (status == QDF_STATUS_E_NOMEM)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006338 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006339
Amar Singhal76b41322015-12-09 14:39:17 -08006340 if ((((reg_dmn & ~COUNTRY_ERD_FLAG) == CTRY_JAPAN14) ||
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006341 ((reg_dmn & ~COUNTRY_ERD_FLAG) == CTRY_KOREA_ROC)) &&
6342 (true == wma->tx_chain_mask_cck))
6343 cck_mask_val = 1;
6344
6345 cck_mask_val |= (wma->self_gen_frm_pwr << 16);
Govind Singhd76a5b02016-03-08 15:12:14 +05306346 pdev_param.param_id = WMI_PDEV_PARAM_TX_CHAIN_MASK_CCK;
6347 pdev_param.param_value = cck_mask_val;
6348 ret = wmi_unified_pdev_param_send(wma->wmi_handle,
6349 &pdev_param,
6350 WMA_WILDCARD_PDEV_ID);
6351
Himanshu Agarwal44195412016-03-09 13:03:54 +05306352 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006353 WMA_LOGE("failed to set PDEV tx_chain_mask_cck %d",
6354 ret);
6355
6356 return;
6357}
6358
6359/**
Houston Hoffmana76591b2015-11-10 16:52:05 -08006360 * wma_post_runtime_resume_msg() - post the resume request
6361 * @handle: validated wma handle
6362 *
6363 * request the MC thread unpaus the vdev and set resume dtim
6364 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306365 * Return: qdf status of the mq post
Houston Hoffmana76591b2015-11-10 16:52:05 -08006366 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306367static QDF_STATUS wma_post_runtime_resume_msg(WMA_HANDLE handle)
Houston Hoffmana76591b2015-11-10 16:52:05 -08006368{
6369 cds_msg_t resume_msg;
Houston Hoffmanc45db892015-11-13 19:59:25 -08006370 QDF_STATUS status;
6371 tp_wma_handle wma = (tp_wma_handle) handle;
6372
6373 qdf_runtime_pm_prevent_suspend(wma->wma_runtime_resume_lock);
Houston Hoffmana76591b2015-11-10 16:52:05 -08006374
6375 resume_msg.bodyptr = NULL;
6376 resume_msg.type = WMA_RUNTIME_PM_RESUME_IND;
Houston Hoffmanc45db892015-11-13 19:59:25 -08006377
6378 status = cds_mq_post_message(QDF_MODULE_ID_WMA, &resume_msg);
6379
6380 if (!QDF_IS_STATUS_SUCCESS(status)) {
6381 WMA_LOGE("Failed to post Runtime PM Resume IND to VOS");
6382 qdf_runtime_pm_allow_suspend(wma->wma_runtime_resume_lock);
6383 }
6384
6385 return status;
Houston Hoffmana76591b2015-11-10 16:52:05 -08006386}
6387
6388/**
6389 * wma_post_runtime_suspend_msg() - post the suspend request
6390 * @handle: validated wma handle
6391 *
6392 * Requests for offloads to be configured for runtime suspend
6393 * on the MC thread
6394 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306395 * Return QDF_STATUS_E_AGAIN in case of timeout or QDF_STATUS_SUCCESS
Houston Hoffmana76591b2015-11-10 16:52:05 -08006396 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306397static QDF_STATUS wma_post_runtime_suspend_msg(WMA_HANDLE handle)
Houston Hoffmana76591b2015-11-10 16:52:05 -08006398{
6399 cds_msg_t cds_msg;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306400 QDF_STATUS qdf_status;
Houston Hoffmana76591b2015-11-10 16:52:05 -08006401 tp_wma_handle wma = (tp_wma_handle) handle;
6402
Anurag Chouhance0dc992016-02-16 18:18:03 +05306403 qdf_event_reset(&wma->runtime_suspend);
Houston Hoffmana76591b2015-11-10 16:52:05 -08006404
6405 cds_msg.bodyptr = NULL;
6406 cds_msg.type = WMA_RUNTIME_PM_SUSPEND_IND;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306407 qdf_status = cds_mq_post_message(QDF_MODULE_ID_WMA, &cds_msg);
Houston Hoffmana76591b2015-11-10 16:52:05 -08006408
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306409 if (qdf_status != QDF_STATUS_SUCCESS)
Houston Hoffmana76591b2015-11-10 16:52:05 -08006410 goto failure;
6411
Anurag Chouhance0dc992016-02-16 18:18:03 +05306412 if (qdf_wait_single_event(&wma->runtime_suspend,
Houston Hoffmana76591b2015-11-10 16:52:05 -08006413 WMA_TGT_SUSPEND_COMPLETE_TIMEOUT) !=
Anurag Chouhance0dc992016-02-16 18:18:03 +05306414 QDF_STATUS_SUCCESS) {
Houston Hoffmana76591b2015-11-10 16:52:05 -08006415 WMA_LOGE("Failed to get runtime suspend event");
Houston Hoffmanc45db892015-11-13 19:59:25 -08006416 goto msg_timed_out;
Houston Hoffmana76591b2015-11-10 16:52:05 -08006417 }
6418
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306419 return QDF_STATUS_SUCCESS;
Houston Hoffmana76591b2015-11-10 16:52:05 -08006420
Houston Hoffmanc45db892015-11-13 19:59:25 -08006421msg_timed_out:
6422 wma_post_runtime_resume_msg(wma);
Houston Hoffmana76591b2015-11-10 16:52:05 -08006423failure:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306424 return QDF_STATUS_E_AGAIN;
Houston Hoffmana76591b2015-11-10 16:52:05 -08006425}
6426
6427/**
6428 * __wma_bus_suspend(): handles bus suspend for wma
6429 * @type: is this suspend part of runtime suspend or system suspend?
6430 *
6431 * Bails if a scan is in progress.
6432 * Calls the appropriate handlers based on configuration and event.
6433 *
6434 * Return: 0 for success or error code
6435 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05306436static int __wma_bus_suspend(enum qdf_suspend_type type)
Houston Hoffmana76591b2015-11-10 16:52:05 -08006437{
Anurag Chouhan6d760662016-02-20 16:05:43 +05306438 WMA_HANDLE handle = cds_get_context(QDF_MODULE_ID_WMA);
Houston Hoffmana76591b2015-11-10 16:52:05 -08006439 if (NULL == handle) {
6440 WMA_LOGE("%s: wma context is NULL", __func__);
6441 return -EFAULT;
6442 }
6443
6444 if (wma_check_scan_in_progress(handle)) {
6445 WMA_LOGE("%s: Scan in progress. Aborting suspend", __func__);
6446 return -EBUSY;
6447 }
6448
Anurag Chouhan6d760662016-02-20 16:05:43 +05306449 if (type == QDF_RUNTIME_SUSPEND) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306450 QDF_STATUS status = wma_post_runtime_suspend_msg(handle);
Houston Hoffmana76591b2015-11-10 16:52:05 -08006451 if (status)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306452 return qdf_status_to_os_return(status);
Houston Hoffmana76591b2015-11-10 16:52:05 -08006453 }
6454
Anurag Chouhan6d760662016-02-20 16:05:43 +05306455 if (type == QDF_SYSTEM_SUSPEND)
Dustin Brown2d228232016-09-22 15:06:19 -07006456 WMA_LOGI("%s: wow mode selected %d", __func__,
Houston Hoffmana76591b2015-11-10 16:52:05 -08006457 wma_is_wow_mode_selected(handle));
6458
6459 if (wma_is_wow_mode_selected(handle)) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306460 QDF_STATUS status = wma_enable_wow_in_fw(handle);
6461 return qdf_status_to_os_return(status);
Houston Hoffmana76591b2015-11-10 16:52:05 -08006462 }
6463
6464 return wma_suspend_target(handle, 0);
6465}
6466
6467/**
6468 * wma_runtime_suspend() - handles runtime suspend request from hdd
6469 *
6470 * Calls the appropriate handler based on configuration and event.
6471 * Last busy marking should prevent race conditions between processing
6472 * of asyncronous fw events and the running of runtime suspend.
6473 * (eg. last busy marking should guarantee that any auth requests have
6474 * been processed)
6475 * Events comming from the host are not protected, but aren't expected
6476 * to be an issue.
6477 *
6478 * Return: 0 for success or error code
6479 */
6480int wma_runtime_suspend(void)
6481{
Anurag Chouhan6d760662016-02-20 16:05:43 +05306482 return __wma_bus_suspend(QDF_RUNTIME_SUSPEND);
Houston Hoffmana76591b2015-11-10 16:52:05 -08006483}
6484
6485/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006486 * wma_bus_suspend() - handles bus suspend request from hdd
6487 *
6488 * Calls the appropriate handler based on configuration and event
6489 *
6490 * Return: 0 for success or error code
6491 */
6492int wma_bus_suspend(void)
6493{
Houston Hoffmana76591b2015-11-10 16:52:05 -08006494
Anurag Chouhan6d760662016-02-20 16:05:43 +05306495 return __wma_bus_suspend(QDF_SYSTEM_SUSPEND);
Houston Hoffmana76591b2015-11-10 16:52:05 -08006496}
6497
6498/**
6499 * __wma_bus_resume() - bus resume for wma
6500 *
6501 * does the part of the bus resume common to bus and system suspend
6502 *
6503 * Return: os error code.
6504 */
6505int __wma_bus_resume(WMA_HANDLE handle)
6506{
6507 bool wow_mode = wma_is_wow_mode_selected(handle);
Rajeev Kumar4c426622016-08-25 14:51:42 -07006508 tp_wma_handle wma = handle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306509 QDF_STATUS status;
Houston Hoffmana76591b2015-11-10 16:52:05 -08006510
Dustin Brown2d228232016-09-22 15:06:19 -07006511 WMA_LOGI("%s: wow mode %d", __func__, wow_mode);
Houston Hoffmana76591b2015-11-10 16:52:05 -08006512
Rajeev Kumar4c426622016-08-25 14:51:42 -07006513 wma->wow_initial_wake_up = false;
6514
Houston Hoffmana76591b2015-11-10 16:52:05 -08006515 if (!wow_mode)
Rajeev Kumar9be537e2016-04-25 17:35:33 -07006516 return qdf_status_to_os_return(wma_resume_target(handle));
Houston Hoffmana76591b2015-11-10 16:52:05 -08006517
6518 status = wma_disable_wow_in_fw(handle);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306519 return qdf_status_to_os_return(status);
Houston Hoffmana76591b2015-11-10 16:52:05 -08006520}
6521
6522/**
6523 * wma_runtime_resume() - do the runtime resume operation for wma
6524 *
6525 * Return: os error code.
6526 */
6527int wma_runtime_resume(void)
6528{
6529 int ret;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306530 QDF_STATUS status;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306531 WMA_HANDLE handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006532 if (NULL == handle) {
6533 WMA_LOGE("%s: wma context is NULL", __func__);
6534 return -EFAULT;
6535 }
6536
Houston Hoffmana76591b2015-11-10 16:52:05 -08006537 ret = __wma_bus_resume(handle);
6538 if (ret)
6539 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006540
Houston Hoffmana76591b2015-11-10 16:52:05 -08006541 status = wma_post_runtime_resume_msg(handle);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306542 return qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006543}
6544
6545/**
6546 * wma_bus_resume() - handles bus resume request from hdd
6547 * @handle: valid wma handle
6548 *
6549 * Calls the appropriate handler based on configuration
6550 *
6551 * Return: 0 for success or error code
6552 */
6553int wma_bus_resume(void)
6554{
Anurag Chouhan6d760662016-02-20 16:05:43 +05306555 WMA_HANDLE handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006556 if (NULL == handle) {
6557 WMA_LOGE("%s: wma context is NULL", __func__);
6558 return -EFAULT;
6559 }
6560
Houston Hoffmana76591b2015-11-10 16:52:05 -08006561 return __wma_bus_resume(handle);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006562}
6563
6564/**
Manjunathappa Prakash7b67e622016-04-12 15:18:45 +05306565 * wma_suspend_target_timeout() - Handles the target suspend timeout
6566 * @is_self_recovery_enabled: Is self recovery enabled or not
6567 *
6568 * Return: NONE
6569 */
6570#ifdef QCA_WIFI_3_0_ADRASTEA
6571static inline void wma_suspend_target_timeout(bool is_self_recovery_enabled)
6572{
6573 if (cds_is_driver_recovering()) {
6574 WMA_LOGE("%s: recovery is in progress, ignore!", __func__);
6575 } else {
6576 if (is_self_recovery_enabled) {
6577 cds_trigger_recovery();
6578 } else {
6579 QDF_BUG(0);
6580 }
6581 }
6582}
6583#else /* ROME chipset */
6584static inline void wma_suspend_target_timeout(bool is_self_recovery_enabled)
6585{
6586 if (cds_is_load_or_unload_in_progress() || cds_is_driver_recovering()) {
6587 WMA_LOGE("%s: Unloading/Loading/recovery is in progress, Ignore!",
6588 __func__);
6589 } else {
6590 if (is_self_recovery_enabled) {
6591 cds_trigger_recovery();
6592 } else {
6593 QDF_BUG(0);
6594 }
6595 }
6596}
6597#endif
6598
6599/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006600 * wma_suspend_target() - suspend target
6601 * @handle: wma handle
6602 * @disable_target_intr: disable target interrupt
6603 *
Govind Singhd76a5b02016-03-08 15:12:14 +05306604 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006605 */
Govind Singhd76a5b02016-03-08 15:12:14 +05306606QDF_STATUS wma_suspend_target(WMA_HANDLE handle, int disable_target_intr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006607{
6608 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhd76a5b02016-03-08 15:12:14 +05306609 QDF_STATUS status;
6610 struct suspend_params param = {0};
6611
Anurag Chouhan6d760662016-02-20 16:05:43 +05306612 tpAniSirGlobal pmac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006613
6614 if (!wma_handle || !wma_handle->wmi_handle) {
6615 WMA_LOGE("WMA is closed. can not issue suspend cmd");
Govind Singhd76a5b02016-03-08 15:12:14 +05306616 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006617 }
Yue Mae1a85f32015-10-20 18:12:45 -07006618
Yue Mae1a85f32015-10-20 18:12:45 -07006619 if (NULL == pmac) {
6620 WMA_LOGE("%s: Unable to get PE context", __func__);
Govind Singhd76a5b02016-03-08 15:12:14 +05306621 return QDF_STATUS_E_INVAL;
Yue Mae1a85f32015-10-20 18:12:45 -07006622 }
Houston Hoffman52ec6692016-04-21 16:36:45 -07006623
Anurag Chouhance0dc992016-02-16 18:18:03 +05306624 qdf_event_reset(&wma_handle->target_suspend);
Govind Singhd76a5b02016-03-08 15:12:14 +05306625 param.disable_target_intr = disable_target_intr;
6626 status = wmi_unified_suspend_send(wma_handle->wmi_handle,
6627 &param,
6628 WMA_WILDCARD_PDEV_ID);
6629 if (QDF_IS_STATUS_ERROR(status))
6630 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006631
6632 wmi_set_target_suspend(wma_handle->wmi_handle, true);
6633
Anurag Chouhance0dc992016-02-16 18:18:03 +05306634 if (qdf_wait_single_event(&wma_handle->target_suspend,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006635 WMA_TGT_SUSPEND_COMPLETE_TIMEOUT)
Anurag Chouhance0dc992016-02-16 18:18:03 +05306636 != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006637 WMA_LOGE("Failed to get ACK from firmware for pdev suspend");
6638 wmi_set_target_suspend(wma_handle->wmi_handle, false);
Manjunathappa Prakash7b67e622016-04-12 15:18:45 +05306639 wma_suspend_target_timeout(pmac->sme.enableSelfRecovery);
Govind Singhd76a5b02016-03-08 15:12:14 +05306640 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006641 }
6642
Govind Singhd76a5b02016-03-08 15:12:14 +05306643 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006644}
6645
6646/**
6647 * wma_target_suspend_acknowledge() - update target susspend status
Houston Hoffmana769ed32016-04-14 17:02:51 -07006648 * @context: HTC_INIT_INFO->context
6649 * @wow_nack: true when wow is rejected
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006650 *
6651 * Return: none
6652 */
Houston Hoffmana769ed32016-04-14 17:02:51 -07006653void wma_target_suspend_acknowledge(void *context, bool wow_nack)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006654{
Anurag Chouhan6d760662016-02-20 16:05:43 +05306655 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006656
6657 if (NULL == wma) {
6658 WMA_LOGE("%s: wma is NULL", __func__);
6659 return;
6660 }
6661
6662 wma->wow_nack = wow_nack;
Anurag Chouhance0dc992016-02-16 18:18:03 +05306663 qdf_event_set(&wma->target_suspend);
Komal Seelam498a0cd2016-09-12 10:29:02 +05306664 if (wow_nack && !wmi_get_runtime_pm_inprogress(wma->wmi_handle)) {
Anurag Chouhan01cfa4e2016-09-04 15:10:49 +05306665 cds_host_diag_log_work(&wma->wow_wake_lock,
6666 WMA_WAKE_LOCK_TIMEOUT,
6667 WIFI_POWER_EVENT_WAKELOCK_WOW);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306668 qdf_wake_lock_timeout_acquire(&wma->wow_wake_lock,
Anurag Chouhan01cfa4e2016-09-04 15:10:49 +05306669 WMA_WAKE_LOCK_TIMEOUT);
6670 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006671}
6672
6673/**
Rajeev Kumar4c426622016-08-25 14:51:42 -07006674 * wma_handle_initial_wake_up() - handle inital wake up
6675 *
6676 * Return: none
6677 */
6678void wma_handle_initial_wake_up(void)
6679{
6680 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
6681
6682 if (NULL == wma) {
6683 WMA_LOGE("%s: wma is NULL", __func__);
6684 return;
6685 }
6686
6687 wma->wow_initial_wake_up = true;
6688}
6689
6690/**
6691 * wma_is_target_wake_up_received() - check for initial wake up
6692 *
6693 * Check if target initial wake up is received and fail PM suspend gracefully
6694 *
6695 * Return: -EAGAIN if initial wake up is received else 0
6696 */
6697int wma_is_target_wake_up_received(void)
6698{
6699 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
6700
6701 if (NULL == wma) {
6702 WMA_LOGE("%s: wma is NULL", __func__);
6703 return -EAGAIN;
6704 }
6705
6706 if (wma->wow_initial_wake_up) {
6707 WMA_LOGE("Target initial wake up received try again");
6708 return -EAGAIN;
Rajeev Kumar4c426622016-08-25 14:51:42 -07006709 }
Rajeev Kumar99805a72016-08-29 13:53:52 -07006710
6711 return 0;
6712}
6713
6714/**
6715 * wma_clear_target_wake_up() - clear initial wake up
6716 *
6717 * Clear target initial wake up reason
6718 *
6719 * Return: 0 for success and negative error code for failure
6720 */
6721int wma_clear_target_wake_up(void)
6722{
6723 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
6724
6725 if (NULL == wma) {
6726 WMA_LOGE("%s: wma is NULL", __func__);
6727 return -EFAULT;
6728 }
6729
6730 wma->wow_initial_wake_up = false;
6731
6732 return 0;
Rajeev Kumar4c426622016-08-25 14:51:42 -07006733}
6734
6735/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006736 * wma_resume_target() - resume target
6737 * @handle: wma handle
6738 *
Govind Singhd76a5b02016-03-08 15:12:14 +05306739 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006740 */
Govind Singhd76a5b02016-03-08 15:12:14 +05306741QDF_STATUS wma_resume_target(WMA_HANDLE handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006742{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006743 tp_wma_handle wma = (tp_wma_handle) handle;
Anurag Chouhance0dc992016-02-16 18:18:03 +05306744 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006745#ifdef CONFIG_CNSS
Anurag Chouhan6d760662016-02-20 16:05:43 +05306746 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006747 if (NULL == pMac) {
6748 WMA_LOGE("%s: Unable to get PE context", __func__);
Govind Singhd76a5b02016-03-08 15:12:14 +05306749 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006750 }
6751#endif /* CONFIG_CNSS */
6752
Anurag Chouhance0dc992016-02-16 18:18:03 +05306753 qdf_event_reset(&wma->wma_resume_event);
Govind Singhd76a5b02016-03-08 15:12:14 +05306754 qdf_status = wmi_unified_resume_send(wma->wmi_handle,
6755 WMA_WILDCARD_PDEV_ID);
6756 if (QDF_IS_STATUS_ERROR(qdf_status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006757 WMA_LOGE("Failed to send WMI_PDEV_RESUME_CMDID command");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006758
Anurag Chouhance0dc992016-02-16 18:18:03 +05306759 qdf_status = qdf_wait_single_event(&(wma->wma_resume_event),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006760 WMA_RESUME_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05306761 if (QDF_STATUS_SUCCESS != qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006762 WMA_LOGP("%s: Timeout waiting for resume event from FW",
6763 __func__);
6764 WMA_LOGP("%s: Pending commands %d credits %d", __func__,
6765 wmi_get_pending_cmds(wma->wmi_handle),
6766 wmi_get_host_credits(wma->wmi_handle));
Prashanth Bhatta9e143052015-12-04 11:56:47 -08006767 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006768#ifdef CONFIG_CNSS
6769 if (pMac->sme.enableSelfRecovery) {
6770 cds_trigger_recovery();
6771 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306772 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006773 }
6774#else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306775 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006776#endif /* CONFIG_CNSS */
6777 } else {
6778 WMA_LOGE("%s: SSR in progress, ignore resume timeout",
6779 __func__);
6780 }
6781 } else {
6782 WMA_LOGD("Host wakeup received");
6783 }
6784
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306785 if (QDF_STATUS_SUCCESS == qdf_status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006786 wmi_set_target_suspend(wma->wmi_handle, false);
6787
Houston Hoffman52ec6692016-04-21 16:36:45 -07006788 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006789}
6790
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006791#ifdef FEATURE_WLAN_TDLS
6792/**
6793 * wma_tdls_event_handler() - handle TDLS event
6794 * @handle: wma handle
6795 * @event: event buffer
6796 * @len: buffer length
6797 *
6798 * Return: 0 for success or error code
6799 */
6800int wma_tdls_event_handler(void *handle, uint8_t *event, uint32_t len)
6801{
6802 tp_wma_handle wma = (tp_wma_handle) handle;
6803 WMI_TDLS_PEER_EVENTID_param_tlvs *param_buf = NULL;
6804 wmi_tdls_peer_event_fixed_param *peer_event = NULL;
6805 tSirTdlsEventnotify *tdls_event;
6806
6807 if (!event) {
6808 WMA_LOGE("%s: event param null", __func__);
6809 return -EINVAL;
6810 }
6811
6812 param_buf = (WMI_TDLS_PEER_EVENTID_param_tlvs *) event;
6813 if (!param_buf) {
6814 WMA_LOGE("%s: received null buf from target", __func__);
6815 return -EINVAL;
6816 }
6817
6818 peer_event = param_buf->fixed_param;
6819 if (!peer_event) {
6820 WMA_LOGE("%s: received null event data from target", __func__);
6821 return -EINVAL;
6822 }
6823
6824 tdls_event = (tSirTdlsEventnotify *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306825 qdf_mem_malloc(sizeof(*tdls_event));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006826 if (!tdls_event) {
6827 WMA_LOGE("%s: failed to allocate memory for tdls_event",
6828 __func__);
6829 return -ENOMEM;
6830 }
6831
6832 tdls_event->sessionId = peer_event->vdev_id;
6833 WMI_MAC_ADDR_TO_CHAR_ARRAY(&peer_event->peer_macaddr,
Srinivas Girigowda4f593792015-11-19 15:33:42 -08006834 tdls_event->peermac.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006835
6836 switch (peer_event->peer_status) {
6837 case WMI_TDLS_SHOULD_DISCOVER:
6838 tdls_event->messageType = WMA_TDLS_SHOULD_DISCOVER_CMD;
6839 break;
6840 case WMI_TDLS_SHOULD_TEARDOWN:
6841 tdls_event->messageType = WMA_TDLS_SHOULD_TEARDOWN_CMD;
6842 break;
6843 case WMI_TDLS_PEER_DISCONNECTED:
6844 tdls_event->messageType = WMA_TDLS_PEER_DISCONNECTED_CMD;
6845 break;
Kabilan Kannan14ec97f2016-05-16 23:48:25 -07006846 case WMI_TDLS_CONNECTION_TRACKER_NOTIFICATION:
6847 tdls_event->messageType =
6848 WMA_TDLS_CONNECTION_TRACKER_NOTIFICATION_CMD;
6849 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006850 default:
6851 WMA_LOGE("%s: Discarding unknown tdls event(%d) from target",
6852 __func__, peer_event->peer_status);
6853 return -EINVAL;
6854 }
6855
6856 switch (peer_event->peer_reason) {
6857 case WMI_TDLS_TEARDOWN_REASON_TX:
6858 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_TX;
6859 break;
6860 case WMI_TDLS_TEARDOWN_REASON_RSSI:
6861 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_RSSI;
6862 break;
6863 case WMI_TDLS_TEARDOWN_REASON_SCAN:
6864 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_SCAN;
6865 break;
6866 case WMI_TDLS_DISCONNECTED_REASON_PEER_DELETE:
6867 tdls_event->peer_reason =
6868 eWNI_TDLS_DISCONNECTED_REASON_PEER_DELETE;
6869 break;
6870 case WMI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT:
6871 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT;
6872 break;
6873 case WMI_TDLS_TEARDOWN_REASON_BAD_PTR:
6874 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_BAD_PTR;
6875 break;
6876 case WMI_TDLS_TEARDOWN_REASON_NO_RESPONSE:
6877 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_NO_RESPONSE;
6878 break;
Kabilan Kannan14ec97f2016-05-16 23:48:25 -07006879 case WMI_TDLS_ENTER_BUF_STA:
6880 tdls_event->peer_reason = eWNI_TDLS_PEER_ENTER_BUF_STA;
6881 break;
6882 case WMI_TDLS_EXIT_BUF_STA:
6883 tdls_event->peer_reason = eWNI_TDLS_PEER_EXIT_BUF_STA;
6884 break;
6885 case WMI_TDLS_ENTER_BT_BUSY_MODE:
6886 tdls_event->peer_reason = eWNI_TDLS_ENTER_BT_BUSY_MODE;
6887 break;
6888 case WMI_TDLS_EXIT_BT_BUSY_MODE:
6889 tdls_event->peer_reason = eWNI_TDLS_EXIT_BT_BUSY_MODE;
6890 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006891 default:
6892 WMA_LOGE("%s: unknown reason(%d) in tdls event(%d) from target",
6893 __func__, peer_event->peer_reason,
6894 peer_event->peer_status);
6895 return -EINVAL;
6896 }
6897
6898 WMA_LOGD("%s: sending msg to umac, messageType: 0x%x, "
6899 "for peer: %pM, reason: %d, smesessionId: %d",
Srinivas Girigowda4f593792015-11-19 15:33:42 -08006900 __func__, tdls_event->messageType, tdls_event->peermac.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006901 tdls_event->peer_reason, tdls_event->sessionId);
6902
6903 wma_send_msg(wma, tdls_event->messageType, (void *)tdls_event, 0);
6904 return 0;
6905}
6906
6907/**
6908 * wma_set_tdls_offchan_mode() - set tdls off channel mode
6909 * @handle: wma handle
6910 * @chan_switch_params: Pointer to tdls channel switch parameter structure
6911 *
6912 * This function sets tdls off channel mode
6913 *
6914 * Return: 0 on success; Negative errno otherwise
6915 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05306916QDF_STATUS wma_set_tdls_offchan_mode(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006917 tdls_chan_switch_params *chan_switch_params)
6918{
6919 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Himanshu Agarwal44195412016-03-09 13:03:54 +05306920 struct tdls_channel_switch_params params = {0};
6921 QDF_STATUS ret = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006922
6923 if (!wma_handle || !wma_handle->wmi_handle) {
6924 WMA_LOGE(FL(
6925 "WMA is closed, can not issue tdls off channel cmd"
6926 ));
6927 ret = -EINVAL;
6928 goto end;
6929 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006930
Himanshu Agarwal44195412016-03-09 13:03:54 +05306931 params.vdev_id = chan_switch_params->vdev_id;
6932 params.tdls_off_ch_bw_offset =
6933 chan_switch_params->tdls_off_ch_bw_offset;
6934 params.tdls_off_ch = chan_switch_params->tdls_off_ch;
6935 params.tdls_sw_mode = chan_switch_params->tdls_sw_mode;
6936 params.oper_class = chan_switch_params->oper_class;
6937 params.is_responder = chan_switch_params->is_responder;
6938 qdf_mem_copy(params.peer_mac_addr, chan_switch_params->peer_mac_addr,
Krunal Soniab793342016-04-22 18:43:20 -07006939 IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006940
Himanshu Agarwal44195412016-03-09 13:03:54 +05306941 ret = wmi_unified_set_tdls_offchan_mode_cmd(wma_handle->wmi_handle,
6942 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006943
6944end:
6945 if (chan_switch_params)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306946 qdf_mem_free(chan_switch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006947 return ret;
6948}
6949
6950/**
6951 * wma_update_fw_tdls_state() - send enable/disable tdls for a vdev
6952 * @wma: wma handle
6953 * @pwmaTdlsparams: TDLS params
6954 *
6955 * Return: 0 for sucess or error code
6956 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05306957QDF_STATUS wma_update_fw_tdls_state(WMA_HANDLE handle, void *pwmaTdlsparams)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006958{
6959 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006960 t_wma_tdls_mode tdls_mode;
6961 t_wma_tdls_params *wma_tdls = (t_wma_tdls_params *) pwmaTdlsparams;
Himanshu Agarwal44195412016-03-09 13:03:54 +05306962 struct wmi_tdls_params params = {0};
6963 QDF_STATUS ret = QDF_STATUS_SUCCESS;
6964 uint8_t tdls_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006965
6966 if (!wma_handle || !wma_handle->wmi_handle) {
6967 WMA_LOGE("%s: WMA is closed, can not issue fw tdls state cmd",
6968 __func__);
6969 ret = -EINVAL;
6970 goto end_fw_tdls_state;
6971 }
6972
Himanshu Agarwal44195412016-03-09 13:03:54 +05306973 params.tdls_state = wma_tdls->tdls_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006974 tdls_mode = wma_tdls->tdls_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006975
6976 if (WMA_TDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == tdls_mode) {
Himanshu Agarwal44195412016-03-09 13:03:54 +05306977 tdls_state = WMI_TDLS_ENABLE_PASSIVE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006978 } else if (WMA_TDLS_SUPPORT_ENABLED == tdls_mode) {
Kabilan Kannan14ec97f2016-05-16 23:48:25 -07006979 tdls_state = WMI_TDLS_ENABLE_CONNECTION_TRACKER_IN_HOST;
Kabilan Kannan421714b2015-11-23 04:44:59 -08006980 } else if (WMA_TDLS_SUPPORT_ACTIVE_EXTERNAL_CONTROL == tdls_mode) {
Kabilan Kannan14ec97f2016-05-16 23:48:25 -07006981 tdls_state = WMI_TDLS_ENABLE_CONNECTION_TRACKER_IN_HOST;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006982 } else {
Himanshu Agarwal44195412016-03-09 13:03:54 +05306983 tdls_state = WMI_TDLS_DISABLE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006984 }
6985
Himanshu Agarwal44195412016-03-09 13:03:54 +05306986 params.vdev_id = wma_tdls->vdev_id;
6987 params.notification_interval_ms = wma_tdls->notification_interval_ms;
6988 params.tx_discovery_threshold = wma_tdls->tx_discovery_threshold;
6989 params.tx_teardown_threshold = wma_tdls->tx_teardown_threshold;
6990 params.rssi_teardown_threshold = wma_tdls->rssi_teardown_threshold;
6991 params.rssi_delta = wma_tdls->rssi_delta;
6992 params.tdls_options = wma_tdls->tdls_options;
6993 params.peer_traffic_ind_window = wma_tdls->peer_traffic_ind_window;
6994 params.peer_traffic_response_timeout =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006995 wma_tdls->peer_traffic_response_timeout;
Himanshu Agarwal44195412016-03-09 13:03:54 +05306996 params.puapsd_mask = wma_tdls->puapsd_mask;
6997 params.puapsd_inactivity_time = wma_tdls->puapsd_inactivity_time;
6998 params.puapsd_rx_frame_threshold =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006999 wma_tdls->puapsd_rx_frame_threshold;
Himanshu Agarwal44195412016-03-09 13:03:54 +05307000 params.teardown_notification_ms =
Kabilan Kannanca670be2015-11-23 01:56:12 -08007001 wma_tdls->teardown_notification_ms;
Himanshu Agarwal44195412016-03-09 13:03:54 +05307002 params.tdls_peer_kickout_threshold =
Kabilan Kannan421714b2015-11-23 04:44:59 -08007003 wma_tdls->tdls_peer_kickout_threshold;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007004
Himanshu Agarwal44195412016-03-09 13:03:54 +05307005 ret = wmi_unified_update_fw_tdls_state_cmd(wma_handle->wmi_handle,
7006 &params, tdls_state);
7007 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007008 goto end_fw_tdls_state;
Himanshu Agarwal44195412016-03-09 13:03:54 +05307009
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007010 WMA_LOGD("%s: vdev_id %d", __func__, wma_tdls->vdev_id);
7011
7012end_fw_tdls_state:
7013 if (pwmaTdlsparams)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307014 qdf_mem_free(pwmaTdlsparams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007015 return ret;
7016}
7017
7018/**
7019 * wma_update_tdls_peer_state() - update TDLS peer state
7020 * @handle: wma handle
7021 * @peerStateParams: TDLS peer state params
7022 *
7023 * Return: 0 for success or error code
7024 */
7025int wma_update_tdls_peer_state(WMA_HANDLE handle,
7026 tTdlsPeerStateParams *peerStateParams)
7027{
7028 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007029 uint32_t i;
7030 ol_txrx_pdev_handle pdev;
7031 uint8_t peer_id;
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07007032 ol_txrx_peer_handle peer;
7033 uint8_t *peer_mac_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007034 int ret = 0;
Kabilan Kannanc89fe712016-07-21 06:57:12 -07007035 uint32_t *ch_mhz = NULL;
Poddar, Siddarth5a91f5b2016-04-28 12:24:10 +05307036 bool restore_last_peer = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007037
7038 if (!wma_handle || !wma_handle->wmi_handle) {
7039 WMA_LOGE("%s: WMA is closed, can not issue cmd", __func__);
7040 ret = -EINVAL;
7041 goto end_tdls_peer_state;
7042 }
7043
7044 /* peer capability info is valid only when peer state is connected */
7045 if (WMA_TDLS_PEER_STATE_CONNECTED != peerStateParams->peerState) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307046 qdf_mem_zero(&peerStateParams->peerCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007047 sizeof(tTdlsPeerCapParams));
7048 }
7049
Kabilan Kannanc89fe712016-07-21 06:57:12 -07007050 if (peerStateParams->peerCap.peerChanLen) {
7051 ch_mhz = qdf_mem_malloc(sizeof(uint32_t) *
7052 peerStateParams->peerCap.peerChanLen);
7053 if (ch_mhz == NULL) {
7054 WMA_LOGE("%s: memory allocation failed", __func__);
7055 ret = -ENOMEM;
7056 goto end_tdls_peer_state;
7057 }
Naveen Rawat35804772016-06-27 15:40:28 -07007058 }
7059
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007060 for (i = 0; i < peerStateParams->peerCap.peerChanLen; ++i) {
Govind Singhaa64c242016-03-08 11:31:49 +05307061 ch_mhz[i] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007062 cds_chan_to_freq(peerStateParams->peerCap.peerChan[i].
7063 chanId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007064 }
7065
Govind Singhaa64c242016-03-08 11:31:49 +05307066 if (wmi_unified_update_tdls_peer_state_cmd(wma_handle->wmi_handle,
7067 (struct tdls_peer_state_params *)peerStateParams,
7068 ch_mhz)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007069 WMA_LOGE("%s: failed to send tdls peer update state command",
7070 __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007071 ret = -EIO;
7072 goto end_tdls_peer_state;
7073 }
7074
7075 /* in case of teardown, remove peer from fw */
7076 if (WMA_TDLS_PEER_STATE_TEARDOWN == peerStateParams->peerState) {
Anurag Chouhan6d760662016-02-20 16:05:43 +05307077 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007078 if (!pdev) {
7079 WMA_LOGE("%s: Failed to find pdev", __func__);
7080 ret = -EIO;
7081 goto end_tdls_peer_state;
7082 }
7083
7084 peer = ol_txrx_find_peer_by_addr(pdev,
7085 peerStateParams->peerMacAddr,
7086 &peer_id);
7087 if (!peer) {
7088 WMA_LOGE("%s: Failed to get peer handle using peer mac %pM",
7089 __func__, peerStateParams->peerMacAddr);
7090 ret = -EIO;
7091 goto end_tdls_peer_state;
7092 }
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07007093 peer_mac_addr = ol_txrx_peer_get_peer_mac_addr(peer);
Poddar, Siddarth5a91f5b2016-04-28 12:24:10 +05307094 restore_last_peer = is_vdev_restore_last_peer(peer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007095
7096 WMA_LOGD("%s: calling wma_remove_peer for peer " MAC_ADDRESS_STR
7097 " vdevId: %d", __func__,
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07007098 MAC_ADDR_ARRAY(peer_mac_addr),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007099 peerStateParams->vdevId);
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07007100 wma_remove_peer(wma_handle, peer_mac_addr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007101 peerStateParams->vdevId, peer, false);
Poddar, Siddarth5a91f5b2016-04-28 12:24:10 +05307102 ol_txrx_update_last_real_peer(pdev, peer, &peer_id,
7103 restore_last_peer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007104 }
7105
7106end_tdls_peer_state:
Kabilan Kannanc89fe712016-07-21 06:57:12 -07007107 if (ch_mhz)
7108 qdf_mem_free(ch_mhz);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007109 if (peerStateParams)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307110 qdf_mem_free(peerStateParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007111 return ret;
7112}
7113#endif /* FEATURE_WLAN_TDLS */
7114
7115
7116/**
7117 * wma_dfs_attach() - Attach DFS methods to the umac state.
7118 * @dfs_ic: ieee80211com ptr
7119 *
7120 * Return: Return ieee80211com ptr with updated info
7121 */
7122struct ieee80211com *wma_dfs_attach(struct ieee80211com *dfs_ic)
7123{
7124 /*Allocate memory for dfs_ic before passing it up to dfs_attach() */
7125 dfs_ic = (struct ieee80211com *)
7126 os_malloc(NULL, sizeof(struct ieee80211com), GFP_ATOMIC);
7127 if (dfs_ic == NULL) {
7128 WMA_LOGE("%s:Allocation of dfs_ic failed %zu",
7129 __func__, sizeof(struct ieee80211com));
7130 return NULL;
7131 }
7132 OS_MEMZERO(dfs_ic, sizeof(struct ieee80211com));
7133 /* DFS pattern matching hooks */
7134 dfs_ic->ic_dfs_attach = ol_if_dfs_attach;
7135 dfs_ic->ic_dfs_disable = ol_if_dfs_disable;
7136 dfs_ic->ic_find_channel = ieee80211_find_channel;
7137 dfs_ic->ic_dfs_enable = ol_if_dfs_enable;
7138 dfs_ic->ic_ieee2mhz = ieee80211_ieee2mhz;
7139
7140 /* Hardware facing hooks */
7141 dfs_ic->ic_get_ext_busy = ol_if_dfs_get_ext_busy;
7142 dfs_ic->ic_get_mib_cycle_counts_pct =
7143 ol_if_dfs_get_mib_cycle_counts_pct;
7144 dfs_ic->ic_get_TSF64 = ol_if_get_tsf64;
7145
7146 /* NOL related hooks */
7147 dfs_ic->ic_dfs_usenol = ol_if_dfs_usenol;
7148 /*
7149 * Hooks from wma/dfs/ back
7150 * into the PE/SME
7151 * and shared DFS code
7152 */
7153 dfs_ic->ic_dfs_notify_radar = ieee80211_mark_dfs;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05307154 qdf_spinlock_create(&dfs_ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007155 /* Initializes DFS Data Structures and queues */
7156 dfs_attach(dfs_ic);
7157
7158 return dfs_ic;
7159}
7160
7161/**
7162 * wma_dfs_detach() - Detach DFS methods
7163 * @dfs_ic: ieee80211com ptr
7164 *
7165 * Return: none
7166 */
7167void wma_dfs_detach(struct ieee80211com *dfs_ic)
7168{
7169 dfs_detach(dfs_ic);
7170
Anurag Chouhana37b5b72016-02-21 14:53:42 +05307171 qdf_spinlock_destroy(&dfs_ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007172 if (NULL != dfs_ic->ic_curchan) {
7173 OS_FREE(dfs_ic->ic_curchan);
7174 dfs_ic->ic_curchan = NULL;
7175 }
7176
7177 OS_FREE(dfs_ic);
7178}
7179
7180/**
7181 * wma_dfs_configure() - configure dfs
7182 * @ic: ieee80211com ptr
7183 *
7184 * Configures Radar Filters during
7185 * vdev start/channel change/regulatory domain
7186 * change.This Configuration enables to program
7187 * the DFS pattern matching module.
7188 *
7189 * Return: none
7190 */
7191void wma_dfs_configure(struct ieee80211com *ic)
7192{
7193 struct ath_dfs_radar_tab_info rinfo;
7194 int dfsdomain;
7195 int radar_enabled_status = 0;
7196 if (ic == NULL) {
7197 WMA_LOGE("%s: DFS ic is Invalid", __func__);
7198 return;
7199 }
7200
7201 dfsdomain = ic->current_dfs_regdomain;
7202
7203 /* Fetch current radar patterns from the lmac */
7204 OS_MEMZERO(&rinfo, sizeof(rinfo));
7205
7206 /*
7207 * Look up the current DFS
7208 * regulatory domain and decide
7209 * which radar pulses to use.
7210 */
7211 switch (dfsdomain) {
Amar Singhala7bb01b2016-01-27 11:31:59 -08007212 case DFS_FCC_REGION:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007213 WMA_LOGI("%s: DFS-FCC domain", __func__);
Amar Singhala7bb01b2016-01-27 11:31:59 -08007214 rinfo.dfsdomain = DFS_FCC_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007215 rinfo.dfs_radars = dfs_fcc_radars;
Anurag Chouhan6d760662016-02-20 16:05:43 +05307216 rinfo.numradars = QDF_ARRAY_SIZE(dfs_fcc_radars);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007217 rinfo.b5pulses = dfs_fcc_bin5pulses;
Anurag Chouhan6d760662016-02-20 16:05:43 +05307218 rinfo.numb5radars = QDF_ARRAY_SIZE(dfs_fcc_bin5pulses);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007219 break;
Amar Singhala7bb01b2016-01-27 11:31:59 -08007220 case DFS_ETSI_REGION:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007221 WMA_LOGI("%s: DFS-ETSI domain", __func__);
Amar Singhala7bb01b2016-01-27 11:31:59 -08007222 rinfo.dfsdomain = DFS_ETSI_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007223 rinfo.dfs_radars = dfs_etsi_radars;
Anurag Chouhan6d760662016-02-20 16:05:43 +05307224 rinfo.numradars = QDF_ARRAY_SIZE(dfs_etsi_radars);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007225 rinfo.b5pulses = NULL;
7226 rinfo.numb5radars = 0;
7227 break;
Amar Singhala7bb01b2016-01-27 11:31:59 -08007228 case DFS_MKK_REGION:
7229 WMA_LOGI("%s: DFS-MKK domain", __func__);
7230 rinfo.dfsdomain = DFS_MKK_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007231 rinfo.dfs_radars = dfs_mkk4_radars;
Anurag Chouhan6d760662016-02-20 16:05:43 +05307232 rinfo.numradars = QDF_ARRAY_SIZE(dfs_mkk4_radars);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007233 rinfo.b5pulses = dfs_jpn_bin5pulses;
Anurag Chouhan6d760662016-02-20 16:05:43 +05307234 rinfo.numb5radars = QDF_ARRAY_SIZE(dfs_jpn_bin5pulses);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007235 break;
Arif Hussainaca67302016-07-28 17:25:00 -07007236 case DFS_CN_REGION:
7237 WMA_LOGI("%s: DFS-CN domain", __func__);
7238 rinfo.dfsdomain = DFS_CN_REGION;
7239 rinfo.dfs_radars = dfs_china_radars;
7240 rinfo.numradars = QDF_ARRAY_SIZE(dfs_china_radars);
7241 rinfo.b5pulses = NULL;
7242 rinfo.numb5radars = 0;
7243 break;
7244 case DFS_KR_REGION:
7245 WMA_LOGI("%s: DFS-KR domain", __func__);
7246 rinfo.dfsdomain = DFS_KR_REGION;
7247 rinfo.dfs_radars = dfs_korea_radars;
7248 rinfo.numradars = QDF_ARRAY_SIZE(dfs_korea_radars);
7249 rinfo.b5pulses = NULL;
7250 rinfo.numb5radars = 0;
7251 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007252 default:
7253 WMA_LOGI("%s: DFS-UNINT domain", __func__);
Amar Singhala7bb01b2016-01-27 11:31:59 -08007254 rinfo.dfsdomain = DFS_UNINIT_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007255 rinfo.dfs_radars = NULL;
7256 rinfo.numradars = 0;
7257 rinfo.b5pulses = NULL;
7258 rinfo.numb5radars = 0;
7259 break;
7260 }
7261
7262 rinfo.dfs_pri_multiplier = ic->dfs_pri_multiplier;
7263
7264 /*
7265 * Set the regulatory domain,
7266 * radar pulse table and enable
7267 * radar events if required.
7268 * dfs_radar_enable() returns
7269 * 0 on success and non-zero
7270 * failure.
7271 */
7272 radar_enabled_status = dfs_radar_enable(ic, &rinfo);
7273 if (radar_enabled_status != DFS_STATUS_SUCCESS) {
7274 WMA_LOGE("%s[%d]: DFS- Radar Detection Enabling Failed",
7275 __func__, __LINE__);
7276 }
7277}
7278
7279/**
7280 * wma_dfs_configure_channel() - configure DFS channel
7281 * @dfs_ic: ieee80211com ptr
Siddarth Poddar17dc4712016-03-09 16:30:27 +05307282 * @band_center_freq1: center frequency 1
7283 * @band_center_freq2: center frequency 2
7284 * (valid only for 11ac vht 80plus80 mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007285 * @ req: vdev start request
7286 *
7287 * Set the Channel parameters in to DFS module
7288 * Also,configure the DFS radar filters for
7289 * matching the DFS phyerrors.
7290 *
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05307291 * Return: dfs_ieee80211_channel / NULL for error
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007292 */
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05307293struct dfs_ieee80211_channel *wma_dfs_configure_channel(
7294 struct ieee80211com *dfs_ic,
Siddarth Poddar17dc4712016-03-09 16:30:27 +05307295 uint32_t band_center_freq1,
7296 uint32_t band_center_freq2,
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05307297 struct wma_vdev_start_req
7298 *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007299{
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08007300 uint8_t ext_channel;
7301
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007302 if (dfs_ic == NULL) {
7303 WMA_LOGE("%s: DFS ic is Invalid", __func__);
7304 return NULL;
7305 }
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05307306
7307 if (!dfs_ic->ic_curchan) {
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05307308 dfs_ic->ic_curchan = (struct dfs_ieee80211_channel *)os_malloc(
7309 NULL,
7310 sizeof(struct dfs_ieee80211_channel),
7311 GFP_ATOMIC);
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05307312 if (dfs_ic->ic_curchan == NULL) {
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05307313 WMA_LOGE(
7314 "%s: allocation of dfs_ic->ic_curchan failed %zu",
7315 __func__, sizeof(struct dfs_ieee80211_channel));
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05307316 return NULL;
7317 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007318 }
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05307319
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05307320 OS_MEMZERO(dfs_ic->ic_curchan, sizeof(struct dfs_ieee80211_channel));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007321
7322 dfs_ic->ic_curchan->ic_ieee = req->chan;
Siddarth Poddar17dc4712016-03-09 16:30:27 +05307323 dfs_ic->ic_curchan->ic_freq = cds_chan_to_freq(req->chan);
7324 dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg1 = band_center_freq1;
7325 dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg2 = band_center_freq2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007326 dfs_ic->ic_curchan->ic_pri_freq_center_freq_mhz_separation =
7327 dfs_ic->ic_curchan->ic_freq -
7328 dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg1;
7329
7330 if ((dfs_ic->ic_curchan->ic_ieee >= WMA_11A_CHANNEL_BEGIN) &&
7331 (dfs_ic->ic_curchan->ic_ieee <= WMA_11A_CHANNEL_END)) {
7332 dfs_ic->ic_curchan->ic_flags |= IEEE80211_CHAN_5GHZ;
7333 }
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08007334
7335 switch (req->chan_width) {
7336 case CH_WIDTH_20MHZ:
7337 dfs_ic->ic_curchan->ic_flags |=
7338 (req->vht_capable ? IEEE80211_CHAN_VHT20 :
7339 IEEE80211_CHAN_HT20);
7340 break;
7341 case CH_WIDTH_40MHZ:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007342 if (req->chan < req->ch_center_freq_seg0)
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08007343 dfs_ic->ic_curchan->ic_flags |=
7344 (req->vht_capable ?
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007345 IEEE80211_CHAN_VHT40PLUS :
7346 IEEE80211_CHAN_HT40PLUS);
7347 else
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08007348 dfs_ic->ic_curchan->ic_flags |=
7349 (req->vht_capable ?
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007350 IEEE80211_CHAN_VHT40MINUS :
7351 IEEE80211_CHAN_HT40MINUS);
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08007352 break;
7353 case CH_WIDTH_80MHZ:
7354 dfs_ic->ic_curchan->ic_flags |= IEEE80211_CHAN_VHT80;
7355 break;
7356 case CH_WIDTH_80P80MHZ:
Siddarth Poddar17dc4712016-03-09 16:30:27 +05307357 ext_channel = cds_freq_to_chan(band_center_freq2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007358 dfs_ic->ic_curchan->ic_flags |=
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08007359 IEEE80211_CHAN_VHT80P80;
7360 dfs_ic->ic_curchan->ic_freq_ext =
Siddarth Poddar17dc4712016-03-09 16:30:27 +05307361 band_center_freq2;
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08007362 dfs_ic->ic_curchan->ic_ieee_ext = ext_channel;
7363
7364 /* verify both the 80MHz are DFS bands or not */
Rajeev Kumara3f6c2d2016-04-15 12:47:41 -07007365 if ((CHANNEL_STATE_DFS ==
7366 cds_get_5g_bonded_channel_state(req->chan ,
7367 CH_WIDTH_80MHZ)) &&
7368 (CHANNEL_STATE_DFS == cds_get_5g_bonded_channel_state(
7369 ext_channel - WMA_80MHZ_START_CENTER_CH_DIFF,
7370 CH_WIDTH_80MHZ)))
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08007371 dfs_ic->ic_curchan->ic_80p80_both_dfs = true;
7372 break;
7373 case CH_WIDTH_160MHZ:
7374 dfs_ic->ic_curchan->ic_flags |=
7375 IEEE80211_CHAN_VHT160;
7376 break;
7377 default:
7378 WMA_LOGE(
7379 "%s: Recieved a wrong channel width %d",
7380 __func__, req->chan_width);
7381 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007382 }
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08007383
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007384 dfs_ic->ic_curchan->ic_flagext |= IEEE80211_CHAN_DFS;
7385
7386 if (req->oper_mode == BSS_OPERATIONAL_MODE_AP) {
7387 dfs_ic->ic_opmode = IEEE80211_M_HOSTAP;
7388 dfs_ic->vdev_id = req->vdev_id;
7389 }
7390
7391 dfs_ic->dfs_pri_multiplier = req->dfs_pri_multiplier;
7392
7393 /*
7394 * Configuring the DFS with current channel and the radar filters
7395 */
7396 wma_dfs_configure(dfs_ic);
7397 WMA_LOGI("%s: DFS- CHANNEL CONFIGURED", __func__);
7398 return dfs_ic->ic_curchan;
7399}
7400
7401
7402/**
7403 * wma_set_dfs_region() - set DFS region
7404 * @wma: wma handle
7405 *
7406 * Configure the DFS region for DFS radar filter initialization
7407 *
7408 * Return: none
7409 */
Amar Singhal604ba6cf2016-07-27 15:29:51 -07007410void wma_set_dfs_region(tp_wma_handle wma, enum dfs_region dfs_region)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007411{
Amar Singhal604ba6cf2016-07-27 15:29:51 -07007412 if (dfs_region >= DFS_UNDEF_REGION ||
7413 dfs_region == DFS_UNINIT_REGION)
7414
Amar Singhala7bb01b2016-01-27 11:31:59 -08007415 /* assign DFS_FCC_REGION as default region*/
7416 wma->dfs_ic->current_dfs_regdomain = DFS_FCC_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007417 else
7418 wma->dfs_ic->current_dfs_regdomain = dfs_region;
7419
7420 WMA_LOGI("%s: DFS Region Domain: %d", __func__,
7421 wma->dfs_ic->current_dfs_regdomain);
7422}
7423
7424/**
7425 * wma_get_channels() - prepare dfs radar channel list
7426 * @ichan: channel
7427 * @chan_list: return channel list
7428 *
7429 * Return: return number of channels
7430 */
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05307431int wma_get_channels(struct dfs_ieee80211_channel *ichan,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007432 struct wma_dfs_radar_channel_list *chan_list)
7433{
7434 uint8_t center_chan = cds_freq_to_chan(ichan->ic_vhtop_ch_freq_seg1);
Vishwajith Upendrabf673e72016-01-19 16:05:40 -08007435 int count = 0;
7436 int start_channel = 0;
7437 int loop;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007438
7439 chan_list->nchannels = 0;
7440
Vishwajith Upendrabf673e72016-01-19 16:05:40 -08007441 if (IEEE80211_IS_CHAN_11AC_VHT160(ichan)) {
Arif Hussaine69337b2016-08-01 12:28:35 -07007442
7443 /*
7444 * as per the latest draft for BSS bandwidth 160MHz,
7445 * channel frequency segment 2 represents the center
7446 * channel frequency.
7447 */
7448 if (ichan->ic_vhtop_ch_freq_seg2)
7449 center_chan =
7450 cds_freq_to_chan(ichan->ic_vhtop_ch_freq_seg2);
Vishwajith Upendrabf673e72016-01-19 16:05:40 -08007451 /*
7452 * In 160MHz channel width, need to
7453 * check if each of the 8 20MHz channel
7454 * is DFS before adding to the NOL list.
7455 * As it is possible that part of the
7456 * 160MHz can be Non-DFS channels.
7457 */
7458 start_channel = center_chan - WMA_160MHZ_START_CENTER_CH_DIFF;
7459 for (loop = 0; loop < WMA_DFS_MAX_20M_SUB_CH; loop++) {
7460 if (cds_get_channel_state(start_channel +
7461 (loop * WMA_NEXT_20MHZ_START_CH_DIFF)) ==
7462 CHANNEL_STATE_DFS) {
7463 chan_list->channels[count] = start_channel +
7464 (loop * WMA_NEXT_20MHZ_START_CH_DIFF);
7465 count++;
7466 }
7467 }
7468 chan_list->nchannels = count;
7469 } else if (IEEE80211_IS_CHAN_11AC_VHT80P80(ichan)) {
7470 chan_list->nchannels = 4;
7471 /*
7472 * If SAP is operating in 80p80 mode, either
7473 * one of the two 80 segments or both the 80
7474 * segments can be DFS channels, so need to
7475 * identify on which 80 segment radar has
7476 * been detected and only add those channels
7477 * to the NOL list. center frequency should be
7478 * based on the segment id passed as part of
7479 * channel information in radar indication.
7480 */
7481 if (ichan->ic_radar_found_segid == DFS_80P80_SEG1)
7482 center_chan =
7483 cds_freq_to_chan(ichan->ic_vhtop_ch_freq_seg2);
7484 chan_list->channels[0] = center_chan - 6;
7485 chan_list->channels[1] = center_chan - 2;
7486 chan_list->channels[2] = center_chan + 2;
7487 chan_list->channels[3] = center_chan + 6;
7488 } else if (IEEE80211_IS_CHAN_11AC_VHT80(ichan)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007489 chan_list->nchannels = 4;
7490 chan_list->channels[0] = center_chan - 6;
7491 chan_list->channels[1] = center_chan - 2;
7492 chan_list->channels[2] = center_chan + 2;
7493 chan_list->channels[3] = center_chan + 6;
7494 } else if (IEEE80211_IS_CHAN_11N_HT40(ichan) ||
7495 IEEE80211_IS_CHAN_11AC_VHT40(ichan)) {
7496 chan_list->nchannels = 2;
7497 chan_list->channels[0] = center_chan - 2;
7498 chan_list->channels[1] = center_chan + 2;
7499 } else {
7500 chan_list->nchannels = 1;
7501 chan_list->channels[0] = center_chan;
7502 }
7503
7504 return chan_list->nchannels;
7505}
7506
7507
7508/**
7509 * wma_dfs_indicate_radar() - Indicate Radar to SAP/HDD
7510 * @ic: ieee80211com ptr
7511 * @ichan: ieee 80211 channel
7512 *
7513 * Return: 0 for success or error code
7514 */
7515int wma_dfs_indicate_radar(struct ieee80211com *ic,
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05307516 struct dfs_ieee80211_channel *ichan)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007517{
7518 tp_wma_handle wma;
7519 void *hdd_ctx;
7520 struct wma_dfs_radar_indication *radar_event;
7521 struct wma_dfs_radar_ind wma_radar_event;
7522 tpAniSirGlobal pmac = NULL;
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05307523 bool indication_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007524
Anurag Chouhan6d760662016-02-20 16:05:43 +05307525 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007526 if (wma == NULL) {
7527 WMA_LOGE("%s: DFS- Invalid wma", __func__);
7528 return -ENOENT;
7529 }
7530
Anurag Chouhan6d760662016-02-20 16:05:43 +05307531 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007532 pmac = (tpAniSirGlobal)
Anurag Chouhan6d760662016-02-20 16:05:43 +05307533 cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007534
7535 if (!pmac) {
7536 WMA_LOGE("%s: Invalid MAC handle", __func__);
7537 return -ENOENT;
7538 }
7539
7540 if (wma->dfs_ic != ic) {
7541 WMA_LOGE("%s:DFS- Invalid WMA handle", __func__);
7542 return -ENOENT;
7543 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007544
7545 /*
7546 * Do not post multiple Radar events on the same channel.
7547 * But, when DFS test mode is enabled, allow multiple dfs
7548 * radar events to be posted on the same channel.
7549 */
Anurag Chouhana37b5b72016-02-21 14:53:42 +05307550 qdf_spin_lock_bh(&ic->chan_lock);
Edhar, Mahesh Kumar35d9b2e2015-10-26 17:06:23 +05307551 if (!pmac->sap.SapDfsInfo.disable_dfs_ch_switch)
7552 wma->dfs_ic->disable_phy_err_processing = true;
7553
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007554 if ((ichan->ic_ieee != (wma->dfs_ic->last_radar_found_chan)) ||
7555 (pmac->sap.SapDfsInfo.disable_dfs_ch_switch == true)) {
Kapil Gupta155748e2016-10-01 13:20:20 +05307556 radar_event = (struct wma_dfs_radar_indication *)
7557 qdf_mem_malloc(sizeof(struct wma_dfs_radar_indication));
7558 if (radar_event == NULL) {
7559 WMA_LOGE(FL("Failed to allocate memory for radar_event"));
7560 return -ENOMEM;
7561 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007562 wma->dfs_ic->last_radar_found_chan = ichan->ic_ieee;
7563 /* Indicate the radar event to HDD to stop the netif Tx queues */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007564 wma_radar_event.chan_freq = ichan->ic_freq;
7565 wma_radar_event.dfs_radar_status = WMA_DFS_RADAR_FOUND;
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05307566 indication_status =
7567 wma->dfs_radar_indication_cb(hdd_ctx, &wma_radar_event);
7568 if (indication_status == false) {
7569 WMA_LOGE("%s:Application triggered channel switch in progress!.. drop radar event indiaction to SAP",
7570 __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307571 qdf_mem_free(radar_event);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05307572 qdf_spin_unlock_bh(&ic->chan_lock);
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05307573 return 0;
7574 }
7575
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007576 WMA_LOGE("%s:DFS- RADAR INDICATED TO HDD", __func__);
7577
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05307578 wma_radar_event.ieee_chan_number = ichan->ic_ieee;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007579 /*
7580 * Indicate to the radar event to SAP to
7581 * select a new channel and set CSA IE
7582 */
7583 radar_event->vdev_id = ic->vdev_id;
7584 wma_get_channels(ichan, &radar_event->chan_list);
7585 radar_event->dfs_radar_status = WMA_DFS_RADAR_FOUND;
7586 radar_event->use_nol = ic->ic_dfs_usenol(ic);
7587 wma_send_msg(wma, WMA_DFS_RADAR_IND, (void *)radar_event, 0);
7588 WMA_LOGE("%s:DFS- WMA_DFS_RADAR_IND Message Posted", __func__);
7589 }
Anurag Chouhana37b5b72016-02-21 14:53:42 +05307590 qdf_spin_unlock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007591
7592 return 0;
7593}
7594
7595#ifdef WLAN_FEATURE_MEMDUMP
7596/*
7597 * wma_process_fw_mem_dump_req() - Function to request fw memory dump from
7598 * firmware
7599 * @wma: Pointer to WMA handle
7600 * @mem_dump_req: Pointer for mem_dump_req
7601 *
7602 * This function sends memory dump request to firmware
7603 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307604 * Return: QDF_STATUS_SUCCESS for success otherwise failure
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007605 *
7606 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307607QDF_STATUS wma_process_fw_mem_dump_req(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007608 struct fw_dump_req *mem_dump_req)
7609{
Govind Singhaa64c242016-03-08 11:31:49 +05307610 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007611
7612 if (!mem_dump_req || !wma) {
7613 WMA_LOGE(FL("input pointer is NULL"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307614 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007615 }
7616
Govind Singhaa64c242016-03-08 11:31:49 +05307617 ret = wmi_unified_process_fw_mem_dump_cmd(wma->wmi_handle,
7618 (struct fw_dump_req_param *) mem_dump_req);
7619 if (ret)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307620 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007621
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307622 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007623}
7624
7625/**
7626 * wma_fw_mem_dump_rsp() - send fw mem dump response to SME
7627 *
7628 * @req_id - request id.
7629 * @status - copy status from the firmware.
7630 *
7631 * This function is called by the memory dump response handler to
7632 * indicate SME that firmware dump copy is complete
7633 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307634 * Return: QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007635 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307636static QDF_STATUS wma_fw_mem_dump_rsp(uint32_t req_id, uint32_t status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007637{
7638 struct fw_dump_rsp *dump_rsp;
7639 cds_msg_t sme_msg = {0};
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307640 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007641
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307642 dump_rsp = qdf_mem_malloc(sizeof(*dump_rsp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007643
7644 if (!dump_rsp) {
7645 WMA_LOGE(FL("Memory allocation failed."));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307646 qdf_status = QDF_STATUS_E_NOMEM;
7647 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007648 }
7649
7650 WMA_LOGI(FL("FW memory dump copy complete status: %d for request: %d"),
7651 status, req_id);
7652
7653 dump_rsp->request_id = req_id;
7654 dump_rsp->dump_complete = status;
7655
7656 sme_msg.type = eWNI_SME_FW_DUMP_IND;
7657 sme_msg.bodyptr = dump_rsp;
7658 sme_msg.bodyval = 0;
7659
Anurag Chouhan6d760662016-02-20 16:05:43 +05307660 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307661 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007662 WMA_LOGE(FL("Fail to post fw mem dump ind msg"));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307663 qdf_mem_free(dump_rsp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007664 }
7665
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307666 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007667}
7668
7669/**
7670 * wma_fw_mem_dump_event_handler() - handles fw memory dump event
7671 *
7672 * @handle: pointer to wma handle.
7673 * @cmd_param_info: pointer to TLV info received in the event.
7674 * @len: length of data in @cmd_param_info
7675 *
7676 * This function is a handler for firmware memory dump event.
7677 *
7678 * Return: integer (0 for success and error code otherwise)
7679 */
7680int wma_fw_mem_dump_event_handler(void *handle, u_int8_t *cmd_param_info,
7681 u_int32_t len)
7682{
7683 WMI_UPDATE_FW_MEM_DUMP_EVENTID_param_tlvs *param_buf;
7684 wmi_update_fw_mem_dump_fixed_param *event;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307685 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007686
7687 param_buf =
7688 (WMI_UPDATE_FW_MEM_DUMP_EVENTID_param_tlvs *) cmd_param_info;
7689 if (!param_buf) {
7690 WMA_LOGA("%s: Invalid stats event", __func__);
7691 return -EINVAL;
7692 }
7693
7694 event = param_buf->fixed_param;
7695
7696 status = wma_fw_mem_dump_rsp(event->request_id,
7697 event->fw_mem_dump_complete);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307698 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007699 WMA_LOGE("Error posting FW MEM DUMP RSP.");
7700 return -EINVAL;
7701 }
7702
7703 WMA_LOGI("FW MEM DUMP RSP posted successfully");
7704 return 0;
7705}
7706#endif /* WLAN_FEATURE_MEMDUMP */
7707
7708/*
7709 * wma_process_set_ie_info() - Function to send IE info to firmware
7710 * @wma: Pointer to WMA handle
7711 * @ie_data: Pointer for ie data
7712 *
7713 * This function sends IE information to firmware
7714 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307715 * Return: QDF_STATUS_SUCCESS for success otherwise failure
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007716 *
7717 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307718QDF_STATUS wma_process_set_ie_info(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007719 struct vdev_ie_info *ie_info)
7720{
Govind Singhaa64c242016-03-08 11:31:49 +05307721 struct vdev_ie_info_param cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007722 int ret;
7723
7724 if (!ie_info || !wma) {
7725 WMA_LOGE(FL("input pointer is NULL"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307726 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007727 }
7728
7729 /* Validate the input */
7730 if (ie_info->length <= 0) {
7731 WMA_LOGE(FL("Invalid IE length"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307732 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007733 }
7734
Govind Singhaa64c242016-03-08 11:31:49 +05307735 cmd.vdev_id = ie_info->vdev_id;
7736 cmd.ie_id = ie_info->ie_id;
7737 cmd.length = ie_info->length;
Naveen Rawat03e8d952016-08-01 15:22:20 -07007738 cmd.band = ie_info->band;
Govind Singhaa64c242016-03-08 11:31:49 +05307739 cmd.data = ie_info->data;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05307740 cmd.ie_source = WMA_SET_VDEV_IE_SOURCE_HOST;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007741
Naveen Rawat03e8d952016-08-01 15:22:20 -07007742 WMA_LOGD(FL("ie_id: %d, band: %d, len: %d"),
7743 ie_info->ie_id, ie_info->band, ie_info->length);
7744
7745 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_DEBUG,
7746 ie_info->data, ie_info->length);
7747
Govind Singhaa64c242016-03-08 11:31:49 +05307748 ret = wmi_unified_process_set_ie_info_cmd(wma->wmi_handle,
7749 &cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007750 return ret;
7751}
7752
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307753/**
7754 * wma_get_bpf_caps_event_handler() - Event handler for get bpf capability
7755 * @handle: WMA global handle
7756 * @cmd_param_info: command event data
7757 * @len: Length of @cmd_param_info
7758 *
7759 * Return: 0 on Success or Errno on failure
7760 */
7761int wma_get_bpf_caps_event_handler(void *handle,
7762 u_int8_t *cmd_param_info,
7763 u_int32_t len)
7764{
7765 WMI_BPF_CAPABILIY_INFO_EVENTID_param_tlvs *param_buf;
7766 wmi_bpf_capability_info_evt_fixed_param *event;
7767 struct sir_bpf_get_offload *bpf_get_offload;
7768 tpAniSirGlobal pmac = (tpAniSirGlobal)cds_get_context(
7769 QDF_MODULE_ID_PE);
7770
7771 if (!pmac) {
7772 WMA_LOGE("%s: Invalid pmac", __func__);
7773 return -EINVAL;
7774 }
7775 if (!pmac->sme.pbpf_get_offload_cb) {
7776 WMA_LOGE("%s: Callback not registered", __func__);
7777 return -EINVAL;
7778 }
7779
7780 param_buf = (WMI_BPF_CAPABILIY_INFO_EVENTID_param_tlvs *)cmd_param_info;
7781 event = param_buf->fixed_param;
7782 bpf_get_offload = qdf_mem_malloc(sizeof(*bpf_get_offload));
7783
7784 if (!bpf_get_offload) {
7785 WMA_LOGP("%s: Memory allocation failed.", __func__);
7786 return -ENOMEM;
7787 }
7788
7789 bpf_get_offload->bpf_version = event->bpf_version;
7790 bpf_get_offload->max_bpf_filters = event->max_bpf_filters;
7791 bpf_get_offload->max_bytes_for_bpf_inst =
7792 event->max_bytes_for_bpf_inst;
7793 WMA_LOGD("%s: BPF capabilities version: %d max bpf filter size: %d",
7794 __func__, bpf_get_offload->bpf_version,
7795 bpf_get_offload->max_bytes_for_bpf_inst);
7796
7797 WMA_LOGD("%s: sending bpf capabilities event to hdd", __func__);
7798 pmac->sme.pbpf_get_offload_cb(pmac->hHdd, bpf_get_offload);
7799 qdf_mem_free(bpf_get_offload);
7800 return 0;
7801}
7802
7803/**
7804 * wma_get_bpf_capabilities - Send get bpf capability to firmware
7805 * @wma_handle: wma handle
7806 *
7807 * Return: QDF_STATUS enumeration.
7808 */
7809QDF_STATUS wma_get_bpf_capabilities(tp_wma_handle wma)
7810{
7811 QDF_STATUS status = QDF_STATUS_SUCCESS;
7812 wmi_bpf_get_capability_cmd_fixed_param *cmd;
7813 wmi_buf_t wmi_buf;
7814 uint32_t len;
7815 u_int8_t *buf_ptr;
7816
7817 if (!wma || !wma->wmi_handle) {
7818 WMA_LOGE(FL("WMA is closed, can not issue get BPF capab"));
7819 return QDF_STATUS_E_INVAL;
7820 }
7821
7822 if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
7823 WMI_SERVICE_BPF_OFFLOAD)) {
7824 WMA_LOGE(FL("BPF cababilities feature bit not enabled"));
7825 return QDF_STATUS_E_FAILURE;
7826 }
7827
7828 len = sizeof(*cmd);
7829 wmi_buf = wmi_buf_alloc(wma->wmi_handle, len);
7830 if (!wmi_buf) {
7831 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
7832 return QDF_STATUS_E_NOMEM;
7833 }
7834
7835 buf_ptr = (u_int8_t *) wmi_buf_data(wmi_buf);
7836 cmd = (wmi_bpf_get_capability_cmd_fixed_param *) buf_ptr;
7837 WMITLV_SET_HDR(&cmd->tlv_header,
7838 WMITLV_TAG_STRUC_wmi_bpf_get_capability_cmd_fixed_param,
7839 WMITLV_GET_STRUCT_TLVLEN(
7840 wmi_bpf_get_capability_cmd_fixed_param));
7841
7842 if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len,
7843 WMI_BPF_GET_CAPABILITY_CMDID)) {
7844 WMA_LOGE(FL("Failed to send BPF capability command"));
7845 wmi_buf_free(wmi_buf);
7846 return QDF_STATUS_E_FAILURE;
7847 }
7848 return status;
7849}
7850
7851/**
7852 * wma_set_bpf_instructions - Set bpf instructions to firmware
7853 * @wma: wma handle
7854 * @bpf_set_offload: Bpf offload information to set to firmware
7855 *
7856 * Return: QDF_STATUS enumeration
7857 */
7858QDF_STATUS wma_set_bpf_instructions(tp_wma_handle wma,
7859 struct sir_bpf_set_offload *bpf_set_offload)
7860{
7861 wmi_bpf_set_vdev_instructions_cmd_fixed_param *cmd;
7862 wmi_buf_t wmi_buf;
7863 uint32_t len = 0, len_aligned = 0;
7864 u_int8_t *buf_ptr;
7865
7866 if (!wma || !wma->wmi_handle) {
7867 WMA_LOGE("%s: WMA is closed, can not issue set BPF capability",
7868 __func__);
7869 return QDF_STATUS_E_INVAL;
7870 }
7871
7872 if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
7873 WMI_SERVICE_BPF_OFFLOAD)) {
7874 WMA_LOGE(FL("BPF offload feature Disabled"));
7875 return QDF_STATUS_E_NOSUPPORT;
7876 }
7877
7878 if (bpf_set_offload->total_length) {
7879 len_aligned = roundup(bpf_set_offload->current_length,
7880 sizeof(A_UINT32));
7881 len = len_aligned + WMI_TLV_HDR_SIZE;
7882 }
7883
7884 len += sizeof(*cmd);
7885 wmi_buf = wmi_buf_alloc(wma->wmi_handle, len);
7886 if (!wmi_buf) {
7887 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
7888 return QDF_STATUS_E_NOMEM;
7889 }
7890
7891 buf_ptr = (u_int8_t *) wmi_buf_data(wmi_buf);
7892 cmd = (wmi_bpf_set_vdev_instructions_cmd_fixed_param *) buf_ptr;
7893
7894 WMITLV_SET_HDR(&cmd->tlv_header,
7895 WMITLV_TAG_STRUC_wmi_bpf_set_vdev_instructions_cmd_fixed_param,
7896 WMITLV_GET_STRUCT_TLVLEN(
7897 wmi_bpf_set_vdev_instructions_cmd_fixed_param));
7898 cmd->vdev_id = bpf_set_offload->session_id;
7899 cmd->filter_id = bpf_set_offload->filter_id;
7900 cmd->total_length = bpf_set_offload->total_length;
7901 cmd->current_offset = bpf_set_offload->current_offset;
7902 cmd->current_length = bpf_set_offload->current_length;
7903
7904 if (bpf_set_offload->total_length) {
7905 buf_ptr +=
7906 sizeof(wmi_bpf_set_vdev_instructions_cmd_fixed_param);
7907 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, len_aligned);
7908 buf_ptr += WMI_TLV_HDR_SIZE;
7909 qdf_mem_copy(buf_ptr, bpf_set_offload->program,
7910 bpf_set_offload->current_length);
7911 qdf_mem_free(bpf_set_offload->program);
7912 }
7913
7914 if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len,
7915 WMI_BPF_SET_VDEV_INSTRUCTIONS_CMDID)) {
7916 WMA_LOGE(FL("Failed to send config bpf instructions command"));
7917 wmi_buf_free(wmi_buf);
7918 return QDF_STATUS_E_FAILURE;
7919 }
7920 return QDF_STATUS_SUCCESS;
7921}
Peng Xu8fdaa492016-06-22 10:20:47 -07007922
7923/**
7924 * wma_p2p_lo_start() - P2P listen offload start
7925 * @params: p2p listen offload parameters
7926 *
7927 * This function sends WMI command to start P2P listen offload.
7928 *
7929 * Return: QDF_STATUS enumeration
7930 */
7931QDF_STATUS wma_p2p_lo_start(struct sir_p2p_lo_start *params)
7932{
7933 wmi_buf_t buf;
7934 wmi_p2p_lo_start_cmd_fixed_param *cmd;
7935 int32_t len = sizeof(*cmd);
7936 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
7937 uint8_t *buf_ptr;
7938 int ret;
Peng Xu4225c152016-07-14 21:18:14 -07007939 int device_types_len_aligned, probe_resp_len_aligned;
Peng Xu8fdaa492016-06-22 10:20:47 -07007940
7941 if (NULL == wma) {
7942 WMA_LOGE("%s: wma context is NULL", __func__);
7943 return QDF_STATUS_E_INVAL;
7944 }
7945
Peng Xu4225c152016-07-14 21:18:14 -07007946 device_types_len_aligned = qdf_roundup(params->dev_types_len,
7947 sizeof(A_UINT32));
7948 probe_resp_len_aligned = qdf_roundup(params->probe_resp_len,
7949 sizeof(A_UINT32));
7950
7951 len += 2 * WMI_TLV_HDR_SIZE + device_types_len_aligned +
7952 probe_resp_len_aligned;
Peng Xu8fdaa492016-06-22 10:20:47 -07007953
7954 buf = wmi_buf_alloc(wma->wmi_handle, len);
7955 if (!buf) {
7956 WMA_LOGP("%s: failed to allocate memory for p2p lo start",
7957 __func__);
7958 return QDF_STATUS_E_NOMEM;
7959 }
7960
7961 cmd = (wmi_p2p_lo_start_cmd_fixed_param *)wmi_buf_data(buf);
7962 buf_ptr = (uint8_t *) wmi_buf_data(buf);
7963
7964 WMITLV_SET_HDR(&cmd->tlv_header,
7965 WMITLV_TAG_STRUC_wmi_p2p_lo_start_cmd_fixed_param,
7966 WMITLV_GET_STRUCT_TLVLEN(
7967 wmi_p2p_lo_start_cmd_fixed_param));
7968
7969 cmd->vdev_id = params->vdev_id;
7970 cmd->ctl_flags = params->ctl_flags;
7971 cmd->channel = params->freq;
7972 cmd->period = params->period;
7973 cmd->interval = params->interval;
7974 cmd->count = params->count;
Peng Xu4225c152016-07-14 21:18:14 -07007975 cmd->device_types_len = params->dev_types_len;
7976 cmd->prob_resp_len = params->probe_resp_len;
Peng Xu8fdaa492016-06-22 10:20:47 -07007977
7978 buf_ptr += sizeof(wmi_p2p_lo_start_cmd_fixed_param);
7979 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE,
Peng Xu4225c152016-07-14 21:18:14 -07007980 device_types_len_aligned);
Peng Xu8fdaa492016-06-22 10:20:47 -07007981 buf_ptr += WMI_TLV_HDR_SIZE;
7982 qdf_mem_copy(buf_ptr, params->device_types, params->dev_types_len);
7983
Peng Xu4225c152016-07-14 21:18:14 -07007984 buf_ptr += device_types_len_aligned;
7985 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, probe_resp_len_aligned);
Peng Xu8fdaa492016-06-22 10:20:47 -07007986 buf_ptr += WMI_TLV_HDR_SIZE;
7987 qdf_mem_copy(buf_ptr, params->probe_resp_tmplt, params->probe_resp_len);
7988
7989 WMA_LOGI("%s: Sending WMI_P2P_LO_START command, channel=%d, period=%d, interval=%d, count=%d",
7990 __func__, cmd->channel, cmd->period,
7991 cmd->interval, cmd->count);
7992
7993 ret = wmi_unified_cmd_send(wma->wmi_handle,
7994 buf, len,
7995 WMI_P2P_LISTEN_OFFLOAD_START_CMDID);
7996 if (ret) {
7997 WMA_LOGE("Failed to send p2p lo start: %d", ret);
7998 wmi_buf_free(buf);
7999 }
8000
8001 WMA_LOGI("%s: Successfully sent WMI_P2P_LO_START", __func__);
8002 wma->interfaces[params->vdev_id].p2p_lo_in_progress = true;
8003
8004 return ret;
8005}
8006
8007/**
8008 * wma_p2p_lo_stop() - P2P listen offload stop
8009 * @vdev_id: vdev identifier
8010 *
8011 * This function sends WMI command to stop P2P listen offload.
8012 *
8013 * Return: QDF_STATUS enumeration
8014 */
8015QDF_STATUS wma_p2p_lo_stop(u_int32_t vdev_id)
8016{
8017 wmi_buf_t buf;
8018 wmi_p2p_lo_stop_cmd_fixed_param *cmd;
8019 int32_t len;
8020 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
8021 int ret;
8022
8023 if (NULL == wma) {
8024 WMA_LOGE("%s: wma context is NULL", __func__);
8025 return QDF_STATUS_E_INVAL;
8026 }
8027
8028 len = sizeof(*cmd);
8029 buf = wmi_buf_alloc(wma->wmi_handle, len);
8030 if (!buf) {
8031 WMA_LOGP("%s: failed to allocate memory for p2p lo stop",
8032 __func__);
8033 return QDF_STATUS_E_NOMEM;
8034 }
8035 cmd = (wmi_p2p_lo_stop_cmd_fixed_param *)wmi_buf_data(buf);
8036
8037 WMITLV_SET_HDR(&cmd->tlv_header,
8038 WMITLV_TAG_STRUC_wmi_p2p_lo_stop_cmd_fixed_param,
8039 WMITLV_GET_STRUCT_TLVLEN(
8040 wmi_p2p_lo_stop_cmd_fixed_param));
8041
8042 cmd->vdev_id = vdev_id;
8043
8044 WMA_LOGI("%s: Sending WMI_P2P_LO_STOP command", __func__);
8045
8046 ret = wmi_unified_cmd_send(wma->wmi_handle,
8047 buf, len,
8048 WMI_P2P_LISTEN_OFFLOAD_STOP_CMDID);
8049 if (ret) {
8050 WMA_LOGE("Failed to send p2p lo stop: %d", ret);
8051 wmi_buf_free(buf);
8052 }
8053
8054 WMA_LOGI("%s: Successfully sent WMI_P2P_LO_STOP", __func__);
8055 wma->interfaces[vdev_id].p2p_lo_in_progress = false;
8056
8057 return ret;
8058}
8059
8060/**
8061 * wma_p2p_lo_event_handler() - p2p lo event
8062 * @handle: the WMA handle
8063 * @event_buf: buffer with the event parameters
8064 * @len: length of the buffer
8065 *
8066 * This function receives P2P listen offload stop event from FW and
8067 * pass the event information to upper layer.
8068 *
8069 * Return: 0 on success
8070 */
8071int wma_p2p_lo_event_handler(void *handle, uint8_t *event_buf,
8072 uint32_t len)
8073{
8074 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
8075 struct sir_p2p_lo_event *event;
8076 WMI_P2P_LISTEN_OFFLOAD_STOPPED_EVENTID_param_tlvs *param_tlvs;
8077 wmi_p2p_lo_stopped_event_fixed_param *fix_param;
8078 tpAniSirGlobal p_mac = cds_get_context(QDF_MODULE_ID_PE);
8079
Varun Reddy Yeturuc48ad6e2016-09-09 14:31:58 -07008080 if (!wma) {
8081 WMA_LOGE("%s: Invalid WMA Context", __func__);
8082 return -EINVAL;
8083 }
8084
Peng Xu8fdaa492016-06-22 10:20:47 -07008085 if (!p_mac) {
8086 WMA_LOGE("%s: Invalid p_mac", __func__);
8087 return -EINVAL;
8088 }
8089
8090 if (!p_mac->sme.p2p_lo_event_callback) {
8091 WMA_LOGE("%s: Callback not registered", __func__);
8092 return -EINVAL;
8093 }
8094
8095 param_tlvs = (WMI_P2P_LISTEN_OFFLOAD_STOPPED_EVENTID_param_tlvs *)
8096 event_buf;
8097 fix_param = param_tlvs->fixed_param;
8098 event = qdf_mem_malloc(sizeof(*event));
8099 if (event == NULL) {
8100 WMA_LOGE("Event allocation failed");
8101 return -ENOMEM;
8102 }
8103 event->vdev_id = fix_param->vdev_id;
8104 event->reason_code = fix_param->reason;
8105
8106 p_mac->sme.p2p_lo_event_callback(p_mac->hHdd, event);
8107
8108 wma->interfaces[event->vdev_id].p2p_lo_in_progress = false;
8109
8110 return 0;
8111}
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308112
8113/**
8114 * wma_get_wakelock_stats() - Collects wake lock stats
8115 * @wake_lock_stats: wakelock structure to be filled
8116 *
8117 * This function collects wake lock stats
8118 *
8119 * Return: VOS_STATUS_SUCCESS on success, error number otherwise
8120 */
8121QDF_STATUS wma_get_wakelock_stats(struct sir_wake_lock_stats *wake_lock_stats)
8122{
8123 tp_wma_handle wma_handle;
8124
8125 wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
8126
8127 if (!wake_lock_stats) {
8128 WMA_LOGE("%s: invalid pointer", __func__);
8129 return QDF_STATUS_E_INVAL;
8130 }
8131
8132 if (!wma_handle) {
8133 WMA_LOGE("%s: WMA context is invalid!", __func__);
8134 return QDF_STATUS_E_INVAL;
8135 }
8136
8137 wake_lock_stats->wow_ucast_wake_up_count =
8138 wma_handle->wow_ucast_wake_up_count;
8139 wake_lock_stats->wow_bcast_wake_up_count =
8140 wma_handle->wow_bcast_wake_up_count;
8141 wake_lock_stats->wow_ipv4_mcast_wake_up_count =
8142 wma_handle->wow_ipv4_mcast_wake_up_count;
8143 wake_lock_stats->wow_ipv6_mcast_wake_up_count =
8144 wma_handle->wow_ipv6_mcast_wake_up_count;
8145 wake_lock_stats->wow_ipv6_mcast_ra_stats =
8146 wma_handle->wow_ipv6_mcast_ra_stats;
8147 wake_lock_stats->wow_ipv6_mcast_ns_stats =
8148 wma_handle->wow_ipv6_mcast_ns_stats;
8149 wake_lock_stats->wow_ipv6_mcast_na_stats =
8150 wma_handle->wow_ipv6_mcast_na_stats;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308151 wake_lock_stats->wow_icmpv4_count = wma_handle->wow_icmpv4_count;
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308152 wake_lock_stats->wow_icmpv6_count =
8153 wma_handle->wow_icmpv6_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308154
8155 return QDF_STATUS_SUCCESS;
8156}
Anurag Chouhanbf5e0e22016-09-12 12:54:09 +05308157
8158/**
8159 * wma_process_fw_test_cmd() - send unit test command to fw.
8160 * @handle: wma handle
8161 * @wma_fwtest: fw test command
8162 *
8163 * This function send fw test command to fw.
8164 *
8165 * Return: none
8166 */
8167void wma_process_fw_test_cmd(WMA_HANDLE handle,
8168 struct set_fwtest_params *wma_fwtest)
8169{
8170 tp_wma_handle wma_handle = (tp_wma_handle) handle;
8171
8172 if (!wma_handle || !wma_handle->wmi_handle) {
8173 WMA_LOGE("%s: WMA is closed, can not issue fw test cmd",
8174 __func__);
8175 return;
8176 }
8177
8178 if (wmi_unified_fw_test_cmd(wma_handle->wmi_handle,
8179 (struct set_fwtest_params *)wma_fwtest)) {
8180 WMA_LOGE("%s: Failed to issue fw test cmd",
8181 __func__);
8182 return;
8183 }
8184}
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05308185
8186/**
8187 * wma_enable_disable_caevent_ind() - Issue WMI command to enable or
8188 * disable ca event indication
8189 * @wma: wma handler
8190 * @val: boolean value true or false
8191 *
8192 * Return: QDF_STATUS
8193 */
8194QDF_STATUS wma_enable_disable_caevent_ind(tp_wma_handle wma, uint8_t val)
8195{
8196 WMI_CHAN_AVOID_RPT_ALLOW_CMD_fixed_param *cmd;
8197 wmi_buf_t wmi_buf;
8198 uint8_t *buf_ptr;
8199 uint32_t len;
8200
8201 if (!wma || !wma->wmi_handle) {
8202 WMA_LOGE(FL("WMA is closed, can not issue set/clear CA"));
8203 return QDF_STATUS_E_INVAL;
8204 }
8205
8206 len = sizeof(*cmd);
8207 wmi_buf = wmi_buf_alloc(wma->wmi_handle, len);
8208 if (!wmi_buf) {
8209 WMA_LOGE(FL("wmi_buf_alloc failed"));
8210 return QDF_STATUS_E_NOMEM;
8211 }
8212 buf_ptr = (uint8_t *) wmi_buf_data(wmi_buf);
8213 cmd = (WMI_CHAN_AVOID_RPT_ALLOW_CMD_fixed_param *) buf_ptr;
8214 WMITLV_SET_HDR(&cmd->tlv_header,
8215 WMITLV_TAG_STRUC_WMI_CHAN_AVOID_RPT_ALLOW_CMD_fixed_param,
8216 WMITLV_GET_STRUCT_TLVLEN(
8217 WMI_CHAN_AVOID_RPT_ALLOW_CMD_fixed_param));
8218 cmd->rpt_allow = val;
8219 if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len,
8220 WMI_CHAN_AVOID_RPT_ALLOW_CMDID)) {
8221 WMA_LOGE(FL("Failed to send enable/disable CA event command"));
8222 wmi_buf_free(wmi_buf);
8223 return QDF_STATUS_E_FAILURE;
8224 }
8225
8226 return QDF_STATUS_SUCCESS;
8227}
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +05308228
8229/**
8230 * wma_encrypt_decrypt_msg() -
8231 * @encrypt_decrypt_params: encryption/decryption params
8232 * @data_len: data length
8233 * @encrypt_decrypt_cb: encrypt/decrypt callback
8234 *
8235 * This function sends WMI command to check encryption/decryption engine.
8236 *
8237 * Return: QDF_STATUS enumeration
8238 */
8239QDF_STATUS wma_encrypt_decrypt_msg(WMA_HANDLE handle,
8240 struct encrypt_decrypt_req_params *encrypt_decrypt_params)
8241{
8242 int ret;
8243 tp_wma_handle wma = (tp_wma_handle) handle;
8244
8245 if (!wma || !wma->wmi_handle) {
8246 WMA_LOGE("%s: WMA is closed, can not issue encrypt/decrypt msg",
8247 __func__);
8248 return QDF_STATUS_E_INVAL;
8249 }
8250
8251 if (encrypt_decrypt_params == NULL) {
8252 WMA_LOGE("%s: encrypt/decrypt ptr NULL",
8253 __func__);
8254 return QDF_STATUS_E_INVAL;
8255 }
8256
8257 ret = wmi_unified_encrypt_decrypt_send_cmd(wma->wmi_handle,
8258 encrypt_decrypt_params);
8259
8260 return ret;
8261}
8262
8263/**
8264 * wma_encrypt_decrypt_msg_handler() - handle encrypt/decrypt data
8265 * indicated by FW
8266 * @handle: wma context
8267 * @data: event buffer
8268 * @data len: length of event buffer
8269 *
8270 * Return: 0 on success
8271 */
8272int wma_encrypt_decrypt_msg_handler(void *handle, uint8_t *data,
8273 uint32_t data_len)
8274{
8275 WMI_VDEV_ENCRYPT_DECRYPT_DATA_RESP_EVENTID_param_tlvs *param_buf;
8276 wmi_vdev_encrypt_decrypt_data_resp_event_fixed_param *data_event;
8277 struct sir_encrypt_decrypt_rsp_params encrypt_decrypt_rsp_params;
8278 tp_wma_handle wma = handle;
8279 u_int8_t *buf_ptr;
8280 tpAniSirGlobal pmac;
8281
8282 if (data == NULL) {
8283 WMA_LOGE("%s: invalid pointer", __func__);
8284 return -EINVAL;
8285 }
8286
8287 if (wma == NULL) {
8288 WMA_LOGE("%s: wma context is NULL", __func__);
8289 return -EINVAL;
8290 }
8291
8292 WMA_LOGE("%s: received WMI_VDEV_ENCRYPT_DECRYPT_DATA_RESP_EVENTID ",
8293 __func__);
8294
8295 pmac = (tpAniSirGlobal)cds_get_context(QDF_MODULE_ID_PE);
8296
8297 if (!pmac) {
8298 WMA_LOGE("%s: Invalid pmac", __func__);
8299 return -EINVAL;
8300 }
8301 if (!pmac->sme.encrypt_decrypt_cb) {
8302 WMA_LOGE("%s: Callback not registered", __func__);
8303 return -EINVAL;
8304 }
8305
8306 param_buf =
8307 (WMI_VDEV_ENCRYPT_DECRYPT_DATA_RESP_EVENTID_param_tlvs *)data;
8308 if (!param_buf) {
8309 WMA_LOGE("%s: Invalid response data buf", __func__);
8310 return -EINVAL;
8311 }
8312
8313 data_event = param_buf->fixed_param;
8314
8315 encrypt_decrypt_rsp_params.vdev_id = data_event->vdev_id;
8316 encrypt_decrypt_rsp_params.status = data_event->status;
8317 encrypt_decrypt_rsp_params.data_length = data_event->data_length;
8318
8319 if (encrypt_decrypt_rsp_params.data_length) {
8320 buf_ptr =
8321 (uint8_t *)data_event +
8322 sizeof(
8323 wmi_vdev_encrypt_decrypt_data_resp_event_fixed_param) +
8324 WMI_TLV_HDR_SIZE;
8325
8326 encrypt_decrypt_rsp_params.data = buf_ptr;
8327 }
8328
8329 pmac->sme.encrypt_decrypt_cb(pmac->hHdd, &encrypt_decrypt_rsp_params);
8330
8331 return 0;
8332}