blob: 00c2df030d6f5b2e23d687baa7e1a373ff172185 [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}
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700422
Manikandan Mohan976e7562016-03-15 16:33:31 -0700423/**
424 * wma_set_tsf_gpio_pin() - send wmi cmd to configure gpio pin
425 * @handle: wma handler
426 * @pin: GPIO pin id
427 *
428 * Return: QDF_STATUS
429 */
430QDF_STATUS wma_set_tsf_gpio_pin(WMA_HANDLE handle, uint32_t pin)
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700431{
Manikandan Mohan976e7562016-03-15 16:33:31 -0700432 tp_wma_handle wma = (tp_wma_handle)handle;
433 struct pdev_params pdev_param = {0};
434 int32_t ret;
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700435
Manikandan Mohan976e7562016-03-15 16:33:31 -0700436 if (!wma || !wma->wmi_handle) {
437 WMA_LOGE("%s: WMA is closed, can not set gpio", __func__);
438 return QDF_STATUS_E_INVAL;
439 }
440
441 WMA_LOGD("%s: set tsf gpio pin: %d", __func__, pin);
442
443 pdev_param.param_id = WMI_PDEV_PARAM_WNTS_CONFIG;
444 pdev_param.param_value = pin;
445 ret = wmi_unified_pdev_param_send(wma->wmi_handle,
446 &pdev_param,
447 WMA_WILDCARD_PDEV_ID);
448 if (ret) {
449 WMA_LOGE("%s: Failed to set tsf gpio pin (%d)", __func__, ret);
450 return QDF_STATUS_E_FAILURE;
451 }
452 return QDF_STATUS_SUCCESS;
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700453}
454#endif
455
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800456#ifdef FEATURE_WLAN_LPHB
457/**
458 * wma_lphb_conf_hbenable() - enable command of LPHB configuration requests
459 * @wma_handle: WMA handle
460 * @lphb_conf_req: configuration info
461 * @by_user: whether this call is from user or cached resent
462 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530463 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800464 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530465QDF_STATUS wma_lphb_conf_hbenable(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800466 tSirLPHBReq *lphb_conf_req, bool by_user)
467{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530468 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800469 int status = 0;
470 tSirLPHBEnableStruct *ts_lphb_enable;
Govind Singhaa64c242016-03-08 11:31:49 +0530471 wmi_hb_set_enable_cmd_fixed_param hb_enable_fp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800472 int i;
473
474 if (lphb_conf_req == NULL) {
475 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530476 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800477 }
478
479 ts_lphb_enable = &(lphb_conf_req->params.lphbEnableReq);
480 WMA_LOGI("%s: WMA --> WMI_HB_SET_ENABLE enable=%d, item=%d, session=%d",
481 __func__,
482 ts_lphb_enable->enable,
483 ts_lphb_enable->item, ts_lphb_enable->session);
484
485 if ((ts_lphb_enable->item != 1) && (ts_lphb_enable->item != 2)) {
486 WMA_LOGE("%s : LPHB configuration wrong item %d",
487 __func__, ts_lphb_enable->item);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530488 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800489 }
490
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800491
492 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530493 hb_enable_fp.vdev_id = ts_lphb_enable->session;
494 hb_enable_fp.enable = ts_lphb_enable->enable;
495 hb_enable_fp.item = ts_lphb_enable->item;
496 hb_enable_fp.session = ts_lphb_enable->session;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800497
Govind Singhaa64c242016-03-08 11:31:49 +0530498 status = wmi_unified_lphb_config_hbenable_cmd(wma_handle->wmi_handle,
499 &hb_enable_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800500 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530501 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800502 goto error;
503 }
504
505 if (by_user) {
506 /* target already configured, now cache command status */
507 if (ts_lphb_enable->enable) {
508 i = ts_lphb_enable->item - 1;
509 wma_handle->wow.lphb_cache[i].cmd
510 = LPHB_SET_EN_PARAMS_INDID;
511 wma_handle->wow.lphb_cache[i].params.lphbEnableReq.
512 enable = ts_lphb_enable->enable;
513 wma_handle->wow.lphb_cache[i].params.lphbEnableReq.
514 item = ts_lphb_enable->item;
515 wma_handle->wow.lphb_cache[i].params.lphbEnableReq.
516 session = ts_lphb_enable->session;
517
518 WMA_LOGI("%s: cached LPHB status in WMA context for item %d",
519 __func__, i);
520 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530521 qdf_mem_zero((void *)&wma_handle->wow.lphb_cache,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800522 sizeof(wma_handle->wow.lphb_cache));
523 WMA_LOGI("%s: cleared all cached LPHB status in WMA context",
524 __func__);
525 }
526 }
527
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530528 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800529error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530530 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800531}
532
533/**
534 * wma_lphb_conf_tcp_params() - set tcp params of LPHB configuration requests
535 * @wma_handle: wma handle
536 * @lphb_conf_req: lphb config request
537 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530538 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800539 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530540QDF_STATUS wma_lphb_conf_tcp_params(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800541 tSirLPHBReq *lphb_conf_req)
542{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530543 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800544 int status = 0;
545 tSirLPHBTcpParamStruct *ts_lphb_tcp_param;
Govind Singhaa64c242016-03-08 11:31:49 +0530546 wmi_hb_set_tcp_params_cmd_fixed_param hb_tcp_params_fp = {0};
547
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800548
549 if (lphb_conf_req == NULL) {
550 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530551 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800552 }
553
554 ts_lphb_tcp_param = &(lphb_conf_req->params.lphbTcpParamReq);
Srinivas Girigowda9dc32cf2015-11-19 14:47:04 -0800555 WMA_LOGI("%s: WMA --> WMI_HB_SET_TCP_PARAMS srv_ip=%08x, "
556 "dev_ip=%08x, src_port=%d, dst_port=%d, timeout=%d, "
557 "session=%d, gateway_mac="MAC_ADDRESS_STR", timePeriodSec=%d, "
558 "tcpSn=%d", __func__, ts_lphb_tcp_param->srv_ip,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800559 ts_lphb_tcp_param->dev_ip, ts_lphb_tcp_param->src_port,
560 ts_lphb_tcp_param->dst_port, ts_lphb_tcp_param->timeout,
Srinivas Girigowda9dc32cf2015-11-19 14:47:04 -0800561 ts_lphb_tcp_param->session,
562 MAC_ADDR_ARRAY(ts_lphb_tcp_param->gateway_mac.bytes),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800563 ts_lphb_tcp_param->timePeriodSec, ts_lphb_tcp_param->tcpSn);
564
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800565 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530566 hb_tcp_params_fp.vdev_id = ts_lphb_tcp_param->session;
567 hb_tcp_params_fp.srv_ip = ts_lphb_tcp_param->srv_ip;
568 hb_tcp_params_fp.dev_ip = ts_lphb_tcp_param->dev_ip;
569 hb_tcp_params_fp.seq = ts_lphb_tcp_param->tcpSn;
570 hb_tcp_params_fp.src_port = ts_lphb_tcp_param->src_port;
571 hb_tcp_params_fp.dst_port = ts_lphb_tcp_param->dst_port;
572 hb_tcp_params_fp.interval = ts_lphb_tcp_param->timePeriodSec;
573 hb_tcp_params_fp.timeout = ts_lphb_tcp_param->timeout;
574 hb_tcp_params_fp.session = ts_lphb_tcp_param->session;
Srinivas Girigowda9dc32cf2015-11-19 14:47:04 -0800575 WMI_CHAR_ARRAY_TO_MAC_ADDR(ts_lphb_tcp_param->gateway_mac.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +0530576 &hb_tcp_params_fp.gateway_mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800577
Govind Singhaa64c242016-03-08 11:31:49 +0530578 status = wmi_unified_lphb_config_tcp_params_cmd(wma_handle->wmi_handle,
579 &hb_tcp_params_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800580 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530581 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800582 goto error;
583 }
584
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530585 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800586error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530587 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800588}
589
590/**
591 * wma_lphb_conf_tcp_pkt_filter() - configure tcp packet filter command of LPHB
592 * @wma_handle: wma handle
593 * @lphb_conf_req: lphb config request
594 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530595 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800596 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530597QDF_STATUS wma_lphb_conf_tcp_pkt_filter(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800598 tSirLPHBReq *lphb_conf_req)
599{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530600 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800601 int status = 0;
602 tSirLPHBTcpFilterStruct *ts_lphb_tcp_filter;
Govind Singhaa64c242016-03-08 11:31:49 +0530603 wmi_hb_set_tcp_pkt_filter_cmd_fixed_param hb_tcp_filter_fp = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800604
605 if (lphb_conf_req == NULL) {
606 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530607 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800608 }
609
610 ts_lphb_tcp_filter = &(lphb_conf_req->params.lphbTcpFilterReq);
611 WMA_LOGI("%s: WMA --> WMI_HB_SET_TCP_PKT_FILTER length=%d, offset=%d, session=%d, "
612 "filter=%2x:%2x:%2x:%2x:%2x:%2x ...", __func__,
613 ts_lphb_tcp_filter->length, ts_lphb_tcp_filter->offset,
614 ts_lphb_tcp_filter->session, ts_lphb_tcp_filter->filter[0],
615 ts_lphb_tcp_filter->filter[1], ts_lphb_tcp_filter->filter[2],
616 ts_lphb_tcp_filter->filter[3], ts_lphb_tcp_filter->filter[4],
617 ts_lphb_tcp_filter->filter[5]);
618
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800619 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530620 hb_tcp_filter_fp.vdev_id = ts_lphb_tcp_filter->session;
621 hb_tcp_filter_fp.length = ts_lphb_tcp_filter->length;
622 hb_tcp_filter_fp.offset = ts_lphb_tcp_filter->offset;
623 hb_tcp_filter_fp.session = ts_lphb_tcp_filter->session;
624 memcpy((void *)&hb_tcp_filter_fp.filter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800625 (void *)&ts_lphb_tcp_filter->filter,
626 WMI_WLAN_HB_MAX_FILTER_SIZE);
627
Govind Singhaa64c242016-03-08 11:31:49 +0530628 status = wmi_unified_lphb_config_tcp_pkt_filter_cmd(wma_handle->wmi_handle,
629 &hb_tcp_filter_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800630 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530631 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800632 goto error;
633 }
634
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530635 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800636error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530637 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800638}
639
640/**
641 * wma_lphb_conf_udp_params() - configure udp param command of LPHB
642 * @wma_handle: wma handle
643 * @lphb_conf_req: lphb config request
644 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530645 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800646 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530647QDF_STATUS wma_lphb_conf_udp_params(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800648 tSirLPHBReq *lphb_conf_req)
649{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530650 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800651 int status = 0;
652 tSirLPHBUdpParamStruct *ts_lphb_udp_param;
Govind Singhaa64c242016-03-08 11:31:49 +0530653 wmi_hb_set_udp_params_cmd_fixed_param hb_udp_params_fp = {0};
654
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800655
656 if (lphb_conf_req == NULL) {
657 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530658 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800659 }
660
661 ts_lphb_udp_param = &(lphb_conf_req->params.lphbUdpParamReq);
662 WMA_LOGI("%s: WMA --> WMI_HB_SET_UDP_PARAMS srv_ip=%d, dev_ip=%d, src_port=%d, "
663 "dst_port=%d, interval=%d, timeout=%d, session=%d, "
Srinivas Girigowda9eddfda2015-11-19 14:38:02 -0800664 "gateway_mac="MAC_ADDRESS_STR, __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800665 ts_lphb_udp_param->srv_ip, ts_lphb_udp_param->dev_ip,
666 ts_lphb_udp_param->src_port, ts_lphb_udp_param->dst_port,
667 ts_lphb_udp_param->interval, ts_lphb_udp_param->timeout,
Srinivas Girigowda9eddfda2015-11-19 14:38:02 -0800668 ts_lphb_udp_param->session,
669 MAC_ADDR_ARRAY(ts_lphb_udp_param->gateway_mac.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800670
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800671
672 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530673 hb_udp_params_fp.vdev_id = ts_lphb_udp_param->session;
674 hb_udp_params_fp.srv_ip = ts_lphb_udp_param->srv_ip;
675 hb_udp_params_fp.dev_ip = ts_lphb_udp_param->dev_ip;
676 hb_udp_params_fp.src_port = ts_lphb_udp_param->src_port;
677 hb_udp_params_fp.dst_port = ts_lphb_udp_param->dst_port;
678 hb_udp_params_fp.interval = ts_lphb_udp_param->interval;
679 hb_udp_params_fp.timeout = ts_lphb_udp_param->timeout;
680 hb_udp_params_fp.session = ts_lphb_udp_param->session;
Srinivas Girigowda9eddfda2015-11-19 14:38:02 -0800681 WMI_CHAR_ARRAY_TO_MAC_ADDR(ts_lphb_udp_param->gateway_mac.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +0530682 &hb_udp_params_fp.gateway_mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800683
Govind Singhaa64c242016-03-08 11:31:49 +0530684 status = wmi_unified_lphb_config_udp_params_cmd(wma_handle->wmi_handle,
685 &hb_udp_params_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800686 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530687 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800688 goto error;
689 }
690
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530691 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800692error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530693 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800694}
695
696/**
697 * wma_lphb_conf_udp_pkt_filter() - configure udp pkt filter command of LPHB
698 * @wma_handle: wma handle
699 * @lphb_conf_req: lphb config request
700 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530701 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800702 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530703QDF_STATUS wma_lphb_conf_udp_pkt_filter(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800704 tSirLPHBReq *lphb_conf_req)
705{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530706 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800707 int status = 0;
708 tSirLPHBUdpFilterStruct *ts_lphb_udp_filter;
Govind Singhaa64c242016-03-08 11:31:49 +0530709 wmi_hb_set_udp_pkt_filter_cmd_fixed_param hb_udp_filter_fp = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800710
711 if (lphb_conf_req == NULL) {
712 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530713 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800714 }
715
716 ts_lphb_udp_filter = &(lphb_conf_req->params.lphbUdpFilterReq);
717 WMA_LOGI("%s: WMA --> WMI_HB_SET_UDP_PKT_FILTER length=%d, offset=%d, session=%d, "
718 "filter=%2x:%2x:%2x:%2x:%2x:%2x ...", __func__,
719 ts_lphb_udp_filter->length, ts_lphb_udp_filter->offset,
720 ts_lphb_udp_filter->session, ts_lphb_udp_filter->filter[0],
721 ts_lphb_udp_filter->filter[1], ts_lphb_udp_filter->filter[2],
722 ts_lphb_udp_filter->filter[3], ts_lphb_udp_filter->filter[4],
723 ts_lphb_udp_filter->filter[5]);
724
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800725
726 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530727 hb_udp_filter_fp.vdev_id = ts_lphb_udp_filter->session;
728 hb_udp_filter_fp.length = ts_lphb_udp_filter->length;
729 hb_udp_filter_fp.offset = ts_lphb_udp_filter->offset;
730 hb_udp_filter_fp.session = ts_lphb_udp_filter->session;
731 memcpy((void *)&hb_udp_filter_fp.filter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800732 (void *)&ts_lphb_udp_filter->filter,
733 WMI_WLAN_HB_MAX_FILTER_SIZE);
734
Govind Singhaa64c242016-03-08 11:31:49 +0530735 status = wmi_unified_lphb_config_udp_pkt_filter_cmd(wma_handle->wmi_handle,
736 &hb_udp_filter_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800737 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530738 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800739 goto error;
740 }
741
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530742 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800743error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530744 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800745}
746
747/**
748 * wma_process_lphb_conf_req() - handle LPHB configuration requests
749 * @wma_handle: wma handle
750 * @lphb_conf_req: lphb config request
751 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530752 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800753 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530754QDF_STATUS wma_process_lphb_conf_req(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800755 tSirLPHBReq *lphb_conf_req)
756{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530757 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800758
759 if (lphb_conf_req == NULL) {
760 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530761 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800762 }
763
764 WMA_LOGI("%s : LPHB configuration cmd id is %d", __func__,
765 lphb_conf_req->cmd);
766 switch (lphb_conf_req->cmd) {
767 case LPHB_SET_EN_PARAMS_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530768 qdf_status = wma_lphb_conf_hbenable(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800769 lphb_conf_req, true);
770 break;
771
772 case LPHB_SET_TCP_PARAMS_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530773 qdf_status = wma_lphb_conf_tcp_params(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800774 lphb_conf_req);
775 break;
776
777 case LPHB_SET_TCP_PKT_FILTER_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530778 qdf_status = wma_lphb_conf_tcp_pkt_filter(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800779 lphb_conf_req);
780 break;
781
782 case LPHB_SET_UDP_PARAMS_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530783 qdf_status = wma_lphb_conf_udp_params(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800784 lphb_conf_req);
785 break;
786
787 case LPHB_SET_UDP_PKT_FILTER_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530788 qdf_status = wma_lphb_conf_udp_pkt_filter(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800789 lphb_conf_req);
790 break;
791
792 case LPHB_SET_NETWORK_INFO_INDID:
793 default:
794 break;
795 }
796
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530797 qdf_mem_free(lphb_conf_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530798 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800799}
800#endif /* FEATURE_WLAN_LPHB */
801
802/**
803 * wma_process_dhcp_ind() - process dhcp indication from SME
804 * @wma_handle: wma handle
805 * @ta_dhcp_ind: DHCP indication
806 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530807 * Return: QDF Status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800808 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530809QDF_STATUS wma_process_dhcp_ind(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800810 tAniDHCPInd *ta_dhcp_ind)
811{
812 uint8_t vdev_id;
813 int status = 0;
Govind Singhaa64c242016-03-08 11:31:49 +0530814 wmi_peer_set_param_cmd_fixed_param peer_set_param_fp = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800815
816 if (!ta_dhcp_ind) {
817 WMA_LOGE("%s : DHCP indication is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530818 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800819 }
820
Srinivas Girigowda296105a2015-09-24 16:31:16 -0700821 if (!wma_find_vdev_by_addr(wma_handle,
822 ta_dhcp_ind->adapterMacAddr.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800823 &vdev_id)) {
824 WMA_LOGE("%s: Failed to find vdev id for DHCP indication",
825 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530826 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800827 }
828
829 WMA_LOGI("%s: WMA --> WMI_PEER_SET_PARAM triggered by DHCP, "
830 "msgType=%s,"
831 "device_mode=%d, macAddr=" MAC_ADDRESS_STR,
832 __func__,
833 ta_dhcp_ind->msgType == WMA_DHCP_START_IND ?
834 "WMA_DHCP_START_IND" : "WMA_DHCP_STOP_IND",
835 ta_dhcp_ind->device_mode,
Srinivas Girigowda296105a2015-09-24 16:31:16 -0700836 MAC_ADDR_ARRAY(ta_dhcp_ind->peerMacAddr.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800837
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800838 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530839 peer_set_param_fp.vdev_id = vdev_id;
840 peer_set_param_fp.param_id = WMI_PEER_CRIT_PROTO_HINT_ENABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800841 if (WMA_DHCP_START_IND == ta_dhcp_ind->msgType)
Govind Singhaa64c242016-03-08 11:31:49 +0530842 peer_set_param_fp.param_value = 1;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800843 else
Govind Singhaa64c242016-03-08 11:31:49 +0530844 peer_set_param_fp.param_value = 0;
Srinivas Girigowda296105a2015-09-24 16:31:16 -0700845 WMI_CHAR_ARRAY_TO_MAC_ADDR(ta_dhcp_ind->peerMacAddr.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +0530846 &peer_set_param_fp.peer_macaddr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800847
Govind Singhaa64c242016-03-08 11:31:49 +0530848 status = wmi_unified_process_dhcp_ind(wma_handle->wmi_handle,
849 &peer_set_param_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800850 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530851 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800852 }
853
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530854 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800855}
856
857/**
858 * wma_chan_to_mode() - convert channel to phy mode
859 * @chan: channel number
860 * @chan_width: channel width
861 * @vht_capable: vht capable
862 * @dot11_mode: 802.11 mode
863 *
864 * Return: return phy mode
865 */
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800866WLAN_PHY_MODE wma_chan_to_mode(u8 chan, enum phy_ch_width chan_width,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800867 u8 vht_capable, u8 dot11_mode)
868{
869 WLAN_PHY_MODE phymode = MODE_UNKNOWN;
870
871 /* 2.4 GHz band */
872 if ((chan >= WMA_11G_CHANNEL_BEGIN) && (chan <= WMA_11G_CHANNEL_END)) {
873 switch (chan_width) {
874 case CH_WIDTH_20MHZ:
875 /* In case of no channel bonding, use dot11_mode
876 * to set phy mode
877 */
878 switch (dot11_mode) {
879 case WNI_CFG_DOT11_MODE_11A:
880 phymode = MODE_11A;
881 break;
882 case WNI_CFG_DOT11_MODE_11B:
883 phymode = MODE_11B;
884 break;
885 case WNI_CFG_DOT11_MODE_11G:
886 phymode = MODE_11G;
887 break;
888 case WNI_CFG_DOT11_MODE_11G_ONLY:
889 phymode = MODE_11GONLY;
890 break;
891 default:
892 /* Configure MODE_11NG_HT20 for
893 * self vdev(for vht too)
894 */
895 phymode = MODE_11NG_HT20;
896 break;
897 }
898 break;
899 case CH_WIDTH_40MHZ:
900 phymode = vht_capable ? MODE_11AC_VHT40 :
901 MODE_11NG_HT40;
902 break;
903 default:
904 break;
905 }
906 }
907
908 /* 5 GHz band */
909 if ((chan >= WMA_11A_CHANNEL_BEGIN) && (chan <= WMA_11A_CHANNEL_END)) {
910 switch (chan_width) {
911 case CH_WIDTH_20MHZ:
912 phymode = vht_capable ? MODE_11AC_VHT20 :
913 MODE_11NA_HT20;
914 break;
915 case CH_WIDTH_40MHZ:
916 phymode = vht_capable ? MODE_11AC_VHT40 :
917 MODE_11NA_HT40;
918 break;
919 case CH_WIDTH_80MHZ:
920 phymode = MODE_11AC_VHT80;
921 break;
922#if CONFIG_160MHZ_SUPPORT != 0
923 case CH_WIDTH_160MHZ:
924 phymode = MODE_11AC_VHT160;
925 break;
926 case CH_WIDTH_80P80MHZ:
927 phymode = MODE_11AC_VHT80_80;
928 break;
929#endif
930
931 default:
932 break;
933 }
934 }
935
936 /* 5.9 GHz Band */
937 if ((chan >= WMA_11P_CHANNEL_BEGIN) && (chan <= WMA_11P_CHANNEL_END))
938 /* Only Legacy Modulation Schemes are supported */
939 phymode = MODE_11A;
940
941 WMA_LOGD("%s: phymode %d channel %d ch_width %d vht_capable %d "
942 "dot11_mode %d", __func__, phymode, chan,
943 chan_width, vht_capable, dot11_mode);
944
945 return phymode;
946}
947
948/**
949 * wma_get_link_speed() -send command to get linkspeed
950 * @handle: wma handle
951 * @pLinkSpeed: link speed info
952 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530953 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800954 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530955QDF_STATUS wma_get_link_speed(WMA_HANDLE handle, tSirLinkSpeedInfo *pLinkSpeed)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800956{
957 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhaa64c242016-03-08 11:31:49 +0530958 wmi_mac_addr peer_macaddr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800959
960 if (!wma_handle || !wma_handle->wmi_handle) {
961 WMA_LOGE("%s: WMA is closed, can not issue get link speed cmd",
962 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530963 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800964 }
965 if (!WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap,
966 WMI_SERVICE_ESTIMATE_LINKSPEED)) {
967 WMA_LOGE("%s: Linkspeed feature bit not enabled"
968 " Sending value 0 as link speed.", __func__);
969 wma_send_link_speed(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530970 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800971 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800972
973 /* Copy the peer macaddress to the wma buffer */
Srinivas Girigowdadccab9a2015-11-19 14:31:14 -0800974 WMI_CHAR_ARRAY_TO_MAC_ADDR(pLinkSpeed->peer_macaddr.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +0530975 &peer_macaddr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800976
977 WMA_LOGD("%s: pLinkSpeed->peerMacAddr: %pM, "
978 "peer_macaddr.mac_addr31to0: 0x%x, peer_macaddr.mac_addr47to32: 0x%x",
Srinivas Girigowdadccab9a2015-11-19 14:31:14 -0800979 __func__, pLinkSpeed->peer_macaddr.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +0530980 peer_macaddr.mac_addr31to0,
981 peer_macaddr.mac_addr47to32);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800982
Govind Singhaa64c242016-03-08 11:31:49 +0530983 if (wmi_unified_get_link_speed_cmd(wma_handle->wmi_handle,
984 peer_macaddr)) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530985 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800986 }
Govind Singhaa64c242016-03-08 11:31:49 +0530987
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530988 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800989}
990
Gupta, Kapil4cb1d7d2016-04-16 18:16:25 -0700991/**
992* wma_add_beacon_filter() - Issue WMI command to set beacon filter
993* @wma: wma handler
994* @filter_params: beacon_filter_param to set
995*
996* Return: Return QDF_STATUS
997*/
998QDF_STATUS wma_add_beacon_filter(WMA_HANDLE handle,
999 struct beacon_filter_param *filter_params)
1000{
1001 int i;
1002 wmi_buf_t wmi_buf;
1003 u_int8_t *buf;
1004 A_UINT32 *ie_map;
1005 int ret;
1006 tp_wma_handle wma = (tp_wma_handle) handle;
1007 wmi_add_bcn_filter_cmd_fixed_param *cmd;
1008 int len = sizeof(wmi_add_bcn_filter_cmd_fixed_param);
1009
1010 len += WMI_TLV_HDR_SIZE;
1011 len += BCN_FLT_MAX_ELEMS_IE_LIST*sizeof(A_UINT32);
1012
1013 if (!wma || !wma->wmi_handle) {
1014 WMA_LOGE("%s: WMA is closed, can not issue set beacon filter",
1015 __func__);
1016 return QDF_STATUS_E_INVAL;
1017 }
1018
1019 wmi_buf = wmi_buf_alloc(wma->wmi_handle, len);
1020 if (!wmi_buf) {
1021 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
1022 return QDF_STATUS_E_NOMEM;
1023 }
1024
1025 buf = (u_int8_t *) wmi_buf_data(wmi_buf);
1026
1027 cmd = (wmi_add_bcn_filter_cmd_fixed_param *)wmi_buf_data(wmi_buf);
1028 cmd->vdev_id = filter_params->vdev_id;
1029
1030 WMITLV_SET_HDR(&cmd->tlv_header,
1031 WMITLV_TAG_STRUC_wmi_add_bcn_filter_cmd_fixed_param,
1032 WMITLV_GET_STRUCT_TLVLEN(
1033 wmi_add_bcn_filter_cmd_fixed_param));
1034
1035 buf += sizeof(wmi_add_bcn_filter_cmd_fixed_param);
1036
1037 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_UINT32,
1038 (BCN_FLT_MAX_ELEMS_IE_LIST * sizeof(u_int32_t)));
1039
1040 ie_map = (A_UINT32 *)(buf + WMI_TLV_HDR_SIZE);
1041 for (i = 0; i < BCN_FLT_MAX_ELEMS_IE_LIST; i++) {
1042 ie_map[i] = filter_params->ie_map[i];
1043 WMA_LOGD("beacon filter ie map = %u", ie_map[i]);
1044 }
1045
1046 ret = wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len,
1047 WMI_ADD_BCN_FILTER_CMDID);
1048 if (ret) {
1049 WMA_LOGE("Failed to send wmi add beacon filter = %d",
1050 ret);
1051 wmi_buf_free(wmi_buf);
1052 return QDF_STATUS_E_FAILURE;
1053 }
1054 WMA_LOGD("added beacon filter = %d", ret);
1055
1056 return QDF_STATUS_SUCCESS;
1057}
1058
1059/**
1060* wma_remove_beacon_filter() - Issue WMI command to remove beacon filter
1061* @wma: wma handler
1062* @filter_params: beacon_filter_params
1063*
1064* Return: Return QDF_STATUS
1065*/
1066QDF_STATUS wma_remove_beacon_filter(WMA_HANDLE handle,
1067 struct beacon_filter_param *filter_params)
1068{
1069 wmi_buf_t buf;
1070 tp_wma_handle wma = (tp_wma_handle) handle;
1071 wmi_rmv_bcn_filter_cmd_fixed_param *cmd;
1072 int len = sizeof(wmi_rmv_bcn_filter_cmd_fixed_param);
1073 int ret;
1074
1075 if (!wma || !wma->wmi_handle) {
1076 WMA_LOGE("%s: WMA is closed, cannot issue remove beacon filter",
1077 __func__);
1078 return QDF_STATUS_E_INVAL;
1079 }
1080
1081 buf = wmi_buf_alloc(wma->wmi_handle, len);
1082 if (!buf) {
1083 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
1084 return QDF_STATUS_E_NOMEM;
1085 }
1086 cmd = (wmi_rmv_bcn_filter_cmd_fixed_param *)wmi_buf_data(buf);
1087 cmd->vdev_id = filter_params->vdev_id;
1088
1089 WMITLV_SET_HDR(&cmd->tlv_header,
1090 WMITLV_TAG_STRUC_wmi_rmv_bcn_filter_cmd_fixed_param,
1091 WMITLV_GET_STRUCT_TLVLEN(
1092 wmi_rmv_bcn_filter_cmd_fixed_param));
1093
1094 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
1095 WMI_RMV_BCN_FILTER_CMDID);
1096 if (ret) {
1097 WMA_LOGE("Failed to send wmi remove beacon filter = %d",
1098 ret);
1099 wmi_buf_free(buf);
1100 return QDF_STATUS_E_FAILURE;
1101 }
1102 WMA_LOGD("removed beacon filter = %d", ret);
1103
1104 return QDF_STATUS_SUCCESS;
1105}
1106
1107
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001108#ifdef FEATURE_GREEN_AP
1109
1110/**
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001111 * wma_egap_info_status_event() - egap info status event
1112 * @handle: pointer to wma handler
1113 * @event: pointer to event
1114 * @len: len of the event
1115 *
1116 * Return: 0 for success, otherwise appropriate error code
1117 */
1118static int wma_egap_info_status_event(void *handle, u_int8_t *event,
1119 uint32_t len)
1120{
1121 WMI_TX_PAUSE_EVENTID_param_tlvs *param_buf;
1122 wmi_ap_ps_egap_info_event_fixed_param *egap_info_event;
1123 wmi_ap_ps_egap_info_chainmask_list *chainmask_event;
1124 u_int8_t *buf_ptr;
1125
1126 param_buf = (WMI_TX_PAUSE_EVENTID_param_tlvs *)event;
1127 if (!param_buf) {
1128 WMA_LOGE("Invalid EGAP Info status event buffer");
1129 return -EINVAL;
1130 }
1131
1132 egap_info_event = (wmi_ap_ps_egap_info_event_fixed_param *)
1133 param_buf->fixed_param;
1134 buf_ptr = (uint8_t *)egap_info_event;
1135 buf_ptr += sizeof(wmi_ap_ps_egap_info_event_fixed_param);
1136 chainmask_event = (wmi_ap_ps_egap_info_chainmask_list *)buf_ptr;
1137
1138 WMA_LOGI("mac_id: %d, status: %d, tx_mask: %x, rx_mask: %d",
1139 chainmask_event->mac_id,
1140 egap_info_event->status,
1141 chainmask_event->tx_chainmask,
1142 chainmask_event->rx_chainmask);
1143 return 0;
1144}
1145
1146/**
1147 * wma_send_egap_conf_params() - send wmi cmd of egap configuration params
1148 * @wma_handle: wma handler
1149 * @egap_params: pointer to egap_params
1150 *
1151 * Return: 0 for success, otherwise appropriate error code
1152 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301153QDF_STATUS wma_send_egap_conf_params(WMA_HANDLE handle,
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001154 struct egap_conf_params *egap_params)
1155{
1156 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhaa64c242016-03-08 11:31:49 +05301157 wmi_ap_ps_egap_param_cmd_fixed_param cmd = {0};
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001158 int32_t err;
1159
Govind Singhaa64c242016-03-08 11:31:49 +05301160 cmd.enable = egap_params->enable;
1161 cmd.inactivity_time = egap_params->inactivity_time;
1162 cmd.wait_time = egap_params->wait_time;
1163 cmd.flags = egap_params->flags;
1164 err = wmi_unified_egap_conf_params_cmd(wma_handle->wmi_handle, &cmd);
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001165 if (err) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301166 return QDF_STATUS_E_FAILURE;
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001167 }
Govind Singhaa64c242016-03-08 11:31:49 +05301168
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301169 return QDF_STATUS_SUCCESS;
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001170}
1171
1172/**
1173 * wma_setup_egap_support() - setup the EGAP support flag
1174 * @tgt_cfg: pointer to hdd target configuration
1175 * @egap_support: EGAP support flag
1176 *
1177 * Return: None
1178 */
1179void wma_setup_egap_support(struct wma_tgt_cfg *tgt_cfg, WMA_HANDLE handle)
1180{
1181 tp_wma_handle wma_handle = (tp_wma_handle) handle;
1182
1183 if (tgt_cfg && wma_handle)
1184 tgt_cfg->egap_support = wma_handle->egap_support;
1185}
1186
1187/**
1188 * wma_register_egap_event_handle() - register the EGAP event handle
1189 * @wma_handle: wma handler
1190 *
1191 * Return: None
1192 */
1193void wma_register_egap_event_handle(WMA_HANDLE handle)
1194{
1195 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhd76a5b02016-03-08 15:12:14 +05301196 QDF_STATUS status;
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001197
1198 if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap,
1199 WMI_SERVICE_EGAP)) {
1200 status = wmi_unified_register_event_handler(
1201 wma_handle->wmi_handle,
1202 WMI_AP_PS_EGAP_INFO_EVENTID,
Govind Singhd76a5b02016-03-08 15:12:14 +05301203 wma_egap_info_status_event,
1204 WMA_RX_SERIALIZER_CTX);
1205 if (QDF_IS_STATUS_ERROR(status)) {
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001206 WMA_LOGE("Failed to register Enhance Green AP event");
1207 wma_handle->egap_support = false;
1208 } else {
1209 WMA_LOGI("Set the Enhance Green AP event handler");
1210 wma_handle->egap_support = true;
1211 }
1212 } else
1213 wma_handle->egap_support = false;
1214}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001215#endif /* FEATURE_GREEN_AP */
1216
Govind Singha471e5e2015-10-12 17:11:14 +05301217/**
Govind Singhaa64c242016-03-08 11:31:49 +05301218 * wma_unified_fw_profiling_cmd() - send FW profiling cmd to WLAN FW
Govind Singha471e5e2015-10-12 17:11:14 +05301219 * @wma: wma handle
1220 * @cmd: Profiling command index
1221 * @value1: parameter1 value
1222 * @value2: parameter2 value
1223 *
1224 * Return: 0 for success else error code
1225 */
Govind Singhaa64c242016-03-08 11:31:49 +05301226QDF_STATUS wma_unified_fw_profiling_cmd(wmi_unified_t wmi_handle,
Govind Singha471e5e2015-10-12 17:11:14 +05301227 uint32_t cmd, uint32_t value1, uint32_t value2)
1228{
Govind Singha471e5e2015-10-12 17:11:14 +05301229 int ret;
Govind Singha471e5e2015-10-12 17:11:14 +05301230
Govind Singhaa64c242016-03-08 11:31:49 +05301231 ret = wmi_unified_fw_profiling_data_cmd(wmi_handle, cmd,
1232 value1, value2);
1233 if (ret) {
1234 WMA_LOGE("enable cmd Failed for id %d value %d",
1235 value1, value2);
1236 return ret;
Govind Singha471e5e2015-10-12 17:11:14 +05301237 }
1238
Govind Singhaa64c242016-03-08 11:31:49 +05301239 return QDF_STATUS_SUCCESS;
Govind Singha471e5e2015-10-12 17:11:14 +05301240}
1241
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001242#ifdef FEATURE_WLAN_LPHB
1243/**
1244 * wma_lphb_handler() - send LPHB indication to SME
1245 * @wma: wma handle
1246 * @event: event handler
1247 *
1248 * Return: 0 for success or error code
1249 */
1250static int wma_lphb_handler(tp_wma_handle wma, uint8_t *event)
1251{
1252 wmi_hb_ind_event_fixed_param *hb_fp;
1253 tSirLPHBInd *slphb_indication;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301254 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001255 cds_msg_t sme_msg = { 0 };
1256
1257 hb_fp = (wmi_hb_ind_event_fixed_param *) event;
1258 if (!hb_fp) {
1259 WMA_LOGE("Invalid wmi_hb_ind_event_fixed_param buffer");
1260 return -EINVAL;
1261 }
1262
1263 WMA_LOGD("lphb indication received with vdev_id=%d, session=%d, reason=%d",
1264 hb_fp->vdev_id, hb_fp->session, hb_fp->reason);
1265
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301266 slphb_indication = (tSirLPHBInd *) qdf_mem_malloc(sizeof(tSirLPHBInd));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001267
1268 if (!slphb_indication) {
1269 WMA_LOGE("Invalid LPHB indication buffer");
1270 return -ENOMEM;
1271 }
1272
1273 slphb_indication->sessionIdx = hb_fp->session;
1274 slphb_indication->protocolType = hb_fp->reason;
1275 slphb_indication->eventReason = hb_fp->reason;
1276
1277 sme_msg.type = eWNI_SME_LPHB_IND;
1278 sme_msg.bodyptr = slphb_indication;
1279 sme_msg.bodyval = 0;
1280
Anurag Chouhan6d760662016-02-20 16:05:43 +05301281 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301282 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001283 WMA_LOGE("Fail to post eWNI_SME_LPHB_IND msg to SME");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301284 qdf_mem_free(slphb_indication);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001285 return -EINVAL;
1286 }
1287
1288 return 0;
1289}
1290#endif /* FEATURE_WLAN_LPHB */
1291
1292#ifdef FEATURE_WLAN_RA_FILTERING
1293/**
1294 * wma_wow_sta_ra_filter() - set RA filter pattern in fw
1295 * @wma: wma handle
1296 * @vdev_id: vdev id
1297 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05301298 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001299 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301300static QDF_STATUS wma_wow_sta_ra_filter(tp_wma_handle wma, uint8_t vdev_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001301{
1302
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001303 struct wma_txrx_node *iface;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001304 int ret;
Govind Singhaa64c242016-03-08 11:31:49 +05301305 uint8_t default_pattern;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001306
1307 iface = &wma->interfaces[vdev_id];
1308
Govind Singhaa64c242016-03-08 11:31:49 +05301309 default_pattern = iface->num_wow_default_patterns++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001310
1311 WMA_LOGD("%s: send RA rate limit [%d] to fw vdev = %d", __func__,
1312 wma->RArateLimitInterval, vdev_id);
1313
Govind Singhaa64c242016-03-08 11:31:49 +05301314 ret = wmi_unified_wow_sta_ra_filter_cmd(wma->wmi_handle, vdev_id,
1315 default_pattern, wma->RArateLimitInterval);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001316 if (ret) {
1317 WMA_LOGE("%s: Failed to send RA rate limit to fw", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001318 iface->num_wow_default_patterns--;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301319 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001320 }
1321
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301322 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001323
1324}
1325#endif /* FEATURE_WLAN_RA_FILTERING */
1326
1327/**
1328 * wmi_unified_nat_keepalive_enable() - enable NAT keepalive filter
1329 * @wma: wma handle
1330 * @vdev_id: vdev id
1331 *
1332 * Return: 0 for success or error code
1333 */
1334int wmi_unified_nat_keepalive_enable(tp_wma_handle wma, uint8_t vdev_id)
1335{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001336
Govind Singhaa64c242016-03-08 11:31:49 +05301337 if (wmi_unified_nat_keepalive_en_cmd(wma->wmi_handle, vdev_id))
1338 return QDF_STATUS_E_FAILURE;
1339
1340 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001341}
1342
1343/**
Govind Singhd76a5b02016-03-08 15:12:14 +05301344 * wma_unified_csa_offload_enable() - sen CSA offload enable command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001345 * @wma: wma handle
1346 * @vdev_id: vdev id
1347 *
1348 * Return: 0 for success or error code
1349 */
Govind Singhd76a5b02016-03-08 15:12:14 +05301350int wma_unified_csa_offload_enable(tp_wma_handle wma, uint8_t vdev_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001351{
Govind Singhaa64c242016-03-08 11:31:49 +05301352 if (wmi_unified_csa_offload_enable(wma->wmi_handle,
1353 vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001354 WMA_LOGP("%s: Failed to send CSA offload enable command",
1355 __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001356 return -EIO;
1357 }
Govind Singhaa64c242016-03-08 11:31:49 +05301358
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001359 return 0;
1360}
1361
1362#ifdef WLAN_FEATURE_NAN
1363/**
1364 * wma_nan_rsp_event_handler() - Function is used to handle nan response
1365 * @handle: wma handle
1366 * @event_buf: event buffer
1367 * @len: length of buffer
1368 *
1369 * Return: 0 for success or error code
1370 */
1371int wma_nan_rsp_event_handler(void *handle, uint8_t *event_buf,
1372 uint32_t len)
1373{
1374 WMI_NAN_EVENTID_param_tlvs *param_buf;
1375 tSirNanEvent *nan_rsp_event;
1376 wmi_nan_event_hdr *nan_rsp_event_hdr;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301377 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001378 cds_msg_t cds_msg;
1379 uint8_t *buf_ptr;
1380 uint32_t alloc_len;
1381
1382 /*
1383 * This is how received event_buf looks like
1384 *
1385 * <-------------------- event_buf ----------------------------------->
1386 *
1387 * <--wmi_nan_event_hdr--><---WMI_TLV_HDR_SIZE---><----- data -------->
1388 *
1389 * +-----------+---------+-----------------------+--------------------+
1390 * | tlv_header| data_len| WMITLV_TAG_ARRAY_BYTE | nan_rsp_event_data |
1391 * +-----------+---------+-----------------------+--------------------+
1392 */
1393
1394 WMA_LOGD("%s: Posting NaN response event to SME", __func__);
1395 param_buf = (WMI_NAN_EVENTID_param_tlvs *) event_buf;
1396 if (!param_buf) {
1397 WMA_LOGE("%s: Invalid nan response event buf", __func__);
1398 return -EINVAL;
1399 }
1400 nan_rsp_event_hdr = param_buf->fixed_param;
1401 buf_ptr = (uint8_t *) nan_rsp_event_hdr;
1402 alloc_len = sizeof(tSirNanEvent);
1403 alloc_len += nan_rsp_event_hdr->data_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301404 nan_rsp_event = (tSirNanEvent *) qdf_mem_malloc(alloc_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001405 if (NULL == nan_rsp_event) {
1406 WMA_LOGE("%s: Memory allocation failure", __func__);
1407 return -ENOMEM;
1408 }
1409
1410 nan_rsp_event->event_data_len = nan_rsp_event_hdr->data_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301411 qdf_mem_copy(nan_rsp_event->event_data, buf_ptr +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001412 sizeof(wmi_nan_event_hdr) + WMI_TLV_HDR_SIZE,
1413 nan_rsp_event->event_data_len);
1414 cds_msg.type = eWNI_SME_NAN_EVENT;
1415 cds_msg.bodyptr = (void *)nan_rsp_event;
1416 cds_msg.bodyval = 0;
1417
1418 status = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301419 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001420 WMA_LOGE("%s: Failed to post NaN response event to SME",
1421 __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301422 qdf_mem_free(nan_rsp_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001423 return -EFAULT;
1424 }
1425 WMA_LOGD("%s: NaN response event Posted to SME", __func__);
1426 return 0;
1427}
1428#endif /* WLAN_FEATURE_NAN */
1429
1430/**
1431 * wma_csa_offload_handler() - CSA event handler
1432 * @handle: wma handle
1433 * @event: event buffer
1434 * @len: buffer length
1435 *
1436 * This event is sent by firmware when it receives CSA IE.
1437 *
1438 * Return: 0 for success or error code
1439 */
1440int wma_csa_offload_handler(void *handle, uint8_t *event, uint32_t len)
1441{
1442 tp_wma_handle wma = (tp_wma_handle) handle;
1443 WMI_CSA_HANDLING_EVENTID_param_tlvs *param_buf;
1444 wmi_csa_event_fixed_param *csa_event;
1445 uint8_t bssid[IEEE80211_ADDR_LEN];
1446 uint8_t vdev_id = 0;
1447 uint8_t cur_chan = 0;
1448 struct ieee80211_channelswitch_ie *csa_ie;
Chandrasekaran, Manishekar5c19dc52016-02-04 14:58:26 +05301449 struct csa_offload_params *csa_offload_event;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001450 struct ieee80211_extendedchannelswitch_ie *xcsa_ie;
1451 struct ieee80211_ie_wide_bw_switch *wb_ie;
1452 struct wma_txrx_node *intr = wma->interfaces;
1453
1454 param_buf = (WMI_CSA_HANDLING_EVENTID_param_tlvs *) event;
1455
1456 WMA_LOGD("%s: Enter", __func__);
1457 if (!param_buf) {
1458 WMA_LOGE("Invalid csa event buffer");
1459 return -EINVAL;
1460 }
1461 csa_event = param_buf->fixed_param;
1462 WMI_MAC_ADDR_TO_CHAR_ARRAY(&csa_event->i_addr2, &bssid[0]);
1463
1464 if (wma_find_vdev_by_bssid(wma, bssid, &vdev_id) == NULL) {
1465 WMA_LOGE("Invalid bssid received %s:%d", __func__, __LINE__);
1466 return -EINVAL;
1467 }
1468
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301469 csa_offload_event = qdf_mem_malloc(sizeof(*csa_offload_event));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001470 if (!csa_offload_event) {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05301471 WMA_LOGE("QDF MEM Alloc Failed for csa_offload_event");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001472 return -EINVAL;
1473 }
1474
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301475 qdf_mem_zero(csa_offload_event, sizeof(*csa_offload_event));
1476 qdf_mem_copy(csa_offload_event->bssId, &bssid, IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001477
1478 if (csa_event->ies_present_flag & WMI_CSA_IE_PRESENT) {
1479 csa_ie = (struct ieee80211_channelswitch_ie *)
1480 (&csa_event->csa_ie[0]);
1481 csa_offload_event->channel = csa_ie->newchannel;
Chandrasekaran, Manishekar5c19dc52016-02-04 14:58:26 +05301482 csa_offload_event->switch_mode = csa_ie->switchmode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001483 } else if (csa_event->ies_present_flag & WMI_XCSA_IE_PRESENT) {
1484 xcsa_ie = (struct ieee80211_extendedchannelswitch_ie *)
1485 (&csa_event->xcsa_ie[0]);
1486 csa_offload_event->channel = xcsa_ie->newchannel;
Chandrasekaran, Manishekar5c19dc52016-02-04 14:58:26 +05301487 csa_offload_event->switch_mode = xcsa_ie->switchmode;
Gupta, Kapil121bf212015-11-25 19:21:29 +05301488 csa_offload_event->new_op_class = xcsa_ie->newClass;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001489 } else {
1490 WMA_LOGE("CSA Event error: No CSA IE present");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301491 qdf_mem_free(csa_offload_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001492 return -EINVAL;
1493 }
1494
1495 if (csa_event->ies_present_flag & WMI_WBW_IE_PRESENT) {
1496 wb_ie = (struct ieee80211_ie_wide_bw_switch *)
1497 (&csa_event->wb_ie[0]);
1498 csa_offload_event->new_ch_width = wb_ie->new_ch_width;
1499 csa_offload_event->new_ch_freq_seg1 = wb_ie->new_ch_freq_seg1;
1500 csa_offload_event->new_ch_freq_seg2 = wb_ie->new_ch_freq_seg2;
1501 }
1502
1503 csa_offload_event->ies_present_flag = csa_event->ies_present_flag;
1504
1505 WMA_LOGD("CSA: New Channel = %d BSSID:%pM",
1506 csa_offload_event->channel, csa_offload_event->bssId);
1507
1508 cur_chan = cds_freq_to_chan(intr[vdev_id].mhz);
1509 /*
1510 * basic sanity check: requested channel should not be 0
1511 * and equal to home channel
1512 */
1513 if ((0 == csa_offload_event->channel) ||
1514 (cur_chan == csa_offload_event->channel)) {
1515 WMA_LOGE("CSA Event with channel %d. Ignore !!",
1516 csa_offload_event->channel);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301517 qdf_mem_free(csa_offload_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001518 return -EINVAL;
1519 }
1520 wma->interfaces[vdev_id].is_channel_switch = true;
1521 wma_send_msg(wma, WMA_CSA_OFFLOAD_EVENT, (void *)csa_offload_event, 0);
1522 return 0;
1523}
1524
1525#ifdef FEATURE_OEM_DATA_SUPPORT
1526
1527/**
1528 * wma_oem_capability_event_callback() - OEM capability event handler
1529 * @handle: wma handle
1530 * @datap: data ptr
1531 * @len: data length
1532 *
1533 * Return: 0 for success or error code
1534 */
1535int wma_oem_capability_event_callback(void *handle,
1536 uint8_t *datap, uint32_t len)
1537{
1538 tp_wma_handle wma = (tp_wma_handle) handle;
1539 WMI_OEM_CAPABILITY_EVENTID_param_tlvs *param_buf;
1540 uint8_t *data;
1541 uint32_t datalen;
1542 uint32_t *msg_subtype;
1543 tStartOemDataRsp *pStartOemDataRsp;
1544
1545 param_buf = (WMI_OEM_CAPABILITY_EVENTID_param_tlvs *) datap;
1546 if (!param_buf) {
1547 WMA_LOGE("%s: Received NULL buf ptr from FW", __func__);
1548 return -ENOMEM;
1549 }
1550
1551 data = param_buf->data;
1552 datalen = param_buf->num_data;
1553
1554 if (!data) {
1555 WMA_LOGE("%s: Received NULL data from FW", __func__);
1556 return -EINVAL;
1557 }
1558
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001559 /*
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001560 * wma puts 4 bytes prefix for msg subtype, so length
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001561 * of data received from target should be 4 bytes less
1562 * then max allowed
1563 */
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001564 if (datalen > (OEM_DATA_RSP_SIZE - OEM_MESSAGE_SUBTYPE_LEN)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001565 WMA_LOGE("%s: Received data len (%d) exceeds max value (%d)",
1566 __func__, datalen, (OEM_DATA_RSP_SIZE - 4));
1567 return -EINVAL;
1568 }
1569
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301570 pStartOemDataRsp = qdf_mem_malloc(sizeof(*pStartOemDataRsp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001571 if (!pStartOemDataRsp) {
1572 WMA_LOGE("%s: Failed to alloc pStartOemDataRsp", __func__);
1573 return -ENOMEM;
1574 }
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001575
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001576 pStartOemDataRsp->rsp_len = datalen + OEM_MESSAGE_SUBTYPE_LEN;
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001577 if (pStartOemDataRsp->rsp_len) {
1578 pStartOemDataRsp->oem_data_rsp =
1579 qdf_mem_malloc(pStartOemDataRsp->rsp_len);
1580 if (!pStartOemDataRsp->oem_data_rsp) {
1581 WMA_LOGE(FL("malloc failed for oem_data_rsp"));
1582 qdf_mem_free(pStartOemDataRsp);
1583 return -ENOMEM;
1584 }
1585 } else {
1586 WMA_LOGE(FL("Invalid rsp length: %d"),
1587 pStartOemDataRsp->rsp_len);
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001588 qdf_mem_free(pStartOemDataRsp);
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001589 return -EINVAL;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001590 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001591
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001592 pStartOemDataRsp->target_rsp = true;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001593 msg_subtype = (uint32_t *) pStartOemDataRsp->oem_data_rsp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001594 *msg_subtype = WMI_OEM_CAPABILITY_RSP;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001595 /* copy data after msg sub type */
1596 qdf_mem_copy(pStartOemDataRsp->oem_data_rsp + OEM_MESSAGE_SUBTYPE_LEN,
1597 data, datalen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001598
1599 WMA_LOGI("%s: Sending WMA_START_OEM_DATA_RSP, data len (%d)",
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001600 __func__, pStartOemDataRsp->rsp_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001601
1602 wma_send_msg(wma, WMA_START_OEM_DATA_RSP, (void *)pStartOemDataRsp, 0);
1603 return 0;
1604}
1605
1606/**
1607 * wma_oem_measurement_report_event_callback() - OEM measurement report handler
1608 * @handle: wma handle
1609 * @datap: data ptr
1610 * @len: data length
1611 *
1612 * Return: 0 for success or error code
1613 */
1614int wma_oem_measurement_report_event_callback(void *handle,
1615 uint8_t *datap,
1616 uint32_t len)
1617{
1618 tp_wma_handle wma = (tp_wma_handle) handle;
1619 WMI_OEM_MEASUREMENT_REPORT_EVENTID_param_tlvs *param_buf;
1620 uint8_t *data;
1621 uint32_t datalen;
1622 uint32_t *msg_subtype;
1623 tStartOemDataRsp *pStartOemDataRsp;
1624
1625 param_buf = (WMI_OEM_MEASUREMENT_REPORT_EVENTID_param_tlvs *) datap;
1626 if (!param_buf) {
1627 WMA_LOGE("%s: Received NULL buf ptr from FW", __func__);
1628 return -ENOMEM;
1629 }
1630
1631 data = param_buf->data;
1632 datalen = param_buf->num_data;
1633
1634 if (!data) {
1635 WMA_LOGE("%s: Received NULL data from FW", __func__);
1636 return -EINVAL;
1637 }
1638
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001639 /*
1640 * wma puts 4 bytes prefix for msg subtype, so length
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001641 * of data received from target should be 4 bytes less
1642 * then max allowed
1643 */
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001644 if (datalen > (OEM_DATA_RSP_SIZE - OEM_MESSAGE_SUBTYPE_LEN)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001645 WMA_LOGE("%s: Received data len (%d) exceeds max value (%d)",
1646 __func__, datalen, (OEM_DATA_RSP_SIZE - 4));
1647 return -EINVAL;
1648 }
1649
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301650 pStartOemDataRsp = qdf_mem_malloc(sizeof(*pStartOemDataRsp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001651 if (!pStartOemDataRsp) {
1652 WMA_LOGE("%s: Failed to alloc pStartOemDataRsp", __func__);
1653 return -ENOMEM;
1654 }
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001655
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001656 pStartOemDataRsp->rsp_len = datalen + OEM_MESSAGE_SUBTYPE_LEN;
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001657 if (pStartOemDataRsp->rsp_len) {
1658 pStartOemDataRsp->oem_data_rsp =
1659 qdf_mem_malloc(pStartOemDataRsp->rsp_len);
1660 if (!pStartOemDataRsp->oem_data_rsp) {
1661 WMA_LOGE(FL("malloc failed for oem_data_rsp"));
1662 qdf_mem_free(pStartOemDataRsp);
1663 return -ENOMEM;
1664 }
1665 } else {
1666 WMA_LOGE(FL("Invalid rsp length: %d"),
1667 pStartOemDataRsp->rsp_len);
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001668 qdf_mem_free(pStartOemDataRsp);
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001669 return -EINVAL;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001670 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001671
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001672 pStartOemDataRsp->target_rsp = true;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001673 msg_subtype = (uint32_t *) pStartOemDataRsp->oem_data_rsp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001674 *msg_subtype = WMI_OEM_MEASUREMENT_RSP;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001675 /* copy data after msg sub type */
1676 qdf_mem_copy(pStartOemDataRsp->oem_data_rsp + OEM_MESSAGE_SUBTYPE_LEN,
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001677 data, datalen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001678
1679 WMA_LOGI("%s: Sending WMA_START_OEM_DATA_RSP, data len (%d)",
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001680 __func__, pStartOemDataRsp->rsp_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001681
1682 wma_send_msg(wma, WMA_START_OEM_DATA_RSP, (void *)pStartOemDataRsp, 0);
1683 return 0;
1684}
1685
1686/**
1687 * wma_oem_error_report_event_callback() - OEM error report handler
1688 * @handle: wma handle
1689 * @datap: data ptr
1690 * @len: data length
1691 *
1692 * Return: 0 for success or error code
1693 */
1694int wma_oem_error_report_event_callback(void *handle,
1695 uint8_t *datap, uint32_t len)
1696{
1697 tp_wma_handle wma = (tp_wma_handle) handle;
1698 WMI_OEM_ERROR_REPORT_EVENTID_param_tlvs *param_buf;
1699 uint8_t *data;
1700 uint32_t datalen;
1701 uint32_t *msg_subtype;
1702 tStartOemDataRsp *pStartOemDataRsp;
1703
1704 param_buf = (WMI_OEM_ERROR_REPORT_EVENTID_param_tlvs *) datap;
1705 if (!param_buf) {
1706 WMA_LOGE("%s: Received NULL buf ptr from FW", __func__);
1707 return -ENOMEM;
1708 }
1709
1710 data = param_buf->data;
1711 datalen = param_buf->num_data;
1712
1713 if (!data) {
1714 WMA_LOGE("%s: Received NULL data from FW", __func__);
1715 return -EINVAL;
1716 }
1717
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001718 /*
1719 * wma puts 4 bytes prefix for msg subtype, so length
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001720 * of data received from target should be 4 bytes less
1721 * then max allowed
1722 */
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001723 if (datalen > (OEM_DATA_RSP_SIZE - OEM_MESSAGE_SUBTYPE_LEN)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001724 WMA_LOGE("%s: Received data len (%d) exceeds max value (%d)",
1725 __func__, datalen, (OEM_DATA_RSP_SIZE - 4));
1726 return -EINVAL;
1727 }
1728
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301729 pStartOemDataRsp = qdf_mem_malloc(sizeof(*pStartOemDataRsp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001730 if (!pStartOemDataRsp) {
1731 WMA_LOGE("%s: Failed to alloc pStartOemDataRsp", __func__);
1732 return -ENOMEM;
1733 }
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001734
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001735 pStartOemDataRsp->rsp_len = datalen + OEM_MESSAGE_SUBTYPE_LEN;
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001736 if (pStartOemDataRsp->rsp_len) {
1737 pStartOemDataRsp->oem_data_rsp =
1738 qdf_mem_malloc(pStartOemDataRsp->rsp_len);
1739 if (!pStartOemDataRsp->oem_data_rsp) {
1740 WMA_LOGE(FL("malloc failed for oem_data_rsp"));
1741 qdf_mem_free(pStartOemDataRsp);
1742 return -ENOMEM;
1743 }
1744 } else {
1745 WMA_LOGE(FL("Invalid rsp length: %d"),
1746 pStartOemDataRsp->rsp_len);
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001747 qdf_mem_free(pStartOemDataRsp);
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001748 return -EINVAL;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001749 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001750
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001751 pStartOemDataRsp->target_rsp = true;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001752 msg_subtype = (uint32_t *) pStartOemDataRsp->oem_data_rsp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001753 *msg_subtype = WMI_OEM_ERROR_REPORT_RSP;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001754 /* copy data after msg sub type */
1755 qdf_mem_copy(pStartOemDataRsp->oem_data_rsp + OEM_MESSAGE_SUBTYPE_LEN,
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001756 data, datalen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001757
1758 WMA_LOGI("%s: Sending WMA_START_OEM_DATA_RSP, data len (%d)",
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001759 __func__, pStartOemDataRsp->rsp_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001760
1761 wma_send_msg(wma, WMA_START_OEM_DATA_RSP, (void *)pStartOemDataRsp, 0);
1762 return 0;
1763}
1764
1765/**
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001766 * wma_oem_data_response_handler() - OEM data response event handler
1767 * @handle: wma handle
1768 * @datap: data ptr
1769 * @len: data length
1770 *
1771 * Return: 0 for success or error code
1772 */
1773int wma_oem_data_response_handler(void *handle,
1774 uint8_t *datap, uint32_t len)
1775{
1776 tp_wma_handle wma = (tp_wma_handle) handle;
1777 WMI_OEM_RESPONSE_EVENTID_param_tlvs *param_buf;
1778 uint8_t *data;
1779 uint32_t datalen;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001780 tStartOemDataRsp *oem_rsp;
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001781
1782 param_buf = (WMI_OEM_RESPONSE_EVENTID_param_tlvs *) datap;
1783 if (!param_buf) {
1784 WMA_LOGE(FL("Received NULL buf ptr from FW"));
1785 return -ENOMEM;
1786 }
1787
1788 data = param_buf->data;
1789 datalen = param_buf->num_data;
1790
1791 if (!data) {
1792 WMA_LOGE(FL("Received NULL data from FW"));
1793 return -EINVAL;
1794 }
1795
1796 if (datalen > OEM_DATA_RSP_SIZE) {
1797 WMA_LOGE(FL("Received data len %d exceeds max value %d"),
1798 datalen, OEM_DATA_RSP_SIZE);
1799 return -EINVAL;
1800 }
1801
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001802 oem_rsp = qdf_mem_malloc(sizeof(*oem_rsp));
1803 if (!oem_rsp) {
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001804 WMA_LOGE(FL("Failed to alloc oem_data_rsp"));
1805 return -ENOMEM;
1806 }
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001807 oem_rsp->rsp_len = datalen;
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001808 if (oem_rsp->rsp_len) {
1809 oem_rsp->oem_data_rsp = qdf_mem_malloc(oem_rsp->rsp_len);
1810 if (!oem_rsp->oem_data_rsp) {
1811 WMA_LOGE(FL("malloc failed for oem_data_rsp"));
1812 qdf_mem_free(oem_rsp);
1813 return -ENOMEM;
1814 }
1815 } else {
1816 WMA_LOGE(FL("Invalid rsp length: %d"),
1817 oem_rsp->rsp_len);
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001818 qdf_mem_free(oem_rsp);
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001819 return -EINVAL;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001820 }
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001821
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001822 oem_rsp->target_rsp = true;
1823 qdf_mem_copy(oem_rsp->oem_data_rsp, data, datalen);
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001824
1825 WMA_LOGI(FL("Sending WMA_START_OEM_DATA_RSP, data len %d"), datalen);
1826
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001827 wma_send_msg(wma, WMA_START_OEM_DATA_RSP, (void *)oem_rsp, 0);
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001828 return 0;
1829}
1830
1831/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001832 * wma_start_oem_data_req() - start OEM data request to target
1833 * @wma_handle: wma handle
1834 * @startOemDataReq: start request params
1835 *
1836 * Return: none
1837 */
1838void wma_start_oem_data_req(tp_wma_handle wma_handle,
1839 tStartOemDataReq *startOemDataReq)
1840{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001841 int ret = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001842 tStartOemDataRsp *pStartOemDataRsp;
1843
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001844 WMA_LOGD(FL("Send OEM Data Request to target"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001845
Sreelakshmi Konamki86d79202016-02-10 12:33:40 +05301846 if (!startOemDataReq || !startOemDataReq->data) {
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001847 WMA_LOGE(FL("startOemDataReq is null"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001848 goto out;
1849 }
1850
1851 if (!wma_handle || !wma_handle->wmi_handle) {
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001852 WMA_LOGE(FL("WMA - closed, can not send Oem data request cmd"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001853 return;
1854 }
1855
Govind Singhaa64c242016-03-08 11:31:49 +05301856 ret = wmi_unified_start_oem_data_cmd(wma_handle->wmi_handle,
1857 startOemDataReq->data_len,
1858 startOemDataReq->data);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001859
1860 if (ret != EOK) {
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001861 WMA_LOGE(FL(":wmi cmd send failed"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001862 }
1863
1864out:
1865 /* free oem data req buffer received from UMAC */
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001866 if (startOemDataReq) {
1867 if (startOemDataReq->data)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301868 qdf_mem_free(startOemDataReq->data);
1869 qdf_mem_free(startOemDataReq);
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001870 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001871
1872 /* Now send data resp back to PE/SME with message sub-type of
1873 * WMI_OEM_INTERNAL_RSP. This is required so that PE/SME clears
1874 * up pending active command. Later when desired oem response(s)
1875 * comes as wmi event from target then those shall be passed
1876 * to oem application
1877 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301878 pStartOemDataRsp = qdf_mem_malloc(sizeof(*pStartOemDataRsp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001879 if (!pStartOemDataRsp) {
1880 WMA_LOGE("%s:failed to allocate memory for OEM Data Resp to PE",
1881 __func__);
1882 return;
1883 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301884 qdf_mem_zero(pStartOemDataRsp, sizeof(tStartOemDataRsp));
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001885 pStartOemDataRsp->target_rsp = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001886
1887 WMA_LOGI("%s: Sending WMA_START_OEM_DATA_RSP to clear up PE/SME pending cmd",
1888 __func__);
1889
1890 wma_send_msg(wma_handle, WMA_START_OEM_DATA_RSP,
1891 (void *)pStartOemDataRsp, 0);
1892
1893 return;
1894}
1895#endif /* FEATURE_OEM_DATA_SUPPORT */
1896
1897
1898/**
1899 * wma_unified_dfs_radar_rx_event_handler() - dfs radar rx event handler
1900 * @handle: wma handle
1901 * @data: data buffer
1902 * @datalen: data length
1903 *
1904 * WMI handler for WMI_DFS_RADAR_EVENTID
1905 * This handler is registered for handling
1906 * filtered DFS Phyerror. This handler is
1907 * will be invoked only when DFS Phyerr
1908 * filtering offload is enabled.
1909 *
1910 * Return: 1 for Success and 0 for error
1911 */
1912static int wma_unified_dfs_radar_rx_event_handler(void *handle,
1913 uint8_t *data,
1914 uint32_t datalen)
1915{
1916 tp_wma_handle wma = (tp_wma_handle) handle;
1917 struct ieee80211com *ic;
1918 struct ath_dfs *dfs;
1919 struct dfs_event *event;
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05301920 struct dfs_ieee80211_channel *chan;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001921 int empty;
1922 int do_check_chirp = 0;
1923 int is_hw_chirp = 0;
1924 int is_sw_chirp = 0;
1925 int is_pri = 0;
Vishwajith Upendrabf673e72016-01-19 16:05:40 -08001926 bool is_ch_dfs = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001927
1928 WMI_DFS_RADAR_EVENTID_param_tlvs *param_tlvs;
1929 wmi_dfs_radar_event_fixed_param *radar_event;
1930
1931 ic = wma->dfs_ic;
1932 if (NULL == ic) {
1933 WMA_LOGE("%s: dfs_ic is NULL ", __func__);
1934 return 0;
1935 }
1936
1937 dfs = (struct ath_dfs *)ic->ic_dfs;
1938 param_tlvs = (WMI_DFS_RADAR_EVENTID_param_tlvs *) data;
1939
1940 if (NULL == dfs) {
1941 WMA_LOGE("%s: dfs is NULL ", __func__);
1942 return 0;
1943 }
1944 /*
1945 * This parameter holds the number
1946 * of phyerror interrupts to the host
1947 * after the phyerrors have passed through
1948 * false detect filters in the firmware.
1949 */
1950 dfs->dfs_phyerr_count++;
1951
1952 if (!param_tlvs) {
1953 WMA_LOGE("%s: Received NULL data from FW", __func__);
1954 return 0;
1955 }
1956
1957 radar_event = param_tlvs->fixed_param;
1958
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301959 qdf_spin_lock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001960 chan = ic->ic_curchan;
Edhar, Mahesh Kumar35d9b2e2015-10-26 17:06:23 +05301961 if (ic->disable_phy_err_processing) {
1962 WMA_LOGD("%s: radar indication done,drop phyerror event",
1963 __func__);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301964 qdf_spin_unlock_bh(&ic->chan_lock);
Edhar, Mahesh Kumar35d9b2e2015-10-26 17:06:23 +05301965 return 0;
1966 }
1967
Vishwajith Upendrabf673e72016-01-19 16:05:40 -08001968 if (IEEE80211_IS_CHAN_11AC_VHT160(chan)) {
1969 is_ch_dfs = true;
1970 } else if (IEEE80211_IS_CHAN_11AC_VHT80P80(chan)) {
1971 if (cds_get_channel_state(chan->ic_ieee) == CHANNEL_STATE_DFS ||
1972 cds_get_channel_state(chan->ic_ieee_ext -
1973 WMA_80MHZ_START_CENTER_CH_DIFF) ==
1974 CHANNEL_STATE_DFS)
1975 is_ch_dfs = true;
1976 } else {
1977 if (cds_get_channel_state(chan->ic_ieee) == CHANNEL_STATE_DFS)
1978 is_ch_dfs = true;
1979 }
1980 if (!is_ch_dfs) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001981 WMA_LOGE
1982 ("%s: Invalid DFS Phyerror event. Channel=%d is Non-DFS",
1983 __func__, chan->ic_ieee);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301984 qdf_spin_unlock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001985 return 0;
1986 }
1987
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301988 qdf_spin_unlock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001989 dfs->ath_dfs_stats.total_phy_errors++;
1990
1991 if (dfs->dfs_caps.ath_chip_is_bb_tlv) {
1992 do_check_chirp = 1;
1993 is_pri = 1;
1994 is_hw_chirp = radar_event->pulse_is_chirp;
1995
1996 if ((uint32_t) dfs->dfs_phyerr_freq_min >
1997 radar_event->pulse_center_freq) {
1998 dfs->dfs_phyerr_freq_min =
1999 (int)radar_event->pulse_center_freq;
2000 }
2001
2002 if (dfs->dfs_phyerr_freq_max <
2003 (int)radar_event->pulse_center_freq) {
2004 dfs->dfs_phyerr_freq_max =
2005 (int)radar_event->pulse_center_freq;
2006 }
2007 }
2008
2009 /*
2010 * Now, add the parsed, checked and filtered
2011 * radar phyerror event radar pulse event list.
2012 * This event will then be processed by
2013 * dfs_radar_processevent() to see if the pattern
2014 * of pulses in radar pulse list match any radar
2015 * singnature in the current regulatory domain.
2016 */
2017
2018 ATH_DFSEVENTQ_LOCK(dfs);
2019 empty = STAILQ_EMPTY(&(dfs->dfs_eventq));
2020 ATH_DFSEVENTQ_UNLOCK(dfs);
2021 if (empty) {
2022 return 0;
2023 }
2024 /*
2025 * Add the event to the list, if there's space.
2026 */
2027 ATH_DFSEVENTQ_LOCK(dfs);
2028 event = STAILQ_FIRST(&(dfs->dfs_eventq));
2029 if (event == NULL) {
2030 ATH_DFSEVENTQ_UNLOCK(dfs);
2031 WMA_LOGE("%s: No more space left for queuing DFS Phyerror events",
2032 __func__);
2033 return 0;
2034 }
2035 STAILQ_REMOVE_HEAD(&(dfs->dfs_eventq), re_list);
2036 ATH_DFSEVENTQ_UNLOCK(dfs);
2037 dfs->dfs_phyerr_queued_count++;
2038 dfs->dfs_phyerr_w53_counter++;
2039 event->re_dur = (uint8_t) radar_event->pulse_duration;
2040 event->re_rssi = radar_event->rssi;
2041 event->re_ts = radar_event->pulse_detect_ts & DFS_TSMASK;
2042 event->re_full_ts = (((uint64_t) radar_event->upload_fullts_high) << 32)
2043 | radar_event->upload_fullts_low;
2044
2045 /*
2046 * Index of peak magnitude
2047 */
2048 event->sidx = radar_event->peak_sidx;
2049
2050 /*
2051 * Handle chirp flags.
2052 */
2053 if (do_check_chirp) {
2054 event->re_flags |= DFS_EVENT_CHECKCHIRP;
2055 if (is_hw_chirp) {
2056 event->re_flags |= DFS_EVENT_HW_CHIRP;
2057 }
2058 if (is_sw_chirp) {
2059 event->re_flags |= DFS_EVENT_SW_CHIRP;
2060 }
2061 }
2062 /*
2063 * Correctly set which channel is being reported on
2064 */
2065 if (is_pri) {
2066 event->re_chanindex = (uint8_t) dfs->dfs_curchan_radindex;
2067 } else {
2068 if (dfs->dfs_extchan_radindex == -1) {
2069 WMA_LOGI("%s phyerr on ext channel", __func__);
2070 }
2071 event->re_chanindex = (uint8_t) dfs->dfs_extchan_radindex;
2072 WMA_LOGI("%s:New extension channel event is added to queue",
2073 __func__);
2074 }
2075
2076 ATH_DFSQ_LOCK(dfs);
2077
2078 STAILQ_INSERT_TAIL(&(dfs->dfs_radarq), event, re_list);
2079
2080 empty = STAILQ_EMPTY(&dfs->dfs_radarq);
2081
2082 ATH_DFSQ_UNLOCK(dfs);
2083
2084 if (!empty && !dfs->ath_radar_tasksched) {
2085 dfs->ath_radar_tasksched = 1;
2086 OS_SET_TIMER(&dfs->ath_dfs_task_timer, 0);
2087 }
2088
2089 return 1;
2090
2091}
2092
2093/**
2094 * wma_unified_phyerr_rx_event_handler() - phyerr event handler
2095 * @handle: wma handle
2096 * @data: data buffer
2097 * @datalen: buffer length
2098 *
2099 * WMI Handler for WMI_PHYERR_EVENTID event from firmware.
2100 * This handler is currently handling only DFS phy errors.
2101 * This handler will be invoked only when the DFS phyerror
2102 * filtering offload is disabled.
2103 *
2104 * Return: 1:Success, 0:Failure
2105 */
2106static int wma_unified_phyerr_rx_event_handler(void *handle,
2107 uint8_t *data, uint32_t datalen)
2108{
2109 tp_wma_handle wma = (tp_wma_handle) handle;
2110 WMI_PHYERR_EVENTID_param_tlvs *param_tlvs;
2111 wmi_comb_phyerr_rx_hdr *pe_hdr;
2112 uint8_t *bufp;
2113 wmi_single_phyerr_rx_event *ev;
2114 struct ieee80211com *ic = wma->dfs_ic;
Anurag Chouhan6d760662016-02-20 16:05:43 +05302115 qdf_size_t n;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002116 A_UINT64 tsf64 = 0;
2117 int phy_err_code = 0;
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002118 A_UINT32 phy_err_mask = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002119 int error = 0;
2120 tpAniSirGlobal mac_ctx =
Anurag Chouhan6d760662016-02-20 16:05:43 +05302121 (tpAniSirGlobal)cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002122 bool enable_log = false;
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002123 int max_dfs_buf_length = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002124
2125 if (NULL == mac_ctx) {
2126 WMA_LOGE("%s: mac_ctx is NULL", __func__);
2127 return 0;
2128 }
2129 enable_log = mac_ctx->sap.enable_dfs_phy_error_logs;
2130
2131 param_tlvs = (WMI_PHYERR_EVENTID_param_tlvs *) data;
2132
2133 if (!param_tlvs) {
2134 WMA_LOGE("%s: Received NULL data from FW", __func__);
2135 return 0;
2136 }
2137
2138 pe_hdr = param_tlvs->hdr;
2139 if (pe_hdr == NULL) {
2140 WMA_LOGE("%s: Received Data PE Header is NULL", __func__);
2141 return 0;
2142 }
2143
2144 /* Ensure it's at least the size of the header */
2145 if (datalen < sizeof(*pe_hdr)) {
2146 WMA_LOGE("%s: Expected minimum size %zu, received %d",
2147 __func__, sizeof(*pe_hdr), datalen);
2148 return 0;
2149 }
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002150 /*
2151 * The max buffer lenght is larger for DFS-3 than DFS-2.
2152 * So, accordingly use the correct max buffer size.
2153 */
2154 if (wma->hw_bd_id != WMI_HWBD_QCA6174)
2155 max_dfs_buf_length = DFS3_MAX_BUF_LENGTH;
2156 else
2157 max_dfs_buf_length = DFS_MAX_BUF_LENGTH;
2158
2159 if (pe_hdr->buf_len > max_dfs_buf_length) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002160 WMA_LOGE("%s: Received Invalid Phyerror event buffer length = %d"
2161 "Maximum allowed buf length = %d", __func__,
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002162 pe_hdr->buf_len, max_dfs_buf_length);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002163
2164 return 0;
2165 }
2166
2167 /*
2168 * Reconstruct the 64 bit event TSF. This isn't from the MAC, it's
2169 * at the time the event was sent to us, the TSF value will be
2170 * in the future.
2171 */
2172 tsf64 = pe_hdr->tsf_l32;
2173 tsf64 |= (((uint64_t) pe_hdr->tsf_u32) << 32);
2174
2175 /*
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002176 * Check the HW board ID to figure out
2177 * if DFS-3 is supported. In DFS-3
2178 * phyerror mask indicates the type of
2179 * phyerror, whereas in DFS-2 phyerrorcode
2180 * indicates the type of phyerror. If the
2181 * board is NOT WMI_HWBD_QCA6174, for now
2182 * assume that it supports DFS-3.
2183 */
2184 if (wma->hw_bd_id != WMI_HWBD_QCA6174) {
2185 phy_err_mask = pe_hdr->rsPhyErrMask0;
2186 WMA_LOGD("%s: DFS-3 phyerror mask = 0x%x",
2187 __func__, phy_err_mask);
2188 }
2189
2190 /*
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002191 * Loop over the bufp, extracting out phyerrors
2192 * wmi_unified_comb_phyerr_rx_event.bufp is a char pointer,
2193 * which isn't correct here - what we have received here
2194 * is an array of TLV-style PHY errors.
2195 */
2196 n = 0; /* Start just after the header */
2197 bufp = param_tlvs->bufp;
2198 while (n < pe_hdr->buf_len) {
2199 /* ensure there's at least space for the header */
2200 if ((pe_hdr->buf_len - n) < sizeof(ev->hdr)) {
2201 WMA_LOGE("%s: Not enough space.(datalen=%d, n=%zu, hdr=%zu bytes",
2202 __func__, pe_hdr->buf_len, n, sizeof(ev->hdr));
2203 error = 1;
2204 break;
2205 }
2206 /*
2207 * Obtain a pointer to the beginning of the current event.
2208 * data[0] is the beginning of the WMI payload.
2209 */
2210 ev = (wmi_single_phyerr_rx_event *) &bufp[n];
2211
2212 /*
2213 * Sanity check the buffer length of the event against
2214 * what we currently have.
2215 * Since buf_len is 32 bits, we check if it overflows
2216 * a large 32 bit value. It's not 0x7fffffff because
2217 * we increase n by (buf_len + sizeof(hdr)), which would
2218 * in itself cause n to overflow.
2219 * If "int" is 64 bits then this becomes a moot point.
2220 */
2221 if (ev->hdr.buf_len > 0x7f000000) {
2222 WMA_LOGE("%s:buf_len is garbage (0x%x)", __func__,
2223 ev->hdr.buf_len);
2224 error = 1;
2225 break;
2226 }
2227 if (n + ev->hdr.buf_len > pe_hdr->buf_len) {
2228 WMA_LOGE("%s: buf_len exceeds available space n=%zu,"
2229 "buf_len=%d, datalen=%d",
2230 __func__, n, ev->hdr.buf_len, pe_hdr->buf_len);
2231 error = 1;
2232 break;
2233 }
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002234 /*
2235 * If the board id is WMI_HWBD_QCA6174
2236 * then it supports only DFS-2. So, fetch
2237 * phyerror code in order to know the type
2238 * of phyerror.
2239 */
2240 if (wma->hw_bd_id == WMI_HWBD_QCA6174) {
2241 phy_err_code = WMI_UNIFIED_PHYERRCODE_GET(&ev->hdr);
2242 WMA_LOGD("%s: DFS-2 phyerror code = 0x%x",
2243 __func__, phy_err_code);
2244 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002245
2246 /*
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002247 * phy_err_code is set for DFS-2 and phy_err_mask
2248 * is set for DFS-3. Checking both to support
2249 * compatability for older platforms.
2250 * If the phyerror or phyerrmask category matches,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002251 * pass radar events to the dfs pattern matching code.
2252 * Don't pass radar events with no buffer payload.
2253 */
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002254 if (((phy_err_mask & WMI_PHY_ERROR_MASK0_RADAR) ||
2255 (phy_err_mask & WMI_PHY_ERROR_MASK0_FALSE_RADAR_EXT)) ||
2256 (phy_err_code == WMA_DFS2_PHYERROR_CODE ||
2257 phy_err_code == WMA_DFS2_FALSE_RADAR_EXT)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002258 if (ev->hdr.buf_len > 0) {
2259 /* Calling in to the DFS module to process the phyerr */
2260 dfs_process_phyerr(ic, &ev->bufp[0],
2261 ev->hdr.buf_len,
2262 WMI_UNIFIED_RSSI_COMB_GET
2263 (&ev->hdr) & 0xff,
2264 /* Extension RSSI */
2265 WMI_UNIFIED_RSSI_COMB_GET
2266 (&ev->hdr) & 0xff,
2267 ev->hdr.tsf_timestamp,
2268 tsf64, enable_log);
2269 }
2270 }
2271
2272 /*
2273 * Advance the buffer pointer to the next PHY error.
2274 * buflen is the length of this payload, so we need to
2275 * advance past the current header _AND_ the payload.
2276 */
2277 n += sizeof(*ev) + ev->hdr.buf_len;
2278
2279 } /*end while() */
2280 if (error)
2281 return 0;
2282 else
2283 return 1;
2284}
2285
2286/**
2287 * wma_register_dfs_event_handler() - register dfs event handler
2288 * @wma_handle: wma handle
2289 *
2290 * Register appropriate dfs phyerror event handler
2291 * based on phyerror filtering offload is enabled
2292 * or disabled.
2293 *
2294 * Return: none
2295 */
2296void wma_register_dfs_event_handler(tp_wma_handle wma_handle)
2297{
2298 if (NULL == wma_handle) {
2299 WMA_LOGE("%s:wma_handle is NULL", __func__);
2300 return;
2301 }
2302
2303 if (false == wma_handle->dfs_phyerr_filter_offload) {
2304 /*
2305 * Register the wma_unified_phyerr_rx_event_handler
2306 * for filtering offload disabled case to handle
2307 * the DFS phyerrors.
2308 */
2309 WMA_LOGD("%s:Phyerror Filtering offload is Disabled in ini",
2310 __func__);
2311 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Govind Singhd76a5b02016-03-08 15:12:14 +05302312 WMI_PHYERR_EVENTID,
2313 wma_unified_phyerr_rx_event_handler,
2314 WMA_RX_WORK_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002315 WMA_LOGD("%s: WMI_PHYERR_EVENTID event handler registered",
2316 __func__);
2317 } else {
2318 WMA_LOGD("%s:Phyerror Filtering offload is Enabled in ini",
2319 __func__);
2320 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Govind Singhd76a5b02016-03-08 15:12:14 +05302321 WMI_DFS_RADAR_EVENTID,
2322 wma_unified_dfs_radar_rx_event_handler,
2323 WMA_RX_WORK_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002324 WMA_LOGD("%s:WMI_DFS_RADAR_EVENTID event handler registered",
2325 __func__);
2326 }
2327
2328 return;
2329}
2330
2331
2332/**
2333 * wma_unified_dfs_phyerr_filter_offload_enable() - enable dfs phyerr filter
2334 * @wma_handle: wma handle
2335 *
2336 * Send WMI_DFS_PHYERR_FILTER_ENA_CMDID or
2337 * WMI_DFS_PHYERR_FILTER_DIS_CMDID command
2338 * to firmware based on phyerr filtering
2339 * offload status.
2340 *
2341 * Return: 1 success, 0 failure
2342 */
2343int
2344wma_unified_dfs_phyerr_filter_offload_enable(tp_wma_handle wma_handle)
2345{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002346 int ret;
2347
2348 if (NULL == wma_handle) {
2349 WMA_LOGE("%s:wma_handle is NULL", __func__);
2350 return 0;
2351 }
2352
Govind Singhaa64c242016-03-08 11:31:49 +05302353 ret = wmi_unified_dfs_phyerr_filter_offload_en_cmd(wma_handle->wmi_handle,
2354 wma_handle->dfs_phyerr_filter_offload);
2355 if (ret)
2356 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002357
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002358
Govind Singhaa64c242016-03-08 11:31:49 +05302359 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002360}
2361
2362#if !defined(REMOVE_PKT_LOG)
2363/**
2364 * wma_pktlog_wmi_send_cmd() - send pktlog enable/disable command to target
2365 * @handle: wma handle
2366 * @params: pktlog params
2367 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302368 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002369 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302370QDF_STATUS wma_pktlog_wmi_send_cmd(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002371 struct ath_pktlog_wmi_params *params)
2372{
2373 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhaa64c242016-03-08 11:31:49 +05302374 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002375
2376 /*Check if packet log is enabled in cfg.ini */
2377 if (!cds_is_packet_log_enabled()) {
2378 WMA_LOGE("%s:pkt log is not enabled in cfg.ini", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302379 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002380 }
2381
Govind Singhaa64c242016-03-08 11:31:49 +05302382 ret = wmi_unified_pktlog_wmi_send_cmd(wma_handle->wmi_handle,
2383 params->pktlog_event,
2384 params->cmd_id);
2385 if (ret)
2386 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002387
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002388
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302389 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002390}
2391#endif /* REMOVE_PKT_LOG */
2392
2393static void wma_send_status_to_suspend_ind(tp_wma_handle wma, bool suspended)
2394{
2395 tSirReadyToSuspendInd *ready_to_suspend;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302396 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002397 cds_msg_t cds_msg;
2398 uint8_t len;
2399
2400 WMA_LOGD("Posting ready to suspend indication to umac");
2401
2402 len = sizeof(tSirReadyToSuspendInd);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302403 ready_to_suspend = (tSirReadyToSuspendInd *) qdf_mem_malloc(len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002404
2405 if (NULL == ready_to_suspend) {
2406 WMA_LOGE("%s: Memory allocation failure", __func__);
2407 return;
2408 }
2409
2410 ready_to_suspend->mesgType = eWNI_SME_READY_TO_SUSPEND_IND;
2411 ready_to_suspend->mesgLen = len;
2412 ready_to_suspend->suspended = suspended;
2413
2414 cds_msg.type = eWNI_SME_READY_TO_SUSPEND_IND;
2415 cds_msg.bodyptr = (void *)ready_to_suspend;
2416 cds_msg.bodyval = 0;
2417
2418 status = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302419 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002420 WMA_LOGE("Failed to post ready to suspend");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302421 qdf_mem_free(ready_to_suspend);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002422 }
2423}
2424
2425/**
2426 * wma_wow_wake_reason_str() - Converts wow wakeup reason code to text format
2427 * @wake_reason - WOW wake reason
2428 *
2429 * Return: reason code in string format
2430 */
2431static const u8 *wma_wow_wake_reason_str(A_INT32 wake_reason)
2432{
2433 switch (wake_reason) {
2434 case WOW_REASON_UNSPECIFIED:
2435 return "UNSPECIFIED";
2436 case WOW_REASON_NLOD:
2437 return "NLOD";
2438 case WOW_REASON_AP_ASSOC_LOST:
2439 return "AP_ASSOC_LOST";
2440 case WOW_REASON_LOW_RSSI:
2441 return "LOW_RSSI";
2442 case WOW_REASON_DEAUTH_RECVD:
2443 return "DEAUTH_RECVD";
2444 case WOW_REASON_DISASSOC_RECVD:
2445 return "DISASSOC_RECVD";
2446 case WOW_REASON_GTK_HS_ERR:
2447 return "GTK_HS_ERR";
2448 case WOW_REASON_EAP_REQ:
2449 return "EAP_REQ";
2450 case WOW_REASON_FOURWAY_HS_RECV:
2451 return "FOURWAY_HS_RECV";
2452 case WOW_REASON_TIMER_INTR_RECV:
2453 return "TIMER_INTR_RECV";
2454 case WOW_REASON_PATTERN_MATCH_FOUND:
2455 return "PATTERN_MATCH_FOUND";
2456 case WOW_REASON_RECV_MAGIC_PATTERN:
2457 return "RECV_MAGIC_PATTERN";
2458 case WOW_REASON_P2P_DISC:
2459 return "P2P_DISC";
2460#ifdef FEATURE_WLAN_LPHB
2461 case WOW_REASON_WLAN_HB:
2462 return "WLAN_HB";
2463#endif /* FEATURE_WLAN_LPHB */
2464
2465 case WOW_REASON_CSA_EVENT:
2466 return "CSA_EVENT";
2467 case WOW_REASON_PROBE_REQ_WPS_IE_RECV:
2468 return "PROBE_REQ_RECV";
2469 case WOW_REASON_AUTH_REQ_RECV:
2470 return "AUTH_REQ_RECV";
2471 case WOW_REASON_ASSOC_REQ_RECV:
2472 return "ASSOC_REQ_RECV";
2473 case WOW_REASON_HTT_EVENT:
2474 return "WOW_REASON_HTT_EVENT";
2475#ifdef FEATURE_WLAN_RA_FILTERING
2476 case WOW_REASON_RA_MATCH:
2477 return "WOW_REASON_RA_MATCH";
2478#endif /* FEATURE_WLAN_RA_FILTERING */
2479 case WOW_REASON_BEACON_RECV:
2480 return "WOW_REASON_IBSS_BEACON_RECV";
2481#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
2482 case WOW_REASON_HOST_AUTO_SHUTDOWN:
2483 return "WOW_REASON_HOST_AUTO_SHUTDOWN";
2484#endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
2485#ifdef WLAN_FEATURE_ROAM_OFFLOAD
2486 case WOW_REASON_ROAM_HO:
2487 return "WOW_REASON_ROAM_HO";
2488#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
2489#ifdef FEATURE_WLAN_EXTSCAN
2490 case WOW_REASON_EXTSCAN:
2491 return "WOW_REASON_EXTSCAN";
2492#endif
2493 case WOW_REASON_RSSI_BREACH_EVENT:
2494 return "WOW_REASON_RSSI_BREACH_EVENT";
Srinivas Girigowdae80cea92015-11-23 11:33:57 -08002495 case WOW_REASON_NLO_SCAN_COMPLETE:
2496 return "WOW_REASON_NLO_SCAN_COMPLETE";
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002497 }
2498 return "unknown";
2499}
2500
2501/**
2502 * wma_wow_wake_up_stats_display() - display wow wake up stats
2503 * @wma: Pointer to wma handle
2504 *
2505 * Return: none
2506 */
2507static void wma_wow_wake_up_stats_display(tp_wma_handle wma)
2508{
2509 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",
2510 wma->wow_ucast_wake_up_count,
2511 wma->wow_bcast_wake_up_count,
2512 wma->wow_ipv4_mcast_wake_up_count,
2513 wma->wow_ipv6_mcast_wake_up_count,
2514 wma->wow_ipv6_mcast_ra_stats,
2515 wma->wow_ipv6_mcast_ns_stats,
2516 wma->wow_ipv6_mcast_na_stats,
2517 wma->wow_pno_match_wake_up_count,
2518 wma->wow_pno_complete_wake_up_count,
2519 wma->wow_gscan_wake_up_count,
2520 wma->wow_low_rssi_wake_up_count,
2521 wma->wow_rssi_breach_wake_up_count);
2522
2523 return;
2524}
2525
2526/**
2527 * wma_wow_ipv6_mcast_stats() - ipv6 mcast wake up stats
2528 * @wma: Pointer to wma handle
2529 * @data: Pointer to pattern match data
2530 *
2531 * Return: none
2532 */
2533static void wma_wow_ipv6_mcast_stats(tp_wma_handle wma, uint8_t *data)
2534{
2535 static const uint8_t ipv6_mcast[] = {0x86, 0xDD};
2536
2537 if (!memcmp(ipv6_mcast, (data + WMA_ETHER_TYPE_OFFSET),
2538 sizeof(ipv6_mcast))) {
2539 if (WMA_ICMP_V6_HEADER_TYPE ==
2540 *(data + WMA_ICMP_V6_HEADER_OFFSET)) {
2541 if (WMA_ICMP_V6_RA_TYPE ==
2542 *(data + WMA_ICMP_V6_TYPE_OFFSET))
2543 wma->wow_ipv6_mcast_ra_stats++;
2544 else if (WMA_ICMP_V6_NS_TYPE ==
2545 *(data + WMA_ICMP_V6_TYPE_OFFSET))
2546 wma->wow_ipv6_mcast_ns_stats++;
2547 else if (WMA_ICMP_V6_NA_TYPE ==
2548 *(data + WMA_ICMP_V6_TYPE_OFFSET))
2549 wma->wow_ipv6_mcast_na_stats++;
2550 else
2551 WMA_LOGA("ICMP V6 type : 0x%x",
2552 *(data + WMA_ICMP_V6_TYPE_OFFSET));
2553 } else {
2554 WMA_LOGA("ICMP_V6 header 0x%x",
2555 *(data + WMA_ICMP_V6_HEADER_OFFSET));
2556 }
2557 } else {
2558 WMA_LOGA("Ethertype x%x:0x%x",
2559 *(data + WMA_ETHER_TYPE_OFFSET),
2560 *(data + WMA_ETHER_TYPE_OFFSET + 1));
2561 }
2562
2563 return;
2564}
2565
2566/**
2567 * wma_wow_wake_up_stats() - maintain wow pattern match wake up stats
2568 * @wma: Pointer to wma handle
2569 * @data: Pointer to pattern match data
2570 * @len: Pattern match data length
2571 * @event: Wake up event
2572 *
2573 * Return: none
2574 */
2575static void wma_wow_wake_up_stats(tp_wma_handle wma, uint8_t *data,
2576 int32_t len, WOW_WAKE_REASON_TYPE event)
2577{
2578 switch (event) {
2579
2580 case WOW_REASON_PATTERN_MATCH_FOUND:
2581 if (WMA_BCAST_MAC_ADDR == *data) {
2582 wma->wow_bcast_wake_up_count++;
2583 } else if (WMA_MCAST_IPV4_MAC_ADDR == *data) {
2584 wma->wow_ipv4_mcast_wake_up_count++;
2585 } else if (WMA_MCAST_IPV6_MAC_ADDR == *data) {
2586 wma->wow_ipv6_mcast_wake_up_count++;
2587 if (len > WMA_ICMP_V6_TYPE_OFFSET)
2588 wma_wow_ipv6_mcast_stats(wma, data);
2589 else
2590 WMA_LOGA("ICMP_V6 data len %d", len);
2591 } else {
2592 wma->wow_ucast_wake_up_count++;
2593 }
2594 break;
2595
2596 case WOW_REASON_RA_MATCH:
2597 wma->wow_ipv6_mcast_ra_stats++;
2598 break;
2599
2600 case WOW_REASON_NLOD:
2601 wma->wow_pno_match_wake_up_count++;
2602 break;
2603
2604 case WOW_REASON_NLO_SCAN_COMPLETE:
2605 wma->wow_pno_complete_wake_up_count++;
2606 break;
2607
2608 case WOW_REASON_LOW_RSSI:
2609 wma->wow_low_rssi_wake_up_count++;
2610 break;
2611
2612 case WOW_REASON_EXTSCAN:
2613 wma->wow_gscan_wake_up_count++;
2614 break;
2615
2616 case WOW_REASON_RSSI_BREACH_EVENT:
2617 wma->wow_rssi_breach_wake_up_count++;
2618 break;
2619
2620 default:
2621 WMA_LOGE("Unknown wake up reason");
2622 break;
2623 }
2624
2625 wma_wow_wake_up_stats_display(wma);
2626 return;
2627}
2628
2629/**
2630 * wma_wow_wakeup_host_event() - wakeup host event handler
2631 * @handle: wma handle
2632 * @event: event data
2633 * @len: buffer length
2634 *
2635 * Handler to catch wow wakeup host event. This event will have
2636 * reason why the firmware has woken the host.
2637 *
2638 * Return: 0 for success or error
2639 */
2640int wma_wow_wakeup_host_event(void *handle, uint8_t *event,
2641 uint32_t len)
2642{
2643 tp_wma_handle wma = (tp_wma_handle) handle;
2644 WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *param_buf;
2645 WOW_EVENT_INFO_fixed_param *wake_info;
2646#ifdef FEATURE_WLAN_SCAN_PNO
2647 struct wma_txrx_node *node;
2648#endif /* FEATURE_WLAN_SCAN_PNO */
2649 uint32_t wake_lock_duration = 0;
2650 uint32_t wow_buf_pkt_len = 0;
2651
2652 param_buf = (WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *) event;
2653 if (!param_buf) {
2654 WMA_LOGE("Invalid wow wakeup host event buf");
2655 return -EINVAL;
2656 }
2657
2658 wake_info = param_buf->fixed_param;
2659
2660 WMA_LOGA("WOW wakeup host event received (reason: %s(%d)) for vdev %d",
2661 wma_wow_wake_reason_str(wake_info->wake_reason),
2662 wake_info->wake_reason, wake_info->vdev_id);
2663
Anurag Chouhance0dc992016-02-16 18:18:03 +05302664 qdf_event_set(&wma->wma_resume_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002665
2666 switch (wake_info->wake_reason) {
2667 case WOW_REASON_AUTH_REQ_RECV:
2668 wake_lock_duration = WMA_AUTH_REQ_RECV_WAKE_LOCK_TIMEOUT;
2669 break;
2670
2671 case WOW_REASON_ASSOC_REQ_RECV:
2672 wake_lock_duration = WMA_ASSOC_REQ_RECV_WAKE_LOCK_DURATION;
2673 break;
2674
2675 case WOW_REASON_DEAUTH_RECVD:
2676 wake_lock_duration = WMA_DEAUTH_RECV_WAKE_LOCK_DURATION;
2677 break;
2678
2679 case WOW_REASON_DISASSOC_RECVD:
2680 wake_lock_duration = WMA_DISASSOC_RECV_WAKE_LOCK_DURATION;
2681 break;
2682
2683 case WOW_REASON_AP_ASSOC_LOST:
2684 wake_lock_duration = WMA_BMISS_EVENT_WAKE_LOCK_DURATION;
2685 WMA_LOGA("Beacon miss indication on vdev %x",
2686 wake_info->vdev_id);
2687 wma_beacon_miss_handler(wma, wake_info->vdev_id);
2688 break;
2689#ifdef FEATURE_WLAN_RA_FILTERING
2690 case WOW_REASON_RA_MATCH:
2691 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_RA_MATCH);
2692 break;
2693#endif /* FEATURE_WLAN_RA_FILTERING */
2694#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
2695 case WOW_REASON_HOST_AUTO_SHUTDOWN:
2696 wake_lock_duration = WMA_AUTO_SHUTDOWN_WAKE_LOCK_DURATION;
2697 WMA_LOGA("Received WOW Auto Shutdown trigger in suspend");
2698 if (wma_post_auto_shutdown_msg())
2699 return -EINVAL;
2700 break;
2701#endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
2702#ifdef FEATURE_WLAN_SCAN_PNO
2703 case WOW_REASON_NLOD:
2704 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_NLOD);
2705 node = &wma->interfaces[wake_info->vdev_id];
2706 if (node) {
2707 WMA_LOGD("NLO match happened");
2708 node->nlo_match_evt_received = true;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302709 qdf_wake_lock_timeout_acquire(&wma->pno_wake_lock,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002710 WMA_PNO_MATCH_WAKE_LOCK_TIMEOUT,
2711 WIFI_POWER_EVENT_WAKELOCK_PNO);
Srinivas Girigowdae80cea92015-11-23 11:33:57 -08002712 }
2713 break;
2714
2715 case WOW_REASON_NLO_SCAN_COMPLETE:
2716 {
2717 WMI_NLO_SCAN_COMPLETE_EVENTID_param_tlvs param;
2718
2719 WMA_LOGD("Host woken up due to pno scan complete reason");
2720
2721 /* First 4-bytes of wow_packet_buffer is the length */
2722 if (param_buf->wow_packet_buffer) {
2723 param.fixed_param = (wmi_nlo_event *)
2724 (param_buf->wow_packet_buffer + 4);
2725 wma_nlo_scan_cmp_evt_handler(handle,
2726 (u_int8_t *)&param, sizeof(param));
2727 } else
2728 WMA_LOGD("No wow_packet_buffer present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002729 }
2730 break;
2731#endif /* FEATURE_WLAN_SCAN_PNO */
2732
2733 case WOW_REASON_CSA_EVENT:
2734 {
2735 WMI_CSA_HANDLING_EVENTID_param_tlvs param;
2736 WMA_LOGD("Host woken up because of CSA IE");
2737 param.fixed_param = (wmi_csa_event_fixed_param *)
2738 (((uint8_t *) wake_info)
2739 + sizeof(WOW_EVENT_INFO_fixed_param)
2740 + WOW_CSA_EVENT_OFFSET);
2741 wma_csa_offload_handler(handle, (uint8_t *) &param,
2742 sizeof(param));
2743 }
2744 break;
2745
2746#ifdef FEATURE_WLAN_LPHB
2747 case WOW_REASON_WLAN_HB:
2748 wma_lphb_handler(wma, (uint8_t *) param_buf->hb_indevt);
2749 break;
2750#endif /* FEATURE_WLAN_LPHB */
2751
2752 case WOW_REASON_HTT_EVENT:
2753 break;
2754 case WOW_REASON_PATTERN_MATCH_FOUND:
2755 wma_wow_wake_up_stats_display(wma);
2756 WMA_LOGD("Wake up for Rx packet, dump starting from ethernet hdr");
2757 if (param_buf->wow_packet_buffer) {
2758 /* First 4-bytes of wow_packet_buffer is the length */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302759 qdf_mem_copy((uint8_t *) &wow_buf_pkt_len,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002760 param_buf->wow_packet_buffer, 4);
2761 wma_wow_wake_up_stats(wma,
2762 param_buf->wow_packet_buffer + 4,
2763 wow_buf_pkt_len,
2764 WOW_REASON_PATTERN_MATCH_FOUND);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302765 qdf_trace_hex_dump(QDF_MODULE_ID_WMA,
2766 QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002767 param_buf->wow_packet_buffer + 4,
2768 wow_buf_pkt_len);
2769 } else {
2770 WMA_LOGE("No wow packet buffer present");
2771 }
2772 break;
2773
2774 case WOW_REASON_LOW_RSSI:
2775 {
2776 /* WOW_REASON_LOW_RSSI is used for all roaming events.
2777 * WMI_ROAM_REASON_BETTER_AP, WMI_ROAM_REASON_BMISS,
2778 * WMI_ROAM_REASON_SUITABLE_AP will be handled by
2779 * wma_roam_event_callback().
2780 */
2781 WMI_ROAM_EVENTID_param_tlvs param;
2782 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_LOW_RSSI);
2783 if (param_buf->wow_packet_buffer) {
2784 /* Roam event is embedded in wow_packet_buffer */
2785 WMA_LOGD("Host woken up because of roam event");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302786 qdf_mem_copy((uint8_t *) &wow_buf_pkt_len,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002787 param_buf->wow_packet_buffer, 4);
2788 WMA_LOGD("wow_packet_buffer dump");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302789 qdf_trace_hex_dump(QDF_MODULE_ID_WMA,
2790 QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002791 param_buf->wow_packet_buffer,
2792 wow_buf_pkt_len);
2793 if (wow_buf_pkt_len >= sizeof(param)) {
2794 param.fixed_param =
2795 (wmi_roam_event_fixed_param *)
2796 (param_buf->wow_packet_buffer + 4);
2797 wma_roam_event_callback(handle,
2798 (uint8_t *) &
2799 param,
2800 sizeof(param));
2801 } else {
2802 WMA_LOGE("Wrong length for roam event = %d bytes",
2803 wow_buf_pkt_len);
2804 }
2805 } else {
2806 /* No wow_packet_buffer means a better AP beacon
2807 * will follow in a later event.
2808 */
2809 WMA_LOGD("Host woken up because of better AP beacon");
2810 }
2811 break;
2812 }
2813 case WOW_REASON_CLIENT_KICKOUT_EVENT:
2814 {
2815 WMI_PEER_STA_KICKOUT_EVENTID_param_tlvs param;
2816 if (param_buf->wow_packet_buffer) {
2817 /* station kickout event embedded in wow_packet_buffer */
2818 WMA_LOGD("Host woken up because of sta_kickout event");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302819 qdf_mem_copy((u_int8_t *) &wow_buf_pkt_len,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002820 param_buf->wow_packet_buffer, 4);
2821 WMA_LOGD("wow_packet_buffer dump");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302822 qdf_trace_hex_dump(QDF_MODULE_ID_WMA,
2823 QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002824 param_buf->wow_packet_buffer, wow_buf_pkt_len);
2825 if (wow_buf_pkt_len >= sizeof(param)) {
2826 param.fixed_param = (wmi_peer_sta_kickout_event_fixed_param *)
2827 (param_buf->wow_packet_buffer + 4);
2828 wma_peer_sta_kickout_event_handler(handle,
2829 (u_int8_t *)&param, sizeof(param));
2830 } else {
2831 WMA_LOGE("Wrong length for sta_kickout event = %d bytes",
2832 wow_buf_pkt_len);
2833 }
2834 } else {
2835 WMA_LOGD("No wow_packet_buffer present");
2836 }
2837 break;
2838 }
2839#ifdef FEATURE_WLAN_EXTSCAN
2840 case WOW_REASON_EXTSCAN:
2841 WMA_LOGD("Host woken up because of extscan reason");
2842 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_EXTSCAN);
2843 if (param_buf->wow_packet_buffer) {
2844 wow_buf_pkt_len =
2845 *(uint32_t *)param_buf->wow_packet_buffer;
2846 wma_extscan_wow_event_callback(handle,
2847 (u_int8_t *)(param_buf->wow_packet_buffer + 4),
2848 wow_buf_pkt_len);
2849 } else
2850 WMA_LOGE("wow_packet_buffer is empty");
2851 break;
2852#endif
2853 case WOW_REASON_RSSI_BREACH_EVENT:
2854 {
2855 WMI_RSSI_BREACH_EVENTID_param_tlvs param;
2856
2857 wma_wow_wake_up_stats(wma, NULL, 0,
2858 WOW_REASON_RSSI_BREACH_EVENT);
2859 WMA_LOGD("Host woken up because of rssi breach reason");
2860 /* rssi breach event is embedded in wow_packet_buffer */
2861 if (param_buf->wow_packet_buffer) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302862 qdf_mem_copy((u_int8_t *) &wow_buf_pkt_len,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002863 param_buf->wow_packet_buffer, 4);
2864 if (wow_buf_pkt_len >= sizeof(param)) {
2865 param.fixed_param =
2866 (wmi_rssi_breach_event_fixed_param *)
2867 (param_buf->wow_packet_buffer + 4);
2868 wma_rssi_breached_event_handler(handle,
2869 (u_int8_t *)&param,
2870 sizeof(param));
2871 } else {
2872 WMA_LOGE("%s: Wrong length: %d bytes",
2873 __func__, wow_buf_pkt_len);
2874 }
2875 } else
2876 WMA_LOGD("No wow_packet_buffer present");
2877 }
2878 break;
2879 default:
2880 break;
2881 }
2882
2883 if (wake_lock_duration) {
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302884 qdf_wake_lock_timeout_acquire(&wma->wow_wake_lock,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002885 wake_lock_duration,
2886 WIFI_POWER_EVENT_WAKELOCK_WOW);
2887 WMA_LOGA("Holding %d msec wake_lock", wake_lock_duration);
2888 }
2889
2890 return 0;
2891}
2892
2893/**
2894 * wma_pdev_resume_event_handler() - PDEV resume event handler
2895 * @handle: wma handle
2896 * @event: event data
2897 * @len: buffer length
2898 *
2899 * Return: 0 for success or error
2900 */
2901int wma_pdev_resume_event_handler(void *handle, uint8_t *event, uint32_t len)
2902{
2903 tp_wma_handle wma = (tp_wma_handle) handle;
2904
2905 WMA_LOGA("Received PDEV resume event");
2906
Anurag Chouhance0dc992016-02-16 18:18:03 +05302907 qdf_event_set(&wma->wma_resume_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002908
2909 return 0;
2910}
2911/**
2912 * wma_set_wow_bus_suspend() - set suspend flag
2913 * @wma: wma handle
2914 * @val: value
2915 *
2916 * Return: none
2917 */
2918static inline void wma_set_wow_bus_suspend(tp_wma_handle wma, int val)
2919{
2920
Anurag Chouhan8e0ccd32016-02-19 15:30:20 +05302921 qdf_atomic_set(&wma->is_wow_bus_suspended, val);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002922}
2923
2924
2925
2926/**
2927 * wma_add_wow_wakeup_event() - Configures wow wakeup events.
2928 * @wma: wma handle
2929 * @vdev_id: vdev id
2930 * @bitmap: Event bitmap
2931 * @enable: enable/disable
2932 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302933 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002934 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302935static QDF_STATUS wma_add_wow_wakeup_event(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002936 uint32_t vdev_id,
2937 uint32_t bitmap,
2938 bool enable)
2939{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002940 int ret;
2941
Govind Singhaa64c242016-03-08 11:31:49 +05302942 ret = wmi_unified_add_wow_wakeup_event_cmd(wma->wmi_handle, vdev_id,
2943 enable, bitmap);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002944 if (ret) {
2945 WMA_LOGE("Failed to config wow wakeup event");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302946 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002947 }
2948
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302949 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002950}
2951
2952/**
2953 * wma_send_wow_patterns_to_fw() - Sends WOW patterns to FW.
2954 * @wma: wma handle
2955 * @vdev_id: vdev id
2956 * @ptrn_id: pattern id
2957 * @ptrn: pattern
2958 * @ptrn_len: pattern length
2959 * @ptrn_offset: pattern offset
2960 * @mask: mask
2961 * @mask_len: mask length
2962 * @user: true for user configured pattern and false for default pattern
2963 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302964 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002965 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302966static QDF_STATUS wma_send_wow_patterns_to_fw(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002967 uint8_t vdev_id, uint8_t ptrn_id,
2968 const uint8_t *ptrn, uint8_t ptrn_len,
2969 uint8_t ptrn_offset, const uint8_t *mask,
2970 uint8_t mask_len, bool user)
2971{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002972 struct wma_txrx_node *iface;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002973 int ret;
Govind Singhaa64c242016-03-08 11:31:49 +05302974 uint8_t default_patterns;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002975
2976 iface = &wma->interfaces[vdev_id];
Govind Singhaa64c242016-03-08 11:31:49 +05302977 default_patterns = iface->num_wow_default_patterns++;
2978 ret = wmi_unified_wow_patterns_to_fw_cmd(wma->wmi_handle,
2979 vdev_id, ptrn_id, ptrn,
2980 ptrn_len, ptrn_offset, mask,
2981 mask_len, user, default_patterns);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002982 if (ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002983 if (!user)
2984 iface->num_wow_default_patterns--;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302985 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002986 }
2987
2988 if (user)
2989 iface->num_wow_user_patterns++;
2990
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302991 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002992}
2993
2994/**
2995 * wma_wow_ap() - set WOW patterns in ap mode
2996 * @wma: wma handle
2997 * @vdev_id: vdev id
2998 *
2999 * Configures default WOW pattern for the given vdev_id which is in AP mode.
3000 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303001 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003002 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303003static QDF_STATUS wma_wow_ap(tp_wma_handle wma, uint8_t vdev_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003004{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303005 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003006 uint8_t arp_offset = 20;
3007 uint8_t mac_mask[IEEE80211_ADDR_LEN];
3008
3009 /* Setup unicast pkt pattern */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303010 qdf_mem_set(&mac_mask, IEEE80211_ADDR_LEN, 0xFF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003011 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
3012 wma->interfaces[vdev_id].addr,
3013 IEEE80211_ADDR_LEN, 0, mac_mask,
3014 IEEE80211_ADDR_LEN, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303015 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003016 WMA_LOGE("Failed to add WOW unicast pattern ret %d", ret);
3017 return ret;
3018 }
3019
3020 /*
3021 * Setup all ARP pkt pattern. This is dummy pattern hence the length
3022 * is zero
3023 */
3024 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
3025 arp_ptrn, 0, arp_offset, arp_mask, 0, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303026 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003027 WMA_LOGE("Failed to add WOW ARP pattern ret %d", ret);
3028 return ret;
3029 }
3030
3031 return ret;
3032}
3033
3034/**
3035 * wma_wow_sta() - set WOW patterns in sta mode
3036 * @wma: wma handle
3037 * @vdev_id: vdev id
3038 *
3039 * Configures default WOW pattern for the given vdev_id which is in sta mode.
3040 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303041 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003042 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303043static QDF_STATUS wma_wow_sta(tp_wma_handle wma, uint8_t vdev_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003044{
3045 uint8_t arp_offset = 12;
3046 uint8_t discvr_offset = 30;
3047 uint8_t mac_mask[IEEE80211_ADDR_LEN];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303048 QDF_STATUS ret = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003049
3050 /* Setup unicast pkt pattern */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303051 qdf_mem_set(&mac_mask, IEEE80211_ADDR_LEN, 0xFF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003052 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
3053 wma->interfaces[vdev_id].addr,
3054 IEEE80211_ADDR_LEN, 0, mac_mask,
3055 IEEE80211_ADDR_LEN, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303056 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003057 WMA_LOGE("Failed to add WOW unicast pattern ret %d", ret);
3058 return ret;
3059 }
3060
3061 /*
3062 * Setup multicast pattern for mDNS 224.0.0.251,
3063 * SSDP 239.255.255.250 and LLMNR 224.0.0.252
3064 */
3065 if (wma->ssdp) {
3066 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
3067 discvr_ptrn, sizeof(discvr_ptrn), discvr_offset,
3068 discvr_mask, sizeof(discvr_ptrn), false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303069 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003070 WMA_LOGE("Failed to add WOW mDNS/SSDP/LLMNR pattern");
3071 return ret;
3072 }
3073 } else
3074 WMA_LOGD("mDNS, SSDP, LLMNR patterns are disabled from ini");
3075
3076 /* when arp offload or ns offloaded is disabled
3077 * from ini file, configure broad cast arp pattern
3078 * to fw, so that host can wake up
3079 */
3080 if (!(wma->ol_ini_info & 0x1)) {
3081 /* Setup all ARP pkt pattern */
3082 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
3083 arp_ptrn, sizeof(arp_ptrn), arp_offset,
3084 arp_mask, sizeof(arp_mask), false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303085 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003086 WMA_LOGE("Failed to add WOW ARP pattern");
3087 return ret;
3088 }
3089 }
3090
3091 /* for NS or NDP offload packets */
3092 if (!(wma->ol_ini_info & 0x2)) {
3093 /* Setup all NS pkt pattern */
3094 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
3095 ns_ptrn, sizeof(arp_ptrn), arp_offset,
3096 arp_mask, sizeof(arp_mask), false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303097 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003098 WMA_LOGE("Failed to add WOW NS pattern");
3099 return ret;
3100 }
3101 }
3102
3103 return ret;
3104}
3105
3106/**
3107 * wma_register_wow_default_patterns() - register default wow patterns with fw
3108 * @handle: Pointer to wma handle
3109 * @vdev_id: vdev id
3110 *
3111 * WoW default wake up pattern rule is:
3112 * - For STA & P2P CLI mode register for same STA specific wow patterns
3113 * - For SAP/P2P GO & IBSS mode register for same SAP specific wow patterns
3114 *
3115 * Return: none
3116 */
3117void wma_register_wow_default_patterns(WMA_HANDLE handle, uint8_t vdev_id)
3118{
3119 tp_wma_handle wma = handle;
3120 struct wma_txrx_node *iface;
3121
3122 if (vdev_id > wma->max_bssid) {
3123 WMA_LOGE("Invalid vdev id %d", vdev_id);
3124 return;
3125 }
3126 iface = &wma->interfaces[vdev_id];
3127
3128 if (iface->ptrn_match_enable) {
Houston Hoffman79b4af22015-10-06 12:01:08 -07003129 if (wma_is_vdev_in_beaconning_mode(wma, vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003130 /* Configure SAP/GO/IBSS mode default wow patterns */
3131 WMA_LOGI("Config SAP specific default wow patterns vdev_id %d",
3132 vdev_id);
3133 wma_wow_ap(wma, vdev_id);
3134 } else {
3135 /* Configure STA/P2P CLI mode default wow patterns */
3136 WMA_LOGI("Config STA specific default wow patterns vdev_id %d",
3137 vdev_id);
3138 wma_wow_sta(wma, vdev_id);
3139 if (wma->IsRArateLimitEnabled) {
3140 WMA_LOGI("Config STA RA limit wow patterns vdev_id %d",
3141 vdev_id);
3142 wma_wow_sta_ra_filter(wma, vdev_id);
3143 }
3144 }
3145 }
3146
3147 return;
3148}
3149
3150/**
3151 * wma_register_wow_wakeup_events() - register vdev specific wake events with fw
3152 * @handle: Pointer to wma handle
3153 * @vdev_id: vdev Id
3154 * @vdev_type: vdev type
3155 * @vdev_subtype: vdev sub type
3156 *
3157 * WoW wake up event rule is following:
3158 * 1) STA mode and P2P CLI mode wake up events are same
3159 * 2) SAP mode and P2P GO mode wake up events are same
3160 * 3) IBSS mode wake events are same as STA mode plus WOW_BEACON_EVENT
3161 *
3162 * Return: none
3163 */
3164void wma_register_wow_wakeup_events(WMA_HANDLE handle,
3165 uint8_t vdev_id,
3166 uint8_t vdev_type,
3167 uint8_t vdev_subtype)
3168{
3169 tp_wma_handle wma = handle;
3170 uint32_t event_bitmap;
3171
3172 WMA_LOGI("vdev_type %d vdev_subtype %d vdev_id %d", vdev_type,
3173 vdev_subtype, vdev_id);
3174
3175 if ((WMI_VDEV_TYPE_STA == vdev_type) ||
3176 ((WMI_VDEV_TYPE_AP == vdev_type) &&
3177 (WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE == vdev_subtype))) {
3178 /* Configure STA/P2P CLI mode specific default wake up events */
3179 event_bitmap = WMA_WOW_STA_WAKE_UP_EVENTS;
3180 WMA_LOGI("STA specific default wake up event 0x%x vdev id %d",
3181 event_bitmap, vdev_id);
3182 } else if (WMI_VDEV_TYPE_IBSS == vdev_type) {
3183 /* Configure IBSS mode specific default wake up events */
3184 event_bitmap = (WMA_WOW_STA_WAKE_UP_EVENTS |
3185 (1 << WOW_BEACON_EVENT));
3186 WMA_LOGI("IBSS specific default wake up event 0x%x vdev id %d",
3187 event_bitmap, vdev_id);
3188 } else if (WMI_VDEV_TYPE_AP == vdev_type) {
3189 /* Configure SAP/GO mode specific default wake up events */
3190 event_bitmap = WMA_WOW_SAP_WAKE_UP_EVENTS;
3191 WMA_LOGI("SAP specific default wake up event 0x%x vdev id %d",
3192 event_bitmap, vdev_id);
3193 } else {
3194 WMA_LOGE("unknown type %d subtype %d", vdev_type, vdev_subtype);
3195 return;
3196 }
3197
3198 wma_add_wow_wakeup_event(wma, vdev_id, event_bitmap, true);
3199
3200 return;
3201}
3202
3203/**
3204 * wma_enable_disable_wakeup_event() - Configures wow wakeup events
3205 * @wma: wma handle
3206 * @vdev_id: vdev id
3207 * @bitmap: Event bitmap
3208 * @enable: enable/disable
3209 *
3210 * Return: none
3211 */
3212void wma_enable_disable_wakeup_event(WMA_HANDLE handle,
3213 uint32_t vdev_id,
3214 uint32_t bitmap,
3215 bool enable)
3216{
3217 tp_wma_handle wma = handle;
3218
3219 WMA_LOGI("vdev_id %d wake up event 0x%x enable %d",
3220 vdev_id, bitmap, enable);
3221 wma_add_wow_wakeup_event(wma, vdev_id, bitmap, enable);
3222}
3223
3224/**
3225 * wma_enable_wow_in_fw() - wnable wow in fw
3226 * @wma: wma handle
3227 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303228 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003229 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303230QDF_STATUS wma_enable_wow_in_fw(WMA_HANDLE handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003231{
3232 tp_wma_handle wma = handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003233 int ret;
Komal Seelam3d202862016-02-24 18:43:24 +05303234 struct hif_opaque_softc *scn;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003235 int host_credits;
3236 int wmi_pending_cmds;
Govind Singhd76a5b02016-03-08 15:12:14 +05303237 struct wow_cmd_params param = {0};
3238
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003239#ifdef CONFIG_CNSS
Anurag Chouhan6d760662016-02-20 16:05:43 +05303240 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003241
3242 if (NULL == pMac) {
3243 WMA_LOGE("%s: Unable to get PE context", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303244 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003245 }
3246#endif /* CONFIG_CNSS */
3247
Anurag Chouhance0dc992016-02-16 18:18:03 +05303248 qdf_event_reset(&wma->target_suspend);
Houston Hoffmana769ed32016-04-14 17:02:51 -07003249 wma->wow_nack = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003250
3251 host_credits = wmi_get_host_credits(wma->wmi_handle);
3252 wmi_pending_cmds = wmi_get_pending_cmds(wma->wmi_handle);
3253
3254 WMA_LOGD("Credits:%d; Pending_Cmds: %d",
3255 host_credits, wmi_pending_cmds);
3256
3257 if (host_credits < WMI_WOW_REQUIRED_CREDITS) {
3258 WMA_LOGE("%s: Host Doesn't have enough credits to Post WMI_WOW_ENABLE_CMDID! "
3259 "Credits:%d, pending_cmds:%d\n", __func__, host_credits,
3260 wmi_pending_cmds);
3261#ifndef QCA_WIFI_3_0_EMU
3262 goto error;
3263#endif
3264 }
3265
Govind Singhd76a5b02016-03-08 15:12:14 +05303266 param.enable = true;
3267 param.can_suspend_link = hif_can_suspend_link(wma->htc_handle);
3268 ret = wmi_unified_wow_enable_send(wma->wmi_handle, &param,
3269 WMA_WILDCARD_PDEV_ID);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003270 if (ret) {
3271 WMA_LOGE("Failed to enable wow in fw");
3272 goto error;
3273 }
3274
3275 wmi_set_target_suspend(wma->wmi_handle, true);
3276
Anurag Chouhance0dc992016-02-16 18:18:03 +05303277 if (qdf_wait_single_event(&wma->target_suspend,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003278 WMA_TGT_SUSPEND_COMPLETE_TIMEOUT)
Anurag Chouhance0dc992016-02-16 18:18:03 +05303279 != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003280 WMA_LOGE("Failed to receive WoW Enable Ack from FW");
3281 WMA_LOGE("Credits:%d; Pending_Cmds: %d",
3282 wmi_get_host_credits(wma->wmi_handle),
3283 wmi_get_pending_cmds(wma->wmi_handle));
Prashanth Bhatta9e143052015-12-04 11:56:47 -08003284 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003285#ifdef CONFIG_CNSS
Yue Ma455aff62015-10-20 18:29:16 -07003286 if (pMac->sme.enableSelfRecovery) {
3287 cds_trigger_recovery();
3288 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303289 QDF_BUG(0);
Yue Ma455aff62015-10-20 18:29:16 -07003290 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003291#else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303292 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003293#endif /* CONFIG_CNSS */
Yue Ma455aff62015-10-20 18:29:16 -07003294 } else {
3295 WMA_LOGE("%s: LOGP is in progress, ignore!", __func__);
3296 }
3297
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003298 wmi_set_target_suspend(wma->wmi_handle, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303299 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003300 }
3301
3302 if (wma->wow_nack) {
3303 WMA_LOGE("FW not ready to WOW");
3304 wmi_set_target_suspend(wma->wmi_handle, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303305 return QDF_STATUS_E_AGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003306 }
3307
3308 host_credits = wmi_get_host_credits(wma->wmi_handle);
3309 wmi_pending_cmds = wmi_get_pending_cmds(wma->wmi_handle);
3310
3311 if (host_credits < WMI_WOW_REQUIRED_CREDITS) {
3312 WMA_LOGE("%s: No Credits after HTC ACK:%d, pending_cmds:%d, "
3313 "cannot resume back", __func__, host_credits,
3314 wmi_pending_cmds);
3315 htc_dump_counter_info(wma->htc_handle);
Prashanth Bhatta9e143052015-12-04 11:56:47 -08003316 if (!cds_is_driver_recovering())
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303317 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003318 else
3319 WMA_LOGE("%s: SSR in progress, ignore no credit issue",
3320 __func__);
3321 }
3322
3323 WMA_LOGD("WOW enabled successfully in fw: credits:%d"
3324 "pending_cmds: %d", host_credits, wmi_pending_cmds);
3325
Anurag Chouhan6d760662016-02-20 16:05:43 +05303326 scn = cds_get_context(QDF_MODULE_ID_HIF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003327
3328 if (scn == NULL) {
3329 WMA_LOGE("%s: Failed to get HIF context", __func__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303330 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303331 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003332 }
3333
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003334 wma->wow.wow_enable_cmd_sent = true;
3335
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303336 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003337
3338error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303339 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003340}
3341
3342/**
3343 * wma_resume_req() - clear configured wow patterns in fw
3344 * @wma: wma handle
Houston Hoffmana76591b2015-11-10 16:52:05 -08003345 * @type: type of suspend
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003346 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303347 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003348 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05303349QDF_STATUS wma_resume_req(tp_wma_handle wma, enum qdf_suspend_type type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003350{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303351 if (type == QDF_SYSTEM_SUSPEND) {
Houston Hoffmana76591b2015-11-10 16:52:05 -08003352 wma->no_of_resume_ind++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003353
Houston Hoffmana76591b2015-11-10 16:52:05 -08003354 if (wma->no_of_resume_ind < wma_get_vdev_count(wma))
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303355 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003356
Houston Hoffmana76591b2015-11-10 16:52:05 -08003357 wma->no_of_resume_ind = 0;
3358 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003359
3360 /* Reset the DTIM Parameters */
3361 wma_set_resume_dtim(wma);
3362 /* need to reset if hif_pci_suspend_fails */
3363 wma_set_wow_bus_suspend(wma, 0);
3364 /* unpause the vdev if left paused and hif_pci_suspend fails */
3365 wma_unpause_vdev(wma);
3366
Houston Hoffman1460fa32015-11-18 02:36:30 -08003367 wmi_set_runtime_pm_inprogress(wma->wmi_handle, false);
3368
Houston Hoffmanc45db892015-11-13 19:59:25 -08003369 if (type == QDF_RUNTIME_SUSPEND)
3370 qdf_runtime_pm_allow_suspend(wma->wma_runtime_resume_lock);
3371
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303372 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003373}
3374
3375/**
3376 * wma_wow_delete_pattern() - delete wow pattern in target
3377 * @wma: wma handle
3378 * @ptrn_id: pattern id
3379 * @vdev_id: vdev id
3380 * @user: true for user pattern and false for default pattern
3381 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303382 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003383 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303384static QDF_STATUS wma_wow_delete_pattern(tp_wma_handle wma, uint8_t ptrn_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003385 uint8_t vdev_id, bool user)
3386{
Govind Singhaa64c242016-03-08 11:31:49 +05303387
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003388 struct wma_txrx_node *iface;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003389 int ret;
3390
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003391 iface = &wma->interfaces[vdev_id];
Govind Singhaa64c242016-03-08 11:31:49 +05303392 ret = wmi_unified_wow_delete_pattern_cmd(wma->wmi_handle, ptrn_id,
3393 vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003394 if (ret) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303395 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003396 }
3397
3398 if (user)
3399 iface->num_wow_user_patterns--;
3400
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303401 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003402}
3403
3404/**
3405 * wma_wow_add_pattern() - add wow pattern in target
3406 * @wma: wma handle
3407 * @ptrn: wow pattern
3408 *
3409 * This function does following:
3410 * 1) Delete all default patterns of the vdev
3411 * 2) Add received wow patterns for given vdev in target.
3412 *
3413 * Target is responsible for caching wow patterns accross multiple
3414 * suspend/resumes until the pattern is deleted by user
3415 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303416 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003417 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303418QDF_STATUS wma_wow_add_pattern(tp_wma_handle wma, struct wow_add_pattern *ptrn)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003419{
3420 uint8_t id;
3421 uint8_t bit_to_check, pos;
3422 struct wma_txrx_node *iface;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303423 QDF_STATUS ret = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003424 uint8_t new_mask[SIR_WOWL_BCAST_PATTERN_MAX_SIZE];
3425
3426 if (ptrn->session_id > wma->max_bssid) {
3427 WMA_LOGE("Invalid vdev id (%d)", ptrn->session_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303428 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003429 }
3430
3431 iface = &wma->interfaces[ptrn->session_id];
3432
3433 /* clear all default patterns cofigured by wma */
3434 for (id = 0; id < iface->num_wow_default_patterns; id++)
3435 wma_wow_delete_pattern(wma, id, ptrn->session_id, false);
3436
3437 iface->num_wow_default_patterns = 0;
3438
3439 WMA_LOGI("Add user passed wow pattern id %d vdev id %d",
3440 ptrn->pattern_id, ptrn->session_id);
3441 /*
3442 * Convert received pattern mask value from bit representation
3443 * to byte representation.
3444 *
3445 * For example, received value from umac,
3446 *
3447 * Mask value : A1 (equivalent binary is "1010 0001")
3448 * Pattern value : 12:00:13:00:00:00:00:44
3449 *
3450 * The value which goes to FW after the conversion from this
3451 * function (1 in mask value will become FF and 0 will
3452 * become 00),
3453 *
3454 * Mask value : FF:00:FF:00:0:00:00:FF
3455 * Pattern value : 12:00:13:00:00:00:00:44
3456 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303457 qdf_mem_zero(new_mask, sizeof(new_mask));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003458 for (pos = 0; pos < ptrn->pattern_size; pos++) {
3459 bit_to_check = (WMA_NUM_BITS_IN_BYTE - 1) -
3460 (pos % WMA_NUM_BITS_IN_BYTE);
3461 bit_to_check = 0x1 << bit_to_check;
3462 if (ptrn->pattern_mask[pos / WMA_NUM_BITS_IN_BYTE] &
3463 bit_to_check)
3464 new_mask[pos] = WMA_WOW_PTRN_MASK_VALID;
3465 }
3466
3467 ret = wma_send_wow_patterns_to_fw(wma, ptrn->session_id,
3468 ptrn->pattern_id,
3469 ptrn->pattern, ptrn->pattern_size,
3470 ptrn->pattern_byte_offset, new_mask,
3471 ptrn->pattern_size, true);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303472 if (ret != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003473 WMA_LOGE("Failed to add wow pattern %d", ptrn->pattern_id);
3474
3475 return ret;
3476}
3477
3478/**
3479 * wma_wow_delete_user_pattern() - delete user configured wow pattern in target
3480 * @wma: wma handle
3481 * @ptrn: wow pattern
3482 *
3483 * This function does following:
3484 * 1) Deletes a particular user configured wow pattern in target
3485 * 2) After deleting all user wow patterns add default wow patterns
3486 * specific to that vdev.
3487 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303488 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003489 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303490QDF_STATUS wma_wow_delete_user_pattern(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003491 struct wow_delete_pattern *pattern)
3492{
3493 struct wma_txrx_node *iface;
3494
3495 if (pattern->session_id > wma->max_bssid) {
3496 WMA_LOGE("Invalid vdev id %d", pattern->session_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303497 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003498 }
3499
3500 iface = &wma->interfaces[pattern->session_id];
3501 if (iface->num_wow_user_patterns <= 0) {
3502 WMA_LOGE("No valid user pattern. Num user pattern %u vdev %d",
3503 iface->num_wow_user_patterns, pattern->session_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303504 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003505 }
3506
3507 WMA_LOGI("Delete user passed wow pattern id %d total user pattern %d",
3508 pattern->pattern_id, iface->num_wow_user_patterns);
3509
3510 wma_wow_delete_pattern(wma, pattern->pattern_id,
3511 pattern->session_id, true);
3512
3513 /* configure default patterns once all user patterns are deleted */
3514 if (!iface->num_wow_user_patterns)
3515 wma_register_wow_default_patterns(wma, pattern->session_id);
3516
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303517 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003518}
3519
3520/**
3521 * wma_wow_enter() - store enable/disable status for pattern
3522 * @wma: wma handle
3523 * @info: wow parameters
3524 *
3525 * Records pattern enable/disable status locally. This choice will
3526 * take effect when the driver enter into suspend state.
3527 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303528 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003529 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303530QDF_STATUS wma_wow_enter(tp_wma_handle wma, tpSirHalWowlEnterParams info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003531{
3532 struct wma_txrx_node *iface;
3533
3534 WMA_LOGD("wow enable req received for vdev id: %d", info->sessionId);
3535
3536 if (info->sessionId > wma->max_bssid) {
3537 WMA_LOGE("Invalid vdev id (%d)", info->sessionId);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303538 qdf_mem_free(info);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303539 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003540 }
3541
3542 iface = &wma->interfaces[info->sessionId];
3543 iface->ptrn_match_enable = info->ucPatternFilteringEnable ?
3544 true : false;
3545 wma->wow.magic_ptrn_enable = info->ucMagicPktEnable ? true : false;
3546 wma->wow.deauth_enable = info->ucWowDeauthRcv ? true : false;
3547 wma->wow.disassoc_enable = info->ucWowDeauthRcv ? true : false;
3548 wma->wow.bmiss_enable = info->ucWowMaxMissedBeacons ? true : false;
3549
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303550 qdf_mem_free(info);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003551
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303552 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003553}
3554
3555/**
3556 * wma_wow_exit() - clear all wma states
3557 * @wma: wma handle
3558 * @info: wow params
3559 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303560 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003561 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303562QDF_STATUS wma_wow_exit(tp_wma_handle wma, tpSirHalWowlExitParams info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003563{
3564 struct wma_txrx_node *iface;
3565
3566 WMA_LOGD("wow disable req received for vdev id: %d", info->sessionId);
3567
3568 if (info->sessionId > wma->max_bssid) {
3569 WMA_LOGE("Invalid vdev id (%d)", info->sessionId);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303570 qdf_mem_free(info);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303571 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003572 }
3573
3574 iface = &wma->interfaces[info->sessionId];
3575 iface->ptrn_match_enable = false;
3576 wma->wow.magic_ptrn_enable = false;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303577 qdf_mem_free(info);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003578
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303579 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003580}
3581
3582/**
Houston Hoffmana76591b2015-11-10 16:52:05 -08003583 * wma_calculate_and_update_conn_state(): calculate each interfaces conn state
3584 * @wma: validated wma handle
3585 *
3586 * Identifies any vdev that is up and not in ap mode as connected.
3587 * stores this in the interfaces conn_state varible.
3588 */
3589void wma_calculate_and_update_conn_state(tp_wma_handle wma)
3590{
3591 int i;
3592 for (i = 0; i < wma->max_bssid; i++) {
3593 wma->interfaces[i].conn_state =
3594 !!(wma->interfaces[i].vdev_up &&
3595 !wma_is_vdev_in_ap_mode(wma, i));
3596 }
3597}
3598
3599/**
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003600 * wma_update_conn_state(): synchronize wma & hdd
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003601 * @wma: wma handle
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003602 * @conn_state: boolean array to populate
3603 * @len: validation parameter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003604 *
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003605 * populate interfaces conn_state with true if the interface
3606 * is a connected client and wow will configure a pattern.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003607 */
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003608void wma_update_conn_state(tp_wma_handle wma, uint32_t conn_mask)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003609{
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003610 int i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003611 for (i = 0; i < wma->max_bssid; i++) {
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003612 if (conn_mask & (1 << i))
3613 wma->interfaces[i].conn_state = true;
3614 else
3615 wma->interfaces[i].conn_state = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003616 }
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003617
3618 if (wma->wow.magic_ptrn_enable)
3619 return;
3620
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003621 for (i = 0; i < wma->max_bssid; i++) {
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003622 if (!wma->interfaces[i].ptrn_match_enable)
3623 wma->interfaces[i].conn_state = false;
3624 }
3625}
3626
3627/**
3628 * wma_is_beaconning_vdev_up(): check if a beaconning vdev is up
3629 * @wma: wma handle
3630 *
3631 * Return TRUE if beaconning vdev is up
3632 */
3633static inline
3634bool wma_is_beaconning_vdev_up(tp_wma_handle wma)
3635{
3636 int i;
3637 for (i = 0; i < wma->max_bssid; i++) {
3638 if (wma_is_vdev_in_beaconning_mode(wma, i)
3639 && wma->interfaces[i].vdev_up)
3640 return true;
3641 }
3642 return false;
3643}
3644
3645/**
3646 * wma_support_wow_for_beaconing: wow query for beaconning
3647 * @wma: wma handle
3648 *
3649 * Need to configure wow to enable beaconning offload when
3650 * a beaconing vdev is up and beaonning offload is configured.
3651 *
3652 * Return: true if we need to enable wow for beaconning offload
3653 */
3654static inline
3655bool wma_support_wow_for_beaconing(tp_wma_handle wma)
3656{
3657 if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
3658 WMI_SERVICE_BEACON_OFFLOAD)) {
3659 if (wma_is_beaconning_vdev_up(wma))
3660 return true;
3661 }
3662 return false;
3663}
3664
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003665#ifdef FEATURE_WLAN_SCAN_PNO
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003666/**
3667 * wma_is_pnoscan_in_progress(): check if a pnoscan is in progress
3668 * @wma: wma handle
3669 * @vdev_id: vdev_id
3670 *
3671 * Return: TRUE/FALSE
3672 */
3673static inline
3674bool wma_is_pnoscan_in_progress(tp_wma_handle wma, int vdev_id)
3675{
3676 return wma->interfaces[vdev_id].pno_in_progress;
3677}
Houston Hoffman345fa402015-12-16 11:28:51 -08003678
3679/**
3680 * wma_is_pnoscan_match_found(): check if a scan match was found
3681 * @wma: wma handle
3682 * @vdev_id: vdev_id
3683 *
3684 * Return: TRUE/FALSE
3685 */
3686static inline
3687bool wma_is_pnoscan_match_found(tp_wma_handle wma, int vdev_id)
3688{
3689 return wma->interfaces[vdev_id].nlo_match_evt_received;
3690}
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003691#else
3692/**
3693 * wma_is_pnoscan_in_progress(): dummy
3694 *
Houston Hoffman345fa402015-12-16 11:28:51 -08003695 * Return: False since no pnoscan cannot be in progress
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003696 * when feature flag is not defined.
3697 */
3698bool wma_is_pnoscan_in_progress(tp_wma_handle wma, int vdev_id)
3699{
3700 return FALSE;
3701}
Houston Hoffman345fa402015-12-16 11:28:51 -08003702
3703/**
3704 * wma_is_pnoscan_match_found(): dummy
3705 * @wma: wma handle
3706 * @vdev_id: vdev_id
3707 *
3708 * Return: False since no pnoscan cannot occur
3709 * when feature flag is not defined.
3710 */
3711static inline
3712bool wma_is_pnoscan_match_found(tp_wma_handle wma, int vdev_id)
3713{
3714 return FALSE;
3715}
Houston Hoffman61667962015-12-15 20:15:41 -08003716#endif
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003717
3718#ifdef FEATURE_WLAN_EXTSCAN
3719static inline
3720/**
3721 * wma_is_extscan_in_progress(): check if an extscan is in progress
3722 * @wma: wma handle
3723 * @vdev_id: vdev_id
3724 *
3725 * Return: TRUE/FALSvE
3726 */
3727bool wma_is_extscan_in_progress(tp_wma_handle wma, int vdev_id)
3728{
3729 return wma->interfaces[vdev_id].extscan_in_progress;
3730}
3731#else
3732/**
3733 * wma_is_extscan_in_progress(): dummy
3734 *
3735 * Return: False since no extscan can be in progress
3736 * when feature flag is not defined.
3737 */
3738bool wma_is_extscan_in_progress(tp_wma_handle wma, int vdev_id)
3739{
3740 return false;
3741}
3742#endif
3743
3744/**
3745 * wma_is_wow_applicable(): should enable wow
3746 * @wma: wma handle
3747 *
3748 * Enable WOW if any one of the condition meets,
3749 * 1) Is any one of vdev in beaconning mode (in AP mode) ?
3750 * 2) Is any one of vdev in connected state (in STA mode) ?
3751 * 3) Is PNO in progress in any one of vdev ?
3752 * 4) Is Extscan in progress in any one of vdev ?
Rajeev Kumaraea89632016-02-02 18:02:32 -08003753 * If none of above conditions is true then return false
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003754 *
Rajeev Kumaraea89632016-02-02 18:02:32 -08003755 * Return: true if wma needs to configure wow false otherwise.
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003756 */
3757bool wma_is_wow_applicable(tp_wma_handle wma)
3758{
3759 int vdev_id;
3760 if (wma_support_wow_for_beaconing(wma)) {
3761 WMA_LOGD("vdev is in beaconning mode, enabling wow");
3762 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003763 }
3764
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003765 for (vdev_id = 0; vdev_id < wma->max_bssid; vdev_id++) {
3766 if (wma->interfaces[vdev_id].conn_state) {
3767 WMA_LOGD("STA is connected, enabling wow");
3768 return true;
3769 } else if (wma_is_pnoscan_in_progress(wma, vdev_id)) {
3770 WMA_LOGD("PNO is in progress, enabling wow");
3771 return true;
3772 } else if (wma_is_extscan_in_progress(wma, vdev_id)) {
3773 WMA_LOGD("EXT is in progress, enabling wow");
3774 return true;
3775 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003776 }
3777
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003778 WMA_LOGD("All vdev are in disconnected state and pno/extscan is not in progress, skipping wow");
Rajeev Kumaraea89632016-02-02 18:02:32 -08003779 return false;
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003780}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003781
Houston Hoffman345fa402015-12-16 11:28:51 -08003782/**
3783 * wma_configure_dynamic_wake_events(): configure dyanmic wake events
3784 * @wma: wma handle
3785 *
3786 * Some wake events need to be enabled dynamically. Controll those here.
3787 *
3788 * Return: none
3789 */
3790void wma_configure_dynamic_wake_events(tp_wma_handle wma)
3791{
3792 int vdev_id;
3793 int enable_mask;
3794 int disable_mask;
3795
3796 for (vdev_id = 0; vdev_id < wma->max_bssid; vdev_id++) {
3797 enable_mask = 0;
3798 disable_mask = 0;
3799
3800 if (wma_is_pnoscan_in_progress(wma, vdev_id)) {
3801 if (wma_is_pnoscan_match_found(wma, vdev_id))
3802 enable_mask |=
3803 (1 << WOW_NLO_SCAN_COMPLETE_EVENT);
3804 else
3805 disable_mask |=
3806 (1 << WOW_NLO_SCAN_COMPLETE_EVENT);
3807 }
3808
3809 if (enable_mask != 0)
3810 wma_enable_disable_wakeup_event(wma, vdev_id,
3811 enable_mask, true);
3812 if (disable_mask != 0)
3813 wma_enable_disable_wakeup_event(wma, vdev_id,
3814 disable_mask, false);
3815 }
3816}
3817
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003818#ifdef FEATURE_WLAN_LPHB
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003819/**
3820 * wma_apply_lphb(): apply cached LPHB settings
3821 * @wma: wma handle
3822 *
3823 * LPHB cache, if any item was enabled, should be
3824 * applied.
3825 */
3826static inline
3827void wma_apply_lphb(tp_wma_handle wma)
3828{
3829 int i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003830 WMA_LOGD("%s: checking LPHB cache", __func__);
3831 for (i = 0; i < 2; i++) {
3832 if (wma->wow.lphb_cache[i].params.lphbEnableReq.enable) {
3833 WMA_LOGD("%s: LPHB cache for item %d is marked as enable",
3834 __func__, i + 1);
3835 wma_lphb_conf_hbenable(wma, &(wma->wow.lphb_cache[i]),
3836 false);
3837 }
3838 }
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003839}
3840#else
3841void wma_apply_lphb(tp_wma_handle wma) {}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003842#endif /* FEATURE_WLAN_LPHB */
3843
Houston Hoffmana76591b2015-11-10 16:52:05 -08003844static void wma_notify_suspend_req_procesed(tp_wma_handle wma,
Anurag Chouhan6d760662016-02-20 16:05:43 +05303845 enum qdf_suspend_type type)
Houston Hoffmana76591b2015-11-10 16:52:05 -08003846{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303847 if (type == QDF_SYSTEM_SUSPEND)
Houston Hoffmana76591b2015-11-10 16:52:05 -08003848 wma_send_status_to_suspend_ind(wma, true);
Anurag Chouhan6d760662016-02-20 16:05:43 +05303849 else if (type == QDF_RUNTIME_SUSPEND)
Anurag Chouhance0dc992016-02-16 18:18:03 +05303850 qdf_event_set(&wma->runtime_suspend);
Houston Hoffmana76591b2015-11-10 16:52:05 -08003851}
3852
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003853/**
3854 * wma_suspend_req() - Handles suspend indication request received from umac.
3855 * @wma: wma handle
Houston Hoffmana76591b2015-11-10 16:52:05 -08003856 * @type: type of suspend
3857 *
3858 * The type controlls how we notify the indicator that the indication has
3859 * been processed
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003860 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303861 * Return: QDF status
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003862 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05303863QDF_STATUS wma_suspend_req(tp_wma_handle wma, enum qdf_suspend_type type)
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003864{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303865 if (type == QDF_RUNTIME_SUSPEND)
Houston Hoffman1460fa32015-11-18 02:36:30 -08003866 wmi_set_runtime_pm_inprogress(wma->wmi_handle, true);
3867
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003868 if (wma_is_wow_applicable(wma)) {
3869 WMA_LOGE("WOW Suspend");
3870 wma_apply_lphb(wma);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003871
Houston Hoffman345fa402015-12-16 11:28:51 -08003872 wma_configure_dynamic_wake_events(wma);
3873
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003874 wma->wow.wow_enable = true;
3875 wma->wow.wow_enable_cmd_sent = false;
3876 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003877
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003878 /* Set the Suspend DTIM Parameters */
3879 wma_set_suspend_dtim(wma);
Houston Hoffmana76591b2015-11-10 16:52:05 -08003880
3881 wma_notify_suspend_req_procesed(wma, type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003882
3883 /* to handle race between hif_pci_suspend and
3884 * unpause/pause tx handler
3885 */
3886 wma_set_wow_bus_suspend(wma, 1);
3887
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303888 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003889}
3890
3891/**
3892 * wma_send_host_wakeup_ind_to_fw() - send wakeup ind to fw
3893 * @wma: wma handle
3894 *
3895 * Sends host wakeup indication to FW. On receiving this indication,
3896 * FW will come out of WOW.
3897 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303898 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003899 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303900static QDF_STATUS wma_send_host_wakeup_ind_to_fw(tp_wma_handle wma)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003901{
Anurag Chouhance0dc992016-02-16 18:18:03 +05303902 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003903 int ret;
3904#ifdef CONFIG_CNSS
Anurag Chouhan6d760662016-02-20 16:05:43 +05303905 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003906 if (NULL == pMac) {
3907 WMA_LOGE("%s: Unable to get PE context", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303908 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003909 }
3910#endif /* CONFIG_CNSS */
3911
Anurag Chouhance0dc992016-02-16 18:18:03 +05303912 qdf_event_reset(&wma->wma_resume_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003913
Govind Singhaa64c242016-03-08 11:31:49 +05303914 ret = wmi_unified_host_wakeup_ind_to_fw_cmd(wma->wmi_handle);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003915 if (ret) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303916 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003917 }
3918
3919 WMA_LOGD("Host wakeup indication sent to fw");
3920
Anurag Chouhance0dc992016-02-16 18:18:03 +05303921 qdf_status = qdf_wait_single_event(&(wma->wma_resume_event),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003922 WMA_RESUME_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05303923 if (QDF_STATUS_SUCCESS != qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003924 WMA_LOGP("%s: Timeout waiting for resume event from FW",
3925 __func__);
3926 WMA_LOGP("%s: Pending commands %d credits %d", __func__,
3927 wmi_get_pending_cmds(wma->wmi_handle),
3928 wmi_get_host_credits(wma->wmi_handle));
Prashanth Bhatta9e143052015-12-04 11:56:47 -08003929 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003930#ifdef CONFIG_CNSS
3931 if (pMac->sme.enableSelfRecovery) {
3932 cds_trigger_recovery();
3933 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303934 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003935 }
3936#else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303937 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003938#endif /* CONFIG_CNSS */
3939 } else {
3940 WMA_LOGE("%s: SSR in progress, ignore resume timeout",
3941 __func__);
3942 }
3943 } else {
3944 WMA_LOGD("Host wakeup received");
3945 }
3946
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303947 if (QDF_STATUS_SUCCESS == qdf_status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003948 wmi_set_target_suspend(wma->wmi_handle, false);
3949
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303950 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003951}
3952
3953/**
3954 * wma_disable_wow_in_fw() - Disable wow in PCIe resume context.
3955 * @handle: wma handle
3956 *
3957 * Return: 0 for success or error code
3958 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303959QDF_STATUS wma_disable_wow_in_fw(WMA_HANDLE handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003960{
3961 tp_wma_handle wma = handle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303962 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003963
3964 if (!wma->wow.wow_enable || !wma->wow.wow_enable_cmd_sent)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303965 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003966
3967 ret = wma_send_host_wakeup_ind_to_fw(wma);
3968
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303969 if (ret != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003970 return ret;
3971
3972 wma->wow.wow_enable = false;
3973 wma->wow.wow_enable_cmd_sent = false;
3974
3975 /* To allow the tx pause/unpause events */
3976 wma_set_wow_bus_suspend(wma, 0);
3977 /* Unpause the vdev as we are resuming */
3978 wma_unpause_vdev(wma);
3979
3980 return ret;
3981}
3982
3983#ifdef WLAN_FEATURE_LPSS
3984/**
3985 * wma_is_lpass_enabled() - check if lpass is enabled
3986 * @handle: Pointer to wma handle
3987 *
3988 * WoW is needed if LPASS or NaN feature is enabled in INI because
3989 * target can't wake up itself if its put in PDEV suspend when LPASS
3990 * or NaN features are supported
3991 *
3992 * Return: true if lpass is enabled else false
3993 */
3994bool static wma_is_lpass_enabled(tp_wma_handle wma)
3995{
3996 if (wma->is_lpass_enabled)
3997 return true;
3998 else
3999 return false;
4000}
4001#else
4002bool static wma_is_lpass_enabled(tp_wma_handle wma)
4003{
4004 return false;
4005}
4006#endif
4007
4008#ifdef WLAN_FEATURE_NAN
4009/**
4010 * wma_is_nan_enabled() - check if NaN is enabled
4011 * @handle: Pointer to wma handle
4012 *
4013 * WoW is needed if LPASS or NaN feature is enabled in INI because
4014 * target can't wake up itself if its put in PDEV suspend when LPASS
4015 * or NaN features are supported
4016 *
4017 * Return: true if NaN is enabled else false
4018 */
4019bool static wma_is_nan_enabled(tp_wma_handle wma)
4020{
4021 if (wma->is_nan_enabled)
4022 return true;
4023 else
4024 return false;
4025}
4026#else
4027bool static wma_is_nan_enabled(tp_wma_handle wma)
4028{
4029 return false;
4030}
4031#endif
4032
4033/**
4034 * wma_is_wow_mode_selected() - check if wow needs to be enabled in fw
4035 * @handle: Pointer to wma handle
4036 *
4037 * If lpass is enabled then always do wow else check wow_enable config
4038 *
4039 * Return: true is wow mode is needed else false
4040 */
Houston Hoffmana76591b2015-11-10 16:52:05 -08004041bool wma_is_wow_mode_selected(WMA_HANDLE handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004042{
4043 tp_wma_handle wma = (tp_wma_handle) handle;
4044
4045 if (wma_is_lpass_enabled(wma)) {
4046 WMA_LOGD("LPASS is enabled select WoW");
4047 return true;
4048 } else if (wma_is_nan_enabled(wma)) {
4049 WMA_LOGD("NAN is enabled select WoW");
4050 return true;
4051 } else {
4052 WMA_LOGD("WoW enable %d", wma->wow.wow_enable);
4053 return wma->wow.wow_enable;
4054 }
4055}
4056
4057/**
4058 * wma_del_ts_req() - send DELTS request to fw
4059 * @wma: wma handle
4060 * @msg: delts params
4061 *
4062 * Return: none
4063 */
4064void wma_del_ts_req(tp_wma_handle wma, tDelTsParams *msg)
4065{
Govind Singhaa64c242016-03-08 11:31:49 +05304066 if (wmi_unified_del_ts_cmd(wma->wmi_handle,
4067 msg->sessionId,
4068 TID_TO_WME_AC(msg->userPrio))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004069 WMA_LOGP("%s: Failed to send vdev DELTS command", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004070 }
Govind Singhaa64c242016-03-08 11:31:49 +05304071
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004072#ifdef WLAN_FEATURE_ROAM_OFFLOAD
4073 if (msg->setRICparams == true)
4074 wma_set_ric_req(wma, msg, false);
4075#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
4076
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304077 qdf_mem_free(msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004078}
4079
4080/**
4081 * wma_aggr_qos_req() - send aggr qos request to fw
4082 * @wma: handle to wma
4083 * @pAggrQosRspMsg - combined struct for all ADD_TS requests.
4084 *
4085 * A function to handle WMA_AGGR_QOS_REQ. This will send out
4086 * ADD_TS requestes to firmware in loop for all the ACs with
4087 * active flow.
4088 *
4089 * Return: none
4090 */
4091void wma_aggr_qos_req(tp_wma_handle wma,
4092 tAggrAddTsParams *pAggrQosRspMsg)
4093{
Govind Singhaa64c242016-03-08 11:31:49 +05304094 wmi_unified_aggr_qos_cmd(wma->wmi_handle,
4095 (struct aggr_add_ts_param *)pAggrQosRspMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004096 /* send reponse to upper layers from here only. */
4097 wma_send_msg(wma, WMA_AGGR_QOS_RSP, pAggrQosRspMsg, 0);
4098}
4099
4100/**
4101 * wma_add_ts_req() - send ADDTS request to fw
4102 * @wma: wma handle
4103 * @msg: ADDTS params
4104 *
4105 * Return: none
4106 */
4107void wma_add_ts_req(tp_wma_handle wma, tAddTsParams *msg)
4108{
Govind Singhaa64c242016-03-08 11:31:49 +05304109 struct add_ts_param cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004110
4111#ifdef FEATURE_WLAN_ESE
4112 /*
4113 * msmt_interval is in unit called TU (1 TU = 1024 us)
4114 * max value of msmt_interval cannot make resulting
4115 * interval_miliseconds overflow 32 bit
4116 */
4117 uint32_t intervalMiliseconds;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304118 ol_txrx_pdev_handle pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004119 if (NULL == pdev) {
4120 WMA_LOGE("%s: Failed to get pdev", __func__);
4121 goto err;
4122 }
4123
4124 intervalMiliseconds = (msg->tsm_interval * 1024) / 1000;
4125
4126 ol_tx_set_compute_interval(pdev, intervalMiliseconds);
4127#endif /* FEATURE_WLAN_ESE */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304128 msg->status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004129
Govind Singhaa64c242016-03-08 11:31:49 +05304130
4131 cmd.sme_session_id = msg->sme_session_id;
4132 cmd.tspec.tsinfo.traffic.userPrio =
4133 TID_TO_WME_AC(msg->tspec.tsinfo.traffic.userPrio);
4134 cmd.tspec.mediumTime = msg->tspec.mediumTime;
4135 if (wmi_unified_add_ts_cmd(wma->wmi_handle, &cmd))
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304136 msg->status = QDF_STATUS_E_FAILURE;
Govind Singhaa64c242016-03-08 11:31:49 +05304137
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004138#ifdef WLAN_FEATURE_ROAM_OFFLOAD
4139 if (msg->setRICparams == true)
4140 wma_set_ric_req(wma, msg, true);
4141#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
4142
4143err:
4144 wma_send_msg(wma, WMA_ADD_TS_RSP, msg, 0);
4145}
4146
4147/**
4148 * wma_enable_disable_packet_filter() - enable/disable packet filter in target
4149 * @wma: Pointer to wma handle
4150 * @vdev_id: vdev id
4151 * @enable: Flag to enable/disable packet filter
4152 *
4153 * Return: 0 for success or error code
4154 */
4155static int wma_enable_disable_packet_filter(tp_wma_handle wma,
4156 uint8_t vdev_id, bool enable)
4157{
Govind Singhaa64c242016-03-08 11:31:49 +05304158 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004159
Govind Singhaa64c242016-03-08 11:31:49 +05304160 ret = wmi_unified_enable_disable_packet_filter_cmd(wma->wmi_handle,
4161 vdev_id, enable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004162 if (ret)
4163 WMA_LOGE("Failed to send packet filter wmi cmd to fw");
4164
4165 return ret;
4166}
4167
4168/**
4169 * wma_config_packet_filter() - configure packet filter in target
4170 * @wma: Pointer to wma handle
4171 * @vdev_id: vdev id
4172 * @rcv_filter_param: Packet filter parameters
4173 * @filter_id: Filter id
4174 * @enable: Flag to add/delete packet filter configuration
4175 *
4176 * Return: 0 for success or error code
4177 */
4178static int wma_config_packet_filter(tp_wma_handle wma,
4179 uint8_t vdev_id, tSirRcvPktFilterCfgType *rcv_filter_param,
4180 uint8_t filter_id, bool enable)
4181{
Govind Singhaa64c242016-03-08 11:31:49 +05304182 int err;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004183
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004184 /* send the command along with data */
Govind Singhaa64c242016-03-08 11:31:49 +05304185 err = wmi_unified_config_packet_filter_cmd(wma->wmi_handle,
4186 vdev_id, (struct rcv_pkt_filter_config *)rcv_filter_param,
4187 filter_id, enable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004188 if (err) {
4189 WMA_LOGE("Failed to send pkt_filter cmd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004190 return -EIO;
4191 }
4192
4193 /* Enable packet filter */
4194 if (enable)
4195 wma_enable_disable_packet_filter(wma, vdev_id, true);
4196
4197 return 0;
4198}
4199
4200/**
4201 * wma_process_receive_filter_set_filter_req() - enable packet filter
4202 * @wma_handle: wma handle
4203 * @rcv_filter_param: filter params
4204 *
4205 * Return: 0 for success or error code
4206 */
4207int wma_process_receive_filter_set_filter_req(tp_wma_handle wma,
4208 tSirRcvPktFilterCfgType *rcv_filter_param)
4209{
4210 int ret = 0;
4211 uint8_t vdev_id;
4212
4213 /* Get the vdev id */
Srinivas Girigowda98530492015-11-20 17:39:24 -08004214 if (!wma_find_vdev_by_bssid(wma,
4215 rcv_filter_param->bssid.bytes, &vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004216 WMA_LOGE("vdev handle is invalid for %pM",
Srinivas Girigowda98530492015-11-20 17:39:24 -08004217 rcv_filter_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004218 return -EINVAL;
4219 }
4220
4221 ret = wma_config_packet_filter(wma, vdev_id, rcv_filter_param,
4222 rcv_filter_param->filterId, true);
4223
4224 return ret;
4225}
4226
4227/**
4228 * wma_process_receive_filter_clear_filter_req() - disable packet filter
4229 * @wma_handle: wma handle
4230 * @rcv_clear_param: filter params
4231 *
4232 * Return: 0 for success or error code
4233 */
4234int wma_process_receive_filter_clear_filter_req(tp_wma_handle wma,
4235 tSirRcvFltPktClearParam *rcv_clear_param)
4236{
4237 int ret = 0;
4238 uint8_t vdev_id;
4239
4240 /* Get the vdev id */
Srinivas Girigowda98530492015-11-20 17:39:24 -08004241 if (!wma_find_vdev_by_bssid(wma,
4242 rcv_clear_param->bssid.bytes, &vdev_id)) {
4243 WMA_LOGE("vdev handle is invalid for %pM",
4244 rcv_clear_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004245 return -EINVAL;
4246 }
4247
4248 ret = wma_config_packet_filter(wma, vdev_id, NULL,
4249 rcv_clear_param->filterId, false);
4250
4251 return ret;
4252}
4253
4254#ifdef FEATURE_WLAN_ESE
4255
4256#define TSM_DELAY_HISTROGRAM_BINS 4
4257/**
4258 * wma_process_tsm_stats_req() - process tsm stats request
4259 * @wma_handler - handle to wma
4260 * @pTsmStatsMsg - TSM stats struct that needs to be populated and
4261 * passed in message.
4262 *
4263 * A parallel function to WMA_ProcessTsmStatsReq for pronto. This
4264 * function fetches stats from data path APIs and post
4265 * WMA_TSM_STATS_RSP msg back to LIM.
4266 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304267 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004268 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304269QDF_STATUS wma_process_tsm_stats_req(tp_wma_handle wma_handler,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004270 void *pTsmStatsMsg)
4271{
4272 uint8_t counter;
4273 uint32_t queue_delay_microsec = 0;
4274 uint32_t tx_delay_microsec = 0;
4275 uint16_t packet_count = 0;
4276 uint16_t packet_loss_count = 0;
4277 tpAniTrafStrmMetrics pTsmMetric = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004278 tpAniGetTsmStatsReq pStats = (tpAniGetTsmStatsReq) pTsmStatsMsg;
4279 tpAniGetTsmStatsRsp pTsmRspParams = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004280 int tid = pStats->tid;
4281 /*
4282 * The number of histrogram bin report by data path api are different
4283 * than required by TSM, hence different (6) size array used
4284 */
4285 uint16_t bin_values[QCA_TX_DELAY_HIST_REPORT_BINS] = { 0, };
4286
Anurag Chouhan6d760662016-02-20 16:05:43 +05304287 ol_txrx_pdev_handle pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004288
4289 if (NULL == pdev) {
4290 WMA_LOGE("%s: Failed to get pdev", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304291 qdf_mem_free(pTsmStatsMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304292 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004293 }
4294
4295 /* get required values from data path APIs */
4296 ol_tx_delay(pdev, &queue_delay_microsec, &tx_delay_microsec, tid);
4297 ol_tx_delay_hist(pdev, bin_values, tid);
4298 ol_tx_packet_count(pdev, &packet_count, &packet_loss_count, tid);
4299
Srinivas Girigowda515a9ef2015-12-11 11:00:48 -08004300 pTsmRspParams = qdf_mem_malloc(sizeof(*pTsmRspParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004301 if (NULL == pTsmRspParams) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304302 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304303 "%s: QDF MEM Alloc Failure", __func__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304304 QDF_ASSERT(0);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304305 qdf_mem_free(pTsmStatsMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304306 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004307 }
4308 pTsmRspParams->staId = pStats->staId;
4309 pTsmRspParams->rc = eSIR_FAILURE;
4310 pTsmRspParams->tsmStatsReq = pStats;
4311 pTsmMetric = &pTsmRspParams->tsmMetrics;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004312 /* populate pTsmMetric */
4313 pTsmMetric->UplinkPktQueueDly = queue_delay_microsec;
4314 /* store only required number of bin values */
4315 for (counter = 0; counter < TSM_DELAY_HISTROGRAM_BINS; counter++) {
4316 pTsmMetric->UplinkPktQueueDlyHist[counter] =
4317 bin_values[counter];
4318 }
4319 pTsmMetric->UplinkPktTxDly = tx_delay_microsec;
4320 pTsmMetric->UplinkPktLoss = packet_loss_count;
4321 pTsmMetric->UplinkPktCount = packet_count;
4322
4323 /*
4324 * No need to populate roaming delay and roaming count as they are
4325 * being populated just before sending IAPP frame out
4326 */
4327 /* post this message to LIM/PE */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004328 wma_send_msg(wma_handler, WMA_TSM_STATS_RSP, (void *)pTsmRspParams, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304329 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004330}
4331
4332#endif /* FEATURE_WLAN_ESE */
4333
4334/**
4335 * wma_add_clear_mcbc_filter() - set mcast filter command to fw
4336 * @wma_handle: wma handle
4337 * @vdev_id: vdev id
4338 * @multicastAddr: mcast address
4339 * @clearList: clear list flag
4340 *
4341 * Return: 0 for success or error code
4342 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304343static QDF_STATUS wma_add_clear_mcbc_filter(tp_wma_handle wma_handle,
4344 uint8_t vdev_id,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304345 struct qdf_mac_addr multicast_addr,
Srinivas Girigowda98530492015-11-20 17:39:24 -08004346 bool clearList)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004347{
Himanshu Agarwal44195412016-03-09 13:03:54 +05304348 return wmi_unified_add_clear_mcbc_filter_cmd(wma_handle->wmi_handle,
4349 vdev_id, multicast_addr, clearList);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004350}
4351
4352/**
Rajeev Kumaref96e152016-04-15 18:10:33 -07004353 * wma_config_enhance_multicast_offload() - config enhance multicast offload
4354 * @wma_handle: wma handle
4355 * @vdev_id: vdev id
4356 * @action: enable or disable enhance multicast offload
4357 *
4358 * Return: none
4359 */
4360static void wma_config_enhance_multicast_offload(tp_wma_handle wma_handle,
4361 uint8_t vdev_id,
4362 uint8_t action)
4363{
4364 int status;
4365 wmi_buf_t buf;
4366 wmi_config_enhanced_mcast_filter_cmd_fixed_param *cmd;
4367
4368 buf = wmi_buf_alloc(wma_handle->wmi_handle, sizeof(*cmd));
4369 if (!buf) {
4370 WMA_LOGE("Failed to allocate buffer to send set key cmd");
4371 return;
4372 }
4373
4374 cmd = (wmi_config_enhanced_mcast_filter_cmd_fixed_param *)
4375 wmi_buf_data(buf);
4376
4377 WMITLV_SET_HDR(&cmd->tlv_header,
4378 WMITLV_TAG_STRUC_wmi_config_enhanced_mcast_filter_fixed_param,
4379 WMITLV_GET_STRUCT_TLVLEN(wmi_config_enhanced_mcast_filter_cmd_fixed_param));
4380
4381 cmd->vdev_id = vdev_id;
4382 cmd->enable = ((0 == action) ? ENHANCED_MCAST_FILTER_DISABLED :
4383 ENHANCED_MCAST_FILTER_ENABLED);
4384
4385 WMA_LOGD("%s: config enhance multicast offload action %d for vdev %d",
4386 __func__, action, vdev_id);
4387
4388 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
4389 sizeof(*cmd), WMI_CONFIG_ENHANCED_MCAST_FILTER_CMDID);
4390 if (status) {
4391 qdf_nbuf_free(buf);
4392 WMA_LOGE("%s:Failed to send WMI_CONFIG_ENHANCED_MCAST_FILTER_CMDID",
4393 __func__);
4394 }
4395
4396 return;
4397}
4398
4399/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004400 * wma_process_mcbc_set_filter_req() - process mcbc set filter request
4401 * @wma_handle: wma handle
4402 * @mcbc_param: mcbc params
4403 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304404 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004405 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304406QDF_STATUS wma_process_mcbc_set_filter_req(tp_wma_handle wma_handle,
Anurag Chouhance0dc992016-02-16 18:18:03 +05304407 tSirRcvFltMcAddrList *mcbc_param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004408{
4409 uint8_t vdev_id = 0;
4410 int i;
4411
4412 if (mcbc_param->ulMulticastAddrCnt <= 0) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004413 WMA_LOGW("Number of multicast addresses is 0");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304414 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004415 }
4416
Srinivas Girigowda98530492015-11-20 17:39:24 -08004417 if (!wma_find_vdev_by_addr(wma_handle,
4418 mcbc_param->self_macaddr.bytes, &vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004419 WMA_LOGE("%s: Failed to find vdev id for %pM", __func__,
Srinivas Girigowda98530492015-11-20 17:39:24 -08004420 mcbc_param->bssid.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304421 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004422 }
Rajeev Kumaref96e152016-04-15 18:10:33 -07004423
4424 /*
4425 * Configure enhance multicast offload feature for filtering out
4426 * multicast IP data packets transmitted using unicast MAC address
4427 */
4428 if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap,
4429 WMI_SERVICE_ENHANCED_MCAST_FILTER)) {
4430 WMA_LOGD("%s: FW supports enhance multicast offload", __func__);
4431 wma_config_enhance_multicast_offload(wma_handle, vdev_id,
4432 mcbc_param->action);
4433 } else {
4434 WMA_LOGD("%s: FW does not support enhance multicast offload",
4435 __func__);
4436 }
4437
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004438 /* set mcbc_param->action to clear MCList and reset
4439 * to configure the MCList in FW
4440 */
4441
4442 for (i = 0; i < mcbc_param->ulMulticastAddrCnt; i++) {
4443 wma_add_clear_mcbc_filter(wma_handle, vdev_id,
4444 mcbc_param->multicastAddr[i],
4445 (mcbc_param->action == 0));
4446 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304447 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004448}
4449
4450#ifdef WLAN_FEATURE_GTK_OFFLOAD
4451#define GTK_OFFLOAD_ENABLE 0
4452#define GTK_OFFLOAD_DISABLE 1
4453
4454/**
4455 * wma_gtk_offload_status_event() - GTK offload status event handler
4456 * @handle: wma handle
4457 * @event: event buffer
4458 * @len: buffer length
4459 *
4460 * Return: 0 for success or error code
4461 */
4462int wma_gtk_offload_status_event(void *handle, uint8_t *event,
4463 uint32_t len)
4464{
4465 tp_wma_handle wma = (tp_wma_handle) handle;
4466 WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param *status;
4467 WMI_GTK_OFFLOAD_STATUS_EVENTID_param_tlvs *param_buf;
4468 tpSirGtkOffloadGetInfoRspParams resp;
4469 cds_msg_t cds_msg;
4470 uint8_t *bssid;
4471
4472 WMA_LOGD("%s Enter", __func__);
4473
4474 param_buf = (WMI_GTK_OFFLOAD_STATUS_EVENTID_param_tlvs *) event;
4475 if (!param_buf) {
4476 WMA_LOGE("param_buf is NULL");
4477 return -EINVAL;
4478 }
4479
4480 status = (WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param *) param_buf->fixed_param;
4481
4482 if (len < sizeof(WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param)) {
4483 WMA_LOGE("Invalid length for GTK status");
4484 return -EINVAL;
4485 }
4486 bssid = wma_find_bssid_by_vdev_id(wma, status->vdev_id);
4487 if (!bssid) {
4488 WMA_LOGE("invalid bssid for vdev id %d", status->vdev_id);
4489 return -ENOENT;
4490 }
4491
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304492 resp = qdf_mem_malloc(sizeof(*resp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004493 if (!resp) {
4494 WMA_LOGE("%s: Failed to alloc response", __func__);
4495 return -ENOMEM;
4496 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304497 qdf_mem_zero(resp, sizeof(*resp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004498 resp->mesgType = eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP;
4499 resp->mesgLen = sizeof(*resp);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304500 resp->ulStatus = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004501 resp->ulTotalRekeyCount = status->refresh_cnt;
4502 /* TODO: Is the total rekey count and GTK rekey count same? */
4503 resp->ulGTKRekeyCount = status->refresh_cnt;
4504
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304505 qdf_mem_copy(&resp->ullKeyReplayCounter, &status->replay_counter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004506 GTK_REPLAY_COUNTER_BYTES);
4507
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304508 qdf_mem_copy(resp->bssid.bytes, bssid, IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004509
4510#ifdef IGTK_OFFLOAD
4511 /* TODO: Is the refresh count same for GTK and IGTK? */
4512 resp->ulIGTKRekeyCount = status->refresh_cnt;
4513#endif /* IGTK_OFFLOAD */
4514
4515 cds_msg.type = eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP;
4516 cds_msg.bodyptr = (void *)resp;
4517 cds_msg.bodyval = 0;
4518
4519 if (cds_mq_post_message(CDS_MQ_ID_SME, (cds_msg_t *) &cds_msg)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304520 != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004521 WMA_LOGE("Failed to post GTK response to SME");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304522 qdf_mem_free(resp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004523 return -EINVAL;
4524 }
4525
4526 WMA_LOGD("GTK: got target status with replay counter "
4527 "%02x%02x%02x%02x%02x%02x%02x%02x. vdev %d "
4528 "Refresh GTK %d times exchanges since last set operation",
4529 status->replay_counter[0],
4530 status->replay_counter[1],
4531 status->replay_counter[2],
4532 status->replay_counter[3],
4533 status->replay_counter[4],
4534 status->replay_counter[5],
4535 status->replay_counter[6],
4536 status->replay_counter[7],
4537 status->vdev_id, status->refresh_cnt);
4538
4539 WMA_LOGD("%s Exit", __func__);
4540
4541 return 0;
4542}
4543
4544/**
4545 * wma_send_gtk_offload_req() - send GTK offload command to fw
4546 * @wma: wma handle
4547 * @vdev_id: vdev id
4548 * @params: GTK offload parameters
4549 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304550 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004551 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304552static QDF_STATUS wma_send_gtk_offload_req(tp_wma_handle wma, uint8_t vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004553 tpSirGtkOffloadParams params)
4554{
Himanshu Agarwal44195412016-03-09 13:03:54 +05304555 struct gtk_offload_params offload_params = {0};
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304556 QDF_STATUS status = QDF_STATUS_SUCCESS;
Himanshu Agarwal44195412016-03-09 13:03:54 +05304557 bool enable_offload;
4558 uint32_t gtk_offload_opcode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004559
4560 WMA_LOGD("%s Enter", __func__);
4561
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004562 /* Request target to enable GTK offload */
4563 if (params->ulFlags == GTK_OFFLOAD_ENABLE) {
Himanshu Agarwal44195412016-03-09 13:03:54 +05304564 gtk_offload_opcode = GTK_OFFLOAD_ENABLE_OPCODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004565 wma->wow.gtk_err_enable[vdev_id] = true;
4566
4567 /* Copy the keys and replay counter */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304568 qdf_mem_copy(offload_params.aKCK, params->aKCK,
4569 GTK_OFFLOAD_KCK_BYTES);
4570 qdf_mem_copy(offload_params.aKEK, params->aKEK,
4571 GTK_OFFLOAD_KEK_BYTES);
4572 qdf_mem_copy(&offload_params.ullKeyReplayCounter,
4573 &params->ullKeyReplayCounter, GTK_REPLAY_COUNTER_BYTES);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004574 } else {
4575 wma->wow.gtk_err_enable[vdev_id] = false;
Himanshu Agarwal44195412016-03-09 13:03:54 +05304576 gtk_offload_opcode = GTK_OFFLOAD_DISABLE_OPCODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004577 }
4578
Himanshu Agarwal44195412016-03-09 13:03:54 +05304579 enable_offload = params->ulFlags;
4580
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004581 /* send the wmi command */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304582 status = wmi_unified_send_gtk_offload_cmd(wma->wmi_handle,
4583 vdev_id, &offload_params,
4584 enable_offload,
4585 gtk_offload_opcode);
4586 if (QDF_IS_STATUS_ERROR(status))
4587 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004588
Himanshu Agarwal44195412016-03-09 13:03:54 +05304589 WMA_LOGD("VDEVID: %d, GTK_FLAGS: x%x", vdev_id, gtk_offload_opcode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004590out:
4591 WMA_LOGD("%s Exit", __func__);
4592 return status;
4593}
4594
4595/**
4596 * wma_process_gtk_offload_req() - process GTK offload req from umac
4597 * @handle: wma handle
4598 * @params: GTK offload params
4599 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304600 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004601 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304602QDF_STATUS wma_process_gtk_offload_req(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004603 tpSirGtkOffloadParams params)
4604{
4605 uint8_t vdev_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304606 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004607
4608 WMA_LOGD("%s Enter", __func__);
4609
4610 /* Get the vdev id */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08004611 if (!wma_find_vdev_by_bssid(wma, params->bssid.bytes, &vdev_id)) {
4612 WMA_LOGE("vdev handle is invalid for %pM", params->bssid.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304613 status = QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004614 goto out;
4615 }
4616
4617 /* Validate vdev id */
4618 if (vdev_id >= wma->max_bssid) {
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08004619 WMA_LOGE("invalid vdev_id %d for %pM", vdev_id,
4620 params->bssid.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304621 status = QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004622 goto out;
4623 }
4624
4625 if ((params->ulFlags == GTK_OFFLOAD_ENABLE) &&
4626 (wma->wow.gtk_err_enable[vdev_id] == true)) {
4627 WMA_LOGE("%s GTK Offload already enabled. Disable it first "
4628 "vdev_id %d", __func__, vdev_id);
4629 params->ulFlags = GTK_OFFLOAD_DISABLE;
4630 status = wma_send_gtk_offload_req(wma, vdev_id, params);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304631 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004632 WMA_LOGE("%s Failed to disable GTK Offload", __func__);
4633 goto out;
4634 }
4635 WMA_LOGD("%s Enable GTK Offload again with updated inputs",
4636 __func__);
4637 params->ulFlags = GTK_OFFLOAD_ENABLE;
4638 }
4639 status = wma_send_gtk_offload_req(wma, vdev_id, params);
4640out:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304641 qdf_mem_free(params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004642 WMA_LOGD("%s Exit", __func__);
4643 return status;
4644}
4645
4646/**
4647 * wma_process_gtk_offload_getinfo_req() - send GTK offload cmd to fw
4648 * @wma: wma handle
4649 * @params: GTK offload params
4650 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304651 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004652 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304653QDF_STATUS wma_process_gtk_offload_getinfo_req(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004654 tpSirGtkOffloadGetInfoRspParams params)
4655{
4656 uint8_t vdev_id;
Himanshu Agarwal44195412016-03-09 13:03:54 +05304657 uint64_t offload_req_opcode;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304658 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004659
4660 WMA_LOGD("%s Enter", __func__);
4661
4662 /* Get the vdev id */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08004663 if (!wma_find_vdev_by_bssid(wma, params->bssid.bytes, &vdev_id)) {
4664 WMA_LOGE("vdev handle is invalid for %pM", params->bssid.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304665 status = QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004666 goto out;
4667 }
4668
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004669 /* Request for GTK offload status */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304670 offload_req_opcode = GTK_OFFLOAD_REQUEST_STATUS_OPCODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004671
4672 /* send the wmi command */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304673 status = wmi_unified_process_gtk_offload_getinfo_cmd(wma->wmi_handle,
4674 vdev_id, offload_req_opcode);
4675
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004676out:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304677 qdf_mem_free(params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004678 WMA_LOGD("%s Exit", __func__);
4679 return status;
4680}
4681#endif /* WLAN_FEATURE_GTK_OFFLOAD */
4682
4683/**
4684 * wma_enable_arp_ns_offload() - enable ARP NS offload
4685 * @wma: wma handle
4686 * @tpSirHostOffloadReq: offload request
Govind Singhaa64c242016-03-08 11:31:49 +05304687 * @arp_only: flag
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004688 *
4689 * To configure ARP NS off load data to firmware
4690 * when target goes to wow mode.
4691 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304692 * Return: QDF Status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004693 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304694QDF_STATUS wma_enable_arp_ns_offload(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004695 tpSirHostOffloadReq
Govind Singhaa64c242016-03-08 11:31:49 +05304696 pHostOffloadParams, bool arp_only)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004697{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004698 int32_t res;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004699 uint8_t vdev_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004700
4701 /* Get the vdev id */
Srinivas Girigowdab084b552015-11-24 12:39:12 -08004702 if (!wma_find_vdev_by_bssid(wma, pHostOffloadParams->bssid.bytes,
4703 &vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004704 WMA_LOGE("vdev handle is invalid for %pM",
Srinivas Girigowdab084b552015-11-24 12:39:12 -08004705 pHostOffloadParams->bssid.bytes);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304706 qdf_mem_free(pHostOffloadParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304707 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004708 }
4709
4710 if (!wma->interfaces[vdev_id].vdev_up) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004711 WMA_LOGE("vdev %d is not up skipping arp/ns offload", vdev_id);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304712 qdf_mem_free(pHostOffloadParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304713 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004714 }
4715
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004716
Govind Singhaa64c242016-03-08 11:31:49 +05304717 res = wmi_unified_enable_arp_ns_offload_cmd(wma->wmi_handle,
4718 (struct host_offload_req_param *)pHostOffloadParams,
4719 arp_only,
4720 vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004721 if (res) {
4722 WMA_LOGE("Failed to enable ARP NDP/NSffload");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304723 qdf_mem_free(pHostOffloadParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304724 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004725 }
4726
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304727 qdf_mem_free(pHostOffloadParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304728 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004729}
4730
4731/**
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08004732 * wma_process_cesium_enable_ind() - enables cesium functionality in target
4733 * @wma: wma handle
4734 *
4735 * Return: QDF status
4736 */
4737QDF_STATUS wma_process_cesium_enable_ind(tp_wma_handle wma)
4738{
4739 QDF_STATUS ret;
4740 int32_t vdev_id;
4741
4742 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
4743 if (vdev_id < 0) {
4744 WMA_LOGE("%s: IBSS vdev does not exist could not enable cesium",
4745 __func__);
4746 return QDF_STATUS_E_FAILURE;
4747 }
4748
4749 /* Send enable cesium command to target */
4750 WMA_LOGE("Enable cesium in target for vdevId %d ", vdev_id);
4751 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
4752 WMI_VDEV_PARAM_ENABLE_RMC, 1);
4753 if (ret) {
4754 WMA_LOGE("Enable cesium failed for vdevId %d", vdev_id);
4755 return QDF_STATUS_E_FAILURE;
4756 }
4757 return QDF_STATUS_SUCCESS;
4758}
4759
4760/**
4761 * wma_process_get_peer_info_req() - sends get peer info cmd to target
4762 * @wma: wma handle
4763 * @preq: get peer info request
4764 *
4765 * Return: QDF status
4766 */
4767QDF_STATUS wma_process_get_peer_info_req
4768 (tp_wma_handle wma, tSirIbssGetPeerInfoReqParams *pReq)
4769{
4770 int32_t ret;
4771 uint8_t *p;
4772 uint16_t len;
4773 wmi_buf_t buf;
4774 int32_t vdev_id;
4775 ol_txrx_pdev_handle pdev;
4776 struct ol_txrx_peer_t *peer;
4777 uint8_t peer_mac[IEEE80211_ADDR_LEN];
4778 wmi_peer_info_req_cmd_fixed_param *p_get_peer_info_cmd;
4779 uint8_t bcast_mac[IEEE80211_ADDR_LEN] = { 0xff, 0xff, 0xff,
4780 0xff, 0xff, 0xff };
4781
4782 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
4783 if (vdev_id < 0) {
4784 WMA_LOGE("%s: IBSS vdev does not exist could not get peer info",
4785 __func__);
4786 return QDF_STATUS_E_FAILURE;
4787 }
4788
4789 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
4790 if (NULL == pdev) {
4791 WMA_LOGE("%s: Failed to get pdev context", __func__);
4792 return QDF_STATUS_E_FAILURE;
4793 }
4794
4795 if (0xFF == pReq->staIdx) {
4796 /*get info for all peers */
4797 qdf_mem_copy(peer_mac, bcast_mac, IEEE80211_ADDR_LEN);
4798 } else {
4799 /*get info for a single peer */
4800 peer = ol_txrx_peer_find_by_local_id(pdev, pReq->staIdx);
4801 if (!peer) {
4802 WMA_LOGE("%s: Failed to get peer handle using peer id %d",
4803 __func__, pReq->staIdx);
4804 return QDF_STATUS_E_FAILURE;
4805 }
4806 WMA_LOGE("%s: staIdx %d peer mac: 0x%2x:0x%2x:0x%2x:0x%2x:0x%2x:0x%2x",
4807 __func__, pReq->staIdx, peer->mac_addr.raw[0],
4808 peer->mac_addr.raw[1], peer->mac_addr.raw[2],
4809 peer->mac_addr.raw[3], peer->mac_addr.raw[4],
4810 peer->mac_addr.raw[5]);
4811 qdf_mem_copy(peer_mac, peer->mac_addr.raw, IEEE80211_ADDR_LEN);
4812 }
4813
4814 len = sizeof(wmi_peer_info_req_cmd_fixed_param);
4815 buf = wmi_buf_alloc(wma->wmi_handle, len);
4816 if (!buf) {
4817 WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__);
4818 return QDF_STATUS_E_FAILURE;
4819 }
4820
4821 p = (uint8_t *) wmi_buf_data(buf);
4822 qdf_mem_zero(p, len);
4823 p_get_peer_info_cmd = (wmi_peer_info_req_cmd_fixed_param *) p;
4824
4825 WMITLV_SET_HDR(&p_get_peer_info_cmd->tlv_header,
4826 WMITLV_TAG_STRUC_wmi_peer_info_req_cmd_fixed_param,
4827 WMITLV_GET_STRUCT_TLVLEN
4828 (wmi_peer_info_req_cmd_fixed_param));
4829
4830 p_get_peer_info_cmd->vdev_id = vdev_id;
4831 WMI_CHAR_ARRAY_TO_MAC_ADDR(peer_mac,
4832 &p_get_peer_info_cmd->peer_mac_address);
4833
4834 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
4835 WMI_PEER_INFO_REQ_CMDID);
4836
4837 WMA_LOGE("IBSS get peer info cmd sent len: %d, vdev %d"
4838 " command id: %d, status: %d", len,
4839 p_get_peer_info_cmd->vdev_id, WMI_PEER_INFO_REQ_CMDID, ret);
4840
4841 return QDF_STATUS_SUCCESS;
4842}
4843
4844/**
4845 * wma_process_tx_fail_monitor_ind() - sends tx fail monitor cmd to target
4846 * @wma: wma handle
4847 * @pReq: tx fail monitor command params
4848 *
4849 * Return: QDF status
4850 */
4851QDF_STATUS wma_process_tx_fail_monitor_ind
4852 (tp_wma_handle wma, tAniTXFailMonitorInd *pReq)
4853{
4854 QDF_STATUS ret;
4855 int32_t vdev_id;
4856
4857 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
4858 if (vdev_id < 0) {
4859 WMA_LOGE("%s: IBSS vdev does not exist could not send fast tx fail"
4860 " monitor indication message to target", __func__);
4861 return QDF_STATUS_E_FAILURE;
4862 }
4863
4864 /* Send enable cesium command to target */
4865 WMA_LOGE("send fast tx fail monitor ind cmd target for vdevId %d val %d",
4866 vdev_id, pReq->tx_fail_count);
4867
4868 if (0 == pReq->tx_fail_count) {
4869 wma->hddTxFailCb = NULL;
4870 } else {
4871 wma->hddTxFailCb = pReq->txFailIndCallback;
4872 }
4873 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
4874 WMI_VDEV_PARAM_SET_IBSS_TX_FAIL_CNT_THR,
4875 pReq->tx_fail_count);
4876 if (ret) {
4877 WMA_LOGE("tx fail monitor failed for vdevId %d", vdev_id);
4878 return QDF_STATUS_E_FAILURE;
4879 }
4880
4881 return QDF_STATUS_SUCCESS;
4882}
4883
4884/**
4885 * wma_process_rmc_enable_ind() - enables RMC functionality in target
4886 * @wma: wma handle
4887 *
4888 * Return: QDF status
4889 */
4890QDF_STATUS wma_process_rmc_enable_ind(tp_wma_handle wma)
4891{
4892 int ret;
4893 uint8_t *p;
4894 uint16_t len;
4895 wmi_buf_t buf;
4896 int32_t vdev_id;
4897 wmi_rmc_set_mode_cmd_fixed_param *p_rmc_enable_cmd;
4898
4899 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
4900 if (vdev_id < 0) {
4901 WMA_LOGE("%s: IBSS vdev does not exist could not enable RMC",
4902 __func__);
4903 return QDF_STATUS_E_FAILURE;
4904 }
4905
4906 len = sizeof(wmi_rmc_set_mode_cmd_fixed_param);
4907 buf = wmi_buf_alloc(wma->wmi_handle, len);
4908 if (!buf) {
4909 WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__);
4910 return QDF_STATUS_E_FAILURE;
4911 }
4912
4913 p = (uint8_t *) wmi_buf_data(buf);
4914 qdf_mem_zero(p, len);
4915 p_rmc_enable_cmd = (wmi_rmc_set_mode_cmd_fixed_param *) p;
4916
4917 WMITLV_SET_HDR(&p_rmc_enable_cmd->tlv_header,
4918 WMITLV_TAG_STRUC_wmi_rmc_set_mode_cmd_fixed_param,
4919 WMITLV_GET_STRUCT_TLVLEN
4920 (wmi_rmc_set_mode_cmd_fixed_param));
4921
4922 p_rmc_enable_cmd->vdev_id = vdev_id;
4923 p_rmc_enable_cmd->enable_rmc = WMI_RMC_MODE_ENABLED;
4924
4925 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
4926 WMI_RMC_SET_MODE_CMDID);
4927
4928 WMA_LOGE("Enable RMC cmd sent len: %d, vdev %d" " command id: %d,"
4929 " status: %d", len, p_rmc_enable_cmd->vdev_id,
4930 WMI_RMC_SET_MODE_CMDID, ret);
4931
4932 return QDF_STATUS_SUCCESS;
4933}
4934
4935/**
4936 * wma_process_rmc_disable_ind() - disables rmc functionality in target
4937 * @wma: wma handle
4938 *
4939 * Return: QDF status
4940 */
4941QDF_STATUS wma_process_rmc_disable_ind(tp_wma_handle wma)
4942{
4943 int ret;
4944 uint8_t *p;
4945 uint16_t len;
4946 wmi_buf_t buf;
4947 int32_t vdev_id;
4948 wmi_rmc_set_mode_cmd_fixed_param *p_rmc_disable_cmd;
4949
4950 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
4951 if (vdev_id < 0) {
4952 WMA_LOGE("%s: IBSS vdev does not exist could not disable RMC",
4953 __func__);
4954 return QDF_STATUS_E_FAILURE;
4955 }
4956
4957 len = sizeof(wmi_rmc_set_mode_cmd_fixed_param);
4958 buf = wmi_buf_alloc(wma->wmi_handle, len);
4959 if (!buf) {
4960 WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__);
4961 return QDF_STATUS_E_FAILURE;
4962 }
4963
4964 p = (uint8_t *) wmi_buf_data(buf);
4965 qdf_mem_zero(p, len);
4966 p_rmc_disable_cmd = (wmi_rmc_set_mode_cmd_fixed_param *) p;
4967
4968 WMITLV_SET_HDR(&p_rmc_disable_cmd->tlv_header,
4969 WMITLV_TAG_STRUC_wmi_rmc_set_mode_cmd_fixed_param,
4970 WMITLV_GET_STRUCT_TLVLEN
4971 (wmi_rmc_set_mode_cmd_fixed_param));
4972
4973 p_rmc_disable_cmd->vdev_id = vdev_id;
4974 p_rmc_disable_cmd->enable_rmc = WMI_RMC_MODE_DISABLED;
4975
4976 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
4977 WMI_RMC_SET_MODE_CMDID);
4978
4979 WMA_LOGE("Disable RMC cmd sent len: %d, vdev %d" " command id: %d,"
4980 " status: %d", len, p_rmc_disable_cmd->vdev_id,
4981 WMI_RMC_SET_MODE_CMDID, ret);
4982
4983 return QDF_STATUS_SUCCESS;
4984}
4985
4986/**
4987 * wma_process_rmc_action_period_ind() - sends RMC action period to target
4988 * @wma: wma handle
4989 *
4990 * Return: QDF status
4991 */
4992QDF_STATUS wma_process_rmc_action_period_ind(tp_wma_handle wma)
4993{
4994 int ret;
4995 uint8_t *p;
4996 uint16_t len;
4997 uint32_t val;
4998 wmi_buf_t buf;
4999 int32_t vdev_id;
5000 wmi_rmc_set_action_period_cmd_fixed_param *p_rmc_cmd;
5001 struct sAniSirGlobal *mac = cds_get_context(QDF_MODULE_ID_PE);
5002
5003 if (NULL == mac) {
5004 WMA_LOGE("%s: MAC mac does not exist", __func__);
5005 return QDF_STATUS_E_FAILURE;
5006 }
5007
5008 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
5009 if (vdev_id < 0) {
5010 WMA_LOGE("%s: IBSS vdev does not exist could not send"
5011 " RMC action period to target", __func__);
5012 return QDF_STATUS_E_FAILURE;
5013 }
5014
5015 len = sizeof(wmi_rmc_set_action_period_cmd_fixed_param);
5016 buf = wmi_buf_alloc(wma->wmi_handle, len);
5017 if (!buf) {
5018 WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__);
5019 return QDF_STATUS_E_FAILURE;
5020 }
5021
5022 p = (uint8_t *) wmi_buf_data(buf);
5023 qdf_mem_zero(p, len);
5024 p_rmc_cmd = (wmi_rmc_set_action_period_cmd_fixed_param *) p;
5025
5026 WMITLV_SET_HDR(&p_rmc_cmd->tlv_header,
5027 WMITLV_TAG_STRUC_wmi_rmc_set_action_period_cmd_fixed_param,
5028 WMITLV_GET_STRUCT_TLVLEN
5029 (wmi_rmc_set_action_period_cmd_fixed_param));
5030
5031 if (wlan_cfg_get_int(mac, WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY, &val)
5032 != eSIR_SUCCESS) {
5033 WMA_LOGE("Failed to get value for RMC action period using default");
5034 val = WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_STADEF;
5035 }
5036
5037 p_rmc_cmd->vdev_id = vdev_id;
5038 p_rmc_cmd->periodicity_msec = val;
5039
5040 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
5041 WMI_RMC_SET_ACTION_PERIOD_CMDID);
5042
5043 WMA_LOGE("RMC action period %d cmd sent len: %d, vdev %d"
5044 " command id: %d, status: %d", p_rmc_cmd->periodicity_msec,
5045 len, p_rmc_cmd->vdev_id, WMI_RMC_SET_ACTION_PERIOD_CMDID, ret);
5046
5047 return QDF_STATUS_SUCCESS;
5048}
5049
5050/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005051 * wma_process_add_periodic_tx_ptrn_ind - add periodic tx ptrn
5052 * @handle: wma handle
5053 * @pAddPeriodicTxPtrnParams: tx ptrn params
5054 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305055 * Retrun: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005056 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305057QDF_STATUS wma_process_add_periodic_tx_ptrn_ind(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005058 tSirAddPeriodicTxPtrn *
5059 pAddPeriodicTxPtrnParams)
5060{
5061 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Himanshu Agarwal44195412016-03-09 13:03:54 +05305062 struct periodic_tx_pattern params;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005063 uint8_t vdev_id;
Himanshu Agarwal44195412016-03-09 13:03:54 +05305064
5065 qdf_mem_set(&params, sizeof(struct periodic_tx_pattern), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005066
5067 if (!wma_handle || !wma_handle->wmi_handle) {
5068 WMA_LOGE("%s: WMA is closed, can not issue fw add pattern cmd",
5069 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305070 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005071 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005072
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005073 if (!wma_find_vdev_by_addr(wma_handle,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005074 pAddPeriodicTxPtrnParams->mac_address.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005075 &vdev_id)) {
5076 WMA_LOGE("%s: Failed to find vdev id for %pM", __func__,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005077 pAddPeriodicTxPtrnParams->mac_address.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305078 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005079 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005080
Himanshu Agarwal44195412016-03-09 13:03:54 +05305081 params.ucPtrnId = pAddPeriodicTxPtrnParams->ucPtrnId;
5082 params.ucPtrnSize = pAddPeriodicTxPtrnParams->ucPtrnSize;
5083 params.usPtrnIntervalMs = pAddPeriodicTxPtrnParams->usPtrnIntervalMs;
5084 qdf_mem_copy(&params.mac_address,
5085 &pAddPeriodicTxPtrnParams->mac_address,
5086 sizeof(struct qdf_mac_addr));
5087 qdf_mem_copy(params.ucPattern, pAddPeriodicTxPtrnParams->ucPattern,
5088 params.ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005089
Himanshu Agarwal44195412016-03-09 13:03:54 +05305090 return wmi_unified_process_add_periodic_tx_ptrn_cmd(
5091 wma_handle->wmi_handle, &params, vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005092}
5093
5094/**
5095 * wma_process_del_periodic_tx_ptrn_ind - del periodic tx ptrn
5096 * @handle: wma handle
5097 * @pDelPeriodicTxPtrnParams: tx ptrn params
5098 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305099 * Retrun: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005100 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305101QDF_STATUS wma_process_del_periodic_tx_ptrn_ind(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005102 tSirDelPeriodicTxPtrn *
5103 pDelPeriodicTxPtrnParams)
5104{
5105 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005106 uint8_t vdev_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005107
5108 if (!wma_handle || !wma_handle->wmi_handle) {
5109 WMA_LOGE("%s: WMA is closed, can not issue Del Pattern cmd",
5110 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305111 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005112 }
Himanshu Agarwal44195412016-03-09 13:03:54 +05305113
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005114 if (!wma_find_vdev_by_addr(wma_handle,
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08005115 pDelPeriodicTxPtrnParams->mac_address.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005116 &vdev_id)) {
5117 WMA_LOGE("%s: Failed to find vdev id for %pM", __func__,
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08005118 pDelPeriodicTxPtrnParams->mac_address.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305119 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005120 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005121
Himanshu Agarwal44195412016-03-09 13:03:54 +05305122 return wmi_unified_process_del_periodic_tx_ptrn_cmd(
5123 wma_handle->wmi_handle, vdev_id,
5124 pDelPeriodicTxPtrnParams->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005125}
5126
5127#ifdef WLAN_FEATURE_STATS_EXT
5128/**
5129 * wma_stats_ext_req() - request ext stats from fw
5130 * @wma_ptr: wma handle
5131 * @preq: stats ext params
5132 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305133 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005134 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305135QDF_STATUS wma_stats_ext_req(void *wma_ptr, tpStatsExtRequest preq)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005136{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005137 tp_wma_handle wma = (tp_wma_handle) wma_ptr;
Himanshu Agarwal44195412016-03-09 13:03:54 +05305138 struct stats_ext_params params = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005139
Himanshu Agarwal44195412016-03-09 13:03:54 +05305140 if (!wma) {
5141 WMA_LOGE("%s: wma handle is NULL", __func__);
5142 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005143 }
5144
Himanshu Agarwal44195412016-03-09 13:03:54 +05305145 params.vdev_id = preq->vdev_id;
5146 params.request_data_len = preq->request_data_len;
5147 qdf_mem_copy(params.request_data, preq->request_data,
5148 params.request_data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005149
Himanshu Agarwal44195412016-03-09 13:03:54 +05305150 return wmi_unified_stats_ext_req_cmd(wma->wmi_handle,
5151 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005152}
5153
5154#endif /* WLAN_FEATURE_STATS_EXT */
5155
5156#ifdef WLAN_FEATURE_EXTWOW_SUPPORT
5157/**
5158 * wma_send_status_of_ext_wow() - send ext wow status to SME
5159 * @wma: wma handle
5160 * @status: status
5161 *
5162 * Return: none
5163 */
5164static void wma_send_status_of_ext_wow(tp_wma_handle wma, bool status)
5165{
5166 tSirReadyToExtWoWInd *ready_to_extwow;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305167 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005168 cds_msg_t cds_msg;
5169 uint8_t len;
5170
5171 WMA_LOGD("Posting ready to suspend indication to umac");
5172
5173 len = sizeof(tSirReadyToExtWoWInd);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305174 ready_to_extwow = (tSirReadyToExtWoWInd *) qdf_mem_malloc(len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005175
5176 if (NULL == ready_to_extwow) {
5177 WMA_LOGE("%s: Memory allocation failure", __func__);
5178 return;
5179 }
5180
5181 ready_to_extwow->mesgType = eWNI_SME_READY_TO_EXTWOW_IND;
5182 ready_to_extwow->mesgLen = len;
5183 ready_to_extwow->status = status;
5184
5185 cds_msg.type = eWNI_SME_READY_TO_EXTWOW_IND;
5186 cds_msg.bodyptr = (void *)ready_to_extwow;
5187 cds_msg.bodyval = 0;
5188
5189 vstatus = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305190 if (vstatus != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005191 WMA_LOGE("Failed to post ready to suspend");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305192 qdf_mem_free(ready_to_extwow);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005193 }
5194}
5195
5196/**
5197 * wma_enable_ext_wow() - enable ext wow in fw
5198 * @wma: wma handle
5199 * @params: ext wow params
5200 *
5201 * Return:0 for success or error code
5202 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05305203QDF_STATUS wma_enable_ext_wow(tp_wma_handle wma, tpSirExtWoWParams params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005204{
Himanshu Agarwal44195412016-03-09 13:03:54 +05305205 struct ext_wow_params wow_params = {0};
5206 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005207
Himanshu Agarwal44195412016-03-09 13:03:54 +05305208 if (!wma) {
5209 WMA_LOGE("%s: wma handle is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305210 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005211 }
5212
Himanshu Agarwal44195412016-03-09 13:03:54 +05305213 wow_params.vdev_id = params->vdev_id;
5214 wow_params.type = (enum wmi_ext_wow_type) params->type;
5215 wow_params.wakeup_pin_num = params->wakeup_pin_num;
5216
5217 status = wmi_unified_enable_ext_wow_cmd(wma->wmi_handle,
5218 &wow_params);
5219 if (QDF_IS_STATUS_ERROR(status))
5220 return status;
5221
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005222 wma_send_status_of_ext_wow(wma, true);
Himanshu Agarwal44195412016-03-09 13:03:54 +05305223 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005224
5225}
5226
5227/**
5228 * wma_set_app_type1_params_in_fw() - set app type1 params in fw
5229 * @wma: wma handle
5230 * @appType1Params: app type1 params
5231 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305232 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005233 */
5234int wma_set_app_type1_params_in_fw(tp_wma_handle wma,
5235 tpSirAppType1Params appType1Params)
5236{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005237 int ret;
5238
Govind Singhaa64c242016-03-08 11:31:49 +05305239 ret = wmi_unified_app_type1_params_in_fw_cmd(wma->wmi_handle,
5240 (struct app_type1_params *)appType1Params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005241 if (ret) {
5242 WMA_LOGE("%s: Failed to set APP TYPE1 PARAMS", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305243 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005244 }
5245
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305246 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005247}
5248
5249/**
5250 * wma_set_app_type2_params_in_fw() - set app type2 params in fw
5251 * @wma: wma handle
5252 * @appType2Params: app type2 params
5253 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305254 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005255 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05305256QDF_STATUS wma_set_app_type2_params_in_fw(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005257 tpSirAppType2Params appType2Params)
5258{
Himanshu Agarwal44195412016-03-09 13:03:54 +05305259 struct app_type2_params params = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005260
Himanshu Agarwal44195412016-03-09 13:03:54 +05305261 if (!wma) {
5262 WMA_LOGE("%s: wma handle is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305263 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005264 }
5265
Himanshu Agarwal44195412016-03-09 13:03:54 +05305266 params.vdev_id = appType2Params->vdev_id;
5267 params.rc4_key_len = appType2Params->rc4_key_len;
5268 qdf_mem_copy(params.rc4_key, appType2Params->rc4_key, 16);
5269 params.ip_id = appType2Params->ip_id;
5270 params.ip_device_ip = appType2Params->ip_device_ip;
5271 params.ip_server_ip = appType2Params->ip_server_ip;
5272 params.tcp_src_port = appType2Params->tcp_src_port;
5273 params.tcp_dst_port = appType2Params->tcp_dst_port;
5274 params.tcp_seq = appType2Params->tcp_seq;
5275 params.tcp_ack_seq = appType2Params->tcp_ack_seq;
5276 params.keepalive_init = appType2Params->keepalive_init;
5277 params.keepalive_min = appType2Params->keepalive_min;
5278 params.keepalive_max = appType2Params->keepalive_max;
5279 params.keepalive_inc = appType2Params->keepalive_inc;
5280 params.tcp_tx_timeout_val = appType2Params->tcp_tx_timeout_val;
5281 params.tcp_rx_timeout_val = appType2Params->tcp_rx_timeout_val;
5282 qdf_mem_copy(&params.gateway_mac, &appType2Params->gateway_mac,
5283 sizeof(struct qdf_mac_addr));
5284
5285 return wmi_unified_set_app_type2_params_in_fw_cmd(wma->wmi_handle,
5286 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005287
5288}
5289#endif /* WLAN_FEATURE_EXTWOW_SUPPORT */
5290
5291#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
5292/**
5293 * wma_auto_shutdown_event_handler() - process auto shutdown timer trigger
5294 * @handle: wma handle
5295 * @event: event buffer
5296 * @len: buffer length
5297 *
5298 * Return: 0 for success or error code
5299 */
5300int wma_auto_shutdown_event_handler(void *handle, uint8_t *event,
5301 uint32_t len)
5302{
5303 wmi_host_auto_shutdown_event_fixed_param *wmi_auto_sh_evt;
5304 WMI_HOST_AUTO_SHUTDOWN_EVENTID_param_tlvs *param_buf =
5305 (WMI_HOST_AUTO_SHUTDOWN_EVENTID_param_tlvs *)
5306 event;
5307
5308 if (!param_buf || !param_buf->fixed_param) {
5309 WMA_LOGE("%s:%d: Invalid Auto shutdown timer evt", __func__,
5310 __LINE__);
5311 return -EINVAL;
5312 }
5313
5314 wmi_auto_sh_evt = param_buf->fixed_param;
5315
5316 if (wmi_auto_sh_evt->shutdown_reason
5317 != WMI_HOST_AUTO_SHUTDOWN_REASON_TIMER_EXPIRY) {
5318 WMA_LOGE("%s:%d: Invalid Auto shutdown timer evt", __func__,
5319 __LINE__);
5320 return -EINVAL;
5321 }
5322
5323 WMA_LOGD("%s:%d: Auto Shutdown Evt: %d", __func__, __LINE__,
5324 wmi_auto_sh_evt->shutdown_reason);
5325 return wma_post_auto_shutdown_msg();
5326}
5327
5328/**
5329 * wma_set_auto_shutdown_timer_req() - sets auto shutdown timer in firmware
5330 * @wma: wma handle
5331 * @auto_sh_cmd: auto shutdown timer value
5332 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305333 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005334 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305335QDF_STATUS wma_set_auto_shutdown_timer_req(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005336 tSirAutoShutdownCmdParams *
5337 auto_sh_cmd)
5338{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005339 if (auto_sh_cmd == NULL) {
5340 WMA_LOGE("%s : Invalid Autoshutdown cfg cmd", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305341 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005342 }
5343
Himanshu Agarwal44195412016-03-09 13:03:54 +05305344 return wmi_unified_set_auto_shutdown_timer_cmd(wma_handle->wmi_handle,
5345 auto_sh_cmd->timer_val);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005346}
5347#endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
5348
5349#ifdef WLAN_FEATURE_NAN
5350/**
5351 * wma_nan_req() - to send nan request to target
5352 * @wma: wma_handle
5353 * @nan_req: request data which will be non-null
5354 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305355 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005356 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305357QDF_STATUS wma_nan_req(void *wma_ptr, tpNanRequest nan_req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005358{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005359 tp_wma_handle wma_handle = (tp_wma_handle) wma_ptr;
Himanshu Agarwal44195412016-03-09 13:03:54 +05305360 struct nan_req_params params = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005361
Himanshu Agarwal44195412016-03-09 13:03:54 +05305362 if (!wma_handle) {
5363 WMA_LOGE("%s: wma handle is NULL", __func__);
5364 return QDF_STATUS_E_FAILURE;
5365 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005366 if (!nan_req) {
5367 WMA_LOGE("%s:nan req is not valid", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305368 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005369 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005370
Himanshu Agarwal44195412016-03-09 13:03:54 +05305371 params.request_data_len = nan_req->request_data_len;
5372 qdf_mem_copy(params.request_data, nan_req->request_data,
5373 params.request_data_len);
5374
5375 return wmi_unified_nan_req_cmd(wma_handle->wmi_handle,
5376 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005377}
5378#endif /* WLAN_FEATURE_NAN */
5379
5380#ifdef DHCP_SERVER_OFFLOAD
5381/**
5382 * wma_process_dhcpserver_offload() - enable DHCP server offload
5383 * @wma_handle: wma handle
5384 * @pDhcpSrvOffloadInfo: DHCP server offload info
5385 *
5386 * Return: 0 for success or error code
5387 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05305388QDF_STATUS wma_process_dhcpserver_offload(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005389 tSirDhcpSrvOffloadInfo *
5390 pDhcpSrvOffloadInfo)
5391{
Himanshu Agarwal44195412016-03-09 13:03:54 +05305392 struct dhcp_offload_info_params params = {0};
5393 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005394
Himanshu Agarwal44195412016-03-09 13:03:54 +05305395 if (!wma_handle) {
5396 WMA_LOGE("%s: wma handle is NULL", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005397 return -EIO;
5398 }
Himanshu Agarwal44195412016-03-09 13:03:54 +05305399
5400 params.vdev_id = pDhcpSrvOffloadInfo->vdev_id;
5401 params.dhcpSrvOffloadEnabled =
5402 pDhcpSrvOffloadInfo->dhcpSrvOffloadEnabled;
5403 params.dhcpClientNum = pDhcpSrvOffloadInfo->dhcpClientNum;
5404 params.dhcpSrvIP = pDhcpSrvOffloadInfo->;
5405
5406 status = wmi_unified_process_dhcpserver_offload_cmd(
5407 wma_handle->wmi_handle, &params);
5408 if (QDF_IS_STATUS_ERROR(status))
5409 return status;
5410
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005411 WMA_LOGD("Set dhcp server offload to vdevId %d",
5412 pDhcpSrvOffloadInfo->vdev_id);
Himanshu Agarwal44195412016-03-09 13:03:54 +05305413 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005414}
5415#endif /* DHCP_SERVER_OFFLOAD */
5416
5417#ifdef WLAN_FEATURE_GPIO_LED_FLASHING
5418/**
5419 * wma_set_led_flashing() - set led flashing in fw
5420 * @wma_handle: wma handle
5421 * @flashing: flashing request
5422 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305423 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005424 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305425QDF_STATUS wma_set_led_flashing(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005426 tSirLedFlashingReq *flashing)
5427{
Govind Singhaa64c242016-03-08 11:31:49 +05305428 struct flashing_req_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005429
5430 if (!wma_handle || !wma_handle->wmi_handle) {
5431 WMA_LOGE(FL("WMA is closed, can not issue cmd"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305432 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005433 }
5434 if (!flashing) {
5435 WMA_LOGE(FL("invalid parameter: flashing"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305436 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005437 }
Govind Singhaa64c242016-03-08 11:31:49 +05305438 cmd.req_id = flashing->reqId;
5439 cmd.pattern_id = flashing->pattern_id;
5440 cmd.led_x0 = flashing->led_x0;
5441 cmd.led_x1 = flashing->led_x1;
5442 status = wmi_unified_set_led_flashing_cmd(wma_handle->wmi_handle,
5443 &cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005444 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305445 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005446 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305447 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005448}
5449#endif /* WLAN_FEATURE_GPIO_LED_FLASHING */
5450
5451#ifdef FEATURE_WLAN_CH_AVOID
5452/**
5453 * wma_channel_avoid_evt_handler() - process channel to avoid event from FW.
5454 * @handle: wma handle
5455 * @event: event buffer
5456 * @len: buffer length
5457 *
5458 * Return: 0 for success or error code
5459 */
5460int wma_channel_avoid_evt_handler(void *handle, uint8_t *event,
5461 uint32_t len)
5462{
5463 wmi_avoid_freq_ranges_event_fixed_param *afr_fixed_param;
5464 wmi_avoid_freq_range_desc *afr_desc;
5465 uint32_t num_freq_ranges, freq_range_idx;
5466 tSirChAvoidIndType *sca_indication;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305467 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005468 cds_msg_t sme_msg = { 0 };
5469 WMI_WLAN_FREQ_AVOID_EVENTID_param_tlvs *param_buf =
5470 (WMI_WLAN_FREQ_AVOID_EVENTID_param_tlvs *) event;
5471
5472 if (!param_buf) {
5473 WMA_LOGE("Invalid channel avoid event buffer");
5474 return -EINVAL;
5475 }
5476
5477 afr_fixed_param = param_buf->fixed_param;
5478 if (!afr_fixed_param) {
5479 WMA_LOGE("Invalid channel avoid event fixed param buffer");
5480 return -EINVAL;
5481 }
5482
5483 num_freq_ranges =
5484 (afr_fixed_param->num_freq_ranges >
5485 SIR_CH_AVOID_MAX_RANGE) ? SIR_CH_AVOID_MAX_RANGE :
5486 afr_fixed_param->num_freq_ranges;
5487
5488 WMA_LOGD("Channel avoid event received with %d ranges",
5489 num_freq_ranges);
5490 for (freq_range_idx = 0; freq_range_idx < num_freq_ranges;
5491 freq_range_idx++) {
5492 afr_desc = (wmi_avoid_freq_range_desc *)
5493 ((void *)param_buf->avd_freq_range +
5494 freq_range_idx * sizeof(wmi_avoid_freq_range_desc));
5495
5496 WMA_LOGD("range %d: tlv id = %u, start freq = %u, end freq = %u",
5497 freq_range_idx, afr_desc->tlv_header, afr_desc->start_freq,
5498 afr_desc->end_freq);
5499 }
5500
5501 sca_indication = (tSirChAvoidIndType *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305502 qdf_mem_malloc(sizeof(tSirChAvoidIndType));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005503 if (!sca_indication) {
5504 WMA_LOGE("Invalid channel avoid indication buffer");
5505 return -EINVAL;
5506 }
5507
5508 sca_indication->avoid_range_count = num_freq_ranges;
5509 for (freq_range_idx = 0; freq_range_idx < num_freq_ranges;
5510 freq_range_idx++) {
5511 afr_desc = (wmi_avoid_freq_range_desc *)
5512 ((void *)param_buf->avd_freq_range +
5513 freq_range_idx * sizeof(wmi_avoid_freq_range_desc));
5514 sca_indication->avoid_freq_range[freq_range_idx].start_freq =
5515 afr_desc->start_freq;
5516 sca_indication->avoid_freq_range[freq_range_idx].end_freq =
5517 afr_desc->end_freq;
5518 }
5519
5520 sme_msg.type = eWNI_SME_CH_AVOID_IND;
5521 sme_msg.bodyptr = sca_indication;
5522 sme_msg.bodyval = 0;
5523
Anurag Chouhan6d760662016-02-20 16:05:43 +05305524 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305525 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005526 WMA_LOGE("Fail to post eWNI_SME_CH_AVOID_IND msg to SME");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305527 qdf_mem_free(sca_indication);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005528 return -EINVAL;
5529 }
5530
5531 return 0;
5532}
5533
5534/**
5535 * wma_process_ch_avoid_update_req() - handles channel avoid update request
5536 * @wma_handle: wma handle
5537 * @ch_avoid_update_req: channel avoid update params
5538 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305539 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005540 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305541QDF_STATUS wma_process_ch_avoid_update_req(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005542 tSirChAvoidUpdateReq *
5543 ch_avoid_update_req)
5544{
Himanshu Agarwal44195412016-03-09 13:03:54 +05305545 QDF_STATUS status;
5546 if (!wma_handle) {
5547 WMA_LOGE("%s: wma handle is NULL", __func__);
5548 return QDF_STATUS_E_FAILURE;
5549 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005550 if (ch_avoid_update_req == NULL) {
5551 WMA_LOGE("%s : ch_avoid_update_req is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305552 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005553 }
5554
5555 WMA_LOGI("%s: WMA --> WMI_CHAN_AVOID_UPDATE", __func__);
5556
Himanshu Agarwal44195412016-03-09 13:03:54 +05305557 status = wmi_unified_process_ch_avoid_update_cmd(
5558 wma_handle->wmi_handle);
5559 if (QDF_IS_STATUS_ERROR(status))
5560 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005561
5562 WMA_LOGI("%s: WMA --> WMI_CHAN_AVOID_UPDATE sent through WMI",
5563 __func__);
Himanshu Agarwal44195412016-03-09 13:03:54 +05305564 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005565}
5566#endif /* FEATURE_WLAN_CH_AVOID */
5567
5568/**
5569 * wma_set_reg_domain() - set reg domain
5570 * @clientCtxt: client context
5571 * @regId: reg id
5572 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305573 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005574 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305575QDF_STATUS wma_set_reg_domain(void *clientCtxt, v_REGDOMAIN_t regId)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005576{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305577 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005578 cds_set_reg_domain(clientCtxt, regId))
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305579 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005580
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305581 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005582}
5583
5584/**
5585 * wma_send_regdomain_info_to_fw() - send regdomain info to fw
5586 * @reg_dmn: reg domain
5587 * @regdmn2G: 2G reg domain
5588 * @regdmn5G: 5G reg domain
5589 * @ctl2G: 2G test limit
5590 * @ctl5G: 5G test limit
5591 *
5592 * Return: none
5593 */
5594void wma_send_regdomain_info_to_fw(uint32_t reg_dmn, uint16_t regdmn2G,
5595 uint16_t regdmn5G, int8_t ctl2G,
5596 int8_t ctl5G)
5597{
Anurag Chouhan6d760662016-02-20 16:05:43 +05305598 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005599 int32_t cck_mask_val = 0;
Govind Singhd76a5b02016-03-08 15:12:14 +05305600 struct pdev_params pdev_param = {0};
Himanshu Agarwal44195412016-03-09 13:03:54 +05305601 QDF_STATUS ret = QDF_STATUS_SUCCESS;
5602 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005603
5604 if (NULL == wma) {
5605 WMA_LOGE("%s: wma context is NULL", __func__);
5606 return;
5607 }
5608
Himanshu Agarwal44195412016-03-09 13:03:54 +05305609 status = wmi_unified_send_regdomain_info_to_fw_cmd(wma->wmi_handle,
5610 reg_dmn, regdmn2G, regdmn5G, ctl2G, ctl5G);
5611 if (status == QDF_STATUS_E_NOMEM)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005612 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005613
Amar Singhal76b41322015-12-09 14:39:17 -08005614 if ((((reg_dmn & ~COUNTRY_ERD_FLAG) == CTRY_JAPAN14) ||
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005615 ((reg_dmn & ~COUNTRY_ERD_FLAG) == CTRY_KOREA_ROC)) &&
5616 (true == wma->tx_chain_mask_cck))
5617 cck_mask_val = 1;
5618
5619 cck_mask_val |= (wma->self_gen_frm_pwr << 16);
Govind Singhd76a5b02016-03-08 15:12:14 +05305620 pdev_param.param_id = WMI_PDEV_PARAM_TX_CHAIN_MASK_CCK;
5621 pdev_param.param_value = cck_mask_val;
5622 ret = wmi_unified_pdev_param_send(wma->wmi_handle,
5623 &pdev_param,
5624 WMA_WILDCARD_PDEV_ID);
5625
Himanshu Agarwal44195412016-03-09 13:03:54 +05305626 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005627 WMA_LOGE("failed to set PDEV tx_chain_mask_cck %d",
5628 ret);
5629
5630 return;
5631}
5632
5633/**
Houston Hoffmana76591b2015-11-10 16:52:05 -08005634 * wma_post_runtime_resume_msg() - post the resume request
5635 * @handle: validated wma handle
5636 *
5637 * request the MC thread unpaus the vdev and set resume dtim
5638 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305639 * Return: qdf status of the mq post
Houston Hoffmana76591b2015-11-10 16:52:05 -08005640 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305641static QDF_STATUS wma_post_runtime_resume_msg(WMA_HANDLE handle)
Houston Hoffmana76591b2015-11-10 16:52:05 -08005642{
5643 cds_msg_t resume_msg;
Houston Hoffmanc45db892015-11-13 19:59:25 -08005644 QDF_STATUS status;
5645 tp_wma_handle wma = (tp_wma_handle) handle;
5646
5647 qdf_runtime_pm_prevent_suspend(wma->wma_runtime_resume_lock);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005648
5649 resume_msg.bodyptr = NULL;
5650 resume_msg.type = WMA_RUNTIME_PM_RESUME_IND;
Houston Hoffmanc45db892015-11-13 19:59:25 -08005651
5652 status = cds_mq_post_message(QDF_MODULE_ID_WMA, &resume_msg);
5653
5654 if (!QDF_IS_STATUS_SUCCESS(status)) {
5655 WMA_LOGE("Failed to post Runtime PM Resume IND to VOS");
5656 qdf_runtime_pm_allow_suspend(wma->wma_runtime_resume_lock);
5657 }
5658
5659 return status;
Houston Hoffmana76591b2015-11-10 16:52:05 -08005660}
5661
5662/**
5663 * wma_post_runtime_suspend_msg() - post the suspend request
5664 * @handle: validated wma handle
5665 *
5666 * Requests for offloads to be configured for runtime suspend
5667 * on the MC thread
5668 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305669 * Return QDF_STATUS_E_AGAIN in case of timeout or QDF_STATUS_SUCCESS
Houston Hoffmana76591b2015-11-10 16:52:05 -08005670 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305671static QDF_STATUS wma_post_runtime_suspend_msg(WMA_HANDLE handle)
Houston Hoffmana76591b2015-11-10 16:52:05 -08005672{
5673 cds_msg_t cds_msg;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305674 QDF_STATUS qdf_status;
Houston Hoffmana76591b2015-11-10 16:52:05 -08005675 tp_wma_handle wma = (tp_wma_handle) handle;
5676
Anurag Chouhance0dc992016-02-16 18:18:03 +05305677 qdf_event_reset(&wma->runtime_suspend);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005678
5679 cds_msg.bodyptr = NULL;
5680 cds_msg.type = WMA_RUNTIME_PM_SUSPEND_IND;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305681 qdf_status = cds_mq_post_message(QDF_MODULE_ID_WMA, &cds_msg);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005682
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305683 if (qdf_status != QDF_STATUS_SUCCESS)
Houston Hoffmana76591b2015-11-10 16:52:05 -08005684 goto failure;
5685
Anurag Chouhance0dc992016-02-16 18:18:03 +05305686 if (qdf_wait_single_event(&wma->runtime_suspend,
Houston Hoffmana76591b2015-11-10 16:52:05 -08005687 WMA_TGT_SUSPEND_COMPLETE_TIMEOUT) !=
Anurag Chouhance0dc992016-02-16 18:18:03 +05305688 QDF_STATUS_SUCCESS) {
Houston Hoffmana76591b2015-11-10 16:52:05 -08005689 WMA_LOGE("Failed to get runtime suspend event");
Houston Hoffmanc45db892015-11-13 19:59:25 -08005690 goto msg_timed_out;
Houston Hoffmana76591b2015-11-10 16:52:05 -08005691 }
5692
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305693 return QDF_STATUS_SUCCESS;
Houston Hoffmana76591b2015-11-10 16:52:05 -08005694
Houston Hoffmanc45db892015-11-13 19:59:25 -08005695msg_timed_out:
5696 wma_post_runtime_resume_msg(wma);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005697failure:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305698 return QDF_STATUS_E_AGAIN;
Houston Hoffmana76591b2015-11-10 16:52:05 -08005699}
5700
5701/**
5702 * __wma_bus_suspend(): handles bus suspend for wma
5703 * @type: is this suspend part of runtime suspend or system suspend?
5704 *
5705 * Bails if a scan is in progress.
5706 * Calls the appropriate handlers based on configuration and event.
5707 *
5708 * Return: 0 for success or error code
5709 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05305710static int __wma_bus_suspend(enum qdf_suspend_type type)
Houston Hoffmana76591b2015-11-10 16:52:05 -08005711{
Anurag Chouhan6d760662016-02-20 16:05:43 +05305712 WMA_HANDLE handle = cds_get_context(QDF_MODULE_ID_WMA);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005713 if (NULL == handle) {
5714 WMA_LOGE("%s: wma context is NULL", __func__);
5715 return -EFAULT;
5716 }
5717
5718 if (wma_check_scan_in_progress(handle)) {
5719 WMA_LOGE("%s: Scan in progress. Aborting suspend", __func__);
5720 return -EBUSY;
5721 }
5722
Anurag Chouhan6d760662016-02-20 16:05:43 +05305723 if (type == QDF_RUNTIME_SUSPEND) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305724 QDF_STATUS status = wma_post_runtime_suspend_msg(handle);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005725 if (status)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305726 return qdf_status_to_os_return(status);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005727 }
5728
Anurag Chouhan6d760662016-02-20 16:05:43 +05305729 if (type == QDF_SYSTEM_SUSPEND)
Houston Hoffmana76591b2015-11-10 16:52:05 -08005730 WMA_LOGE("%s: wow mode selected %d", __func__,
5731 wma_is_wow_mode_selected(handle));
5732
5733 if (wma_is_wow_mode_selected(handle)) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305734 QDF_STATUS status = wma_enable_wow_in_fw(handle);
5735 return qdf_status_to_os_return(status);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005736 }
5737
5738 return wma_suspend_target(handle, 0);
5739}
5740
5741/**
5742 * wma_runtime_suspend() - handles runtime suspend request from hdd
5743 *
5744 * Calls the appropriate handler based on configuration and event.
5745 * Last busy marking should prevent race conditions between processing
5746 * of asyncronous fw events and the running of runtime suspend.
5747 * (eg. last busy marking should guarantee that any auth requests have
5748 * been processed)
5749 * Events comming from the host are not protected, but aren't expected
5750 * to be an issue.
5751 *
5752 * Return: 0 for success or error code
5753 */
5754int wma_runtime_suspend(void)
5755{
Anurag Chouhan6d760662016-02-20 16:05:43 +05305756 return __wma_bus_suspend(QDF_RUNTIME_SUSPEND);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005757}
5758
5759/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005760 * wma_bus_suspend() - handles bus suspend request from hdd
5761 *
5762 * Calls the appropriate handler based on configuration and event
5763 *
5764 * Return: 0 for success or error code
5765 */
5766int wma_bus_suspend(void)
5767{
Houston Hoffmana76591b2015-11-10 16:52:05 -08005768
Anurag Chouhan6d760662016-02-20 16:05:43 +05305769 return __wma_bus_suspend(QDF_SYSTEM_SUSPEND);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005770}
5771
5772/**
5773 * __wma_bus_resume() - bus resume for wma
5774 *
5775 * does the part of the bus resume common to bus and system suspend
5776 *
5777 * Return: os error code.
5778 */
5779int __wma_bus_resume(WMA_HANDLE handle)
5780{
5781 bool wow_mode = wma_is_wow_mode_selected(handle);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305782 QDF_STATUS status;
Houston Hoffmana76591b2015-11-10 16:52:05 -08005783
5784 WMA_LOGE("%s: wow mode %d", __func__, wow_mode);
5785
5786 if (!wow_mode)
Rajeev Kumar9be537e2016-04-25 17:35:33 -07005787 return qdf_status_to_os_return(wma_resume_target(handle));
Houston Hoffmana76591b2015-11-10 16:52:05 -08005788
5789 status = wma_disable_wow_in_fw(handle);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305790 return qdf_status_to_os_return(status);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005791}
5792
5793/**
5794 * wma_runtime_resume() - do the runtime resume operation for wma
5795 *
5796 * Return: os error code.
5797 */
5798int wma_runtime_resume(void)
5799{
5800 int ret;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305801 QDF_STATUS status;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305802 WMA_HANDLE handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005803 if (NULL == handle) {
5804 WMA_LOGE("%s: wma context is NULL", __func__);
5805 return -EFAULT;
5806 }
5807
Houston Hoffmana76591b2015-11-10 16:52:05 -08005808 ret = __wma_bus_resume(handle);
5809 if (ret)
5810 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005811
Houston Hoffmana76591b2015-11-10 16:52:05 -08005812 status = wma_post_runtime_resume_msg(handle);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305813 return qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005814}
5815
5816/**
5817 * wma_bus_resume() - handles bus resume request from hdd
5818 * @handle: valid wma handle
5819 *
5820 * Calls the appropriate handler based on configuration
5821 *
5822 * Return: 0 for success or error code
5823 */
5824int wma_bus_resume(void)
5825{
Anurag Chouhan6d760662016-02-20 16:05:43 +05305826 WMA_HANDLE handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005827 if (NULL == handle) {
5828 WMA_LOGE("%s: wma context is NULL", __func__);
5829 return -EFAULT;
5830 }
5831
Houston Hoffmana76591b2015-11-10 16:52:05 -08005832 return __wma_bus_resume(handle);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005833}
5834
5835/**
Manjunathappa Prakash7b67e622016-04-12 15:18:45 +05305836 * wma_suspend_target_timeout() - Handles the target suspend timeout
5837 * @is_self_recovery_enabled: Is self recovery enabled or not
5838 *
5839 * Return: NONE
5840 */
5841#ifdef QCA_WIFI_3_0_ADRASTEA
5842static inline void wma_suspend_target_timeout(bool is_self_recovery_enabled)
5843{
5844 if (cds_is_driver_recovering()) {
5845 WMA_LOGE("%s: recovery is in progress, ignore!", __func__);
5846 } else {
5847 if (is_self_recovery_enabled) {
5848 cds_trigger_recovery();
5849 } else {
5850 QDF_BUG(0);
5851 }
5852 }
5853}
5854#else /* ROME chipset */
5855static inline void wma_suspend_target_timeout(bool is_self_recovery_enabled)
5856{
5857 if (cds_is_load_or_unload_in_progress() || cds_is_driver_recovering()) {
5858 WMA_LOGE("%s: Unloading/Loading/recovery is in progress, Ignore!",
5859 __func__);
5860 } else {
5861 if (is_self_recovery_enabled) {
5862 cds_trigger_recovery();
5863 } else {
5864 QDF_BUG(0);
5865 }
5866 }
5867}
5868#endif
5869
5870/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005871 * wma_suspend_target() - suspend target
5872 * @handle: wma handle
5873 * @disable_target_intr: disable target interrupt
5874 *
Govind Singhd76a5b02016-03-08 15:12:14 +05305875 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005876 */
Govind Singhd76a5b02016-03-08 15:12:14 +05305877QDF_STATUS wma_suspend_target(WMA_HANDLE handle, int disable_target_intr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005878{
5879 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Komal Seelam3d202862016-02-24 18:43:24 +05305880 struct hif_opaque_softc *scn;
Govind Singhd76a5b02016-03-08 15:12:14 +05305881 QDF_STATUS status;
5882 struct suspend_params param = {0};
5883
Anurag Chouhan6d760662016-02-20 16:05:43 +05305884 tpAniSirGlobal pmac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005885
5886 if (!wma_handle || !wma_handle->wmi_handle) {
5887 WMA_LOGE("WMA is closed. can not issue suspend cmd");
Govind Singhd76a5b02016-03-08 15:12:14 +05305888 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005889 }
Yue Mae1a85f32015-10-20 18:12:45 -07005890
Yue Mae1a85f32015-10-20 18:12:45 -07005891 if (NULL == pmac) {
5892 WMA_LOGE("%s: Unable to get PE context", __func__);
Govind Singhd76a5b02016-03-08 15:12:14 +05305893 return QDF_STATUS_E_INVAL;
Yue Mae1a85f32015-10-20 18:12:45 -07005894 }
Houston Hoffman52ec6692016-04-21 16:36:45 -07005895
Anurag Chouhance0dc992016-02-16 18:18:03 +05305896 qdf_event_reset(&wma_handle->target_suspend);
Govind Singhd76a5b02016-03-08 15:12:14 +05305897 param.disable_target_intr = disable_target_intr;
5898 status = wmi_unified_suspend_send(wma_handle->wmi_handle,
5899 &param,
5900 WMA_WILDCARD_PDEV_ID);
5901 if (QDF_IS_STATUS_ERROR(status))
5902 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005903
5904 wmi_set_target_suspend(wma_handle->wmi_handle, true);
5905
Anurag Chouhance0dc992016-02-16 18:18:03 +05305906 if (qdf_wait_single_event(&wma_handle->target_suspend,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005907 WMA_TGT_SUSPEND_COMPLETE_TIMEOUT)
Anurag Chouhance0dc992016-02-16 18:18:03 +05305908 != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005909 WMA_LOGE("Failed to get ACK from firmware for pdev suspend");
5910 wmi_set_target_suspend(wma_handle->wmi_handle, false);
Manjunathappa Prakash7b67e622016-04-12 15:18:45 +05305911 wma_suspend_target_timeout(pmac->sme.enableSelfRecovery);
Govind Singhd76a5b02016-03-08 15:12:14 +05305912 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005913 }
5914
Anurag Chouhan6d760662016-02-20 16:05:43 +05305915 scn = cds_get_context(QDF_MODULE_ID_HIF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005916
5917 if (scn == NULL) {
5918 WMA_LOGE("%s: Failed to get HIF context", __func__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305919 QDF_ASSERT(0);
Govind Singhd76a5b02016-03-08 15:12:14 +05305920 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005921 }
5922
Govind Singhd76a5b02016-03-08 15:12:14 +05305923 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005924}
5925
5926/**
5927 * wma_target_suspend_acknowledge() - update target susspend status
Houston Hoffmana769ed32016-04-14 17:02:51 -07005928 * @context: HTC_INIT_INFO->context
5929 * @wow_nack: true when wow is rejected
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005930 *
5931 * Return: none
5932 */
Houston Hoffmana769ed32016-04-14 17:02:51 -07005933void wma_target_suspend_acknowledge(void *context, bool wow_nack)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005934{
Anurag Chouhan6d760662016-02-20 16:05:43 +05305935 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005936
5937 if (NULL == wma) {
5938 WMA_LOGE("%s: wma is NULL", __func__);
5939 return;
5940 }
5941
5942 wma->wow_nack = wow_nack;
Anurag Chouhance0dc992016-02-16 18:18:03 +05305943 qdf_event_set(&wma->target_suspend);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005944 if (wow_nack)
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305945 qdf_wake_lock_timeout_acquire(&wma->wow_wake_lock,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005946 WMA_WAKE_LOCK_TIMEOUT,
5947 WIFI_POWER_EVENT_WAKELOCK_WOW);
5948}
5949
5950/**
5951 * wma_resume_target() - resume target
5952 * @handle: wma handle
5953 *
Govind Singhd76a5b02016-03-08 15:12:14 +05305954 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005955 */
Govind Singhd76a5b02016-03-08 15:12:14 +05305956QDF_STATUS wma_resume_target(WMA_HANDLE handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005957{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005958 tp_wma_handle wma = (tp_wma_handle) handle;
Anurag Chouhance0dc992016-02-16 18:18:03 +05305959 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005960#ifdef CONFIG_CNSS
Anurag Chouhan6d760662016-02-20 16:05:43 +05305961 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005962 if (NULL == pMac) {
5963 WMA_LOGE("%s: Unable to get PE context", __func__);
Govind Singhd76a5b02016-03-08 15:12:14 +05305964 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005965 }
5966#endif /* CONFIG_CNSS */
5967
Anurag Chouhance0dc992016-02-16 18:18:03 +05305968 qdf_event_reset(&wma->wma_resume_event);
Govind Singhd76a5b02016-03-08 15:12:14 +05305969 qdf_status = wmi_unified_resume_send(wma->wmi_handle,
5970 WMA_WILDCARD_PDEV_ID);
5971 if (QDF_IS_STATUS_ERROR(qdf_status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005972 WMA_LOGE("Failed to send WMI_PDEV_RESUME_CMDID command");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005973
Anurag Chouhance0dc992016-02-16 18:18:03 +05305974 qdf_status = qdf_wait_single_event(&(wma->wma_resume_event),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005975 WMA_RESUME_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05305976 if (QDF_STATUS_SUCCESS != qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005977 WMA_LOGP("%s: Timeout waiting for resume event from FW",
5978 __func__);
5979 WMA_LOGP("%s: Pending commands %d credits %d", __func__,
5980 wmi_get_pending_cmds(wma->wmi_handle),
5981 wmi_get_host_credits(wma->wmi_handle));
Prashanth Bhatta9e143052015-12-04 11:56:47 -08005982 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005983#ifdef CONFIG_CNSS
5984 if (pMac->sme.enableSelfRecovery) {
5985 cds_trigger_recovery();
5986 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305987 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005988 }
5989#else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305990 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005991#endif /* CONFIG_CNSS */
5992 } else {
5993 WMA_LOGE("%s: SSR in progress, ignore resume timeout",
5994 __func__);
5995 }
5996 } else {
5997 WMA_LOGD("Host wakeup received");
5998 }
5999
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306000 if (QDF_STATUS_SUCCESS == qdf_status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006001 wmi_set_target_suspend(wma->wmi_handle, false);
6002
Houston Hoffman52ec6692016-04-21 16:36:45 -07006003 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006004}
6005
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006006#ifdef FEATURE_WLAN_TDLS
6007/**
6008 * wma_tdls_event_handler() - handle TDLS event
6009 * @handle: wma handle
6010 * @event: event buffer
6011 * @len: buffer length
6012 *
6013 * Return: 0 for success or error code
6014 */
6015int wma_tdls_event_handler(void *handle, uint8_t *event, uint32_t len)
6016{
6017 tp_wma_handle wma = (tp_wma_handle) handle;
6018 WMI_TDLS_PEER_EVENTID_param_tlvs *param_buf = NULL;
6019 wmi_tdls_peer_event_fixed_param *peer_event = NULL;
6020 tSirTdlsEventnotify *tdls_event;
6021
6022 if (!event) {
6023 WMA_LOGE("%s: event param null", __func__);
6024 return -EINVAL;
6025 }
6026
6027 param_buf = (WMI_TDLS_PEER_EVENTID_param_tlvs *) event;
6028 if (!param_buf) {
6029 WMA_LOGE("%s: received null buf from target", __func__);
6030 return -EINVAL;
6031 }
6032
6033 peer_event = param_buf->fixed_param;
6034 if (!peer_event) {
6035 WMA_LOGE("%s: received null event data from target", __func__);
6036 return -EINVAL;
6037 }
6038
6039 tdls_event = (tSirTdlsEventnotify *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306040 qdf_mem_malloc(sizeof(*tdls_event));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006041 if (!tdls_event) {
6042 WMA_LOGE("%s: failed to allocate memory for tdls_event",
6043 __func__);
6044 return -ENOMEM;
6045 }
6046
6047 tdls_event->sessionId = peer_event->vdev_id;
6048 WMI_MAC_ADDR_TO_CHAR_ARRAY(&peer_event->peer_macaddr,
Srinivas Girigowda4f593792015-11-19 15:33:42 -08006049 tdls_event->peermac.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006050
6051 switch (peer_event->peer_status) {
6052 case WMI_TDLS_SHOULD_DISCOVER:
6053 tdls_event->messageType = WMA_TDLS_SHOULD_DISCOVER_CMD;
6054 break;
6055 case WMI_TDLS_SHOULD_TEARDOWN:
6056 tdls_event->messageType = WMA_TDLS_SHOULD_TEARDOWN_CMD;
6057 break;
6058 case WMI_TDLS_PEER_DISCONNECTED:
6059 tdls_event->messageType = WMA_TDLS_PEER_DISCONNECTED_CMD;
6060 break;
6061 default:
6062 WMA_LOGE("%s: Discarding unknown tdls event(%d) from target",
6063 __func__, peer_event->peer_status);
6064 return -EINVAL;
6065 }
6066
6067 switch (peer_event->peer_reason) {
6068 case WMI_TDLS_TEARDOWN_REASON_TX:
6069 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_TX;
6070 break;
6071 case WMI_TDLS_TEARDOWN_REASON_RSSI:
6072 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_RSSI;
6073 break;
6074 case WMI_TDLS_TEARDOWN_REASON_SCAN:
6075 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_SCAN;
6076 break;
6077 case WMI_TDLS_DISCONNECTED_REASON_PEER_DELETE:
6078 tdls_event->peer_reason =
6079 eWNI_TDLS_DISCONNECTED_REASON_PEER_DELETE;
6080 break;
6081 case WMI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT:
6082 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT;
6083 break;
6084 case WMI_TDLS_TEARDOWN_REASON_BAD_PTR:
6085 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_BAD_PTR;
6086 break;
6087 case WMI_TDLS_TEARDOWN_REASON_NO_RESPONSE:
6088 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_NO_RESPONSE;
6089 break;
6090 default:
6091 WMA_LOGE("%s: unknown reason(%d) in tdls event(%d) from target",
6092 __func__, peer_event->peer_reason,
6093 peer_event->peer_status);
6094 return -EINVAL;
6095 }
6096
6097 WMA_LOGD("%s: sending msg to umac, messageType: 0x%x, "
6098 "for peer: %pM, reason: %d, smesessionId: %d",
Srinivas Girigowda4f593792015-11-19 15:33:42 -08006099 __func__, tdls_event->messageType, tdls_event->peermac.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006100 tdls_event->peer_reason, tdls_event->sessionId);
6101
6102 wma_send_msg(wma, tdls_event->messageType, (void *)tdls_event, 0);
6103 return 0;
6104}
6105
6106/**
6107 * wma_set_tdls_offchan_mode() - set tdls off channel mode
6108 * @handle: wma handle
6109 * @chan_switch_params: Pointer to tdls channel switch parameter structure
6110 *
6111 * This function sets tdls off channel mode
6112 *
6113 * Return: 0 on success; Negative errno otherwise
6114 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05306115QDF_STATUS wma_set_tdls_offchan_mode(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006116 tdls_chan_switch_params *chan_switch_params)
6117{
6118 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Himanshu Agarwal44195412016-03-09 13:03:54 +05306119 struct tdls_channel_switch_params params = {0};
6120 QDF_STATUS ret = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006121
6122 if (!wma_handle || !wma_handle->wmi_handle) {
6123 WMA_LOGE(FL(
6124 "WMA is closed, can not issue tdls off channel cmd"
6125 ));
6126 ret = -EINVAL;
6127 goto end;
6128 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006129
Himanshu Agarwal44195412016-03-09 13:03:54 +05306130 params.vdev_id = chan_switch_params->vdev_id;
6131 params.tdls_off_ch_bw_offset =
6132 chan_switch_params->tdls_off_ch_bw_offset;
6133 params.tdls_off_ch = chan_switch_params->tdls_off_ch;
6134 params.tdls_sw_mode = chan_switch_params->tdls_sw_mode;
6135 params.oper_class = chan_switch_params->oper_class;
6136 params.is_responder = chan_switch_params->is_responder;
6137 qdf_mem_copy(params.peer_mac_addr, chan_switch_params->peer_mac_addr,
Krunal Soniab793342016-04-22 18:43:20 -07006138 IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006139
Himanshu Agarwal44195412016-03-09 13:03:54 +05306140 ret = wmi_unified_set_tdls_offchan_mode_cmd(wma_handle->wmi_handle,
6141 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006142
6143end:
6144 if (chan_switch_params)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306145 qdf_mem_free(chan_switch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006146 return ret;
6147}
6148
6149/**
6150 * wma_update_fw_tdls_state() - send enable/disable tdls for a vdev
6151 * @wma: wma handle
6152 * @pwmaTdlsparams: TDLS params
6153 *
6154 * Return: 0 for sucess or error code
6155 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05306156QDF_STATUS wma_update_fw_tdls_state(WMA_HANDLE handle, void *pwmaTdlsparams)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006157{
6158 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006159 t_wma_tdls_mode tdls_mode;
6160 t_wma_tdls_params *wma_tdls = (t_wma_tdls_params *) pwmaTdlsparams;
Himanshu Agarwal44195412016-03-09 13:03:54 +05306161 struct wmi_tdls_params params = {0};
6162 QDF_STATUS ret = QDF_STATUS_SUCCESS;
6163 uint8_t tdls_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006164
6165 if (!wma_handle || !wma_handle->wmi_handle) {
6166 WMA_LOGE("%s: WMA is closed, can not issue fw tdls state cmd",
6167 __func__);
6168 ret = -EINVAL;
6169 goto end_fw_tdls_state;
6170 }
6171
Himanshu Agarwal44195412016-03-09 13:03:54 +05306172 params.tdls_state = wma_tdls->tdls_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006173 tdls_mode = wma_tdls->tdls_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006174
6175 if (WMA_TDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == tdls_mode) {
Himanshu Agarwal44195412016-03-09 13:03:54 +05306176 tdls_state = WMI_TDLS_ENABLE_PASSIVE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006177 } else if (WMA_TDLS_SUPPORT_ENABLED == tdls_mode) {
Himanshu Agarwal44195412016-03-09 13:03:54 +05306178 tdls_state = WMI_TDLS_ENABLE_ACTIVE;
Kabilan Kannan421714b2015-11-23 04:44:59 -08006179 } else if (WMA_TDLS_SUPPORT_ACTIVE_EXTERNAL_CONTROL == tdls_mode) {
Himanshu Agarwal44195412016-03-09 13:03:54 +05306180 tdls_state = WMI_TDLS_ENABLE_ACTIVE_EXTERNAL_CONTROL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006181 } else {
Himanshu Agarwal44195412016-03-09 13:03:54 +05306182 tdls_state = WMI_TDLS_DISABLE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006183 }
6184
Himanshu Agarwal44195412016-03-09 13:03:54 +05306185 params.vdev_id = wma_tdls->vdev_id;
6186 params.notification_interval_ms = wma_tdls->notification_interval_ms;
6187 params.tx_discovery_threshold = wma_tdls->tx_discovery_threshold;
6188 params.tx_teardown_threshold = wma_tdls->tx_teardown_threshold;
6189 params.rssi_teardown_threshold = wma_tdls->rssi_teardown_threshold;
6190 params.rssi_delta = wma_tdls->rssi_delta;
6191 params.tdls_options = wma_tdls->tdls_options;
6192 params.peer_traffic_ind_window = wma_tdls->peer_traffic_ind_window;
6193 params.peer_traffic_response_timeout =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006194 wma_tdls->peer_traffic_response_timeout;
Himanshu Agarwal44195412016-03-09 13:03:54 +05306195 params.puapsd_mask = wma_tdls->puapsd_mask;
6196 params.puapsd_inactivity_time = wma_tdls->puapsd_inactivity_time;
6197 params.puapsd_rx_frame_threshold =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006198 wma_tdls->puapsd_rx_frame_threshold;
Himanshu Agarwal44195412016-03-09 13:03:54 +05306199 params.teardown_notification_ms =
Kabilan Kannanca670be2015-11-23 01:56:12 -08006200 wma_tdls->teardown_notification_ms;
Himanshu Agarwal44195412016-03-09 13:03:54 +05306201 params.tdls_peer_kickout_threshold =
Kabilan Kannan421714b2015-11-23 04:44:59 -08006202 wma_tdls->tdls_peer_kickout_threshold;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006203
Himanshu Agarwal44195412016-03-09 13:03:54 +05306204 ret = wmi_unified_update_fw_tdls_state_cmd(wma_handle->wmi_handle,
6205 &params, tdls_state);
6206 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006207 goto end_fw_tdls_state;
Himanshu Agarwal44195412016-03-09 13:03:54 +05306208
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006209 WMA_LOGD("%s: vdev_id %d", __func__, wma_tdls->vdev_id);
6210
6211end_fw_tdls_state:
6212 if (pwmaTdlsparams)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306213 qdf_mem_free(pwmaTdlsparams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006214 return ret;
6215}
6216
6217/**
6218 * wma_update_tdls_peer_state() - update TDLS peer state
6219 * @handle: wma handle
6220 * @peerStateParams: TDLS peer state params
6221 *
6222 * Return: 0 for success or error code
6223 */
6224int wma_update_tdls_peer_state(WMA_HANDLE handle,
6225 tTdlsPeerStateParams *peerStateParams)
6226{
6227 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006228 uint32_t i;
6229 ol_txrx_pdev_handle pdev;
6230 uint8_t peer_id;
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07006231 ol_txrx_peer_handle peer;
6232 uint8_t *peer_mac_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006233 int ret = 0;
Govind Singhaa64c242016-03-08 11:31:49 +05306234 uint32_t *ch_mhz;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006235
6236 if (!wma_handle || !wma_handle->wmi_handle) {
6237 WMA_LOGE("%s: WMA is closed, can not issue cmd", __func__);
6238 ret = -EINVAL;
6239 goto end_tdls_peer_state;
6240 }
6241
6242 /* peer capability info is valid only when peer state is connected */
6243 if (WMA_TDLS_PEER_STATE_CONNECTED != peerStateParams->peerState) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306244 qdf_mem_zero(&peerStateParams->peerCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006245 sizeof(tTdlsPeerCapParams));
6246 }
6247
Govind Singhaa64c242016-03-08 11:31:49 +05306248 ch_mhz = qdf_mem_malloc(sizeof(uint32_t) *
6249 peerStateParams->peerCap.peerChanLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006250 for (i = 0; i < peerStateParams->peerCap.peerChanLen; ++i) {
Govind Singhaa64c242016-03-08 11:31:49 +05306251 ch_mhz[i] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006252 cds_chan_to_freq(peerStateParams->peerCap.peerChan[i].
6253 chanId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006254 }
6255
Govind Singhaa64c242016-03-08 11:31:49 +05306256 if (wmi_unified_update_tdls_peer_state_cmd(wma_handle->wmi_handle,
6257 (struct tdls_peer_state_params *)peerStateParams,
6258 ch_mhz)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006259 WMA_LOGE("%s: failed to send tdls peer update state command",
6260 __func__);
Govind Singhaa64c242016-03-08 11:31:49 +05306261 qdf_mem_free(ch_mhz);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006262 ret = -EIO;
6263 goto end_tdls_peer_state;
6264 }
6265
Govind Singhaa64c242016-03-08 11:31:49 +05306266 qdf_mem_free(ch_mhz);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006267 /* in case of teardown, remove peer from fw */
6268 if (WMA_TDLS_PEER_STATE_TEARDOWN == peerStateParams->peerState) {
Anurag Chouhan6d760662016-02-20 16:05:43 +05306269 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006270 if (!pdev) {
6271 WMA_LOGE("%s: Failed to find pdev", __func__);
6272 ret = -EIO;
6273 goto end_tdls_peer_state;
6274 }
6275
6276 peer = ol_txrx_find_peer_by_addr(pdev,
6277 peerStateParams->peerMacAddr,
6278 &peer_id);
6279 if (!peer) {
6280 WMA_LOGE("%s: Failed to get peer handle using peer mac %pM",
6281 __func__, peerStateParams->peerMacAddr);
6282 ret = -EIO;
6283 goto end_tdls_peer_state;
6284 }
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07006285 peer_mac_addr = ol_txrx_peer_get_peer_mac_addr(peer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006286
6287 WMA_LOGD("%s: calling wma_remove_peer for peer " MAC_ADDRESS_STR
6288 " vdevId: %d", __func__,
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07006289 MAC_ADDR_ARRAY(peer_mac_addr),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006290 peerStateParams->vdevId);
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07006291 wma_remove_peer(wma_handle, peer_mac_addr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006292 peerStateParams->vdevId, peer, false);
6293 }
6294
6295end_tdls_peer_state:
6296 if (peerStateParams)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306297 qdf_mem_free(peerStateParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006298 return ret;
6299}
6300#endif /* FEATURE_WLAN_TDLS */
6301
6302
6303/**
6304 * wma_dfs_attach() - Attach DFS methods to the umac state.
6305 * @dfs_ic: ieee80211com ptr
6306 *
6307 * Return: Return ieee80211com ptr with updated info
6308 */
6309struct ieee80211com *wma_dfs_attach(struct ieee80211com *dfs_ic)
6310{
6311 /*Allocate memory for dfs_ic before passing it up to dfs_attach() */
6312 dfs_ic = (struct ieee80211com *)
6313 os_malloc(NULL, sizeof(struct ieee80211com), GFP_ATOMIC);
6314 if (dfs_ic == NULL) {
6315 WMA_LOGE("%s:Allocation of dfs_ic failed %zu",
6316 __func__, sizeof(struct ieee80211com));
6317 return NULL;
6318 }
6319 OS_MEMZERO(dfs_ic, sizeof(struct ieee80211com));
6320 /* DFS pattern matching hooks */
6321 dfs_ic->ic_dfs_attach = ol_if_dfs_attach;
6322 dfs_ic->ic_dfs_disable = ol_if_dfs_disable;
6323 dfs_ic->ic_find_channel = ieee80211_find_channel;
6324 dfs_ic->ic_dfs_enable = ol_if_dfs_enable;
6325 dfs_ic->ic_ieee2mhz = ieee80211_ieee2mhz;
6326
6327 /* Hardware facing hooks */
6328 dfs_ic->ic_get_ext_busy = ol_if_dfs_get_ext_busy;
6329 dfs_ic->ic_get_mib_cycle_counts_pct =
6330 ol_if_dfs_get_mib_cycle_counts_pct;
6331 dfs_ic->ic_get_TSF64 = ol_if_get_tsf64;
6332
6333 /* NOL related hooks */
6334 dfs_ic->ic_dfs_usenol = ol_if_dfs_usenol;
6335 /*
6336 * Hooks from wma/dfs/ back
6337 * into the PE/SME
6338 * and shared DFS code
6339 */
6340 dfs_ic->ic_dfs_notify_radar = ieee80211_mark_dfs;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306341 qdf_spinlock_create(&dfs_ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006342 /* Initializes DFS Data Structures and queues */
6343 dfs_attach(dfs_ic);
6344
6345 return dfs_ic;
6346}
6347
6348/**
6349 * wma_dfs_detach() - Detach DFS methods
6350 * @dfs_ic: ieee80211com ptr
6351 *
6352 * Return: none
6353 */
6354void wma_dfs_detach(struct ieee80211com *dfs_ic)
6355{
6356 dfs_detach(dfs_ic);
6357
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306358 qdf_spinlock_destroy(&dfs_ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006359 if (NULL != dfs_ic->ic_curchan) {
6360 OS_FREE(dfs_ic->ic_curchan);
6361 dfs_ic->ic_curchan = NULL;
6362 }
6363
6364 OS_FREE(dfs_ic);
6365}
6366
6367/**
6368 * wma_dfs_configure() - configure dfs
6369 * @ic: ieee80211com ptr
6370 *
6371 * Configures Radar Filters during
6372 * vdev start/channel change/regulatory domain
6373 * change.This Configuration enables to program
6374 * the DFS pattern matching module.
6375 *
6376 * Return: none
6377 */
6378void wma_dfs_configure(struct ieee80211com *ic)
6379{
6380 struct ath_dfs_radar_tab_info rinfo;
6381 int dfsdomain;
6382 int radar_enabled_status = 0;
6383 if (ic == NULL) {
6384 WMA_LOGE("%s: DFS ic is Invalid", __func__);
6385 return;
6386 }
6387
6388 dfsdomain = ic->current_dfs_regdomain;
6389
6390 /* Fetch current radar patterns from the lmac */
6391 OS_MEMZERO(&rinfo, sizeof(rinfo));
6392
6393 /*
6394 * Look up the current DFS
6395 * regulatory domain and decide
6396 * which radar pulses to use.
6397 */
6398 switch (dfsdomain) {
Amar Singhala7bb01b2016-01-27 11:31:59 -08006399 case DFS_FCC_REGION:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006400 WMA_LOGI("%s: DFS-FCC domain", __func__);
Amar Singhala7bb01b2016-01-27 11:31:59 -08006401 rinfo.dfsdomain = DFS_FCC_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006402 rinfo.dfs_radars = dfs_fcc_radars;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306403 rinfo.numradars = QDF_ARRAY_SIZE(dfs_fcc_radars);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006404 rinfo.b5pulses = dfs_fcc_bin5pulses;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306405 rinfo.numb5radars = QDF_ARRAY_SIZE(dfs_fcc_bin5pulses);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006406 break;
Amar Singhala7bb01b2016-01-27 11:31:59 -08006407 case DFS_ETSI_REGION:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006408 WMA_LOGI("%s: DFS-ETSI domain", __func__);
Amar Singhala7bb01b2016-01-27 11:31:59 -08006409 rinfo.dfsdomain = DFS_ETSI_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006410 rinfo.dfs_radars = dfs_etsi_radars;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306411 rinfo.numradars = QDF_ARRAY_SIZE(dfs_etsi_radars);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006412 rinfo.b5pulses = NULL;
6413 rinfo.numb5radars = 0;
6414 break;
Amar Singhala7bb01b2016-01-27 11:31:59 -08006415 case DFS_MKK_REGION:
6416 WMA_LOGI("%s: DFS-MKK domain", __func__);
6417 rinfo.dfsdomain = DFS_MKK_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006418 rinfo.dfs_radars = dfs_mkk4_radars;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306419 rinfo.numradars = QDF_ARRAY_SIZE(dfs_mkk4_radars);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006420 rinfo.b5pulses = dfs_jpn_bin5pulses;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306421 rinfo.numb5radars = QDF_ARRAY_SIZE(dfs_jpn_bin5pulses);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006422 break;
6423 default:
6424 WMA_LOGI("%s: DFS-UNINT domain", __func__);
Amar Singhala7bb01b2016-01-27 11:31:59 -08006425 rinfo.dfsdomain = DFS_UNINIT_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006426 rinfo.dfs_radars = NULL;
6427 rinfo.numradars = 0;
6428 rinfo.b5pulses = NULL;
6429 rinfo.numb5radars = 0;
6430 break;
6431 }
6432
6433 rinfo.dfs_pri_multiplier = ic->dfs_pri_multiplier;
6434
6435 /*
6436 * Set the regulatory domain,
6437 * radar pulse table and enable
6438 * radar events if required.
6439 * dfs_radar_enable() returns
6440 * 0 on success and non-zero
6441 * failure.
6442 */
6443 radar_enabled_status = dfs_radar_enable(ic, &rinfo);
6444 if (radar_enabled_status != DFS_STATUS_SUCCESS) {
6445 WMA_LOGE("%s[%d]: DFS- Radar Detection Enabling Failed",
6446 __func__, __LINE__);
6447 }
6448}
6449
6450/**
6451 * wma_dfs_configure_channel() - configure DFS channel
6452 * @dfs_ic: ieee80211com ptr
Siddarth Poddar17dc4712016-03-09 16:30:27 +05306453 * @band_center_freq1: center frequency 1
6454 * @band_center_freq2: center frequency 2
6455 * (valid only for 11ac vht 80plus80 mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006456 * @ req: vdev start request
6457 *
6458 * Set the Channel parameters in to DFS module
6459 * Also,configure the DFS radar filters for
6460 * matching the DFS phyerrors.
6461 *
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306462 * Return: dfs_ieee80211_channel / NULL for error
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006463 */
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306464struct dfs_ieee80211_channel *wma_dfs_configure_channel(
6465 struct ieee80211com *dfs_ic,
Siddarth Poddar17dc4712016-03-09 16:30:27 +05306466 uint32_t band_center_freq1,
6467 uint32_t band_center_freq2,
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306468 struct wma_vdev_start_req
6469 *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006470{
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006471 uint8_t ext_channel;
6472
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006473 if (dfs_ic == NULL) {
6474 WMA_LOGE("%s: DFS ic is Invalid", __func__);
6475 return NULL;
6476 }
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05306477
6478 if (!dfs_ic->ic_curchan) {
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306479 dfs_ic->ic_curchan = (struct dfs_ieee80211_channel *)os_malloc(
6480 NULL,
6481 sizeof(struct dfs_ieee80211_channel),
6482 GFP_ATOMIC);
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05306483 if (dfs_ic->ic_curchan == NULL) {
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306484 WMA_LOGE(
6485 "%s: allocation of dfs_ic->ic_curchan failed %zu",
6486 __func__, sizeof(struct dfs_ieee80211_channel));
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05306487 return NULL;
6488 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006489 }
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05306490
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306491 OS_MEMZERO(dfs_ic->ic_curchan, sizeof(struct dfs_ieee80211_channel));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006492
6493 dfs_ic->ic_curchan->ic_ieee = req->chan;
Siddarth Poddar17dc4712016-03-09 16:30:27 +05306494 dfs_ic->ic_curchan->ic_freq = cds_chan_to_freq(req->chan);
6495 dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg1 = band_center_freq1;
6496 dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg2 = band_center_freq2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006497 dfs_ic->ic_curchan->ic_pri_freq_center_freq_mhz_separation =
6498 dfs_ic->ic_curchan->ic_freq -
6499 dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg1;
6500
6501 if ((dfs_ic->ic_curchan->ic_ieee >= WMA_11A_CHANNEL_BEGIN) &&
6502 (dfs_ic->ic_curchan->ic_ieee <= WMA_11A_CHANNEL_END)) {
6503 dfs_ic->ic_curchan->ic_flags |= IEEE80211_CHAN_5GHZ;
6504 }
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006505
6506 switch (req->chan_width) {
6507 case CH_WIDTH_20MHZ:
6508 dfs_ic->ic_curchan->ic_flags |=
6509 (req->vht_capable ? IEEE80211_CHAN_VHT20 :
6510 IEEE80211_CHAN_HT20);
6511 break;
6512 case CH_WIDTH_40MHZ:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006513 if (req->chan < req->ch_center_freq_seg0)
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006514 dfs_ic->ic_curchan->ic_flags |=
6515 (req->vht_capable ?
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006516 IEEE80211_CHAN_VHT40PLUS :
6517 IEEE80211_CHAN_HT40PLUS);
6518 else
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006519 dfs_ic->ic_curchan->ic_flags |=
6520 (req->vht_capable ?
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006521 IEEE80211_CHAN_VHT40MINUS :
6522 IEEE80211_CHAN_HT40MINUS);
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006523 break;
6524 case CH_WIDTH_80MHZ:
6525 dfs_ic->ic_curchan->ic_flags |= IEEE80211_CHAN_VHT80;
6526 break;
6527 case CH_WIDTH_80P80MHZ:
Siddarth Poddar17dc4712016-03-09 16:30:27 +05306528 ext_channel = cds_freq_to_chan(band_center_freq2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006529 dfs_ic->ic_curchan->ic_flags |=
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006530 IEEE80211_CHAN_VHT80P80;
6531 dfs_ic->ic_curchan->ic_freq_ext =
Siddarth Poddar17dc4712016-03-09 16:30:27 +05306532 band_center_freq2;
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006533 dfs_ic->ic_curchan->ic_ieee_ext = ext_channel;
6534
6535 /* verify both the 80MHz are DFS bands or not */
Rajeev Kumara3f6c2d2016-04-15 12:47:41 -07006536 if ((CHANNEL_STATE_DFS ==
6537 cds_get_5g_bonded_channel_state(req->chan ,
6538 CH_WIDTH_80MHZ)) &&
6539 (CHANNEL_STATE_DFS == cds_get_5g_bonded_channel_state(
6540 ext_channel - WMA_80MHZ_START_CENTER_CH_DIFF,
6541 CH_WIDTH_80MHZ)))
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006542 dfs_ic->ic_curchan->ic_80p80_both_dfs = true;
6543 break;
6544 case CH_WIDTH_160MHZ:
6545 dfs_ic->ic_curchan->ic_flags |=
6546 IEEE80211_CHAN_VHT160;
6547 break;
6548 default:
6549 WMA_LOGE(
6550 "%s: Recieved a wrong channel width %d",
6551 __func__, req->chan_width);
6552 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006553 }
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006554
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006555 dfs_ic->ic_curchan->ic_flagext |= IEEE80211_CHAN_DFS;
6556
6557 if (req->oper_mode == BSS_OPERATIONAL_MODE_AP) {
6558 dfs_ic->ic_opmode = IEEE80211_M_HOSTAP;
6559 dfs_ic->vdev_id = req->vdev_id;
6560 }
6561
6562 dfs_ic->dfs_pri_multiplier = req->dfs_pri_multiplier;
6563
6564 /*
6565 * Configuring the DFS with current channel and the radar filters
6566 */
6567 wma_dfs_configure(dfs_ic);
6568 WMA_LOGI("%s: DFS- CHANNEL CONFIGURED", __func__);
6569 return dfs_ic->ic_curchan;
6570}
6571
6572
6573/**
6574 * wma_set_dfs_region() - set DFS region
6575 * @wma: wma handle
6576 *
6577 * Configure the DFS region for DFS radar filter initialization
6578 *
6579 * Return: none
6580 */
6581void wma_set_dfs_region(tp_wma_handle wma, uint8_t dfs_region)
6582{
6583 /* dfs information is passed */
Amar Singhala7bb01b2016-01-27 11:31:59 -08006584 if (dfs_region > DFS_MKK_REGION || dfs_region == DFS_UNINIT_REGION)
6585 /* assign DFS_FCC_REGION as default region*/
6586 wma->dfs_ic->current_dfs_regdomain = DFS_FCC_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006587 else
6588 wma->dfs_ic->current_dfs_regdomain = dfs_region;
6589
6590 WMA_LOGI("%s: DFS Region Domain: %d", __func__,
6591 wma->dfs_ic->current_dfs_regdomain);
6592}
6593
6594/**
6595 * wma_get_channels() - prepare dfs radar channel list
6596 * @ichan: channel
6597 * @chan_list: return channel list
6598 *
6599 * Return: return number of channels
6600 */
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306601int wma_get_channels(struct dfs_ieee80211_channel *ichan,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006602 struct wma_dfs_radar_channel_list *chan_list)
6603{
6604 uint8_t center_chan = cds_freq_to_chan(ichan->ic_vhtop_ch_freq_seg1);
Vishwajith Upendrabf673e72016-01-19 16:05:40 -08006605 int count = 0;
6606 int start_channel = 0;
6607 int loop;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006608
6609 chan_list->nchannels = 0;
6610
Vishwajith Upendrabf673e72016-01-19 16:05:40 -08006611 if (IEEE80211_IS_CHAN_11AC_VHT160(ichan)) {
6612 /*
6613 * In 160MHz channel width, need to
6614 * check if each of the 8 20MHz channel
6615 * is DFS before adding to the NOL list.
6616 * As it is possible that part of the
6617 * 160MHz can be Non-DFS channels.
6618 */
6619 start_channel = center_chan - WMA_160MHZ_START_CENTER_CH_DIFF;
6620 for (loop = 0; loop < WMA_DFS_MAX_20M_SUB_CH; loop++) {
6621 if (cds_get_channel_state(start_channel +
6622 (loop * WMA_NEXT_20MHZ_START_CH_DIFF)) ==
6623 CHANNEL_STATE_DFS) {
6624 chan_list->channels[count] = start_channel +
6625 (loop * WMA_NEXT_20MHZ_START_CH_DIFF);
6626 count++;
6627 }
6628 }
6629 chan_list->nchannels = count;
6630 } else if (IEEE80211_IS_CHAN_11AC_VHT80P80(ichan)) {
6631 chan_list->nchannels = 4;
6632 /*
6633 * If SAP is operating in 80p80 mode, either
6634 * one of the two 80 segments or both the 80
6635 * segments can be DFS channels, so need to
6636 * identify on which 80 segment radar has
6637 * been detected and only add those channels
6638 * to the NOL list. center frequency should be
6639 * based on the segment id passed as part of
6640 * channel information in radar indication.
6641 */
6642 if (ichan->ic_radar_found_segid == DFS_80P80_SEG1)
6643 center_chan =
6644 cds_freq_to_chan(ichan->ic_vhtop_ch_freq_seg2);
6645 chan_list->channels[0] = center_chan - 6;
6646 chan_list->channels[1] = center_chan - 2;
6647 chan_list->channels[2] = center_chan + 2;
6648 chan_list->channels[3] = center_chan + 6;
6649 } else if (IEEE80211_IS_CHAN_11AC_VHT80(ichan)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006650 chan_list->nchannels = 4;
6651 chan_list->channels[0] = center_chan - 6;
6652 chan_list->channels[1] = center_chan - 2;
6653 chan_list->channels[2] = center_chan + 2;
6654 chan_list->channels[3] = center_chan + 6;
6655 } else if (IEEE80211_IS_CHAN_11N_HT40(ichan) ||
6656 IEEE80211_IS_CHAN_11AC_VHT40(ichan)) {
6657 chan_list->nchannels = 2;
6658 chan_list->channels[0] = center_chan - 2;
6659 chan_list->channels[1] = center_chan + 2;
6660 } else {
6661 chan_list->nchannels = 1;
6662 chan_list->channels[0] = center_chan;
6663 }
6664
6665 return chan_list->nchannels;
6666}
6667
6668
6669/**
6670 * wma_dfs_indicate_radar() - Indicate Radar to SAP/HDD
6671 * @ic: ieee80211com ptr
6672 * @ichan: ieee 80211 channel
6673 *
6674 * Return: 0 for success or error code
6675 */
6676int wma_dfs_indicate_radar(struct ieee80211com *ic,
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306677 struct dfs_ieee80211_channel *ichan)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006678{
6679 tp_wma_handle wma;
6680 void *hdd_ctx;
6681 struct wma_dfs_radar_indication *radar_event;
6682 struct wma_dfs_radar_ind wma_radar_event;
6683 tpAniSirGlobal pmac = NULL;
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05306684 bool indication_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006685
Anurag Chouhan6d760662016-02-20 16:05:43 +05306686 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006687 if (wma == NULL) {
6688 WMA_LOGE("%s: DFS- Invalid wma", __func__);
6689 return -ENOENT;
6690 }
6691
Anurag Chouhan6d760662016-02-20 16:05:43 +05306692 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006693 pmac = (tpAniSirGlobal)
Anurag Chouhan6d760662016-02-20 16:05:43 +05306694 cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006695
6696 if (!pmac) {
6697 WMA_LOGE("%s: Invalid MAC handle", __func__);
6698 return -ENOENT;
6699 }
6700
6701 if (wma->dfs_ic != ic) {
6702 WMA_LOGE("%s:DFS- Invalid WMA handle", __func__);
6703 return -ENOENT;
6704 }
6705 radar_event = (struct wma_dfs_radar_indication *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306706 qdf_mem_malloc(sizeof(struct wma_dfs_radar_indication));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006707 if (radar_event == NULL) {
6708 WMA_LOGE("%s:DFS- Invalid radar_event", __func__);
6709 return -ENOMEM;
6710 }
6711
6712 /*
6713 * Do not post multiple Radar events on the same channel.
6714 * But, when DFS test mode is enabled, allow multiple dfs
6715 * radar events to be posted on the same channel.
6716 */
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306717 qdf_spin_lock_bh(&ic->chan_lock);
Edhar, Mahesh Kumar35d9b2e2015-10-26 17:06:23 +05306718 if (!pmac->sap.SapDfsInfo.disable_dfs_ch_switch)
6719 wma->dfs_ic->disable_phy_err_processing = true;
6720
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006721 if ((ichan->ic_ieee != (wma->dfs_ic->last_radar_found_chan)) ||
6722 (pmac->sap.SapDfsInfo.disable_dfs_ch_switch == true)) {
6723 wma->dfs_ic->last_radar_found_chan = ichan->ic_ieee;
6724 /* Indicate the radar event to HDD to stop the netif Tx queues */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006725 wma_radar_event.chan_freq = ichan->ic_freq;
6726 wma_radar_event.dfs_radar_status = WMA_DFS_RADAR_FOUND;
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05306727 indication_status =
6728 wma->dfs_radar_indication_cb(hdd_ctx, &wma_radar_event);
6729 if (indication_status == false) {
6730 WMA_LOGE("%s:Application triggered channel switch in progress!.. drop radar event indiaction to SAP",
6731 __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306732 qdf_mem_free(radar_event);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306733 qdf_spin_unlock_bh(&ic->chan_lock);
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05306734 return 0;
6735 }
6736
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006737 WMA_LOGE("%s:DFS- RADAR INDICATED TO HDD", __func__);
6738
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05306739 wma_radar_event.ieee_chan_number = ichan->ic_ieee;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006740 /*
6741 * Indicate to the radar event to SAP to
6742 * select a new channel and set CSA IE
6743 */
6744 radar_event->vdev_id = ic->vdev_id;
6745 wma_get_channels(ichan, &radar_event->chan_list);
6746 radar_event->dfs_radar_status = WMA_DFS_RADAR_FOUND;
6747 radar_event->use_nol = ic->ic_dfs_usenol(ic);
6748 wma_send_msg(wma, WMA_DFS_RADAR_IND, (void *)radar_event, 0);
6749 WMA_LOGE("%s:DFS- WMA_DFS_RADAR_IND Message Posted", __func__);
6750 }
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306751 qdf_spin_unlock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006752
6753 return 0;
6754}
6755
6756#ifdef WLAN_FEATURE_MEMDUMP
6757/*
6758 * wma_process_fw_mem_dump_req() - Function to request fw memory dump from
6759 * firmware
6760 * @wma: Pointer to WMA handle
6761 * @mem_dump_req: Pointer for mem_dump_req
6762 *
6763 * This function sends memory dump request to firmware
6764 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306765 * Return: QDF_STATUS_SUCCESS for success otherwise failure
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006766 *
6767 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306768QDF_STATUS wma_process_fw_mem_dump_req(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006769 struct fw_dump_req *mem_dump_req)
6770{
Govind Singhaa64c242016-03-08 11:31:49 +05306771 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006772
6773 if (!mem_dump_req || !wma) {
6774 WMA_LOGE(FL("input pointer is NULL"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306775 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006776 }
6777
Govind Singhaa64c242016-03-08 11:31:49 +05306778 ret = wmi_unified_process_fw_mem_dump_cmd(wma->wmi_handle,
6779 (struct fw_dump_req_param *) mem_dump_req);
6780 if (ret)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306781 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006782
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306783 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006784}
6785
6786/**
6787 * wma_fw_mem_dump_rsp() - send fw mem dump response to SME
6788 *
6789 * @req_id - request id.
6790 * @status - copy status from the firmware.
6791 *
6792 * This function is called by the memory dump response handler to
6793 * indicate SME that firmware dump copy is complete
6794 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306795 * Return: QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006796 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306797static QDF_STATUS wma_fw_mem_dump_rsp(uint32_t req_id, uint32_t status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006798{
6799 struct fw_dump_rsp *dump_rsp;
6800 cds_msg_t sme_msg = {0};
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306801 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006802
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306803 dump_rsp = qdf_mem_malloc(sizeof(*dump_rsp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006804
6805 if (!dump_rsp) {
6806 WMA_LOGE(FL("Memory allocation failed."));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306807 qdf_status = QDF_STATUS_E_NOMEM;
6808 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006809 }
6810
6811 WMA_LOGI(FL("FW memory dump copy complete status: %d for request: %d"),
6812 status, req_id);
6813
6814 dump_rsp->request_id = req_id;
6815 dump_rsp->dump_complete = status;
6816
6817 sme_msg.type = eWNI_SME_FW_DUMP_IND;
6818 sme_msg.bodyptr = dump_rsp;
6819 sme_msg.bodyval = 0;
6820
Anurag Chouhan6d760662016-02-20 16:05:43 +05306821 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306822 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006823 WMA_LOGE(FL("Fail to post fw mem dump ind msg"));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306824 qdf_mem_free(dump_rsp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006825 }
6826
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306827 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006828}
6829
6830/**
6831 * wma_fw_mem_dump_event_handler() - handles fw memory dump event
6832 *
6833 * @handle: pointer to wma handle.
6834 * @cmd_param_info: pointer to TLV info received in the event.
6835 * @len: length of data in @cmd_param_info
6836 *
6837 * This function is a handler for firmware memory dump event.
6838 *
6839 * Return: integer (0 for success and error code otherwise)
6840 */
6841int wma_fw_mem_dump_event_handler(void *handle, u_int8_t *cmd_param_info,
6842 u_int32_t len)
6843{
6844 WMI_UPDATE_FW_MEM_DUMP_EVENTID_param_tlvs *param_buf;
6845 wmi_update_fw_mem_dump_fixed_param *event;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306846 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006847
6848 param_buf =
6849 (WMI_UPDATE_FW_MEM_DUMP_EVENTID_param_tlvs *) cmd_param_info;
6850 if (!param_buf) {
6851 WMA_LOGA("%s: Invalid stats event", __func__);
6852 return -EINVAL;
6853 }
6854
6855 event = param_buf->fixed_param;
6856
6857 status = wma_fw_mem_dump_rsp(event->request_id,
6858 event->fw_mem_dump_complete);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306859 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006860 WMA_LOGE("Error posting FW MEM DUMP RSP.");
6861 return -EINVAL;
6862 }
6863
6864 WMA_LOGI("FW MEM DUMP RSP posted successfully");
6865 return 0;
6866}
6867#endif /* WLAN_FEATURE_MEMDUMP */
6868
6869/*
6870 * wma_process_set_ie_info() - Function to send IE info to firmware
6871 * @wma: Pointer to WMA handle
6872 * @ie_data: Pointer for ie data
6873 *
6874 * This function sends IE information to firmware
6875 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306876 * Return: QDF_STATUS_SUCCESS for success otherwise failure
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006877 *
6878 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306879QDF_STATUS wma_process_set_ie_info(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006880 struct vdev_ie_info *ie_info)
6881{
Govind Singhaa64c242016-03-08 11:31:49 +05306882 struct vdev_ie_info_param cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006883 int ret;
6884
6885 if (!ie_info || !wma) {
6886 WMA_LOGE(FL("input pointer is NULL"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306887 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006888 }
6889
6890 /* Validate the input */
6891 if (ie_info->length <= 0) {
6892 WMA_LOGE(FL("Invalid IE length"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306893 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006894 }
6895
Govind Singhaa64c242016-03-08 11:31:49 +05306896 cmd.vdev_id = ie_info->vdev_id;
6897 cmd.ie_id = ie_info->ie_id;
6898 cmd.length = ie_info->length;
6899 cmd.data = ie_info->data;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006900
Govind Singhaa64c242016-03-08 11:31:49 +05306901 ret = wmi_unified_process_set_ie_info_cmd(wma->wmi_handle,
6902 &cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006903
6904 return ret;
6905}
6906
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306907/**
6908 * wma_get_bpf_caps_event_handler() - Event handler for get bpf capability
6909 * @handle: WMA global handle
6910 * @cmd_param_info: command event data
6911 * @len: Length of @cmd_param_info
6912 *
6913 * Return: 0 on Success or Errno on failure
6914 */
6915int wma_get_bpf_caps_event_handler(void *handle,
6916 u_int8_t *cmd_param_info,
6917 u_int32_t len)
6918{
6919 WMI_BPF_CAPABILIY_INFO_EVENTID_param_tlvs *param_buf;
6920 wmi_bpf_capability_info_evt_fixed_param *event;
6921 struct sir_bpf_get_offload *bpf_get_offload;
6922 tpAniSirGlobal pmac = (tpAniSirGlobal)cds_get_context(
6923 QDF_MODULE_ID_PE);
6924
6925 if (!pmac) {
6926 WMA_LOGE("%s: Invalid pmac", __func__);
6927 return -EINVAL;
6928 }
6929 if (!pmac->sme.pbpf_get_offload_cb) {
6930 WMA_LOGE("%s: Callback not registered", __func__);
6931 return -EINVAL;
6932 }
6933
6934 param_buf = (WMI_BPF_CAPABILIY_INFO_EVENTID_param_tlvs *)cmd_param_info;
6935 event = param_buf->fixed_param;
6936 bpf_get_offload = qdf_mem_malloc(sizeof(*bpf_get_offload));
6937
6938 if (!bpf_get_offload) {
6939 WMA_LOGP("%s: Memory allocation failed.", __func__);
6940 return -ENOMEM;
6941 }
6942
6943 bpf_get_offload->bpf_version = event->bpf_version;
6944 bpf_get_offload->max_bpf_filters = event->max_bpf_filters;
6945 bpf_get_offload->max_bytes_for_bpf_inst =
6946 event->max_bytes_for_bpf_inst;
6947 WMA_LOGD("%s: BPF capabilities version: %d max bpf filter size: %d",
6948 __func__, bpf_get_offload->bpf_version,
6949 bpf_get_offload->max_bytes_for_bpf_inst);
6950
6951 WMA_LOGD("%s: sending bpf capabilities event to hdd", __func__);
6952 pmac->sme.pbpf_get_offload_cb(pmac->hHdd, bpf_get_offload);
6953 qdf_mem_free(bpf_get_offload);
6954 return 0;
6955}
6956
6957/**
6958 * wma_get_bpf_capabilities - Send get bpf capability to firmware
6959 * @wma_handle: wma handle
6960 *
6961 * Return: QDF_STATUS enumeration.
6962 */
6963QDF_STATUS wma_get_bpf_capabilities(tp_wma_handle wma)
6964{
6965 QDF_STATUS status = QDF_STATUS_SUCCESS;
6966 wmi_bpf_get_capability_cmd_fixed_param *cmd;
6967 wmi_buf_t wmi_buf;
6968 uint32_t len;
6969 u_int8_t *buf_ptr;
6970
6971 if (!wma || !wma->wmi_handle) {
6972 WMA_LOGE(FL("WMA is closed, can not issue get BPF capab"));
6973 return QDF_STATUS_E_INVAL;
6974 }
6975
6976 if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
6977 WMI_SERVICE_BPF_OFFLOAD)) {
6978 WMA_LOGE(FL("BPF cababilities feature bit not enabled"));
6979 return QDF_STATUS_E_FAILURE;
6980 }
6981
6982 len = sizeof(*cmd);
6983 wmi_buf = wmi_buf_alloc(wma->wmi_handle, len);
6984 if (!wmi_buf) {
6985 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
6986 return QDF_STATUS_E_NOMEM;
6987 }
6988
6989 buf_ptr = (u_int8_t *) wmi_buf_data(wmi_buf);
6990 cmd = (wmi_bpf_get_capability_cmd_fixed_param *) buf_ptr;
6991 WMITLV_SET_HDR(&cmd->tlv_header,
6992 WMITLV_TAG_STRUC_wmi_bpf_get_capability_cmd_fixed_param,
6993 WMITLV_GET_STRUCT_TLVLEN(
6994 wmi_bpf_get_capability_cmd_fixed_param));
6995
6996 if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len,
6997 WMI_BPF_GET_CAPABILITY_CMDID)) {
6998 WMA_LOGE(FL("Failed to send BPF capability command"));
6999 wmi_buf_free(wmi_buf);
7000 return QDF_STATUS_E_FAILURE;
7001 }
7002 return status;
7003}
7004
7005/**
7006 * wma_set_bpf_instructions - Set bpf instructions to firmware
7007 * @wma: wma handle
7008 * @bpf_set_offload: Bpf offload information to set to firmware
7009 *
7010 * Return: QDF_STATUS enumeration
7011 */
7012QDF_STATUS wma_set_bpf_instructions(tp_wma_handle wma,
7013 struct sir_bpf_set_offload *bpf_set_offload)
7014{
7015 wmi_bpf_set_vdev_instructions_cmd_fixed_param *cmd;
7016 wmi_buf_t wmi_buf;
7017 uint32_t len = 0, len_aligned = 0;
7018 u_int8_t *buf_ptr;
7019
7020 if (!wma || !wma->wmi_handle) {
7021 WMA_LOGE("%s: WMA is closed, can not issue set BPF capability",
7022 __func__);
7023 return QDF_STATUS_E_INVAL;
7024 }
7025
7026 if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
7027 WMI_SERVICE_BPF_OFFLOAD)) {
7028 WMA_LOGE(FL("BPF offload feature Disabled"));
7029 return QDF_STATUS_E_NOSUPPORT;
7030 }
7031
7032 if (bpf_set_offload->total_length) {
7033 len_aligned = roundup(bpf_set_offload->current_length,
7034 sizeof(A_UINT32));
7035 len = len_aligned + WMI_TLV_HDR_SIZE;
7036 }
7037
7038 len += sizeof(*cmd);
7039 wmi_buf = wmi_buf_alloc(wma->wmi_handle, len);
7040 if (!wmi_buf) {
7041 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
7042 return QDF_STATUS_E_NOMEM;
7043 }
7044
7045 buf_ptr = (u_int8_t *) wmi_buf_data(wmi_buf);
7046 cmd = (wmi_bpf_set_vdev_instructions_cmd_fixed_param *) buf_ptr;
7047
7048 WMITLV_SET_HDR(&cmd->tlv_header,
7049 WMITLV_TAG_STRUC_wmi_bpf_set_vdev_instructions_cmd_fixed_param,
7050 WMITLV_GET_STRUCT_TLVLEN(
7051 wmi_bpf_set_vdev_instructions_cmd_fixed_param));
7052 cmd->vdev_id = bpf_set_offload->session_id;
7053 cmd->filter_id = bpf_set_offload->filter_id;
7054 cmd->total_length = bpf_set_offload->total_length;
7055 cmd->current_offset = bpf_set_offload->current_offset;
7056 cmd->current_length = bpf_set_offload->current_length;
7057
7058 if (bpf_set_offload->total_length) {
7059 buf_ptr +=
7060 sizeof(wmi_bpf_set_vdev_instructions_cmd_fixed_param);
7061 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, len_aligned);
7062 buf_ptr += WMI_TLV_HDR_SIZE;
7063 qdf_mem_copy(buf_ptr, bpf_set_offload->program,
7064 bpf_set_offload->current_length);
7065 qdf_mem_free(bpf_set_offload->program);
7066 }
7067
7068 if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len,
7069 WMI_BPF_SET_VDEV_INSTRUCTIONS_CMDID)) {
7070 WMA_LOGE(FL("Failed to send config bpf instructions command"));
7071 wmi_buf_free(wmi_buf);
7072 return QDF_STATUS_E_FAILURE;
7073 }
7074 return QDF_STATUS_SUCCESS;
7075}