blob: 3e526e53b38b38f1599f24ad6a292a954e7a4701 [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
36#include "wma.h"
37#include "wma_api.h"
38#include "cds_api.h"
39#include "wmi_unified_api.h"
40#include "wlan_qct_sys.h"
41#include "wni_api.h"
42#include "ani_global.h"
43#include "wmi_unified.h"
44#include "wni_cfg.h"
45#include "cfg_api.h"
Manjunathappa Prakash3454fd62016-04-01 08:52:06 -070046#include "ol_txrx_ctrl_api.h"
47#include <cdp_txrx_tx_delay.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080048#include "wlan_tgt_def_config.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"
73
74#ifndef ARRAY_LENGTH
75#define ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0]))
76#endif
77
78#define WMA_WOW_STA_WAKE_UP_EVENTS ((1 << WOW_CSA_IE_EVENT) |\
79 (1 << WOW_CLIENT_KICKOUT_EVENT) |\
80 (1 << WOW_PATTERN_MATCH_EVENT) |\
81 (1 << WOW_MAGIC_PKT_RECVD_EVENT) |\
82 (1 << WOW_DEAUTH_RECVD_EVENT) |\
83 (1 << WOW_DISASSOC_RECVD_EVENT) |\
84 (1 << WOW_BMISS_EVENT) |\
85 (1 << WOW_GTK_ERR_EVENT) |\
86 (1 << WOW_BETTER_AP_EVENT) |\
87 (1 << WOW_HTT_EVENT) |\
88 (1 << WOW_RA_MATCH_EVENT) |\
89 (1 << WOW_NLO_DETECTED_EVENT) |\
90 (1 << WOW_EXTSCAN_EVENT))\
91
92#define WMA_WOW_SAP_WAKE_UP_EVENTS ((1 << WOW_PROBE_REQ_WPS_IE_EVENT) |\
93 (1 << WOW_PATTERN_MATCH_EVENT) |\
94 (1 << WOW_AUTH_REQ_EVENT) |\
95 (1 << WOW_ASSOC_REQ_EVENT) |\
96 (1 << WOW_DEAUTH_RECVD_EVENT) |\
97 (1 << WOW_DISASSOC_RECVD_EVENT) |\
98 (1 << WOW_HTT_EVENT))\
99
100static const uint8_t arp_ptrn[] = {0x08, 0x06};
101static const uint8_t arp_mask[] = {0xff, 0xff};
102static const uint8_t ns_ptrn[] = {0x86, 0xDD};
103static const uint8_t discvr_ptrn[] = {0xe0, 0x00, 0x00, 0xf8};
104static const uint8_t discvr_mask[] = {0xf0, 0x00, 0x00, 0xf8};
105
106#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
107/**
108 * wma_post_auto_shutdown_msg() - to post auto shutdown event to sme
109 *
110 * Return: 0 for success or error code
111 */
112static int wma_post_auto_shutdown_msg(void)
113{
114 tSirAutoShutdownEvtParams *auto_sh_evt;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530115 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800116 cds_msg_t sme_msg = { 0 };
117
118 auto_sh_evt = (tSirAutoShutdownEvtParams *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530119 qdf_mem_malloc(sizeof(tSirAutoShutdownEvtParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800120 if (!auto_sh_evt) {
121 WMA_LOGE(FL("No Mem"));
122 return -ENOMEM;
123 }
124
125 auto_sh_evt->shutdown_reason =
126 WMI_HOST_AUTO_SHUTDOWN_REASON_TIMER_EXPIRY;
127 sme_msg.type = eWNI_SME_AUTO_SHUTDOWN_IND;
128 sme_msg.bodyptr = auto_sh_evt;
129 sme_msg.bodyval = 0;
130
Anurag Chouhan6d760662016-02-20 16:05:43 +0530131 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530132 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800133 WMA_LOGE("Fail to post eWNI_SME_AUTO_SHUTDOWN_IND msg to SME");
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530134 qdf_mem_free(auto_sh_evt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800135 return -EINVAL;
136 }
137
138 return 0;
139}
140#endif
141/**
142 * wma_send_snr_request() - send request to fw to get RSSI stats
143 * @wma_handle: wma handle
144 * @pGetRssiReq: get RSSI request
145 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530146 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800147 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530148QDF_STATUS wma_send_snr_request(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800149 void *pGetRssiReq)
150{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800151 tAniGetRssiReq *pRssiBkUp = NULL;
152
153 /* command is in progess */
154 if (NULL != wma_handle->pGetRssiReq)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530155 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800156
157 /* create a copy of csrRssiCallback to send rssi value
158 * after wmi event
159 */
160 if (pGetRssiReq) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530161 pRssiBkUp = qdf_mem_malloc(sizeof(tAniGetRssiReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800162 if (!pRssiBkUp) {
163 WMA_LOGE("Failed to allocate memory for tAniGetRssiReq");
164 wma_handle->pGetRssiReq = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530165 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800166 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530167 qdf_mem_set(pRssiBkUp, sizeof(tAniGetRssiReq), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800168 pRssiBkUp->sessionId =
169 ((tAniGetRssiReq *) pGetRssiReq)->sessionId;
170 pRssiBkUp->rssiCallback =
171 ((tAniGetRssiReq *) pGetRssiReq)->rssiCallback;
172 pRssiBkUp->pDevContext =
173 ((tAniGetRssiReq *) pGetRssiReq)->pDevContext;
174 wma_handle->pGetRssiReq = (void *)pRssiBkUp;
175 }
176
Govind Singhaa64c242016-03-08 11:31:49 +0530177 if (wmi_unified_snr_request_cmd(wma_handle->wmi_handle)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800178 WMA_LOGE("Failed to send host stats request to fw");
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530179 qdf_mem_free(pRssiBkUp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800180 wma_handle->pGetRssiReq = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530181 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800182 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530183 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800184}
185
186/**
187 * wma_get_snr() - get RSSI from fw
188 * @psnr_req: request params
189 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530190 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800191 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530192QDF_STATUS wma_get_snr(tAniGetSnrReq *psnr_req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800193{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800194 tAniGetSnrReq *psnr_req_bkp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800195 tp_wma_handle wma_handle = NULL;
196 struct wma_txrx_node *intr;
197
Anurag Chouhan6d760662016-02-20 16:05:43 +0530198 wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800199
200 if (NULL == wma_handle) {
201 WMA_LOGE("%s : Failed to get wma_handle", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530202 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800203 }
204
205 intr = &wma_handle->interfaces[psnr_req->sessionId];
206 /* command is in progess */
207 if (NULL != intr->psnr_req) {
208 WMA_LOGE("%s : previous snr request is pending", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530209 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800210 }
211
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530212 psnr_req_bkp = qdf_mem_malloc(sizeof(tAniGetSnrReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800213 if (!psnr_req_bkp) {
214 WMA_LOGE("Failed to allocate memory for tAniGetSnrReq");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530215 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800216 }
217
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530218 qdf_mem_set(psnr_req_bkp, sizeof(tAniGetSnrReq), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800219 psnr_req_bkp->staId = psnr_req->staId;
220 psnr_req_bkp->pDevContext = psnr_req->pDevContext;
221 psnr_req_bkp->snrCallback = psnr_req->snrCallback;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800222 intr->psnr_req = (void *)psnr_req_bkp;
Govind Singhaa64c242016-03-08 11:31:49 +0530223
224 if (wmi_unified_snr_cmd(wma_handle->wmi_handle,
225 psnr_req->sessionId)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800226 WMA_LOGE("Failed to send host stats request to fw");
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530227 qdf_mem_free(psnr_req_bkp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800228 intr->psnr_req = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530229 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800230 }
231
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530232 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800233}
234
235/**
236 * wma_process_link_status_req() - process link status request from UMAC
237 * @wma: wma handle
238 * @pGetLinkStatus: get link params
239 *
240 * Return: none
241 */
242void wma_process_link_status_req(tp_wma_handle wma,
243 tAniGetLinkStatus *pGetLinkStatus)
244{
Govind Singhaa64c242016-03-08 11:31:49 +0530245 struct link_status_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800246 struct wma_txrx_node *iface =
247 &wma->interfaces[pGetLinkStatus->sessionId];
248
249 if (iface->plink_status_req) {
250 WMA_LOGE("%s:previous link status request is pending,deleting the new request",
251 __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530252 qdf_mem_free(pGetLinkStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800253 return;
254 }
255
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800256 iface->plink_status_req = pGetLinkStatus;
Govind Singhaa64c242016-03-08 11:31:49 +0530257 cmd.session_id = pGetLinkStatus->sessionId;
258 if (wmi_unified_link_status_req_cmd(wma->wmi_handle, &cmd)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800259 WMA_LOGE("Failed to send WMI link status request to fw");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800260 iface->plink_status_req = NULL;
261 goto end;
262 }
263
264 return;
265
266end:
267 wma_post_link_status(pGetLinkStatus, LINK_STATUS_LEGACY);
268}
269
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700270#ifdef WLAN_FEATURE_TSF
271/**
272 * wma_vdev_tsf_handler() - handle tsf event indicated by FW
273 * @handle: wma context
274 * @data: event buffer
275 * @data len: length of event buffer
276 *
277 * Return: 0 on success
278 */
279int wma_vdev_tsf_handler(void *handle, uint8_t *data, uint32_t data_len)
280{
281 cds_msg_t tsf_msg = {0};
282 WMI_VDEV_TSF_REPORT_EVENTID_param_tlvs *param_buf;
283 wmi_vdev_tsf_report_event_fixed_param *tsf_event;
284 struct stsf *ptsf;
285
286 if (data == NULL) {
287 WMA_LOGE("%s: invalid pointer", __func__);
288 return -EINVAL;
289 }
290 ptsf = qdf_mem_malloc(sizeof(*ptsf));
291 if (NULL == ptsf) {
292 WMA_LOGE("%s: failed to allocate tsf data structure", __func__);
293 return -ENOMEM;
294 }
295
296 param_buf = (WMI_VDEV_TSF_REPORT_EVENTID_param_tlvs *)data;
297 tsf_event = param_buf->fixed_param;
298
299 ptsf->vdev_id = tsf_event->vdev_id;
300 ptsf->tsf_low = tsf_event->tsf_low;
301 ptsf->tsf_high = tsf_event->tsf_high;
302
303 WMA_LOGD("%s: receive WMI_VDEV_TSF_REPORT_EVENTID ", __func__);
304 WMA_LOGD("%s: vdev_id = %u,tsf_low =%u, tsf_high = %u", __func__,
305 ptsf->vdev_id, ptsf->tsf_low, ptsf->tsf_high);
306
307 tsf_msg.type = eWNI_SME_TSF_EVENT;
308 tsf_msg.bodyptr = ptsf;
309 tsf_msg.bodyval = 0;
310
311 if (QDF_STATUS_SUCCESS !=
312 cds_mq_post_message(CDS_MQ_ID_SME, &tsf_msg)) {
313
314 WMA_LOGP("%s: Failed to post eWNI_SME_TSF_EVENT", __func__);
315 qdf_mem_free(ptsf);
316 return -EINVAL;
317 }
318 return 0;
319}
320
321/**
322 * wma_capture_tsf() - send wmi to fw to capture tsf
323 * @wma_handle: wma handler
324 * @vdev_id: vdev id
325 *
326 * Return: wmi send state
327 */
328QDF_STATUS wma_capture_tsf(tp_wma_handle wma_handle, uint32_t vdev_id)
329{
330 QDF_STATUS status = QDF_STATUS_SUCCESS;
331 wmi_buf_t buf;
332 wmi_vdev_tsf_tstamp_action_cmd_fixed_param *cmd;
333 int ret;
334 int len = sizeof(*cmd);
335
336 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
337 if (!buf) {
338 WMA_LOGP("%s: failed to allocate memory for cap tsf cmd",
339 __func__);
340 return QDF_STATUS_E_NOMEM;
341 }
342
343 cmd = (wmi_vdev_tsf_tstamp_action_cmd_fixed_param *) wmi_buf_data(buf);
344 cmd->vdev_id = vdev_id;
345 cmd->tsf_action = TSF_TSTAMP_CAPTURE_REQ;
346
347 WMA_LOGD("%s :vdev_id %u, TSF_TSTAMP_CAPTURE_REQ", __func__,
348 cmd->vdev_id);
349
350 WMITLV_SET_HDR(&cmd->tlv_header,
351 WMITLV_TAG_STRUC_wmi_vdev_tsf_tstamp_action_cmd_fixed_param,
352 WMITLV_GET_STRUCT_TLVLEN(
353 wmi_vdev_tsf_tstamp_action_cmd_fixed_param));
354
355 ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
356 WMI_VDEV_TSF_TSTAMP_ACTION_CMDID);
357 if (ret != EOK) {
358 WMA_LOGE("wmi_unified_cmd_send returned Error %d", status);
359 status = QDF_STATUS_E_FAILURE;
360 goto error;
361 }
362
363 return QDF_STATUS_SUCCESS;
364
365error:
366 if (buf)
367 wmi_buf_free(buf);
368 return status;
369}
370
371/**
372 * wma_reset_tsf_gpio() - send wmi to fw to reset GPIO
373 * @wma_handle: wma handler
374 * @vdev_id: vdev id
375 *
376 * Return: wmi send state
377 */
378QDF_STATUS wma_reset_tsf_gpio(tp_wma_handle wma_handle, uint32_t vdev_id)
379{
380 QDF_STATUS status = QDF_STATUS_SUCCESS;
381 wmi_buf_t buf;
382 wmi_vdev_tsf_tstamp_action_cmd_fixed_param *cmd;
383 int ret;
384 int len = sizeof(*cmd);
385 uint8_t *buf_ptr;
386
387 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
388 if (!buf) {
389 WMA_LOGP("%s: failed to allocate memory for reset tsf gpio",
390 __func__);
391 return QDF_STATUS_E_NOMEM;
392 }
393
394 buf_ptr = (uint8_t *) wmi_buf_data(buf);
395 cmd = (wmi_vdev_tsf_tstamp_action_cmd_fixed_param *) buf_ptr;
396 cmd->vdev_id = vdev_id;
397 cmd->tsf_action = TSF_TSTAMP_CAPTURE_RESET;
398
399 WMA_LOGD("%s :vdev_id %u, TSF_TSTAMP_CAPTURE_RESET", __func__,
400 cmd->vdev_id);
401
402 WMITLV_SET_HDR(&cmd->tlv_header,
403 WMITLV_TAG_STRUC_wmi_vdev_tsf_tstamp_action_cmd_fixed_param,
404 WMITLV_GET_STRUCT_TLVLEN(
405 wmi_vdev_tsf_tstamp_action_cmd_fixed_param));
406
407 ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
408 WMI_VDEV_TSF_TSTAMP_ACTION_CMDID);
409
410 if (ret != EOK) {
411 WMA_LOGE("wmi_unified_cmd_send returned Error %d", status);
412 status = QDF_STATUS_E_FAILURE;
413 goto error;
414 }
415 return QDF_STATUS_SUCCESS;
416
417error:
418 if (buf)
419 wmi_buf_free(buf);
420 return status;
421}
422#else
423QDF_STATUS wma_capture_tsf(tp_wma_handle wma_handle, uint32_t vdev_id)
424{
425 return QDF_STATUS_SUCCESS;
426}
427
428QDF_STATUS wma_reset_tsf_gpio(tp_wma_handle wma_handle, uint32_t vdev_id)
429{
430 return QDF_STATUS_SUCCESS;
431}
432
433int wma_vdev_tsf_handler(void *handle, uint8_t *data, uint32_t data_len)
434{
435 return 0;
436}
437#endif
438
439
440
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800441#ifdef FEATURE_WLAN_LPHB
442/**
443 * wma_lphb_conf_hbenable() - enable command of LPHB configuration requests
444 * @wma_handle: WMA handle
445 * @lphb_conf_req: configuration info
446 * @by_user: whether this call is from user or cached resent
447 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530448 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800449 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530450QDF_STATUS wma_lphb_conf_hbenable(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800451 tSirLPHBReq *lphb_conf_req, bool by_user)
452{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530453 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800454 int status = 0;
455 tSirLPHBEnableStruct *ts_lphb_enable;
Govind Singhaa64c242016-03-08 11:31:49 +0530456 wmi_hb_set_enable_cmd_fixed_param hb_enable_fp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800457 int i;
458
459 if (lphb_conf_req == NULL) {
460 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530461 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800462 }
463
464 ts_lphb_enable = &(lphb_conf_req->params.lphbEnableReq);
465 WMA_LOGI("%s: WMA --> WMI_HB_SET_ENABLE enable=%d, item=%d, session=%d",
466 __func__,
467 ts_lphb_enable->enable,
468 ts_lphb_enable->item, ts_lphb_enable->session);
469
470 if ((ts_lphb_enable->item != 1) && (ts_lphb_enable->item != 2)) {
471 WMA_LOGE("%s : LPHB configuration wrong item %d",
472 __func__, ts_lphb_enable->item);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530473 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800474 }
475
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800476
477 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530478 hb_enable_fp.vdev_id = ts_lphb_enable->session;
479 hb_enable_fp.enable = ts_lphb_enable->enable;
480 hb_enable_fp.item = ts_lphb_enable->item;
481 hb_enable_fp.session = ts_lphb_enable->session;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800482
Govind Singhaa64c242016-03-08 11:31:49 +0530483 status = wmi_unified_lphb_config_hbenable_cmd(wma_handle->wmi_handle,
484 &hb_enable_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800485 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530486 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800487 goto error;
488 }
489
490 if (by_user) {
491 /* target already configured, now cache command status */
492 if (ts_lphb_enable->enable) {
493 i = ts_lphb_enable->item - 1;
494 wma_handle->wow.lphb_cache[i].cmd
495 = LPHB_SET_EN_PARAMS_INDID;
496 wma_handle->wow.lphb_cache[i].params.lphbEnableReq.
497 enable = ts_lphb_enable->enable;
498 wma_handle->wow.lphb_cache[i].params.lphbEnableReq.
499 item = ts_lphb_enable->item;
500 wma_handle->wow.lphb_cache[i].params.lphbEnableReq.
501 session = ts_lphb_enable->session;
502
503 WMA_LOGI("%s: cached LPHB status in WMA context for item %d",
504 __func__, i);
505 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530506 qdf_mem_zero((void *)&wma_handle->wow.lphb_cache,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800507 sizeof(wma_handle->wow.lphb_cache));
508 WMA_LOGI("%s: cleared all cached LPHB status in WMA context",
509 __func__);
510 }
511 }
512
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530513 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800514error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530515 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800516}
517
518/**
519 * wma_lphb_conf_tcp_params() - set tcp params of LPHB configuration requests
520 * @wma_handle: wma handle
521 * @lphb_conf_req: lphb config request
522 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530523 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800524 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530525QDF_STATUS wma_lphb_conf_tcp_params(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800526 tSirLPHBReq *lphb_conf_req)
527{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530528 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800529 int status = 0;
530 tSirLPHBTcpParamStruct *ts_lphb_tcp_param;
Govind Singhaa64c242016-03-08 11:31:49 +0530531 wmi_hb_set_tcp_params_cmd_fixed_param hb_tcp_params_fp = {0};
532
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800533
534 if (lphb_conf_req == NULL) {
535 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530536 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800537 }
538
539 ts_lphb_tcp_param = &(lphb_conf_req->params.lphbTcpParamReq);
Srinivas Girigowda9dc32cf2015-11-19 14:47:04 -0800540 WMA_LOGI("%s: WMA --> WMI_HB_SET_TCP_PARAMS srv_ip=%08x, "
541 "dev_ip=%08x, src_port=%d, dst_port=%d, timeout=%d, "
542 "session=%d, gateway_mac="MAC_ADDRESS_STR", timePeriodSec=%d, "
543 "tcpSn=%d", __func__, ts_lphb_tcp_param->srv_ip,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800544 ts_lphb_tcp_param->dev_ip, ts_lphb_tcp_param->src_port,
545 ts_lphb_tcp_param->dst_port, ts_lphb_tcp_param->timeout,
Srinivas Girigowda9dc32cf2015-11-19 14:47:04 -0800546 ts_lphb_tcp_param->session,
547 MAC_ADDR_ARRAY(ts_lphb_tcp_param->gateway_mac.bytes),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800548 ts_lphb_tcp_param->timePeriodSec, ts_lphb_tcp_param->tcpSn);
549
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800550 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530551 hb_tcp_params_fp.vdev_id = ts_lphb_tcp_param->session;
552 hb_tcp_params_fp.srv_ip = ts_lphb_tcp_param->srv_ip;
553 hb_tcp_params_fp.dev_ip = ts_lphb_tcp_param->dev_ip;
554 hb_tcp_params_fp.seq = ts_lphb_tcp_param->tcpSn;
555 hb_tcp_params_fp.src_port = ts_lphb_tcp_param->src_port;
556 hb_tcp_params_fp.dst_port = ts_lphb_tcp_param->dst_port;
557 hb_tcp_params_fp.interval = ts_lphb_tcp_param->timePeriodSec;
558 hb_tcp_params_fp.timeout = ts_lphb_tcp_param->timeout;
559 hb_tcp_params_fp.session = ts_lphb_tcp_param->session;
Srinivas Girigowda9dc32cf2015-11-19 14:47:04 -0800560 WMI_CHAR_ARRAY_TO_MAC_ADDR(ts_lphb_tcp_param->gateway_mac.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +0530561 &hb_tcp_params_fp.gateway_mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800562
Govind Singhaa64c242016-03-08 11:31:49 +0530563 status = wmi_unified_lphb_config_tcp_params_cmd(wma_handle->wmi_handle,
564 &hb_tcp_params_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800565 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530566 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800567 goto error;
568 }
569
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530570 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800571error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530572 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800573}
574
575/**
576 * wma_lphb_conf_tcp_pkt_filter() - configure tcp packet filter command of LPHB
577 * @wma_handle: wma handle
578 * @lphb_conf_req: lphb config request
579 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530580 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800581 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530582QDF_STATUS wma_lphb_conf_tcp_pkt_filter(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800583 tSirLPHBReq *lphb_conf_req)
584{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530585 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800586 int status = 0;
587 tSirLPHBTcpFilterStruct *ts_lphb_tcp_filter;
Govind Singhaa64c242016-03-08 11:31:49 +0530588 wmi_hb_set_tcp_pkt_filter_cmd_fixed_param hb_tcp_filter_fp = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800589
590 if (lphb_conf_req == NULL) {
591 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530592 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800593 }
594
595 ts_lphb_tcp_filter = &(lphb_conf_req->params.lphbTcpFilterReq);
596 WMA_LOGI("%s: WMA --> WMI_HB_SET_TCP_PKT_FILTER length=%d, offset=%d, session=%d, "
597 "filter=%2x:%2x:%2x:%2x:%2x:%2x ...", __func__,
598 ts_lphb_tcp_filter->length, ts_lphb_tcp_filter->offset,
599 ts_lphb_tcp_filter->session, ts_lphb_tcp_filter->filter[0],
600 ts_lphb_tcp_filter->filter[1], ts_lphb_tcp_filter->filter[2],
601 ts_lphb_tcp_filter->filter[3], ts_lphb_tcp_filter->filter[4],
602 ts_lphb_tcp_filter->filter[5]);
603
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800604 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530605 hb_tcp_filter_fp.vdev_id = ts_lphb_tcp_filter->session;
606 hb_tcp_filter_fp.length = ts_lphb_tcp_filter->length;
607 hb_tcp_filter_fp.offset = ts_lphb_tcp_filter->offset;
608 hb_tcp_filter_fp.session = ts_lphb_tcp_filter->session;
609 memcpy((void *)&hb_tcp_filter_fp.filter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800610 (void *)&ts_lphb_tcp_filter->filter,
611 WMI_WLAN_HB_MAX_FILTER_SIZE);
612
Govind Singhaa64c242016-03-08 11:31:49 +0530613 status = wmi_unified_lphb_config_tcp_pkt_filter_cmd(wma_handle->wmi_handle,
614 &hb_tcp_filter_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800615 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530616 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800617 goto error;
618 }
619
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530620 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800621error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530622 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800623}
624
625/**
626 * wma_lphb_conf_udp_params() - configure udp param command of LPHB
627 * @wma_handle: wma handle
628 * @lphb_conf_req: lphb config request
629 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530630 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800631 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530632QDF_STATUS wma_lphb_conf_udp_params(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800633 tSirLPHBReq *lphb_conf_req)
634{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530635 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800636 int status = 0;
637 tSirLPHBUdpParamStruct *ts_lphb_udp_param;
Govind Singhaa64c242016-03-08 11:31:49 +0530638 wmi_hb_set_udp_params_cmd_fixed_param hb_udp_params_fp = {0};
639
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800640
641 if (lphb_conf_req == NULL) {
642 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530643 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800644 }
645
646 ts_lphb_udp_param = &(lphb_conf_req->params.lphbUdpParamReq);
647 WMA_LOGI("%s: WMA --> WMI_HB_SET_UDP_PARAMS srv_ip=%d, dev_ip=%d, src_port=%d, "
648 "dst_port=%d, interval=%d, timeout=%d, session=%d, "
Srinivas Girigowda9eddfda2015-11-19 14:38:02 -0800649 "gateway_mac="MAC_ADDRESS_STR, __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800650 ts_lphb_udp_param->srv_ip, ts_lphb_udp_param->dev_ip,
651 ts_lphb_udp_param->src_port, ts_lphb_udp_param->dst_port,
652 ts_lphb_udp_param->interval, ts_lphb_udp_param->timeout,
Srinivas Girigowda9eddfda2015-11-19 14:38:02 -0800653 ts_lphb_udp_param->session,
654 MAC_ADDR_ARRAY(ts_lphb_udp_param->gateway_mac.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800655
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800656
657 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530658 hb_udp_params_fp.vdev_id = ts_lphb_udp_param->session;
659 hb_udp_params_fp.srv_ip = ts_lphb_udp_param->srv_ip;
660 hb_udp_params_fp.dev_ip = ts_lphb_udp_param->dev_ip;
661 hb_udp_params_fp.src_port = ts_lphb_udp_param->src_port;
662 hb_udp_params_fp.dst_port = ts_lphb_udp_param->dst_port;
663 hb_udp_params_fp.interval = ts_lphb_udp_param->interval;
664 hb_udp_params_fp.timeout = ts_lphb_udp_param->timeout;
665 hb_udp_params_fp.session = ts_lphb_udp_param->session;
Srinivas Girigowda9eddfda2015-11-19 14:38:02 -0800666 WMI_CHAR_ARRAY_TO_MAC_ADDR(ts_lphb_udp_param->gateway_mac.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +0530667 &hb_udp_params_fp.gateway_mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800668
Govind Singhaa64c242016-03-08 11:31:49 +0530669 status = wmi_unified_lphb_config_udp_params_cmd(wma_handle->wmi_handle,
670 &hb_udp_params_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800671 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530672 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800673 goto error;
674 }
675
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530676 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800677error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530678 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800679}
680
681/**
682 * wma_lphb_conf_udp_pkt_filter() - configure udp pkt filter command of LPHB
683 * @wma_handle: wma handle
684 * @lphb_conf_req: lphb config request
685 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530686 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800687 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530688QDF_STATUS wma_lphb_conf_udp_pkt_filter(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800689 tSirLPHBReq *lphb_conf_req)
690{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530691 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800692 int status = 0;
693 tSirLPHBUdpFilterStruct *ts_lphb_udp_filter;
Govind Singhaa64c242016-03-08 11:31:49 +0530694 wmi_hb_set_udp_pkt_filter_cmd_fixed_param hb_udp_filter_fp = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800695
696 if (lphb_conf_req == NULL) {
697 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530698 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800699 }
700
701 ts_lphb_udp_filter = &(lphb_conf_req->params.lphbUdpFilterReq);
702 WMA_LOGI("%s: WMA --> WMI_HB_SET_UDP_PKT_FILTER length=%d, offset=%d, session=%d, "
703 "filter=%2x:%2x:%2x:%2x:%2x:%2x ...", __func__,
704 ts_lphb_udp_filter->length, ts_lphb_udp_filter->offset,
705 ts_lphb_udp_filter->session, ts_lphb_udp_filter->filter[0],
706 ts_lphb_udp_filter->filter[1], ts_lphb_udp_filter->filter[2],
707 ts_lphb_udp_filter->filter[3], ts_lphb_udp_filter->filter[4],
708 ts_lphb_udp_filter->filter[5]);
709
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800710
711 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530712 hb_udp_filter_fp.vdev_id = ts_lphb_udp_filter->session;
713 hb_udp_filter_fp.length = ts_lphb_udp_filter->length;
714 hb_udp_filter_fp.offset = ts_lphb_udp_filter->offset;
715 hb_udp_filter_fp.session = ts_lphb_udp_filter->session;
716 memcpy((void *)&hb_udp_filter_fp.filter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800717 (void *)&ts_lphb_udp_filter->filter,
718 WMI_WLAN_HB_MAX_FILTER_SIZE);
719
Govind Singhaa64c242016-03-08 11:31:49 +0530720 status = wmi_unified_lphb_config_udp_pkt_filter_cmd(wma_handle->wmi_handle,
721 &hb_udp_filter_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800722 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530723 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800724 goto error;
725 }
726
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530727 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800728error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530729 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800730}
731
732/**
733 * wma_process_lphb_conf_req() - handle LPHB configuration requests
734 * @wma_handle: wma handle
735 * @lphb_conf_req: lphb config request
736 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530737 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800738 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530739QDF_STATUS wma_process_lphb_conf_req(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800740 tSirLPHBReq *lphb_conf_req)
741{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530742 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800743
744 if (lphb_conf_req == NULL) {
745 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530746 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800747 }
748
749 WMA_LOGI("%s : LPHB configuration cmd id is %d", __func__,
750 lphb_conf_req->cmd);
751 switch (lphb_conf_req->cmd) {
752 case LPHB_SET_EN_PARAMS_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530753 qdf_status = wma_lphb_conf_hbenable(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800754 lphb_conf_req, true);
755 break;
756
757 case LPHB_SET_TCP_PARAMS_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530758 qdf_status = wma_lphb_conf_tcp_params(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800759 lphb_conf_req);
760 break;
761
762 case LPHB_SET_TCP_PKT_FILTER_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530763 qdf_status = wma_lphb_conf_tcp_pkt_filter(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800764 lphb_conf_req);
765 break;
766
767 case LPHB_SET_UDP_PARAMS_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530768 qdf_status = wma_lphb_conf_udp_params(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800769 lphb_conf_req);
770 break;
771
772 case LPHB_SET_UDP_PKT_FILTER_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530773 qdf_status = wma_lphb_conf_udp_pkt_filter(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800774 lphb_conf_req);
775 break;
776
777 case LPHB_SET_NETWORK_INFO_INDID:
778 default:
779 break;
780 }
781
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530782 qdf_mem_free(lphb_conf_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530783 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800784}
785#endif /* FEATURE_WLAN_LPHB */
786
787/**
788 * wma_process_dhcp_ind() - process dhcp indication from SME
789 * @wma_handle: wma handle
790 * @ta_dhcp_ind: DHCP indication
791 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530792 * Return: QDF Status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800793 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530794QDF_STATUS wma_process_dhcp_ind(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800795 tAniDHCPInd *ta_dhcp_ind)
796{
797 uint8_t vdev_id;
798 int status = 0;
Govind Singhaa64c242016-03-08 11:31:49 +0530799 wmi_peer_set_param_cmd_fixed_param peer_set_param_fp = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800800
801 if (!ta_dhcp_ind) {
802 WMA_LOGE("%s : DHCP indication is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530803 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800804 }
805
Srinivas Girigowda296105a2015-09-24 16:31:16 -0700806 if (!wma_find_vdev_by_addr(wma_handle,
807 ta_dhcp_ind->adapterMacAddr.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800808 &vdev_id)) {
809 WMA_LOGE("%s: Failed to find vdev id for DHCP indication",
810 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530811 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800812 }
813
814 WMA_LOGI("%s: WMA --> WMI_PEER_SET_PARAM triggered by DHCP, "
815 "msgType=%s,"
816 "device_mode=%d, macAddr=" MAC_ADDRESS_STR,
817 __func__,
818 ta_dhcp_ind->msgType == WMA_DHCP_START_IND ?
819 "WMA_DHCP_START_IND" : "WMA_DHCP_STOP_IND",
820 ta_dhcp_ind->device_mode,
Srinivas Girigowda296105a2015-09-24 16:31:16 -0700821 MAC_ADDR_ARRAY(ta_dhcp_ind->peerMacAddr.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800822
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800823 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530824 peer_set_param_fp.vdev_id = vdev_id;
825 peer_set_param_fp.param_id = WMI_PEER_CRIT_PROTO_HINT_ENABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800826 if (WMA_DHCP_START_IND == ta_dhcp_ind->msgType)
Govind Singhaa64c242016-03-08 11:31:49 +0530827 peer_set_param_fp.param_value = 1;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800828 else
Govind Singhaa64c242016-03-08 11:31:49 +0530829 peer_set_param_fp.param_value = 0;
Srinivas Girigowda296105a2015-09-24 16:31:16 -0700830 WMI_CHAR_ARRAY_TO_MAC_ADDR(ta_dhcp_ind->peerMacAddr.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +0530831 &peer_set_param_fp.peer_macaddr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800832
Govind Singhaa64c242016-03-08 11:31:49 +0530833 status = wmi_unified_process_dhcp_ind(wma_handle->wmi_handle,
834 &peer_set_param_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800835 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530836 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800837 }
838
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530839 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800840}
841
842/**
843 * wma_chan_to_mode() - convert channel to phy mode
844 * @chan: channel number
845 * @chan_width: channel width
846 * @vht_capable: vht capable
847 * @dot11_mode: 802.11 mode
848 *
849 * Return: return phy mode
850 */
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800851WLAN_PHY_MODE wma_chan_to_mode(u8 chan, enum phy_ch_width chan_width,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800852 u8 vht_capable, u8 dot11_mode)
853{
854 WLAN_PHY_MODE phymode = MODE_UNKNOWN;
855
856 /* 2.4 GHz band */
857 if ((chan >= WMA_11G_CHANNEL_BEGIN) && (chan <= WMA_11G_CHANNEL_END)) {
858 switch (chan_width) {
859 case CH_WIDTH_20MHZ:
860 /* In case of no channel bonding, use dot11_mode
861 * to set phy mode
862 */
863 switch (dot11_mode) {
864 case WNI_CFG_DOT11_MODE_11A:
865 phymode = MODE_11A;
866 break;
867 case WNI_CFG_DOT11_MODE_11B:
868 phymode = MODE_11B;
869 break;
870 case WNI_CFG_DOT11_MODE_11G:
871 phymode = MODE_11G;
872 break;
873 case WNI_CFG_DOT11_MODE_11G_ONLY:
874 phymode = MODE_11GONLY;
875 break;
876 default:
877 /* Configure MODE_11NG_HT20 for
878 * self vdev(for vht too)
879 */
880 phymode = MODE_11NG_HT20;
881 break;
882 }
883 break;
884 case CH_WIDTH_40MHZ:
885 phymode = vht_capable ? MODE_11AC_VHT40 :
886 MODE_11NG_HT40;
887 break;
888 default:
889 break;
890 }
891 }
892
893 /* 5 GHz band */
894 if ((chan >= WMA_11A_CHANNEL_BEGIN) && (chan <= WMA_11A_CHANNEL_END)) {
895 switch (chan_width) {
896 case CH_WIDTH_20MHZ:
897 phymode = vht_capable ? MODE_11AC_VHT20 :
898 MODE_11NA_HT20;
899 break;
900 case CH_WIDTH_40MHZ:
901 phymode = vht_capable ? MODE_11AC_VHT40 :
902 MODE_11NA_HT40;
903 break;
904 case CH_WIDTH_80MHZ:
905 phymode = MODE_11AC_VHT80;
906 break;
907#if CONFIG_160MHZ_SUPPORT != 0
908 case CH_WIDTH_160MHZ:
909 phymode = MODE_11AC_VHT160;
910 break;
911 case CH_WIDTH_80P80MHZ:
912 phymode = MODE_11AC_VHT80_80;
913 break;
914#endif
915
916 default:
917 break;
918 }
919 }
920
921 /* 5.9 GHz Band */
922 if ((chan >= WMA_11P_CHANNEL_BEGIN) && (chan <= WMA_11P_CHANNEL_END))
923 /* Only Legacy Modulation Schemes are supported */
924 phymode = MODE_11A;
925
926 WMA_LOGD("%s: phymode %d channel %d ch_width %d vht_capable %d "
927 "dot11_mode %d", __func__, phymode, chan,
928 chan_width, vht_capable, dot11_mode);
929
930 return phymode;
931}
932
933/**
934 * wma_get_link_speed() -send command to get linkspeed
935 * @handle: wma handle
936 * @pLinkSpeed: link speed info
937 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530938 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800939 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530940QDF_STATUS wma_get_link_speed(WMA_HANDLE handle, tSirLinkSpeedInfo *pLinkSpeed)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800941{
942 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhaa64c242016-03-08 11:31:49 +0530943 wmi_mac_addr peer_macaddr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800944
945 if (!wma_handle || !wma_handle->wmi_handle) {
946 WMA_LOGE("%s: WMA is closed, can not issue get link speed cmd",
947 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530948 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800949 }
950 if (!WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap,
951 WMI_SERVICE_ESTIMATE_LINKSPEED)) {
952 WMA_LOGE("%s: Linkspeed feature bit not enabled"
953 " Sending value 0 as link speed.", __func__);
954 wma_send_link_speed(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530955 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800956 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800957
958 /* Copy the peer macaddress to the wma buffer */
Srinivas Girigowdadccab9a2015-11-19 14:31:14 -0800959 WMI_CHAR_ARRAY_TO_MAC_ADDR(pLinkSpeed->peer_macaddr.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +0530960 &peer_macaddr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800961
962 WMA_LOGD("%s: pLinkSpeed->peerMacAddr: %pM, "
963 "peer_macaddr.mac_addr31to0: 0x%x, peer_macaddr.mac_addr47to32: 0x%x",
Srinivas Girigowdadccab9a2015-11-19 14:31:14 -0800964 __func__, pLinkSpeed->peer_macaddr.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +0530965 peer_macaddr.mac_addr31to0,
966 peer_macaddr.mac_addr47to32);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800967
Govind Singhaa64c242016-03-08 11:31:49 +0530968 if (wmi_unified_get_link_speed_cmd(wma_handle->wmi_handle,
969 peer_macaddr)) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530970 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800971 }
Govind Singhaa64c242016-03-08 11:31:49 +0530972
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530973 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800974}
975
Gupta, Kapil4cb1d7d2016-04-16 18:16:25 -0700976/**
977* wma_add_beacon_filter() - Issue WMI command to set beacon filter
978* @wma: wma handler
979* @filter_params: beacon_filter_param to set
980*
981* Return: Return QDF_STATUS
982*/
983QDF_STATUS wma_add_beacon_filter(WMA_HANDLE handle,
984 struct beacon_filter_param *filter_params)
985{
986 int i;
987 wmi_buf_t wmi_buf;
988 u_int8_t *buf;
989 A_UINT32 *ie_map;
990 int ret;
991 tp_wma_handle wma = (tp_wma_handle) handle;
992 wmi_add_bcn_filter_cmd_fixed_param *cmd;
993 int len = sizeof(wmi_add_bcn_filter_cmd_fixed_param);
994
995 len += WMI_TLV_HDR_SIZE;
996 len += BCN_FLT_MAX_ELEMS_IE_LIST*sizeof(A_UINT32);
997
998 if (!wma || !wma->wmi_handle) {
999 WMA_LOGE("%s: WMA is closed, can not issue set beacon filter",
1000 __func__);
1001 return QDF_STATUS_E_INVAL;
1002 }
1003
1004 wmi_buf = wmi_buf_alloc(wma->wmi_handle, len);
1005 if (!wmi_buf) {
1006 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
1007 return QDF_STATUS_E_NOMEM;
1008 }
1009
1010 buf = (u_int8_t *) wmi_buf_data(wmi_buf);
1011
1012 cmd = (wmi_add_bcn_filter_cmd_fixed_param *)wmi_buf_data(wmi_buf);
1013 cmd->vdev_id = filter_params->vdev_id;
1014
1015 WMITLV_SET_HDR(&cmd->tlv_header,
1016 WMITLV_TAG_STRUC_wmi_add_bcn_filter_cmd_fixed_param,
1017 WMITLV_GET_STRUCT_TLVLEN(
1018 wmi_add_bcn_filter_cmd_fixed_param));
1019
1020 buf += sizeof(wmi_add_bcn_filter_cmd_fixed_param);
1021
1022 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_UINT32,
1023 (BCN_FLT_MAX_ELEMS_IE_LIST * sizeof(u_int32_t)));
1024
1025 ie_map = (A_UINT32 *)(buf + WMI_TLV_HDR_SIZE);
1026 for (i = 0; i < BCN_FLT_MAX_ELEMS_IE_LIST; i++) {
1027 ie_map[i] = filter_params->ie_map[i];
1028 WMA_LOGD("beacon filter ie map = %u", ie_map[i]);
1029 }
1030
1031 ret = wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len,
1032 WMI_ADD_BCN_FILTER_CMDID);
1033 if (ret) {
1034 WMA_LOGE("Failed to send wmi add beacon filter = %d",
1035 ret);
1036 wmi_buf_free(wmi_buf);
1037 return QDF_STATUS_E_FAILURE;
1038 }
1039 WMA_LOGD("added beacon filter = %d", ret);
1040
1041 return QDF_STATUS_SUCCESS;
1042}
1043
1044/**
1045* wma_remove_beacon_filter() - Issue WMI command to remove beacon filter
1046* @wma: wma handler
1047* @filter_params: beacon_filter_params
1048*
1049* Return: Return QDF_STATUS
1050*/
1051QDF_STATUS wma_remove_beacon_filter(WMA_HANDLE handle,
1052 struct beacon_filter_param *filter_params)
1053{
1054 wmi_buf_t buf;
1055 tp_wma_handle wma = (tp_wma_handle) handle;
1056 wmi_rmv_bcn_filter_cmd_fixed_param *cmd;
1057 int len = sizeof(wmi_rmv_bcn_filter_cmd_fixed_param);
1058 int ret;
1059
1060 if (!wma || !wma->wmi_handle) {
1061 WMA_LOGE("%s: WMA is closed, cannot issue remove beacon filter",
1062 __func__);
1063 return QDF_STATUS_E_INVAL;
1064 }
1065
1066 buf = wmi_buf_alloc(wma->wmi_handle, len);
1067 if (!buf) {
1068 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
1069 return QDF_STATUS_E_NOMEM;
1070 }
1071 cmd = (wmi_rmv_bcn_filter_cmd_fixed_param *)wmi_buf_data(buf);
1072 cmd->vdev_id = filter_params->vdev_id;
1073
1074 WMITLV_SET_HDR(&cmd->tlv_header,
1075 WMITLV_TAG_STRUC_wmi_rmv_bcn_filter_cmd_fixed_param,
1076 WMITLV_GET_STRUCT_TLVLEN(
1077 wmi_rmv_bcn_filter_cmd_fixed_param));
1078
1079 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
1080 WMI_RMV_BCN_FILTER_CMDID);
1081 if (ret) {
1082 WMA_LOGE("Failed to send wmi remove beacon filter = %d",
1083 ret);
1084 wmi_buf_free(buf);
1085 return QDF_STATUS_E_FAILURE;
1086 }
1087 WMA_LOGD("removed beacon filter = %d", ret);
1088
1089 return QDF_STATUS_SUCCESS;
1090}
1091
1092
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001093#ifdef FEATURE_GREEN_AP
1094
1095/**
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001096 * wma_egap_info_status_event() - egap info status event
1097 * @handle: pointer to wma handler
1098 * @event: pointer to event
1099 * @len: len of the event
1100 *
1101 * Return: 0 for success, otherwise appropriate error code
1102 */
1103static int wma_egap_info_status_event(void *handle, u_int8_t *event,
1104 uint32_t len)
1105{
1106 WMI_TX_PAUSE_EVENTID_param_tlvs *param_buf;
1107 wmi_ap_ps_egap_info_event_fixed_param *egap_info_event;
1108 wmi_ap_ps_egap_info_chainmask_list *chainmask_event;
1109 u_int8_t *buf_ptr;
1110
1111 param_buf = (WMI_TX_PAUSE_EVENTID_param_tlvs *)event;
1112 if (!param_buf) {
1113 WMA_LOGE("Invalid EGAP Info status event buffer");
1114 return -EINVAL;
1115 }
1116
1117 egap_info_event = (wmi_ap_ps_egap_info_event_fixed_param *)
1118 param_buf->fixed_param;
1119 buf_ptr = (uint8_t *)egap_info_event;
1120 buf_ptr += sizeof(wmi_ap_ps_egap_info_event_fixed_param);
1121 chainmask_event = (wmi_ap_ps_egap_info_chainmask_list *)buf_ptr;
1122
1123 WMA_LOGI("mac_id: %d, status: %d, tx_mask: %x, rx_mask: %d",
1124 chainmask_event->mac_id,
1125 egap_info_event->status,
1126 chainmask_event->tx_chainmask,
1127 chainmask_event->rx_chainmask);
1128 return 0;
1129}
1130
1131/**
1132 * wma_send_egap_conf_params() - send wmi cmd of egap configuration params
1133 * @wma_handle: wma handler
1134 * @egap_params: pointer to egap_params
1135 *
1136 * Return: 0 for success, otherwise appropriate error code
1137 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301138QDF_STATUS wma_send_egap_conf_params(WMA_HANDLE handle,
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001139 struct egap_conf_params *egap_params)
1140{
1141 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhaa64c242016-03-08 11:31:49 +05301142 wmi_ap_ps_egap_param_cmd_fixed_param cmd = {0};
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001143 int32_t err;
1144
Govind Singhaa64c242016-03-08 11:31:49 +05301145 cmd.enable = egap_params->enable;
1146 cmd.inactivity_time = egap_params->inactivity_time;
1147 cmd.wait_time = egap_params->wait_time;
1148 cmd.flags = egap_params->flags;
1149 err = wmi_unified_egap_conf_params_cmd(wma_handle->wmi_handle, &cmd);
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001150 if (err) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301151 return QDF_STATUS_E_FAILURE;
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001152 }
Govind Singhaa64c242016-03-08 11:31:49 +05301153
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301154 return QDF_STATUS_SUCCESS;
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001155}
1156
1157/**
1158 * wma_setup_egap_support() - setup the EGAP support flag
1159 * @tgt_cfg: pointer to hdd target configuration
1160 * @egap_support: EGAP support flag
1161 *
1162 * Return: None
1163 */
1164void wma_setup_egap_support(struct wma_tgt_cfg *tgt_cfg, WMA_HANDLE handle)
1165{
1166 tp_wma_handle wma_handle = (tp_wma_handle) handle;
1167
1168 if (tgt_cfg && wma_handle)
1169 tgt_cfg->egap_support = wma_handle->egap_support;
1170}
1171
1172/**
1173 * wma_register_egap_event_handle() - register the EGAP event handle
1174 * @wma_handle: wma handler
1175 *
1176 * Return: None
1177 */
1178void wma_register_egap_event_handle(WMA_HANDLE handle)
1179{
1180 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhd76a5b02016-03-08 15:12:14 +05301181 QDF_STATUS status;
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001182
1183 if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap,
1184 WMI_SERVICE_EGAP)) {
1185 status = wmi_unified_register_event_handler(
1186 wma_handle->wmi_handle,
1187 WMI_AP_PS_EGAP_INFO_EVENTID,
Govind Singhd76a5b02016-03-08 15:12:14 +05301188 wma_egap_info_status_event,
1189 WMA_RX_SERIALIZER_CTX);
1190 if (QDF_IS_STATUS_ERROR(status)) {
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001191 WMA_LOGE("Failed to register Enhance Green AP event");
1192 wma_handle->egap_support = false;
1193 } else {
1194 WMA_LOGI("Set the Enhance Green AP event handler");
1195 wma_handle->egap_support = true;
1196 }
1197 } else
1198 wma_handle->egap_support = false;
1199}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001200#endif /* FEATURE_GREEN_AP */
1201
Govind Singha471e5e2015-10-12 17:11:14 +05301202/**
Govind Singhaa64c242016-03-08 11:31:49 +05301203 * wma_unified_fw_profiling_cmd() - send FW profiling cmd to WLAN FW
Govind Singha471e5e2015-10-12 17:11:14 +05301204 * @wma: wma handle
1205 * @cmd: Profiling command index
1206 * @value1: parameter1 value
1207 * @value2: parameter2 value
1208 *
1209 * Return: 0 for success else error code
1210 */
Govind Singhaa64c242016-03-08 11:31:49 +05301211QDF_STATUS wma_unified_fw_profiling_cmd(wmi_unified_t wmi_handle,
Govind Singha471e5e2015-10-12 17:11:14 +05301212 uint32_t cmd, uint32_t value1, uint32_t value2)
1213{
Govind Singha471e5e2015-10-12 17:11:14 +05301214 int ret;
Govind Singha471e5e2015-10-12 17:11:14 +05301215
Govind Singhaa64c242016-03-08 11:31:49 +05301216 ret = wmi_unified_fw_profiling_data_cmd(wmi_handle, cmd,
1217 value1, value2);
1218 if (ret) {
1219 WMA_LOGE("enable cmd Failed for id %d value %d",
1220 value1, value2);
1221 return ret;
Govind Singha471e5e2015-10-12 17:11:14 +05301222 }
1223
Govind Singhaa64c242016-03-08 11:31:49 +05301224 return QDF_STATUS_SUCCESS;
Govind Singha471e5e2015-10-12 17:11:14 +05301225}
1226
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001227#ifdef FEATURE_WLAN_LPHB
1228/**
1229 * wma_lphb_handler() - send LPHB indication to SME
1230 * @wma: wma handle
1231 * @event: event handler
1232 *
1233 * Return: 0 for success or error code
1234 */
1235static int wma_lphb_handler(tp_wma_handle wma, uint8_t *event)
1236{
1237 wmi_hb_ind_event_fixed_param *hb_fp;
1238 tSirLPHBInd *slphb_indication;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301239 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001240 cds_msg_t sme_msg = { 0 };
1241
1242 hb_fp = (wmi_hb_ind_event_fixed_param *) event;
1243 if (!hb_fp) {
1244 WMA_LOGE("Invalid wmi_hb_ind_event_fixed_param buffer");
1245 return -EINVAL;
1246 }
1247
1248 WMA_LOGD("lphb indication received with vdev_id=%d, session=%d, reason=%d",
1249 hb_fp->vdev_id, hb_fp->session, hb_fp->reason);
1250
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301251 slphb_indication = (tSirLPHBInd *) qdf_mem_malloc(sizeof(tSirLPHBInd));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001252
1253 if (!slphb_indication) {
1254 WMA_LOGE("Invalid LPHB indication buffer");
1255 return -ENOMEM;
1256 }
1257
1258 slphb_indication->sessionIdx = hb_fp->session;
1259 slphb_indication->protocolType = hb_fp->reason;
1260 slphb_indication->eventReason = hb_fp->reason;
1261
1262 sme_msg.type = eWNI_SME_LPHB_IND;
1263 sme_msg.bodyptr = slphb_indication;
1264 sme_msg.bodyval = 0;
1265
Anurag Chouhan6d760662016-02-20 16:05:43 +05301266 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301267 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001268 WMA_LOGE("Fail to post eWNI_SME_LPHB_IND msg to SME");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301269 qdf_mem_free(slphb_indication);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001270 return -EINVAL;
1271 }
1272
1273 return 0;
1274}
1275#endif /* FEATURE_WLAN_LPHB */
1276
1277#ifdef FEATURE_WLAN_RA_FILTERING
1278/**
1279 * wma_wow_sta_ra_filter() - set RA filter pattern in fw
1280 * @wma: wma handle
1281 * @vdev_id: vdev id
1282 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05301283 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001284 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301285static QDF_STATUS wma_wow_sta_ra_filter(tp_wma_handle wma, uint8_t vdev_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001286{
1287
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001288 struct wma_txrx_node *iface;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001289 int ret;
Govind Singhaa64c242016-03-08 11:31:49 +05301290 uint8_t default_pattern;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001291
1292 iface = &wma->interfaces[vdev_id];
1293
Govind Singhaa64c242016-03-08 11:31:49 +05301294 default_pattern = iface->num_wow_default_patterns++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001295
1296 WMA_LOGD("%s: send RA rate limit [%d] to fw vdev = %d", __func__,
1297 wma->RArateLimitInterval, vdev_id);
1298
Govind Singhaa64c242016-03-08 11:31:49 +05301299 ret = wmi_unified_wow_sta_ra_filter_cmd(wma->wmi_handle, vdev_id,
1300 default_pattern, wma->RArateLimitInterval);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001301 if (ret) {
1302 WMA_LOGE("%s: Failed to send RA rate limit to fw", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001303 iface->num_wow_default_patterns--;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301304 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001305 }
1306
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301307 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001308
1309}
1310#endif /* FEATURE_WLAN_RA_FILTERING */
1311
1312/**
1313 * wmi_unified_nat_keepalive_enable() - enable NAT keepalive filter
1314 * @wma: wma handle
1315 * @vdev_id: vdev id
1316 *
1317 * Return: 0 for success or error code
1318 */
1319int wmi_unified_nat_keepalive_enable(tp_wma_handle wma, uint8_t vdev_id)
1320{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001321
Govind Singhaa64c242016-03-08 11:31:49 +05301322 if (wmi_unified_nat_keepalive_en_cmd(wma->wmi_handle, vdev_id))
1323 return QDF_STATUS_E_FAILURE;
1324
1325 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001326}
1327
1328/**
Govind Singhd76a5b02016-03-08 15:12:14 +05301329 * wma_unified_csa_offload_enable() - sen CSA offload enable command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001330 * @wma: wma handle
1331 * @vdev_id: vdev id
1332 *
1333 * Return: 0 for success or error code
1334 */
Govind Singhd76a5b02016-03-08 15:12:14 +05301335int wma_unified_csa_offload_enable(tp_wma_handle wma, uint8_t vdev_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001336{
Govind Singhaa64c242016-03-08 11:31:49 +05301337 if (wmi_unified_csa_offload_enable(wma->wmi_handle,
1338 vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001339 WMA_LOGP("%s: Failed to send CSA offload enable command",
1340 __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001341 return -EIO;
1342 }
Govind Singhaa64c242016-03-08 11:31:49 +05301343
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001344 return 0;
1345}
1346
1347#ifdef WLAN_FEATURE_NAN
1348/**
1349 * wma_nan_rsp_event_handler() - Function is used to handle nan response
1350 * @handle: wma handle
1351 * @event_buf: event buffer
1352 * @len: length of buffer
1353 *
1354 * Return: 0 for success or error code
1355 */
1356int wma_nan_rsp_event_handler(void *handle, uint8_t *event_buf,
1357 uint32_t len)
1358{
1359 WMI_NAN_EVENTID_param_tlvs *param_buf;
1360 tSirNanEvent *nan_rsp_event;
1361 wmi_nan_event_hdr *nan_rsp_event_hdr;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301362 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001363 cds_msg_t cds_msg;
1364 uint8_t *buf_ptr;
1365 uint32_t alloc_len;
1366
1367 /*
1368 * This is how received event_buf looks like
1369 *
1370 * <-------------------- event_buf ----------------------------------->
1371 *
1372 * <--wmi_nan_event_hdr--><---WMI_TLV_HDR_SIZE---><----- data -------->
1373 *
1374 * +-----------+---------+-----------------------+--------------------+
1375 * | tlv_header| data_len| WMITLV_TAG_ARRAY_BYTE | nan_rsp_event_data |
1376 * +-----------+---------+-----------------------+--------------------+
1377 */
1378
1379 WMA_LOGD("%s: Posting NaN response event to SME", __func__);
1380 param_buf = (WMI_NAN_EVENTID_param_tlvs *) event_buf;
1381 if (!param_buf) {
1382 WMA_LOGE("%s: Invalid nan response event buf", __func__);
1383 return -EINVAL;
1384 }
1385 nan_rsp_event_hdr = param_buf->fixed_param;
1386 buf_ptr = (uint8_t *) nan_rsp_event_hdr;
1387 alloc_len = sizeof(tSirNanEvent);
1388 alloc_len += nan_rsp_event_hdr->data_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301389 nan_rsp_event = (tSirNanEvent *) qdf_mem_malloc(alloc_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001390 if (NULL == nan_rsp_event) {
1391 WMA_LOGE("%s: Memory allocation failure", __func__);
1392 return -ENOMEM;
1393 }
1394
1395 nan_rsp_event->event_data_len = nan_rsp_event_hdr->data_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301396 qdf_mem_copy(nan_rsp_event->event_data, buf_ptr +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001397 sizeof(wmi_nan_event_hdr) + WMI_TLV_HDR_SIZE,
1398 nan_rsp_event->event_data_len);
1399 cds_msg.type = eWNI_SME_NAN_EVENT;
1400 cds_msg.bodyptr = (void *)nan_rsp_event;
1401 cds_msg.bodyval = 0;
1402
1403 status = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301404 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001405 WMA_LOGE("%s: Failed to post NaN response event to SME",
1406 __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301407 qdf_mem_free(nan_rsp_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001408 return -EFAULT;
1409 }
1410 WMA_LOGD("%s: NaN response event Posted to SME", __func__);
1411 return 0;
1412}
1413#endif /* WLAN_FEATURE_NAN */
1414
1415/**
1416 * wma_csa_offload_handler() - CSA event handler
1417 * @handle: wma handle
1418 * @event: event buffer
1419 * @len: buffer length
1420 *
1421 * This event is sent by firmware when it receives CSA IE.
1422 *
1423 * Return: 0 for success or error code
1424 */
1425int wma_csa_offload_handler(void *handle, uint8_t *event, uint32_t len)
1426{
1427 tp_wma_handle wma = (tp_wma_handle) handle;
1428 WMI_CSA_HANDLING_EVENTID_param_tlvs *param_buf;
1429 wmi_csa_event_fixed_param *csa_event;
1430 uint8_t bssid[IEEE80211_ADDR_LEN];
1431 uint8_t vdev_id = 0;
1432 uint8_t cur_chan = 0;
1433 struct ieee80211_channelswitch_ie *csa_ie;
Chandrasekaran, Manishekar5c19dc52016-02-04 14:58:26 +05301434 struct csa_offload_params *csa_offload_event;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001435 struct ieee80211_extendedchannelswitch_ie *xcsa_ie;
1436 struct ieee80211_ie_wide_bw_switch *wb_ie;
1437 struct wma_txrx_node *intr = wma->interfaces;
1438
1439 param_buf = (WMI_CSA_HANDLING_EVENTID_param_tlvs *) event;
1440
1441 WMA_LOGD("%s: Enter", __func__);
1442 if (!param_buf) {
1443 WMA_LOGE("Invalid csa event buffer");
1444 return -EINVAL;
1445 }
1446 csa_event = param_buf->fixed_param;
1447 WMI_MAC_ADDR_TO_CHAR_ARRAY(&csa_event->i_addr2, &bssid[0]);
1448
1449 if (wma_find_vdev_by_bssid(wma, bssid, &vdev_id) == NULL) {
1450 WMA_LOGE("Invalid bssid received %s:%d", __func__, __LINE__);
1451 return -EINVAL;
1452 }
1453
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301454 csa_offload_event = qdf_mem_malloc(sizeof(*csa_offload_event));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001455 if (!csa_offload_event) {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05301456 WMA_LOGE("QDF MEM Alloc Failed for csa_offload_event");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001457 return -EINVAL;
1458 }
1459
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301460 qdf_mem_zero(csa_offload_event, sizeof(*csa_offload_event));
1461 qdf_mem_copy(csa_offload_event->bssId, &bssid, IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001462
1463 if (csa_event->ies_present_flag & WMI_CSA_IE_PRESENT) {
1464 csa_ie = (struct ieee80211_channelswitch_ie *)
1465 (&csa_event->csa_ie[0]);
1466 csa_offload_event->channel = csa_ie->newchannel;
Chandrasekaran, Manishekar5c19dc52016-02-04 14:58:26 +05301467 csa_offload_event->switch_mode = csa_ie->switchmode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001468 } else if (csa_event->ies_present_flag & WMI_XCSA_IE_PRESENT) {
1469 xcsa_ie = (struct ieee80211_extendedchannelswitch_ie *)
1470 (&csa_event->xcsa_ie[0]);
1471 csa_offload_event->channel = xcsa_ie->newchannel;
Chandrasekaran, Manishekar5c19dc52016-02-04 14:58:26 +05301472 csa_offload_event->switch_mode = xcsa_ie->switchmode;
Gupta, Kapil121bf212015-11-25 19:21:29 +05301473 csa_offload_event->new_op_class = xcsa_ie->newClass;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001474 } else {
1475 WMA_LOGE("CSA Event error: No CSA IE present");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301476 qdf_mem_free(csa_offload_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001477 return -EINVAL;
1478 }
1479
1480 if (csa_event->ies_present_flag & WMI_WBW_IE_PRESENT) {
1481 wb_ie = (struct ieee80211_ie_wide_bw_switch *)
1482 (&csa_event->wb_ie[0]);
1483 csa_offload_event->new_ch_width = wb_ie->new_ch_width;
1484 csa_offload_event->new_ch_freq_seg1 = wb_ie->new_ch_freq_seg1;
1485 csa_offload_event->new_ch_freq_seg2 = wb_ie->new_ch_freq_seg2;
1486 }
1487
1488 csa_offload_event->ies_present_flag = csa_event->ies_present_flag;
1489
1490 WMA_LOGD("CSA: New Channel = %d BSSID:%pM",
1491 csa_offload_event->channel, csa_offload_event->bssId);
1492
1493 cur_chan = cds_freq_to_chan(intr[vdev_id].mhz);
1494 /*
1495 * basic sanity check: requested channel should not be 0
1496 * and equal to home channel
1497 */
1498 if ((0 == csa_offload_event->channel) ||
1499 (cur_chan == csa_offload_event->channel)) {
1500 WMA_LOGE("CSA Event with channel %d. Ignore !!",
1501 csa_offload_event->channel);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301502 qdf_mem_free(csa_offload_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001503 return -EINVAL;
1504 }
1505 wma->interfaces[vdev_id].is_channel_switch = true;
1506 wma_send_msg(wma, WMA_CSA_OFFLOAD_EVENT, (void *)csa_offload_event, 0);
1507 return 0;
1508}
1509
1510#ifdef FEATURE_OEM_DATA_SUPPORT
1511
1512/**
1513 * wma_oem_capability_event_callback() - OEM capability event handler
1514 * @handle: wma handle
1515 * @datap: data ptr
1516 * @len: data length
1517 *
1518 * Return: 0 for success or error code
1519 */
1520int wma_oem_capability_event_callback(void *handle,
1521 uint8_t *datap, uint32_t len)
1522{
1523 tp_wma_handle wma = (tp_wma_handle) handle;
1524 WMI_OEM_CAPABILITY_EVENTID_param_tlvs *param_buf;
1525 uint8_t *data;
1526 uint32_t datalen;
1527 uint32_t *msg_subtype;
1528 tStartOemDataRsp *pStartOemDataRsp;
1529
1530 param_buf = (WMI_OEM_CAPABILITY_EVENTID_param_tlvs *) datap;
1531 if (!param_buf) {
1532 WMA_LOGE("%s: Received NULL buf ptr from FW", __func__);
1533 return -ENOMEM;
1534 }
1535
1536 data = param_buf->data;
1537 datalen = param_buf->num_data;
1538
1539 if (!data) {
1540 WMA_LOGE("%s: Received NULL data from FW", __func__);
1541 return -EINVAL;
1542 }
1543
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001544 /*
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001545 * wma puts 4 bytes prefix for msg subtype, so length
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001546 * of data received from target should be 4 bytes less
1547 * then max allowed
1548 */
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001549 if (datalen > (OEM_DATA_RSP_SIZE - OEM_MESSAGE_SUBTYPE_LEN)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001550 WMA_LOGE("%s: Received data len (%d) exceeds max value (%d)",
1551 __func__, datalen, (OEM_DATA_RSP_SIZE - 4));
1552 return -EINVAL;
1553 }
1554
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301555 pStartOemDataRsp = qdf_mem_malloc(sizeof(*pStartOemDataRsp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001556 if (!pStartOemDataRsp) {
1557 WMA_LOGE("%s: Failed to alloc pStartOemDataRsp", __func__);
1558 return -ENOMEM;
1559 }
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001560
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001561 pStartOemDataRsp->rsp_len = datalen + OEM_MESSAGE_SUBTYPE_LEN;
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001562 if (pStartOemDataRsp->rsp_len) {
1563 pStartOemDataRsp->oem_data_rsp =
1564 qdf_mem_malloc(pStartOemDataRsp->rsp_len);
1565 if (!pStartOemDataRsp->oem_data_rsp) {
1566 WMA_LOGE(FL("malloc failed for oem_data_rsp"));
1567 qdf_mem_free(pStartOemDataRsp);
1568 return -ENOMEM;
1569 }
1570 } else {
1571 WMA_LOGE(FL("Invalid rsp length: %d"),
1572 pStartOemDataRsp->rsp_len);
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001573 qdf_mem_free(pStartOemDataRsp);
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001574 return -EINVAL;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001575 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001576
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001577 pStartOemDataRsp->target_rsp = true;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001578 msg_subtype = (uint32_t *) pStartOemDataRsp->oem_data_rsp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001579 *msg_subtype = WMI_OEM_CAPABILITY_RSP;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001580 /* copy data after msg sub type */
1581 qdf_mem_copy(pStartOemDataRsp->oem_data_rsp + OEM_MESSAGE_SUBTYPE_LEN,
1582 data, datalen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001583
1584 WMA_LOGI("%s: Sending WMA_START_OEM_DATA_RSP, data len (%d)",
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001585 __func__, pStartOemDataRsp->rsp_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001586
1587 wma_send_msg(wma, WMA_START_OEM_DATA_RSP, (void *)pStartOemDataRsp, 0);
1588 return 0;
1589}
1590
1591/**
1592 * wma_oem_measurement_report_event_callback() - OEM measurement report handler
1593 * @handle: wma handle
1594 * @datap: data ptr
1595 * @len: data length
1596 *
1597 * Return: 0 for success or error code
1598 */
1599int wma_oem_measurement_report_event_callback(void *handle,
1600 uint8_t *datap,
1601 uint32_t len)
1602{
1603 tp_wma_handle wma = (tp_wma_handle) handle;
1604 WMI_OEM_MEASUREMENT_REPORT_EVENTID_param_tlvs *param_buf;
1605 uint8_t *data;
1606 uint32_t datalen;
1607 uint32_t *msg_subtype;
1608 tStartOemDataRsp *pStartOemDataRsp;
1609
1610 param_buf = (WMI_OEM_MEASUREMENT_REPORT_EVENTID_param_tlvs *) datap;
1611 if (!param_buf) {
1612 WMA_LOGE("%s: Received NULL buf ptr from FW", __func__);
1613 return -ENOMEM;
1614 }
1615
1616 data = param_buf->data;
1617 datalen = param_buf->num_data;
1618
1619 if (!data) {
1620 WMA_LOGE("%s: Received NULL data from FW", __func__);
1621 return -EINVAL;
1622 }
1623
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001624 /*
1625 * wma puts 4 bytes prefix for msg subtype, so length
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001626 * of data received from target should be 4 bytes less
1627 * then max allowed
1628 */
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001629 if (datalen > (OEM_DATA_RSP_SIZE - OEM_MESSAGE_SUBTYPE_LEN)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001630 WMA_LOGE("%s: Received data len (%d) exceeds max value (%d)",
1631 __func__, datalen, (OEM_DATA_RSP_SIZE - 4));
1632 return -EINVAL;
1633 }
1634
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301635 pStartOemDataRsp = qdf_mem_malloc(sizeof(*pStartOemDataRsp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001636 if (!pStartOemDataRsp) {
1637 WMA_LOGE("%s: Failed to alloc pStartOemDataRsp", __func__);
1638 return -ENOMEM;
1639 }
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001640
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001641 pStartOemDataRsp->rsp_len = datalen + OEM_MESSAGE_SUBTYPE_LEN;
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001642 if (pStartOemDataRsp->rsp_len) {
1643 pStartOemDataRsp->oem_data_rsp =
1644 qdf_mem_malloc(pStartOemDataRsp->rsp_len);
1645 if (!pStartOemDataRsp->oem_data_rsp) {
1646 WMA_LOGE(FL("malloc failed for oem_data_rsp"));
1647 qdf_mem_free(pStartOemDataRsp);
1648 return -ENOMEM;
1649 }
1650 } else {
1651 WMA_LOGE(FL("Invalid rsp length: %d"),
1652 pStartOemDataRsp->rsp_len);
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001653 qdf_mem_free(pStartOemDataRsp);
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001654 return -EINVAL;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001655 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001656
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001657 pStartOemDataRsp->target_rsp = true;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001658 msg_subtype = (uint32_t *) pStartOemDataRsp->oem_data_rsp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001659 *msg_subtype = WMI_OEM_MEASUREMENT_RSP;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001660 /* copy data after msg sub type */
1661 qdf_mem_copy(pStartOemDataRsp->oem_data_rsp + OEM_MESSAGE_SUBTYPE_LEN,
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001662 data, datalen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001663
1664 WMA_LOGI("%s: Sending WMA_START_OEM_DATA_RSP, data len (%d)",
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001665 __func__, pStartOemDataRsp->rsp_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001666
1667 wma_send_msg(wma, WMA_START_OEM_DATA_RSP, (void *)pStartOemDataRsp, 0);
1668 return 0;
1669}
1670
1671/**
1672 * wma_oem_error_report_event_callback() - OEM error report handler
1673 * @handle: wma handle
1674 * @datap: data ptr
1675 * @len: data length
1676 *
1677 * Return: 0 for success or error code
1678 */
1679int wma_oem_error_report_event_callback(void *handle,
1680 uint8_t *datap, uint32_t len)
1681{
1682 tp_wma_handle wma = (tp_wma_handle) handle;
1683 WMI_OEM_ERROR_REPORT_EVENTID_param_tlvs *param_buf;
1684 uint8_t *data;
1685 uint32_t datalen;
1686 uint32_t *msg_subtype;
1687 tStartOemDataRsp *pStartOemDataRsp;
1688
1689 param_buf = (WMI_OEM_ERROR_REPORT_EVENTID_param_tlvs *) datap;
1690 if (!param_buf) {
1691 WMA_LOGE("%s: Received NULL buf ptr from FW", __func__);
1692 return -ENOMEM;
1693 }
1694
1695 data = param_buf->data;
1696 datalen = param_buf->num_data;
1697
1698 if (!data) {
1699 WMA_LOGE("%s: Received NULL data from FW", __func__);
1700 return -EINVAL;
1701 }
1702
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001703 /*
1704 * wma puts 4 bytes prefix for msg subtype, so length
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001705 * of data received from target should be 4 bytes less
1706 * then max allowed
1707 */
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001708 if (datalen > (OEM_DATA_RSP_SIZE - OEM_MESSAGE_SUBTYPE_LEN)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001709 WMA_LOGE("%s: Received data len (%d) exceeds max value (%d)",
1710 __func__, datalen, (OEM_DATA_RSP_SIZE - 4));
1711 return -EINVAL;
1712 }
1713
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301714 pStartOemDataRsp = qdf_mem_malloc(sizeof(*pStartOemDataRsp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001715 if (!pStartOemDataRsp) {
1716 WMA_LOGE("%s: Failed to alloc pStartOemDataRsp", __func__);
1717 return -ENOMEM;
1718 }
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001719
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001720 pStartOemDataRsp->rsp_len = datalen + OEM_MESSAGE_SUBTYPE_LEN;
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001721 if (pStartOemDataRsp->rsp_len) {
1722 pStartOemDataRsp->oem_data_rsp =
1723 qdf_mem_malloc(pStartOemDataRsp->rsp_len);
1724 if (!pStartOemDataRsp->oem_data_rsp) {
1725 WMA_LOGE(FL("malloc failed for oem_data_rsp"));
1726 qdf_mem_free(pStartOemDataRsp);
1727 return -ENOMEM;
1728 }
1729 } else {
1730 WMA_LOGE(FL("Invalid rsp length: %d"),
1731 pStartOemDataRsp->rsp_len);
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001732 qdf_mem_free(pStartOemDataRsp);
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001733 return -EINVAL;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001734 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001735
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001736 pStartOemDataRsp->target_rsp = true;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001737 msg_subtype = (uint32_t *) pStartOemDataRsp->oem_data_rsp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001738 *msg_subtype = WMI_OEM_ERROR_REPORT_RSP;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001739 /* copy data after msg sub type */
1740 qdf_mem_copy(pStartOemDataRsp->oem_data_rsp + OEM_MESSAGE_SUBTYPE_LEN,
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001741 data, datalen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001742
1743 WMA_LOGI("%s: Sending WMA_START_OEM_DATA_RSP, data len (%d)",
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001744 __func__, pStartOemDataRsp->rsp_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001745
1746 wma_send_msg(wma, WMA_START_OEM_DATA_RSP, (void *)pStartOemDataRsp, 0);
1747 return 0;
1748}
1749
1750/**
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001751 * wma_oem_data_response_handler() - OEM data response event handler
1752 * @handle: wma handle
1753 * @datap: data ptr
1754 * @len: data length
1755 *
1756 * Return: 0 for success or error code
1757 */
1758int wma_oem_data_response_handler(void *handle,
1759 uint8_t *datap, uint32_t len)
1760{
1761 tp_wma_handle wma = (tp_wma_handle) handle;
1762 WMI_OEM_RESPONSE_EVENTID_param_tlvs *param_buf;
1763 uint8_t *data;
1764 uint32_t datalen;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001765 tStartOemDataRsp *oem_rsp;
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001766
1767 param_buf = (WMI_OEM_RESPONSE_EVENTID_param_tlvs *) datap;
1768 if (!param_buf) {
1769 WMA_LOGE(FL("Received NULL buf ptr from FW"));
1770 return -ENOMEM;
1771 }
1772
1773 data = param_buf->data;
1774 datalen = param_buf->num_data;
1775
1776 if (!data) {
1777 WMA_LOGE(FL("Received NULL data from FW"));
1778 return -EINVAL;
1779 }
1780
1781 if (datalen > OEM_DATA_RSP_SIZE) {
1782 WMA_LOGE(FL("Received data len %d exceeds max value %d"),
1783 datalen, OEM_DATA_RSP_SIZE);
1784 return -EINVAL;
1785 }
1786
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001787 oem_rsp = qdf_mem_malloc(sizeof(*oem_rsp));
1788 if (!oem_rsp) {
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001789 WMA_LOGE(FL("Failed to alloc oem_data_rsp"));
1790 return -ENOMEM;
1791 }
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001792 oem_rsp->rsp_len = datalen;
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001793 if (oem_rsp->rsp_len) {
1794 oem_rsp->oem_data_rsp = qdf_mem_malloc(oem_rsp->rsp_len);
1795 if (!oem_rsp->oem_data_rsp) {
1796 WMA_LOGE(FL("malloc failed for oem_data_rsp"));
1797 qdf_mem_free(oem_rsp);
1798 return -ENOMEM;
1799 }
1800 } else {
1801 WMA_LOGE(FL("Invalid rsp length: %d"),
1802 oem_rsp->rsp_len);
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001803 qdf_mem_free(oem_rsp);
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001804 return -EINVAL;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001805 }
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001806
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001807 oem_rsp->target_rsp = true;
1808 qdf_mem_copy(oem_rsp->oem_data_rsp, data, datalen);
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001809
1810 WMA_LOGI(FL("Sending WMA_START_OEM_DATA_RSP, data len %d"), datalen);
1811
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001812 wma_send_msg(wma, WMA_START_OEM_DATA_RSP, (void *)oem_rsp, 0);
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001813 return 0;
1814}
1815
1816/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001817 * wma_start_oem_data_req() - start OEM data request to target
1818 * @wma_handle: wma handle
1819 * @startOemDataReq: start request params
1820 *
1821 * Return: none
1822 */
1823void wma_start_oem_data_req(tp_wma_handle wma_handle,
1824 tStartOemDataReq *startOemDataReq)
1825{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001826 int ret = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001827 tStartOemDataRsp *pStartOemDataRsp;
1828
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001829 WMA_LOGD(FL("Send OEM Data Request to target"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001830
Sreelakshmi Konamki86d79202016-02-10 12:33:40 +05301831 if (!startOemDataReq || !startOemDataReq->data) {
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001832 WMA_LOGE(FL("startOemDataReq is null"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001833 goto out;
1834 }
1835
1836 if (!wma_handle || !wma_handle->wmi_handle) {
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001837 WMA_LOGE(FL("WMA - closed, can not send Oem data request cmd"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001838 return;
1839 }
1840
Govind Singhaa64c242016-03-08 11:31:49 +05301841 ret = wmi_unified_start_oem_data_cmd(wma_handle->wmi_handle,
1842 startOemDataReq->data_len,
1843 startOemDataReq->data);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001844
1845 if (ret != EOK) {
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001846 WMA_LOGE(FL(":wmi cmd send failed"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001847 }
1848
1849out:
1850 /* free oem data req buffer received from UMAC */
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001851 if (startOemDataReq) {
1852 if (startOemDataReq->data)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301853 qdf_mem_free(startOemDataReq->data);
1854 qdf_mem_free(startOemDataReq);
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001855 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001856
1857 /* Now send data resp back to PE/SME with message sub-type of
1858 * WMI_OEM_INTERNAL_RSP. This is required so that PE/SME clears
1859 * up pending active command. Later when desired oem response(s)
1860 * comes as wmi event from target then those shall be passed
1861 * to oem application
1862 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301863 pStartOemDataRsp = qdf_mem_malloc(sizeof(*pStartOemDataRsp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001864 if (!pStartOemDataRsp) {
1865 WMA_LOGE("%s:failed to allocate memory for OEM Data Resp to PE",
1866 __func__);
1867 return;
1868 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301869 qdf_mem_zero(pStartOemDataRsp, sizeof(tStartOemDataRsp));
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001870 pStartOemDataRsp->target_rsp = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001871
1872 WMA_LOGI("%s: Sending WMA_START_OEM_DATA_RSP to clear up PE/SME pending cmd",
1873 __func__);
1874
1875 wma_send_msg(wma_handle, WMA_START_OEM_DATA_RSP,
1876 (void *)pStartOemDataRsp, 0);
1877
1878 return;
1879}
1880#endif /* FEATURE_OEM_DATA_SUPPORT */
1881
1882
1883/**
1884 * wma_unified_dfs_radar_rx_event_handler() - dfs radar rx event handler
1885 * @handle: wma handle
1886 * @data: data buffer
1887 * @datalen: data length
1888 *
1889 * WMI handler for WMI_DFS_RADAR_EVENTID
1890 * This handler is registered for handling
1891 * filtered DFS Phyerror. This handler is
1892 * will be invoked only when DFS Phyerr
1893 * filtering offload is enabled.
1894 *
1895 * Return: 1 for Success and 0 for error
1896 */
1897static int wma_unified_dfs_radar_rx_event_handler(void *handle,
1898 uint8_t *data,
1899 uint32_t datalen)
1900{
1901 tp_wma_handle wma = (tp_wma_handle) handle;
1902 struct ieee80211com *ic;
1903 struct ath_dfs *dfs;
1904 struct dfs_event *event;
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05301905 struct dfs_ieee80211_channel *chan;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001906 int empty;
1907 int do_check_chirp = 0;
1908 int is_hw_chirp = 0;
1909 int is_sw_chirp = 0;
1910 int is_pri = 0;
Vishwajith Upendrabf673e72016-01-19 16:05:40 -08001911 bool is_ch_dfs = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001912
1913 WMI_DFS_RADAR_EVENTID_param_tlvs *param_tlvs;
1914 wmi_dfs_radar_event_fixed_param *radar_event;
1915
1916 ic = wma->dfs_ic;
1917 if (NULL == ic) {
1918 WMA_LOGE("%s: dfs_ic is NULL ", __func__);
1919 return 0;
1920 }
1921
1922 dfs = (struct ath_dfs *)ic->ic_dfs;
1923 param_tlvs = (WMI_DFS_RADAR_EVENTID_param_tlvs *) data;
1924
1925 if (NULL == dfs) {
1926 WMA_LOGE("%s: dfs is NULL ", __func__);
1927 return 0;
1928 }
1929 /*
1930 * This parameter holds the number
1931 * of phyerror interrupts to the host
1932 * after the phyerrors have passed through
1933 * false detect filters in the firmware.
1934 */
1935 dfs->dfs_phyerr_count++;
1936
1937 if (!param_tlvs) {
1938 WMA_LOGE("%s: Received NULL data from FW", __func__);
1939 return 0;
1940 }
1941
1942 radar_event = param_tlvs->fixed_param;
1943
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301944 qdf_spin_lock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001945 chan = ic->ic_curchan;
Edhar, Mahesh Kumar35d9b2e2015-10-26 17:06:23 +05301946 if (ic->disable_phy_err_processing) {
1947 WMA_LOGD("%s: radar indication done,drop phyerror event",
1948 __func__);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301949 qdf_spin_unlock_bh(&ic->chan_lock);
Edhar, Mahesh Kumar35d9b2e2015-10-26 17:06:23 +05301950 return 0;
1951 }
1952
Vishwajith Upendrabf673e72016-01-19 16:05:40 -08001953 if (IEEE80211_IS_CHAN_11AC_VHT160(chan)) {
1954 is_ch_dfs = true;
1955 } else if (IEEE80211_IS_CHAN_11AC_VHT80P80(chan)) {
1956 if (cds_get_channel_state(chan->ic_ieee) == CHANNEL_STATE_DFS ||
1957 cds_get_channel_state(chan->ic_ieee_ext -
1958 WMA_80MHZ_START_CENTER_CH_DIFF) ==
1959 CHANNEL_STATE_DFS)
1960 is_ch_dfs = true;
1961 } else {
1962 if (cds_get_channel_state(chan->ic_ieee) == CHANNEL_STATE_DFS)
1963 is_ch_dfs = true;
1964 }
1965 if (!is_ch_dfs) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001966 WMA_LOGE
1967 ("%s: Invalid DFS Phyerror event. Channel=%d is Non-DFS",
1968 __func__, chan->ic_ieee);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301969 qdf_spin_unlock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001970 return 0;
1971 }
1972
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301973 qdf_spin_unlock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001974 dfs->ath_dfs_stats.total_phy_errors++;
1975
1976 if (dfs->dfs_caps.ath_chip_is_bb_tlv) {
1977 do_check_chirp = 1;
1978 is_pri = 1;
1979 is_hw_chirp = radar_event->pulse_is_chirp;
1980
1981 if ((uint32_t) dfs->dfs_phyerr_freq_min >
1982 radar_event->pulse_center_freq) {
1983 dfs->dfs_phyerr_freq_min =
1984 (int)radar_event->pulse_center_freq;
1985 }
1986
1987 if (dfs->dfs_phyerr_freq_max <
1988 (int)radar_event->pulse_center_freq) {
1989 dfs->dfs_phyerr_freq_max =
1990 (int)radar_event->pulse_center_freq;
1991 }
1992 }
1993
1994 /*
1995 * Now, add the parsed, checked and filtered
1996 * radar phyerror event radar pulse event list.
1997 * This event will then be processed by
1998 * dfs_radar_processevent() to see if the pattern
1999 * of pulses in radar pulse list match any radar
2000 * singnature in the current regulatory domain.
2001 */
2002
2003 ATH_DFSEVENTQ_LOCK(dfs);
2004 empty = STAILQ_EMPTY(&(dfs->dfs_eventq));
2005 ATH_DFSEVENTQ_UNLOCK(dfs);
2006 if (empty) {
2007 return 0;
2008 }
2009 /*
2010 * Add the event to the list, if there's space.
2011 */
2012 ATH_DFSEVENTQ_LOCK(dfs);
2013 event = STAILQ_FIRST(&(dfs->dfs_eventq));
2014 if (event == NULL) {
2015 ATH_DFSEVENTQ_UNLOCK(dfs);
2016 WMA_LOGE("%s: No more space left for queuing DFS Phyerror events",
2017 __func__);
2018 return 0;
2019 }
2020 STAILQ_REMOVE_HEAD(&(dfs->dfs_eventq), re_list);
2021 ATH_DFSEVENTQ_UNLOCK(dfs);
2022 dfs->dfs_phyerr_queued_count++;
2023 dfs->dfs_phyerr_w53_counter++;
2024 event->re_dur = (uint8_t) radar_event->pulse_duration;
2025 event->re_rssi = radar_event->rssi;
2026 event->re_ts = radar_event->pulse_detect_ts & DFS_TSMASK;
2027 event->re_full_ts = (((uint64_t) radar_event->upload_fullts_high) << 32)
2028 | radar_event->upload_fullts_low;
2029
2030 /*
2031 * Index of peak magnitude
2032 */
2033 event->sidx = radar_event->peak_sidx;
2034
2035 /*
2036 * Handle chirp flags.
2037 */
2038 if (do_check_chirp) {
2039 event->re_flags |= DFS_EVENT_CHECKCHIRP;
2040 if (is_hw_chirp) {
2041 event->re_flags |= DFS_EVENT_HW_CHIRP;
2042 }
2043 if (is_sw_chirp) {
2044 event->re_flags |= DFS_EVENT_SW_CHIRP;
2045 }
2046 }
2047 /*
2048 * Correctly set which channel is being reported on
2049 */
2050 if (is_pri) {
2051 event->re_chanindex = (uint8_t) dfs->dfs_curchan_radindex;
2052 } else {
2053 if (dfs->dfs_extchan_radindex == -1) {
2054 WMA_LOGI("%s phyerr on ext channel", __func__);
2055 }
2056 event->re_chanindex = (uint8_t) dfs->dfs_extchan_radindex;
2057 WMA_LOGI("%s:New extension channel event is added to queue",
2058 __func__);
2059 }
2060
2061 ATH_DFSQ_LOCK(dfs);
2062
2063 STAILQ_INSERT_TAIL(&(dfs->dfs_radarq), event, re_list);
2064
2065 empty = STAILQ_EMPTY(&dfs->dfs_radarq);
2066
2067 ATH_DFSQ_UNLOCK(dfs);
2068
2069 if (!empty && !dfs->ath_radar_tasksched) {
2070 dfs->ath_radar_tasksched = 1;
2071 OS_SET_TIMER(&dfs->ath_dfs_task_timer, 0);
2072 }
2073
2074 return 1;
2075
2076}
2077
2078/**
2079 * wma_unified_phyerr_rx_event_handler() - phyerr event handler
2080 * @handle: wma handle
2081 * @data: data buffer
2082 * @datalen: buffer length
2083 *
2084 * WMI Handler for WMI_PHYERR_EVENTID event from firmware.
2085 * This handler is currently handling only DFS phy errors.
2086 * This handler will be invoked only when the DFS phyerror
2087 * filtering offload is disabled.
2088 *
2089 * Return: 1:Success, 0:Failure
2090 */
2091static int wma_unified_phyerr_rx_event_handler(void *handle,
2092 uint8_t *data, uint32_t datalen)
2093{
2094 tp_wma_handle wma = (tp_wma_handle) handle;
2095 WMI_PHYERR_EVENTID_param_tlvs *param_tlvs;
2096 wmi_comb_phyerr_rx_hdr *pe_hdr;
2097 uint8_t *bufp;
2098 wmi_single_phyerr_rx_event *ev;
2099 struct ieee80211com *ic = wma->dfs_ic;
Anurag Chouhan6d760662016-02-20 16:05:43 +05302100 qdf_size_t n;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002101 A_UINT64 tsf64 = 0;
2102 int phy_err_code = 0;
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002103 A_UINT32 phy_err_mask = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002104 int error = 0;
2105 tpAniSirGlobal mac_ctx =
Anurag Chouhan6d760662016-02-20 16:05:43 +05302106 (tpAniSirGlobal)cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002107 bool enable_log = false;
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002108 int max_dfs_buf_length = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002109
2110 if (NULL == mac_ctx) {
2111 WMA_LOGE("%s: mac_ctx is NULL", __func__);
2112 return 0;
2113 }
2114 enable_log = mac_ctx->sap.enable_dfs_phy_error_logs;
2115
2116 param_tlvs = (WMI_PHYERR_EVENTID_param_tlvs *) data;
2117
2118 if (!param_tlvs) {
2119 WMA_LOGE("%s: Received NULL data from FW", __func__);
2120 return 0;
2121 }
2122
2123 pe_hdr = param_tlvs->hdr;
2124 if (pe_hdr == NULL) {
2125 WMA_LOGE("%s: Received Data PE Header is NULL", __func__);
2126 return 0;
2127 }
2128
2129 /* Ensure it's at least the size of the header */
2130 if (datalen < sizeof(*pe_hdr)) {
2131 WMA_LOGE("%s: Expected minimum size %zu, received %d",
2132 __func__, sizeof(*pe_hdr), datalen);
2133 return 0;
2134 }
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002135 /*
2136 * The max buffer lenght is larger for DFS-3 than DFS-2.
2137 * So, accordingly use the correct max buffer size.
2138 */
2139 if (wma->hw_bd_id != WMI_HWBD_QCA6174)
2140 max_dfs_buf_length = DFS3_MAX_BUF_LENGTH;
2141 else
2142 max_dfs_buf_length = DFS_MAX_BUF_LENGTH;
2143
2144 if (pe_hdr->buf_len > max_dfs_buf_length) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002145 WMA_LOGE("%s: Received Invalid Phyerror event buffer length = %d"
2146 "Maximum allowed buf length = %d", __func__,
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002147 pe_hdr->buf_len, max_dfs_buf_length);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002148
2149 return 0;
2150 }
2151
2152 /*
2153 * Reconstruct the 64 bit event TSF. This isn't from the MAC, it's
2154 * at the time the event was sent to us, the TSF value will be
2155 * in the future.
2156 */
2157 tsf64 = pe_hdr->tsf_l32;
2158 tsf64 |= (((uint64_t) pe_hdr->tsf_u32) << 32);
2159
2160 /*
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002161 * Check the HW board ID to figure out
2162 * if DFS-3 is supported. In DFS-3
2163 * phyerror mask indicates the type of
2164 * phyerror, whereas in DFS-2 phyerrorcode
2165 * indicates the type of phyerror. If the
2166 * board is NOT WMI_HWBD_QCA6174, for now
2167 * assume that it supports DFS-3.
2168 */
2169 if (wma->hw_bd_id != WMI_HWBD_QCA6174) {
2170 phy_err_mask = pe_hdr->rsPhyErrMask0;
2171 WMA_LOGD("%s: DFS-3 phyerror mask = 0x%x",
2172 __func__, phy_err_mask);
2173 }
2174
2175 /*
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002176 * Loop over the bufp, extracting out phyerrors
2177 * wmi_unified_comb_phyerr_rx_event.bufp is a char pointer,
2178 * which isn't correct here - what we have received here
2179 * is an array of TLV-style PHY errors.
2180 */
2181 n = 0; /* Start just after the header */
2182 bufp = param_tlvs->bufp;
2183 while (n < pe_hdr->buf_len) {
2184 /* ensure there's at least space for the header */
2185 if ((pe_hdr->buf_len - n) < sizeof(ev->hdr)) {
2186 WMA_LOGE("%s: Not enough space.(datalen=%d, n=%zu, hdr=%zu bytes",
2187 __func__, pe_hdr->buf_len, n, sizeof(ev->hdr));
2188 error = 1;
2189 break;
2190 }
2191 /*
2192 * Obtain a pointer to the beginning of the current event.
2193 * data[0] is the beginning of the WMI payload.
2194 */
2195 ev = (wmi_single_phyerr_rx_event *) &bufp[n];
2196
2197 /*
2198 * Sanity check the buffer length of the event against
2199 * what we currently have.
2200 * Since buf_len is 32 bits, we check if it overflows
2201 * a large 32 bit value. It's not 0x7fffffff because
2202 * we increase n by (buf_len + sizeof(hdr)), which would
2203 * in itself cause n to overflow.
2204 * If "int" is 64 bits then this becomes a moot point.
2205 */
2206 if (ev->hdr.buf_len > 0x7f000000) {
2207 WMA_LOGE("%s:buf_len is garbage (0x%x)", __func__,
2208 ev->hdr.buf_len);
2209 error = 1;
2210 break;
2211 }
2212 if (n + ev->hdr.buf_len > pe_hdr->buf_len) {
2213 WMA_LOGE("%s: buf_len exceeds available space n=%zu,"
2214 "buf_len=%d, datalen=%d",
2215 __func__, n, ev->hdr.buf_len, pe_hdr->buf_len);
2216 error = 1;
2217 break;
2218 }
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002219 /*
2220 * If the board id is WMI_HWBD_QCA6174
2221 * then it supports only DFS-2. So, fetch
2222 * phyerror code in order to know the type
2223 * of phyerror.
2224 */
2225 if (wma->hw_bd_id == WMI_HWBD_QCA6174) {
2226 phy_err_code = WMI_UNIFIED_PHYERRCODE_GET(&ev->hdr);
2227 WMA_LOGD("%s: DFS-2 phyerror code = 0x%x",
2228 __func__, phy_err_code);
2229 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002230
2231 /*
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002232 * phy_err_code is set for DFS-2 and phy_err_mask
2233 * is set for DFS-3. Checking both to support
2234 * compatability for older platforms.
2235 * If the phyerror or phyerrmask category matches,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002236 * pass radar events to the dfs pattern matching code.
2237 * Don't pass radar events with no buffer payload.
2238 */
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002239 if (((phy_err_mask & WMI_PHY_ERROR_MASK0_RADAR) ||
2240 (phy_err_mask & WMI_PHY_ERROR_MASK0_FALSE_RADAR_EXT)) ||
2241 (phy_err_code == WMA_DFS2_PHYERROR_CODE ||
2242 phy_err_code == WMA_DFS2_FALSE_RADAR_EXT)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002243 if (ev->hdr.buf_len > 0) {
2244 /* Calling in to the DFS module to process the phyerr */
2245 dfs_process_phyerr(ic, &ev->bufp[0],
2246 ev->hdr.buf_len,
2247 WMI_UNIFIED_RSSI_COMB_GET
2248 (&ev->hdr) & 0xff,
2249 /* Extension RSSI */
2250 WMI_UNIFIED_RSSI_COMB_GET
2251 (&ev->hdr) & 0xff,
2252 ev->hdr.tsf_timestamp,
2253 tsf64, enable_log);
2254 }
2255 }
2256
2257 /*
2258 * Advance the buffer pointer to the next PHY error.
2259 * buflen is the length of this payload, so we need to
2260 * advance past the current header _AND_ the payload.
2261 */
2262 n += sizeof(*ev) + ev->hdr.buf_len;
2263
2264 } /*end while() */
2265 if (error)
2266 return 0;
2267 else
2268 return 1;
2269}
2270
2271/**
2272 * wma_register_dfs_event_handler() - register dfs event handler
2273 * @wma_handle: wma handle
2274 *
2275 * Register appropriate dfs phyerror event handler
2276 * based on phyerror filtering offload is enabled
2277 * or disabled.
2278 *
2279 * Return: none
2280 */
2281void wma_register_dfs_event_handler(tp_wma_handle wma_handle)
2282{
2283 if (NULL == wma_handle) {
2284 WMA_LOGE("%s:wma_handle is NULL", __func__);
2285 return;
2286 }
2287
2288 if (false == wma_handle->dfs_phyerr_filter_offload) {
2289 /*
2290 * Register the wma_unified_phyerr_rx_event_handler
2291 * for filtering offload disabled case to handle
2292 * the DFS phyerrors.
2293 */
2294 WMA_LOGD("%s:Phyerror Filtering offload is Disabled in ini",
2295 __func__);
2296 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Govind Singhd76a5b02016-03-08 15:12:14 +05302297 WMI_PHYERR_EVENTID,
2298 wma_unified_phyerr_rx_event_handler,
2299 WMA_RX_WORK_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002300 WMA_LOGD("%s: WMI_PHYERR_EVENTID event handler registered",
2301 __func__);
2302 } else {
2303 WMA_LOGD("%s:Phyerror Filtering offload is Enabled in ini",
2304 __func__);
2305 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Govind Singhd76a5b02016-03-08 15:12:14 +05302306 WMI_DFS_RADAR_EVENTID,
2307 wma_unified_dfs_radar_rx_event_handler,
2308 WMA_RX_WORK_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002309 WMA_LOGD("%s:WMI_DFS_RADAR_EVENTID event handler registered",
2310 __func__);
2311 }
2312
2313 return;
2314}
2315
2316
2317/**
2318 * wma_unified_dfs_phyerr_filter_offload_enable() - enable dfs phyerr filter
2319 * @wma_handle: wma handle
2320 *
2321 * Send WMI_DFS_PHYERR_FILTER_ENA_CMDID or
2322 * WMI_DFS_PHYERR_FILTER_DIS_CMDID command
2323 * to firmware based on phyerr filtering
2324 * offload status.
2325 *
2326 * Return: 1 success, 0 failure
2327 */
2328int
2329wma_unified_dfs_phyerr_filter_offload_enable(tp_wma_handle wma_handle)
2330{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002331 int ret;
2332
2333 if (NULL == wma_handle) {
2334 WMA_LOGE("%s:wma_handle is NULL", __func__);
2335 return 0;
2336 }
2337
Govind Singhaa64c242016-03-08 11:31:49 +05302338 ret = wmi_unified_dfs_phyerr_filter_offload_en_cmd(wma_handle->wmi_handle,
2339 wma_handle->dfs_phyerr_filter_offload);
2340 if (ret)
2341 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002342
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002343
Govind Singhaa64c242016-03-08 11:31:49 +05302344 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002345}
2346
2347#if !defined(REMOVE_PKT_LOG)
2348/**
2349 * wma_pktlog_wmi_send_cmd() - send pktlog enable/disable command to target
2350 * @handle: wma handle
2351 * @params: pktlog params
2352 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302353 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002354 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302355QDF_STATUS wma_pktlog_wmi_send_cmd(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002356 struct ath_pktlog_wmi_params *params)
2357{
2358 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhaa64c242016-03-08 11:31:49 +05302359 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002360
2361 /*Check if packet log is enabled in cfg.ini */
2362 if (!cds_is_packet_log_enabled()) {
2363 WMA_LOGE("%s:pkt log is not enabled in cfg.ini", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302364 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002365 }
2366
Govind Singhaa64c242016-03-08 11:31:49 +05302367 ret = wmi_unified_pktlog_wmi_send_cmd(wma_handle->wmi_handle,
2368 params->pktlog_event,
2369 params->cmd_id);
2370 if (ret)
2371 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002372
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002373
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302374 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002375}
2376#endif /* REMOVE_PKT_LOG */
2377
2378static void wma_send_status_to_suspend_ind(tp_wma_handle wma, bool suspended)
2379{
2380 tSirReadyToSuspendInd *ready_to_suspend;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302381 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002382 cds_msg_t cds_msg;
2383 uint8_t len;
2384
2385 WMA_LOGD("Posting ready to suspend indication to umac");
2386
2387 len = sizeof(tSirReadyToSuspendInd);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302388 ready_to_suspend = (tSirReadyToSuspendInd *) qdf_mem_malloc(len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002389
2390 if (NULL == ready_to_suspend) {
2391 WMA_LOGE("%s: Memory allocation failure", __func__);
2392 return;
2393 }
2394
2395 ready_to_suspend->mesgType = eWNI_SME_READY_TO_SUSPEND_IND;
2396 ready_to_suspend->mesgLen = len;
2397 ready_to_suspend->suspended = suspended;
2398
2399 cds_msg.type = eWNI_SME_READY_TO_SUSPEND_IND;
2400 cds_msg.bodyptr = (void *)ready_to_suspend;
2401 cds_msg.bodyval = 0;
2402
2403 status = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302404 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002405 WMA_LOGE("Failed to post ready to suspend");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302406 qdf_mem_free(ready_to_suspend);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002407 }
2408}
2409
2410/**
2411 * wma_wow_wake_reason_str() - Converts wow wakeup reason code to text format
2412 * @wake_reason - WOW wake reason
2413 *
2414 * Return: reason code in string format
2415 */
2416static const u8 *wma_wow_wake_reason_str(A_INT32 wake_reason)
2417{
2418 switch (wake_reason) {
2419 case WOW_REASON_UNSPECIFIED:
2420 return "UNSPECIFIED";
2421 case WOW_REASON_NLOD:
2422 return "NLOD";
2423 case WOW_REASON_AP_ASSOC_LOST:
2424 return "AP_ASSOC_LOST";
2425 case WOW_REASON_LOW_RSSI:
2426 return "LOW_RSSI";
2427 case WOW_REASON_DEAUTH_RECVD:
2428 return "DEAUTH_RECVD";
2429 case WOW_REASON_DISASSOC_RECVD:
2430 return "DISASSOC_RECVD";
2431 case WOW_REASON_GTK_HS_ERR:
2432 return "GTK_HS_ERR";
2433 case WOW_REASON_EAP_REQ:
2434 return "EAP_REQ";
2435 case WOW_REASON_FOURWAY_HS_RECV:
2436 return "FOURWAY_HS_RECV";
2437 case WOW_REASON_TIMER_INTR_RECV:
2438 return "TIMER_INTR_RECV";
2439 case WOW_REASON_PATTERN_MATCH_FOUND:
2440 return "PATTERN_MATCH_FOUND";
2441 case WOW_REASON_RECV_MAGIC_PATTERN:
2442 return "RECV_MAGIC_PATTERN";
2443 case WOW_REASON_P2P_DISC:
2444 return "P2P_DISC";
2445#ifdef FEATURE_WLAN_LPHB
2446 case WOW_REASON_WLAN_HB:
2447 return "WLAN_HB";
2448#endif /* FEATURE_WLAN_LPHB */
2449
2450 case WOW_REASON_CSA_EVENT:
2451 return "CSA_EVENT";
2452 case WOW_REASON_PROBE_REQ_WPS_IE_RECV:
2453 return "PROBE_REQ_RECV";
2454 case WOW_REASON_AUTH_REQ_RECV:
2455 return "AUTH_REQ_RECV";
2456 case WOW_REASON_ASSOC_REQ_RECV:
2457 return "ASSOC_REQ_RECV";
2458 case WOW_REASON_HTT_EVENT:
2459 return "WOW_REASON_HTT_EVENT";
2460#ifdef FEATURE_WLAN_RA_FILTERING
2461 case WOW_REASON_RA_MATCH:
2462 return "WOW_REASON_RA_MATCH";
2463#endif /* FEATURE_WLAN_RA_FILTERING */
2464 case WOW_REASON_BEACON_RECV:
2465 return "WOW_REASON_IBSS_BEACON_RECV";
2466#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
2467 case WOW_REASON_HOST_AUTO_SHUTDOWN:
2468 return "WOW_REASON_HOST_AUTO_SHUTDOWN";
2469#endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
2470#ifdef WLAN_FEATURE_ROAM_OFFLOAD
2471 case WOW_REASON_ROAM_HO:
2472 return "WOW_REASON_ROAM_HO";
2473#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
2474#ifdef FEATURE_WLAN_EXTSCAN
2475 case WOW_REASON_EXTSCAN:
2476 return "WOW_REASON_EXTSCAN";
2477#endif
2478 case WOW_REASON_RSSI_BREACH_EVENT:
2479 return "WOW_REASON_RSSI_BREACH_EVENT";
Srinivas Girigowdae80cea92015-11-23 11:33:57 -08002480 case WOW_REASON_NLO_SCAN_COMPLETE:
2481 return "WOW_REASON_NLO_SCAN_COMPLETE";
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002482 }
2483 return "unknown";
2484}
2485
2486/**
2487 * wma_wow_wake_up_stats_display() - display wow wake up stats
2488 * @wma: Pointer to wma handle
2489 *
2490 * Return: none
2491 */
2492static void wma_wow_wake_up_stats_display(tp_wma_handle wma)
2493{
2494 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",
2495 wma->wow_ucast_wake_up_count,
2496 wma->wow_bcast_wake_up_count,
2497 wma->wow_ipv4_mcast_wake_up_count,
2498 wma->wow_ipv6_mcast_wake_up_count,
2499 wma->wow_ipv6_mcast_ra_stats,
2500 wma->wow_ipv6_mcast_ns_stats,
2501 wma->wow_ipv6_mcast_na_stats,
2502 wma->wow_pno_match_wake_up_count,
2503 wma->wow_pno_complete_wake_up_count,
2504 wma->wow_gscan_wake_up_count,
2505 wma->wow_low_rssi_wake_up_count,
2506 wma->wow_rssi_breach_wake_up_count);
2507
2508 return;
2509}
2510
2511/**
2512 * wma_wow_ipv6_mcast_stats() - ipv6 mcast wake up stats
2513 * @wma: Pointer to wma handle
2514 * @data: Pointer to pattern match data
2515 *
2516 * Return: none
2517 */
2518static void wma_wow_ipv6_mcast_stats(tp_wma_handle wma, uint8_t *data)
2519{
2520 static const uint8_t ipv6_mcast[] = {0x86, 0xDD};
2521
2522 if (!memcmp(ipv6_mcast, (data + WMA_ETHER_TYPE_OFFSET),
2523 sizeof(ipv6_mcast))) {
2524 if (WMA_ICMP_V6_HEADER_TYPE ==
2525 *(data + WMA_ICMP_V6_HEADER_OFFSET)) {
2526 if (WMA_ICMP_V6_RA_TYPE ==
2527 *(data + WMA_ICMP_V6_TYPE_OFFSET))
2528 wma->wow_ipv6_mcast_ra_stats++;
2529 else if (WMA_ICMP_V6_NS_TYPE ==
2530 *(data + WMA_ICMP_V6_TYPE_OFFSET))
2531 wma->wow_ipv6_mcast_ns_stats++;
2532 else if (WMA_ICMP_V6_NA_TYPE ==
2533 *(data + WMA_ICMP_V6_TYPE_OFFSET))
2534 wma->wow_ipv6_mcast_na_stats++;
2535 else
2536 WMA_LOGA("ICMP V6 type : 0x%x",
2537 *(data + WMA_ICMP_V6_TYPE_OFFSET));
2538 } else {
2539 WMA_LOGA("ICMP_V6 header 0x%x",
2540 *(data + WMA_ICMP_V6_HEADER_OFFSET));
2541 }
2542 } else {
2543 WMA_LOGA("Ethertype x%x:0x%x",
2544 *(data + WMA_ETHER_TYPE_OFFSET),
2545 *(data + WMA_ETHER_TYPE_OFFSET + 1));
2546 }
2547
2548 return;
2549}
2550
2551/**
2552 * wma_wow_wake_up_stats() - maintain wow pattern match wake up stats
2553 * @wma: Pointer to wma handle
2554 * @data: Pointer to pattern match data
2555 * @len: Pattern match data length
2556 * @event: Wake up event
2557 *
2558 * Return: none
2559 */
2560static void wma_wow_wake_up_stats(tp_wma_handle wma, uint8_t *data,
2561 int32_t len, WOW_WAKE_REASON_TYPE event)
2562{
2563 switch (event) {
2564
2565 case WOW_REASON_PATTERN_MATCH_FOUND:
2566 if (WMA_BCAST_MAC_ADDR == *data) {
2567 wma->wow_bcast_wake_up_count++;
2568 } else if (WMA_MCAST_IPV4_MAC_ADDR == *data) {
2569 wma->wow_ipv4_mcast_wake_up_count++;
2570 } else if (WMA_MCAST_IPV6_MAC_ADDR == *data) {
2571 wma->wow_ipv6_mcast_wake_up_count++;
2572 if (len > WMA_ICMP_V6_TYPE_OFFSET)
2573 wma_wow_ipv6_mcast_stats(wma, data);
2574 else
2575 WMA_LOGA("ICMP_V6 data len %d", len);
2576 } else {
2577 wma->wow_ucast_wake_up_count++;
2578 }
2579 break;
2580
2581 case WOW_REASON_RA_MATCH:
2582 wma->wow_ipv6_mcast_ra_stats++;
2583 break;
2584
2585 case WOW_REASON_NLOD:
2586 wma->wow_pno_match_wake_up_count++;
2587 break;
2588
2589 case WOW_REASON_NLO_SCAN_COMPLETE:
2590 wma->wow_pno_complete_wake_up_count++;
2591 break;
2592
2593 case WOW_REASON_LOW_RSSI:
2594 wma->wow_low_rssi_wake_up_count++;
2595 break;
2596
2597 case WOW_REASON_EXTSCAN:
2598 wma->wow_gscan_wake_up_count++;
2599 break;
2600
2601 case WOW_REASON_RSSI_BREACH_EVENT:
2602 wma->wow_rssi_breach_wake_up_count++;
2603 break;
2604
2605 default:
2606 WMA_LOGE("Unknown wake up reason");
2607 break;
2608 }
2609
2610 wma_wow_wake_up_stats_display(wma);
2611 return;
2612}
2613
2614/**
2615 * wma_wow_wakeup_host_event() - wakeup host event handler
2616 * @handle: wma handle
2617 * @event: event data
2618 * @len: buffer length
2619 *
2620 * Handler to catch wow wakeup host event. This event will have
2621 * reason why the firmware has woken the host.
2622 *
2623 * Return: 0 for success or error
2624 */
2625int wma_wow_wakeup_host_event(void *handle, uint8_t *event,
2626 uint32_t len)
2627{
2628 tp_wma_handle wma = (tp_wma_handle) handle;
2629 WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *param_buf;
2630 WOW_EVENT_INFO_fixed_param *wake_info;
2631#ifdef FEATURE_WLAN_SCAN_PNO
2632 struct wma_txrx_node *node;
2633#endif /* FEATURE_WLAN_SCAN_PNO */
2634 uint32_t wake_lock_duration = 0;
2635 uint32_t wow_buf_pkt_len = 0;
2636
2637 param_buf = (WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *) event;
2638 if (!param_buf) {
2639 WMA_LOGE("Invalid wow wakeup host event buf");
2640 return -EINVAL;
2641 }
2642
2643 wake_info = param_buf->fixed_param;
2644
2645 WMA_LOGA("WOW wakeup host event received (reason: %s(%d)) for vdev %d",
2646 wma_wow_wake_reason_str(wake_info->wake_reason),
2647 wake_info->wake_reason, wake_info->vdev_id);
2648
Anurag Chouhance0dc992016-02-16 18:18:03 +05302649 qdf_event_set(&wma->wma_resume_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002650
2651 switch (wake_info->wake_reason) {
2652 case WOW_REASON_AUTH_REQ_RECV:
2653 wake_lock_duration = WMA_AUTH_REQ_RECV_WAKE_LOCK_TIMEOUT;
2654 break;
2655
2656 case WOW_REASON_ASSOC_REQ_RECV:
2657 wake_lock_duration = WMA_ASSOC_REQ_RECV_WAKE_LOCK_DURATION;
2658 break;
2659
2660 case WOW_REASON_DEAUTH_RECVD:
2661 wake_lock_duration = WMA_DEAUTH_RECV_WAKE_LOCK_DURATION;
2662 break;
2663
2664 case WOW_REASON_DISASSOC_RECVD:
2665 wake_lock_duration = WMA_DISASSOC_RECV_WAKE_LOCK_DURATION;
2666 break;
2667
2668 case WOW_REASON_AP_ASSOC_LOST:
2669 wake_lock_duration = WMA_BMISS_EVENT_WAKE_LOCK_DURATION;
2670 WMA_LOGA("Beacon miss indication on vdev %x",
2671 wake_info->vdev_id);
2672 wma_beacon_miss_handler(wma, wake_info->vdev_id);
2673 break;
2674#ifdef FEATURE_WLAN_RA_FILTERING
2675 case WOW_REASON_RA_MATCH:
2676 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_RA_MATCH);
2677 break;
2678#endif /* FEATURE_WLAN_RA_FILTERING */
2679#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
2680 case WOW_REASON_HOST_AUTO_SHUTDOWN:
2681 wake_lock_duration = WMA_AUTO_SHUTDOWN_WAKE_LOCK_DURATION;
2682 WMA_LOGA("Received WOW Auto Shutdown trigger in suspend");
2683 if (wma_post_auto_shutdown_msg())
2684 return -EINVAL;
2685 break;
2686#endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
2687#ifdef FEATURE_WLAN_SCAN_PNO
2688 case WOW_REASON_NLOD:
2689 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_NLOD);
2690 node = &wma->interfaces[wake_info->vdev_id];
2691 if (node) {
2692 WMA_LOGD("NLO match happened");
2693 node->nlo_match_evt_received = true;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302694 qdf_wake_lock_timeout_acquire(&wma->pno_wake_lock,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002695 WMA_PNO_MATCH_WAKE_LOCK_TIMEOUT,
2696 WIFI_POWER_EVENT_WAKELOCK_PNO);
Srinivas Girigowdae80cea92015-11-23 11:33:57 -08002697 }
2698 break;
2699
2700 case WOW_REASON_NLO_SCAN_COMPLETE:
2701 {
2702 WMI_NLO_SCAN_COMPLETE_EVENTID_param_tlvs param;
2703
2704 WMA_LOGD("Host woken up due to pno scan complete reason");
2705
2706 /* First 4-bytes of wow_packet_buffer is the length */
2707 if (param_buf->wow_packet_buffer) {
2708 param.fixed_param = (wmi_nlo_event *)
2709 (param_buf->wow_packet_buffer + 4);
2710 wma_nlo_scan_cmp_evt_handler(handle,
2711 (u_int8_t *)&param, sizeof(param));
2712 } else
2713 WMA_LOGD("No wow_packet_buffer present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002714 }
2715 break;
2716#endif /* FEATURE_WLAN_SCAN_PNO */
2717
2718 case WOW_REASON_CSA_EVENT:
2719 {
2720 WMI_CSA_HANDLING_EVENTID_param_tlvs param;
2721 WMA_LOGD("Host woken up because of CSA IE");
2722 param.fixed_param = (wmi_csa_event_fixed_param *)
2723 (((uint8_t *) wake_info)
2724 + sizeof(WOW_EVENT_INFO_fixed_param)
2725 + WOW_CSA_EVENT_OFFSET);
2726 wma_csa_offload_handler(handle, (uint8_t *) &param,
2727 sizeof(param));
2728 }
2729 break;
2730
2731#ifdef FEATURE_WLAN_LPHB
2732 case WOW_REASON_WLAN_HB:
2733 wma_lphb_handler(wma, (uint8_t *) param_buf->hb_indevt);
2734 break;
2735#endif /* FEATURE_WLAN_LPHB */
2736
2737 case WOW_REASON_HTT_EVENT:
2738 break;
2739 case WOW_REASON_PATTERN_MATCH_FOUND:
2740 wma_wow_wake_up_stats_display(wma);
2741 WMA_LOGD("Wake up for Rx packet, dump starting from ethernet hdr");
2742 if (param_buf->wow_packet_buffer) {
2743 /* First 4-bytes of wow_packet_buffer is the length */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302744 qdf_mem_copy((uint8_t *) &wow_buf_pkt_len,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002745 param_buf->wow_packet_buffer, 4);
2746 wma_wow_wake_up_stats(wma,
2747 param_buf->wow_packet_buffer + 4,
2748 wow_buf_pkt_len,
2749 WOW_REASON_PATTERN_MATCH_FOUND);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302750 qdf_trace_hex_dump(QDF_MODULE_ID_WMA,
2751 QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002752 param_buf->wow_packet_buffer + 4,
2753 wow_buf_pkt_len);
2754 } else {
2755 WMA_LOGE("No wow packet buffer present");
2756 }
2757 break;
2758
2759 case WOW_REASON_LOW_RSSI:
2760 {
2761 /* WOW_REASON_LOW_RSSI is used for all roaming events.
2762 * WMI_ROAM_REASON_BETTER_AP, WMI_ROAM_REASON_BMISS,
2763 * WMI_ROAM_REASON_SUITABLE_AP will be handled by
2764 * wma_roam_event_callback().
2765 */
2766 WMI_ROAM_EVENTID_param_tlvs param;
2767 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_LOW_RSSI);
2768 if (param_buf->wow_packet_buffer) {
2769 /* Roam event is embedded in wow_packet_buffer */
2770 WMA_LOGD("Host woken up because of roam event");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302771 qdf_mem_copy((uint8_t *) &wow_buf_pkt_len,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002772 param_buf->wow_packet_buffer, 4);
2773 WMA_LOGD("wow_packet_buffer dump");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302774 qdf_trace_hex_dump(QDF_MODULE_ID_WMA,
2775 QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002776 param_buf->wow_packet_buffer,
2777 wow_buf_pkt_len);
2778 if (wow_buf_pkt_len >= sizeof(param)) {
2779 param.fixed_param =
2780 (wmi_roam_event_fixed_param *)
2781 (param_buf->wow_packet_buffer + 4);
2782 wma_roam_event_callback(handle,
2783 (uint8_t *) &
2784 param,
2785 sizeof(param));
2786 } else {
2787 WMA_LOGE("Wrong length for roam event = %d bytes",
2788 wow_buf_pkt_len);
2789 }
2790 } else {
2791 /* No wow_packet_buffer means a better AP beacon
2792 * will follow in a later event.
2793 */
2794 WMA_LOGD("Host woken up because of better AP beacon");
2795 }
2796 break;
2797 }
2798 case WOW_REASON_CLIENT_KICKOUT_EVENT:
2799 {
2800 WMI_PEER_STA_KICKOUT_EVENTID_param_tlvs param;
2801 if (param_buf->wow_packet_buffer) {
2802 /* station kickout event embedded in wow_packet_buffer */
2803 WMA_LOGD("Host woken up because of sta_kickout event");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302804 qdf_mem_copy((u_int8_t *) &wow_buf_pkt_len,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002805 param_buf->wow_packet_buffer, 4);
2806 WMA_LOGD("wow_packet_buffer dump");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302807 qdf_trace_hex_dump(QDF_MODULE_ID_WMA,
2808 QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002809 param_buf->wow_packet_buffer, wow_buf_pkt_len);
2810 if (wow_buf_pkt_len >= sizeof(param)) {
2811 param.fixed_param = (wmi_peer_sta_kickout_event_fixed_param *)
2812 (param_buf->wow_packet_buffer + 4);
2813 wma_peer_sta_kickout_event_handler(handle,
2814 (u_int8_t *)&param, sizeof(param));
2815 } else {
2816 WMA_LOGE("Wrong length for sta_kickout event = %d bytes",
2817 wow_buf_pkt_len);
2818 }
2819 } else {
2820 WMA_LOGD("No wow_packet_buffer present");
2821 }
2822 break;
2823 }
2824#ifdef FEATURE_WLAN_EXTSCAN
2825 case WOW_REASON_EXTSCAN:
2826 WMA_LOGD("Host woken up because of extscan reason");
2827 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_EXTSCAN);
2828 if (param_buf->wow_packet_buffer) {
2829 wow_buf_pkt_len =
2830 *(uint32_t *)param_buf->wow_packet_buffer;
2831 wma_extscan_wow_event_callback(handle,
2832 (u_int8_t *)(param_buf->wow_packet_buffer + 4),
2833 wow_buf_pkt_len);
2834 } else
2835 WMA_LOGE("wow_packet_buffer is empty");
2836 break;
2837#endif
2838 case WOW_REASON_RSSI_BREACH_EVENT:
2839 {
2840 WMI_RSSI_BREACH_EVENTID_param_tlvs param;
2841
2842 wma_wow_wake_up_stats(wma, NULL, 0,
2843 WOW_REASON_RSSI_BREACH_EVENT);
2844 WMA_LOGD("Host woken up because of rssi breach reason");
2845 /* rssi breach event is embedded in wow_packet_buffer */
2846 if (param_buf->wow_packet_buffer) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302847 qdf_mem_copy((u_int8_t *) &wow_buf_pkt_len,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002848 param_buf->wow_packet_buffer, 4);
2849 if (wow_buf_pkt_len >= sizeof(param)) {
2850 param.fixed_param =
2851 (wmi_rssi_breach_event_fixed_param *)
2852 (param_buf->wow_packet_buffer + 4);
2853 wma_rssi_breached_event_handler(handle,
2854 (u_int8_t *)&param,
2855 sizeof(param));
2856 } else {
2857 WMA_LOGE("%s: Wrong length: %d bytes",
2858 __func__, wow_buf_pkt_len);
2859 }
2860 } else
2861 WMA_LOGD("No wow_packet_buffer present");
2862 }
2863 break;
2864 default:
2865 break;
2866 }
2867
2868 if (wake_lock_duration) {
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302869 qdf_wake_lock_timeout_acquire(&wma->wow_wake_lock,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002870 wake_lock_duration,
2871 WIFI_POWER_EVENT_WAKELOCK_WOW);
2872 WMA_LOGA("Holding %d msec wake_lock", wake_lock_duration);
2873 }
2874
2875 return 0;
2876}
2877
2878/**
2879 * wma_pdev_resume_event_handler() - PDEV resume event handler
2880 * @handle: wma handle
2881 * @event: event data
2882 * @len: buffer length
2883 *
2884 * Return: 0 for success or error
2885 */
2886int wma_pdev_resume_event_handler(void *handle, uint8_t *event, uint32_t len)
2887{
2888 tp_wma_handle wma = (tp_wma_handle) handle;
2889
2890 WMA_LOGA("Received PDEV resume event");
2891
Anurag Chouhance0dc992016-02-16 18:18:03 +05302892 qdf_event_set(&wma->wma_resume_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002893
2894 return 0;
2895}
2896/**
2897 * wma_set_wow_bus_suspend() - set suspend flag
2898 * @wma: wma handle
2899 * @val: value
2900 *
2901 * Return: none
2902 */
2903static inline void wma_set_wow_bus_suspend(tp_wma_handle wma, int val)
2904{
2905
Anurag Chouhan8e0ccd32016-02-19 15:30:20 +05302906 qdf_atomic_set(&wma->is_wow_bus_suspended, val);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002907}
2908
2909
2910
2911/**
2912 * wma_add_wow_wakeup_event() - Configures wow wakeup events.
2913 * @wma: wma handle
2914 * @vdev_id: vdev id
2915 * @bitmap: Event bitmap
2916 * @enable: enable/disable
2917 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302918 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002919 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302920static QDF_STATUS wma_add_wow_wakeup_event(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002921 uint32_t vdev_id,
2922 uint32_t bitmap,
2923 bool enable)
2924{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002925 int ret;
2926
Govind Singhaa64c242016-03-08 11:31:49 +05302927 ret = wmi_unified_add_wow_wakeup_event_cmd(wma->wmi_handle, vdev_id,
2928 enable, bitmap);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002929 if (ret) {
2930 WMA_LOGE("Failed to config wow wakeup event");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302931 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002932 }
2933
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302934 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002935}
2936
2937/**
2938 * wma_send_wow_patterns_to_fw() - Sends WOW patterns to FW.
2939 * @wma: wma handle
2940 * @vdev_id: vdev id
2941 * @ptrn_id: pattern id
2942 * @ptrn: pattern
2943 * @ptrn_len: pattern length
2944 * @ptrn_offset: pattern offset
2945 * @mask: mask
2946 * @mask_len: mask length
2947 * @user: true for user configured pattern and false for default pattern
2948 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302949 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002950 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302951static QDF_STATUS wma_send_wow_patterns_to_fw(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002952 uint8_t vdev_id, uint8_t ptrn_id,
2953 const uint8_t *ptrn, uint8_t ptrn_len,
2954 uint8_t ptrn_offset, const uint8_t *mask,
2955 uint8_t mask_len, bool user)
2956{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002957 struct wma_txrx_node *iface;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002958 int ret;
Govind Singhaa64c242016-03-08 11:31:49 +05302959 uint8_t default_patterns;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002960
2961 iface = &wma->interfaces[vdev_id];
Govind Singhaa64c242016-03-08 11:31:49 +05302962 default_patterns = iface->num_wow_default_patterns++;
2963 ret = wmi_unified_wow_patterns_to_fw_cmd(wma->wmi_handle,
2964 vdev_id, ptrn_id, ptrn,
2965 ptrn_len, ptrn_offset, mask,
2966 mask_len, user, default_patterns);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002967 if (ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002968 if (!user)
2969 iface->num_wow_default_patterns--;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302970 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002971 }
2972
2973 if (user)
2974 iface->num_wow_user_patterns++;
2975
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302976 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002977}
2978
2979/**
2980 * wma_wow_ap() - set WOW patterns in ap mode
2981 * @wma: wma handle
2982 * @vdev_id: vdev id
2983 *
2984 * Configures default WOW pattern for the given vdev_id which is in AP mode.
2985 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302986 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002987 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302988static QDF_STATUS wma_wow_ap(tp_wma_handle wma, uint8_t vdev_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002989{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302990 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002991 uint8_t arp_offset = 20;
2992 uint8_t mac_mask[IEEE80211_ADDR_LEN];
2993
2994 /* Setup unicast pkt pattern */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302995 qdf_mem_set(&mac_mask, IEEE80211_ADDR_LEN, 0xFF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002996 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
2997 wma->interfaces[vdev_id].addr,
2998 IEEE80211_ADDR_LEN, 0, mac_mask,
2999 IEEE80211_ADDR_LEN, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303000 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003001 WMA_LOGE("Failed to add WOW unicast pattern ret %d", ret);
3002 return ret;
3003 }
3004
3005 /*
3006 * Setup all ARP pkt pattern. This is dummy pattern hence the length
3007 * is zero
3008 */
3009 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
3010 arp_ptrn, 0, arp_offset, arp_mask, 0, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303011 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003012 WMA_LOGE("Failed to add WOW ARP pattern ret %d", ret);
3013 return ret;
3014 }
3015
3016 return ret;
3017}
3018
3019/**
3020 * wma_wow_sta() - set WOW patterns in sta mode
3021 * @wma: wma handle
3022 * @vdev_id: vdev id
3023 *
3024 * Configures default WOW pattern for the given vdev_id which is in sta mode.
3025 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303026 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003027 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303028static QDF_STATUS wma_wow_sta(tp_wma_handle wma, uint8_t vdev_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003029{
3030 uint8_t arp_offset = 12;
3031 uint8_t discvr_offset = 30;
3032 uint8_t mac_mask[IEEE80211_ADDR_LEN];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303033 QDF_STATUS ret = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003034
3035 /* Setup unicast pkt pattern */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303036 qdf_mem_set(&mac_mask, IEEE80211_ADDR_LEN, 0xFF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003037 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
3038 wma->interfaces[vdev_id].addr,
3039 IEEE80211_ADDR_LEN, 0, mac_mask,
3040 IEEE80211_ADDR_LEN, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303041 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003042 WMA_LOGE("Failed to add WOW unicast pattern ret %d", ret);
3043 return ret;
3044 }
3045
3046 /*
3047 * Setup multicast pattern for mDNS 224.0.0.251,
3048 * SSDP 239.255.255.250 and LLMNR 224.0.0.252
3049 */
3050 if (wma->ssdp) {
3051 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
3052 discvr_ptrn, sizeof(discvr_ptrn), discvr_offset,
3053 discvr_mask, sizeof(discvr_ptrn), false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303054 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003055 WMA_LOGE("Failed to add WOW mDNS/SSDP/LLMNR pattern");
3056 return ret;
3057 }
3058 } else
3059 WMA_LOGD("mDNS, SSDP, LLMNR patterns are disabled from ini");
3060
3061 /* when arp offload or ns offloaded is disabled
3062 * from ini file, configure broad cast arp pattern
3063 * to fw, so that host can wake up
3064 */
3065 if (!(wma->ol_ini_info & 0x1)) {
3066 /* Setup all ARP pkt pattern */
3067 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
3068 arp_ptrn, sizeof(arp_ptrn), arp_offset,
3069 arp_mask, sizeof(arp_mask), false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303070 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003071 WMA_LOGE("Failed to add WOW ARP pattern");
3072 return ret;
3073 }
3074 }
3075
3076 /* for NS or NDP offload packets */
3077 if (!(wma->ol_ini_info & 0x2)) {
3078 /* Setup all NS pkt pattern */
3079 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
3080 ns_ptrn, sizeof(arp_ptrn), arp_offset,
3081 arp_mask, sizeof(arp_mask), false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303082 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003083 WMA_LOGE("Failed to add WOW NS pattern");
3084 return ret;
3085 }
3086 }
3087
3088 return ret;
3089}
3090
3091/**
3092 * wma_register_wow_default_patterns() - register default wow patterns with fw
3093 * @handle: Pointer to wma handle
3094 * @vdev_id: vdev id
3095 *
3096 * WoW default wake up pattern rule is:
3097 * - For STA & P2P CLI mode register for same STA specific wow patterns
3098 * - For SAP/P2P GO & IBSS mode register for same SAP specific wow patterns
3099 *
3100 * Return: none
3101 */
3102void wma_register_wow_default_patterns(WMA_HANDLE handle, uint8_t vdev_id)
3103{
3104 tp_wma_handle wma = handle;
3105 struct wma_txrx_node *iface;
3106
3107 if (vdev_id > wma->max_bssid) {
3108 WMA_LOGE("Invalid vdev id %d", vdev_id);
3109 return;
3110 }
3111 iface = &wma->interfaces[vdev_id];
3112
3113 if (iface->ptrn_match_enable) {
Houston Hoffman79b4af22015-10-06 12:01:08 -07003114 if (wma_is_vdev_in_beaconning_mode(wma, vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003115 /* Configure SAP/GO/IBSS mode default wow patterns */
3116 WMA_LOGI("Config SAP specific default wow patterns vdev_id %d",
3117 vdev_id);
3118 wma_wow_ap(wma, vdev_id);
3119 } else {
3120 /* Configure STA/P2P CLI mode default wow patterns */
3121 WMA_LOGI("Config STA specific default wow patterns vdev_id %d",
3122 vdev_id);
3123 wma_wow_sta(wma, vdev_id);
3124 if (wma->IsRArateLimitEnabled) {
3125 WMA_LOGI("Config STA RA limit wow patterns vdev_id %d",
3126 vdev_id);
3127 wma_wow_sta_ra_filter(wma, vdev_id);
3128 }
3129 }
3130 }
3131
3132 return;
3133}
3134
3135/**
3136 * wma_register_wow_wakeup_events() - register vdev specific wake events with fw
3137 * @handle: Pointer to wma handle
3138 * @vdev_id: vdev Id
3139 * @vdev_type: vdev type
3140 * @vdev_subtype: vdev sub type
3141 *
3142 * WoW wake up event rule is following:
3143 * 1) STA mode and P2P CLI mode wake up events are same
3144 * 2) SAP mode and P2P GO mode wake up events are same
3145 * 3) IBSS mode wake events are same as STA mode plus WOW_BEACON_EVENT
3146 *
3147 * Return: none
3148 */
3149void wma_register_wow_wakeup_events(WMA_HANDLE handle,
3150 uint8_t vdev_id,
3151 uint8_t vdev_type,
3152 uint8_t vdev_subtype)
3153{
3154 tp_wma_handle wma = handle;
3155 uint32_t event_bitmap;
3156
3157 WMA_LOGI("vdev_type %d vdev_subtype %d vdev_id %d", vdev_type,
3158 vdev_subtype, vdev_id);
3159
3160 if ((WMI_VDEV_TYPE_STA == vdev_type) ||
3161 ((WMI_VDEV_TYPE_AP == vdev_type) &&
3162 (WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE == vdev_subtype))) {
3163 /* Configure STA/P2P CLI mode specific default wake up events */
3164 event_bitmap = WMA_WOW_STA_WAKE_UP_EVENTS;
3165 WMA_LOGI("STA specific default wake up event 0x%x vdev id %d",
3166 event_bitmap, vdev_id);
3167 } else if (WMI_VDEV_TYPE_IBSS == vdev_type) {
3168 /* Configure IBSS mode specific default wake up events */
3169 event_bitmap = (WMA_WOW_STA_WAKE_UP_EVENTS |
3170 (1 << WOW_BEACON_EVENT));
3171 WMA_LOGI("IBSS specific default wake up event 0x%x vdev id %d",
3172 event_bitmap, vdev_id);
3173 } else if (WMI_VDEV_TYPE_AP == vdev_type) {
3174 /* Configure SAP/GO mode specific default wake up events */
3175 event_bitmap = WMA_WOW_SAP_WAKE_UP_EVENTS;
3176 WMA_LOGI("SAP specific default wake up event 0x%x vdev id %d",
3177 event_bitmap, vdev_id);
3178 } else {
3179 WMA_LOGE("unknown type %d subtype %d", vdev_type, vdev_subtype);
3180 return;
3181 }
3182
3183 wma_add_wow_wakeup_event(wma, vdev_id, event_bitmap, true);
3184
3185 return;
3186}
3187
3188/**
3189 * wma_enable_disable_wakeup_event() - Configures wow wakeup events
3190 * @wma: wma handle
3191 * @vdev_id: vdev id
3192 * @bitmap: Event bitmap
3193 * @enable: enable/disable
3194 *
3195 * Return: none
3196 */
3197void wma_enable_disable_wakeup_event(WMA_HANDLE handle,
3198 uint32_t vdev_id,
3199 uint32_t bitmap,
3200 bool enable)
3201{
3202 tp_wma_handle wma = handle;
3203
3204 WMA_LOGI("vdev_id %d wake up event 0x%x enable %d",
3205 vdev_id, bitmap, enable);
3206 wma_add_wow_wakeup_event(wma, vdev_id, bitmap, enable);
3207}
3208
3209/**
3210 * wma_enable_wow_in_fw() - wnable wow in fw
3211 * @wma: wma handle
3212 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303213 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003214 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303215QDF_STATUS wma_enable_wow_in_fw(WMA_HANDLE handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003216{
3217 tp_wma_handle wma = handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003218 int ret;
Komal Seelam3d202862016-02-24 18:43:24 +05303219 struct hif_opaque_softc *scn;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003220 int host_credits;
3221 int wmi_pending_cmds;
Govind Singhd76a5b02016-03-08 15:12:14 +05303222 struct wow_cmd_params param = {0};
3223
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003224#ifdef CONFIG_CNSS
Anurag Chouhan6d760662016-02-20 16:05:43 +05303225 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003226
3227 if (NULL == pMac) {
3228 WMA_LOGE("%s: Unable to get PE context", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303229 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003230 }
3231#endif /* CONFIG_CNSS */
3232
Anurag Chouhance0dc992016-02-16 18:18:03 +05303233 qdf_event_reset(&wma->target_suspend);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003234 wma->wow_nack = 0;
3235
3236 host_credits = wmi_get_host_credits(wma->wmi_handle);
3237 wmi_pending_cmds = wmi_get_pending_cmds(wma->wmi_handle);
3238
3239 WMA_LOGD("Credits:%d; Pending_Cmds: %d",
3240 host_credits, wmi_pending_cmds);
3241
3242 if (host_credits < WMI_WOW_REQUIRED_CREDITS) {
3243 WMA_LOGE("%s: Host Doesn't have enough credits to Post WMI_WOW_ENABLE_CMDID! "
3244 "Credits:%d, pending_cmds:%d\n", __func__, host_credits,
3245 wmi_pending_cmds);
3246#ifndef QCA_WIFI_3_0_EMU
3247 goto error;
3248#endif
3249 }
3250
Govind Singhd76a5b02016-03-08 15:12:14 +05303251 param.enable = true;
3252 param.can_suspend_link = hif_can_suspend_link(wma->htc_handle);
3253 ret = wmi_unified_wow_enable_send(wma->wmi_handle, &param,
3254 WMA_WILDCARD_PDEV_ID);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003255 if (ret) {
3256 WMA_LOGE("Failed to enable wow in fw");
3257 goto error;
3258 }
3259
3260 wmi_set_target_suspend(wma->wmi_handle, true);
3261
Anurag Chouhance0dc992016-02-16 18:18:03 +05303262 if (qdf_wait_single_event(&wma->target_suspend,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003263 WMA_TGT_SUSPEND_COMPLETE_TIMEOUT)
Anurag Chouhance0dc992016-02-16 18:18:03 +05303264 != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003265 WMA_LOGE("Failed to receive WoW Enable Ack from FW");
3266 WMA_LOGE("Credits:%d; Pending_Cmds: %d",
3267 wmi_get_host_credits(wma->wmi_handle),
3268 wmi_get_pending_cmds(wma->wmi_handle));
Prashanth Bhatta9e143052015-12-04 11:56:47 -08003269 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003270#ifdef CONFIG_CNSS
Yue Ma455aff62015-10-20 18:29:16 -07003271 if (pMac->sme.enableSelfRecovery) {
3272 cds_trigger_recovery();
3273 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303274 QDF_BUG(0);
Yue Ma455aff62015-10-20 18:29:16 -07003275 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003276#else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303277 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003278#endif /* CONFIG_CNSS */
Yue Ma455aff62015-10-20 18:29:16 -07003279 } else {
3280 WMA_LOGE("%s: LOGP is in progress, ignore!", __func__);
3281 }
3282
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003283 wmi_set_target_suspend(wma->wmi_handle, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303284 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003285 }
3286
3287 if (wma->wow_nack) {
3288 WMA_LOGE("FW not ready to WOW");
3289 wmi_set_target_suspend(wma->wmi_handle, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303290 return QDF_STATUS_E_AGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003291 }
3292
3293 host_credits = wmi_get_host_credits(wma->wmi_handle);
3294 wmi_pending_cmds = wmi_get_pending_cmds(wma->wmi_handle);
3295
3296 if (host_credits < WMI_WOW_REQUIRED_CREDITS) {
3297 WMA_LOGE("%s: No Credits after HTC ACK:%d, pending_cmds:%d, "
3298 "cannot resume back", __func__, host_credits,
3299 wmi_pending_cmds);
3300 htc_dump_counter_info(wma->htc_handle);
Prashanth Bhatta9e143052015-12-04 11:56:47 -08003301 if (!cds_is_driver_recovering())
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303302 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003303 else
3304 WMA_LOGE("%s: SSR in progress, ignore no credit issue",
3305 __func__);
3306 }
3307
3308 WMA_LOGD("WOW enabled successfully in fw: credits:%d"
3309 "pending_cmds: %d", host_credits, wmi_pending_cmds);
3310
Anurag Chouhan6d760662016-02-20 16:05:43 +05303311 scn = cds_get_context(QDF_MODULE_ID_HIF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003312
3313 if (scn == NULL) {
3314 WMA_LOGE("%s: Failed to get HIF context", __func__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303315 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303316 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003317 }
3318
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003319 wma->wow.wow_enable_cmd_sent = true;
3320
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303321 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003322
3323error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303324 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003325}
3326
3327/**
3328 * wma_resume_req() - clear configured wow patterns in fw
3329 * @wma: wma handle
Houston Hoffmana76591b2015-11-10 16:52:05 -08003330 * @type: type of suspend
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003331 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303332 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003333 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05303334QDF_STATUS wma_resume_req(tp_wma_handle wma, enum qdf_suspend_type type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003335{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303336 if (type == QDF_SYSTEM_SUSPEND) {
Houston Hoffmana76591b2015-11-10 16:52:05 -08003337 wma->no_of_resume_ind++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003338
Houston Hoffmana76591b2015-11-10 16:52:05 -08003339 if (wma->no_of_resume_ind < wma_get_vdev_count(wma))
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303340 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003341
Houston Hoffmana76591b2015-11-10 16:52:05 -08003342 wma->no_of_resume_ind = 0;
3343 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003344
3345 /* Reset the DTIM Parameters */
3346 wma_set_resume_dtim(wma);
3347 /* need to reset if hif_pci_suspend_fails */
3348 wma_set_wow_bus_suspend(wma, 0);
3349 /* unpause the vdev if left paused and hif_pci_suspend fails */
3350 wma_unpause_vdev(wma);
3351
Houston Hoffman1460fa32015-11-18 02:36:30 -08003352 wmi_set_runtime_pm_inprogress(wma->wmi_handle, false);
3353
Houston Hoffmanc45db892015-11-13 19:59:25 -08003354 if (type == QDF_RUNTIME_SUSPEND)
3355 qdf_runtime_pm_allow_suspend(wma->wma_runtime_resume_lock);
3356
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303357 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003358}
3359
3360/**
3361 * wma_wow_delete_pattern() - delete wow pattern in target
3362 * @wma: wma handle
3363 * @ptrn_id: pattern id
3364 * @vdev_id: vdev id
3365 * @user: true for user pattern and false for default pattern
3366 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303367 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003368 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303369static QDF_STATUS wma_wow_delete_pattern(tp_wma_handle wma, uint8_t ptrn_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003370 uint8_t vdev_id, bool user)
3371{
Govind Singhaa64c242016-03-08 11:31:49 +05303372
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003373 struct wma_txrx_node *iface;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003374 int ret;
3375
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003376 iface = &wma->interfaces[vdev_id];
Govind Singhaa64c242016-03-08 11:31:49 +05303377 ret = wmi_unified_wow_delete_pattern_cmd(wma->wmi_handle, ptrn_id,
3378 vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003379 if (ret) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303380 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003381 }
3382
3383 if (user)
3384 iface->num_wow_user_patterns--;
3385
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303386 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003387}
3388
3389/**
3390 * wma_wow_add_pattern() - add wow pattern in target
3391 * @wma: wma handle
3392 * @ptrn: wow pattern
3393 *
3394 * This function does following:
3395 * 1) Delete all default patterns of the vdev
3396 * 2) Add received wow patterns for given vdev in target.
3397 *
3398 * Target is responsible for caching wow patterns accross multiple
3399 * suspend/resumes until the pattern is deleted by user
3400 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303401 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003402 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303403QDF_STATUS wma_wow_add_pattern(tp_wma_handle wma, struct wow_add_pattern *ptrn)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003404{
3405 uint8_t id;
3406 uint8_t bit_to_check, pos;
3407 struct wma_txrx_node *iface;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303408 QDF_STATUS ret = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003409 uint8_t new_mask[SIR_WOWL_BCAST_PATTERN_MAX_SIZE];
3410
3411 if (ptrn->session_id > wma->max_bssid) {
3412 WMA_LOGE("Invalid vdev id (%d)", ptrn->session_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303413 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003414 }
3415
3416 iface = &wma->interfaces[ptrn->session_id];
3417
3418 /* clear all default patterns cofigured by wma */
3419 for (id = 0; id < iface->num_wow_default_patterns; id++)
3420 wma_wow_delete_pattern(wma, id, ptrn->session_id, false);
3421
3422 iface->num_wow_default_patterns = 0;
3423
3424 WMA_LOGI("Add user passed wow pattern id %d vdev id %d",
3425 ptrn->pattern_id, ptrn->session_id);
3426 /*
3427 * Convert received pattern mask value from bit representation
3428 * to byte representation.
3429 *
3430 * For example, received value from umac,
3431 *
3432 * Mask value : A1 (equivalent binary is "1010 0001")
3433 * Pattern value : 12:00:13:00:00:00:00:44
3434 *
3435 * The value which goes to FW after the conversion from this
3436 * function (1 in mask value will become FF and 0 will
3437 * become 00),
3438 *
3439 * Mask value : FF:00:FF:00:0:00:00:FF
3440 * Pattern value : 12:00:13:00:00:00:00:44
3441 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303442 qdf_mem_zero(new_mask, sizeof(new_mask));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003443 for (pos = 0; pos < ptrn->pattern_size; pos++) {
3444 bit_to_check = (WMA_NUM_BITS_IN_BYTE - 1) -
3445 (pos % WMA_NUM_BITS_IN_BYTE);
3446 bit_to_check = 0x1 << bit_to_check;
3447 if (ptrn->pattern_mask[pos / WMA_NUM_BITS_IN_BYTE] &
3448 bit_to_check)
3449 new_mask[pos] = WMA_WOW_PTRN_MASK_VALID;
3450 }
3451
3452 ret = wma_send_wow_patterns_to_fw(wma, ptrn->session_id,
3453 ptrn->pattern_id,
3454 ptrn->pattern, ptrn->pattern_size,
3455 ptrn->pattern_byte_offset, new_mask,
3456 ptrn->pattern_size, true);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303457 if (ret != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003458 WMA_LOGE("Failed to add wow pattern %d", ptrn->pattern_id);
3459
3460 return ret;
3461}
3462
3463/**
3464 * wma_wow_delete_user_pattern() - delete user configured wow pattern in target
3465 * @wma: wma handle
3466 * @ptrn: wow pattern
3467 *
3468 * This function does following:
3469 * 1) Deletes a particular user configured wow pattern in target
3470 * 2) After deleting all user wow patterns add default wow patterns
3471 * specific to that vdev.
3472 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303473 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003474 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303475QDF_STATUS wma_wow_delete_user_pattern(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003476 struct wow_delete_pattern *pattern)
3477{
3478 struct wma_txrx_node *iface;
3479
3480 if (pattern->session_id > wma->max_bssid) {
3481 WMA_LOGE("Invalid vdev id %d", pattern->session_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303482 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003483 }
3484
3485 iface = &wma->interfaces[pattern->session_id];
3486 if (iface->num_wow_user_patterns <= 0) {
3487 WMA_LOGE("No valid user pattern. Num user pattern %u vdev %d",
3488 iface->num_wow_user_patterns, pattern->session_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303489 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003490 }
3491
3492 WMA_LOGI("Delete user passed wow pattern id %d total user pattern %d",
3493 pattern->pattern_id, iface->num_wow_user_patterns);
3494
3495 wma_wow_delete_pattern(wma, pattern->pattern_id,
3496 pattern->session_id, true);
3497
3498 /* configure default patterns once all user patterns are deleted */
3499 if (!iface->num_wow_user_patterns)
3500 wma_register_wow_default_patterns(wma, pattern->session_id);
3501
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303502 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003503}
3504
3505/**
3506 * wma_wow_enter() - store enable/disable status for pattern
3507 * @wma: wma handle
3508 * @info: wow parameters
3509 *
3510 * Records pattern enable/disable status locally. This choice will
3511 * take effect when the driver enter into suspend state.
3512 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303513 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003514 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303515QDF_STATUS wma_wow_enter(tp_wma_handle wma, tpSirHalWowlEnterParams info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003516{
3517 struct wma_txrx_node *iface;
3518
3519 WMA_LOGD("wow enable req received for vdev id: %d", info->sessionId);
3520
3521 if (info->sessionId > wma->max_bssid) {
3522 WMA_LOGE("Invalid vdev id (%d)", info->sessionId);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303523 qdf_mem_free(info);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303524 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003525 }
3526
3527 iface = &wma->interfaces[info->sessionId];
3528 iface->ptrn_match_enable = info->ucPatternFilteringEnable ?
3529 true : false;
3530 wma->wow.magic_ptrn_enable = info->ucMagicPktEnable ? true : false;
3531 wma->wow.deauth_enable = info->ucWowDeauthRcv ? true : false;
3532 wma->wow.disassoc_enable = info->ucWowDeauthRcv ? true : false;
3533 wma->wow.bmiss_enable = info->ucWowMaxMissedBeacons ? true : false;
3534
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303535 qdf_mem_free(info);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003536
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303537 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003538}
3539
3540/**
3541 * wma_wow_exit() - clear all wma states
3542 * @wma: wma handle
3543 * @info: wow params
3544 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303545 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003546 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303547QDF_STATUS wma_wow_exit(tp_wma_handle wma, tpSirHalWowlExitParams info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003548{
3549 struct wma_txrx_node *iface;
3550
3551 WMA_LOGD("wow disable req received for vdev id: %d", info->sessionId);
3552
3553 if (info->sessionId > wma->max_bssid) {
3554 WMA_LOGE("Invalid vdev id (%d)", info->sessionId);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303555 qdf_mem_free(info);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303556 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003557 }
3558
3559 iface = &wma->interfaces[info->sessionId];
3560 iface->ptrn_match_enable = false;
3561 wma->wow.magic_ptrn_enable = false;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303562 qdf_mem_free(info);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003563
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303564 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003565}
3566
3567/**
Houston Hoffmana76591b2015-11-10 16:52:05 -08003568 * wma_calculate_and_update_conn_state(): calculate each interfaces conn state
3569 * @wma: validated wma handle
3570 *
3571 * Identifies any vdev that is up and not in ap mode as connected.
3572 * stores this in the interfaces conn_state varible.
3573 */
3574void wma_calculate_and_update_conn_state(tp_wma_handle wma)
3575{
3576 int i;
3577 for (i = 0; i < wma->max_bssid; i++) {
3578 wma->interfaces[i].conn_state =
3579 !!(wma->interfaces[i].vdev_up &&
3580 !wma_is_vdev_in_ap_mode(wma, i));
3581 }
3582}
3583
3584/**
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003585 * wma_update_conn_state(): synchronize wma & hdd
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003586 * @wma: wma handle
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003587 * @conn_state: boolean array to populate
3588 * @len: validation parameter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003589 *
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003590 * populate interfaces conn_state with true if the interface
3591 * is a connected client and wow will configure a pattern.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003592 */
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003593void wma_update_conn_state(tp_wma_handle wma, uint32_t conn_mask)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003594{
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003595 int i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003596 for (i = 0; i < wma->max_bssid; i++) {
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003597 if (conn_mask & (1 << i))
3598 wma->interfaces[i].conn_state = true;
3599 else
3600 wma->interfaces[i].conn_state = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003601 }
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003602
3603 if (wma->wow.magic_ptrn_enable)
3604 return;
3605
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003606 for (i = 0; i < wma->max_bssid; i++) {
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003607 if (!wma->interfaces[i].ptrn_match_enable)
3608 wma->interfaces[i].conn_state = false;
3609 }
3610}
3611
3612/**
3613 * wma_is_beaconning_vdev_up(): check if a beaconning vdev is up
3614 * @wma: wma handle
3615 *
3616 * Return TRUE if beaconning vdev is up
3617 */
3618static inline
3619bool wma_is_beaconning_vdev_up(tp_wma_handle wma)
3620{
3621 int i;
3622 for (i = 0; i < wma->max_bssid; i++) {
3623 if (wma_is_vdev_in_beaconning_mode(wma, i)
3624 && wma->interfaces[i].vdev_up)
3625 return true;
3626 }
3627 return false;
3628}
3629
3630/**
3631 * wma_support_wow_for_beaconing: wow query for beaconning
3632 * @wma: wma handle
3633 *
3634 * Need to configure wow to enable beaconning offload when
3635 * a beaconing vdev is up and beaonning offload is configured.
3636 *
3637 * Return: true if we need to enable wow for beaconning offload
3638 */
3639static inline
3640bool wma_support_wow_for_beaconing(tp_wma_handle wma)
3641{
3642 if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
3643 WMI_SERVICE_BEACON_OFFLOAD)) {
3644 if (wma_is_beaconning_vdev_up(wma))
3645 return true;
3646 }
3647 return false;
3648}
3649
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003650#ifdef FEATURE_WLAN_SCAN_PNO
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003651/**
3652 * wma_is_pnoscan_in_progress(): check if a pnoscan is in progress
3653 * @wma: wma handle
3654 * @vdev_id: vdev_id
3655 *
3656 * Return: TRUE/FALSE
3657 */
3658static inline
3659bool wma_is_pnoscan_in_progress(tp_wma_handle wma, int vdev_id)
3660{
3661 return wma->interfaces[vdev_id].pno_in_progress;
3662}
Houston Hoffman345fa402015-12-16 11:28:51 -08003663
3664/**
3665 * wma_is_pnoscan_match_found(): check if a scan match was found
3666 * @wma: wma handle
3667 * @vdev_id: vdev_id
3668 *
3669 * Return: TRUE/FALSE
3670 */
3671static inline
3672bool wma_is_pnoscan_match_found(tp_wma_handle wma, int vdev_id)
3673{
3674 return wma->interfaces[vdev_id].nlo_match_evt_received;
3675}
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003676#else
3677/**
3678 * wma_is_pnoscan_in_progress(): dummy
3679 *
Houston Hoffman345fa402015-12-16 11:28:51 -08003680 * Return: False since no pnoscan cannot be in progress
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003681 * when feature flag is not defined.
3682 */
3683bool wma_is_pnoscan_in_progress(tp_wma_handle wma, int vdev_id)
3684{
3685 return FALSE;
3686}
Houston Hoffman345fa402015-12-16 11:28:51 -08003687
3688/**
3689 * wma_is_pnoscan_match_found(): dummy
3690 * @wma: wma handle
3691 * @vdev_id: vdev_id
3692 *
3693 * Return: False since no pnoscan cannot occur
3694 * when feature flag is not defined.
3695 */
3696static inline
3697bool wma_is_pnoscan_match_found(tp_wma_handle wma, int vdev_id)
3698{
3699 return FALSE;
3700}
Houston Hoffman61667962015-12-15 20:15:41 -08003701#endif
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003702
3703#ifdef FEATURE_WLAN_EXTSCAN
3704static inline
3705/**
3706 * wma_is_extscan_in_progress(): check if an extscan is in progress
3707 * @wma: wma handle
3708 * @vdev_id: vdev_id
3709 *
3710 * Return: TRUE/FALSvE
3711 */
3712bool wma_is_extscan_in_progress(tp_wma_handle wma, int vdev_id)
3713{
3714 return wma->interfaces[vdev_id].extscan_in_progress;
3715}
3716#else
3717/**
3718 * wma_is_extscan_in_progress(): dummy
3719 *
3720 * Return: False since no extscan can be in progress
3721 * when feature flag is not defined.
3722 */
3723bool wma_is_extscan_in_progress(tp_wma_handle wma, int vdev_id)
3724{
3725 return false;
3726}
3727#endif
3728
3729/**
3730 * wma_is_wow_applicable(): should enable wow
3731 * @wma: wma handle
3732 *
3733 * Enable WOW if any one of the condition meets,
3734 * 1) Is any one of vdev in beaconning mode (in AP mode) ?
3735 * 2) Is any one of vdev in connected state (in STA mode) ?
3736 * 3) Is PNO in progress in any one of vdev ?
3737 * 4) Is Extscan in progress in any one of vdev ?
Rajeev Kumaraea89632016-02-02 18:02:32 -08003738 * If none of above conditions is true then return false
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003739 *
Rajeev Kumaraea89632016-02-02 18:02:32 -08003740 * Return: true if wma needs to configure wow false otherwise.
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003741 */
3742bool wma_is_wow_applicable(tp_wma_handle wma)
3743{
3744 int vdev_id;
3745 if (wma_support_wow_for_beaconing(wma)) {
3746 WMA_LOGD("vdev is in beaconning mode, enabling wow");
3747 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003748 }
3749
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003750 for (vdev_id = 0; vdev_id < wma->max_bssid; vdev_id++) {
3751 if (wma->interfaces[vdev_id].conn_state) {
3752 WMA_LOGD("STA is connected, enabling wow");
3753 return true;
3754 } else if (wma_is_pnoscan_in_progress(wma, vdev_id)) {
3755 WMA_LOGD("PNO is in progress, enabling wow");
3756 return true;
3757 } else if (wma_is_extscan_in_progress(wma, vdev_id)) {
3758 WMA_LOGD("EXT is in progress, enabling wow");
3759 return true;
3760 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003761 }
3762
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003763 WMA_LOGD("All vdev are in disconnected state and pno/extscan is not in progress, skipping wow");
Rajeev Kumaraea89632016-02-02 18:02:32 -08003764 return false;
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003765}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003766
Houston Hoffman345fa402015-12-16 11:28:51 -08003767/**
3768 * wma_configure_dynamic_wake_events(): configure dyanmic wake events
3769 * @wma: wma handle
3770 *
3771 * Some wake events need to be enabled dynamically. Controll those here.
3772 *
3773 * Return: none
3774 */
3775void wma_configure_dynamic_wake_events(tp_wma_handle wma)
3776{
3777 int vdev_id;
3778 int enable_mask;
3779 int disable_mask;
3780
3781 for (vdev_id = 0; vdev_id < wma->max_bssid; vdev_id++) {
3782 enable_mask = 0;
3783 disable_mask = 0;
3784
3785 if (wma_is_pnoscan_in_progress(wma, vdev_id)) {
3786 if (wma_is_pnoscan_match_found(wma, vdev_id))
3787 enable_mask |=
3788 (1 << WOW_NLO_SCAN_COMPLETE_EVENT);
3789 else
3790 disable_mask |=
3791 (1 << WOW_NLO_SCAN_COMPLETE_EVENT);
3792 }
3793
3794 if (enable_mask != 0)
3795 wma_enable_disable_wakeup_event(wma, vdev_id,
3796 enable_mask, true);
3797 if (disable_mask != 0)
3798 wma_enable_disable_wakeup_event(wma, vdev_id,
3799 disable_mask, false);
3800 }
3801}
3802
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003803#ifdef FEATURE_WLAN_LPHB
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003804/**
3805 * wma_apply_lphb(): apply cached LPHB settings
3806 * @wma: wma handle
3807 *
3808 * LPHB cache, if any item was enabled, should be
3809 * applied.
3810 */
3811static inline
3812void wma_apply_lphb(tp_wma_handle wma)
3813{
3814 int i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003815 WMA_LOGD("%s: checking LPHB cache", __func__);
3816 for (i = 0; i < 2; i++) {
3817 if (wma->wow.lphb_cache[i].params.lphbEnableReq.enable) {
3818 WMA_LOGD("%s: LPHB cache for item %d is marked as enable",
3819 __func__, i + 1);
3820 wma_lphb_conf_hbenable(wma, &(wma->wow.lphb_cache[i]),
3821 false);
3822 }
3823 }
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003824}
3825#else
3826void wma_apply_lphb(tp_wma_handle wma) {}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003827#endif /* FEATURE_WLAN_LPHB */
3828
Houston Hoffmana76591b2015-11-10 16:52:05 -08003829static void wma_notify_suspend_req_procesed(tp_wma_handle wma,
Anurag Chouhan6d760662016-02-20 16:05:43 +05303830 enum qdf_suspend_type type)
Houston Hoffmana76591b2015-11-10 16:52:05 -08003831{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303832 if (type == QDF_SYSTEM_SUSPEND)
Houston Hoffmana76591b2015-11-10 16:52:05 -08003833 wma_send_status_to_suspend_ind(wma, true);
Anurag Chouhan6d760662016-02-20 16:05:43 +05303834 else if (type == QDF_RUNTIME_SUSPEND)
Anurag Chouhance0dc992016-02-16 18:18:03 +05303835 qdf_event_set(&wma->runtime_suspend);
Houston Hoffmana76591b2015-11-10 16:52:05 -08003836}
3837
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003838/**
3839 * wma_suspend_req() - Handles suspend indication request received from umac.
3840 * @wma: wma handle
Houston Hoffmana76591b2015-11-10 16:52:05 -08003841 * @type: type of suspend
3842 *
3843 * The type controlls how we notify the indicator that the indication has
3844 * been processed
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003845 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303846 * Return: QDF status
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003847 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05303848QDF_STATUS wma_suspend_req(tp_wma_handle wma, enum qdf_suspend_type type)
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003849{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303850 if (type == QDF_RUNTIME_SUSPEND)
Houston Hoffman1460fa32015-11-18 02:36:30 -08003851 wmi_set_runtime_pm_inprogress(wma->wmi_handle, true);
3852
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003853 if (wma_is_wow_applicable(wma)) {
3854 WMA_LOGE("WOW Suspend");
3855 wma_apply_lphb(wma);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003856
Houston Hoffman345fa402015-12-16 11:28:51 -08003857 wma_configure_dynamic_wake_events(wma);
3858
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003859 wma->wow.wow_enable = true;
3860 wma->wow.wow_enable_cmd_sent = false;
3861 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003862
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003863 /* Set the Suspend DTIM Parameters */
3864 wma_set_suspend_dtim(wma);
Houston Hoffmana76591b2015-11-10 16:52:05 -08003865
3866 wma_notify_suspend_req_procesed(wma, type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003867
3868 /* to handle race between hif_pci_suspend and
3869 * unpause/pause tx handler
3870 */
3871 wma_set_wow_bus_suspend(wma, 1);
3872
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303873 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003874}
3875
3876/**
3877 * wma_send_host_wakeup_ind_to_fw() - send wakeup ind to fw
3878 * @wma: wma handle
3879 *
3880 * Sends host wakeup indication to FW. On receiving this indication,
3881 * FW will come out of WOW.
3882 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303883 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003884 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303885static QDF_STATUS wma_send_host_wakeup_ind_to_fw(tp_wma_handle wma)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003886{
Anurag Chouhance0dc992016-02-16 18:18:03 +05303887 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003888 int ret;
3889#ifdef CONFIG_CNSS
Anurag Chouhan6d760662016-02-20 16:05:43 +05303890 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003891 if (NULL == pMac) {
3892 WMA_LOGE("%s: Unable to get PE context", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303893 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003894 }
3895#endif /* CONFIG_CNSS */
3896
Anurag Chouhance0dc992016-02-16 18:18:03 +05303897 qdf_event_reset(&wma->wma_resume_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003898
Govind Singhaa64c242016-03-08 11:31:49 +05303899 ret = wmi_unified_host_wakeup_ind_to_fw_cmd(wma->wmi_handle);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003900 if (ret) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303901 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003902 }
3903
3904 WMA_LOGD("Host wakeup indication sent to fw");
3905
Anurag Chouhance0dc992016-02-16 18:18:03 +05303906 qdf_status = qdf_wait_single_event(&(wma->wma_resume_event),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003907 WMA_RESUME_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05303908 if (QDF_STATUS_SUCCESS != qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003909 WMA_LOGP("%s: Timeout waiting for resume event from FW",
3910 __func__);
3911 WMA_LOGP("%s: Pending commands %d credits %d", __func__,
3912 wmi_get_pending_cmds(wma->wmi_handle),
3913 wmi_get_host_credits(wma->wmi_handle));
Prashanth Bhatta9e143052015-12-04 11:56:47 -08003914 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003915#ifdef CONFIG_CNSS
3916 if (pMac->sme.enableSelfRecovery) {
3917 cds_trigger_recovery();
3918 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303919 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003920 }
3921#else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303922 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003923#endif /* CONFIG_CNSS */
3924 } else {
3925 WMA_LOGE("%s: SSR in progress, ignore resume timeout",
3926 __func__);
3927 }
3928 } else {
3929 WMA_LOGD("Host wakeup received");
3930 }
3931
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303932 if (QDF_STATUS_SUCCESS == qdf_status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003933 wmi_set_target_suspend(wma->wmi_handle, false);
3934
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303935 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003936}
3937
3938/**
3939 * wma_disable_wow_in_fw() - Disable wow in PCIe resume context.
3940 * @handle: wma handle
3941 *
3942 * Return: 0 for success or error code
3943 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303944QDF_STATUS wma_disable_wow_in_fw(WMA_HANDLE handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003945{
3946 tp_wma_handle wma = handle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303947 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003948
3949 if (!wma->wow.wow_enable || !wma->wow.wow_enable_cmd_sent)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303950 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003951
3952 ret = wma_send_host_wakeup_ind_to_fw(wma);
3953
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303954 if (ret != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003955 return ret;
3956
3957 wma->wow.wow_enable = false;
3958 wma->wow.wow_enable_cmd_sent = false;
3959
3960 /* To allow the tx pause/unpause events */
3961 wma_set_wow_bus_suspend(wma, 0);
3962 /* Unpause the vdev as we are resuming */
3963 wma_unpause_vdev(wma);
3964
3965 return ret;
3966}
3967
3968#ifdef WLAN_FEATURE_LPSS
3969/**
3970 * wma_is_lpass_enabled() - check if lpass is enabled
3971 * @handle: Pointer to wma handle
3972 *
3973 * WoW is needed if LPASS or NaN feature is enabled in INI because
3974 * target can't wake up itself if its put in PDEV suspend when LPASS
3975 * or NaN features are supported
3976 *
3977 * Return: true if lpass is enabled else false
3978 */
3979bool static wma_is_lpass_enabled(tp_wma_handle wma)
3980{
3981 if (wma->is_lpass_enabled)
3982 return true;
3983 else
3984 return false;
3985}
3986#else
3987bool static wma_is_lpass_enabled(tp_wma_handle wma)
3988{
3989 return false;
3990}
3991#endif
3992
3993#ifdef WLAN_FEATURE_NAN
3994/**
3995 * wma_is_nan_enabled() - check if NaN is enabled
3996 * @handle: Pointer to wma handle
3997 *
3998 * WoW is needed if LPASS or NaN feature is enabled in INI because
3999 * target can't wake up itself if its put in PDEV suspend when LPASS
4000 * or NaN features are supported
4001 *
4002 * Return: true if NaN is enabled else false
4003 */
4004bool static wma_is_nan_enabled(tp_wma_handle wma)
4005{
4006 if (wma->is_nan_enabled)
4007 return true;
4008 else
4009 return false;
4010}
4011#else
4012bool static wma_is_nan_enabled(tp_wma_handle wma)
4013{
4014 return false;
4015}
4016#endif
4017
4018/**
4019 * wma_is_wow_mode_selected() - check if wow needs to be enabled in fw
4020 * @handle: Pointer to wma handle
4021 *
4022 * If lpass is enabled then always do wow else check wow_enable config
4023 *
4024 * Return: true is wow mode is needed else false
4025 */
Houston Hoffmana76591b2015-11-10 16:52:05 -08004026bool wma_is_wow_mode_selected(WMA_HANDLE handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004027{
4028 tp_wma_handle wma = (tp_wma_handle) handle;
4029
4030 if (wma_is_lpass_enabled(wma)) {
4031 WMA_LOGD("LPASS is enabled select WoW");
4032 return true;
4033 } else if (wma_is_nan_enabled(wma)) {
4034 WMA_LOGD("NAN is enabled select WoW");
4035 return true;
4036 } else {
4037 WMA_LOGD("WoW enable %d", wma->wow.wow_enable);
4038 return wma->wow.wow_enable;
4039 }
4040}
4041
4042/**
4043 * wma_del_ts_req() - send DELTS request to fw
4044 * @wma: wma handle
4045 * @msg: delts params
4046 *
4047 * Return: none
4048 */
4049void wma_del_ts_req(tp_wma_handle wma, tDelTsParams *msg)
4050{
Govind Singhaa64c242016-03-08 11:31:49 +05304051 if (wmi_unified_del_ts_cmd(wma->wmi_handle,
4052 msg->sessionId,
4053 TID_TO_WME_AC(msg->userPrio))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004054 WMA_LOGP("%s: Failed to send vdev DELTS command", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004055 }
Govind Singhaa64c242016-03-08 11:31:49 +05304056
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004057#ifdef WLAN_FEATURE_ROAM_OFFLOAD
4058 if (msg->setRICparams == true)
4059 wma_set_ric_req(wma, msg, false);
4060#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
4061
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304062 qdf_mem_free(msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004063}
4064
4065/**
4066 * wma_aggr_qos_req() - send aggr qos request to fw
4067 * @wma: handle to wma
4068 * @pAggrQosRspMsg - combined struct for all ADD_TS requests.
4069 *
4070 * A function to handle WMA_AGGR_QOS_REQ. This will send out
4071 * ADD_TS requestes to firmware in loop for all the ACs with
4072 * active flow.
4073 *
4074 * Return: none
4075 */
4076void wma_aggr_qos_req(tp_wma_handle wma,
4077 tAggrAddTsParams *pAggrQosRspMsg)
4078{
Govind Singhaa64c242016-03-08 11:31:49 +05304079 wmi_unified_aggr_qos_cmd(wma->wmi_handle,
4080 (struct aggr_add_ts_param *)pAggrQosRspMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004081 /* send reponse to upper layers from here only. */
4082 wma_send_msg(wma, WMA_AGGR_QOS_RSP, pAggrQosRspMsg, 0);
4083}
4084
4085/**
4086 * wma_add_ts_req() - send ADDTS request to fw
4087 * @wma: wma handle
4088 * @msg: ADDTS params
4089 *
4090 * Return: none
4091 */
4092void wma_add_ts_req(tp_wma_handle wma, tAddTsParams *msg)
4093{
Govind Singhaa64c242016-03-08 11:31:49 +05304094 struct add_ts_param cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004095
4096#ifdef FEATURE_WLAN_ESE
4097 /*
4098 * msmt_interval is in unit called TU (1 TU = 1024 us)
4099 * max value of msmt_interval cannot make resulting
4100 * interval_miliseconds overflow 32 bit
4101 */
4102 uint32_t intervalMiliseconds;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304103 ol_txrx_pdev_handle pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004104 if (NULL == pdev) {
4105 WMA_LOGE("%s: Failed to get pdev", __func__);
4106 goto err;
4107 }
4108
4109 intervalMiliseconds = (msg->tsm_interval * 1024) / 1000;
4110
4111 ol_tx_set_compute_interval(pdev, intervalMiliseconds);
4112#endif /* FEATURE_WLAN_ESE */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304113 msg->status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004114
Govind Singhaa64c242016-03-08 11:31:49 +05304115
4116 cmd.sme_session_id = msg->sme_session_id;
4117 cmd.tspec.tsinfo.traffic.userPrio =
4118 TID_TO_WME_AC(msg->tspec.tsinfo.traffic.userPrio);
4119 cmd.tspec.mediumTime = msg->tspec.mediumTime;
4120 if (wmi_unified_add_ts_cmd(wma->wmi_handle, &cmd))
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304121 msg->status = QDF_STATUS_E_FAILURE;
Govind Singhaa64c242016-03-08 11:31:49 +05304122
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004123#ifdef WLAN_FEATURE_ROAM_OFFLOAD
4124 if (msg->setRICparams == true)
4125 wma_set_ric_req(wma, msg, true);
4126#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
4127
4128err:
4129 wma_send_msg(wma, WMA_ADD_TS_RSP, msg, 0);
4130}
4131
4132/**
4133 * wma_enable_disable_packet_filter() - enable/disable packet filter in target
4134 * @wma: Pointer to wma handle
4135 * @vdev_id: vdev id
4136 * @enable: Flag to enable/disable packet filter
4137 *
4138 * Return: 0 for success or error code
4139 */
4140static int wma_enable_disable_packet_filter(tp_wma_handle wma,
4141 uint8_t vdev_id, bool enable)
4142{
Govind Singhaa64c242016-03-08 11:31:49 +05304143 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004144
Govind Singhaa64c242016-03-08 11:31:49 +05304145 ret = wmi_unified_enable_disable_packet_filter_cmd(wma->wmi_handle,
4146 vdev_id, enable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004147 if (ret)
4148 WMA_LOGE("Failed to send packet filter wmi cmd to fw");
4149
4150 return ret;
4151}
4152
4153/**
4154 * wma_config_packet_filter() - configure packet filter in target
4155 * @wma: Pointer to wma handle
4156 * @vdev_id: vdev id
4157 * @rcv_filter_param: Packet filter parameters
4158 * @filter_id: Filter id
4159 * @enable: Flag to add/delete packet filter configuration
4160 *
4161 * Return: 0 for success or error code
4162 */
4163static int wma_config_packet_filter(tp_wma_handle wma,
4164 uint8_t vdev_id, tSirRcvPktFilterCfgType *rcv_filter_param,
4165 uint8_t filter_id, bool enable)
4166{
Govind Singhaa64c242016-03-08 11:31:49 +05304167 int err;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004168
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004169 /* send the command along with data */
Govind Singhaa64c242016-03-08 11:31:49 +05304170 err = wmi_unified_config_packet_filter_cmd(wma->wmi_handle,
4171 vdev_id, (struct rcv_pkt_filter_config *)rcv_filter_param,
4172 filter_id, enable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004173 if (err) {
4174 WMA_LOGE("Failed to send pkt_filter cmd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004175 return -EIO;
4176 }
4177
4178 /* Enable packet filter */
4179 if (enable)
4180 wma_enable_disable_packet_filter(wma, vdev_id, true);
4181
4182 return 0;
4183}
4184
4185/**
4186 * wma_process_receive_filter_set_filter_req() - enable packet filter
4187 * @wma_handle: wma handle
4188 * @rcv_filter_param: filter params
4189 *
4190 * Return: 0 for success or error code
4191 */
4192int wma_process_receive_filter_set_filter_req(tp_wma_handle wma,
4193 tSirRcvPktFilterCfgType *rcv_filter_param)
4194{
4195 int ret = 0;
4196 uint8_t vdev_id;
4197
4198 /* Get the vdev id */
Srinivas Girigowda98530492015-11-20 17:39:24 -08004199 if (!wma_find_vdev_by_bssid(wma,
4200 rcv_filter_param->bssid.bytes, &vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004201 WMA_LOGE("vdev handle is invalid for %pM",
Srinivas Girigowda98530492015-11-20 17:39:24 -08004202 rcv_filter_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004203 return -EINVAL;
4204 }
4205
4206 ret = wma_config_packet_filter(wma, vdev_id, rcv_filter_param,
4207 rcv_filter_param->filterId, true);
4208
4209 return ret;
4210}
4211
4212/**
4213 * wma_process_receive_filter_clear_filter_req() - disable packet filter
4214 * @wma_handle: wma handle
4215 * @rcv_clear_param: filter params
4216 *
4217 * Return: 0 for success or error code
4218 */
4219int wma_process_receive_filter_clear_filter_req(tp_wma_handle wma,
4220 tSirRcvFltPktClearParam *rcv_clear_param)
4221{
4222 int ret = 0;
4223 uint8_t vdev_id;
4224
4225 /* Get the vdev id */
Srinivas Girigowda98530492015-11-20 17:39:24 -08004226 if (!wma_find_vdev_by_bssid(wma,
4227 rcv_clear_param->bssid.bytes, &vdev_id)) {
4228 WMA_LOGE("vdev handle is invalid for %pM",
4229 rcv_clear_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004230 return -EINVAL;
4231 }
4232
4233 ret = wma_config_packet_filter(wma, vdev_id, NULL,
4234 rcv_clear_param->filterId, false);
4235
4236 return ret;
4237}
4238
4239#ifdef FEATURE_WLAN_ESE
4240
4241#define TSM_DELAY_HISTROGRAM_BINS 4
4242/**
4243 * wma_process_tsm_stats_req() - process tsm stats request
4244 * @wma_handler - handle to wma
4245 * @pTsmStatsMsg - TSM stats struct that needs to be populated and
4246 * passed in message.
4247 *
4248 * A parallel function to WMA_ProcessTsmStatsReq for pronto. This
4249 * function fetches stats from data path APIs and post
4250 * WMA_TSM_STATS_RSP msg back to LIM.
4251 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304252 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004253 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304254QDF_STATUS wma_process_tsm_stats_req(tp_wma_handle wma_handler,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004255 void *pTsmStatsMsg)
4256{
4257 uint8_t counter;
4258 uint32_t queue_delay_microsec = 0;
4259 uint32_t tx_delay_microsec = 0;
4260 uint16_t packet_count = 0;
4261 uint16_t packet_loss_count = 0;
4262 tpAniTrafStrmMetrics pTsmMetric = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004263 tpAniGetTsmStatsReq pStats = (tpAniGetTsmStatsReq) pTsmStatsMsg;
4264 tpAniGetTsmStatsRsp pTsmRspParams = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004265 int tid = pStats->tid;
4266 /*
4267 * The number of histrogram bin report by data path api are different
4268 * than required by TSM, hence different (6) size array used
4269 */
4270 uint16_t bin_values[QCA_TX_DELAY_HIST_REPORT_BINS] = { 0, };
4271
Anurag Chouhan6d760662016-02-20 16:05:43 +05304272 ol_txrx_pdev_handle pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004273
4274 if (NULL == pdev) {
4275 WMA_LOGE("%s: Failed to get pdev", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304276 qdf_mem_free(pTsmStatsMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304277 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004278 }
4279
4280 /* get required values from data path APIs */
4281 ol_tx_delay(pdev, &queue_delay_microsec, &tx_delay_microsec, tid);
4282 ol_tx_delay_hist(pdev, bin_values, tid);
4283 ol_tx_packet_count(pdev, &packet_count, &packet_loss_count, tid);
4284
Srinivas Girigowda515a9ef2015-12-11 11:00:48 -08004285 pTsmRspParams = qdf_mem_malloc(sizeof(*pTsmRspParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004286 if (NULL == pTsmRspParams) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304287 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304288 "%s: QDF MEM Alloc Failure", __func__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304289 QDF_ASSERT(0);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304290 qdf_mem_free(pTsmStatsMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304291 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004292 }
4293 pTsmRspParams->staId = pStats->staId;
4294 pTsmRspParams->rc = eSIR_FAILURE;
4295 pTsmRspParams->tsmStatsReq = pStats;
4296 pTsmMetric = &pTsmRspParams->tsmMetrics;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004297 /* populate pTsmMetric */
4298 pTsmMetric->UplinkPktQueueDly = queue_delay_microsec;
4299 /* store only required number of bin values */
4300 for (counter = 0; counter < TSM_DELAY_HISTROGRAM_BINS; counter++) {
4301 pTsmMetric->UplinkPktQueueDlyHist[counter] =
4302 bin_values[counter];
4303 }
4304 pTsmMetric->UplinkPktTxDly = tx_delay_microsec;
4305 pTsmMetric->UplinkPktLoss = packet_loss_count;
4306 pTsmMetric->UplinkPktCount = packet_count;
4307
4308 /*
4309 * No need to populate roaming delay and roaming count as they are
4310 * being populated just before sending IAPP frame out
4311 */
4312 /* post this message to LIM/PE */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004313 wma_send_msg(wma_handler, WMA_TSM_STATS_RSP, (void *)pTsmRspParams, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304314 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004315}
4316
4317#endif /* FEATURE_WLAN_ESE */
4318
4319/**
4320 * wma_add_clear_mcbc_filter() - set mcast filter command to fw
4321 * @wma_handle: wma handle
4322 * @vdev_id: vdev id
4323 * @multicastAddr: mcast address
4324 * @clearList: clear list flag
4325 *
4326 * Return: 0 for success or error code
4327 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304328static QDF_STATUS wma_add_clear_mcbc_filter(tp_wma_handle wma_handle,
4329 uint8_t vdev_id,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304330 struct qdf_mac_addr multicast_addr,
Srinivas Girigowda98530492015-11-20 17:39:24 -08004331 bool clearList)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004332{
Himanshu Agarwal44195412016-03-09 13:03:54 +05304333 return wmi_unified_add_clear_mcbc_filter_cmd(wma_handle->wmi_handle,
4334 vdev_id, multicast_addr, clearList);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004335}
4336
4337/**
Rajeev Kumaref96e152016-04-15 18:10:33 -07004338 * wma_config_enhance_multicast_offload() - config enhance multicast offload
4339 * @wma_handle: wma handle
4340 * @vdev_id: vdev id
4341 * @action: enable or disable enhance multicast offload
4342 *
4343 * Return: none
4344 */
4345static void wma_config_enhance_multicast_offload(tp_wma_handle wma_handle,
4346 uint8_t vdev_id,
4347 uint8_t action)
4348{
4349 int status;
4350 wmi_buf_t buf;
4351 wmi_config_enhanced_mcast_filter_cmd_fixed_param *cmd;
4352
4353 buf = wmi_buf_alloc(wma_handle->wmi_handle, sizeof(*cmd));
4354 if (!buf) {
4355 WMA_LOGE("Failed to allocate buffer to send set key cmd");
4356 return;
4357 }
4358
4359 cmd = (wmi_config_enhanced_mcast_filter_cmd_fixed_param *)
4360 wmi_buf_data(buf);
4361
4362 WMITLV_SET_HDR(&cmd->tlv_header,
4363 WMITLV_TAG_STRUC_wmi_config_enhanced_mcast_filter_fixed_param,
4364 WMITLV_GET_STRUCT_TLVLEN(wmi_config_enhanced_mcast_filter_cmd_fixed_param));
4365
4366 cmd->vdev_id = vdev_id;
4367 cmd->enable = ((0 == action) ? ENHANCED_MCAST_FILTER_DISABLED :
4368 ENHANCED_MCAST_FILTER_ENABLED);
4369
4370 WMA_LOGD("%s: config enhance multicast offload action %d for vdev %d",
4371 __func__, action, vdev_id);
4372
4373 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
4374 sizeof(*cmd), WMI_CONFIG_ENHANCED_MCAST_FILTER_CMDID);
4375 if (status) {
4376 qdf_nbuf_free(buf);
4377 WMA_LOGE("%s:Failed to send WMI_CONFIG_ENHANCED_MCAST_FILTER_CMDID",
4378 __func__);
4379 }
4380
4381 return;
4382}
4383
4384/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004385 * wma_process_mcbc_set_filter_req() - process mcbc set filter request
4386 * @wma_handle: wma handle
4387 * @mcbc_param: mcbc params
4388 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304389 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004390 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304391QDF_STATUS wma_process_mcbc_set_filter_req(tp_wma_handle wma_handle,
Anurag Chouhance0dc992016-02-16 18:18:03 +05304392 tSirRcvFltMcAddrList *mcbc_param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004393{
4394 uint8_t vdev_id = 0;
4395 int i;
4396
4397 if (mcbc_param->ulMulticastAddrCnt <= 0) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004398 WMA_LOGW("Number of multicast addresses is 0");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304399 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004400 }
4401
Srinivas Girigowda98530492015-11-20 17:39:24 -08004402 if (!wma_find_vdev_by_addr(wma_handle,
4403 mcbc_param->self_macaddr.bytes, &vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004404 WMA_LOGE("%s: Failed to find vdev id for %pM", __func__,
Srinivas Girigowda98530492015-11-20 17:39:24 -08004405 mcbc_param->bssid.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304406 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004407 }
Rajeev Kumaref96e152016-04-15 18:10:33 -07004408
4409 /*
4410 * Configure enhance multicast offload feature for filtering out
4411 * multicast IP data packets transmitted using unicast MAC address
4412 */
4413 if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap,
4414 WMI_SERVICE_ENHANCED_MCAST_FILTER)) {
4415 WMA_LOGD("%s: FW supports enhance multicast offload", __func__);
4416 wma_config_enhance_multicast_offload(wma_handle, vdev_id,
4417 mcbc_param->action);
4418 } else {
4419 WMA_LOGD("%s: FW does not support enhance multicast offload",
4420 __func__);
4421 }
4422
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004423 /* set mcbc_param->action to clear MCList and reset
4424 * to configure the MCList in FW
4425 */
4426
4427 for (i = 0; i < mcbc_param->ulMulticastAddrCnt; i++) {
4428 wma_add_clear_mcbc_filter(wma_handle, vdev_id,
4429 mcbc_param->multicastAddr[i],
4430 (mcbc_param->action == 0));
4431 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304432 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004433}
4434
4435#ifdef WLAN_FEATURE_GTK_OFFLOAD
4436#define GTK_OFFLOAD_ENABLE 0
4437#define GTK_OFFLOAD_DISABLE 1
4438
4439/**
4440 * wma_gtk_offload_status_event() - GTK offload status event handler
4441 * @handle: wma handle
4442 * @event: event buffer
4443 * @len: buffer length
4444 *
4445 * Return: 0 for success or error code
4446 */
4447int wma_gtk_offload_status_event(void *handle, uint8_t *event,
4448 uint32_t len)
4449{
4450 tp_wma_handle wma = (tp_wma_handle) handle;
4451 WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param *status;
4452 WMI_GTK_OFFLOAD_STATUS_EVENTID_param_tlvs *param_buf;
4453 tpSirGtkOffloadGetInfoRspParams resp;
4454 cds_msg_t cds_msg;
4455 uint8_t *bssid;
4456
4457 WMA_LOGD("%s Enter", __func__);
4458
4459 param_buf = (WMI_GTK_OFFLOAD_STATUS_EVENTID_param_tlvs *) event;
4460 if (!param_buf) {
4461 WMA_LOGE("param_buf is NULL");
4462 return -EINVAL;
4463 }
4464
4465 status = (WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param *) param_buf->fixed_param;
4466
4467 if (len < sizeof(WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param)) {
4468 WMA_LOGE("Invalid length for GTK status");
4469 return -EINVAL;
4470 }
4471 bssid = wma_find_bssid_by_vdev_id(wma, status->vdev_id);
4472 if (!bssid) {
4473 WMA_LOGE("invalid bssid for vdev id %d", status->vdev_id);
4474 return -ENOENT;
4475 }
4476
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304477 resp = qdf_mem_malloc(sizeof(*resp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004478 if (!resp) {
4479 WMA_LOGE("%s: Failed to alloc response", __func__);
4480 return -ENOMEM;
4481 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304482 qdf_mem_zero(resp, sizeof(*resp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004483 resp->mesgType = eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP;
4484 resp->mesgLen = sizeof(*resp);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304485 resp->ulStatus = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004486 resp->ulTotalRekeyCount = status->refresh_cnt;
4487 /* TODO: Is the total rekey count and GTK rekey count same? */
4488 resp->ulGTKRekeyCount = status->refresh_cnt;
4489
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304490 qdf_mem_copy(&resp->ullKeyReplayCounter, &status->replay_counter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004491 GTK_REPLAY_COUNTER_BYTES);
4492
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304493 qdf_mem_copy(resp->bssid.bytes, bssid, IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004494
4495#ifdef IGTK_OFFLOAD
4496 /* TODO: Is the refresh count same for GTK and IGTK? */
4497 resp->ulIGTKRekeyCount = status->refresh_cnt;
4498#endif /* IGTK_OFFLOAD */
4499
4500 cds_msg.type = eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP;
4501 cds_msg.bodyptr = (void *)resp;
4502 cds_msg.bodyval = 0;
4503
4504 if (cds_mq_post_message(CDS_MQ_ID_SME, (cds_msg_t *) &cds_msg)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304505 != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004506 WMA_LOGE("Failed to post GTK response to SME");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304507 qdf_mem_free(resp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004508 return -EINVAL;
4509 }
4510
4511 WMA_LOGD("GTK: got target status with replay counter "
4512 "%02x%02x%02x%02x%02x%02x%02x%02x. vdev %d "
4513 "Refresh GTK %d times exchanges since last set operation",
4514 status->replay_counter[0],
4515 status->replay_counter[1],
4516 status->replay_counter[2],
4517 status->replay_counter[3],
4518 status->replay_counter[4],
4519 status->replay_counter[5],
4520 status->replay_counter[6],
4521 status->replay_counter[7],
4522 status->vdev_id, status->refresh_cnt);
4523
4524 WMA_LOGD("%s Exit", __func__);
4525
4526 return 0;
4527}
4528
4529/**
4530 * wma_send_gtk_offload_req() - send GTK offload command to fw
4531 * @wma: wma handle
4532 * @vdev_id: vdev id
4533 * @params: GTK offload parameters
4534 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304535 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004536 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304537static QDF_STATUS wma_send_gtk_offload_req(tp_wma_handle wma, uint8_t vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004538 tpSirGtkOffloadParams params)
4539{
Himanshu Agarwal44195412016-03-09 13:03:54 +05304540 struct gtk_offload_params offload_params = {0};
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304541 QDF_STATUS status = QDF_STATUS_SUCCESS;
Himanshu Agarwal44195412016-03-09 13:03:54 +05304542 bool enable_offload;
4543 uint32_t gtk_offload_opcode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004544
4545 WMA_LOGD("%s Enter", __func__);
4546
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004547 /* Request target to enable GTK offload */
4548 if (params->ulFlags == GTK_OFFLOAD_ENABLE) {
Himanshu Agarwal44195412016-03-09 13:03:54 +05304549 gtk_offload_opcode = GTK_OFFLOAD_ENABLE_OPCODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004550 wma->wow.gtk_err_enable[vdev_id] = true;
4551
4552 /* Copy the keys and replay counter */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304553 qdf_mem_copy(offload_params.aKCK, params->aKCK,
4554 GTK_OFFLOAD_KCK_BYTES);
4555 qdf_mem_copy(offload_params.aKEK, params->aKEK,
4556 GTK_OFFLOAD_KEK_BYTES);
4557 qdf_mem_copy(&offload_params.ullKeyReplayCounter,
4558 &params->ullKeyReplayCounter, GTK_REPLAY_COUNTER_BYTES);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004559 } else {
4560 wma->wow.gtk_err_enable[vdev_id] = false;
Himanshu Agarwal44195412016-03-09 13:03:54 +05304561 gtk_offload_opcode = GTK_OFFLOAD_DISABLE_OPCODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004562 }
4563
Himanshu Agarwal44195412016-03-09 13:03:54 +05304564 enable_offload = params->ulFlags;
4565
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004566 /* send the wmi command */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304567 status = wmi_unified_send_gtk_offload_cmd(wma->wmi_handle,
4568 vdev_id, &offload_params,
4569 enable_offload,
4570 gtk_offload_opcode);
4571 if (QDF_IS_STATUS_ERROR(status))
4572 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004573
Himanshu Agarwal44195412016-03-09 13:03:54 +05304574 WMA_LOGD("VDEVID: %d, GTK_FLAGS: x%x", vdev_id, gtk_offload_opcode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004575out:
4576 WMA_LOGD("%s Exit", __func__);
4577 return status;
4578}
4579
4580/**
4581 * wma_process_gtk_offload_req() - process GTK offload req from umac
4582 * @handle: wma handle
4583 * @params: GTK offload params
4584 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304585 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004586 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304587QDF_STATUS wma_process_gtk_offload_req(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004588 tpSirGtkOffloadParams params)
4589{
4590 uint8_t vdev_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304591 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004592
4593 WMA_LOGD("%s Enter", __func__);
4594
4595 /* Get the vdev id */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08004596 if (!wma_find_vdev_by_bssid(wma, params->bssid.bytes, &vdev_id)) {
4597 WMA_LOGE("vdev handle is invalid for %pM", params->bssid.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304598 status = QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004599 goto out;
4600 }
4601
4602 /* Validate vdev id */
4603 if (vdev_id >= wma->max_bssid) {
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08004604 WMA_LOGE("invalid vdev_id %d for %pM", vdev_id,
4605 params->bssid.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304606 status = QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004607 goto out;
4608 }
4609
4610 if ((params->ulFlags == GTK_OFFLOAD_ENABLE) &&
4611 (wma->wow.gtk_err_enable[vdev_id] == true)) {
4612 WMA_LOGE("%s GTK Offload already enabled. Disable it first "
4613 "vdev_id %d", __func__, vdev_id);
4614 params->ulFlags = GTK_OFFLOAD_DISABLE;
4615 status = wma_send_gtk_offload_req(wma, vdev_id, params);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304616 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004617 WMA_LOGE("%s Failed to disable GTK Offload", __func__);
4618 goto out;
4619 }
4620 WMA_LOGD("%s Enable GTK Offload again with updated inputs",
4621 __func__);
4622 params->ulFlags = GTK_OFFLOAD_ENABLE;
4623 }
4624 status = wma_send_gtk_offload_req(wma, vdev_id, params);
4625out:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304626 qdf_mem_free(params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004627 WMA_LOGD("%s Exit", __func__);
4628 return status;
4629}
4630
4631/**
4632 * wma_process_gtk_offload_getinfo_req() - send GTK offload cmd to fw
4633 * @wma: wma handle
4634 * @params: GTK offload params
4635 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304636 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004637 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304638QDF_STATUS wma_process_gtk_offload_getinfo_req(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004639 tpSirGtkOffloadGetInfoRspParams params)
4640{
4641 uint8_t vdev_id;
Himanshu Agarwal44195412016-03-09 13:03:54 +05304642 uint64_t offload_req_opcode;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304643 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004644
4645 WMA_LOGD("%s Enter", __func__);
4646
4647 /* Get the vdev id */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08004648 if (!wma_find_vdev_by_bssid(wma, params->bssid.bytes, &vdev_id)) {
4649 WMA_LOGE("vdev handle is invalid for %pM", params->bssid.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304650 status = QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004651 goto out;
4652 }
4653
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004654 /* Request for GTK offload status */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304655 offload_req_opcode = GTK_OFFLOAD_REQUEST_STATUS_OPCODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004656
4657 /* send the wmi command */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304658 status = wmi_unified_process_gtk_offload_getinfo_cmd(wma->wmi_handle,
4659 vdev_id, offload_req_opcode);
4660
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004661out:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304662 qdf_mem_free(params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004663 WMA_LOGD("%s Exit", __func__);
4664 return status;
4665}
4666#endif /* WLAN_FEATURE_GTK_OFFLOAD */
4667
4668/**
4669 * wma_enable_arp_ns_offload() - enable ARP NS offload
4670 * @wma: wma handle
4671 * @tpSirHostOffloadReq: offload request
Govind Singhaa64c242016-03-08 11:31:49 +05304672 * @arp_only: flag
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004673 *
4674 * To configure ARP NS off load data to firmware
4675 * when target goes to wow mode.
4676 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304677 * Return: QDF Status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004678 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304679QDF_STATUS wma_enable_arp_ns_offload(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004680 tpSirHostOffloadReq
Govind Singhaa64c242016-03-08 11:31:49 +05304681 pHostOffloadParams, bool arp_only)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004682{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004683 int32_t res;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004684 uint8_t vdev_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004685
4686 /* Get the vdev id */
Srinivas Girigowdab084b552015-11-24 12:39:12 -08004687 if (!wma_find_vdev_by_bssid(wma, pHostOffloadParams->bssid.bytes,
4688 &vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004689 WMA_LOGE("vdev handle is invalid for %pM",
Srinivas Girigowdab084b552015-11-24 12:39:12 -08004690 pHostOffloadParams->bssid.bytes);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304691 qdf_mem_free(pHostOffloadParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304692 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004693 }
4694
4695 if (!wma->interfaces[vdev_id].vdev_up) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004696 WMA_LOGE("vdev %d is not up skipping arp/ns offload", vdev_id);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304697 qdf_mem_free(pHostOffloadParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304698 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004699 }
4700
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004701
Govind Singhaa64c242016-03-08 11:31:49 +05304702 res = wmi_unified_enable_arp_ns_offload_cmd(wma->wmi_handle,
4703 (struct host_offload_req_param *)pHostOffloadParams,
4704 arp_only,
4705 vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004706 if (res) {
4707 WMA_LOGE("Failed to enable ARP NDP/NSffload");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304708 qdf_mem_free(pHostOffloadParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304709 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004710 }
4711
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304712 qdf_mem_free(pHostOffloadParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304713 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004714}
4715
4716/**
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08004717 * wma_process_cesium_enable_ind() - enables cesium functionality in target
4718 * @wma: wma handle
4719 *
4720 * Return: QDF status
4721 */
4722QDF_STATUS wma_process_cesium_enable_ind(tp_wma_handle wma)
4723{
4724 QDF_STATUS ret;
4725 int32_t vdev_id;
4726
4727 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
4728 if (vdev_id < 0) {
4729 WMA_LOGE("%s: IBSS vdev does not exist could not enable cesium",
4730 __func__);
4731 return QDF_STATUS_E_FAILURE;
4732 }
4733
4734 /* Send enable cesium command to target */
4735 WMA_LOGE("Enable cesium in target for vdevId %d ", vdev_id);
4736 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
4737 WMI_VDEV_PARAM_ENABLE_RMC, 1);
4738 if (ret) {
4739 WMA_LOGE("Enable cesium failed for vdevId %d", vdev_id);
4740 return QDF_STATUS_E_FAILURE;
4741 }
4742 return QDF_STATUS_SUCCESS;
4743}
4744
4745/**
4746 * wma_process_get_peer_info_req() - sends get peer info cmd to target
4747 * @wma: wma handle
4748 * @preq: get peer info request
4749 *
4750 * Return: QDF status
4751 */
4752QDF_STATUS wma_process_get_peer_info_req
4753 (tp_wma_handle wma, tSirIbssGetPeerInfoReqParams *pReq)
4754{
4755 int32_t ret;
4756 uint8_t *p;
4757 uint16_t len;
4758 wmi_buf_t buf;
4759 int32_t vdev_id;
4760 ol_txrx_pdev_handle pdev;
4761 struct ol_txrx_peer_t *peer;
4762 uint8_t peer_mac[IEEE80211_ADDR_LEN];
4763 wmi_peer_info_req_cmd_fixed_param *p_get_peer_info_cmd;
4764 uint8_t bcast_mac[IEEE80211_ADDR_LEN] = { 0xff, 0xff, 0xff,
4765 0xff, 0xff, 0xff };
4766
4767 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
4768 if (vdev_id < 0) {
4769 WMA_LOGE("%s: IBSS vdev does not exist could not get peer info",
4770 __func__);
4771 return QDF_STATUS_E_FAILURE;
4772 }
4773
4774 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
4775 if (NULL == pdev) {
4776 WMA_LOGE("%s: Failed to get pdev context", __func__);
4777 return QDF_STATUS_E_FAILURE;
4778 }
4779
4780 if (0xFF == pReq->staIdx) {
4781 /*get info for all peers */
4782 qdf_mem_copy(peer_mac, bcast_mac, IEEE80211_ADDR_LEN);
4783 } else {
4784 /*get info for a single peer */
4785 peer = ol_txrx_peer_find_by_local_id(pdev, pReq->staIdx);
4786 if (!peer) {
4787 WMA_LOGE("%s: Failed to get peer handle using peer id %d",
4788 __func__, pReq->staIdx);
4789 return QDF_STATUS_E_FAILURE;
4790 }
4791 WMA_LOGE("%s: staIdx %d peer mac: 0x%2x:0x%2x:0x%2x:0x%2x:0x%2x:0x%2x",
4792 __func__, pReq->staIdx, peer->mac_addr.raw[0],
4793 peer->mac_addr.raw[1], peer->mac_addr.raw[2],
4794 peer->mac_addr.raw[3], peer->mac_addr.raw[4],
4795 peer->mac_addr.raw[5]);
4796 qdf_mem_copy(peer_mac, peer->mac_addr.raw, IEEE80211_ADDR_LEN);
4797 }
4798
4799 len = sizeof(wmi_peer_info_req_cmd_fixed_param);
4800 buf = wmi_buf_alloc(wma->wmi_handle, len);
4801 if (!buf) {
4802 WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__);
4803 return QDF_STATUS_E_FAILURE;
4804 }
4805
4806 p = (uint8_t *) wmi_buf_data(buf);
4807 qdf_mem_zero(p, len);
4808 p_get_peer_info_cmd = (wmi_peer_info_req_cmd_fixed_param *) p;
4809
4810 WMITLV_SET_HDR(&p_get_peer_info_cmd->tlv_header,
4811 WMITLV_TAG_STRUC_wmi_peer_info_req_cmd_fixed_param,
4812 WMITLV_GET_STRUCT_TLVLEN
4813 (wmi_peer_info_req_cmd_fixed_param));
4814
4815 p_get_peer_info_cmd->vdev_id = vdev_id;
4816 WMI_CHAR_ARRAY_TO_MAC_ADDR(peer_mac,
4817 &p_get_peer_info_cmd->peer_mac_address);
4818
4819 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
4820 WMI_PEER_INFO_REQ_CMDID);
4821
4822 WMA_LOGE("IBSS get peer info cmd sent len: %d, vdev %d"
4823 " command id: %d, status: %d", len,
4824 p_get_peer_info_cmd->vdev_id, WMI_PEER_INFO_REQ_CMDID, ret);
4825
4826 return QDF_STATUS_SUCCESS;
4827}
4828
4829/**
4830 * wma_process_tx_fail_monitor_ind() - sends tx fail monitor cmd to target
4831 * @wma: wma handle
4832 * @pReq: tx fail monitor command params
4833 *
4834 * Return: QDF status
4835 */
4836QDF_STATUS wma_process_tx_fail_monitor_ind
4837 (tp_wma_handle wma, tAniTXFailMonitorInd *pReq)
4838{
4839 QDF_STATUS ret;
4840 int32_t vdev_id;
4841
4842 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
4843 if (vdev_id < 0) {
4844 WMA_LOGE("%s: IBSS vdev does not exist could not send fast tx fail"
4845 " monitor indication message to target", __func__);
4846 return QDF_STATUS_E_FAILURE;
4847 }
4848
4849 /* Send enable cesium command to target */
4850 WMA_LOGE("send fast tx fail monitor ind cmd target for vdevId %d val %d",
4851 vdev_id, pReq->tx_fail_count);
4852
4853 if (0 == pReq->tx_fail_count) {
4854 wma->hddTxFailCb = NULL;
4855 } else {
4856 wma->hddTxFailCb = pReq->txFailIndCallback;
4857 }
4858 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
4859 WMI_VDEV_PARAM_SET_IBSS_TX_FAIL_CNT_THR,
4860 pReq->tx_fail_count);
4861 if (ret) {
4862 WMA_LOGE("tx fail monitor failed for vdevId %d", vdev_id);
4863 return QDF_STATUS_E_FAILURE;
4864 }
4865
4866 return QDF_STATUS_SUCCESS;
4867}
4868
4869/**
4870 * wma_process_rmc_enable_ind() - enables RMC functionality in target
4871 * @wma: wma handle
4872 *
4873 * Return: QDF status
4874 */
4875QDF_STATUS wma_process_rmc_enable_ind(tp_wma_handle wma)
4876{
4877 int ret;
4878 uint8_t *p;
4879 uint16_t len;
4880 wmi_buf_t buf;
4881 int32_t vdev_id;
4882 wmi_rmc_set_mode_cmd_fixed_param *p_rmc_enable_cmd;
4883
4884 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
4885 if (vdev_id < 0) {
4886 WMA_LOGE("%s: IBSS vdev does not exist could not enable RMC",
4887 __func__);
4888 return QDF_STATUS_E_FAILURE;
4889 }
4890
4891 len = sizeof(wmi_rmc_set_mode_cmd_fixed_param);
4892 buf = wmi_buf_alloc(wma->wmi_handle, len);
4893 if (!buf) {
4894 WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__);
4895 return QDF_STATUS_E_FAILURE;
4896 }
4897
4898 p = (uint8_t *) wmi_buf_data(buf);
4899 qdf_mem_zero(p, len);
4900 p_rmc_enable_cmd = (wmi_rmc_set_mode_cmd_fixed_param *) p;
4901
4902 WMITLV_SET_HDR(&p_rmc_enable_cmd->tlv_header,
4903 WMITLV_TAG_STRUC_wmi_rmc_set_mode_cmd_fixed_param,
4904 WMITLV_GET_STRUCT_TLVLEN
4905 (wmi_rmc_set_mode_cmd_fixed_param));
4906
4907 p_rmc_enable_cmd->vdev_id = vdev_id;
4908 p_rmc_enable_cmd->enable_rmc = WMI_RMC_MODE_ENABLED;
4909
4910 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
4911 WMI_RMC_SET_MODE_CMDID);
4912
4913 WMA_LOGE("Enable RMC cmd sent len: %d, vdev %d" " command id: %d,"
4914 " status: %d", len, p_rmc_enable_cmd->vdev_id,
4915 WMI_RMC_SET_MODE_CMDID, ret);
4916
4917 return QDF_STATUS_SUCCESS;
4918}
4919
4920/**
4921 * wma_process_rmc_disable_ind() - disables rmc functionality in target
4922 * @wma: wma handle
4923 *
4924 * Return: QDF status
4925 */
4926QDF_STATUS wma_process_rmc_disable_ind(tp_wma_handle wma)
4927{
4928 int ret;
4929 uint8_t *p;
4930 uint16_t len;
4931 wmi_buf_t buf;
4932 int32_t vdev_id;
4933 wmi_rmc_set_mode_cmd_fixed_param *p_rmc_disable_cmd;
4934
4935 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
4936 if (vdev_id < 0) {
4937 WMA_LOGE("%s: IBSS vdev does not exist could not disable RMC",
4938 __func__);
4939 return QDF_STATUS_E_FAILURE;
4940 }
4941
4942 len = sizeof(wmi_rmc_set_mode_cmd_fixed_param);
4943 buf = wmi_buf_alloc(wma->wmi_handle, len);
4944 if (!buf) {
4945 WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__);
4946 return QDF_STATUS_E_FAILURE;
4947 }
4948
4949 p = (uint8_t *) wmi_buf_data(buf);
4950 qdf_mem_zero(p, len);
4951 p_rmc_disable_cmd = (wmi_rmc_set_mode_cmd_fixed_param *) p;
4952
4953 WMITLV_SET_HDR(&p_rmc_disable_cmd->tlv_header,
4954 WMITLV_TAG_STRUC_wmi_rmc_set_mode_cmd_fixed_param,
4955 WMITLV_GET_STRUCT_TLVLEN
4956 (wmi_rmc_set_mode_cmd_fixed_param));
4957
4958 p_rmc_disable_cmd->vdev_id = vdev_id;
4959 p_rmc_disable_cmd->enable_rmc = WMI_RMC_MODE_DISABLED;
4960
4961 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
4962 WMI_RMC_SET_MODE_CMDID);
4963
4964 WMA_LOGE("Disable RMC cmd sent len: %d, vdev %d" " command id: %d,"
4965 " status: %d", len, p_rmc_disable_cmd->vdev_id,
4966 WMI_RMC_SET_MODE_CMDID, ret);
4967
4968 return QDF_STATUS_SUCCESS;
4969}
4970
4971/**
4972 * wma_process_rmc_action_period_ind() - sends RMC action period to target
4973 * @wma: wma handle
4974 *
4975 * Return: QDF status
4976 */
4977QDF_STATUS wma_process_rmc_action_period_ind(tp_wma_handle wma)
4978{
4979 int ret;
4980 uint8_t *p;
4981 uint16_t len;
4982 uint32_t val;
4983 wmi_buf_t buf;
4984 int32_t vdev_id;
4985 wmi_rmc_set_action_period_cmd_fixed_param *p_rmc_cmd;
4986 struct sAniSirGlobal *mac = cds_get_context(QDF_MODULE_ID_PE);
4987
4988 if (NULL == mac) {
4989 WMA_LOGE("%s: MAC mac does not exist", __func__);
4990 return QDF_STATUS_E_FAILURE;
4991 }
4992
4993 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
4994 if (vdev_id < 0) {
4995 WMA_LOGE("%s: IBSS vdev does not exist could not send"
4996 " RMC action period to target", __func__);
4997 return QDF_STATUS_E_FAILURE;
4998 }
4999
5000 len = sizeof(wmi_rmc_set_action_period_cmd_fixed_param);
5001 buf = wmi_buf_alloc(wma->wmi_handle, len);
5002 if (!buf) {
5003 WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__);
5004 return QDF_STATUS_E_FAILURE;
5005 }
5006
5007 p = (uint8_t *) wmi_buf_data(buf);
5008 qdf_mem_zero(p, len);
5009 p_rmc_cmd = (wmi_rmc_set_action_period_cmd_fixed_param *) p;
5010
5011 WMITLV_SET_HDR(&p_rmc_cmd->tlv_header,
5012 WMITLV_TAG_STRUC_wmi_rmc_set_action_period_cmd_fixed_param,
5013 WMITLV_GET_STRUCT_TLVLEN
5014 (wmi_rmc_set_action_period_cmd_fixed_param));
5015
5016 if (wlan_cfg_get_int(mac, WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY, &val)
5017 != eSIR_SUCCESS) {
5018 WMA_LOGE("Failed to get value for RMC action period using default");
5019 val = WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_STADEF;
5020 }
5021
5022 p_rmc_cmd->vdev_id = vdev_id;
5023 p_rmc_cmd->periodicity_msec = val;
5024
5025 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
5026 WMI_RMC_SET_ACTION_PERIOD_CMDID);
5027
5028 WMA_LOGE("RMC action period %d cmd sent len: %d, vdev %d"
5029 " command id: %d, status: %d", p_rmc_cmd->periodicity_msec,
5030 len, p_rmc_cmd->vdev_id, WMI_RMC_SET_ACTION_PERIOD_CMDID, ret);
5031
5032 return QDF_STATUS_SUCCESS;
5033}
5034
5035/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005036 * wma_process_add_periodic_tx_ptrn_ind - add periodic tx ptrn
5037 * @handle: wma handle
5038 * @pAddPeriodicTxPtrnParams: tx ptrn params
5039 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305040 * Retrun: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005041 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305042QDF_STATUS wma_process_add_periodic_tx_ptrn_ind(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005043 tSirAddPeriodicTxPtrn *
5044 pAddPeriodicTxPtrnParams)
5045{
5046 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Himanshu Agarwal44195412016-03-09 13:03:54 +05305047 struct periodic_tx_pattern params;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005048 uint8_t vdev_id;
Himanshu Agarwal44195412016-03-09 13:03:54 +05305049
5050 qdf_mem_set(&params, sizeof(struct periodic_tx_pattern), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005051
5052 if (!wma_handle || !wma_handle->wmi_handle) {
5053 WMA_LOGE("%s: WMA is closed, can not issue fw add pattern cmd",
5054 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305055 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005056 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005057
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005058 if (!wma_find_vdev_by_addr(wma_handle,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005059 pAddPeriodicTxPtrnParams->mac_address.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005060 &vdev_id)) {
5061 WMA_LOGE("%s: Failed to find vdev id for %pM", __func__,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005062 pAddPeriodicTxPtrnParams->mac_address.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305063 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005064 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005065
Himanshu Agarwal44195412016-03-09 13:03:54 +05305066 params.ucPtrnId = pAddPeriodicTxPtrnParams->ucPtrnId;
5067 params.ucPtrnSize = pAddPeriodicTxPtrnParams->ucPtrnSize;
5068 params.usPtrnIntervalMs = pAddPeriodicTxPtrnParams->usPtrnIntervalMs;
5069 qdf_mem_copy(&params.mac_address,
5070 &pAddPeriodicTxPtrnParams->mac_address,
5071 sizeof(struct qdf_mac_addr));
5072 qdf_mem_copy(params.ucPattern, pAddPeriodicTxPtrnParams->ucPattern,
5073 params.ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005074
Himanshu Agarwal44195412016-03-09 13:03:54 +05305075 return wmi_unified_process_add_periodic_tx_ptrn_cmd(
5076 wma_handle->wmi_handle, &params, vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005077}
5078
5079/**
5080 * wma_process_del_periodic_tx_ptrn_ind - del periodic tx ptrn
5081 * @handle: wma handle
5082 * @pDelPeriodicTxPtrnParams: tx ptrn params
5083 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305084 * Retrun: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005085 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305086QDF_STATUS wma_process_del_periodic_tx_ptrn_ind(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005087 tSirDelPeriodicTxPtrn *
5088 pDelPeriodicTxPtrnParams)
5089{
5090 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005091 uint8_t vdev_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005092
5093 if (!wma_handle || !wma_handle->wmi_handle) {
5094 WMA_LOGE("%s: WMA is closed, can not issue Del Pattern cmd",
5095 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305096 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005097 }
Himanshu Agarwal44195412016-03-09 13:03:54 +05305098
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005099 if (!wma_find_vdev_by_addr(wma_handle,
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08005100 pDelPeriodicTxPtrnParams->mac_address.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005101 &vdev_id)) {
5102 WMA_LOGE("%s: Failed to find vdev id for %pM", __func__,
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08005103 pDelPeriodicTxPtrnParams->mac_address.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305104 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005105 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005106
Himanshu Agarwal44195412016-03-09 13:03:54 +05305107 return wmi_unified_process_del_periodic_tx_ptrn_cmd(
5108 wma_handle->wmi_handle, vdev_id,
5109 pDelPeriodicTxPtrnParams->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005110}
5111
5112#ifdef WLAN_FEATURE_STATS_EXT
5113/**
5114 * wma_stats_ext_req() - request ext stats from fw
5115 * @wma_ptr: wma handle
5116 * @preq: stats ext params
5117 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305118 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005119 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305120QDF_STATUS wma_stats_ext_req(void *wma_ptr, tpStatsExtRequest preq)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005121{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005122 tp_wma_handle wma = (tp_wma_handle) wma_ptr;
Himanshu Agarwal44195412016-03-09 13:03:54 +05305123 struct stats_ext_params params = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005124
Himanshu Agarwal44195412016-03-09 13:03:54 +05305125 if (!wma) {
5126 WMA_LOGE("%s: wma handle is NULL", __func__);
5127 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005128 }
5129
Himanshu Agarwal44195412016-03-09 13:03:54 +05305130 params.vdev_id = preq->vdev_id;
5131 params.request_data_len = preq->request_data_len;
5132 qdf_mem_copy(params.request_data, preq->request_data,
5133 params.request_data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005134
Himanshu Agarwal44195412016-03-09 13:03:54 +05305135 return wmi_unified_stats_ext_req_cmd(wma->wmi_handle,
5136 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005137}
5138
5139#endif /* WLAN_FEATURE_STATS_EXT */
5140
5141#ifdef WLAN_FEATURE_EXTWOW_SUPPORT
5142/**
5143 * wma_send_status_of_ext_wow() - send ext wow status to SME
5144 * @wma: wma handle
5145 * @status: status
5146 *
5147 * Return: none
5148 */
5149static void wma_send_status_of_ext_wow(tp_wma_handle wma, bool status)
5150{
5151 tSirReadyToExtWoWInd *ready_to_extwow;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305152 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005153 cds_msg_t cds_msg;
5154 uint8_t len;
5155
5156 WMA_LOGD("Posting ready to suspend indication to umac");
5157
5158 len = sizeof(tSirReadyToExtWoWInd);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305159 ready_to_extwow = (tSirReadyToExtWoWInd *) qdf_mem_malloc(len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005160
5161 if (NULL == ready_to_extwow) {
5162 WMA_LOGE("%s: Memory allocation failure", __func__);
5163 return;
5164 }
5165
5166 ready_to_extwow->mesgType = eWNI_SME_READY_TO_EXTWOW_IND;
5167 ready_to_extwow->mesgLen = len;
5168 ready_to_extwow->status = status;
5169
5170 cds_msg.type = eWNI_SME_READY_TO_EXTWOW_IND;
5171 cds_msg.bodyptr = (void *)ready_to_extwow;
5172 cds_msg.bodyval = 0;
5173
5174 vstatus = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305175 if (vstatus != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005176 WMA_LOGE("Failed to post ready to suspend");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305177 qdf_mem_free(ready_to_extwow);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005178 }
5179}
5180
5181/**
5182 * wma_enable_ext_wow() - enable ext wow in fw
5183 * @wma: wma handle
5184 * @params: ext wow params
5185 *
5186 * Return:0 for success or error code
5187 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05305188QDF_STATUS wma_enable_ext_wow(tp_wma_handle wma, tpSirExtWoWParams params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005189{
Himanshu Agarwal44195412016-03-09 13:03:54 +05305190 struct ext_wow_params wow_params = {0};
5191 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005192
Himanshu Agarwal44195412016-03-09 13:03:54 +05305193 if (!wma) {
5194 WMA_LOGE("%s: wma handle is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305195 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005196 }
5197
Himanshu Agarwal44195412016-03-09 13:03:54 +05305198 wow_params.vdev_id = params->vdev_id;
5199 wow_params.type = (enum wmi_ext_wow_type) params->type;
5200 wow_params.wakeup_pin_num = params->wakeup_pin_num;
5201
5202 status = wmi_unified_enable_ext_wow_cmd(wma->wmi_handle,
5203 &wow_params);
5204 if (QDF_IS_STATUS_ERROR(status))
5205 return status;
5206
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005207 wma_send_status_of_ext_wow(wma, true);
Himanshu Agarwal44195412016-03-09 13:03:54 +05305208 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005209
5210}
5211
5212/**
5213 * wma_set_app_type1_params_in_fw() - set app type1 params in fw
5214 * @wma: wma handle
5215 * @appType1Params: app type1 params
5216 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305217 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005218 */
5219int wma_set_app_type1_params_in_fw(tp_wma_handle wma,
5220 tpSirAppType1Params appType1Params)
5221{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005222 int ret;
5223
Govind Singhaa64c242016-03-08 11:31:49 +05305224 ret = wmi_unified_app_type1_params_in_fw_cmd(wma->wmi_handle,
5225 (struct app_type1_params *)appType1Params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005226 if (ret) {
5227 WMA_LOGE("%s: Failed to set APP TYPE1 PARAMS", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305228 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005229 }
5230
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305231 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005232}
5233
5234/**
5235 * wma_set_app_type2_params_in_fw() - set app type2 params in fw
5236 * @wma: wma handle
5237 * @appType2Params: app type2 params
5238 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305239 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005240 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05305241QDF_STATUS wma_set_app_type2_params_in_fw(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005242 tpSirAppType2Params appType2Params)
5243{
Himanshu Agarwal44195412016-03-09 13:03:54 +05305244 struct app_type2_params params = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005245
Himanshu Agarwal44195412016-03-09 13:03:54 +05305246 if (!wma) {
5247 WMA_LOGE("%s: wma handle is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305248 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005249 }
5250
Himanshu Agarwal44195412016-03-09 13:03:54 +05305251 params.vdev_id = appType2Params->vdev_id;
5252 params.rc4_key_len = appType2Params->rc4_key_len;
5253 qdf_mem_copy(params.rc4_key, appType2Params->rc4_key, 16);
5254 params.ip_id = appType2Params->ip_id;
5255 params.ip_device_ip = appType2Params->ip_device_ip;
5256 params.ip_server_ip = appType2Params->ip_server_ip;
5257 params.tcp_src_port = appType2Params->tcp_src_port;
5258 params.tcp_dst_port = appType2Params->tcp_dst_port;
5259 params.tcp_seq = appType2Params->tcp_seq;
5260 params.tcp_ack_seq = appType2Params->tcp_ack_seq;
5261 params.keepalive_init = appType2Params->keepalive_init;
5262 params.keepalive_min = appType2Params->keepalive_min;
5263 params.keepalive_max = appType2Params->keepalive_max;
5264 params.keepalive_inc = appType2Params->keepalive_inc;
5265 params.tcp_tx_timeout_val = appType2Params->tcp_tx_timeout_val;
5266 params.tcp_rx_timeout_val = appType2Params->tcp_rx_timeout_val;
5267 qdf_mem_copy(&params.gateway_mac, &appType2Params->gateway_mac,
5268 sizeof(struct qdf_mac_addr));
5269
5270 return wmi_unified_set_app_type2_params_in_fw_cmd(wma->wmi_handle,
5271 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005272
5273}
5274#endif /* WLAN_FEATURE_EXTWOW_SUPPORT */
5275
5276#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
5277/**
5278 * wma_auto_shutdown_event_handler() - process auto shutdown timer trigger
5279 * @handle: wma handle
5280 * @event: event buffer
5281 * @len: buffer length
5282 *
5283 * Return: 0 for success or error code
5284 */
5285int wma_auto_shutdown_event_handler(void *handle, uint8_t *event,
5286 uint32_t len)
5287{
5288 wmi_host_auto_shutdown_event_fixed_param *wmi_auto_sh_evt;
5289 WMI_HOST_AUTO_SHUTDOWN_EVENTID_param_tlvs *param_buf =
5290 (WMI_HOST_AUTO_SHUTDOWN_EVENTID_param_tlvs *)
5291 event;
5292
5293 if (!param_buf || !param_buf->fixed_param) {
5294 WMA_LOGE("%s:%d: Invalid Auto shutdown timer evt", __func__,
5295 __LINE__);
5296 return -EINVAL;
5297 }
5298
5299 wmi_auto_sh_evt = param_buf->fixed_param;
5300
5301 if (wmi_auto_sh_evt->shutdown_reason
5302 != WMI_HOST_AUTO_SHUTDOWN_REASON_TIMER_EXPIRY) {
5303 WMA_LOGE("%s:%d: Invalid Auto shutdown timer evt", __func__,
5304 __LINE__);
5305 return -EINVAL;
5306 }
5307
5308 WMA_LOGD("%s:%d: Auto Shutdown Evt: %d", __func__, __LINE__,
5309 wmi_auto_sh_evt->shutdown_reason);
5310 return wma_post_auto_shutdown_msg();
5311}
5312
5313/**
5314 * wma_set_auto_shutdown_timer_req() - sets auto shutdown timer in firmware
5315 * @wma: wma handle
5316 * @auto_sh_cmd: auto shutdown timer value
5317 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305318 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005319 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305320QDF_STATUS wma_set_auto_shutdown_timer_req(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005321 tSirAutoShutdownCmdParams *
5322 auto_sh_cmd)
5323{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005324 if (auto_sh_cmd == NULL) {
5325 WMA_LOGE("%s : Invalid Autoshutdown cfg cmd", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305326 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005327 }
5328
Himanshu Agarwal44195412016-03-09 13:03:54 +05305329 return wmi_unified_set_auto_shutdown_timer_cmd(wma_handle->wmi_handle,
5330 auto_sh_cmd->timer_val);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005331}
5332#endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
5333
5334#ifdef WLAN_FEATURE_NAN
5335/**
5336 * wma_nan_req() - to send nan request to target
5337 * @wma: wma_handle
5338 * @nan_req: request data which will be non-null
5339 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305340 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005341 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305342QDF_STATUS wma_nan_req(void *wma_ptr, tpNanRequest nan_req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005343{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005344 tp_wma_handle wma_handle = (tp_wma_handle) wma_ptr;
Himanshu Agarwal44195412016-03-09 13:03:54 +05305345 struct nan_req_params params = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005346
Himanshu Agarwal44195412016-03-09 13:03:54 +05305347 if (!wma_handle) {
5348 WMA_LOGE("%s: wma handle is NULL", __func__);
5349 return QDF_STATUS_E_FAILURE;
5350 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005351 if (!nan_req) {
5352 WMA_LOGE("%s:nan req is not valid", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305353 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005354 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005355
Himanshu Agarwal44195412016-03-09 13:03:54 +05305356 params.request_data_len = nan_req->request_data_len;
5357 qdf_mem_copy(params.request_data, nan_req->request_data,
5358 params.request_data_len);
5359
5360 return wmi_unified_nan_req_cmd(wma_handle->wmi_handle,
5361 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005362}
5363#endif /* WLAN_FEATURE_NAN */
5364
5365#ifdef DHCP_SERVER_OFFLOAD
5366/**
5367 * wma_process_dhcpserver_offload() - enable DHCP server offload
5368 * @wma_handle: wma handle
5369 * @pDhcpSrvOffloadInfo: DHCP server offload info
5370 *
5371 * Return: 0 for success or error code
5372 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05305373QDF_STATUS wma_process_dhcpserver_offload(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005374 tSirDhcpSrvOffloadInfo *
5375 pDhcpSrvOffloadInfo)
5376{
Himanshu Agarwal44195412016-03-09 13:03:54 +05305377 struct dhcp_offload_info_params params = {0};
5378 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005379
Himanshu Agarwal44195412016-03-09 13:03:54 +05305380 if (!wma_handle) {
5381 WMA_LOGE("%s: wma handle is NULL", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005382 return -EIO;
5383 }
Himanshu Agarwal44195412016-03-09 13:03:54 +05305384
5385 params.vdev_id = pDhcpSrvOffloadInfo->vdev_id;
5386 params.dhcpSrvOffloadEnabled =
5387 pDhcpSrvOffloadInfo->dhcpSrvOffloadEnabled;
5388 params.dhcpClientNum = pDhcpSrvOffloadInfo->dhcpClientNum;
5389 params.dhcpSrvIP = pDhcpSrvOffloadInfo->;
5390
5391 status = wmi_unified_process_dhcpserver_offload_cmd(
5392 wma_handle->wmi_handle, &params);
5393 if (QDF_IS_STATUS_ERROR(status))
5394 return status;
5395
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005396 WMA_LOGD("Set dhcp server offload to vdevId %d",
5397 pDhcpSrvOffloadInfo->vdev_id);
Himanshu Agarwal44195412016-03-09 13:03:54 +05305398 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005399}
5400#endif /* DHCP_SERVER_OFFLOAD */
5401
5402#ifdef WLAN_FEATURE_GPIO_LED_FLASHING
5403/**
5404 * wma_set_led_flashing() - set led flashing in fw
5405 * @wma_handle: wma handle
5406 * @flashing: flashing request
5407 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305408 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005409 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305410QDF_STATUS wma_set_led_flashing(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005411 tSirLedFlashingReq *flashing)
5412{
Govind Singhaa64c242016-03-08 11:31:49 +05305413 struct flashing_req_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005414
5415 if (!wma_handle || !wma_handle->wmi_handle) {
5416 WMA_LOGE(FL("WMA is closed, can not issue cmd"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305417 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005418 }
5419 if (!flashing) {
5420 WMA_LOGE(FL("invalid parameter: flashing"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305421 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005422 }
Govind Singhaa64c242016-03-08 11:31:49 +05305423 cmd.req_id = flashing->reqId;
5424 cmd.pattern_id = flashing->pattern_id;
5425 cmd.led_x0 = flashing->led_x0;
5426 cmd.led_x1 = flashing->led_x1;
5427 status = wmi_unified_set_led_flashing_cmd(wma_handle->wmi_handle,
5428 &cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005429 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305430 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005431 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305432 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005433}
5434#endif /* WLAN_FEATURE_GPIO_LED_FLASHING */
5435
5436#ifdef FEATURE_WLAN_CH_AVOID
5437/**
5438 * wma_channel_avoid_evt_handler() - process channel to avoid event from FW.
5439 * @handle: wma handle
5440 * @event: event buffer
5441 * @len: buffer length
5442 *
5443 * Return: 0 for success or error code
5444 */
5445int wma_channel_avoid_evt_handler(void *handle, uint8_t *event,
5446 uint32_t len)
5447{
5448 wmi_avoid_freq_ranges_event_fixed_param *afr_fixed_param;
5449 wmi_avoid_freq_range_desc *afr_desc;
5450 uint32_t num_freq_ranges, freq_range_idx;
5451 tSirChAvoidIndType *sca_indication;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305452 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005453 cds_msg_t sme_msg = { 0 };
5454 WMI_WLAN_FREQ_AVOID_EVENTID_param_tlvs *param_buf =
5455 (WMI_WLAN_FREQ_AVOID_EVENTID_param_tlvs *) event;
5456
5457 if (!param_buf) {
5458 WMA_LOGE("Invalid channel avoid event buffer");
5459 return -EINVAL;
5460 }
5461
5462 afr_fixed_param = param_buf->fixed_param;
5463 if (!afr_fixed_param) {
5464 WMA_LOGE("Invalid channel avoid event fixed param buffer");
5465 return -EINVAL;
5466 }
5467
5468 num_freq_ranges =
5469 (afr_fixed_param->num_freq_ranges >
5470 SIR_CH_AVOID_MAX_RANGE) ? SIR_CH_AVOID_MAX_RANGE :
5471 afr_fixed_param->num_freq_ranges;
5472
5473 WMA_LOGD("Channel avoid event received with %d ranges",
5474 num_freq_ranges);
5475 for (freq_range_idx = 0; freq_range_idx < num_freq_ranges;
5476 freq_range_idx++) {
5477 afr_desc = (wmi_avoid_freq_range_desc *)
5478 ((void *)param_buf->avd_freq_range +
5479 freq_range_idx * sizeof(wmi_avoid_freq_range_desc));
5480
5481 WMA_LOGD("range %d: tlv id = %u, start freq = %u, end freq = %u",
5482 freq_range_idx, afr_desc->tlv_header, afr_desc->start_freq,
5483 afr_desc->end_freq);
5484 }
5485
5486 sca_indication = (tSirChAvoidIndType *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305487 qdf_mem_malloc(sizeof(tSirChAvoidIndType));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005488 if (!sca_indication) {
5489 WMA_LOGE("Invalid channel avoid indication buffer");
5490 return -EINVAL;
5491 }
5492
5493 sca_indication->avoid_range_count = num_freq_ranges;
5494 for (freq_range_idx = 0; freq_range_idx < num_freq_ranges;
5495 freq_range_idx++) {
5496 afr_desc = (wmi_avoid_freq_range_desc *)
5497 ((void *)param_buf->avd_freq_range +
5498 freq_range_idx * sizeof(wmi_avoid_freq_range_desc));
5499 sca_indication->avoid_freq_range[freq_range_idx].start_freq =
5500 afr_desc->start_freq;
5501 sca_indication->avoid_freq_range[freq_range_idx].end_freq =
5502 afr_desc->end_freq;
5503 }
5504
5505 sme_msg.type = eWNI_SME_CH_AVOID_IND;
5506 sme_msg.bodyptr = sca_indication;
5507 sme_msg.bodyval = 0;
5508
Anurag Chouhan6d760662016-02-20 16:05:43 +05305509 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305510 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005511 WMA_LOGE("Fail to post eWNI_SME_CH_AVOID_IND msg to SME");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305512 qdf_mem_free(sca_indication);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005513 return -EINVAL;
5514 }
5515
5516 return 0;
5517}
5518
5519/**
5520 * wma_process_ch_avoid_update_req() - handles channel avoid update request
5521 * @wma_handle: wma handle
5522 * @ch_avoid_update_req: channel avoid update params
5523 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305524 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005525 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305526QDF_STATUS wma_process_ch_avoid_update_req(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005527 tSirChAvoidUpdateReq *
5528 ch_avoid_update_req)
5529{
Himanshu Agarwal44195412016-03-09 13:03:54 +05305530 QDF_STATUS status;
5531 if (!wma_handle) {
5532 WMA_LOGE("%s: wma handle is NULL", __func__);
5533 return QDF_STATUS_E_FAILURE;
5534 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005535 if (ch_avoid_update_req == NULL) {
5536 WMA_LOGE("%s : ch_avoid_update_req is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305537 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005538 }
5539
5540 WMA_LOGI("%s: WMA --> WMI_CHAN_AVOID_UPDATE", __func__);
5541
Himanshu Agarwal44195412016-03-09 13:03:54 +05305542 status = wmi_unified_process_ch_avoid_update_cmd(
5543 wma_handle->wmi_handle);
5544 if (QDF_IS_STATUS_ERROR(status))
5545 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005546
5547 WMA_LOGI("%s: WMA --> WMI_CHAN_AVOID_UPDATE sent through WMI",
5548 __func__);
Himanshu Agarwal44195412016-03-09 13:03:54 +05305549 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005550}
5551#endif /* FEATURE_WLAN_CH_AVOID */
5552
5553/**
5554 * wma_set_reg_domain() - set reg domain
5555 * @clientCtxt: client context
5556 * @regId: reg id
5557 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305558 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005559 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305560QDF_STATUS wma_set_reg_domain(void *clientCtxt, v_REGDOMAIN_t regId)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005561{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305562 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005563 cds_set_reg_domain(clientCtxt, regId))
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305564 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005565
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305566 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005567}
5568
5569/**
5570 * wma_send_regdomain_info_to_fw() - send regdomain info to fw
5571 * @reg_dmn: reg domain
5572 * @regdmn2G: 2G reg domain
5573 * @regdmn5G: 5G reg domain
5574 * @ctl2G: 2G test limit
5575 * @ctl5G: 5G test limit
5576 *
5577 * Return: none
5578 */
5579void wma_send_regdomain_info_to_fw(uint32_t reg_dmn, uint16_t regdmn2G,
5580 uint16_t regdmn5G, int8_t ctl2G,
5581 int8_t ctl5G)
5582{
Anurag Chouhan6d760662016-02-20 16:05:43 +05305583 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005584 int32_t cck_mask_val = 0;
Govind Singhd76a5b02016-03-08 15:12:14 +05305585 struct pdev_params pdev_param = {0};
Himanshu Agarwal44195412016-03-09 13:03:54 +05305586 QDF_STATUS ret = QDF_STATUS_SUCCESS;
5587 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005588
5589 if (NULL == wma) {
5590 WMA_LOGE("%s: wma context is NULL", __func__);
5591 return;
5592 }
5593
Himanshu Agarwal44195412016-03-09 13:03:54 +05305594 status = wmi_unified_send_regdomain_info_to_fw_cmd(wma->wmi_handle,
5595 reg_dmn, regdmn2G, regdmn5G, ctl2G, ctl5G);
5596 if (status == QDF_STATUS_E_NOMEM)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005597 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005598
Amar Singhal76b41322015-12-09 14:39:17 -08005599 if ((((reg_dmn & ~COUNTRY_ERD_FLAG) == CTRY_JAPAN14) ||
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005600 ((reg_dmn & ~COUNTRY_ERD_FLAG) == CTRY_KOREA_ROC)) &&
5601 (true == wma->tx_chain_mask_cck))
5602 cck_mask_val = 1;
5603
5604 cck_mask_val |= (wma->self_gen_frm_pwr << 16);
Govind Singhd76a5b02016-03-08 15:12:14 +05305605 pdev_param.param_id = WMI_PDEV_PARAM_TX_CHAIN_MASK_CCK;
5606 pdev_param.param_value = cck_mask_val;
5607 ret = wmi_unified_pdev_param_send(wma->wmi_handle,
5608 &pdev_param,
5609 WMA_WILDCARD_PDEV_ID);
5610
Himanshu Agarwal44195412016-03-09 13:03:54 +05305611 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005612 WMA_LOGE("failed to set PDEV tx_chain_mask_cck %d",
5613 ret);
5614
5615 return;
5616}
5617
5618/**
Houston Hoffmana76591b2015-11-10 16:52:05 -08005619 * wma_post_runtime_resume_msg() - post the resume request
5620 * @handle: validated wma handle
5621 *
5622 * request the MC thread unpaus the vdev and set resume dtim
5623 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305624 * Return: qdf status of the mq post
Houston Hoffmana76591b2015-11-10 16:52:05 -08005625 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305626static QDF_STATUS wma_post_runtime_resume_msg(WMA_HANDLE handle)
Houston Hoffmana76591b2015-11-10 16:52:05 -08005627{
5628 cds_msg_t resume_msg;
Houston Hoffmanc45db892015-11-13 19:59:25 -08005629 QDF_STATUS status;
5630 tp_wma_handle wma = (tp_wma_handle) handle;
5631
5632 qdf_runtime_pm_prevent_suspend(wma->wma_runtime_resume_lock);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005633
5634 resume_msg.bodyptr = NULL;
5635 resume_msg.type = WMA_RUNTIME_PM_RESUME_IND;
Houston Hoffmanc45db892015-11-13 19:59:25 -08005636
5637 status = cds_mq_post_message(QDF_MODULE_ID_WMA, &resume_msg);
5638
5639 if (!QDF_IS_STATUS_SUCCESS(status)) {
5640 WMA_LOGE("Failed to post Runtime PM Resume IND to VOS");
5641 qdf_runtime_pm_allow_suspend(wma->wma_runtime_resume_lock);
5642 }
5643
5644 return status;
Houston Hoffmana76591b2015-11-10 16:52:05 -08005645}
5646
5647/**
5648 * wma_post_runtime_suspend_msg() - post the suspend request
5649 * @handle: validated wma handle
5650 *
5651 * Requests for offloads to be configured for runtime suspend
5652 * on the MC thread
5653 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305654 * Return QDF_STATUS_E_AGAIN in case of timeout or QDF_STATUS_SUCCESS
Houston Hoffmana76591b2015-11-10 16:52:05 -08005655 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305656static QDF_STATUS wma_post_runtime_suspend_msg(WMA_HANDLE handle)
Houston Hoffmana76591b2015-11-10 16:52:05 -08005657{
5658 cds_msg_t cds_msg;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305659 QDF_STATUS qdf_status;
Houston Hoffmana76591b2015-11-10 16:52:05 -08005660 tp_wma_handle wma = (tp_wma_handle) handle;
5661
Anurag Chouhance0dc992016-02-16 18:18:03 +05305662 qdf_event_reset(&wma->runtime_suspend);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005663
5664 cds_msg.bodyptr = NULL;
5665 cds_msg.type = WMA_RUNTIME_PM_SUSPEND_IND;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305666 qdf_status = cds_mq_post_message(QDF_MODULE_ID_WMA, &cds_msg);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005667
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305668 if (qdf_status != QDF_STATUS_SUCCESS)
Houston Hoffmana76591b2015-11-10 16:52:05 -08005669 goto failure;
5670
Anurag Chouhance0dc992016-02-16 18:18:03 +05305671 if (qdf_wait_single_event(&wma->runtime_suspend,
Houston Hoffmana76591b2015-11-10 16:52:05 -08005672 WMA_TGT_SUSPEND_COMPLETE_TIMEOUT) !=
Anurag Chouhance0dc992016-02-16 18:18:03 +05305673 QDF_STATUS_SUCCESS) {
Houston Hoffmana76591b2015-11-10 16:52:05 -08005674 WMA_LOGE("Failed to get runtime suspend event");
Houston Hoffmanc45db892015-11-13 19:59:25 -08005675 goto msg_timed_out;
Houston Hoffmana76591b2015-11-10 16:52:05 -08005676 }
5677
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305678 return QDF_STATUS_SUCCESS;
Houston Hoffmana76591b2015-11-10 16:52:05 -08005679
Houston Hoffmanc45db892015-11-13 19:59:25 -08005680msg_timed_out:
5681 wma_post_runtime_resume_msg(wma);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005682failure:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305683 return QDF_STATUS_E_AGAIN;
Houston Hoffmana76591b2015-11-10 16:52:05 -08005684}
5685
5686/**
5687 * __wma_bus_suspend(): handles bus suspend for wma
5688 * @type: is this suspend part of runtime suspend or system suspend?
5689 *
5690 * Bails if a scan is in progress.
5691 * Calls the appropriate handlers based on configuration and event.
5692 *
5693 * Return: 0 for success or error code
5694 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05305695static int __wma_bus_suspend(enum qdf_suspend_type type)
Houston Hoffmana76591b2015-11-10 16:52:05 -08005696{
Anurag Chouhan6d760662016-02-20 16:05:43 +05305697 WMA_HANDLE handle = cds_get_context(QDF_MODULE_ID_WMA);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005698 if (NULL == handle) {
5699 WMA_LOGE("%s: wma context is NULL", __func__);
5700 return -EFAULT;
5701 }
5702
5703 if (wma_check_scan_in_progress(handle)) {
5704 WMA_LOGE("%s: Scan in progress. Aborting suspend", __func__);
5705 return -EBUSY;
5706 }
5707
Anurag Chouhan6d760662016-02-20 16:05:43 +05305708 if (type == QDF_RUNTIME_SUSPEND) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305709 QDF_STATUS status = wma_post_runtime_suspend_msg(handle);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005710 if (status)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305711 return qdf_status_to_os_return(status);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005712 }
5713
Anurag Chouhan6d760662016-02-20 16:05:43 +05305714 if (type == QDF_SYSTEM_SUSPEND)
Houston Hoffmana76591b2015-11-10 16:52:05 -08005715 WMA_LOGE("%s: wow mode selected %d", __func__,
5716 wma_is_wow_mode_selected(handle));
5717
5718 if (wma_is_wow_mode_selected(handle)) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305719 QDF_STATUS status = wma_enable_wow_in_fw(handle);
5720 return qdf_status_to_os_return(status);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005721 }
5722
5723 return wma_suspend_target(handle, 0);
5724}
5725
5726/**
5727 * wma_runtime_suspend() - handles runtime suspend request from hdd
5728 *
5729 * Calls the appropriate handler based on configuration and event.
5730 * Last busy marking should prevent race conditions between processing
5731 * of asyncronous fw events and the running of runtime suspend.
5732 * (eg. last busy marking should guarantee that any auth requests have
5733 * been processed)
5734 * Events comming from the host are not protected, but aren't expected
5735 * to be an issue.
5736 *
5737 * Return: 0 for success or error code
5738 */
5739int wma_runtime_suspend(void)
5740{
Anurag Chouhan6d760662016-02-20 16:05:43 +05305741 return __wma_bus_suspend(QDF_RUNTIME_SUSPEND);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005742}
5743
5744/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005745 * wma_bus_suspend() - handles bus suspend request from hdd
5746 *
5747 * Calls the appropriate handler based on configuration and event
5748 *
5749 * Return: 0 for success or error code
5750 */
5751int wma_bus_suspend(void)
5752{
Houston Hoffmana76591b2015-11-10 16:52:05 -08005753
Anurag Chouhan6d760662016-02-20 16:05:43 +05305754 return __wma_bus_suspend(QDF_SYSTEM_SUSPEND);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005755}
5756
5757/**
5758 * __wma_bus_resume() - bus resume for wma
5759 *
5760 * does the part of the bus resume common to bus and system suspend
5761 *
5762 * Return: os error code.
5763 */
5764int __wma_bus_resume(WMA_HANDLE handle)
5765{
5766 bool wow_mode = wma_is_wow_mode_selected(handle);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305767 QDF_STATUS status;
Houston Hoffmana76591b2015-11-10 16:52:05 -08005768
5769 WMA_LOGE("%s: wow mode %d", __func__, wow_mode);
5770
5771 if (!wow_mode)
Rajeev Kumar9be537e2016-04-25 17:35:33 -07005772 return qdf_status_to_os_return(wma_resume_target(handle));
Houston Hoffmana76591b2015-11-10 16:52:05 -08005773
5774 status = wma_disable_wow_in_fw(handle);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305775 return qdf_status_to_os_return(status);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005776}
5777
5778/**
5779 * wma_runtime_resume() - do the runtime resume operation for wma
5780 *
5781 * Return: os error code.
5782 */
5783int wma_runtime_resume(void)
5784{
5785 int ret;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305786 QDF_STATUS status;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305787 WMA_HANDLE handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005788 if (NULL == handle) {
5789 WMA_LOGE("%s: wma context is NULL", __func__);
5790 return -EFAULT;
5791 }
5792
Houston Hoffmana76591b2015-11-10 16:52:05 -08005793 ret = __wma_bus_resume(handle);
5794 if (ret)
5795 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005796
Houston Hoffmana76591b2015-11-10 16:52:05 -08005797 status = wma_post_runtime_resume_msg(handle);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305798 return qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005799}
5800
5801/**
5802 * wma_bus_resume() - handles bus resume request from hdd
5803 * @handle: valid wma handle
5804 *
5805 * Calls the appropriate handler based on configuration
5806 *
5807 * Return: 0 for success or error code
5808 */
5809int wma_bus_resume(void)
5810{
Anurag Chouhan6d760662016-02-20 16:05:43 +05305811 WMA_HANDLE handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005812 if (NULL == handle) {
5813 WMA_LOGE("%s: wma context is NULL", __func__);
5814 return -EFAULT;
5815 }
5816
Houston Hoffmana76591b2015-11-10 16:52:05 -08005817 return __wma_bus_resume(handle);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005818}
5819
5820/**
Manjunathappa Prakash7b67e622016-04-12 15:18:45 +05305821 * wma_suspend_target_timeout() - Handles the target suspend timeout
5822 * @is_self_recovery_enabled: Is self recovery enabled or not
5823 *
5824 * Return: NONE
5825 */
5826#ifdef QCA_WIFI_3_0_ADRASTEA
5827static inline void wma_suspend_target_timeout(bool is_self_recovery_enabled)
5828{
5829 if (cds_is_driver_recovering()) {
5830 WMA_LOGE("%s: recovery is in progress, ignore!", __func__);
5831 } else {
5832 if (is_self_recovery_enabled) {
5833 cds_trigger_recovery();
5834 } else {
5835 QDF_BUG(0);
5836 }
5837 }
5838}
5839#else /* ROME chipset */
5840static inline void wma_suspend_target_timeout(bool is_self_recovery_enabled)
5841{
5842 if (cds_is_load_or_unload_in_progress() || cds_is_driver_recovering()) {
5843 WMA_LOGE("%s: Unloading/Loading/recovery is in progress, Ignore!",
5844 __func__);
5845 } else {
5846 if (is_self_recovery_enabled) {
5847 cds_trigger_recovery();
5848 } else {
5849 QDF_BUG(0);
5850 }
5851 }
5852}
5853#endif
5854
5855/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005856 * wma_suspend_target() - suspend target
5857 * @handle: wma handle
5858 * @disable_target_intr: disable target interrupt
5859 *
Govind Singhd76a5b02016-03-08 15:12:14 +05305860 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005861 */
Govind Singhd76a5b02016-03-08 15:12:14 +05305862QDF_STATUS wma_suspend_target(WMA_HANDLE handle, int disable_target_intr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005863{
5864 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Komal Seelam3d202862016-02-24 18:43:24 +05305865 struct hif_opaque_softc *scn;
Govind Singhd76a5b02016-03-08 15:12:14 +05305866 QDF_STATUS status;
5867 struct suspend_params param = {0};
5868
Anurag Chouhan6d760662016-02-20 16:05:43 +05305869 tpAniSirGlobal pmac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005870
5871 if (!wma_handle || !wma_handle->wmi_handle) {
5872 WMA_LOGE("WMA is closed. can not issue suspend cmd");
Govind Singhd76a5b02016-03-08 15:12:14 +05305873 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005874 }
Yue Mae1a85f32015-10-20 18:12:45 -07005875
Yue Mae1a85f32015-10-20 18:12:45 -07005876 if (NULL == pmac) {
5877 WMA_LOGE("%s: Unable to get PE context", __func__);
Govind Singhd76a5b02016-03-08 15:12:14 +05305878 return QDF_STATUS_E_INVAL;
Yue Mae1a85f32015-10-20 18:12:45 -07005879 }
Houston Hoffman52ec6692016-04-21 16:36:45 -07005880
Anurag Chouhance0dc992016-02-16 18:18:03 +05305881 qdf_event_reset(&wma_handle->target_suspend);
Govind Singhd76a5b02016-03-08 15:12:14 +05305882 param.disable_target_intr = disable_target_intr;
5883 status = wmi_unified_suspend_send(wma_handle->wmi_handle,
5884 &param,
5885 WMA_WILDCARD_PDEV_ID);
5886 if (QDF_IS_STATUS_ERROR(status))
5887 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005888
5889 wmi_set_target_suspend(wma_handle->wmi_handle, true);
5890
Anurag Chouhance0dc992016-02-16 18:18:03 +05305891 if (qdf_wait_single_event(&wma_handle->target_suspend,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005892 WMA_TGT_SUSPEND_COMPLETE_TIMEOUT)
Anurag Chouhance0dc992016-02-16 18:18:03 +05305893 != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005894 WMA_LOGE("Failed to get ACK from firmware for pdev suspend");
5895 wmi_set_target_suspend(wma_handle->wmi_handle, false);
Manjunathappa Prakash7b67e622016-04-12 15:18:45 +05305896 wma_suspend_target_timeout(pmac->sme.enableSelfRecovery);
Govind Singhd76a5b02016-03-08 15:12:14 +05305897 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005898 }
5899
Anurag Chouhan6d760662016-02-20 16:05:43 +05305900 scn = cds_get_context(QDF_MODULE_ID_HIF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005901
5902 if (scn == NULL) {
5903 WMA_LOGE("%s: Failed to get HIF context", __func__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305904 QDF_ASSERT(0);
Govind Singhd76a5b02016-03-08 15:12:14 +05305905 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005906 }
5907
Govind Singhd76a5b02016-03-08 15:12:14 +05305908 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005909}
5910
5911/**
5912 * wma_target_suspend_acknowledge() - update target susspend status
5913 * @context: wma context
5914 *
5915 * Return: none
5916 */
5917void wma_target_suspend_acknowledge(void *context)
5918{
Anurag Chouhan6d760662016-02-20 16:05:43 +05305919 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005920 int wow_nack = *((int *)context);
5921
5922 if (NULL == wma) {
5923 WMA_LOGE("%s: wma is NULL", __func__);
5924 return;
5925 }
5926
5927 wma->wow_nack = wow_nack;
Anurag Chouhance0dc992016-02-16 18:18:03 +05305928 qdf_event_set(&wma->target_suspend);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005929 if (wow_nack)
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305930 qdf_wake_lock_timeout_acquire(&wma->wow_wake_lock,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005931 WMA_WAKE_LOCK_TIMEOUT,
5932 WIFI_POWER_EVENT_WAKELOCK_WOW);
5933}
5934
5935/**
5936 * wma_resume_target() - resume target
5937 * @handle: wma handle
5938 *
Govind Singhd76a5b02016-03-08 15:12:14 +05305939 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005940 */
Govind Singhd76a5b02016-03-08 15:12:14 +05305941QDF_STATUS wma_resume_target(WMA_HANDLE handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005942{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005943 tp_wma_handle wma = (tp_wma_handle) handle;
Anurag Chouhance0dc992016-02-16 18:18:03 +05305944 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005945#ifdef CONFIG_CNSS
Anurag Chouhan6d760662016-02-20 16:05:43 +05305946 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005947 if (NULL == pMac) {
5948 WMA_LOGE("%s: Unable to get PE context", __func__);
Govind Singhd76a5b02016-03-08 15:12:14 +05305949 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005950 }
5951#endif /* CONFIG_CNSS */
5952
Anurag Chouhance0dc992016-02-16 18:18:03 +05305953 qdf_event_reset(&wma->wma_resume_event);
Govind Singhd76a5b02016-03-08 15:12:14 +05305954 qdf_status = wmi_unified_resume_send(wma->wmi_handle,
5955 WMA_WILDCARD_PDEV_ID);
5956 if (QDF_IS_STATUS_ERROR(qdf_status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005957 WMA_LOGE("Failed to send WMI_PDEV_RESUME_CMDID command");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005958
Anurag Chouhance0dc992016-02-16 18:18:03 +05305959 qdf_status = qdf_wait_single_event(&(wma->wma_resume_event),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005960 WMA_RESUME_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05305961 if (QDF_STATUS_SUCCESS != qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005962 WMA_LOGP("%s: Timeout waiting for resume event from FW",
5963 __func__);
5964 WMA_LOGP("%s: Pending commands %d credits %d", __func__,
5965 wmi_get_pending_cmds(wma->wmi_handle),
5966 wmi_get_host_credits(wma->wmi_handle));
Prashanth Bhatta9e143052015-12-04 11:56:47 -08005967 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005968#ifdef CONFIG_CNSS
5969 if (pMac->sme.enableSelfRecovery) {
5970 cds_trigger_recovery();
5971 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305972 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005973 }
5974#else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305975 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005976#endif /* CONFIG_CNSS */
5977 } else {
5978 WMA_LOGE("%s: SSR in progress, ignore resume timeout",
5979 __func__);
5980 }
5981 } else {
5982 WMA_LOGD("Host wakeup received");
5983 }
5984
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305985 if (QDF_STATUS_SUCCESS == qdf_status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005986 wmi_set_target_suspend(wma->wmi_handle, false);
5987
Houston Hoffman52ec6692016-04-21 16:36:45 -07005988 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005989}
5990
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005991#ifdef FEATURE_WLAN_TDLS
5992/**
5993 * wma_tdls_event_handler() - handle TDLS event
5994 * @handle: wma handle
5995 * @event: event buffer
5996 * @len: buffer length
5997 *
5998 * Return: 0 for success or error code
5999 */
6000int wma_tdls_event_handler(void *handle, uint8_t *event, uint32_t len)
6001{
6002 tp_wma_handle wma = (tp_wma_handle) handle;
6003 WMI_TDLS_PEER_EVENTID_param_tlvs *param_buf = NULL;
6004 wmi_tdls_peer_event_fixed_param *peer_event = NULL;
6005 tSirTdlsEventnotify *tdls_event;
6006
6007 if (!event) {
6008 WMA_LOGE("%s: event param null", __func__);
6009 return -EINVAL;
6010 }
6011
6012 param_buf = (WMI_TDLS_PEER_EVENTID_param_tlvs *) event;
6013 if (!param_buf) {
6014 WMA_LOGE("%s: received null buf from target", __func__);
6015 return -EINVAL;
6016 }
6017
6018 peer_event = param_buf->fixed_param;
6019 if (!peer_event) {
6020 WMA_LOGE("%s: received null event data from target", __func__);
6021 return -EINVAL;
6022 }
6023
6024 tdls_event = (tSirTdlsEventnotify *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306025 qdf_mem_malloc(sizeof(*tdls_event));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006026 if (!tdls_event) {
6027 WMA_LOGE("%s: failed to allocate memory for tdls_event",
6028 __func__);
6029 return -ENOMEM;
6030 }
6031
6032 tdls_event->sessionId = peer_event->vdev_id;
6033 WMI_MAC_ADDR_TO_CHAR_ARRAY(&peer_event->peer_macaddr,
Srinivas Girigowda4f593792015-11-19 15:33:42 -08006034 tdls_event->peermac.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006035
6036 switch (peer_event->peer_status) {
6037 case WMI_TDLS_SHOULD_DISCOVER:
6038 tdls_event->messageType = WMA_TDLS_SHOULD_DISCOVER_CMD;
6039 break;
6040 case WMI_TDLS_SHOULD_TEARDOWN:
6041 tdls_event->messageType = WMA_TDLS_SHOULD_TEARDOWN_CMD;
6042 break;
6043 case WMI_TDLS_PEER_DISCONNECTED:
6044 tdls_event->messageType = WMA_TDLS_PEER_DISCONNECTED_CMD;
6045 break;
6046 default:
6047 WMA_LOGE("%s: Discarding unknown tdls event(%d) from target",
6048 __func__, peer_event->peer_status);
6049 return -EINVAL;
6050 }
6051
6052 switch (peer_event->peer_reason) {
6053 case WMI_TDLS_TEARDOWN_REASON_TX:
6054 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_TX;
6055 break;
6056 case WMI_TDLS_TEARDOWN_REASON_RSSI:
6057 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_RSSI;
6058 break;
6059 case WMI_TDLS_TEARDOWN_REASON_SCAN:
6060 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_SCAN;
6061 break;
6062 case WMI_TDLS_DISCONNECTED_REASON_PEER_DELETE:
6063 tdls_event->peer_reason =
6064 eWNI_TDLS_DISCONNECTED_REASON_PEER_DELETE;
6065 break;
6066 case WMI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT:
6067 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT;
6068 break;
6069 case WMI_TDLS_TEARDOWN_REASON_BAD_PTR:
6070 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_BAD_PTR;
6071 break;
6072 case WMI_TDLS_TEARDOWN_REASON_NO_RESPONSE:
6073 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_NO_RESPONSE;
6074 break;
6075 default:
6076 WMA_LOGE("%s: unknown reason(%d) in tdls event(%d) from target",
6077 __func__, peer_event->peer_reason,
6078 peer_event->peer_status);
6079 return -EINVAL;
6080 }
6081
6082 WMA_LOGD("%s: sending msg to umac, messageType: 0x%x, "
6083 "for peer: %pM, reason: %d, smesessionId: %d",
Srinivas Girigowda4f593792015-11-19 15:33:42 -08006084 __func__, tdls_event->messageType, tdls_event->peermac.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006085 tdls_event->peer_reason, tdls_event->sessionId);
6086
6087 wma_send_msg(wma, tdls_event->messageType, (void *)tdls_event, 0);
6088 return 0;
6089}
6090
6091/**
6092 * wma_set_tdls_offchan_mode() - set tdls off channel mode
6093 * @handle: wma handle
6094 * @chan_switch_params: Pointer to tdls channel switch parameter structure
6095 *
6096 * This function sets tdls off channel mode
6097 *
6098 * Return: 0 on success; Negative errno otherwise
6099 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05306100QDF_STATUS wma_set_tdls_offchan_mode(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006101 tdls_chan_switch_params *chan_switch_params)
6102{
6103 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Himanshu Agarwal44195412016-03-09 13:03:54 +05306104 struct tdls_channel_switch_params params = {0};
6105 QDF_STATUS ret = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006106
6107 if (!wma_handle || !wma_handle->wmi_handle) {
6108 WMA_LOGE(FL(
6109 "WMA is closed, can not issue tdls off channel cmd"
6110 ));
6111 ret = -EINVAL;
6112 goto end;
6113 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006114
Himanshu Agarwal44195412016-03-09 13:03:54 +05306115 params.vdev_id = chan_switch_params->vdev_id;
6116 params.tdls_off_ch_bw_offset =
6117 chan_switch_params->tdls_off_ch_bw_offset;
6118 params.tdls_off_ch = chan_switch_params->tdls_off_ch;
6119 params.tdls_sw_mode = chan_switch_params->tdls_sw_mode;
6120 params.oper_class = chan_switch_params->oper_class;
6121 params.is_responder = chan_switch_params->is_responder;
6122 qdf_mem_copy(params.peer_mac_addr, chan_switch_params->peer_mac_addr,
Krunal Soniab793342016-04-22 18:43:20 -07006123 IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006124
Himanshu Agarwal44195412016-03-09 13:03:54 +05306125 ret = wmi_unified_set_tdls_offchan_mode_cmd(wma_handle->wmi_handle,
6126 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006127
6128end:
6129 if (chan_switch_params)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306130 qdf_mem_free(chan_switch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006131 return ret;
6132}
6133
6134/**
6135 * wma_update_fw_tdls_state() - send enable/disable tdls for a vdev
6136 * @wma: wma handle
6137 * @pwmaTdlsparams: TDLS params
6138 *
6139 * Return: 0 for sucess or error code
6140 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05306141QDF_STATUS wma_update_fw_tdls_state(WMA_HANDLE handle, void *pwmaTdlsparams)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006142{
6143 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006144 t_wma_tdls_mode tdls_mode;
6145 t_wma_tdls_params *wma_tdls = (t_wma_tdls_params *) pwmaTdlsparams;
Himanshu Agarwal44195412016-03-09 13:03:54 +05306146 struct wmi_tdls_params params = {0};
6147 QDF_STATUS ret = QDF_STATUS_SUCCESS;
6148 uint8_t tdls_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006149
6150 if (!wma_handle || !wma_handle->wmi_handle) {
6151 WMA_LOGE("%s: WMA is closed, can not issue fw tdls state cmd",
6152 __func__);
6153 ret = -EINVAL;
6154 goto end_fw_tdls_state;
6155 }
6156
Himanshu Agarwal44195412016-03-09 13:03:54 +05306157 params.tdls_state = wma_tdls->tdls_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006158 tdls_mode = wma_tdls->tdls_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006159
6160 if (WMA_TDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == tdls_mode) {
Himanshu Agarwal44195412016-03-09 13:03:54 +05306161 tdls_state = WMI_TDLS_ENABLE_PASSIVE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006162 } else if (WMA_TDLS_SUPPORT_ENABLED == tdls_mode) {
Himanshu Agarwal44195412016-03-09 13:03:54 +05306163 tdls_state = WMI_TDLS_ENABLE_ACTIVE;
Kabilan Kannan421714b2015-11-23 04:44:59 -08006164 } else if (WMA_TDLS_SUPPORT_ACTIVE_EXTERNAL_CONTROL == tdls_mode) {
Himanshu Agarwal44195412016-03-09 13:03:54 +05306165 tdls_state = WMI_TDLS_ENABLE_ACTIVE_EXTERNAL_CONTROL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006166 } else {
Himanshu Agarwal44195412016-03-09 13:03:54 +05306167 tdls_state = WMI_TDLS_DISABLE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006168 }
6169
Himanshu Agarwal44195412016-03-09 13:03:54 +05306170 params.vdev_id = wma_tdls->vdev_id;
6171 params.notification_interval_ms = wma_tdls->notification_interval_ms;
6172 params.tx_discovery_threshold = wma_tdls->tx_discovery_threshold;
6173 params.tx_teardown_threshold = wma_tdls->tx_teardown_threshold;
6174 params.rssi_teardown_threshold = wma_tdls->rssi_teardown_threshold;
6175 params.rssi_delta = wma_tdls->rssi_delta;
6176 params.tdls_options = wma_tdls->tdls_options;
6177 params.peer_traffic_ind_window = wma_tdls->peer_traffic_ind_window;
6178 params.peer_traffic_response_timeout =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006179 wma_tdls->peer_traffic_response_timeout;
Himanshu Agarwal44195412016-03-09 13:03:54 +05306180 params.puapsd_mask = wma_tdls->puapsd_mask;
6181 params.puapsd_inactivity_time = wma_tdls->puapsd_inactivity_time;
6182 params.puapsd_rx_frame_threshold =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006183 wma_tdls->puapsd_rx_frame_threshold;
Himanshu Agarwal44195412016-03-09 13:03:54 +05306184 params.teardown_notification_ms =
Kabilan Kannanca670be2015-11-23 01:56:12 -08006185 wma_tdls->teardown_notification_ms;
Himanshu Agarwal44195412016-03-09 13:03:54 +05306186 params.tdls_peer_kickout_threshold =
Kabilan Kannan421714b2015-11-23 04:44:59 -08006187 wma_tdls->tdls_peer_kickout_threshold;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006188
Himanshu Agarwal44195412016-03-09 13:03:54 +05306189 ret = wmi_unified_update_fw_tdls_state_cmd(wma_handle->wmi_handle,
6190 &params, tdls_state);
6191 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006192 goto end_fw_tdls_state;
Himanshu Agarwal44195412016-03-09 13:03:54 +05306193
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006194 WMA_LOGD("%s: vdev_id %d", __func__, wma_tdls->vdev_id);
6195
6196end_fw_tdls_state:
6197 if (pwmaTdlsparams)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306198 qdf_mem_free(pwmaTdlsparams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006199 return ret;
6200}
6201
6202/**
6203 * wma_update_tdls_peer_state() - update TDLS peer state
6204 * @handle: wma handle
6205 * @peerStateParams: TDLS peer state params
6206 *
6207 * Return: 0 for success or error code
6208 */
6209int wma_update_tdls_peer_state(WMA_HANDLE handle,
6210 tTdlsPeerStateParams *peerStateParams)
6211{
6212 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006213 uint32_t i;
6214 ol_txrx_pdev_handle pdev;
6215 uint8_t peer_id;
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07006216 ol_txrx_peer_handle peer;
6217 uint8_t *peer_mac_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006218 int ret = 0;
Govind Singhaa64c242016-03-08 11:31:49 +05306219 uint32_t *ch_mhz;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006220
6221 if (!wma_handle || !wma_handle->wmi_handle) {
6222 WMA_LOGE("%s: WMA is closed, can not issue cmd", __func__);
6223 ret = -EINVAL;
6224 goto end_tdls_peer_state;
6225 }
6226
6227 /* peer capability info is valid only when peer state is connected */
6228 if (WMA_TDLS_PEER_STATE_CONNECTED != peerStateParams->peerState) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306229 qdf_mem_zero(&peerStateParams->peerCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006230 sizeof(tTdlsPeerCapParams));
6231 }
6232
Govind Singhaa64c242016-03-08 11:31:49 +05306233 ch_mhz = qdf_mem_malloc(sizeof(uint32_t) *
6234 peerStateParams->peerCap.peerChanLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006235 for (i = 0; i < peerStateParams->peerCap.peerChanLen; ++i) {
Govind Singhaa64c242016-03-08 11:31:49 +05306236 ch_mhz[i] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006237 cds_chan_to_freq(peerStateParams->peerCap.peerChan[i].
6238 chanId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006239 }
6240
Govind Singhaa64c242016-03-08 11:31:49 +05306241 if (wmi_unified_update_tdls_peer_state_cmd(wma_handle->wmi_handle,
6242 (struct tdls_peer_state_params *)peerStateParams,
6243 ch_mhz)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006244 WMA_LOGE("%s: failed to send tdls peer update state command",
6245 __func__);
Govind Singhaa64c242016-03-08 11:31:49 +05306246 qdf_mem_free(ch_mhz);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006247 ret = -EIO;
6248 goto end_tdls_peer_state;
6249 }
6250
Govind Singhaa64c242016-03-08 11:31:49 +05306251 qdf_mem_free(ch_mhz);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006252 /* in case of teardown, remove peer from fw */
6253 if (WMA_TDLS_PEER_STATE_TEARDOWN == peerStateParams->peerState) {
Anurag Chouhan6d760662016-02-20 16:05:43 +05306254 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006255 if (!pdev) {
6256 WMA_LOGE("%s: Failed to find pdev", __func__);
6257 ret = -EIO;
6258 goto end_tdls_peer_state;
6259 }
6260
6261 peer = ol_txrx_find_peer_by_addr(pdev,
6262 peerStateParams->peerMacAddr,
6263 &peer_id);
6264 if (!peer) {
6265 WMA_LOGE("%s: Failed to get peer handle using peer mac %pM",
6266 __func__, peerStateParams->peerMacAddr);
6267 ret = -EIO;
6268 goto end_tdls_peer_state;
6269 }
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07006270 peer_mac_addr = ol_txrx_peer_get_peer_mac_addr(peer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006271
6272 WMA_LOGD("%s: calling wma_remove_peer for peer " MAC_ADDRESS_STR
6273 " vdevId: %d", __func__,
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07006274 MAC_ADDR_ARRAY(peer_mac_addr),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006275 peerStateParams->vdevId);
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07006276 wma_remove_peer(wma_handle, peer_mac_addr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006277 peerStateParams->vdevId, peer, false);
6278 }
6279
6280end_tdls_peer_state:
6281 if (peerStateParams)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306282 qdf_mem_free(peerStateParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006283 return ret;
6284}
6285#endif /* FEATURE_WLAN_TDLS */
6286
6287
6288/**
6289 * wma_dfs_attach() - Attach DFS methods to the umac state.
6290 * @dfs_ic: ieee80211com ptr
6291 *
6292 * Return: Return ieee80211com ptr with updated info
6293 */
6294struct ieee80211com *wma_dfs_attach(struct ieee80211com *dfs_ic)
6295{
6296 /*Allocate memory for dfs_ic before passing it up to dfs_attach() */
6297 dfs_ic = (struct ieee80211com *)
6298 os_malloc(NULL, sizeof(struct ieee80211com), GFP_ATOMIC);
6299 if (dfs_ic == NULL) {
6300 WMA_LOGE("%s:Allocation of dfs_ic failed %zu",
6301 __func__, sizeof(struct ieee80211com));
6302 return NULL;
6303 }
6304 OS_MEMZERO(dfs_ic, sizeof(struct ieee80211com));
6305 /* DFS pattern matching hooks */
6306 dfs_ic->ic_dfs_attach = ol_if_dfs_attach;
6307 dfs_ic->ic_dfs_disable = ol_if_dfs_disable;
6308 dfs_ic->ic_find_channel = ieee80211_find_channel;
6309 dfs_ic->ic_dfs_enable = ol_if_dfs_enable;
6310 dfs_ic->ic_ieee2mhz = ieee80211_ieee2mhz;
6311
6312 /* Hardware facing hooks */
6313 dfs_ic->ic_get_ext_busy = ol_if_dfs_get_ext_busy;
6314 dfs_ic->ic_get_mib_cycle_counts_pct =
6315 ol_if_dfs_get_mib_cycle_counts_pct;
6316 dfs_ic->ic_get_TSF64 = ol_if_get_tsf64;
6317
6318 /* NOL related hooks */
6319 dfs_ic->ic_dfs_usenol = ol_if_dfs_usenol;
6320 /*
6321 * Hooks from wma/dfs/ back
6322 * into the PE/SME
6323 * and shared DFS code
6324 */
6325 dfs_ic->ic_dfs_notify_radar = ieee80211_mark_dfs;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306326 qdf_spinlock_create(&dfs_ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006327 /* Initializes DFS Data Structures and queues */
6328 dfs_attach(dfs_ic);
6329
6330 return dfs_ic;
6331}
6332
6333/**
6334 * wma_dfs_detach() - Detach DFS methods
6335 * @dfs_ic: ieee80211com ptr
6336 *
6337 * Return: none
6338 */
6339void wma_dfs_detach(struct ieee80211com *dfs_ic)
6340{
6341 dfs_detach(dfs_ic);
6342
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306343 qdf_spinlock_destroy(&dfs_ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006344 if (NULL != dfs_ic->ic_curchan) {
6345 OS_FREE(dfs_ic->ic_curchan);
6346 dfs_ic->ic_curchan = NULL;
6347 }
6348
6349 OS_FREE(dfs_ic);
6350}
6351
6352/**
6353 * wma_dfs_configure() - configure dfs
6354 * @ic: ieee80211com ptr
6355 *
6356 * Configures Radar Filters during
6357 * vdev start/channel change/regulatory domain
6358 * change.This Configuration enables to program
6359 * the DFS pattern matching module.
6360 *
6361 * Return: none
6362 */
6363void wma_dfs_configure(struct ieee80211com *ic)
6364{
6365 struct ath_dfs_radar_tab_info rinfo;
6366 int dfsdomain;
6367 int radar_enabled_status = 0;
6368 if (ic == NULL) {
6369 WMA_LOGE("%s: DFS ic is Invalid", __func__);
6370 return;
6371 }
6372
6373 dfsdomain = ic->current_dfs_regdomain;
6374
6375 /* Fetch current radar patterns from the lmac */
6376 OS_MEMZERO(&rinfo, sizeof(rinfo));
6377
6378 /*
6379 * Look up the current DFS
6380 * regulatory domain and decide
6381 * which radar pulses to use.
6382 */
6383 switch (dfsdomain) {
Amar Singhala7bb01b2016-01-27 11:31:59 -08006384 case DFS_FCC_REGION:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006385 WMA_LOGI("%s: DFS-FCC domain", __func__);
Amar Singhala7bb01b2016-01-27 11:31:59 -08006386 rinfo.dfsdomain = DFS_FCC_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006387 rinfo.dfs_radars = dfs_fcc_radars;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306388 rinfo.numradars = QDF_ARRAY_SIZE(dfs_fcc_radars);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006389 rinfo.b5pulses = dfs_fcc_bin5pulses;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306390 rinfo.numb5radars = QDF_ARRAY_SIZE(dfs_fcc_bin5pulses);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006391 break;
Amar Singhala7bb01b2016-01-27 11:31:59 -08006392 case DFS_ETSI_REGION:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006393 WMA_LOGI("%s: DFS-ETSI domain", __func__);
Amar Singhala7bb01b2016-01-27 11:31:59 -08006394 rinfo.dfsdomain = DFS_ETSI_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006395 rinfo.dfs_radars = dfs_etsi_radars;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306396 rinfo.numradars = QDF_ARRAY_SIZE(dfs_etsi_radars);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006397 rinfo.b5pulses = NULL;
6398 rinfo.numb5radars = 0;
6399 break;
Amar Singhala7bb01b2016-01-27 11:31:59 -08006400 case DFS_MKK_REGION:
6401 WMA_LOGI("%s: DFS-MKK domain", __func__);
6402 rinfo.dfsdomain = DFS_MKK_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006403 rinfo.dfs_radars = dfs_mkk4_radars;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306404 rinfo.numradars = QDF_ARRAY_SIZE(dfs_mkk4_radars);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006405 rinfo.b5pulses = dfs_jpn_bin5pulses;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306406 rinfo.numb5radars = QDF_ARRAY_SIZE(dfs_jpn_bin5pulses);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006407 break;
6408 default:
6409 WMA_LOGI("%s: DFS-UNINT domain", __func__);
Amar Singhala7bb01b2016-01-27 11:31:59 -08006410 rinfo.dfsdomain = DFS_UNINIT_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006411 rinfo.dfs_radars = NULL;
6412 rinfo.numradars = 0;
6413 rinfo.b5pulses = NULL;
6414 rinfo.numb5radars = 0;
6415 break;
6416 }
6417
6418 rinfo.dfs_pri_multiplier = ic->dfs_pri_multiplier;
6419
6420 /*
6421 * Set the regulatory domain,
6422 * radar pulse table and enable
6423 * radar events if required.
6424 * dfs_radar_enable() returns
6425 * 0 on success and non-zero
6426 * failure.
6427 */
6428 radar_enabled_status = dfs_radar_enable(ic, &rinfo);
6429 if (radar_enabled_status != DFS_STATUS_SUCCESS) {
6430 WMA_LOGE("%s[%d]: DFS- Radar Detection Enabling Failed",
6431 __func__, __LINE__);
6432 }
6433}
6434
6435/**
6436 * wma_dfs_configure_channel() - configure DFS channel
6437 * @dfs_ic: ieee80211com ptr
Siddarth Poddar17dc4712016-03-09 16:30:27 +05306438 * @band_center_freq1: center frequency 1
6439 * @band_center_freq2: center frequency 2
6440 * (valid only for 11ac vht 80plus80 mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006441 * @ req: vdev start request
6442 *
6443 * Set the Channel parameters in to DFS module
6444 * Also,configure the DFS radar filters for
6445 * matching the DFS phyerrors.
6446 *
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306447 * Return: dfs_ieee80211_channel / NULL for error
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006448 */
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306449struct dfs_ieee80211_channel *wma_dfs_configure_channel(
6450 struct ieee80211com *dfs_ic,
Siddarth Poddar17dc4712016-03-09 16:30:27 +05306451 uint32_t band_center_freq1,
6452 uint32_t band_center_freq2,
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306453 struct wma_vdev_start_req
6454 *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006455{
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006456 uint8_t ext_channel;
6457
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006458 if (dfs_ic == NULL) {
6459 WMA_LOGE("%s: DFS ic is Invalid", __func__);
6460 return NULL;
6461 }
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05306462
6463 if (!dfs_ic->ic_curchan) {
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306464 dfs_ic->ic_curchan = (struct dfs_ieee80211_channel *)os_malloc(
6465 NULL,
6466 sizeof(struct dfs_ieee80211_channel),
6467 GFP_ATOMIC);
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05306468 if (dfs_ic->ic_curchan == NULL) {
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306469 WMA_LOGE(
6470 "%s: allocation of dfs_ic->ic_curchan failed %zu",
6471 __func__, sizeof(struct dfs_ieee80211_channel));
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05306472 return NULL;
6473 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006474 }
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05306475
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306476 OS_MEMZERO(dfs_ic->ic_curchan, sizeof(struct dfs_ieee80211_channel));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006477
6478 dfs_ic->ic_curchan->ic_ieee = req->chan;
Siddarth Poddar17dc4712016-03-09 16:30:27 +05306479 dfs_ic->ic_curchan->ic_freq = cds_chan_to_freq(req->chan);
6480 dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg1 = band_center_freq1;
6481 dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg2 = band_center_freq2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006482 dfs_ic->ic_curchan->ic_pri_freq_center_freq_mhz_separation =
6483 dfs_ic->ic_curchan->ic_freq -
6484 dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg1;
6485
6486 if ((dfs_ic->ic_curchan->ic_ieee >= WMA_11A_CHANNEL_BEGIN) &&
6487 (dfs_ic->ic_curchan->ic_ieee <= WMA_11A_CHANNEL_END)) {
6488 dfs_ic->ic_curchan->ic_flags |= IEEE80211_CHAN_5GHZ;
6489 }
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006490
6491 switch (req->chan_width) {
6492 case CH_WIDTH_20MHZ:
6493 dfs_ic->ic_curchan->ic_flags |=
6494 (req->vht_capable ? IEEE80211_CHAN_VHT20 :
6495 IEEE80211_CHAN_HT20);
6496 break;
6497 case CH_WIDTH_40MHZ:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006498 if (req->chan < req->ch_center_freq_seg0)
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006499 dfs_ic->ic_curchan->ic_flags |=
6500 (req->vht_capable ?
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006501 IEEE80211_CHAN_VHT40PLUS :
6502 IEEE80211_CHAN_HT40PLUS);
6503 else
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006504 dfs_ic->ic_curchan->ic_flags |=
6505 (req->vht_capable ?
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006506 IEEE80211_CHAN_VHT40MINUS :
6507 IEEE80211_CHAN_HT40MINUS);
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006508 break;
6509 case CH_WIDTH_80MHZ:
6510 dfs_ic->ic_curchan->ic_flags |= IEEE80211_CHAN_VHT80;
6511 break;
6512 case CH_WIDTH_80P80MHZ:
Siddarth Poddar17dc4712016-03-09 16:30:27 +05306513 ext_channel = cds_freq_to_chan(band_center_freq2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006514 dfs_ic->ic_curchan->ic_flags |=
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006515 IEEE80211_CHAN_VHT80P80;
6516 dfs_ic->ic_curchan->ic_freq_ext =
Siddarth Poddar17dc4712016-03-09 16:30:27 +05306517 band_center_freq2;
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006518 dfs_ic->ic_curchan->ic_ieee_ext = ext_channel;
6519
6520 /* verify both the 80MHz are DFS bands or not */
Rajeev Kumara3f6c2d2016-04-15 12:47:41 -07006521 if ((CHANNEL_STATE_DFS ==
6522 cds_get_5g_bonded_channel_state(req->chan ,
6523 CH_WIDTH_80MHZ)) &&
6524 (CHANNEL_STATE_DFS == cds_get_5g_bonded_channel_state(
6525 ext_channel - WMA_80MHZ_START_CENTER_CH_DIFF,
6526 CH_WIDTH_80MHZ)))
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006527 dfs_ic->ic_curchan->ic_80p80_both_dfs = true;
6528 break;
6529 case CH_WIDTH_160MHZ:
6530 dfs_ic->ic_curchan->ic_flags |=
6531 IEEE80211_CHAN_VHT160;
6532 break;
6533 default:
6534 WMA_LOGE(
6535 "%s: Recieved a wrong channel width %d",
6536 __func__, req->chan_width);
6537 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006538 }
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006539
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006540 dfs_ic->ic_curchan->ic_flagext |= IEEE80211_CHAN_DFS;
6541
6542 if (req->oper_mode == BSS_OPERATIONAL_MODE_AP) {
6543 dfs_ic->ic_opmode = IEEE80211_M_HOSTAP;
6544 dfs_ic->vdev_id = req->vdev_id;
6545 }
6546
6547 dfs_ic->dfs_pri_multiplier = req->dfs_pri_multiplier;
6548
6549 /*
6550 * Configuring the DFS with current channel and the radar filters
6551 */
6552 wma_dfs_configure(dfs_ic);
6553 WMA_LOGI("%s: DFS- CHANNEL CONFIGURED", __func__);
6554 return dfs_ic->ic_curchan;
6555}
6556
6557
6558/**
6559 * wma_set_dfs_region() - set DFS region
6560 * @wma: wma handle
6561 *
6562 * Configure the DFS region for DFS radar filter initialization
6563 *
6564 * Return: none
6565 */
6566void wma_set_dfs_region(tp_wma_handle wma, uint8_t dfs_region)
6567{
6568 /* dfs information is passed */
Amar Singhala7bb01b2016-01-27 11:31:59 -08006569 if (dfs_region > DFS_MKK_REGION || dfs_region == DFS_UNINIT_REGION)
6570 /* assign DFS_FCC_REGION as default region*/
6571 wma->dfs_ic->current_dfs_regdomain = DFS_FCC_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006572 else
6573 wma->dfs_ic->current_dfs_regdomain = dfs_region;
6574
6575 WMA_LOGI("%s: DFS Region Domain: %d", __func__,
6576 wma->dfs_ic->current_dfs_regdomain);
6577}
6578
6579/**
6580 * wma_get_channels() - prepare dfs radar channel list
6581 * @ichan: channel
6582 * @chan_list: return channel list
6583 *
6584 * Return: return number of channels
6585 */
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306586int wma_get_channels(struct dfs_ieee80211_channel *ichan,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006587 struct wma_dfs_radar_channel_list *chan_list)
6588{
6589 uint8_t center_chan = cds_freq_to_chan(ichan->ic_vhtop_ch_freq_seg1);
Vishwajith Upendrabf673e72016-01-19 16:05:40 -08006590 int count = 0;
6591 int start_channel = 0;
6592 int loop;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006593
6594 chan_list->nchannels = 0;
6595
Vishwajith Upendrabf673e72016-01-19 16:05:40 -08006596 if (IEEE80211_IS_CHAN_11AC_VHT160(ichan)) {
6597 /*
6598 * In 160MHz channel width, need to
6599 * check if each of the 8 20MHz channel
6600 * is DFS before adding to the NOL list.
6601 * As it is possible that part of the
6602 * 160MHz can be Non-DFS channels.
6603 */
6604 start_channel = center_chan - WMA_160MHZ_START_CENTER_CH_DIFF;
6605 for (loop = 0; loop < WMA_DFS_MAX_20M_SUB_CH; loop++) {
6606 if (cds_get_channel_state(start_channel +
6607 (loop * WMA_NEXT_20MHZ_START_CH_DIFF)) ==
6608 CHANNEL_STATE_DFS) {
6609 chan_list->channels[count] = start_channel +
6610 (loop * WMA_NEXT_20MHZ_START_CH_DIFF);
6611 count++;
6612 }
6613 }
6614 chan_list->nchannels = count;
6615 } else if (IEEE80211_IS_CHAN_11AC_VHT80P80(ichan)) {
6616 chan_list->nchannels = 4;
6617 /*
6618 * If SAP is operating in 80p80 mode, either
6619 * one of the two 80 segments or both the 80
6620 * segments can be DFS channels, so need to
6621 * identify on which 80 segment radar has
6622 * been detected and only add those channels
6623 * to the NOL list. center frequency should be
6624 * based on the segment id passed as part of
6625 * channel information in radar indication.
6626 */
6627 if (ichan->ic_radar_found_segid == DFS_80P80_SEG1)
6628 center_chan =
6629 cds_freq_to_chan(ichan->ic_vhtop_ch_freq_seg2);
6630 chan_list->channels[0] = center_chan - 6;
6631 chan_list->channels[1] = center_chan - 2;
6632 chan_list->channels[2] = center_chan + 2;
6633 chan_list->channels[3] = center_chan + 6;
6634 } else if (IEEE80211_IS_CHAN_11AC_VHT80(ichan)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006635 chan_list->nchannels = 4;
6636 chan_list->channels[0] = center_chan - 6;
6637 chan_list->channels[1] = center_chan - 2;
6638 chan_list->channels[2] = center_chan + 2;
6639 chan_list->channels[3] = center_chan + 6;
6640 } else if (IEEE80211_IS_CHAN_11N_HT40(ichan) ||
6641 IEEE80211_IS_CHAN_11AC_VHT40(ichan)) {
6642 chan_list->nchannels = 2;
6643 chan_list->channels[0] = center_chan - 2;
6644 chan_list->channels[1] = center_chan + 2;
6645 } else {
6646 chan_list->nchannels = 1;
6647 chan_list->channels[0] = center_chan;
6648 }
6649
6650 return chan_list->nchannels;
6651}
6652
6653
6654/**
6655 * wma_dfs_indicate_radar() - Indicate Radar to SAP/HDD
6656 * @ic: ieee80211com ptr
6657 * @ichan: ieee 80211 channel
6658 *
6659 * Return: 0 for success or error code
6660 */
6661int wma_dfs_indicate_radar(struct ieee80211com *ic,
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306662 struct dfs_ieee80211_channel *ichan)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006663{
6664 tp_wma_handle wma;
6665 void *hdd_ctx;
6666 struct wma_dfs_radar_indication *radar_event;
6667 struct wma_dfs_radar_ind wma_radar_event;
6668 tpAniSirGlobal pmac = NULL;
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05306669 bool indication_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006670
Anurag Chouhan6d760662016-02-20 16:05:43 +05306671 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006672 if (wma == NULL) {
6673 WMA_LOGE("%s: DFS- Invalid wma", __func__);
6674 return -ENOENT;
6675 }
6676
Anurag Chouhan6d760662016-02-20 16:05:43 +05306677 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006678 pmac = (tpAniSirGlobal)
Anurag Chouhan6d760662016-02-20 16:05:43 +05306679 cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006680
6681 if (!pmac) {
6682 WMA_LOGE("%s: Invalid MAC handle", __func__);
6683 return -ENOENT;
6684 }
6685
6686 if (wma->dfs_ic != ic) {
6687 WMA_LOGE("%s:DFS- Invalid WMA handle", __func__);
6688 return -ENOENT;
6689 }
6690 radar_event = (struct wma_dfs_radar_indication *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306691 qdf_mem_malloc(sizeof(struct wma_dfs_radar_indication));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006692 if (radar_event == NULL) {
6693 WMA_LOGE("%s:DFS- Invalid radar_event", __func__);
6694 return -ENOMEM;
6695 }
6696
6697 /*
6698 * Do not post multiple Radar events on the same channel.
6699 * But, when DFS test mode is enabled, allow multiple dfs
6700 * radar events to be posted on the same channel.
6701 */
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306702 qdf_spin_lock_bh(&ic->chan_lock);
Edhar, Mahesh Kumar35d9b2e2015-10-26 17:06:23 +05306703 if (!pmac->sap.SapDfsInfo.disable_dfs_ch_switch)
6704 wma->dfs_ic->disable_phy_err_processing = true;
6705
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006706 if ((ichan->ic_ieee != (wma->dfs_ic->last_radar_found_chan)) ||
6707 (pmac->sap.SapDfsInfo.disable_dfs_ch_switch == true)) {
6708 wma->dfs_ic->last_radar_found_chan = ichan->ic_ieee;
6709 /* Indicate the radar event to HDD to stop the netif Tx queues */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006710 wma_radar_event.chan_freq = ichan->ic_freq;
6711 wma_radar_event.dfs_radar_status = WMA_DFS_RADAR_FOUND;
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05306712 indication_status =
6713 wma->dfs_radar_indication_cb(hdd_ctx, &wma_radar_event);
6714 if (indication_status == false) {
6715 WMA_LOGE("%s:Application triggered channel switch in progress!.. drop radar event indiaction to SAP",
6716 __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306717 qdf_mem_free(radar_event);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306718 qdf_spin_unlock_bh(&ic->chan_lock);
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05306719 return 0;
6720 }
6721
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006722 WMA_LOGE("%s:DFS- RADAR INDICATED TO HDD", __func__);
6723
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05306724 wma_radar_event.ieee_chan_number = ichan->ic_ieee;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006725 /*
6726 * Indicate to the radar event to SAP to
6727 * select a new channel and set CSA IE
6728 */
6729 radar_event->vdev_id = ic->vdev_id;
6730 wma_get_channels(ichan, &radar_event->chan_list);
6731 radar_event->dfs_radar_status = WMA_DFS_RADAR_FOUND;
6732 radar_event->use_nol = ic->ic_dfs_usenol(ic);
6733 wma_send_msg(wma, WMA_DFS_RADAR_IND, (void *)radar_event, 0);
6734 WMA_LOGE("%s:DFS- WMA_DFS_RADAR_IND Message Posted", __func__);
6735 }
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306736 qdf_spin_unlock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006737
6738 return 0;
6739}
6740
6741#ifdef WLAN_FEATURE_MEMDUMP
6742/*
6743 * wma_process_fw_mem_dump_req() - Function to request fw memory dump from
6744 * firmware
6745 * @wma: Pointer to WMA handle
6746 * @mem_dump_req: Pointer for mem_dump_req
6747 *
6748 * This function sends memory dump request to firmware
6749 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306750 * Return: QDF_STATUS_SUCCESS for success otherwise failure
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006751 *
6752 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306753QDF_STATUS wma_process_fw_mem_dump_req(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006754 struct fw_dump_req *mem_dump_req)
6755{
Govind Singhaa64c242016-03-08 11:31:49 +05306756 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006757
6758 if (!mem_dump_req || !wma) {
6759 WMA_LOGE(FL("input pointer is NULL"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306760 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006761 }
6762
Govind Singhaa64c242016-03-08 11:31:49 +05306763 ret = wmi_unified_process_fw_mem_dump_cmd(wma->wmi_handle,
6764 (struct fw_dump_req_param *) mem_dump_req);
6765 if (ret)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306766 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006767
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306768 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006769}
6770
6771/**
6772 * wma_fw_mem_dump_rsp() - send fw mem dump response to SME
6773 *
6774 * @req_id - request id.
6775 * @status - copy status from the firmware.
6776 *
6777 * This function is called by the memory dump response handler to
6778 * indicate SME that firmware dump copy is complete
6779 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306780 * Return: QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006781 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306782static QDF_STATUS wma_fw_mem_dump_rsp(uint32_t req_id, uint32_t status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006783{
6784 struct fw_dump_rsp *dump_rsp;
6785 cds_msg_t sme_msg = {0};
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306786 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006787
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306788 dump_rsp = qdf_mem_malloc(sizeof(*dump_rsp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006789
6790 if (!dump_rsp) {
6791 WMA_LOGE(FL("Memory allocation failed."));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306792 qdf_status = QDF_STATUS_E_NOMEM;
6793 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006794 }
6795
6796 WMA_LOGI(FL("FW memory dump copy complete status: %d for request: %d"),
6797 status, req_id);
6798
6799 dump_rsp->request_id = req_id;
6800 dump_rsp->dump_complete = status;
6801
6802 sme_msg.type = eWNI_SME_FW_DUMP_IND;
6803 sme_msg.bodyptr = dump_rsp;
6804 sme_msg.bodyval = 0;
6805
Anurag Chouhan6d760662016-02-20 16:05:43 +05306806 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306807 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006808 WMA_LOGE(FL("Fail to post fw mem dump ind msg"));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306809 qdf_mem_free(dump_rsp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006810 }
6811
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306812 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006813}
6814
6815/**
6816 * wma_fw_mem_dump_event_handler() - handles fw memory dump event
6817 *
6818 * @handle: pointer to wma handle.
6819 * @cmd_param_info: pointer to TLV info received in the event.
6820 * @len: length of data in @cmd_param_info
6821 *
6822 * This function is a handler for firmware memory dump event.
6823 *
6824 * Return: integer (0 for success and error code otherwise)
6825 */
6826int wma_fw_mem_dump_event_handler(void *handle, u_int8_t *cmd_param_info,
6827 u_int32_t len)
6828{
6829 WMI_UPDATE_FW_MEM_DUMP_EVENTID_param_tlvs *param_buf;
6830 wmi_update_fw_mem_dump_fixed_param *event;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306831 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006832
6833 param_buf =
6834 (WMI_UPDATE_FW_MEM_DUMP_EVENTID_param_tlvs *) cmd_param_info;
6835 if (!param_buf) {
6836 WMA_LOGA("%s: Invalid stats event", __func__);
6837 return -EINVAL;
6838 }
6839
6840 event = param_buf->fixed_param;
6841
6842 status = wma_fw_mem_dump_rsp(event->request_id,
6843 event->fw_mem_dump_complete);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306844 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006845 WMA_LOGE("Error posting FW MEM DUMP RSP.");
6846 return -EINVAL;
6847 }
6848
6849 WMA_LOGI("FW MEM DUMP RSP posted successfully");
6850 return 0;
6851}
6852#endif /* WLAN_FEATURE_MEMDUMP */
6853
6854/*
6855 * wma_process_set_ie_info() - Function to send IE info to firmware
6856 * @wma: Pointer to WMA handle
6857 * @ie_data: Pointer for ie data
6858 *
6859 * This function sends IE information to firmware
6860 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306861 * Return: QDF_STATUS_SUCCESS for success otherwise failure
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006862 *
6863 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306864QDF_STATUS wma_process_set_ie_info(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006865 struct vdev_ie_info *ie_info)
6866{
Govind Singhaa64c242016-03-08 11:31:49 +05306867 struct vdev_ie_info_param cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006868 int ret;
6869
6870 if (!ie_info || !wma) {
6871 WMA_LOGE(FL("input pointer is NULL"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306872 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006873 }
6874
6875 /* Validate the input */
6876 if (ie_info->length <= 0) {
6877 WMA_LOGE(FL("Invalid IE length"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306878 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006879 }
6880
Govind Singhaa64c242016-03-08 11:31:49 +05306881 cmd.vdev_id = ie_info->vdev_id;
6882 cmd.ie_id = ie_info->ie_id;
6883 cmd.length = ie_info->length;
6884 cmd.data = ie_info->data;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006885
Govind Singhaa64c242016-03-08 11:31:49 +05306886 ret = wmi_unified_process_set_ie_info_cmd(wma->wmi_handle,
6887 &cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006888
6889 return ret;
6890}
6891