blob: a906e0b610c764a888bcb4ee9e6e83b9ecc44fe5 [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>
Manjunathappa Prakash3454fd62016-04-01 08:52:06 -070048#include <cdp_txrx_peer_ops.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080049
Nirav Shahcbc6d722016-03-01 16:24:53 +053050#include "qdf_nbuf.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053051#include "qdf_types.h"
Anurag Chouhan600c3a02016-03-01 10:33:54 +053052#include "qdf_mem.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080053#include "ol_txrx_peer_find.h"
54
55#include "wma_types.h"
56#include "lim_api.h"
57#include "lim_session_utils.h"
58
59#include "cds_utils.h"
60
61#if !defined(REMOVE_PKT_LOG)
62#include "pktlog_ac.h"
63#endif /* REMOVE_PKT_LOG */
64
65#include "dbglog_host.h"
66#include "csr_api.h"
67#include "ol_fw.h"
68
69#include "dfs.h"
70#include "radar_filters.h"
71#include "wma_internal.h"
Poddar, Siddarth5a91f5b2016-04-28 12:24:10 +053072#include "ol_txrx.h"
Naveen Rawate82c1f32016-06-22 15:34:36 -070073#include "wma_nan_datapath.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080074
75#ifndef ARRAY_LENGTH
76#define ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0]))
77#endif
78
79#define WMA_WOW_STA_WAKE_UP_EVENTS ((1 << WOW_CSA_IE_EVENT) |\
80 (1 << WOW_CLIENT_KICKOUT_EVENT) |\
81 (1 << WOW_PATTERN_MATCH_EVENT) |\
82 (1 << WOW_MAGIC_PKT_RECVD_EVENT) |\
83 (1 << WOW_DEAUTH_RECVD_EVENT) |\
84 (1 << WOW_DISASSOC_RECVD_EVENT) |\
85 (1 << WOW_BMISS_EVENT) |\
86 (1 << WOW_GTK_ERR_EVENT) |\
87 (1 << WOW_BETTER_AP_EVENT) |\
88 (1 << WOW_HTT_EVENT) |\
89 (1 << WOW_RA_MATCH_EVENT) |\
90 (1 << WOW_NLO_DETECTED_EVENT) |\
91 (1 << WOW_EXTSCAN_EVENT))\
92
93#define WMA_WOW_SAP_WAKE_UP_EVENTS ((1 << WOW_PROBE_REQ_WPS_IE_EVENT) |\
94 (1 << WOW_PATTERN_MATCH_EVENT) |\
95 (1 << WOW_AUTH_REQ_EVENT) |\
96 (1 << WOW_ASSOC_REQ_EVENT) |\
97 (1 << WOW_DEAUTH_RECVD_EVENT) |\
98 (1 << WOW_DISASSOC_RECVD_EVENT) |\
99 (1 << WOW_HTT_EVENT))\
100
101static const uint8_t arp_ptrn[] = {0x08, 0x06};
102static const uint8_t arp_mask[] = {0xff, 0xff};
103static const uint8_t ns_ptrn[] = {0x86, 0xDD};
104static const uint8_t discvr_ptrn[] = {0xe0, 0x00, 0x00, 0xf8};
105static const uint8_t discvr_mask[] = {0xf0, 0x00, 0x00, 0xf8};
106
107#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
108/**
109 * wma_post_auto_shutdown_msg() - to post auto shutdown event to sme
110 *
111 * Return: 0 for success or error code
112 */
113static int wma_post_auto_shutdown_msg(void)
114{
115 tSirAutoShutdownEvtParams *auto_sh_evt;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530116 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800117 cds_msg_t sme_msg = { 0 };
118
119 auto_sh_evt = (tSirAutoShutdownEvtParams *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530120 qdf_mem_malloc(sizeof(tSirAutoShutdownEvtParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800121 if (!auto_sh_evt) {
122 WMA_LOGE(FL("No Mem"));
123 return -ENOMEM;
124 }
125
126 auto_sh_evt->shutdown_reason =
127 WMI_HOST_AUTO_SHUTDOWN_REASON_TIMER_EXPIRY;
128 sme_msg.type = eWNI_SME_AUTO_SHUTDOWN_IND;
129 sme_msg.bodyptr = auto_sh_evt;
130 sme_msg.bodyval = 0;
131
Anurag Chouhan6d760662016-02-20 16:05:43 +0530132 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530133 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800134 WMA_LOGE("Fail to post eWNI_SME_AUTO_SHUTDOWN_IND msg to SME");
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530135 qdf_mem_free(auto_sh_evt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800136 return -EINVAL;
137 }
138
139 return 0;
140}
141#endif
142/**
143 * wma_send_snr_request() - send request to fw to get RSSI stats
144 * @wma_handle: wma handle
145 * @pGetRssiReq: get RSSI request
146 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530147 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800148 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530149QDF_STATUS wma_send_snr_request(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800150 void *pGetRssiReq)
151{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800152 tAniGetRssiReq *pRssiBkUp = NULL;
153
154 /* command is in progess */
155 if (NULL != wma_handle->pGetRssiReq)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530156 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800157
158 /* create a copy of csrRssiCallback to send rssi value
159 * after wmi event
160 */
161 if (pGetRssiReq) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530162 pRssiBkUp = qdf_mem_malloc(sizeof(tAniGetRssiReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800163 if (!pRssiBkUp) {
164 WMA_LOGE("Failed to allocate memory for tAniGetRssiReq");
165 wma_handle->pGetRssiReq = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530166 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800167 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530168 qdf_mem_set(pRssiBkUp, sizeof(tAniGetRssiReq), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800169 pRssiBkUp->sessionId =
170 ((tAniGetRssiReq *) pGetRssiReq)->sessionId;
171 pRssiBkUp->rssiCallback =
172 ((tAniGetRssiReq *) pGetRssiReq)->rssiCallback;
173 pRssiBkUp->pDevContext =
174 ((tAniGetRssiReq *) pGetRssiReq)->pDevContext;
175 wma_handle->pGetRssiReq = (void *)pRssiBkUp;
176 }
177
Govind Singhaa64c242016-03-08 11:31:49 +0530178 if (wmi_unified_snr_request_cmd(wma_handle->wmi_handle)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800179 WMA_LOGE("Failed to send host stats request to fw");
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530180 qdf_mem_free(pRssiBkUp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800181 wma_handle->pGetRssiReq = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530182 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800183 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530184 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800185}
186
187/**
188 * wma_get_snr() - get RSSI from fw
189 * @psnr_req: request params
190 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530191 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800192 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530193QDF_STATUS wma_get_snr(tAniGetSnrReq *psnr_req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800194{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800195 tAniGetSnrReq *psnr_req_bkp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800196 tp_wma_handle wma_handle = NULL;
197 struct wma_txrx_node *intr;
198
Anurag Chouhan6d760662016-02-20 16:05:43 +0530199 wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800200
201 if (NULL == wma_handle) {
202 WMA_LOGE("%s : Failed to get wma_handle", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530203 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800204 }
205
206 intr = &wma_handle->interfaces[psnr_req->sessionId];
207 /* command is in progess */
208 if (NULL != intr->psnr_req) {
209 WMA_LOGE("%s : previous snr request is pending", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530210 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800211 }
212
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530213 psnr_req_bkp = qdf_mem_malloc(sizeof(tAniGetSnrReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800214 if (!psnr_req_bkp) {
215 WMA_LOGE("Failed to allocate memory for tAniGetSnrReq");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530216 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800217 }
218
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530219 qdf_mem_set(psnr_req_bkp, sizeof(tAniGetSnrReq), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800220 psnr_req_bkp->staId = psnr_req->staId;
221 psnr_req_bkp->pDevContext = psnr_req->pDevContext;
222 psnr_req_bkp->snrCallback = psnr_req->snrCallback;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800223 intr->psnr_req = (void *)psnr_req_bkp;
Govind Singhaa64c242016-03-08 11:31:49 +0530224
225 if (wmi_unified_snr_cmd(wma_handle->wmi_handle,
226 psnr_req->sessionId)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800227 WMA_LOGE("Failed to send host stats request to fw");
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530228 qdf_mem_free(psnr_req_bkp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800229 intr->psnr_req = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530230 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800231 }
232
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530233 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800234}
235
236/**
237 * wma_process_link_status_req() - process link status request from UMAC
238 * @wma: wma handle
239 * @pGetLinkStatus: get link params
240 *
241 * Return: none
242 */
243void wma_process_link_status_req(tp_wma_handle wma,
244 tAniGetLinkStatus *pGetLinkStatus)
245{
Govind Singhaa64c242016-03-08 11:31:49 +0530246 struct link_status_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800247 struct wma_txrx_node *iface =
248 &wma->interfaces[pGetLinkStatus->sessionId];
249
250 if (iface->plink_status_req) {
251 WMA_LOGE("%s:previous link status request is pending,deleting the new request",
252 __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530253 qdf_mem_free(pGetLinkStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800254 return;
255 }
256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800257 iface->plink_status_req = pGetLinkStatus;
Govind Singhaa64c242016-03-08 11:31:49 +0530258 cmd.session_id = pGetLinkStatus->sessionId;
259 if (wmi_unified_link_status_req_cmd(wma->wmi_handle, &cmd)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800260 WMA_LOGE("Failed to send WMI link status request to fw");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800261 iface->plink_status_req = NULL;
262 goto end;
263 }
264
265 return;
266
267end:
268 wma_post_link_status(pGetLinkStatus, LINK_STATUS_LEGACY);
269}
270
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700271#ifdef WLAN_FEATURE_TSF
272/**
273 * wma_vdev_tsf_handler() - handle tsf event indicated by FW
274 * @handle: wma context
275 * @data: event buffer
276 * @data len: length of event buffer
277 *
278 * Return: 0 on success
279 */
280int wma_vdev_tsf_handler(void *handle, uint8_t *data, uint32_t data_len)
281{
282 cds_msg_t tsf_msg = {0};
283 WMI_VDEV_TSF_REPORT_EVENTID_param_tlvs *param_buf;
284 wmi_vdev_tsf_report_event_fixed_param *tsf_event;
285 struct stsf *ptsf;
286
287 if (data == NULL) {
288 WMA_LOGE("%s: invalid pointer", __func__);
289 return -EINVAL;
290 }
291 ptsf = qdf_mem_malloc(sizeof(*ptsf));
292 if (NULL == ptsf) {
293 WMA_LOGE("%s: failed to allocate tsf data structure", __func__);
294 return -ENOMEM;
295 }
296
297 param_buf = (WMI_VDEV_TSF_REPORT_EVENTID_param_tlvs *)data;
298 tsf_event = param_buf->fixed_param;
299
300 ptsf->vdev_id = tsf_event->vdev_id;
301 ptsf->tsf_low = tsf_event->tsf_low;
302 ptsf->tsf_high = tsf_event->tsf_high;
Manikandan Mohan5356c2b2016-04-03 15:51:35 -0700303 ptsf->soc_timer_low = tsf_event->qtimer_low;
304 ptsf->soc_timer_high = tsf_event->qtimer_high;
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700305
306 WMA_LOGD("%s: receive WMI_VDEV_TSF_REPORT_EVENTID ", __func__);
307 WMA_LOGD("%s: vdev_id = %u,tsf_low =%u, tsf_high = %u", __func__,
308 ptsf->vdev_id, ptsf->tsf_low, ptsf->tsf_high);
309
310 tsf_msg.type = eWNI_SME_TSF_EVENT;
311 tsf_msg.bodyptr = ptsf;
312 tsf_msg.bodyval = 0;
313
314 if (QDF_STATUS_SUCCESS !=
315 cds_mq_post_message(CDS_MQ_ID_SME, &tsf_msg)) {
316
317 WMA_LOGP("%s: Failed to post eWNI_SME_TSF_EVENT", __func__);
318 qdf_mem_free(ptsf);
319 return -EINVAL;
320 }
321 return 0;
322}
323
Manikandan Mohan5356c2b2016-04-03 15:51:35 -0700324#ifdef QCA_WIFI_3_0
325#define TSF_FW_ACTION_CMD TSF_TSTAMP_QTIMER_CAPTURE_REQ
326#else
327#define TSF_FW_ACTION_CMD TSF_TSTAMP_CAPTURE_REQ
328#endif
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700329/**
330 * wma_capture_tsf() - send wmi to fw to capture tsf
331 * @wma_handle: wma handler
332 * @vdev_id: vdev id
333 *
334 * Return: wmi send state
335 */
336QDF_STATUS wma_capture_tsf(tp_wma_handle wma_handle, uint32_t vdev_id)
337{
338 QDF_STATUS status = QDF_STATUS_SUCCESS;
339 wmi_buf_t buf;
340 wmi_vdev_tsf_tstamp_action_cmd_fixed_param *cmd;
341 int ret;
342 int len = sizeof(*cmd);
343
344 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
345 if (!buf) {
346 WMA_LOGP("%s: failed to allocate memory for cap tsf cmd",
347 __func__);
348 return QDF_STATUS_E_NOMEM;
349 }
350
351 cmd = (wmi_vdev_tsf_tstamp_action_cmd_fixed_param *) wmi_buf_data(buf);
352 cmd->vdev_id = vdev_id;
Manikandan Mohan5356c2b2016-04-03 15:51:35 -0700353 cmd->tsf_action = TSF_FW_ACTION_CMD;
354 WMA_LOGD("%s :vdev_id %u, tsf_cmd: %d", __func__, cmd->vdev_id,
355 cmd->tsf_action);
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700356
357 WMITLV_SET_HDR(&cmd->tlv_header,
358 WMITLV_TAG_STRUC_wmi_vdev_tsf_tstamp_action_cmd_fixed_param,
359 WMITLV_GET_STRUCT_TLVLEN(
360 wmi_vdev_tsf_tstamp_action_cmd_fixed_param));
361
362 ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
363 WMI_VDEV_TSF_TSTAMP_ACTION_CMDID);
364 if (ret != EOK) {
365 WMA_LOGE("wmi_unified_cmd_send returned Error %d", status);
366 status = QDF_STATUS_E_FAILURE;
367 goto error;
368 }
369
370 return QDF_STATUS_SUCCESS;
371
372error:
373 if (buf)
374 wmi_buf_free(buf);
375 return status;
376}
377
378/**
379 * wma_reset_tsf_gpio() - send wmi to fw to reset GPIO
380 * @wma_handle: wma handler
381 * @vdev_id: vdev id
382 *
383 * Return: wmi send state
384 */
385QDF_STATUS wma_reset_tsf_gpio(tp_wma_handle wma_handle, uint32_t vdev_id)
386{
387 QDF_STATUS status = QDF_STATUS_SUCCESS;
388 wmi_buf_t buf;
389 wmi_vdev_tsf_tstamp_action_cmd_fixed_param *cmd;
390 int ret;
391 int len = sizeof(*cmd);
392 uint8_t *buf_ptr;
393
394 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
395 if (!buf) {
396 WMA_LOGP("%s: failed to allocate memory for reset tsf gpio",
397 __func__);
398 return QDF_STATUS_E_NOMEM;
399 }
400
401 buf_ptr = (uint8_t *) wmi_buf_data(buf);
402 cmd = (wmi_vdev_tsf_tstamp_action_cmd_fixed_param *) buf_ptr;
403 cmd->vdev_id = vdev_id;
404 cmd->tsf_action = TSF_TSTAMP_CAPTURE_RESET;
405
406 WMA_LOGD("%s :vdev_id %u, TSF_TSTAMP_CAPTURE_RESET", __func__,
407 cmd->vdev_id);
408
409 WMITLV_SET_HDR(&cmd->tlv_header,
410 WMITLV_TAG_STRUC_wmi_vdev_tsf_tstamp_action_cmd_fixed_param,
411 WMITLV_GET_STRUCT_TLVLEN(
412 wmi_vdev_tsf_tstamp_action_cmd_fixed_param));
413
414 ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
415 WMI_VDEV_TSF_TSTAMP_ACTION_CMDID);
416
417 if (ret != EOK) {
418 WMA_LOGE("wmi_unified_cmd_send returned Error %d", status);
419 status = QDF_STATUS_E_FAILURE;
420 goto error;
421 }
422 return QDF_STATUS_SUCCESS;
423
424error:
425 if (buf)
426 wmi_buf_free(buf);
427 return status;
428}
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700429
Manikandan Mohan976e7562016-03-15 16:33:31 -0700430/**
431 * wma_set_tsf_gpio_pin() - send wmi cmd to configure gpio pin
432 * @handle: wma handler
433 * @pin: GPIO pin id
434 *
435 * Return: QDF_STATUS
436 */
437QDF_STATUS wma_set_tsf_gpio_pin(WMA_HANDLE handle, uint32_t pin)
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700438{
Manikandan Mohan976e7562016-03-15 16:33:31 -0700439 tp_wma_handle wma = (tp_wma_handle)handle;
440 struct pdev_params pdev_param = {0};
441 int32_t ret;
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700442
Manikandan Mohan976e7562016-03-15 16:33:31 -0700443 if (!wma || !wma->wmi_handle) {
444 WMA_LOGE("%s: WMA is closed, can not set gpio", __func__);
445 return QDF_STATUS_E_INVAL;
446 }
447
448 WMA_LOGD("%s: set tsf gpio pin: %d", __func__, pin);
449
450 pdev_param.param_id = WMI_PDEV_PARAM_WNTS_CONFIG;
451 pdev_param.param_value = pin;
452 ret = wmi_unified_pdev_param_send(wma->wmi_handle,
453 &pdev_param,
454 WMA_WILDCARD_PDEV_ID);
455 if (ret) {
456 WMA_LOGE("%s: Failed to set tsf gpio pin (%d)", __func__, ret);
457 return QDF_STATUS_E_FAILURE;
458 }
459 return QDF_STATUS_SUCCESS;
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700460}
461#endif
462
Manikandan Mohan80dea792016-04-28 16:36:48 -0700463/**
464 * wma_set_wisa_params(): Set WISA features related params in FW
465 * @wma_handle: WMA handle
466 * @wisa: Pointer to WISA param struct
467 *
468 * Return: CDF status
469 */
470QDF_STATUS wma_set_wisa_params(tp_wma_handle wma_handle,
471 struct sir_wisa_params *wisa)
472{
473 QDF_STATUS status = QDF_STATUS_SUCCESS;
474 wmi_buf_t buf;
475 wmi_vdev_wisa_cmd_fixed_param *cmd;
476 int ret, len = sizeof(*cmd);
477
478 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
479 if (!buf) {
480 WMA_LOGP("%s: failed to allocate memory for WISA params",
481 __func__);
482 return QDF_STATUS_E_NOMEM;
483 }
484
485 cmd = (wmi_vdev_wisa_cmd_fixed_param *) wmi_buf_data(buf);
486 cmd->wisa_mode = wisa->mode;
487 cmd->vdev_id = wisa->vdev_id;
488
489 WMITLV_SET_HDR(&cmd->tlv_header,
490 WMITLV_TAG_STRUC_wmi_vdev_wisa_cmd_fixed_param,
491 WMITLV_GET_STRUCT_TLVLEN(
492 wmi_vdev_wisa_cmd_fixed_param));
493
494 ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
495 WMI_VDEV_WISA_CMDID);
496 if (ret != EOK) {
497 WMA_LOGE("wmi_unified_cmd_send returned Error %d", status);
498 status = QDF_STATUS_E_FAILURE;
499 goto error;
500 }
501 return QDF_STATUS_SUCCESS;
502
503error:
504 wmi_buf_free(buf);
505 return status;
506}
507
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800508#ifdef FEATURE_WLAN_LPHB
509/**
510 * wma_lphb_conf_hbenable() - enable command of LPHB configuration requests
511 * @wma_handle: WMA handle
512 * @lphb_conf_req: configuration info
513 * @by_user: whether this call is from user or cached resent
514 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530515 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800516 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530517QDF_STATUS wma_lphb_conf_hbenable(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800518 tSirLPHBReq *lphb_conf_req, bool by_user)
519{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530520 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800521 int status = 0;
522 tSirLPHBEnableStruct *ts_lphb_enable;
Govind Singhaa64c242016-03-08 11:31:49 +0530523 wmi_hb_set_enable_cmd_fixed_param hb_enable_fp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800524 int i;
525
526 if (lphb_conf_req == NULL) {
527 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530528 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800529 }
530
531 ts_lphb_enable = &(lphb_conf_req->params.lphbEnableReq);
532 WMA_LOGI("%s: WMA --> WMI_HB_SET_ENABLE enable=%d, item=%d, session=%d",
533 __func__,
534 ts_lphb_enable->enable,
535 ts_lphb_enable->item, ts_lphb_enable->session);
536
537 if ((ts_lphb_enable->item != 1) && (ts_lphb_enable->item != 2)) {
538 WMA_LOGE("%s : LPHB configuration wrong item %d",
539 __func__, ts_lphb_enable->item);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530540 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800541 }
542
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800543
544 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530545 hb_enable_fp.vdev_id = ts_lphb_enable->session;
546 hb_enable_fp.enable = ts_lphb_enable->enable;
547 hb_enable_fp.item = ts_lphb_enable->item;
548 hb_enable_fp.session = ts_lphb_enable->session;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800549
Govind Singhaa64c242016-03-08 11:31:49 +0530550 status = wmi_unified_lphb_config_hbenable_cmd(wma_handle->wmi_handle,
551 &hb_enable_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800552 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530553 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800554 goto error;
555 }
556
557 if (by_user) {
558 /* target already configured, now cache command status */
559 if (ts_lphb_enable->enable) {
560 i = ts_lphb_enable->item - 1;
561 wma_handle->wow.lphb_cache[i].cmd
562 = LPHB_SET_EN_PARAMS_INDID;
563 wma_handle->wow.lphb_cache[i].params.lphbEnableReq.
564 enable = ts_lphb_enable->enable;
565 wma_handle->wow.lphb_cache[i].params.lphbEnableReq.
566 item = ts_lphb_enable->item;
567 wma_handle->wow.lphb_cache[i].params.lphbEnableReq.
568 session = ts_lphb_enable->session;
569
570 WMA_LOGI("%s: cached LPHB status in WMA context for item %d",
571 __func__, i);
572 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530573 qdf_mem_zero((void *)&wma_handle->wow.lphb_cache,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800574 sizeof(wma_handle->wow.lphb_cache));
575 WMA_LOGI("%s: cleared all cached LPHB status in WMA context",
576 __func__);
577 }
578 }
579
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530580 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800581error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530582 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800583}
584
585/**
586 * wma_lphb_conf_tcp_params() - set tcp params of LPHB configuration requests
587 * @wma_handle: wma handle
588 * @lphb_conf_req: lphb config request
589 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530590 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800591 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530592QDF_STATUS wma_lphb_conf_tcp_params(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800593 tSirLPHBReq *lphb_conf_req)
594{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530595 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800596 int status = 0;
597 tSirLPHBTcpParamStruct *ts_lphb_tcp_param;
Govind Singhaa64c242016-03-08 11:31:49 +0530598 wmi_hb_set_tcp_params_cmd_fixed_param hb_tcp_params_fp = {0};
599
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800600
601 if (lphb_conf_req == NULL) {
602 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530603 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800604 }
605
606 ts_lphb_tcp_param = &(lphb_conf_req->params.lphbTcpParamReq);
Srinivas Girigowda9dc32cf2015-11-19 14:47:04 -0800607 WMA_LOGI("%s: WMA --> WMI_HB_SET_TCP_PARAMS srv_ip=%08x, "
608 "dev_ip=%08x, src_port=%d, dst_port=%d, timeout=%d, "
609 "session=%d, gateway_mac="MAC_ADDRESS_STR", timePeriodSec=%d, "
610 "tcpSn=%d", __func__, ts_lphb_tcp_param->srv_ip,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800611 ts_lphb_tcp_param->dev_ip, ts_lphb_tcp_param->src_port,
612 ts_lphb_tcp_param->dst_port, ts_lphb_tcp_param->timeout,
Srinivas Girigowda9dc32cf2015-11-19 14:47:04 -0800613 ts_lphb_tcp_param->session,
614 MAC_ADDR_ARRAY(ts_lphb_tcp_param->gateway_mac.bytes),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800615 ts_lphb_tcp_param->timePeriodSec, ts_lphb_tcp_param->tcpSn);
616
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800617 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530618 hb_tcp_params_fp.vdev_id = ts_lphb_tcp_param->session;
619 hb_tcp_params_fp.srv_ip = ts_lphb_tcp_param->srv_ip;
620 hb_tcp_params_fp.dev_ip = ts_lphb_tcp_param->dev_ip;
621 hb_tcp_params_fp.seq = ts_lphb_tcp_param->tcpSn;
622 hb_tcp_params_fp.src_port = ts_lphb_tcp_param->src_port;
623 hb_tcp_params_fp.dst_port = ts_lphb_tcp_param->dst_port;
624 hb_tcp_params_fp.interval = ts_lphb_tcp_param->timePeriodSec;
625 hb_tcp_params_fp.timeout = ts_lphb_tcp_param->timeout;
626 hb_tcp_params_fp.session = ts_lphb_tcp_param->session;
Srinivas Girigowda9dc32cf2015-11-19 14:47:04 -0800627 WMI_CHAR_ARRAY_TO_MAC_ADDR(ts_lphb_tcp_param->gateway_mac.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +0530628 &hb_tcp_params_fp.gateway_mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800629
Govind Singhaa64c242016-03-08 11:31:49 +0530630 status = wmi_unified_lphb_config_tcp_params_cmd(wma_handle->wmi_handle,
631 &hb_tcp_params_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800632 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530633 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800634 goto error;
635 }
636
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530637 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800638error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530639 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800640}
641
642/**
643 * wma_lphb_conf_tcp_pkt_filter() - configure tcp packet filter command of LPHB
644 * @wma_handle: wma handle
645 * @lphb_conf_req: lphb config request
646 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530647 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800648 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530649QDF_STATUS wma_lphb_conf_tcp_pkt_filter(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800650 tSirLPHBReq *lphb_conf_req)
651{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530652 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800653 int status = 0;
654 tSirLPHBTcpFilterStruct *ts_lphb_tcp_filter;
Govind Singhaa64c242016-03-08 11:31:49 +0530655 wmi_hb_set_tcp_pkt_filter_cmd_fixed_param hb_tcp_filter_fp = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800656
657 if (lphb_conf_req == NULL) {
658 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530659 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800660 }
661
662 ts_lphb_tcp_filter = &(lphb_conf_req->params.lphbTcpFilterReq);
663 WMA_LOGI("%s: WMA --> WMI_HB_SET_TCP_PKT_FILTER length=%d, offset=%d, session=%d, "
664 "filter=%2x:%2x:%2x:%2x:%2x:%2x ...", __func__,
665 ts_lphb_tcp_filter->length, ts_lphb_tcp_filter->offset,
666 ts_lphb_tcp_filter->session, ts_lphb_tcp_filter->filter[0],
667 ts_lphb_tcp_filter->filter[1], ts_lphb_tcp_filter->filter[2],
668 ts_lphb_tcp_filter->filter[3], ts_lphb_tcp_filter->filter[4],
669 ts_lphb_tcp_filter->filter[5]);
670
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800671 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530672 hb_tcp_filter_fp.vdev_id = ts_lphb_tcp_filter->session;
673 hb_tcp_filter_fp.length = ts_lphb_tcp_filter->length;
674 hb_tcp_filter_fp.offset = ts_lphb_tcp_filter->offset;
675 hb_tcp_filter_fp.session = ts_lphb_tcp_filter->session;
676 memcpy((void *)&hb_tcp_filter_fp.filter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800677 (void *)&ts_lphb_tcp_filter->filter,
678 WMI_WLAN_HB_MAX_FILTER_SIZE);
679
Govind Singhaa64c242016-03-08 11:31:49 +0530680 status = wmi_unified_lphb_config_tcp_pkt_filter_cmd(wma_handle->wmi_handle,
681 &hb_tcp_filter_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800682 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530683 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800684 goto error;
685 }
686
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530687 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800688error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530689 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800690}
691
692/**
693 * wma_lphb_conf_udp_params() - configure udp param command of LPHB
694 * @wma_handle: wma handle
695 * @lphb_conf_req: lphb config request
696 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530697 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800698 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530699QDF_STATUS wma_lphb_conf_udp_params(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800700 tSirLPHBReq *lphb_conf_req)
701{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530702 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800703 int status = 0;
704 tSirLPHBUdpParamStruct *ts_lphb_udp_param;
Govind Singhaa64c242016-03-08 11:31:49 +0530705 wmi_hb_set_udp_params_cmd_fixed_param hb_udp_params_fp = {0};
706
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800707
708 if (lphb_conf_req == NULL) {
709 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530710 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800711 }
712
713 ts_lphb_udp_param = &(lphb_conf_req->params.lphbUdpParamReq);
714 WMA_LOGI("%s: WMA --> WMI_HB_SET_UDP_PARAMS srv_ip=%d, dev_ip=%d, src_port=%d, "
715 "dst_port=%d, interval=%d, timeout=%d, session=%d, "
Srinivas Girigowda9eddfda2015-11-19 14:38:02 -0800716 "gateway_mac="MAC_ADDRESS_STR, __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800717 ts_lphb_udp_param->srv_ip, ts_lphb_udp_param->dev_ip,
718 ts_lphb_udp_param->src_port, ts_lphb_udp_param->dst_port,
719 ts_lphb_udp_param->interval, ts_lphb_udp_param->timeout,
Srinivas Girigowda9eddfda2015-11-19 14:38:02 -0800720 ts_lphb_udp_param->session,
721 MAC_ADDR_ARRAY(ts_lphb_udp_param->gateway_mac.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800722
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800723
724 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530725 hb_udp_params_fp.vdev_id = ts_lphb_udp_param->session;
726 hb_udp_params_fp.srv_ip = ts_lphb_udp_param->srv_ip;
727 hb_udp_params_fp.dev_ip = ts_lphb_udp_param->dev_ip;
728 hb_udp_params_fp.src_port = ts_lphb_udp_param->src_port;
729 hb_udp_params_fp.dst_port = ts_lphb_udp_param->dst_port;
730 hb_udp_params_fp.interval = ts_lphb_udp_param->interval;
731 hb_udp_params_fp.timeout = ts_lphb_udp_param->timeout;
732 hb_udp_params_fp.session = ts_lphb_udp_param->session;
Srinivas Girigowda9eddfda2015-11-19 14:38:02 -0800733 WMI_CHAR_ARRAY_TO_MAC_ADDR(ts_lphb_udp_param->gateway_mac.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +0530734 &hb_udp_params_fp.gateway_mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800735
Govind Singhaa64c242016-03-08 11:31:49 +0530736 status = wmi_unified_lphb_config_udp_params_cmd(wma_handle->wmi_handle,
737 &hb_udp_params_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800738 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530739 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800740 goto error;
741 }
742
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530743 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800744error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530745 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800746}
747
748/**
749 * wma_lphb_conf_udp_pkt_filter() - configure udp pkt filter command of LPHB
750 * @wma_handle: wma handle
751 * @lphb_conf_req: lphb config request
752 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530753 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800754 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530755QDF_STATUS wma_lphb_conf_udp_pkt_filter(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800756 tSirLPHBReq *lphb_conf_req)
757{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530758 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800759 int status = 0;
760 tSirLPHBUdpFilterStruct *ts_lphb_udp_filter;
Govind Singhaa64c242016-03-08 11:31:49 +0530761 wmi_hb_set_udp_pkt_filter_cmd_fixed_param hb_udp_filter_fp = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800762
763 if (lphb_conf_req == NULL) {
764 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530765 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800766 }
767
768 ts_lphb_udp_filter = &(lphb_conf_req->params.lphbUdpFilterReq);
769 WMA_LOGI("%s: WMA --> WMI_HB_SET_UDP_PKT_FILTER length=%d, offset=%d, session=%d, "
770 "filter=%2x:%2x:%2x:%2x:%2x:%2x ...", __func__,
771 ts_lphb_udp_filter->length, ts_lphb_udp_filter->offset,
772 ts_lphb_udp_filter->session, ts_lphb_udp_filter->filter[0],
773 ts_lphb_udp_filter->filter[1], ts_lphb_udp_filter->filter[2],
774 ts_lphb_udp_filter->filter[3], ts_lphb_udp_filter->filter[4],
775 ts_lphb_udp_filter->filter[5]);
776
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800777
778 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530779 hb_udp_filter_fp.vdev_id = ts_lphb_udp_filter->session;
780 hb_udp_filter_fp.length = ts_lphb_udp_filter->length;
781 hb_udp_filter_fp.offset = ts_lphb_udp_filter->offset;
782 hb_udp_filter_fp.session = ts_lphb_udp_filter->session;
783 memcpy((void *)&hb_udp_filter_fp.filter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800784 (void *)&ts_lphb_udp_filter->filter,
785 WMI_WLAN_HB_MAX_FILTER_SIZE);
786
Govind Singhaa64c242016-03-08 11:31:49 +0530787 status = wmi_unified_lphb_config_udp_pkt_filter_cmd(wma_handle->wmi_handle,
788 &hb_udp_filter_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800789 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530790 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800791 goto error;
792 }
793
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530794 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800795error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530796 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800797}
798
799/**
800 * wma_process_lphb_conf_req() - handle LPHB configuration requests
801 * @wma_handle: wma handle
802 * @lphb_conf_req: lphb config request
803 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530804 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800805 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530806QDF_STATUS wma_process_lphb_conf_req(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800807 tSirLPHBReq *lphb_conf_req)
808{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530809 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800810
811 if (lphb_conf_req == NULL) {
812 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530813 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800814 }
815
816 WMA_LOGI("%s : LPHB configuration cmd id is %d", __func__,
817 lphb_conf_req->cmd);
818 switch (lphb_conf_req->cmd) {
819 case LPHB_SET_EN_PARAMS_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530820 qdf_status = wma_lphb_conf_hbenable(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800821 lphb_conf_req, true);
822 break;
823
824 case LPHB_SET_TCP_PARAMS_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530825 qdf_status = wma_lphb_conf_tcp_params(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800826 lphb_conf_req);
827 break;
828
829 case LPHB_SET_TCP_PKT_FILTER_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530830 qdf_status = wma_lphb_conf_tcp_pkt_filter(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800831 lphb_conf_req);
832 break;
833
834 case LPHB_SET_UDP_PARAMS_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530835 qdf_status = wma_lphb_conf_udp_params(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800836 lphb_conf_req);
837 break;
838
839 case LPHB_SET_UDP_PKT_FILTER_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530840 qdf_status = wma_lphb_conf_udp_pkt_filter(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800841 lphb_conf_req);
842 break;
843
844 case LPHB_SET_NETWORK_INFO_INDID:
845 default:
846 break;
847 }
848
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530849 qdf_mem_free(lphb_conf_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530850 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800851}
852#endif /* FEATURE_WLAN_LPHB */
853
854/**
855 * wma_process_dhcp_ind() - process dhcp indication from SME
856 * @wma_handle: wma handle
857 * @ta_dhcp_ind: DHCP indication
858 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530859 * Return: QDF Status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800860 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530861QDF_STATUS wma_process_dhcp_ind(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800862 tAniDHCPInd *ta_dhcp_ind)
863{
864 uint8_t vdev_id;
865 int status = 0;
Govind Singhaa64c242016-03-08 11:31:49 +0530866 wmi_peer_set_param_cmd_fixed_param peer_set_param_fp = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800867
868 if (!ta_dhcp_ind) {
869 WMA_LOGE("%s : DHCP indication is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530870 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800871 }
872
Srinivas Girigowda296105a2015-09-24 16:31:16 -0700873 if (!wma_find_vdev_by_addr(wma_handle,
874 ta_dhcp_ind->adapterMacAddr.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800875 &vdev_id)) {
876 WMA_LOGE("%s: Failed to find vdev id for DHCP indication",
877 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530878 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800879 }
880
881 WMA_LOGI("%s: WMA --> WMI_PEER_SET_PARAM triggered by DHCP, "
882 "msgType=%s,"
883 "device_mode=%d, macAddr=" MAC_ADDRESS_STR,
884 __func__,
885 ta_dhcp_ind->msgType == WMA_DHCP_START_IND ?
886 "WMA_DHCP_START_IND" : "WMA_DHCP_STOP_IND",
887 ta_dhcp_ind->device_mode,
Srinivas Girigowda296105a2015-09-24 16:31:16 -0700888 MAC_ADDR_ARRAY(ta_dhcp_ind->peerMacAddr.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800889
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800890 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530891 peer_set_param_fp.vdev_id = vdev_id;
892 peer_set_param_fp.param_id = WMI_PEER_CRIT_PROTO_HINT_ENABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800893 if (WMA_DHCP_START_IND == ta_dhcp_ind->msgType)
Govind Singhaa64c242016-03-08 11:31:49 +0530894 peer_set_param_fp.param_value = 1;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800895 else
Govind Singhaa64c242016-03-08 11:31:49 +0530896 peer_set_param_fp.param_value = 0;
Srinivas Girigowda296105a2015-09-24 16:31:16 -0700897 WMI_CHAR_ARRAY_TO_MAC_ADDR(ta_dhcp_ind->peerMacAddr.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +0530898 &peer_set_param_fp.peer_macaddr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800899
Govind Singhaa64c242016-03-08 11:31:49 +0530900 status = wmi_unified_process_dhcp_ind(wma_handle->wmi_handle,
901 &peer_set_param_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800902 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530903 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800904 }
905
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530906 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800907}
908
909/**
Amar Singhal046eb8a2016-05-05 12:50:15 -0700910 * wma_chan_phy__mode() - get WLAN_PHY_MODE for channel
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800911 * @chan: channel number
Amar Singhal046eb8a2016-05-05 12:50:15 -0700912 * @chan_width: maximum channel width possible
913 * @dot11_mode: maximum phy_mode possible
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800914 *
Amar Singhal046eb8a2016-05-05 12:50:15 -0700915 * Return: return WLAN_PHY_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800916 */
Amar Singhal046eb8a2016-05-05 12:50:15 -0700917WLAN_PHY_MODE wma_chan_phy_mode(u8 chan, enum phy_ch_width chan_width,
918 u8 dot11_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800919{
920 WLAN_PHY_MODE phymode = MODE_UNKNOWN;
Amar Singhal046eb8a2016-05-05 12:50:15 -0700921 uint16_t bw_val = cds_bw_value(chan_width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800922
Amar Singhal046eb8a2016-05-05 12:50:15 -0700923 if (CDS_IS_CHANNEL_24GHZ(chan)) {
924 if (((CH_WIDTH_5MHZ == chan_width) ||
925 (CH_WIDTH_10MHZ == chan_width)) &&
926 ((WNI_CFG_DOT11_MODE_11B == dot11_mode) ||
927 (WNI_CFG_DOT11_MODE_11G == dot11_mode) ||
928 (WNI_CFG_DOT11_MODE_11N == dot11_mode) ||
929 (WNI_CFG_DOT11_MODE_ALL == dot11_mode) ||
930 (WNI_CFG_DOT11_MODE_11AC == dot11_mode)))
931 phymode = MODE_11G;
932 else {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800933 switch (dot11_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800934 case WNI_CFG_DOT11_MODE_11B:
Amar Singhal046eb8a2016-05-05 12:50:15 -0700935 if ((20 == bw_val) ||
936 (40 == bw_val))
937 phymode = MODE_11B;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800938 break;
939 case WNI_CFG_DOT11_MODE_11G:
Amar Singhal046eb8a2016-05-05 12:50:15 -0700940 if ((20 == bw_val) ||
941 (40 == bw_val))
942 phymode = MODE_11G;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800943 break;
944 case WNI_CFG_DOT11_MODE_11G_ONLY:
Amar Singhal046eb8a2016-05-05 12:50:15 -0700945 if ((20 == bw_val) ||
946 (40 == bw_val))
947 phymode = MODE_11GONLY;
948 break;
949 case WNI_CFG_DOT11_MODE_11N:
950 case WNI_CFG_DOT11_MODE_11N_ONLY:
951 if (20 == bw_val)
952 phymode = MODE_11NG_HT20;
953 else if (40 == bw_val)
954 phymode = MODE_11NG_HT40;
955 break;
956 case WNI_CFG_DOT11_MODE_ALL:
957 case WNI_CFG_DOT11_MODE_11AC:
958 case WNI_CFG_DOT11_MODE_11AC_ONLY:
959 if (20 == bw_val)
960 phymode = MODE_11AC_VHT20_2G;
961 else if (40 == bw_val)
962 phymode = MODE_11AC_VHT40_2G;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800963 break;
964 default:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800965 break;
966 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800967 }
Amar Singhal046eb8a2016-05-05 12:50:15 -0700968 } else if (CDS_IS_CHANNEL_DSRC(chan))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800969 phymode = MODE_11A;
Amar Singhal046eb8a2016-05-05 12:50:15 -0700970 else {
971 if (((CH_WIDTH_5MHZ == chan_width) ||
972 (CH_WIDTH_10MHZ == chan_width)) &&
973 ((WNI_CFG_DOT11_MODE_11A == dot11_mode) ||
974 (WNI_CFG_DOT11_MODE_11N == dot11_mode) ||
975 (WNI_CFG_DOT11_MODE_ALL == dot11_mode) ||
976 (WNI_CFG_DOT11_MODE_11AC == dot11_mode)))
977 phymode = MODE_11A;
978 else {
979 switch (dot11_mode) {
980 case WNI_CFG_DOT11_MODE_11A:
981 if (0 < bw_val)
982 phymode = MODE_11A;
983 break;
984 case WNI_CFG_DOT11_MODE_11N:
985 case WNI_CFG_DOT11_MODE_11N_ONLY:
986 if (20 == bw_val)
987 phymode = MODE_11NA_HT20;
988 else if (40 <= bw_val)
989 phymode = MODE_11NA_HT40;
990 break;
991 case WNI_CFG_DOT11_MODE_ALL:
992 case WNI_CFG_DOT11_MODE_11AC:
993 case WNI_CFG_DOT11_MODE_11AC_ONLY:
994 if (20 == bw_val)
995 phymode = MODE_11AC_VHT20;
996 else if (40 == bw_val)
997 phymode = MODE_11AC_VHT40;
998 else if (80 == bw_val)
999 phymode = MODE_11AC_VHT80;
1000 else if (CH_WIDTH_160MHZ == chan_width)
1001 phymode = MODE_11AC_VHT160;
1002 else if (CH_WIDTH_80P80MHZ == chan_width)
1003 phymode = MODE_11AC_VHT80_80;
1004 break;
1005 default:
1006 break;
1007 }
1008 }
1009 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001010
Amar Singhal046eb8a2016-05-05 12:50:15 -07001011 WMA_LOGD("%s: phymode %d channel %d ch_width %d"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001012 "dot11_mode %d", __func__, phymode, chan,
Amar Singhal046eb8a2016-05-05 12:50:15 -07001013 chan_width, dot11_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001014
Amar Singhal046eb8a2016-05-05 12:50:15 -07001015 QDF_ASSERT(MODE_UNKNOWN != phymode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001016 return phymode;
1017}
1018
1019/**
1020 * wma_get_link_speed() -send command to get linkspeed
1021 * @handle: wma handle
1022 * @pLinkSpeed: link speed info
1023 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05301024 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001025 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301026QDF_STATUS wma_get_link_speed(WMA_HANDLE handle, tSirLinkSpeedInfo *pLinkSpeed)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001027{
1028 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhaa64c242016-03-08 11:31:49 +05301029 wmi_mac_addr peer_macaddr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001030
1031 if (!wma_handle || !wma_handle->wmi_handle) {
1032 WMA_LOGE("%s: WMA is closed, can not issue get link speed cmd",
1033 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301034 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001035 }
1036 if (!WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap,
1037 WMI_SERVICE_ESTIMATE_LINKSPEED)) {
1038 WMA_LOGE("%s: Linkspeed feature bit not enabled"
1039 " Sending value 0 as link speed.", __func__);
1040 wma_send_link_speed(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301041 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001042 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001043
1044 /* Copy the peer macaddress to the wma buffer */
Srinivas Girigowdadccab9a2015-11-19 14:31:14 -08001045 WMI_CHAR_ARRAY_TO_MAC_ADDR(pLinkSpeed->peer_macaddr.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +05301046 &peer_macaddr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001047
1048 WMA_LOGD("%s: pLinkSpeed->peerMacAddr: %pM, "
1049 "peer_macaddr.mac_addr31to0: 0x%x, peer_macaddr.mac_addr47to32: 0x%x",
Srinivas Girigowdadccab9a2015-11-19 14:31:14 -08001050 __func__, pLinkSpeed->peer_macaddr.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +05301051 peer_macaddr.mac_addr31to0,
1052 peer_macaddr.mac_addr47to32);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001053
Govind Singhaa64c242016-03-08 11:31:49 +05301054 if (wmi_unified_get_link_speed_cmd(wma_handle->wmi_handle,
1055 peer_macaddr)) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301056 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001057 }
Govind Singhaa64c242016-03-08 11:31:49 +05301058
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301059 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001060}
1061
Gupta, Kapil4cb1d7d2016-04-16 18:16:25 -07001062/**
1063* wma_add_beacon_filter() - Issue WMI command to set beacon filter
1064* @wma: wma handler
1065* @filter_params: beacon_filter_param to set
1066*
1067* Return: Return QDF_STATUS
1068*/
1069QDF_STATUS wma_add_beacon_filter(WMA_HANDLE handle,
1070 struct beacon_filter_param *filter_params)
1071{
1072 int i;
1073 wmi_buf_t wmi_buf;
1074 u_int8_t *buf;
1075 A_UINT32 *ie_map;
1076 int ret;
1077 tp_wma_handle wma = (tp_wma_handle) handle;
1078 wmi_add_bcn_filter_cmd_fixed_param *cmd;
1079 int len = sizeof(wmi_add_bcn_filter_cmd_fixed_param);
1080
1081 len += WMI_TLV_HDR_SIZE;
1082 len += BCN_FLT_MAX_ELEMS_IE_LIST*sizeof(A_UINT32);
1083
1084 if (!wma || !wma->wmi_handle) {
1085 WMA_LOGE("%s: WMA is closed, can not issue set beacon filter",
1086 __func__);
1087 return QDF_STATUS_E_INVAL;
1088 }
1089
1090 wmi_buf = wmi_buf_alloc(wma->wmi_handle, len);
1091 if (!wmi_buf) {
1092 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
1093 return QDF_STATUS_E_NOMEM;
1094 }
1095
1096 buf = (u_int8_t *) wmi_buf_data(wmi_buf);
1097
1098 cmd = (wmi_add_bcn_filter_cmd_fixed_param *)wmi_buf_data(wmi_buf);
1099 cmd->vdev_id = filter_params->vdev_id;
1100
1101 WMITLV_SET_HDR(&cmd->tlv_header,
1102 WMITLV_TAG_STRUC_wmi_add_bcn_filter_cmd_fixed_param,
1103 WMITLV_GET_STRUCT_TLVLEN(
1104 wmi_add_bcn_filter_cmd_fixed_param));
1105
1106 buf += sizeof(wmi_add_bcn_filter_cmd_fixed_param);
1107
1108 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_UINT32,
1109 (BCN_FLT_MAX_ELEMS_IE_LIST * sizeof(u_int32_t)));
1110
1111 ie_map = (A_UINT32 *)(buf + WMI_TLV_HDR_SIZE);
1112 for (i = 0; i < BCN_FLT_MAX_ELEMS_IE_LIST; i++) {
1113 ie_map[i] = filter_params->ie_map[i];
1114 WMA_LOGD("beacon filter ie map = %u", ie_map[i]);
1115 }
1116
1117 ret = wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len,
1118 WMI_ADD_BCN_FILTER_CMDID);
1119 if (ret) {
1120 WMA_LOGE("Failed to send wmi add beacon filter = %d",
1121 ret);
1122 wmi_buf_free(wmi_buf);
1123 return QDF_STATUS_E_FAILURE;
1124 }
1125 WMA_LOGD("added beacon filter = %d", ret);
1126
1127 return QDF_STATUS_SUCCESS;
1128}
1129
1130/**
1131* wma_remove_beacon_filter() - Issue WMI command to remove beacon filter
1132* @wma: wma handler
1133* @filter_params: beacon_filter_params
1134*
1135* Return: Return QDF_STATUS
1136*/
1137QDF_STATUS wma_remove_beacon_filter(WMA_HANDLE handle,
1138 struct beacon_filter_param *filter_params)
1139{
1140 wmi_buf_t buf;
1141 tp_wma_handle wma = (tp_wma_handle) handle;
1142 wmi_rmv_bcn_filter_cmd_fixed_param *cmd;
1143 int len = sizeof(wmi_rmv_bcn_filter_cmd_fixed_param);
1144 int ret;
1145
1146 if (!wma || !wma->wmi_handle) {
1147 WMA_LOGE("%s: WMA is closed, cannot issue remove beacon filter",
1148 __func__);
1149 return QDF_STATUS_E_INVAL;
1150 }
1151
1152 buf = wmi_buf_alloc(wma->wmi_handle, len);
1153 if (!buf) {
1154 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
1155 return QDF_STATUS_E_NOMEM;
1156 }
1157 cmd = (wmi_rmv_bcn_filter_cmd_fixed_param *)wmi_buf_data(buf);
1158 cmd->vdev_id = filter_params->vdev_id;
1159
1160 WMITLV_SET_HDR(&cmd->tlv_header,
1161 WMITLV_TAG_STRUC_wmi_rmv_bcn_filter_cmd_fixed_param,
1162 WMITLV_GET_STRUCT_TLVLEN(
1163 wmi_rmv_bcn_filter_cmd_fixed_param));
1164
1165 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
1166 WMI_RMV_BCN_FILTER_CMDID);
1167 if (ret) {
1168 WMA_LOGE("Failed to send wmi remove beacon filter = %d",
1169 ret);
1170 wmi_buf_free(buf);
1171 return QDF_STATUS_E_FAILURE;
1172 }
1173 WMA_LOGD("removed beacon filter = %d", ret);
1174
1175 return QDF_STATUS_SUCCESS;
1176}
1177
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05301178/**
1179 * wma_send_adapt_dwelltime_params() - send adaptive dwelltime configuration
1180 * params to firmware
1181 * @wma_handle: wma handler
1182 * @dwelltime_params: pointer to dwelltime_params
1183 *
1184 * Return: QDF_STATUS_SUCCESS on success and QDF failure reason code for failure
1185 */
1186QDF_STATUS wma_send_adapt_dwelltime_params(WMA_HANDLE handle,
1187 struct adaptive_dwelltime_params *dwelltime_params)
1188{
1189 tp_wma_handle wma_handle = (tp_wma_handle) handle;
1190 struct wmi_adaptive_dwelltime_params wmi_param = {0};
1191 int32_t err;
1192
1193 wmi_param.is_enabled = dwelltime_params->is_enabled;
1194 wmi_param.dwelltime_mode = dwelltime_params->dwelltime_mode;
1195 wmi_param.lpf_weight = dwelltime_params->lpf_weight;
1196 wmi_param.passive_mon_intval = dwelltime_params->passive_mon_intval;
1197 wmi_param.wifi_act_threshold = dwelltime_params->wifi_act_threshold;
1198 err = wmi_unified_send_adapt_dwelltime_params_cmd(wma_handle->
1199 wmi_handle, &wmi_param);
1200 if (err)
1201 return QDF_STATUS_E_FAILURE;
1202
1203 return QDF_STATUS_SUCCESS;
1204}
Gupta, Kapil4cb1d7d2016-04-16 18:16:25 -07001205
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001206#ifdef FEATURE_GREEN_AP
1207
1208/**
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001209 * wma_egap_info_status_event() - egap info status event
1210 * @handle: pointer to wma handler
1211 * @event: pointer to event
1212 * @len: len of the event
1213 *
1214 * Return: 0 for success, otherwise appropriate error code
1215 */
1216static int wma_egap_info_status_event(void *handle, u_int8_t *event,
1217 uint32_t len)
1218{
1219 WMI_TX_PAUSE_EVENTID_param_tlvs *param_buf;
1220 wmi_ap_ps_egap_info_event_fixed_param *egap_info_event;
1221 wmi_ap_ps_egap_info_chainmask_list *chainmask_event;
1222 u_int8_t *buf_ptr;
1223
1224 param_buf = (WMI_TX_PAUSE_EVENTID_param_tlvs *)event;
1225 if (!param_buf) {
1226 WMA_LOGE("Invalid EGAP Info status event buffer");
1227 return -EINVAL;
1228 }
1229
1230 egap_info_event = (wmi_ap_ps_egap_info_event_fixed_param *)
1231 param_buf->fixed_param;
1232 buf_ptr = (uint8_t *)egap_info_event;
1233 buf_ptr += sizeof(wmi_ap_ps_egap_info_event_fixed_param);
1234 chainmask_event = (wmi_ap_ps_egap_info_chainmask_list *)buf_ptr;
1235
1236 WMA_LOGI("mac_id: %d, status: %d, tx_mask: %x, rx_mask: %d",
1237 chainmask_event->mac_id,
1238 egap_info_event->status,
1239 chainmask_event->tx_chainmask,
1240 chainmask_event->rx_chainmask);
1241 return 0;
1242}
1243
1244/**
1245 * wma_send_egap_conf_params() - send wmi cmd of egap configuration params
1246 * @wma_handle: wma handler
1247 * @egap_params: pointer to egap_params
1248 *
1249 * Return: 0 for success, otherwise appropriate error code
1250 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301251QDF_STATUS wma_send_egap_conf_params(WMA_HANDLE handle,
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001252 struct egap_conf_params *egap_params)
1253{
1254 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhaa64c242016-03-08 11:31:49 +05301255 wmi_ap_ps_egap_param_cmd_fixed_param cmd = {0};
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001256 int32_t err;
1257
Govind Singhaa64c242016-03-08 11:31:49 +05301258 cmd.enable = egap_params->enable;
1259 cmd.inactivity_time = egap_params->inactivity_time;
1260 cmd.wait_time = egap_params->wait_time;
1261 cmd.flags = egap_params->flags;
1262 err = wmi_unified_egap_conf_params_cmd(wma_handle->wmi_handle, &cmd);
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001263 if (err) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301264 return QDF_STATUS_E_FAILURE;
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001265 }
Govind Singhaa64c242016-03-08 11:31:49 +05301266
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301267 return QDF_STATUS_SUCCESS;
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001268}
1269
1270/**
1271 * wma_setup_egap_support() - setup the EGAP support flag
1272 * @tgt_cfg: pointer to hdd target configuration
1273 * @egap_support: EGAP support flag
1274 *
1275 * Return: None
1276 */
1277void wma_setup_egap_support(struct wma_tgt_cfg *tgt_cfg, WMA_HANDLE handle)
1278{
1279 tp_wma_handle wma_handle = (tp_wma_handle) handle;
1280
1281 if (tgt_cfg && wma_handle)
1282 tgt_cfg->egap_support = wma_handle->egap_support;
1283}
1284
1285/**
1286 * wma_register_egap_event_handle() - register the EGAP event handle
1287 * @wma_handle: wma handler
1288 *
1289 * Return: None
1290 */
1291void wma_register_egap_event_handle(WMA_HANDLE handle)
1292{
1293 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhd76a5b02016-03-08 15:12:14 +05301294 QDF_STATUS status;
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001295
1296 if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap,
1297 WMI_SERVICE_EGAP)) {
1298 status = wmi_unified_register_event_handler(
1299 wma_handle->wmi_handle,
1300 WMI_AP_PS_EGAP_INFO_EVENTID,
Govind Singhd76a5b02016-03-08 15:12:14 +05301301 wma_egap_info_status_event,
1302 WMA_RX_SERIALIZER_CTX);
1303 if (QDF_IS_STATUS_ERROR(status)) {
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001304 WMA_LOGE("Failed to register Enhance Green AP event");
1305 wma_handle->egap_support = false;
1306 } else {
1307 WMA_LOGI("Set the Enhance Green AP event handler");
1308 wma_handle->egap_support = true;
1309 }
1310 } else
1311 wma_handle->egap_support = false;
1312}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001313#endif /* FEATURE_GREEN_AP */
1314
Govind Singha471e5e2015-10-12 17:11:14 +05301315/**
Govind Singhaa64c242016-03-08 11:31:49 +05301316 * wma_unified_fw_profiling_cmd() - send FW profiling cmd to WLAN FW
Govind Singha471e5e2015-10-12 17:11:14 +05301317 * @wma: wma handle
1318 * @cmd: Profiling command index
1319 * @value1: parameter1 value
1320 * @value2: parameter2 value
1321 *
1322 * Return: 0 for success else error code
1323 */
Govind Singhaa64c242016-03-08 11:31:49 +05301324QDF_STATUS wma_unified_fw_profiling_cmd(wmi_unified_t wmi_handle,
Govind Singha471e5e2015-10-12 17:11:14 +05301325 uint32_t cmd, uint32_t value1, uint32_t value2)
1326{
Govind Singha471e5e2015-10-12 17:11:14 +05301327 int ret;
Govind Singha471e5e2015-10-12 17:11:14 +05301328
Govind Singhaa64c242016-03-08 11:31:49 +05301329 ret = wmi_unified_fw_profiling_data_cmd(wmi_handle, cmd,
1330 value1, value2);
1331 if (ret) {
1332 WMA_LOGE("enable cmd Failed for id %d value %d",
1333 value1, value2);
1334 return ret;
Govind Singha471e5e2015-10-12 17:11:14 +05301335 }
1336
Govind Singhaa64c242016-03-08 11:31:49 +05301337 return QDF_STATUS_SUCCESS;
Govind Singha471e5e2015-10-12 17:11:14 +05301338}
1339
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001340#ifdef FEATURE_WLAN_LPHB
1341/**
1342 * wma_lphb_handler() - send LPHB indication to SME
1343 * @wma: wma handle
1344 * @event: event handler
1345 *
1346 * Return: 0 for success or error code
1347 */
1348static int wma_lphb_handler(tp_wma_handle wma, uint8_t *event)
1349{
1350 wmi_hb_ind_event_fixed_param *hb_fp;
1351 tSirLPHBInd *slphb_indication;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301352 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001353 cds_msg_t sme_msg = { 0 };
1354
1355 hb_fp = (wmi_hb_ind_event_fixed_param *) event;
1356 if (!hb_fp) {
1357 WMA_LOGE("Invalid wmi_hb_ind_event_fixed_param buffer");
1358 return -EINVAL;
1359 }
1360
1361 WMA_LOGD("lphb indication received with vdev_id=%d, session=%d, reason=%d",
1362 hb_fp->vdev_id, hb_fp->session, hb_fp->reason);
1363
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301364 slphb_indication = (tSirLPHBInd *) qdf_mem_malloc(sizeof(tSirLPHBInd));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001365
1366 if (!slphb_indication) {
1367 WMA_LOGE("Invalid LPHB indication buffer");
1368 return -ENOMEM;
1369 }
1370
1371 slphb_indication->sessionIdx = hb_fp->session;
1372 slphb_indication->protocolType = hb_fp->reason;
1373 slphb_indication->eventReason = hb_fp->reason;
1374
1375 sme_msg.type = eWNI_SME_LPHB_IND;
1376 sme_msg.bodyptr = slphb_indication;
1377 sme_msg.bodyval = 0;
1378
Anurag Chouhan6d760662016-02-20 16:05:43 +05301379 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301380 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001381 WMA_LOGE("Fail to post eWNI_SME_LPHB_IND msg to SME");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301382 qdf_mem_free(slphb_indication);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001383 return -EINVAL;
1384 }
1385
1386 return 0;
1387}
1388#endif /* FEATURE_WLAN_LPHB */
1389
1390#ifdef FEATURE_WLAN_RA_FILTERING
1391/**
1392 * wma_wow_sta_ra_filter() - set RA filter pattern in fw
1393 * @wma: wma handle
1394 * @vdev_id: vdev id
1395 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05301396 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001397 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301398static QDF_STATUS wma_wow_sta_ra_filter(tp_wma_handle wma, uint8_t vdev_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001399{
1400
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001401 struct wma_txrx_node *iface;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001402 int ret;
Govind Singhaa64c242016-03-08 11:31:49 +05301403 uint8_t default_pattern;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001404
1405 iface = &wma->interfaces[vdev_id];
1406
Govind Singhaa64c242016-03-08 11:31:49 +05301407 default_pattern = iface->num_wow_default_patterns++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001408
1409 WMA_LOGD("%s: send RA rate limit [%d] to fw vdev = %d", __func__,
1410 wma->RArateLimitInterval, vdev_id);
1411
Govind Singhaa64c242016-03-08 11:31:49 +05301412 ret = wmi_unified_wow_sta_ra_filter_cmd(wma->wmi_handle, vdev_id,
1413 default_pattern, wma->RArateLimitInterval);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001414 if (ret) {
1415 WMA_LOGE("%s: Failed to send RA rate limit to fw", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001416 iface->num_wow_default_patterns--;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301417 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001418 }
1419
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301420 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001421
1422}
1423#endif /* FEATURE_WLAN_RA_FILTERING */
1424
1425/**
1426 * wmi_unified_nat_keepalive_enable() - enable NAT keepalive filter
1427 * @wma: wma handle
1428 * @vdev_id: vdev id
1429 *
1430 * Return: 0 for success or error code
1431 */
1432int wmi_unified_nat_keepalive_enable(tp_wma_handle wma, uint8_t vdev_id)
1433{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001434
Govind Singhaa64c242016-03-08 11:31:49 +05301435 if (wmi_unified_nat_keepalive_en_cmd(wma->wmi_handle, vdev_id))
1436 return QDF_STATUS_E_FAILURE;
1437
1438 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001439}
1440
1441/**
Govind Singhd76a5b02016-03-08 15:12:14 +05301442 * wma_unified_csa_offload_enable() - sen CSA offload enable command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001443 * @wma: wma handle
1444 * @vdev_id: vdev id
1445 *
1446 * Return: 0 for success or error code
1447 */
Govind Singhd76a5b02016-03-08 15:12:14 +05301448int wma_unified_csa_offload_enable(tp_wma_handle wma, uint8_t vdev_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001449{
Govind Singhaa64c242016-03-08 11:31:49 +05301450 if (wmi_unified_csa_offload_enable(wma->wmi_handle,
1451 vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001452 WMA_LOGP("%s: Failed to send CSA offload enable command",
1453 __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001454 return -EIO;
1455 }
Govind Singhaa64c242016-03-08 11:31:49 +05301456
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001457 return 0;
1458}
1459
1460#ifdef WLAN_FEATURE_NAN
1461/**
1462 * wma_nan_rsp_event_handler() - Function is used to handle nan response
1463 * @handle: wma handle
1464 * @event_buf: event buffer
1465 * @len: length of buffer
1466 *
1467 * Return: 0 for success or error code
1468 */
1469int wma_nan_rsp_event_handler(void *handle, uint8_t *event_buf,
1470 uint32_t len)
1471{
1472 WMI_NAN_EVENTID_param_tlvs *param_buf;
1473 tSirNanEvent *nan_rsp_event;
1474 wmi_nan_event_hdr *nan_rsp_event_hdr;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301475 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001476 cds_msg_t cds_msg;
1477 uint8_t *buf_ptr;
1478 uint32_t alloc_len;
1479
1480 /*
1481 * This is how received event_buf looks like
1482 *
1483 * <-------------------- event_buf ----------------------------------->
1484 *
1485 * <--wmi_nan_event_hdr--><---WMI_TLV_HDR_SIZE---><----- data -------->
1486 *
1487 * +-----------+---------+-----------------------+--------------------+
1488 * | tlv_header| data_len| WMITLV_TAG_ARRAY_BYTE | nan_rsp_event_data |
1489 * +-----------+---------+-----------------------+--------------------+
1490 */
1491
1492 WMA_LOGD("%s: Posting NaN response event to SME", __func__);
1493 param_buf = (WMI_NAN_EVENTID_param_tlvs *) event_buf;
1494 if (!param_buf) {
1495 WMA_LOGE("%s: Invalid nan response event buf", __func__);
1496 return -EINVAL;
1497 }
1498 nan_rsp_event_hdr = param_buf->fixed_param;
1499 buf_ptr = (uint8_t *) nan_rsp_event_hdr;
1500 alloc_len = sizeof(tSirNanEvent);
1501 alloc_len += nan_rsp_event_hdr->data_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301502 nan_rsp_event = (tSirNanEvent *) qdf_mem_malloc(alloc_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001503 if (NULL == nan_rsp_event) {
1504 WMA_LOGE("%s: Memory allocation failure", __func__);
1505 return -ENOMEM;
1506 }
1507
1508 nan_rsp_event->event_data_len = nan_rsp_event_hdr->data_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301509 qdf_mem_copy(nan_rsp_event->event_data, buf_ptr +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001510 sizeof(wmi_nan_event_hdr) + WMI_TLV_HDR_SIZE,
1511 nan_rsp_event->event_data_len);
1512 cds_msg.type = eWNI_SME_NAN_EVENT;
1513 cds_msg.bodyptr = (void *)nan_rsp_event;
1514 cds_msg.bodyval = 0;
1515
1516 status = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301517 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001518 WMA_LOGE("%s: Failed to post NaN response event to SME",
1519 __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301520 qdf_mem_free(nan_rsp_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001521 return -EFAULT;
1522 }
1523 WMA_LOGD("%s: NaN response event Posted to SME", __func__);
1524 return 0;
1525}
Naveen Rawatc9f09522016-05-12 14:02:42 -07001526#else
1527int wma_nan_rsp_event_handler(void *handle, uint8_t *event_buf,
1528 uint32_t len)
1529{
1530 return 0;
1531}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001532#endif /* WLAN_FEATURE_NAN */
1533
1534/**
1535 * wma_csa_offload_handler() - CSA event handler
1536 * @handle: wma handle
1537 * @event: event buffer
1538 * @len: buffer length
1539 *
1540 * This event is sent by firmware when it receives CSA IE.
1541 *
1542 * Return: 0 for success or error code
1543 */
1544int wma_csa_offload_handler(void *handle, uint8_t *event, uint32_t len)
1545{
1546 tp_wma_handle wma = (tp_wma_handle) handle;
1547 WMI_CSA_HANDLING_EVENTID_param_tlvs *param_buf;
1548 wmi_csa_event_fixed_param *csa_event;
1549 uint8_t bssid[IEEE80211_ADDR_LEN];
1550 uint8_t vdev_id = 0;
1551 uint8_t cur_chan = 0;
1552 struct ieee80211_channelswitch_ie *csa_ie;
Chandrasekaran, Manishekar5c19dc52016-02-04 14:58:26 +05301553 struct csa_offload_params *csa_offload_event;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001554 struct ieee80211_extendedchannelswitch_ie *xcsa_ie;
1555 struct ieee80211_ie_wide_bw_switch *wb_ie;
1556 struct wma_txrx_node *intr = wma->interfaces;
1557
1558 param_buf = (WMI_CSA_HANDLING_EVENTID_param_tlvs *) event;
1559
1560 WMA_LOGD("%s: Enter", __func__);
1561 if (!param_buf) {
1562 WMA_LOGE("Invalid csa event buffer");
1563 return -EINVAL;
1564 }
1565 csa_event = param_buf->fixed_param;
1566 WMI_MAC_ADDR_TO_CHAR_ARRAY(&csa_event->i_addr2, &bssid[0]);
1567
1568 if (wma_find_vdev_by_bssid(wma, bssid, &vdev_id) == NULL) {
1569 WMA_LOGE("Invalid bssid received %s:%d", __func__, __LINE__);
1570 return -EINVAL;
1571 }
1572
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301573 csa_offload_event = qdf_mem_malloc(sizeof(*csa_offload_event));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001574 if (!csa_offload_event) {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05301575 WMA_LOGE("QDF MEM Alloc Failed for csa_offload_event");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001576 return -EINVAL;
1577 }
1578
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301579 qdf_mem_zero(csa_offload_event, sizeof(*csa_offload_event));
1580 qdf_mem_copy(csa_offload_event->bssId, &bssid, IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001581
1582 if (csa_event->ies_present_flag & WMI_CSA_IE_PRESENT) {
1583 csa_ie = (struct ieee80211_channelswitch_ie *)
1584 (&csa_event->csa_ie[0]);
1585 csa_offload_event->channel = csa_ie->newchannel;
Chandrasekaran, Manishekar5c19dc52016-02-04 14:58:26 +05301586 csa_offload_event->switch_mode = csa_ie->switchmode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001587 } else if (csa_event->ies_present_flag & WMI_XCSA_IE_PRESENT) {
1588 xcsa_ie = (struct ieee80211_extendedchannelswitch_ie *)
1589 (&csa_event->xcsa_ie[0]);
1590 csa_offload_event->channel = xcsa_ie->newchannel;
Chandrasekaran, Manishekar5c19dc52016-02-04 14:58:26 +05301591 csa_offload_event->switch_mode = xcsa_ie->switchmode;
Gupta, Kapil121bf212015-11-25 19:21:29 +05301592 csa_offload_event->new_op_class = xcsa_ie->newClass;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001593 } else {
1594 WMA_LOGE("CSA Event error: No CSA IE present");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301595 qdf_mem_free(csa_offload_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001596 return -EINVAL;
1597 }
1598
1599 if (csa_event->ies_present_flag & WMI_WBW_IE_PRESENT) {
1600 wb_ie = (struct ieee80211_ie_wide_bw_switch *)
1601 (&csa_event->wb_ie[0]);
1602 csa_offload_event->new_ch_width = wb_ie->new_ch_width;
1603 csa_offload_event->new_ch_freq_seg1 = wb_ie->new_ch_freq_seg1;
1604 csa_offload_event->new_ch_freq_seg2 = wb_ie->new_ch_freq_seg2;
1605 }
1606
1607 csa_offload_event->ies_present_flag = csa_event->ies_present_flag;
1608
1609 WMA_LOGD("CSA: New Channel = %d BSSID:%pM",
1610 csa_offload_event->channel, csa_offload_event->bssId);
1611
1612 cur_chan = cds_freq_to_chan(intr[vdev_id].mhz);
1613 /*
1614 * basic sanity check: requested channel should not be 0
1615 * and equal to home channel
1616 */
1617 if ((0 == csa_offload_event->channel) ||
1618 (cur_chan == csa_offload_event->channel)) {
1619 WMA_LOGE("CSA Event with channel %d. Ignore !!",
1620 csa_offload_event->channel);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301621 qdf_mem_free(csa_offload_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001622 return -EINVAL;
1623 }
1624 wma->interfaces[vdev_id].is_channel_switch = true;
1625 wma_send_msg(wma, WMA_CSA_OFFLOAD_EVENT, (void *)csa_offload_event, 0);
1626 return 0;
1627}
1628
1629#ifdef FEATURE_OEM_DATA_SUPPORT
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001630/**
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001631 * wma_oem_data_response_handler() - OEM data response event handler
1632 * @handle: wma handle
1633 * @datap: data ptr
1634 * @len: data length
1635 *
1636 * Return: 0 for success or error code
1637 */
1638int wma_oem_data_response_handler(void *handle,
1639 uint8_t *datap, uint32_t len)
1640{
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001641 WMI_OEM_RESPONSE_EVENTID_param_tlvs *param_buf;
1642 uint8_t *data;
1643 uint32_t datalen;
Krishna Kumaar Natarajanc1fa17d2016-08-03 14:19:20 -07001644 struct oem_data_rsp *oem_rsp;
Krishna Kumaar Natarajan73ea9f22016-06-30 18:38:47 -07001645 tpAniSirGlobal pmac = cds_get_context(QDF_MODULE_ID_PE);
1646
1647 if (!pmac) {
1648 WMA_LOGE(FL("Invalid pmac"));
1649 return -EINVAL;
1650 }
1651
Krishna Kumaar Natarajanbbbf2ef2016-08-03 14:06:26 -07001652 if (!pmac->sme.oem_data_rsp_callback) {
Krishna Kumaar Natarajan73ea9f22016-06-30 18:38:47 -07001653 WMA_LOGE(FL("Callback not registered"));
1654 return -EINVAL;
1655 }
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001656
1657 param_buf = (WMI_OEM_RESPONSE_EVENTID_param_tlvs *) datap;
1658 if (!param_buf) {
1659 WMA_LOGE(FL("Received NULL buf ptr from FW"));
1660 return -ENOMEM;
1661 }
1662
1663 data = param_buf->data;
1664 datalen = param_buf->num_data;
1665
1666 if (!data) {
1667 WMA_LOGE(FL("Received NULL data from FW"));
1668 return -EINVAL;
1669 }
1670
1671 if (datalen > OEM_DATA_RSP_SIZE) {
1672 WMA_LOGE(FL("Received data len %d exceeds max value %d"),
1673 datalen, OEM_DATA_RSP_SIZE);
1674 return -EINVAL;
1675 }
1676
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001677 oem_rsp = qdf_mem_malloc(sizeof(*oem_rsp));
1678 if (!oem_rsp) {
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001679 WMA_LOGE(FL("Failed to alloc oem_data_rsp"));
1680 return -ENOMEM;
1681 }
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001682 oem_rsp->rsp_len = datalen;
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001683 if (oem_rsp->rsp_len) {
Krishna Kumaar Natarajan73ea9f22016-06-30 18:38:47 -07001684 oem_rsp->data = qdf_mem_malloc(oem_rsp->rsp_len);
1685 if (!oem_rsp->data) {
1686 WMA_LOGE(FL("malloc failed for data"));
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001687 qdf_mem_free(oem_rsp);
1688 return -ENOMEM;
1689 }
1690 } else {
1691 WMA_LOGE(FL("Invalid rsp length: %d"),
1692 oem_rsp->rsp_len);
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001693 qdf_mem_free(oem_rsp);
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001694 return -EINVAL;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001695 }
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001696
Krishna Kumaar Natarajan73ea9f22016-06-30 18:38:47 -07001697 qdf_mem_copy(oem_rsp->data, data, datalen);
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001698
Krishna Kumaar Natarajan73ea9f22016-06-30 18:38:47 -07001699 WMA_LOGI(FL("Sending OEM_DATA_RSP(len: %d) to upper layer"), datalen);
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001700
Krishna Kumaar Natarajanbbbf2ef2016-08-03 14:06:26 -07001701 pmac->sme.oem_data_rsp_callback(oem_rsp);
Krishna Kumaar Natarajan73ea9f22016-06-30 18:38:47 -07001702
1703 if (oem_rsp->data)
1704 qdf_mem_free(oem_rsp->data);
1705 qdf_mem_free(oem_rsp);
1706
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001707 return 0;
1708}
1709
1710/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001711 * wma_start_oem_data_req() - start OEM data request to target
1712 * @wma_handle: wma handle
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -07001713 * @oem_data_req: start request params
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001714 *
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -07001715 * Return: QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001716 */
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -07001717QDF_STATUS wma_start_oem_data_req(tp_wma_handle wma_handle,
Krishna Kumaar Natarajanc1fa17d2016-08-03 14:19:20 -07001718 struct oem_data_req *oem_data_req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001719{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001720 int ret = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001721
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001722 WMA_LOGD(FL("Send OEM Data Request to target"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001723
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -07001724 if (!oem_data_req || !oem_data_req->data) {
1725 WMA_LOGE(FL("oem_data_req is null"));
1726 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001727 }
1728
1729 if (!wma_handle || !wma_handle->wmi_handle) {
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001730 WMA_LOGE(FL("WMA - closed, can not send Oem data request cmd"));
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -07001731 qdf_mem_free(oem_data_req->data);
1732 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001733 }
1734
Govind Singhaa64c242016-03-08 11:31:49 +05301735 ret = wmi_unified_start_oem_data_cmd(wma_handle->wmi_handle,
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -07001736 oem_data_req->data_len,
1737 oem_data_req->data);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001738
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -07001739 if (!QDF_IS_STATUS_SUCCESS(ret))
1740 WMA_LOGE(FL("wmi cmd send failed"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001741
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -07001742 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001743}
1744#endif /* FEATURE_OEM_DATA_SUPPORT */
1745
1746
1747/**
1748 * wma_unified_dfs_radar_rx_event_handler() - dfs radar rx event handler
1749 * @handle: wma handle
1750 * @data: data buffer
1751 * @datalen: data length
1752 *
1753 * WMI handler for WMI_DFS_RADAR_EVENTID
1754 * This handler is registered for handling
1755 * filtered DFS Phyerror. This handler is
1756 * will be invoked only when DFS Phyerr
1757 * filtering offload is enabled.
1758 *
1759 * Return: 1 for Success and 0 for error
1760 */
1761static int wma_unified_dfs_radar_rx_event_handler(void *handle,
1762 uint8_t *data,
1763 uint32_t datalen)
1764{
1765 tp_wma_handle wma = (tp_wma_handle) handle;
1766 struct ieee80211com *ic;
1767 struct ath_dfs *dfs;
1768 struct dfs_event *event;
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05301769 struct dfs_ieee80211_channel *chan;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001770 int empty;
1771 int do_check_chirp = 0;
1772 int is_hw_chirp = 0;
1773 int is_sw_chirp = 0;
1774 int is_pri = 0;
Vishwajith Upendrabf673e72016-01-19 16:05:40 -08001775 bool is_ch_dfs = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001776
1777 WMI_DFS_RADAR_EVENTID_param_tlvs *param_tlvs;
1778 wmi_dfs_radar_event_fixed_param *radar_event;
1779
1780 ic = wma->dfs_ic;
1781 if (NULL == ic) {
1782 WMA_LOGE("%s: dfs_ic is NULL ", __func__);
1783 return 0;
1784 }
1785
1786 dfs = (struct ath_dfs *)ic->ic_dfs;
1787 param_tlvs = (WMI_DFS_RADAR_EVENTID_param_tlvs *) data;
1788
1789 if (NULL == dfs) {
1790 WMA_LOGE("%s: dfs is NULL ", __func__);
1791 return 0;
1792 }
1793 /*
1794 * This parameter holds the number
1795 * of phyerror interrupts to the host
1796 * after the phyerrors have passed through
1797 * false detect filters in the firmware.
1798 */
1799 dfs->dfs_phyerr_count++;
1800
1801 if (!param_tlvs) {
1802 WMA_LOGE("%s: Received NULL data from FW", __func__);
1803 return 0;
1804 }
1805
1806 radar_event = param_tlvs->fixed_param;
1807
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301808 qdf_spin_lock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001809 chan = ic->ic_curchan;
Edhar, Mahesh Kumar35d9b2e2015-10-26 17:06:23 +05301810 if (ic->disable_phy_err_processing) {
1811 WMA_LOGD("%s: radar indication done,drop phyerror event",
1812 __func__);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301813 qdf_spin_unlock_bh(&ic->chan_lock);
Edhar, Mahesh Kumar35d9b2e2015-10-26 17:06:23 +05301814 return 0;
1815 }
1816
Vishwajith Upendrabf673e72016-01-19 16:05:40 -08001817 if (IEEE80211_IS_CHAN_11AC_VHT160(chan)) {
1818 is_ch_dfs = true;
1819 } else if (IEEE80211_IS_CHAN_11AC_VHT80P80(chan)) {
1820 if (cds_get_channel_state(chan->ic_ieee) == CHANNEL_STATE_DFS ||
1821 cds_get_channel_state(chan->ic_ieee_ext -
1822 WMA_80MHZ_START_CENTER_CH_DIFF) ==
1823 CHANNEL_STATE_DFS)
1824 is_ch_dfs = true;
1825 } else {
1826 if (cds_get_channel_state(chan->ic_ieee) == CHANNEL_STATE_DFS)
1827 is_ch_dfs = true;
1828 }
1829 if (!is_ch_dfs) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001830 WMA_LOGE
1831 ("%s: Invalid DFS Phyerror event. Channel=%d is Non-DFS",
1832 __func__, chan->ic_ieee);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301833 qdf_spin_unlock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001834 return 0;
1835 }
1836
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301837 qdf_spin_unlock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001838 dfs->ath_dfs_stats.total_phy_errors++;
1839
1840 if (dfs->dfs_caps.ath_chip_is_bb_tlv) {
1841 do_check_chirp = 1;
1842 is_pri = 1;
1843 is_hw_chirp = radar_event->pulse_is_chirp;
1844
1845 if ((uint32_t) dfs->dfs_phyerr_freq_min >
1846 radar_event->pulse_center_freq) {
1847 dfs->dfs_phyerr_freq_min =
1848 (int)radar_event->pulse_center_freq;
1849 }
1850
1851 if (dfs->dfs_phyerr_freq_max <
1852 (int)radar_event->pulse_center_freq) {
1853 dfs->dfs_phyerr_freq_max =
1854 (int)radar_event->pulse_center_freq;
1855 }
1856 }
1857
1858 /*
1859 * Now, add the parsed, checked and filtered
1860 * radar phyerror event radar pulse event list.
1861 * This event will then be processed by
1862 * dfs_radar_processevent() to see if the pattern
1863 * of pulses in radar pulse list match any radar
1864 * singnature in the current regulatory domain.
1865 */
1866
1867 ATH_DFSEVENTQ_LOCK(dfs);
1868 empty = STAILQ_EMPTY(&(dfs->dfs_eventq));
1869 ATH_DFSEVENTQ_UNLOCK(dfs);
1870 if (empty) {
1871 return 0;
1872 }
1873 /*
1874 * Add the event to the list, if there's space.
1875 */
1876 ATH_DFSEVENTQ_LOCK(dfs);
1877 event = STAILQ_FIRST(&(dfs->dfs_eventq));
1878 if (event == NULL) {
1879 ATH_DFSEVENTQ_UNLOCK(dfs);
1880 WMA_LOGE("%s: No more space left for queuing DFS Phyerror events",
1881 __func__);
1882 return 0;
1883 }
1884 STAILQ_REMOVE_HEAD(&(dfs->dfs_eventq), re_list);
1885 ATH_DFSEVENTQ_UNLOCK(dfs);
1886 dfs->dfs_phyerr_queued_count++;
1887 dfs->dfs_phyerr_w53_counter++;
1888 event->re_dur = (uint8_t) radar_event->pulse_duration;
1889 event->re_rssi = radar_event->rssi;
1890 event->re_ts = radar_event->pulse_detect_ts & DFS_TSMASK;
1891 event->re_full_ts = (((uint64_t) radar_event->upload_fullts_high) << 32)
1892 | radar_event->upload_fullts_low;
1893
1894 /*
1895 * Index of peak magnitude
1896 */
1897 event->sidx = radar_event->peak_sidx;
1898
1899 /*
1900 * Handle chirp flags.
1901 */
1902 if (do_check_chirp) {
1903 event->re_flags |= DFS_EVENT_CHECKCHIRP;
1904 if (is_hw_chirp) {
1905 event->re_flags |= DFS_EVENT_HW_CHIRP;
1906 }
1907 if (is_sw_chirp) {
1908 event->re_flags |= DFS_EVENT_SW_CHIRP;
1909 }
1910 }
1911 /*
1912 * Correctly set which channel is being reported on
1913 */
1914 if (is_pri) {
1915 event->re_chanindex = (uint8_t) dfs->dfs_curchan_radindex;
1916 } else {
1917 if (dfs->dfs_extchan_radindex == -1) {
1918 WMA_LOGI("%s phyerr on ext channel", __func__);
1919 }
1920 event->re_chanindex = (uint8_t) dfs->dfs_extchan_radindex;
1921 WMA_LOGI("%s:New extension channel event is added to queue",
1922 __func__);
1923 }
1924
1925 ATH_DFSQ_LOCK(dfs);
1926
1927 STAILQ_INSERT_TAIL(&(dfs->dfs_radarq), event, re_list);
1928
1929 empty = STAILQ_EMPTY(&dfs->dfs_radarq);
1930
1931 ATH_DFSQ_UNLOCK(dfs);
1932
1933 if (!empty && !dfs->ath_radar_tasksched) {
1934 dfs->ath_radar_tasksched = 1;
1935 OS_SET_TIMER(&dfs->ath_dfs_task_timer, 0);
1936 }
1937
1938 return 1;
1939
1940}
1941
1942/**
1943 * wma_unified_phyerr_rx_event_handler() - phyerr event handler
1944 * @handle: wma handle
1945 * @data: data buffer
1946 * @datalen: buffer length
1947 *
1948 * WMI Handler for WMI_PHYERR_EVENTID event from firmware.
1949 * This handler is currently handling only DFS phy errors.
1950 * This handler will be invoked only when the DFS phyerror
1951 * filtering offload is disabled.
1952 *
1953 * Return: 1:Success, 0:Failure
1954 */
1955static int wma_unified_phyerr_rx_event_handler(void *handle,
1956 uint8_t *data, uint32_t datalen)
1957{
1958 tp_wma_handle wma = (tp_wma_handle) handle;
1959 WMI_PHYERR_EVENTID_param_tlvs *param_tlvs;
1960 wmi_comb_phyerr_rx_hdr *pe_hdr;
1961 uint8_t *bufp;
1962 wmi_single_phyerr_rx_event *ev;
1963 struct ieee80211com *ic = wma->dfs_ic;
Anurag Chouhan6d760662016-02-20 16:05:43 +05301964 qdf_size_t n;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001965 A_UINT64 tsf64 = 0;
1966 int phy_err_code = 0;
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08001967 A_UINT32 phy_err_mask = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001968 int error = 0;
1969 tpAniSirGlobal mac_ctx =
Anurag Chouhan6d760662016-02-20 16:05:43 +05301970 (tpAniSirGlobal)cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001971 bool enable_log = false;
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08001972 int max_dfs_buf_length = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001973
1974 if (NULL == mac_ctx) {
1975 WMA_LOGE("%s: mac_ctx is NULL", __func__);
1976 return 0;
1977 }
1978 enable_log = mac_ctx->sap.enable_dfs_phy_error_logs;
1979
1980 param_tlvs = (WMI_PHYERR_EVENTID_param_tlvs *) data;
1981
1982 if (!param_tlvs) {
1983 WMA_LOGE("%s: Received NULL data from FW", __func__);
1984 return 0;
1985 }
1986
1987 pe_hdr = param_tlvs->hdr;
1988 if (pe_hdr == NULL) {
1989 WMA_LOGE("%s: Received Data PE Header is NULL", __func__);
1990 return 0;
1991 }
1992
1993 /* Ensure it's at least the size of the header */
1994 if (datalen < sizeof(*pe_hdr)) {
1995 WMA_LOGE("%s: Expected minimum size %zu, received %d",
1996 __func__, sizeof(*pe_hdr), datalen);
1997 return 0;
1998 }
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08001999 /*
2000 * The max buffer lenght is larger for DFS-3 than DFS-2.
2001 * So, accordingly use the correct max buffer size.
2002 */
2003 if (wma->hw_bd_id != WMI_HWBD_QCA6174)
2004 max_dfs_buf_length = DFS3_MAX_BUF_LENGTH;
2005 else
2006 max_dfs_buf_length = DFS_MAX_BUF_LENGTH;
2007
2008 if (pe_hdr->buf_len > max_dfs_buf_length) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002009 WMA_LOGE("%s: Received Invalid Phyerror event buffer length = %d"
2010 "Maximum allowed buf length = %d", __func__,
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002011 pe_hdr->buf_len, max_dfs_buf_length);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002012
2013 return 0;
2014 }
2015
2016 /*
2017 * Reconstruct the 64 bit event TSF. This isn't from the MAC, it's
2018 * at the time the event was sent to us, the TSF value will be
2019 * in the future.
2020 */
2021 tsf64 = pe_hdr->tsf_l32;
2022 tsf64 |= (((uint64_t) pe_hdr->tsf_u32) << 32);
2023
2024 /*
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002025 * Check the HW board ID to figure out
2026 * if DFS-3 is supported. In DFS-3
2027 * phyerror mask indicates the type of
2028 * phyerror, whereas in DFS-2 phyerrorcode
2029 * indicates the type of phyerror. If the
2030 * board is NOT WMI_HWBD_QCA6174, for now
2031 * assume that it supports DFS-3.
2032 */
2033 if (wma->hw_bd_id != WMI_HWBD_QCA6174) {
2034 phy_err_mask = pe_hdr->rsPhyErrMask0;
2035 WMA_LOGD("%s: DFS-3 phyerror mask = 0x%x",
2036 __func__, phy_err_mask);
2037 }
2038
2039 /*
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002040 * Loop over the bufp, extracting out phyerrors
2041 * wmi_unified_comb_phyerr_rx_event.bufp is a char pointer,
2042 * which isn't correct here - what we have received here
2043 * is an array of TLV-style PHY errors.
2044 */
2045 n = 0; /* Start just after the header */
2046 bufp = param_tlvs->bufp;
2047 while (n < pe_hdr->buf_len) {
2048 /* ensure there's at least space for the header */
2049 if ((pe_hdr->buf_len - n) < sizeof(ev->hdr)) {
2050 WMA_LOGE("%s: Not enough space.(datalen=%d, n=%zu, hdr=%zu bytes",
2051 __func__, pe_hdr->buf_len, n, sizeof(ev->hdr));
2052 error = 1;
2053 break;
2054 }
2055 /*
2056 * Obtain a pointer to the beginning of the current event.
2057 * data[0] is the beginning of the WMI payload.
2058 */
2059 ev = (wmi_single_phyerr_rx_event *) &bufp[n];
2060
2061 /*
2062 * Sanity check the buffer length of the event against
2063 * what we currently have.
2064 * Since buf_len is 32 bits, we check if it overflows
2065 * a large 32 bit value. It's not 0x7fffffff because
2066 * we increase n by (buf_len + sizeof(hdr)), which would
2067 * in itself cause n to overflow.
2068 * If "int" is 64 bits then this becomes a moot point.
2069 */
2070 if (ev->hdr.buf_len > 0x7f000000) {
2071 WMA_LOGE("%s:buf_len is garbage (0x%x)", __func__,
2072 ev->hdr.buf_len);
2073 error = 1;
2074 break;
2075 }
2076 if (n + ev->hdr.buf_len > pe_hdr->buf_len) {
2077 WMA_LOGE("%s: buf_len exceeds available space n=%zu,"
2078 "buf_len=%d, datalen=%d",
2079 __func__, n, ev->hdr.buf_len, pe_hdr->buf_len);
2080 error = 1;
2081 break;
2082 }
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002083 /*
2084 * If the board id is WMI_HWBD_QCA6174
2085 * then it supports only DFS-2. So, fetch
2086 * phyerror code in order to know the type
2087 * of phyerror.
2088 */
2089 if (wma->hw_bd_id == WMI_HWBD_QCA6174) {
2090 phy_err_code = WMI_UNIFIED_PHYERRCODE_GET(&ev->hdr);
2091 WMA_LOGD("%s: DFS-2 phyerror code = 0x%x",
2092 __func__, phy_err_code);
2093 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002094
2095 /*
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002096 * phy_err_code is set for DFS-2 and phy_err_mask
2097 * is set for DFS-3. Checking both to support
2098 * compatability for older platforms.
2099 * If the phyerror or phyerrmask category matches,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002100 * pass radar events to the dfs pattern matching code.
2101 * Don't pass radar events with no buffer payload.
2102 */
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002103 if (((phy_err_mask & WMI_PHY_ERROR_MASK0_RADAR) ||
2104 (phy_err_mask & WMI_PHY_ERROR_MASK0_FALSE_RADAR_EXT)) ||
2105 (phy_err_code == WMA_DFS2_PHYERROR_CODE ||
2106 phy_err_code == WMA_DFS2_FALSE_RADAR_EXT)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002107 if (ev->hdr.buf_len > 0) {
2108 /* Calling in to the DFS module to process the phyerr */
2109 dfs_process_phyerr(ic, &ev->bufp[0],
2110 ev->hdr.buf_len,
2111 WMI_UNIFIED_RSSI_COMB_GET
2112 (&ev->hdr) & 0xff,
2113 /* Extension RSSI */
2114 WMI_UNIFIED_RSSI_COMB_GET
2115 (&ev->hdr) & 0xff,
2116 ev->hdr.tsf_timestamp,
2117 tsf64, enable_log);
2118 }
2119 }
2120
2121 /*
2122 * Advance the buffer pointer to the next PHY error.
2123 * buflen is the length of this payload, so we need to
2124 * advance past the current header _AND_ the payload.
2125 */
2126 n += sizeof(*ev) + ev->hdr.buf_len;
2127
2128 } /*end while() */
2129 if (error)
2130 return 0;
2131 else
2132 return 1;
2133}
2134
2135/**
2136 * wma_register_dfs_event_handler() - register dfs event handler
2137 * @wma_handle: wma handle
2138 *
2139 * Register appropriate dfs phyerror event handler
2140 * based on phyerror filtering offload is enabled
2141 * or disabled.
2142 *
2143 * Return: none
2144 */
2145void wma_register_dfs_event_handler(tp_wma_handle wma_handle)
2146{
2147 if (NULL == wma_handle) {
2148 WMA_LOGE("%s:wma_handle is NULL", __func__);
2149 return;
2150 }
2151
2152 if (false == wma_handle->dfs_phyerr_filter_offload) {
2153 /*
2154 * Register the wma_unified_phyerr_rx_event_handler
2155 * for filtering offload disabled case to handle
2156 * the DFS phyerrors.
2157 */
2158 WMA_LOGD("%s:Phyerror Filtering offload is Disabled in ini",
2159 __func__);
2160 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Govind Singhd76a5b02016-03-08 15:12:14 +05302161 WMI_PHYERR_EVENTID,
2162 wma_unified_phyerr_rx_event_handler,
2163 WMA_RX_WORK_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002164 WMA_LOGD("%s: WMI_PHYERR_EVENTID event handler registered",
2165 __func__);
2166 } else {
2167 WMA_LOGD("%s:Phyerror Filtering offload is Enabled in ini",
2168 __func__);
2169 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Govind Singhd76a5b02016-03-08 15:12:14 +05302170 WMI_DFS_RADAR_EVENTID,
2171 wma_unified_dfs_radar_rx_event_handler,
2172 WMA_RX_WORK_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002173 WMA_LOGD("%s:WMI_DFS_RADAR_EVENTID event handler registered",
2174 __func__);
2175 }
2176
2177 return;
2178}
2179
2180
2181/**
2182 * wma_unified_dfs_phyerr_filter_offload_enable() - enable dfs phyerr filter
2183 * @wma_handle: wma handle
2184 *
2185 * Send WMI_DFS_PHYERR_FILTER_ENA_CMDID or
2186 * WMI_DFS_PHYERR_FILTER_DIS_CMDID command
2187 * to firmware based on phyerr filtering
2188 * offload status.
2189 *
2190 * Return: 1 success, 0 failure
2191 */
2192int
2193wma_unified_dfs_phyerr_filter_offload_enable(tp_wma_handle wma_handle)
2194{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002195 int ret;
2196
2197 if (NULL == wma_handle) {
2198 WMA_LOGE("%s:wma_handle is NULL", __func__);
2199 return 0;
2200 }
2201
Govind Singhaa64c242016-03-08 11:31:49 +05302202 ret = wmi_unified_dfs_phyerr_filter_offload_en_cmd(wma_handle->wmi_handle,
2203 wma_handle->dfs_phyerr_filter_offload);
2204 if (ret)
2205 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002206
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002207
Govind Singhaa64c242016-03-08 11:31:49 +05302208 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002209}
2210
2211#if !defined(REMOVE_PKT_LOG)
2212/**
2213 * wma_pktlog_wmi_send_cmd() - send pktlog enable/disable command to target
2214 * @handle: wma handle
2215 * @params: pktlog params
2216 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302217 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002218 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302219QDF_STATUS wma_pktlog_wmi_send_cmd(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002220 struct ath_pktlog_wmi_params *params)
2221{
2222 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhaa64c242016-03-08 11:31:49 +05302223 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002224
2225 /*Check if packet log is enabled in cfg.ini */
2226 if (!cds_is_packet_log_enabled()) {
2227 WMA_LOGE("%s:pkt log is not enabled in cfg.ini", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302228 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002229 }
2230
Govind Singhaa64c242016-03-08 11:31:49 +05302231 ret = wmi_unified_pktlog_wmi_send_cmd(wma_handle->wmi_handle,
2232 params->pktlog_event,
2233 params->cmd_id);
2234 if (ret)
2235 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002236
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002237
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302238 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002239}
2240#endif /* REMOVE_PKT_LOG */
2241
2242static void wma_send_status_to_suspend_ind(tp_wma_handle wma, bool suspended)
2243{
2244 tSirReadyToSuspendInd *ready_to_suspend;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302245 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002246 cds_msg_t cds_msg;
2247 uint8_t len;
2248
2249 WMA_LOGD("Posting ready to suspend indication to umac");
2250
2251 len = sizeof(tSirReadyToSuspendInd);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302252 ready_to_suspend = (tSirReadyToSuspendInd *) qdf_mem_malloc(len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002253
2254 if (NULL == ready_to_suspend) {
2255 WMA_LOGE("%s: Memory allocation failure", __func__);
2256 return;
2257 }
2258
2259 ready_to_suspend->mesgType = eWNI_SME_READY_TO_SUSPEND_IND;
2260 ready_to_suspend->mesgLen = len;
2261 ready_to_suspend->suspended = suspended;
2262
2263 cds_msg.type = eWNI_SME_READY_TO_SUSPEND_IND;
2264 cds_msg.bodyptr = (void *)ready_to_suspend;
2265 cds_msg.bodyval = 0;
2266
2267 status = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302268 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002269 WMA_LOGE("Failed to post ready to suspend");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302270 qdf_mem_free(ready_to_suspend);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002271 }
2272}
2273
2274/**
2275 * wma_wow_wake_reason_str() - Converts wow wakeup reason code to text format
2276 * @wake_reason - WOW wake reason
2277 *
2278 * Return: reason code in string format
2279 */
2280static const u8 *wma_wow_wake_reason_str(A_INT32 wake_reason)
2281{
2282 switch (wake_reason) {
2283 case WOW_REASON_UNSPECIFIED:
2284 return "UNSPECIFIED";
2285 case WOW_REASON_NLOD:
2286 return "NLOD";
2287 case WOW_REASON_AP_ASSOC_LOST:
2288 return "AP_ASSOC_LOST";
2289 case WOW_REASON_LOW_RSSI:
2290 return "LOW_RSSI";
2291 case WOW_REASON_DEAUTH_RECVD:
2292 return "DEAUTH_RECVD";
2293 case WOW_REASON_DISASSOC_RECVD:
2294 return "DISASSOC_RECVD";
2295 case WOW_REASON_GTK_HS_ERR:
2296 return "GTK_HS_ERR";
2297 case WOW_REASON_EAP_REQ:
2298 return "EAP_REQ";
2299 case WOW_REASON_FOURWAY_HS_RECV:
2300 return "FOURWAY_HS_RECV";
2301 case WOW_REASON_TIMER_INTR_RECV:
2302 return "TIMER_INTR_RECV";
2303 case WOW_REASON_PATTERN_MATCH_FOUND:
2304 return "PATTERN_MATCH_FOUND";
2305 case WOW_REASON_RECV_MAGIC_PATTERN:
2306 return "RECV_MAGIC_PATTERN";
2307 case WOW_REASON_P2P_DISC:
2308 return "P2P_DISC";
2309#ifdef FEATURE_WLAN_LPHB
2310 case WOW_REASON_WLAN_HB:
2311 return "WLAN_HB";
2312#endif /* FEATURE_WLAN_LPHB */
2313
2314 case WOW_REASON_CSA_EVENT:
2315 return "CSA_EVENT";
2316 case WOW_REASON_PROBE_REQ_WPS_IE_RECV:
2317 return "PROBE_REQ_RECV";
2318 case WOW_REASON_AUTH_REQ_RECV:
2319 return "AUTH_REQ_RECV";
2320 case WOW_REASON_ASSOC_REQ_RECV:
2321 return "ASSOC_REQ_RECV";
2322 case WOW_REASON_HTT_EVENT:
2323 return "WOW_REASON_HTT_EVENT";
2324#ifdef FEATURE_WLAN_RA_FILTERING
2325 case WOW_REASON_RA_MATCH:
2326 return "WOW_REASON_RA_MATCH";
2327#endif /* FEATURE_WLAN_RA_FILTERING */
2328 case WOW_REASON_BEACON_RECV:
2329 return "WOW_REASON_IBSS_BEACON_RECV";
2330#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
2331 case WOW_REASON_HOST_AUTO_SHUTDOWN:
2332 return "WOW_REASON_HOST_AUTO_SHUTDOWN";
2333#endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
2334#ifdef WLAN_FEATURE_ROAM_OFFLOAD
2335 case WOW_REASON_ROAM_HO:
2336 return "WOW_REASON_ROAM_HO";
2337#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
2338#ifdef FEATURE_WLAN_EXTSCAN
2339 case WOW_REASON_EXTSCAN:
2340 return "WOW_REASON_EXTSCAN";
2341#endif
2342 case WOW_REASON_RSSI_BREACH_EVENT:
2343 return "WOW_REASON_RSSI_BREACH_EVENT";
Srinivas Girigowdae80cea92015-11-23 11:33:57 -08002344 case WOW_REASON_NLO_SCAN_COMPLETE:
2345 return "WOW_REASON_NLO_SCAN_COMPLETE";
Naveen Rawatc9f09522016-05-12 14:02:42 -07002346 case WOW_REASON_NAN_EVENT:
2347 return "WOW_REASON_NAN_EVENT";
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002348 }
2349 return "unknown";
2350}
2351
2352/**
2353 * wma_wow_wake_up_stats_display() - display wow wake up stats
2354 * @wma: Pointer to wma handle
2355 *
2356 * Return: none
2357 */
2358static void wma_wow_wake_up_stats_display(tp_wma_handle wma)
2359{
2360 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",
2361 wma->wow_ucast_wake_up_count,
2362 wma->wow_bcast_wake_up_count,
2363 wma->wow_ipv4_mcast_wake_up_count,
2364 wma->wow_ipv6_mcast_wake_up_count,
2365 wma->wow_ipv6_mcast_ra_stats,
2366 wma->wow_ipv6_mcast_ns_stats,
2367 wma->wow_ipv6_mcast_na_stats,
2368 wma->wow_pno_match_wake_up_count,
2369 wma->wow_pno_complete_wake_up_count,
2370 wma->wow_gscan_wake_up_count,
2371 wma->wow_low_rssi_wake_up_count,
2372 wma->wow_rssi_breach_wake_up_count);
2373
2374 return;
2375}
2376
2377/**
2378 * wma_wow_ipv6_mcast_stats() - ipv6 mcast wake up stats
2379 * @wma: Pointer to wma handle
2380 * @data: Pointer to pattern match data
2381 *
2382 * Return: none
2383 */
2384static void wma_wow_ipv6_mcast_stats(tp_wma_handle wma, uint8_t *data)
2385{
2386 static const uint8_t ipv6_mcast[] = {0x86, 0xDD};
2387
2388 if (!memcmp(ipv6_mcast, (data + WMA_ETHER_TYPE_OFFSET),
2389 sizeof(ipv6_mcast))) {
2390 if (WMA_ICMP_V6_HEADER_TYPE ==
2391 *(data + WMA_ICMP_V6_HEADER_OFFSET)) {
2392 if (WMA_ICMP_V6_RA_TYPE ==
2393 *(data + WMA_ICMP_V6_TYPE_OFFSET))
2394 wma->wow_ipv6_mcast_ra_stats++;
2395 else if (WMA_ICMP_V6_NS_TYPE ==
2396 *(data + WMA_ICMP_V6_TYPE_OFFSET))
2397 wma->wow_ipv6_mcast_ns_stats++;
2398 else if (WMA_ICMP_V6_NA_TYPE ==
2399 *(data + WMA_ICMP_V6_TYPE_OFFSET))
2400 wma->wow_ipv6_mcast_na_stats++;
2401 else
2402 WMA_LOGA("ICMP V6 type : 0x%x",
2403 *(data + WMA_ICMP_V6_TYPE_OFFSET));
2404 } else {
2405 WMA_LOGA("ICMP_V6 header 0x%x",
2406 *(data + WMA_ICMP_V6_HEADER_OFFSET));
2407 }
2408 } else {
2409 WMA_LOGA("Ethertype x%x:0x%x",
2410 *(data + WMA_ETHER_TYPE_OFFSET),
2411 *(data + WMA_ETHER_TYPE_OFFSET + 1));
2412 }
2413
2414 return;
2415}
2416
2417/**
2418 * wma_wow_wake_up_stats() - maintain wow pattern match wake up stats
2419 * @wma: Pointer to wma handle
2420 * @data: Pointer to pattern match data
2421 * @len: Pattern match data length
2422 * @event: Wake up event
2423 *
2424 * Return: none
2425 */
2426static void wma_wow_wake_up_stats(tp_wma_handle wma, uint8_t *data,
2427 int32_t len, WOW_WAKE_REASON_TYPE event)
2428{
2429 switch (event) {
2430
2431 case WOW_REASON_PATTERN_MATCH_FOUND:
2432 if (WMA_BCAST_MAC_ADDR == *data) {
2433 wma->wow_bcast_wake_up_count++;
2434 } else if (WMA_MCAST_IPV4_MAC_ADDR == *data) {
2435 wma->wow_ipv4_mcast_wake_up_count++;
2436 } else if (WMA_MCAST_IPV6_MAC_ADDR == *data) {
2437 wma->wow_ipv6_mcast_wake_up_count++;
2438 if (len > WMA_ICMP_V6_TYPE_OFFSET)
2439 wma_wow_ipv6_mcast_stats(wma, data);
2440 else
2441 WMA_LOGA("ICMP_V6 data len %d", len);
2442 } else {
2443 wma->wow_ucast_wake_up_count++;
2444 }
2445 break;
2446
2447 case WOW_REASON_RA_MATCH:
2448 wma->wow_ipv6_mcast_ra_stats++;
2449 break;
2450
2451 case WOW_REASON_NLOD:
2452 wma->wow_pno_match_wake_up_count++;
2453 break;
2454
2455 case WOW_REASON_NLO_SCAN_COMPLETE:
2456 wma->wow_pno_complete_wake_up_count++;
2457 break;
2458
2459 case WOW_REASON_LOW_RSSI:
2460 wma->wow_low_rssi_wake_up_count++;
2461 break;
2462
2463 case WOW_REASON_EXTSCAN:
2464 wma->wow_gscan_wake_up_count++;
2465 break;
2466
2467 case WOW_REASON_RSSI_BREACH_EVENT:
2468 wma->wow_rssi_breach_wake_up_count++;
2469 break;
2470
2471 default:
2472 WMA_LOGE("Unknown wake up reason");
2473 break;
2474 }
2475
2476 wma_wow_wake_up_stats_display(wma);
2477 return;
2478}
2479
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07002480#ifdef FEATURE_WLAN_EXTSCAN
2481/**
2482 * wma_extscan_get_eventid_from_tlvtag() - map tlv tag to corresponding event id
2483 * @tag: WMI TLV tag
2484 *
2485 * Return:
2486 * 0 if TLV tag is invalid
2487 * else return corresponding WMI event id
2488 */
2489static int wma_extscan_get_eventid_from_tlvtag(uint32_t tag)
2490{
2491 uint32_t event_id;
2492
2493 switch (tag) {
2494 case WMITLV_TAG_STRUC_wmi_extscan_start_stop_event_fixed_param:
2495 event_id = WMI_EXTSCAN_START_STOP_EVENTID;
2496 break;
2497
2498 case WMITLV_TAG_STRUC_wmi_extscan_operation_event_fixed_param:
2499 event_id = WMI_EXTSCAN_OPERATION_EVENTID;
2500 break;
2501
2502 case WMITLV_TAG_STRUC_wmi_extscan_table_usage_event_fixed_param:
2503 event_id = WMI_EXTSCAN_TABLE_USAGE_EVENTID;
2504 break;
2505
2506 case WMITLV_TAG_STRUC_wmi_extscan_cached_results_event_fixed_param:
2507 event_id = WMI_EXTSCAN_CACHED_RESULTS_EVENTID;
2508 break;
2509
2510 case WMITLV_TAG_STRUC_wmi_extscan_wlan_change_results_event_fixed_param:
2511 event_id = WMI_EXTSCAN_WLAN_CHANGE_RESULTS_EVENTID;
2512 break;
2513
2514 case WMITLV_TAG_STRUC_wmi_extscan_hotlist_match_event_fixed_param:
2515 event_id = WMI_EXTSCAN_HOTLIST_MATCH_EVENTID;
2516 break;
2517
2518 case WMITLV_TAG_STRUC_wmi_extscan_capabilities_event_fixed_param:
2519 event_id = WMI_EXTSCAN_CAPABILITIES_EVENTID;
2520 break;
2521
2522 case WMITLV_TAG_STRUC_wmi_extscan_hotlist_ssid_match_event_fixed_param:
2523 event_id = WMI_EXTSCAN_HOTLIST_SSID_MATCH_EVENTID;
2524 break;
2525
2526 default:
2527 event_id = 0;
2528 WMA_LOGE("%s: Unknown tag: %d", __func__, tag);
2529 break;
2530 }
2531
2532 WMA_LOGI("%s: For tag %d WMI event 0x%x", __func__, tag, event_id);
2533 return event_id;
2534}
2535#else
2536static int wma_extscan_get_eventid_from_tlvtag(uint32_t tag)
2537{
2538 return 0;
2539}
2540#endif
2541
2542/**
2543 * wow_get_wmi_eventid() - map reason or tlv tag to corresponding event id
2544 * @tag: WMI TLV tag
2545 * @reason: WOW reason
2546 *
2547 * WOW reason type is primarily used to find the ID. If there could be
2548 * multiple events that can be sent as a WOW event with same reason
2549 * then tlv tag is used to identify the corresponding event.
2550 *
2551 * Return:
2552 * 0 if TLV tag/reason is invalid
2553 * else return corresponding WMI event id
2554 */
2555static int wow_get_wmi_eventid(int32_t reason, uint32_t tag)
2556{
2557 uint32_t event_id;
2558
2559 switch (reason) {
2560 case WOW_REASON_NLO_SCAN_COMPLETE:
2561 event_id = WMI_NLO_SCAN_COMPLETE_EVENTID;
2562 break;
2563 case WOW_REASON_CSA_EVENT:
2564 event_id = WMI_CSA_HANDLING_EVENTID;
2565 break;
2566 case WOW_REASON_LOW_RSSI:
2567 event_id = WMI_ROAM_EVENTID;
2568 break;
2569 case WOW_REASON_CLIENT_KICKOUT_EVENT:
2570 event_id = WMI_PEER_STA_KICKOUT_EVENTID;
2571 break;
2572 case WOW_REASON_EXTSCAN:
2573 event_id = wma_extscan_get_eventid_from_tlvtag(tag);
2574 break;
2575 case WOW_REASON_RSSI_BREACH_EVENT:
2576 event_id = WMI_RSSI_BREACH_EVENTID;
2577 break;
2578 case WOW_REASON_NAN_EVENT:
2579 event_id = WMI_NAN_EVENTID;
2580 break;
2581 default:
2582 WMA_LOGD(FL("Unexpected WOW reason : %s(%d)"),
2583 wma_wow_wake_reason_str(reason), reason);
2584 event_id = 0;
2585 break;
2586 }
2587
2588 return event_id;
2589}
2590
2591/**
2592 * tlv_check_required() - tells whether to check the wow packet buffer
2593 * for proper TLV structure.
2594 * @reason: WOW reason
2595 *
2596 * In most cases, wow wake up event carries the actual event buffer in
2597 * wow_packet_buffer with some exceptions. This function is used to
2598 * determine when to check for the TLVs in wow_packet_buffer.
2599 *
2600 * Return: true if check is required and false otherwise.
2601 */
2602static bool tlv_check_required(int32_t reason)
2603{
2604 switch (reason) {
2605 case WOW_REASON_PATTERN_MATCH_FOUND:
2606 return false;
2607 default:
2608 return true;
2609 }
2610}
2611
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002612/**
2613 * wma_wow_wakeup_host_event() - wakeup host event handler
2614 * @handle: wma handle
2615 * @event: event data
2616 * @len: buffer length
2617 *
2618 * Handler to catch wow wakeup host event. This event will have
2619 * reason why the firmware has woken the host.
2620 *
2621 * Return: 0 for success or error
2622 */
2623int wma_wow_wakeup_host_event(void *handle, uint8_t *event,
2624 uint32_t len)
2625{
2626 tp_wma_handle wma = (tp_wma_handle) handle;
2627 WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *param_buf;
2628 WOW_EVENT_INFO_fixed_param *wake_info;
2629#ifdef FEATURE_WLAN_SCAN_PNO
2630 struct wma_txrx_node *node;
2631#endif /* FEATURE_WLAN_SCAN_PNO */
2632 uint32_t wake_lock_duration = 0;
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07002633 void *wmi_cmd_struct_ptr = NULL;
2634 uint32_t tlv_hdr, tag, wow_buf_pkt_len = 0, event_id = 0;
2635 int tlv_ok_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002636
2637 param_buf = (WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *) event;
2638 if (!param_buf) {
2639 WMA_LOGE("Invalid wow wakeup host event buf");
2640 return -EINVAL;
2641 }
2642
2643 wake_info = param_buf->fixed_param;
2644
2645 WMA_LOGA("WOW wakeup host event received (reason: %s(%d)) for vdev %d",
2646 wma_wow_wake_reason_str(wake_info->wake_reason),
2647 wake_info->wake_reason, wake_info->vdev_id);
2648
Anurag Chouhance0dc992016-02-16 18:18:03 +05302649 qdf_event_set(&wma->wma_resume_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002650
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07002651 if (param_buf->wow_packet_buffer &&
2652 tlv_check_required(wake_info->wake_reason)) {
2653 /*
2654 * In case of wow_packet_buffer, first 4 bytes is the length.
2655 * Following the length is the actual buffer.
2656 */
2657 wow_buf_pkt_len = *(uint32_t *)param_buf->wow_packet_buffer;
2658 tlv_hdr = WMITLV_GET_HDR(
2659 (uint8_t *)param_buf->wow_packet_buffer + 4);
2660
2661 tag = WMITLV_GET_TLVTAG(tlv_hdr);
2662 event_id = wow_get_wmi_eventid(wake_info->wake_reason, tag);
2663 if (!event_id) {
2664 WMA_LOGE(FL("Unable to find matching ID"));
2665 return -EINVAL;
2666 }
2667
2668 tlv_ok_status = wmitlv_check_and_pad_event_tlvs(
2669 handle, param_buf->wow_packet_buffer + 4,
2670 wow_buf_pkt_len, event_id,
2671 &wmi_cmd_struct_ptr);
2672
2673 if (tlv_ok_status != 0) {
2674 WMA_LOGE(FL("Invalid TLVs, Length:%d event_id:%d status: %d"),
2675 wow_buf_pkt_len, event_id, tlv_ok_status);
2676 return -EINVAL;
2677 }
2678 }
2679
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002680 switch (wake_info->wake_reason) {
2681 case WOW_REASON_AUTH_REQ_RECV:
2682 wake_lock_duration = WMA_AUTH_REQ_RECV_WAKE_LOCK_TIMEOUT;
2683 break;
2684
2685 case WOW_REASON_ASSOC_REQ_RECV:
2686 wake_lock_duration = WMA_ASSOC_REQ_RECV_WAKE_LOCK_DURATION;
2687 break;
2688
2689 case WOW_REASON_DEAUTH_RECVD:
2690 wake_lock_duration = WMA_DEAUTH_RECV_WAKE_LOCK_DURATION;
2691 break;
2692
2693 case WOW_REASON_DISASSOC_RECVD:
2694 wake_lock_duration = WMA_DISASSOC_RECV_WAKE_LOCK_DURATION;
2695 break;
2696
2697 case WOW_REASON_AP_ASSOC_LOST:
2698 wake_lock_duration = WMA_BMISS_EVENT_WAKE_LOCK_DURATION;
2699 WMA_LOGA("Beacon miss indication on vdev %x",
2700 wake_info->vdev_id);
2701 wma_beacon_miss_handler(wma, wake_info->vdev_id);
2702 break;
2703#ifdef FEATURE_WLAN_RA_FILTERING
2704 case WOW_REASON_RA_MATCH:
2705 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_RA_MATCH);
2706 break;
2707#endif /* FEATURE_WLAN_RA_FILTERING */
2708#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
2709 case WOW_REASON_HOST_AUTO_SHUTDOWN:
2710 wake_lock_duration = WMA_AUTO_SHUTDOWN_WAKE_LOCK_DURATION;
2711 WMA_LOGA("Received WOW Auto Shutdown trigger in suspend");
2712 if (wma_post_auto_shutdown_msg())
2713 return -EINVAL;
2714 break;
2715#endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
2716#ifdef FEATURE_WLAN_SCAN_PNO
2717 case WOW_REASON_NLOD:
2718 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_NLOD);
2719 node = &wma->interfaces[wake_info->vdev_id];
2720 if (node) {
2721 WMA_LOGD("NLO match happened");
2722 node->nlo_match_evt_received = true;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302723 qdf_wake_lock_timeout_acquire(&wma->pno_wake_lock,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002724 WMA_PNO_MATCH_WAKE_LOCK_TIMEOUT,
2725 WIFI_POWER_EVENT_WAKELOCK_PNO);
Srinivas Girigowdae80cea92015-11-23 11:33:57 -08002726 }
2727 break;
2728
2729 case WOW_REASON_NLO_SCAN_COMPLETE:
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07002730 WMA_LOGD("Host woken up due to pno scan complete reason");
2731 if (param_buf->wow_packet_buffer)
2732 wma_nlo_scan_cmp_evt_handler(handle,
2733 wmi_cmd_struct_ptr, wow_buf_pkt_len);
2734 else
2735 WMA_LOGD("No wow_packet_buffer present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002736 break;
2737#endif /* FEATURE_WLAN_SCAN_PNO */
2738
2739 case WOW_REASON_CSA_EVENT:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002740 WMA_LOGD("Host woken up because of CSA IE");
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07002741 wma_csa_offload_handler(handle, wmi_cmd_struct_ptr,
2742 wow_buf_pkt_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002743 break;
2744
2745#ifdef FEATURE_WLAN_LPHB
2746 case WOW_REASON_WLAN_HB:
2747 wma_lphb_handler(wma, (uint8_t *) param_buf->hb_indevt);
2748 break;
2749#endif /* FEATURE_WLAN_LPHB */
2750
2751 case WOW_REASON_HTT_EVENT:
2752 break;
2753 case WOW_REASON_PATTERN_MATCH_FOUND:
2754 wma_wow_wake_up_stats_display(wma);
2755 WMA_LOGD("Wake up for Rx packet, dump starting from ethernet hdr");
2756 if (param_buf->wow_packet_buffer) {
2757 /* First 4-bytes of wow_packet_buffer is the length */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302758 qdf_mem_copy((uint8_t *) &wow_buf_pkt_len,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002759 param_buf->wow_packet_buffer, 4);
2760 wma_wow_wake_up_stats(wma,
2761 param_buf->wow_packet_buffer + 4,
2762 wow_buf_pkt_len,
2763 WOW_REASON_PATTERN_MATCH_FOUND);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302764 qdf_trace_hex_dump(QDF_MODULE_ID_WMA,
2765 QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002766 param_buf->wow_packet_buffer + 4,
2767 wow_buf_pkt_len);
2768 } else {
2769 WMA_LOGE("No wow packet buffer present");
2770 }
2771 break;
2772
2773 case WOW_REASON_LOW_RSSI:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002774 /* WOW_REASON_LOW_RSSI is used for all roaming events.
2775 * WMI_ROAM_REASON_BETTER_AP, WMI_ROAM_REASON_BMISS,
2776 * WMI_ROAM_REASON_SUITABLE_AP will be handled by
2777 * wma_roam_event_callback().
2778 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002779 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_LOW_RSSI);
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07002780 WMA_LOGD("Host woken up because of roam event");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002781 if (param_buf->wow_packet_buffer) {
2782 /* Roam event is embedded in wow_packet_buffer */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002783 WMA_LOGD("wow_packet_buffer dump");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302784 qdf_trace_hex_dump(QDF_MODULE_ID_WMA,
2785 QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002786 param_buf->wow_packet_buffer,
2787 wow_buf_pkt_len);
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07002788 wma_roam_event_callback(handle, wmi_cmd_struct_ptr,
2789 wow_buf_pkt_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002790 } else {
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07002791 /*
2792 * No wow_packet_buffer means a better AP beacon
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002793 * will follow in a later event.
2794 */
2795 WMA_LOGD("Host woken up because of better AP beacon");
2796 }
2797 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002798 case WOW_REASON_CLIENT_KICKOUT_EVENT:
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07002799 WMA_LOGD("Host woken up because of sta_kickout event");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002800 if (param_buf->wow_packet_buffer) {
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07002801 WMA_LOGD("wow_packet_buffer dump");
2802 qdf_trace_hex_dump(QDF_MODULE_ID_WMA,
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302803 QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002804 param_buf->wow_packet_buffer, wow_buf_pkt_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002805 wma_peer_sta_kickout_event_handler(handle,
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07002806 wmi_cmd_struct_ptr, wow_buf_pkt_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002807 } else {
2808 WMA_LOGD("No wow_packet_buffer present");
2809 }
2810 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002811#ifdef FEATURE_WLAN_EXTSCAN
2812 case WOW_REASON_EXTSCAN:
2813 WMA_LOGD("Host woken up because of extscan reason");
2814 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_EXTSCAN);
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07002815 if (param_buf->wow_packet_buffer)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002816 wma_extscan_wow_event_callback(handle,
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07002817 wmi_cmd_struct_ptr, wow_buf_pkt_len);
2818 else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002819 WMA_LOGE("wow_packet_buffer is empty");
2820 break;
2821#endif
2822 case WOW_REASON_RSSI_BREACH_EVENT:
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07002823 wma_wow_wake_up_stats(wma, NULL, 0,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002824 WOW_REASON_RSSI_BREACH_EVENT);
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07002825 WMA_LOGD("Host woken up because of rssi breach reason");
2826 /* rssi breach event is embedded in wow_packet_buffer */
2827 if (param_buf->wow_packet_buffer)
2828 wma_rssi_breached_event_handler(handle,
2829 wmi_cmd_struct_ptr, wow_buf_pkt_len);
2830 else
2831 WMA_LOGD("No wow_packet_buffer present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002832 break;
Naveen Rawatc9f09522016-05-12 14:02:42 -07002833 case WOW_REASON_NAN_EVENT:
2834 WMA_LOGA("Host woken up due to NAN event reason");
2835 wma_nan_rsp_event_handler(handle,
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07002836 wmi_cmd_struct_ptr, wow_buf_pkt_len);
Naveen Rawatc9f09522016-05-12 14:02:42 -07002837 break;
Naveen Rawate82c1f32016-06-22 15:34:36 -07002838 case WOW_REASON_NAN_DATA:
2839 WMA_LOGD(FL("Host woken up for NAN data path event from FW"));
2840 if (param_buf->wow_packet_buffer) {
2841 wow_buf_pkt_len =
2842 *(uint32_t *)param_buf->wow_packet_buffer;
2843 WMA_LOGD(FL("wow_packet_buffer dump"));
2844 qdf_trace_hex_dump(QDF_MODULE_ID_WMA,
2845 QDF_TRACE_LEVEL_DEBUG,
2846 param_buf->wow_packet_buffer,
2847 wow_buf_pkt_len);
2848 wma_ndp_wow_event_callback(handle,
2849 (param_buf->wow_packet_buffer + 4),
2850 wow_buf_pkt_len);
2851 } else {
2852 WMA_LOGE(FL("wow_packet_buffer is empty"));
2853 }
2854 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002855 default:
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07002856 WMA_LOGE(FL("WOW reason %s(%d)- not handled"),
2857 wma_wow_wake_reason_str(wake_info->wake_reason),
2858 wake_info->wake_reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002859 break;
2860 }
2861
2862 if (wake_lock_duration) {
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302863 qdf_wake_lock_timeout_acquire(&wma->wow_wake_lock,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002864 wake_lock_duration,
2865 WIFI_POWER_EVENT_WAKELOCK_WOW);
2866 WMA_LOGA("Holding %d msec wake_lock", wake_lock_duration);
2867 }
2868
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07002869 wmitlv_free_allocated_event_tlvs(event_id, &wmi_cmd_struct_ptr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002870 return 0;
2871}
2872
2873/**
2874 * wma_pdev_resume_event_handler() - PDEV resume event handler
2875 * @handle: wma handle
2876 * @event: event data
2877 * @len: buffer length
2878 *
2879 * Return: 0 for success or error
2880 */
2881int wma_pdev_resume_event_handler(void *handle, uint8_t *event, uint32_t len)
2882{
2883 tp_wma_handle wma = (tp_wma_handle) handle;
2884
2885 WMA_LOGA("Received PDEV resume event");
2886
Anurag Chouhance0dc992016-02-16 18:18:03 +05302887 qdf_event_set(&wma->wma_resume_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002888
2889 return 0;
2890}
2891/**
2892 * wma_set_wow_bus_suspend() - set suspend flag
2893 * @wma: wma handle
2894 * @val: value
2895 *
2896 * Return: none
2897 */
2898static inline void wma_set_wow_bus_suspend(tp_wma_handle wma, int val)
2899{
2900
Anurag Chouhan8e0ccd32016-02-19 15:30:20 +05302901 qdf_atomic_set(&wma->is_wow_bus_suspended, val);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002902}
2903
2904
2905
2906/**
2907 * wma_add_wow_wakeup_event() - Configures wow wakeup events.
2908 * @wma: wma handle
2909 * @vdev_id: vdev id
2910 * @bitmap: Event bitmap
2911 * @enable: enable/disable
2912 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302913 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002914 */
Naveen Rawate82c1f32016-06-22 15:34:36 -07002915QDF_STATUS wma_add_wow_wakeup_event(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002916 uint32_t vdev_id,
2917 uint32_t bitmap,
2918 bool enable)
2919{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002920 int ret;
2921
Govind Singhaa64c242016-03-08 11:31:49 +05302922 ret = wmi_unified_add_wow_wakeup_event_cmd(wma->wmi_handle, vdev_id,
Rajeev Kumar4002e5b2016-06-22 12:01:15 -07002923 bitmap, enable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002924 if (ret) {
2925 WMA_LOGE("Failed to config wow wakeup event");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302926 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002927 }
2928
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302929 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002930}
2931
2932/**
2933 * wma_send_wow_patterns_to_fw() - Sends WOW patterns to FW.
2934 * @wma: wma handle
2935 * @vdev_id: vdev id
2936 * @ptrn_id: pattern id
2937 * @ptrn: pattern
2938 * @ptrn_len: pattern length
2939 * @ptrn_offset: pattern offset
2940 * @mask: mask
2941 * @mask_len: mask length
2942 * @user: true for user configured pattern and false for default pattern
2943 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302944 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002945 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302946static QDF_STATUS wma_send_wow_patterns_to_fw(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002947 uint8_t vdev_id, uint8_t ptrn_id,
2948 const uint8_t *ptrn, uint8_t ptrn_len,
2949 uint8_t ptrn_offset, const uint8_t *mask,
2950 uint8_t mask_len, bool user)
2951{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002952 struct wma_txrx_node *iface;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002953 int ret;
Govind Singhaa64c242016-03-08 11:31:49 +05302954 uint8_t default_patterns;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002955
2956 iface = &wma->interfaces[vdev_id];
Govind Singhaa64c242016-03-08 11:31:49 +05302957 default_patterns = iface->num_wow_default_patterns++;
2958 ret = wmi_unified_wow_patterns_to_fw_cmd(wma->wmi_handle,
2959 vdev_id, ptrn_id, ptrn,
2960 ptrn_len, ptrn_offset, mask,
2961 mask_len, user, default_patterns);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002962 if (ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002963 if (!user)
2964 iface->num_wow_default_patterns--;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302965 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002966 }
2967
2968 if (user)
2969 iface->num_wow_user_patterns++;
2970
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302971 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002972}
2973
2974/**
2975 * wma_wow_ap() - set WOW patterns in ap mode
2976 * @wma: wma handle
2977 * @vdev_id: vdev id
2978 *
2979 * Configures default WOW pattern for the given vdev_id which is in AP mode.
2980 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302981 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002982 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302983static QDF_STATUS wma_wow_ap(tp_wma_handle wma, uint8_t vdev_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002984{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302985 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002986 uint8_t arp_offset = 20;
2987 uint8_t mac_mask[IEEE80211_ADDR_LEN];
2988
2989 /* Setup unicast pkt pattern */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302990 qdf_mem_set(&mac_mask, IEEE80211_ADDR_LEN, 0xFF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002991 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
2992 wma->interfaces[vdev_id].addr,
2993 IEEE80211_ADDR_LEN, 0, mac_mask,
2994 IEEE80211_ADDR_LEN, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302995 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002996 WMA_LOGE("Failed to add WOW unicast pattern ret %d", ret);
2997 return ret;
2998 }
2999
3000 /*
3001 * Setup all ARP pkt pattern. This is dummy pattern hence the length
3002 * is zero
3003 */
3004 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
3005 arp_ptrn, 0, arp_offset, arp_mask, 0, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303006 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003007 WMA_LOGE("Failed to add WOW ARP pattern ret %d", ret);
3008 return ret;
3009 }
3010
3011 return ret;
3012}
3013
3014/**
Komal Seelam9764a842016-05-24 11:07:23 +05303015 * wma_configure_wow_ssdp() - API to configure WoW SSDP
3016 * @wma: WMA Handle
3017 * @vdev_id: Vdev Id
3018 *
3019 * API to configure SSDP pattern as WoW pattern
3020 *
3021 * Return: Success/Failure
3022 */
3023static QDF_STATUS wma_configure_wow_ssdp(tp_wma_handle wma, uint8_t vdev_id)
3024{
3025 QDF_STATUS status = QDF_STATUS_SUCCESS;
3026 uint8_t discvr_offset = 30;
3027
3028 status = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
3029 discvr_ptrn, sizeof(discvr_ptrn), discvr_offset,
3030 discvr_mask, sizeof(discvr_ptrn), false);
3031
3032 if (status != QDF_STATUS_SUCCESS)
3033 WMA_LOGE("Failed to add WOW mDNS/SSDP/LLMNR pattern");
3034
3035 return status;
3036}
3037
3038/**
3039 * wma_configure_mc_ssdp() - API to configure SSDP address as MC list
3040 * @wma: WMA Handle
3041 * @vdev_id: Vdev Id
3042 *
3043 * SSDP address 239.255.255.250 is converted to Multicast Mac address
3044 * and configure it to FW. Firmware will apply this pattern on the incoming
3045 * packets to filter them out during chatter/wow mode.
3046 *
3047 * Return: Success/Failure
3048 */
3049static QDF_STATUS wma_configure_mc_ssdp(tp_wma_handle wma, uint8_t vdev_id)
3050{
3051 WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param *cmd;
3052 wmi_buf_t buf;
3053 const tSirMacAddr ssdp_addr = {0x01, 0x00, 0x5e, 0x7f, 0xff, 0xfa};
3054 int ret;
3055 WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param fixed_param;
3056 uint32_t tag =
3057 WMITLV_TAG_STRUC_WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param;
3058
3059 buf = wmi_buf_alloc(wma->wmi_handle, sizeof(*cmd));
3060 if (!buf) {
3061 WMA_LOGE("%s No Memory for MC address", __func__);
3062 return QDF_STATUS_E_NOMEM;
3063 }
3064
3065 cmd = (WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param *) wmi_buf_data(buf);
3066
3067 WMITLV_SET_HDR(&cmd->tlv_header, tag,
3068 WMITLV_GET_STRUCT_TLVLEN(fixed_param));
3069
3070 cmd->action = WMI_MCAST_FILTER_SET;
3071 cmd->vdev_id = vdev_id;
3072 WMI_CHAR_ARRAY_TO_MAC_ADDR(ssdp_addr, &cmd->mcastbdcastaddr);
3073 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, sizeof(*cmd),
3074 WMI_SET_MCASTBCAST_FILTER_CMDID);
3075 if (ret != QDF_STATUS_SUCCESS) {
3076 WMA_LOGE("%s Failed to configure FW with SSDP MC address",
3077 __func__);
3078 wmi_buf_free(buf);
3079 return QDF_STATUS_E_FAILURE;
3080 }
3081
3082 return QDF_STATUS_SUCCESS;
3083}
3084
3085/**
3086 * wma_configure_ssdp() - API to Configure SSDP pattern to FW
3087 * @wma: WMA Handle
3088 * @vdev_id: VDEV ID
3089 *
3090 * Setup multicast pattern for mDNS 224.0.0.251, SSDP 239.255.255.250 and LLMNR
3091 * 224.0.0.252
3092 *
3093 * Return: Success/Failure.
3094 */
3095static QDF_STATUS wma_configure_ssdp(tp_wma_handle wma, uint8_t vdev_id)
3096{
3097 if (!wma->ssdp) {
3098 WMA_LOGD("mDNS, SSDP, LLMNR patterns are disabled from ini");
3099 return QDF_STATUS_SUCCESS;
3100 }
3101
3102 WMA_LOGD("%s, enable_mc_list:%d", __func__, wma->enable_mc_list);
3103
3104 if (wma->enable_mc_list)
3105 return wma_configure_mc_ssdp(wma, vdev_id);
3106
3107 return wma_configure_wow_ssdp(wma, vdev_id);
3108}
3109
3110/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003111 * wma_wow_sta() - set WOW patterns in sta mode
3112 * @wma: wma handle
3113 * @vdev_id: vdev id
3114 *
3115 * Configures default WOW pattern for the given vdev_id which is in sta mode.
3116 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303117 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003118 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303119static QDF_STATUS wma_wow_sta(tp_wma_handle wma, uint8_t vdev_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003120{
3121 uint8_t arp_offset = 12;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003122 uint8_t mac_mask[IEEE80211_ADDR_LEN];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303123 QDF_STATUS ret = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003124
3125 /* Setup unicast pkt pattern */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303126 qdf_mem_set(&mac_mask, IEEE80211_ADDR_LEN, 0xFF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003127 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
3128 wma->interfaces[vdev_id].addr,
3129 IEEE80211_ADDR_LEN, 0, mac_mask,
3130 IEEE80211_ADDR_LEN, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303131 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003132 WMA_LOGE("Failed to add WOW unicast pattern ret %d", ret);
3133 return ret;
3134 }
3135
Komal Seelam9764a842016-05-24 11:07:23 +05303136 ret = wma_configure_ssdp(wma, vdev_id);
3137 if (ret != QDF_STATUS_SUCCESS)
3138 WMA_LOGE("Failed to configure SSDP patterns to FW");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003139
3140 /* when arp offload or ns offloaded is disabled
3141 * from ini file, configure broad cast arp pattern
3142 * to fw, so that host can wake up
3143 */
3144 if (!(wma->ol_ini_info & 0x1)) {
3145 /* Setup all ARP pkt pattern */
3146 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
3147 arp_ptrn, sizeof(arp_ptrn), arp_offset,
3148 arp_mask, sizeof(arp_mask), false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303149 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003150 WMA_LOGE("Failed to add WOW ARP pattern");
3151 return ret;
3152 }
3153 }
3154
3155 /* for NS or NDP offload packets */
3156 if (!(wma->ol_ini_info & 0x2)) {
3157 /* Setup all NS pkt pattern */
3158 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
3159 ns_ptrn, sizeof(arp_ptrn), arp_offset,
3160 arp_mask, sizeof(arp_mask), false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303161 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003162 WMA_LOGE("Failed to add WOW NS pattern");
3163 return ret;
3164 }
3165 }
3166
3167 return ret;
3168}
3169
3170/**
3171 * wma_register_wow_default_patterns() - register default wow patterns with fw
3172 * @handle: Pointer to wma handle
3173 * @vdev_id: vdev id
3174 *
3175 * WoW default wake up pattern rule is:
3176 * - For STA & P2P CLI mode register for same STA specific wow patterns
3177 * - For SAP/P2P GO & IBSS mode register for same SAP specific wow patterns
3178 *
3179 * Return: none
3180 */
3181void wma_register_wow_default_patterns(WMA_HANDLE handle, uint8_t vdev_id)
3182{
3183 tp_wma_handle wma = handle;
3184 struct wma_txrx_node *iface;
3185
3186 if (vdev_id > wma->max_bssid) {
3187 WMA_LOGE("Invalid vdev id %d", vdev_id);
3188 return;
3189 }
3190 iface = &wma->interfaces[vdev_id];
3191
3192 if (iface->ptrn_match_enable) {
Houston Hoffman79b4af22015-10-06 12:01:08 -07003193 if (wma_is_vdev_in_beaconning_mode(wma, vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003194 /* Configure SAP/GO/IBSS mode default wow patterns */
3195 WMA_LOGI("Config SAP specific default wow patterns vdev_id %d",
3196 vdev_id);
3197 wma_wow_ap(wma, vdev_id);
3198 } else {
3199 /* Configure STA/P2P CLI mode default wow patterns */
3200 WMA_LOGI("Config STA specific default wow patterns vdev_id %d",
3201 vdev_id);
3202 wma_wow_sta(wma, vdev_id);
3203 if (wma->IsRArateLimitEnabled) {
3204 WMA_LOGI("Config STA RA limit wow patterns vdev_id %d",
3205 vdev_id);
3206 wma_wow_sta_ra_filter(wma, vdev_id);
3207 }
3208 }
3209 }
3210
3211 return;
3212}
3213
3214/**
3215 * wma_register_wow_wakeup_events() - register vdev specific wake events with fw
3216 * @handle: Pointer to wma handle
3217 * @vdev_id: vdev Id
3218 * @vdev_type: vdev type
3219 * @vdev_subtype: vdev sub type
3220 *
3221 * WoW wake up event rule is following:
3222 * 1) STA mode and P2P CLI mode wake up events are same
3223 * 2) SAP mode and P2P GO mode wake up events are same
3224 * 3) IBSS mode wake events are same as STA mode plus WOW_BEACON_EVENT
3225 *
3226 * Return: none
3227 */
3228void wma_register_wow_wakeup_events(WMA_HANDLE handle,
3229 uint8_t vdev_id,
3230 uint8_t vdev_type,
3231 uint8_t vdev_subtype)
3232{
3233 tp_wma_handle wma = handle;
3234 uint32_t event_bitmap;
3235
3236 WMA_LOGI("vdev_type %d vdev_subtype %d vdev_id %d", vdev_type,
3237 vdev_subtype, vdev_id);
3238
3239 if ((WMI_VDEV_TYPE_STA == vdev_type) ||
3240 ((WMI_VDEV_TYPE_AP == vdev_type) &&
3241 (WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE == vdev_subtype))) {
3242 /* Configure STA/P2P CLI mode specific default wake up events */
3243 event_bitmap = WMA_WOW_STA_WAKE_UP_EVENTS;
3244 WMA_LOGI("STA specific default wake up event 0x%x vdev id %d",
3245 event_bitmap, vdev_id);
3246 } else if (WMI_VDEV_TYPE_IBSS == vdev_type) {
3247 /* Configure IBSS mode specific default wake up events */
3248 event_bitmap = (WMA_WOW_STA_WAKE_UP_EVENTS |
3249 (1 << WOW_BEACON_EVENT));
3250 WMA_LOGI("IBSS specific default wake up event 0x%x vdev id %d",
3251 event_bitmap, vdev_id);
3252 } else if (WMI_VDEV_TYPE_AP == vdev_type) {
3253 /* Configure SAP/GO mode specific default wake up events */
3254 event_bitmap = WMA_WOW_SAP_WAKE_UP_EVENTS;
3255 WMA_LOGI("SAP specific default wake up event 0x%x vdev id %d",
3256 event_bitmap, vdev_id);
Naveen Rawate82c1f32016-06-22 15:34:36 -07003257 } else if (WMI_VDEV_TYPE_NDI == vdev_type) {
3258 /*
3259 * Configure NAN data path specific default wake up events.
3260 * Following routine sends the command to firmware.
3261 */
3262 wma_ndp_add_wow_wakeup_event(wma, vdev_id);
3263 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003264 } else {
3265 WMA_LOGE("unknown type %d subtype %d", vdev_type, vdev_subtype);
3266 return;
3267 }
3268
3269 wma_add_wow_wakeup_event(wma, vdev_id, event_bitmap, true);
3270
3271 return;
3272}
3273
3274/**
3275 * wma_enable_disable_wakeup_event() - Configures wow wakeup events
3276 * @wma: wma handle
3277 * @vdev_id: vdev id
3278 * @bitmap: Event bitmap
3279 * @enable: enable/disable
3280 *
3281 * Return: none
3282 */
3283void wma_enable_disable_wakeup_event(WMA_HANDLE handle,
3284 uint32_t vdev_id,
3285 uint32_t bitmap,
3286 bool enable)
3287{
3288 tp_wma_handle wma = handle;
3289
3290 WMA_LOGI("vdev_id %d wake up event 0x%x enable %d",
3291 vdev_id, bitmap, enable);
3292 wma_add_wow_wakeup_event(wma, vdev_id, bitmap, enable);
3293}
3294
3295/**
3296 * wma_enable_wow_in_fw() - wnable wow in fw
3297 * @wma: wma handle
3298 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303299 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003300 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303301QDF_STATUS wma_enable_wow_in_fw(WMA_HANDLE handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003302{
3303 tp_wma_handle wma = handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003304 int ret;
Komal Seelam3d202862016-02-24 18:43:24 +05303305 struct hif_opaque_softc *scn;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003306 int host_credits;
3307 int wmi_pending_cmds;
Govind Singhd76a5b02016-03-08 15:12:14 +05303308 struct wow_cmd_params param = {0};
3309
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003310#ifdef CONFIG_CNSS
Anurag Chouhan6d760662016-02-20 16:05:43 +05303311 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003312
3313 if (NULL == pMac) {
3314 WMA_LOGE("%s: Unable to get PE context", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303315 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003316 }
3317#endif /* CONFIG_CNSS */
3318
Anurag Chouhance0dc992016-02-16 18:18:03 +05303319 qdf_event_reset(&wma->target_suspend);
Houston Hoffmana769ed32016-04-14 17:02:51 -07003320 wma->wow_nack = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003321
3322 host_credits = wmi_get_host_credits(wma->wmi_handle);
3323 wmi_pending_cmds = wmi_get_pending_cmds(wma->wmi_handle);
3324
3325 WMA_LOGD("Credits:%d; Pending_Cmds: %d",
3326 host_credits, wmi_pending_cmds);
3327
3328 if (host_credits < WMI_WOW_REQUIRED_CREDITS) {
3329 WMA_LOGE("%s: Host Doesn't have enough credits to Post WMI_WOW_ENABLE_CMDID! "
3330 "Credits:%d, pending_cmds:%d\n", __func__, host_credits,
3331 wmi_pending_cmds);
3332#ifndef QCA_WIFI_3_0_EMU
3333 goto error;
3334#endif
3335 }
3336
Govind Singhd76a5b02016-03-08 15:12:14 +05303337 param.enable = true;
Houston Hoffman77f0e342016-07-25 13:28:10 -07003338 param.can_suspend_link = htc_can_suspend_link(wma->htc_handle);
Govind Singhd76a5b02016-03-08 15:12:14 +05303339 ret = wmi_unified_wow_enable_send(wma->wmi_handle, &param,
3340 WMA_WILDCARD_PDEV_ID);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003341 if (ret) {
3342 WMA_LOGE("Failed to enable wow in fw");
3343 goto error;
3344 }
3345
3346 wmi_set_target_suspend(wma->wmi_handle, true);
3347
Anurag Chouhance0dc992016-02-16 18:18:03 +05303348 if (qdf_wait_single_event(&wma->target_suspend,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003349 WMA_TGT_SUSPEND_COMPLETE_TIMEOUT)
Anurag Chouhance0dc992016-02-16 18:18:03 +05303350 != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003351 WMA_LOGE("Failed to receive WoW Enable Ack from FW");
3352 WMA_LOGE("Credits:%d; Pending_Cmds: %d",
3353 wmi_get_host_credits(wma->wmi_handle),
3354 wmi_get_pending_cmds(wma->wmi_handle));
Prashanth Bhatta9e143052015-12-04 11:56:47 -08003355 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003356#ifdef CONFIG_CNSS
Yue Ma455aff62015-10-20 18:29:16 -07003357 if (pMac->sme.enableSelfRecovery) {
3358 cds_trigger_recovery();
3359 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303360 QDF_BUG(0);
Yue Ma455aff62015-10-20 18:29:16 -07003361 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003362#else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303363 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003364#endif /* CONFIG_CNSS */
Yue Ma455aff62015-10-20 18:29:16 -07003365 } else {
3366 WMA_LOGE("%s: LOGP is in progress, ignore!", __func__);
3367 }
3368
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003369 wmi_set_target_suspend(wma->wmi_handle, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303370 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003371 }
3372
3373 if (wma->wow_nack) {
3374 WMA_LOGE("FW not ready to WOW");
3375 wmi_set_target_suspend(wma->wmi_handle, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303376 return QDF_STATUS_E_AGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003377 }
3378
3379 host_credits = wmi_get_host_credits(wma->wmi_handle);
3380 wmi_pending_cmds = wmi_get_pending_cmds(wma->wmi_handle);
3381
3382 if (host_credits < WMI_WOW_REQUIRED_CREDITS) {
3383 WMA_LOGE("%s: No Credits after HTC ACK:%d, pending_cmds:%d, "
3384 "cannot resume back", __func__, host_credits,
3385 wmi_pending_cmds);
3386 htc_dump_counter_info(wma->htc_handle);
Prashanth Bhatta9e143052015-12-04 11:56:47 -08003387 if (!cds_is_driver_recovering())
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303388 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003389 else
3390 WMA_LOGE("%s: SSR in progress, ignore no credit issue",
3391 __func__);
3392 }
3393
3394 WMA_LOGD("WOW enabled successfully in fw: credits:%d"
3395 "pending_cmds: %d", host_credits, wmi_pending_cmds);
3396
Anurag Chouhan6d760662016-02-20 16:05:43 +05303397 scn = cds_get_context(QDF_MODULE_ID_HIF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003398
3399 if (scn == NULL) {
3400 WMA_LOGE("%s: Failed to get HIF context", __func__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303401 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303402 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003403 }
3404
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003405 wma->wow.wow_enable_cmd_sent = true;
3406
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303407 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003408
3409error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303410 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003411}
3412
3413/**
3414 * wma_resume_req() - clear configured wow patterns in fw
3415 * @wma: wma handle
Houston Hoffmana76591b2015-11-10 16:52:05 -08003416 * @type: type of suspend
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003417 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303418 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003419 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05303420QDF_STATUS wma_resume_req(tp_wma_handle wma, enum qdf_suspend_type type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003421{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303422 if (type == QDF_SYSTEM_SUSPEND) {
Houston Hoffmana76591b2015-11-10 16:52:05 -08003423 wma->no_of_resume_ind++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003424
Houston Hoffmana76591b2015-11-10 16:52:05 -08003425 if (wma->no_of_resume_ind < wma_get_vdev_count(wma))
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303426 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003427
Houston Hoffmana76591b2015-11-10 16:52:05 -08003428 wma->no_of_resume_ind = 0;
3429 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003430
3431 /* Reset the DTIM Parameters */
3432 wma_set_resume_dtim(wma);
3433 /* need to reset if hif_pci_suspend_fails */
3434 wma_set_wow_bus_suspend(wma, 0);
3435 /* unpause the vdev if left paused and hif_pci_suspend fails */
3436 wma_unpause_vdev(wma);
3437
Houston Hoffman1460fa32015-11-18 02:36:30 -08003438 wmi_set_runtime_pm_inprogress(wma->wmi_handle, false);
3439
Houston Hoffmanc45db892015-11-13 19:59:25 -08003440 if (type == QDF_RUNTIME_SUSPEND)
3441 qdf_runtime_pm_allow_suspend(wma->wma_runtime_resume_lock);
3442
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303443 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003444}
3445
3446/**
3447 * wma_wow_delete_pattern() - delete wow pattern in target
3448 * @wma: wma handle
3449 * @ptrn_id: pattern id
3450 * @vdev_id: vdev id
3451 * @user: true for user pattern and false for default pattern
3452 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303453 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003454 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303455static QDF_STATUS wma_wow_delete_pattern(tp_wma_handle wma, uint8_t ptrn_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003456 uint8_t vdev_id, bool user)
3457{
Govind Singhaa64c242016-03-08 11:31:49 +05303458
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003459 struct wma_txrx_node *iface;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003460 int ret;
3461
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003462 iface = &wma->interfaces[vdev_id];
Govind Singhaa64c242016-03-08 11:31:49 +05303463 ret = wmi_unified_wow_delete_pattern_cmd(wma->wmi_handle, ptrn_id,
3464 vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003465 if (ret) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303466 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003467 }
3468
3469 if (user)
3470 iface->num_wow_user_patterns--;
3471
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303472 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003473}
3474
3475/**
3476 * wma_wow_add_pattern() - add wow pattern in target
3477 * @wma: wma handle
3478 * @ptrn: wow pattern
3479 *
3480 * This function does following:
3481 * 1) Delete all default patterns of the vdev
3482 * 2) Add received wow patterns for given vdev in target.
3483 *
3484 * Target is responsible for caching wow patterns accross multiple
3485 * suspend/resumes until the pattern is deleted by user
3486 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303487 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003488 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303489QDF_STATUS wma_wow_add_pattern(tp_wma_handle wma, struct wow_add_pattern *ptrn)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003490{
3491 uint8_t id;
3492 uint8_t bit_to_check, pos;
3493 struct wma_txrx_node *iface;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303494 QDF_STATUS ret = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003495 uint8_t new_mask[SIR_WOWL_BCAST_PATTERN_MAX_SIZE];
3496
3497 if (ptrn->session_id > wma->max_bssid) {
3498 WMA_LOGE("Invalid vdev id (%d)", ptrn->session_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303499 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003500 }
3501
3502 iface = &wma->interfaces[ptrn->session_id];
3503
3504 /* clear all default patterns cofigured by wma */
3505 for (id = 0; id < iface->num_wow_default_patterns; id++)
3506 wma_wow_delete_pattern(wma, id, ptrn->session_id, false);
3507
3508 iface->num_wow_default_patterns = 0;
3509
3510 WMA_LOGI("Add user passed wow pattern id %d vdev id %d",
3511 ptrn->pattern_id, ptrn->session_id);
3512 /*
3513 * Convert received pattern mask value from bit representation
3514 * to byte representation.
3515 *
3516 * For example, received value from umac,
3517 *
3518 * Mask value : A1 (equivalent binary is "1010 0001")
3519 * Pattern value : 12:00:13:00:00:00:00:44
3520 *
3521 * The value which goes to FW after the conversion from this
3522 * function (1 in mask value will become FF and 0 will
3523 * become 00),
3524 *
3525 * Mask value : FF:00:FF:00:0:00:00:FF
3526 * Pattern value : 12:00:13:00:00:00:00:44
3527 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303528 qdf_mem_zero(new_mask, sizeof(new_mask));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003529 for (pos = 0; pos < ptrn->pattern_size; pos++) {
3530 bit_to_check = (WMA_NUM_BITS_IN_BYTE - 1) -
3531 (pos % WMA_NUM_BITS_IN_BYTE);
3532 bit_to_check = 0x1 << bit_to_check;
3533 if (ptrn->pattern_mask[pos / WMA_NUM_BITS_IN_BYTE] &
3534 bit_to_check)
3535 new_mask[pos] = WMA_WOW_PTRN_MASK_VALID;
3536 }
3537
3538 ret = wma_send_wow_patterns_to_fw(wma, ptrn->session_id,
3539 ptrn->pattern_id,
3540 ptrn->pattern, ptrn->pattern_size,
3541 ptrn->pattern_byte_offset, new_mask,
3542 ptrn->pattern_size, true);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303543 if (ret != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003544 WMA_LOGE("Failed to add wow pattern %d", ptrn->pattern_id);
3545
3546 return ret;
3547}
3548
3549/**
3550 * wma_wow_delete_user_pattern() - delete user configured wow pattern in target
3551 * @wma: wma handle
3552 * @ptrn: wow pattern
3553 *
3554 * This function does following:
3555 * 1) Deletes a particular user configured wow pattern in target
3556 * 2) After deleting all user wow patterns add default wow patterns
3557 * specific to that vdev.
3558 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303559 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003560 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303561QDF_STATUS wma_wow_delete_user_pattern(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003562 struct wow_delete_pattern *pattern)
3563{
3564 struct wma_txrx_node *iface;
3565
3566 if (pattern->session_id > wma->max_bssid) {
3567 WMA_LOGE("Invalid vdev id %d", pattern->session_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303568 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003569 }
3570
3571 iface = &wma->interfaces[pattern->session_id];
3572 if (iface->num_wow_user_patterns <= 0) {
3573 WMA_LOGE("No valid user pattern. Num user pattern %u vdev %d",
3574 iface->num_wow_user_patterns, pattern->session_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303575 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003576 }
3577
3578 WMA_LOGI("Delete user passed wow pattern id %d total user pattern %d",
3579 pattern->pattern_id, iface->num_wow_user_patterns);
3580
3581 wma_wow_delete_pattern(wma, pattern->pattern_id,
3582 pattern->session_id, true);
3583
3584 /* configure default patterns once all user patterns are deleted */
3585 if (!iface->num_wow_user_patterns)
3586 wma_register_wow_default_patterns(wma, pattern->session_id);
3587
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303588 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003589}
3590
3591/**
3592 * wma_wow_enter() - store enable/disable status for pattern
3593 * @wma: wma handle
3594 * @info: wow parameters
3595 *
3596 * Records pattern enable/disable status locally. This choice will
3597 * take effect when the driver enter into suspend state.
3598 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303599 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003600 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303601QDF_STATUS wma_wow_enter(tp_wma_handle wma, tpSirHalWowlEnterParams info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003602{
3603 struct wma_txrx_node *iface;
3604
3605 WMA_LOGD("wow enable req received for vdev id: %d", info->sessionId);
3606
3607 if (info->sessionId > wma->max_bssid) {
3608 WMA_LOGE("Invalid vdev id (%d)", info->sessionId);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303609 qdf_mem_free(info);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303610 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003611 }
3612
3613 iface = &wma->interfaces[info->sessionId];
3614 iface->ptrn_match_enable = info->ucPatternFilteringEnable ?
3615 true : false;
3616 wma->wow.magic_ptrn_enable = info->ucMagicPktEnable ? true : false;
3617 wma->wow.deauth_enable = info->ucWowDeauthRcv ? true : false;
3618 wma->wow.disassoc_enable = info->ucWowDeauthRcv ? true : false;
3619 wma->wow.bmiss_enable = info->ucWowMaxMissedBeacons ? true : false;
3620
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303621 qdf_mem_free(info);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003622
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303623 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003624}
3625
3626/**
3627 * wma_wow_exit() - clear all wma states
3628 * @wma: wma handle
3629 * @info: wow params
3630 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303631 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003632 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303633QDF_STATUS wma_wow_exit(tp_wma_handle wma, tpSirHalWowlExitParams info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003634{
3635 struct wma_txrx_node *iface;
3636
3637 WMA_LOGD("wow disable req received for vdev id: %d", info->sessionId);
3638
3639 if (info->sessionId > wma->max_bssid) {
3640 WMA_LOGE("Invalid vdev id (%d)", info->sessionId);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303641 qdf_mem_free(info);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303642 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003643 }
3644
3645 iface = &wma->interfaces[info->sessionId];
3646 iface->ptrn_match_enable = false;
3647 wma->wow.magic_ptrn_enable = false;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303648 qdf_mem_free(info);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003649
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303650 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003651}
3652
3653/**
Houston Hoffmana76591b2015-11-10 16:52:05 -08003654 * wma_calculate_and_update_conn_state(): calculate each interfaces conn state
3655 * @wma: validated wma handle
3656 *
3657 * Identifies any vdev that is up and not in ap mode as connected.
3658 * stores this in the interfaces conn_state varible.
3659 */
3660void wma_calculate_and_update_conn_state(tp_wma_handle wma)
3661{
3662 int i;
3663 for (i = 0; i < wma->max_bssid; i++) {
3664 wma->interfaces[i].conn_state =
3665 !!(wma->interfaces[i].vdev_up &&
3666 !wma_is_vdev_in_ap_mode(wma, i));
3667 }
3668}
3669
3670/**
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003671 * wma_update_conn_state(): synchronize wma & hdd
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003672 * @wma: wma handle
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003673 * @conn_state: boolean array to populate
3674 * @len: validation parameter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003675 *
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003676 * populate interfaces conn_state with true if the interface
3677 * is a connected client and wow will configure a pattern.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003678 */
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003679void wma_update_conn_state(tp_wma_handle wma, uint32_t conn_mask)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003680{
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003681 int i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003682 for (i = 0; i < wma->max_bssid; i++) {
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003683 if (conn_mask & (1 << i))
3684 wma->interfaces[i].conn_state = true;
3685 else
3686 wma->interfaces[i].conn_state = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003687 }
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003688
3689 if (wma->wow.magic_ptrn_enable)
3690 return;
3691
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003692 for (i = 0; i < wma->max_bssid; i++) {
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003693 if (!wma->interfaces[i].ptrn_match_enable)
3694 wma->interfaces[i].conn_state = false;
3695 }
3696}
3697
3698/**
3699 * wma_is_beaconning_vdev_up(): check if a beaconning vdev is up
3700 * @wma: wma handle
3701 *
3702 * Return TRUE if beaconning vdev is up
3703 */
3704static inline
3705bool wma_is_beaconning_vdev_up(tp_wma_handle wma)
3706{
3707 int i;
3708 for (i = 0; i < wma->max_bssid; i++) {
3709 if (wma_is_vdev_in_beaconning_mode(wma, i)
3710 && wma->interfaces[i].vdev_up)
3711 return true;
3712 }
3713 return false;
3714}
3715
3716/**
3717 * wma_support_wow_for_beaconing: wow query for beaconning
3718 * @wma: wma handle
3719 *
3720 * Need to configure wow to enable beaconning offload when
3721 * a beaconing vdev is up and beaonning offload is configured.
3722 *
3723 * Return: true if we need to enable wow for beaconning offload
3724 */
3725static inline
3726bool wma_support_wow_for_beaconing(tp_wma_handle wma)
3727{
3728 if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
3729 WMI_SERVICE_BEACON_OFFLOAD)) {
3730 if (wma_is_beaconning_vdev_up(wma))
3731 return true;
3732 }
3733 return false;
3734}
3735
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003736#ifdef FEATURE_WLAN_SCAN_PNO
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003737/**
3738 * wma_is_pnoscan_in_progress(): check if a pnoscan is in progress
3739 * @wma: wma handle
3740 * @vdev_id: vdev_id
3741 *
3742 * Return: TRUE/FALSE
3743 */
3744static inline
3745bool wma_is_pnoscan_in_progress(tp_wma_handle wma, int vdev_id)
3746{
3747 return wma->interfaces[vdev_id].pno_in_progress;
3748}
Houston Hoffman345fa402015-12-16 11:28:51 -08003749
3750/**
3751 * wma_is_pnoscan_match_found(): check if a scan match was found
3752 * @wma: wma handle
3753 * @vdev_id: vdev_id
3754 *
3755 * Return: TRUE/FALSE
3756 */
3757static inline
3758bool wma_is_pnoscan_match_found(tp_wma_handle wma, int vdev_id)
3759{
3760 return wma->interfaces[vdev_id].nlo_match_evt_received;
3761}
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003762#else
3763/**
3764 * wma_is_pnoscan_in_progress(): dummy
3765 *
Houston Hoffman345fa402015-12-16 11:28:51 -08003766 * Return: False since no pnoscan cannot be in progress
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003767 * when feature flag is not defined.
3768 */
3769bool wma_is_pnoscan_in_progress(tp_wma_handle wma, int vdev_id)
3770{
3771 return FALSE;
3772}
Houston Hoffman345fa402015-12-16 11:28:51 -08003773
3774/**
3775 * wma_is_pnoscan_match_found(): dummy
3776 * @wma: wma handle
3777 * @vdev_id: vdev_id
3778 *
3779 * Return: False since no pnoscan cannot occur
3780 * when feature flag is not defined.
3781 */
3782static inline
3783bool wma_is_pnoscan_match_found(tp_wma_handle wma, int vdev_id)
3784{
3785 return FALSE;
3786}
Houston Hoffman61667962015-12-15 20:15:41 -08003787#endif
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003788
3789#ifdef FEATURE_WLAN_EXTSCAN
3790static inline
3791/**
3792 * wma_is_extscan_in_progress(): check if an extscan is in progress
3793 * @wma: wma handle
3794 * @vdev_id: vdev_id
3795 *
3796 * Return: TRUE/FALSvE
3797 */
3798bool wma_is_extscan_in_progress(tp_wma_handle wma, int vdev_id)
3799{
3800 return wma->interfaces[vdev_id].extscan_in_progress;
3801}
3802#else
3803/**
3804 * wma_is_extscan_in_progress(): dummy
3805 *
3806 * Return: False since no extscan can be in progress
3807 * when feature flag is not defined.
3808 */
3809bool wma_is_extscan_in_progress(tp_wma_handle wma, int vdev_id)
3810{
3811 return false;
3812}
3813#endif
3814
3815/**
Peng Xu8fdaa492016-06-22 10:20:47 -07003816 * wma_is_p2plo_in_progress(): check if P2P listen offload is in progress
3817 * @wma: wma handle
3818 * @vdev_id: vdev_id
3819 *
3820 * This function is to check if p2p listen offload is in progress,
3821 * true: p2p listen offload in progress
3822 * false: otherwise
3823 *
3824 * Return: TRUE/FALSE
3825 */
3826static inline
3827bool wma_is_p2plo_in_progress(tp_wma_handle wma, int vdev_id)
3828{
3829 return wma->interfaces[vdev_id].p2p_lo_in_progress;
3830}
3831
3832/**
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003833 * wma_is_wow_applicable(): should enable wow
3834 * @wma: wma handle
3835 *
3836 * Enable WOW if any one of the condition meets,
3837 * 1) Is any one of vdev in beaconning mode (in AP mode) ?
3838 * 2) Is any one of vdev in connected state (in STA mode) ?
3839 * 3) Is PNO in progress in any one of vdev ?
3840 * 4) Is Extscan in progress in any one of vdev ?
Peng Xu8fdaa492016-06-22 10:20:47 -07003841 * 5) Is P2P listen offload in any one of vdev?
Naveen Rawate82c1f32016-06-22 15:34:36 -07003842 * 6) Is any vdev in NAN data mode? BSS is already started at the
3843 * the time of device creation. It is ready to accept data
3844 * requests.
Rajeev Kumaraea89632016-02-02 18:02:32 -08003845 * If none of above conditions is true then return false
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003846 *
Rajeev Kumaraea89632016-02-02 18:02:32 -08003847 * Return: true if wma needs to configure wow false otherwise.
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003848 */
3849bool wma_is_wow_applicable(tp_wma_handle wma)
3850{
3851 int vdev_id;
3852 if (wma_support_wow_for_beaconing(wma)) {
3853 WMA_LOGD("vdev is in beaconning mode, enabling wow");
3854 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003855 }
3856
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003857 for (vdev_id = 0; vdev_id < wma->max_bssid; vdev_id++) {
3858 if (wma->interfaces[vdev_id].conn_state) {
3859 WMA_LOGD("STA is connected, enabling wow");
3860 return true;
3861 } else if (wma_is_pnoscan_in_progress(wma, vdev_id)) {
3862 WMA_LOGD("PNO is in progress, enabling wow");
3863 return true;
3864 } else if (wma_is_extscan_in_progress(wma, vdev_id)) {
3865 WMA_LOGD("EXT is in progress, enabling wow");
3866 return true;
Peng Xu8fdaa492016-06-22 10:20:47 -07003867 } else if (wma_is_p2plo_in_progress(wma, vdev_id)) {
3868 WMA_LOGD("P2P LO is in progress, enabling wow");
3869 return true;
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003870 }
Naveen Rawate82c1f32016-06-22 15:34:36 -07003871 if (WMA_IS_VDEV_IN_NDI_MODE(wma->interfaces, vdev_id)) {
3872 WMA_LOGD("vdev %d is in NAN data mode, enabling wow",
3873 vdev_id);
3874 return true;
3875 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003876 }
3877
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003878 WMA_LOGD("All vdev are in disconnected state and pno/extscan is not in progress, skipping wow");
Rajeev Kumaraea89632016-02-02 18:02:32 -08003879 return false;
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003880}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003881
Houston Hoffman345fa402015-12-16 11:28:51 -08003882/**
3883 * wma_configure_dynamic_wake_events(): configure dyanmic wake events
3884 * @wma: wma handle
3885 *
3886 * Some wake events need to be enabled dynamically. Controll those here.
3887 *
3888 * Return: none
3889 */
3890void wma_configure_dynamic_wake_events(tp_wma_handle wma)
3891{
3892 int vdev_id;
3893 int enable_mask;
3894 int disable_mask;
3895
3896 for (vdev_id = 0; vdev_id < wma->max_bssid; vdev_id++) {
3897 enable_mask = 0;
3898 disable_mask = 0;
3899
3900 if (wma_is_pnoscan_in_progress(wma, vdev_id)) {
3901 if (wma_is_pnoscan_match_found(wma, vdev_id))
3902 enable_mask |=
3903 (1 << WOW_NLO_SCAN_COMPLETE_EVENT);
3904 else
3905 disable_mask |=
3906 (1 << WOW_NLO_SCAN_COMPLETE_EVENT);
3907 }
3908
3909 if (enable_mask != 0)
3910 wma_enable_disable_wakeup_event(wma, vdev_id,
3911 enable_mask, true);
3912 if (disable_mask != 0)
3913 wma_enable_disable_wakeup_event(wma, vdev_id,
3914 disable_mask, false);
3915 }
3916}
3917
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003918#ifdef FEATURE_WLAN_LPHB
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003919/**
3920 * wma_apply_lphb(): apply cached LPHB settings
3921 * @wma: wma handle
3922 *
3923 * LPHB cache, if any item was enabled, should be
3924 * applied.
3925 */
3926static inline
3927void wma_apply_lphb(tp_wma_handle wma)
3928{
3929 int i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003930 WMA_LOGD("%s: checking LPHB cache", __func__);
3931 for (i = 0; i < 2; i++) {
3932 if (wma->wow.lphb_cache[i].params.lphbEnableReq.enable) {
3933 WMA_LOGD("%s: LPHB cache for item %d is marked as enable",
3934 __func__, i + 1);
3935 wma_lphb_conf_hbenable(wma, &(wma->wow.lphb_cache[i]),
3936 false);
3937 }
3938 }
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003939}
3940#else
3941void wma_apply_lphb(tp_wma_handle wma) {}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003942#endif /* FEATURE_WLAN_LPHB */
3943
Houston Hoffmana76591b2015-11-10 16:52:05 -08003944static void wma_notify_suspend_req_procesed(tp_wma_handle wma,
Anurag Chouhan6d760662016-02-20 16:05:43 +05303945 enum qdf_suspend_type type)
Houston Hoffmana76591b2015-11-10 16:52:05 -08003946{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303947 if (type == QDF_SYSTEM_SUSPEND)
Houston Hoffmana76591b2015-11-10 16:52:05 -08003948 wma_send_status_to_suspend_ind(wma, true);
Anurag Chouhan6d760662016-02-20 16:05:43 +05303949 else if (type == QDF_RUNTIME_SUSPEND)
Anurag Chouhance0dc992016-02-16 18:18:03 +05303950 qdf_event_set(&wma->runtime_suspend);
Houston Hoffmana76591b2015-11-10 16:52:05 -08003951}
3952
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003953/**
3954 * wma_suspend_req() - Handles suspend indication request received from umac.
3955 * @wma: wma handle
Houston Hoffmana76591b2015-11-10 16:52:05 -08003956 * @type: type of suspend
3957 *
3958 * The type controlls how we notify the indicator that the indication has
3959 * been processed
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003960 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303961 * Return: QDF status
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003962 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05303963QDF_STATUS wma_suspend_req(tp_wma_handle wma, enum qdf_suspend_type type)
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003964{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303965 if (type == QDF_RUNTIME_SUSPEND)
Houston Hoffman1460fa32015-11-18 02:36:30 -08003966 wmi_set_runtime_pm_inprogress(wma->wmi_handle, true);
3967
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003968 if (wma_is_wow_applicable(wma)) {
3969 WMA_LOGE("WOW Suspend");
3970 wma_apply_lphb(wma);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003971
Houston Hoffman345fa402015-12-16 11:28:51 -08003972 wma_configure_dynamic_wake_events(wma);
3973
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003974 wma->wow.wow_enable = true;
3975 wma->wow.wow_enable_cmd_sent = false;
3976 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003977
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003978 /* Set the Suspend DTIM Parameters */
3979 wma_set_suspend_dtim(wma);
Houston Hoffmana76591b2015-11-10 16:52:05 -08003980
3981 wma_notify_suspend_req_procesed(wma, type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003982
3983 /* to handle race between hif_pci_suspend and
3984 * unpause/pause tx handler
3985 */
3986 wma_set_wow_bus_suspend(wma, 1);
3987
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303988 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003989}
3990
3991/**
3992 * wma_send_host_wakeup_ind_to_fw() - send wakeup ind to fw
3993 * @wma: wma handle
3994 *
3995 * Sends host wakeup indication to FW. On receiving this indication,
3996 * FW will come out of WOW.
3997 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303998 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003999 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304000static QDF_STATUS wma_send_host_wakeup_ind_to_fw(tp_wma_handle wma)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004001{
Anurag Chouhance0dc992016-02-16 18:18:03 +05304002 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004003 int ret;
4004#ifdef CONFIG_CNSS
Anurag Chouhan6d760662016-02-20 16:05:43 +05304005 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004006 if (NULL == pMac) {
4007 WMA_LOGE("%s: Unable to get PE context", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304008 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004009 }
4010#endif /* CONFIG_CNSS */
4011
Anurag Chouhance0dc992016-02-16 18:18:03 +05304012 qdf_event_reset(&wma->wma_resume_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004013
Govind Singhaa64c242016-03-08 11:31:49 +05304014 ret = wmi_unified_host_wakeup_ind_to_fw_cmd(wma->wmi_handle);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004015 if (ret) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304016 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004017 }
4018
4019 WMA_LOGD("Host wakeup indication sent to fw");
4020
Anurag Chouhance0dc992016-02-16 18:18:03 +05304021 qdf_status = qdf_wait_single_event(&(wma->wma_resume_event),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004022 WMA_RESUME_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05304023 if (QDF_STATUS_SUCCESS != qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004024 WMA_LOGP("%s: Timeout waiting for resume event from FW",
4025 __func__);
4026 WMA_LOGP("%s: Pending commands %d credits %d", __func__,
4027 wmi_get_pending_cmds(wma->wmi_handle),
4028 wmi_get_host_credits(wma->wmi_handle));
Prashanth Bhatta9e143052015-12-04 11:56:47 -08004029 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004030#ifdef CONFIG_CNSS
4031 if (pMac->sme.enableSelfRecovery) {
4032 cds_trigger_recovery();
4033 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304034 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004035 }
4036#else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304037 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004038#endif /* CONFIG_CNSS */
4039 } else {
4040 WMA_LOGE("%s: SSR in progress, ignore resume timeout",
4041 __func__);
4042 }
4043 } else {
4044 WMA_LOGD("Host wakeup received");
4045 }
4046
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304047 if (QDF_STATUS_SUCCESS == qdf_status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004048 wmi_set_target_suspend(wma->wmi_handle, false);
4049
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304050 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004051}
4052
4053/**
4054 * wma_disable_wow_in_fw() - Disable wow in PCIe resume context.
4055 * @handle: wma handle
4056 *
4057 * Return: 0 for success or error code
4058 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304059QDF_STATUS wma_disable_wow_in_fw(WMA_HANDLE handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004060{
4061 tp_wma_handle wma = handle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304062 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004063
4064 if (!wma->wow.wow_enable || !wma->wow.wow_enable_cmd_sent)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304065 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004066
4067 ret = wma_send_host_wakeup_ind_to_fw(wma);
4068
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304069 if (ret != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004070 return ret;
4071
4072 wma->wow.wow_enable = false;
4073 wma->wow.wow_enable_cmd_sent = false;
4074
4075 /* To allow the tx pause/unpause events */
4076 wma_set_wow_bus_suspend(wma, 0);
4077 /* Unpause the vdev as we are resuming */
4078 wma_unpause_vdev(wma);
4079
4080 return ret;
4081}
4082
4083#ifdef WLAN_FEATURE_LPSS
4084/**
4085 * wma_is_lpass_enabled() - check if lpass is enabled
4086 * @handle: Pointer to wma handle
4087 *
4088 * WoW is needed if LPASS or NaN feature is enabled in INI because
4089 * target can't wake up itself if its put in PDEV suspend when LPASS
4090 * or NaN features are supported
4091 *
4092 * Return: true if lpass is enabled else false
4093 */
4094bool static wma_is_lpass_enabled(tp_wma_handle wma)
4095{
4096 if (wma->is_lpass_enabled)
4097 return true;
4098 else
4099 return false;
4100}
4101#else
4102bool static wma_is_lpass_enabled(tp_wma_handle wma)
4103{
4104 return false;
4105}
4106#endif
4107
4108#ifdef WLAN_FEATURE_NAN
4109/**
4110 * wma_is_nan_enabled() - check if NaN is enabled
4111 * @handle: Pointer to wma handle
4112 *
4113 * WoW is needed if LPASS or NaN feature is enabled in INI because
4114 * target can't wake up itself if its put in PDEV suspend when LPASS
4115 * or NaN features are supported
4116 *
4117 * Return: true if NaN is enabled else false
4118 */
4119bool static wma_is_nan_enabled(tp_wma_handle wma)
4120{
4121 if (wma->is_nan_enabled)
4122 return true;
4123 else
4124 return false;
4125}
4126#else
4127bool static wma_is_nan_enabled(tp_wma_handle wma)
4128{
4129 return false;
4130}
4131#endif
4132
4133/**
4134 * wma_is_wow_mode_selected() - check if wow needs to be enabled in fw
4135 * @handle: Pointer to wma handle
4136 *
4137 * If lpass is enabled then always do wow else check wow_enable config
4138 *
4139 * Return: true is wow mode is needed else false
4140 */
Houston Hoffmana76591b2015-11-10 16:52:05 -08004141bool wma_is_wow_mode_selected(WMA_HANDLE handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004142{
4143 tp_wma_handle wma = (tp_wma_handle) handle;
4144
4145 if (wma_is_lpass_enabled(wma)) {
4146 WMA_LOGD("LPASS is enabled select WoW");
4147 return true;
4148 } else if (wma_is_nan_enabled(wma)) {
4149 WMA_LOGD("NAN is enabled select WoW");
4150 return true;
4151 } else {
4152 WMA_LOGD("WoW enable %d", wma->wow.wow_enable);
4153 return wma->wow.wow_enable;
4154 }
4155}
4156
4157/**
4158 * wma_del_ts_req() - send DELTS request to fw
4159 * @wma: wma handle
4160 * @msg: delts params
4161 *
4162 * Return: none
4163 */
4164void wma_del_ts_req(tp_wma_handle wma, tDelTsParams *msg)
4165{
Govind Singhaa64c242016-03-08 11:31:49 +05304166 if (wmi_unified_del_ts_cmd(wma->wmi_handle,
4167 msg->sessionId,
4168 TID_TO_WME_AC(msg->userPrio))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004169 WMA_LOGP("%s: Failed to send vdev DELTS command", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004170 }
Govind Singhaa64c242016-03-08 11:31:49 +05304171
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004172#ifdef WLAN_FEATURE_ROAM_OFFLOAD
4173 if (msg->setRICparams == true)
4174 wma_set_ric_req(wma, msg, false);
4175#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
4176
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304177 qdf_mem_free(msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004178}
4179
4180/**
4181 * wma_aggr_qos_req() - send aggr qos request to fw
4182 * @wma: handle to wma
4183 * @pAggrQosRspMsg - combined struct for all ADD_TS requests.
4184 *
4185 * A function to handle WMA_AGGR_QOS_REQ. This will send out
4186 * ADD_TS requestes to firmware in loop for all the ACs with
4187 * active flow.
4188 *
4189 * Return: none
4190 */
4191void wma_aggr_qos_req(tp_wma_handle wma,
4192 tAggrAddTsParams *pAggrQosRspMsg)
4193{
Govind Singhaa64c242016-03-08 11:31:49 +05304194 wmi_unified_aggr_qos_cmd(wma->wmi_handle,
4195 (struct aggr_add_ts_param *)pAggrQosRspMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004196 /* send reponse to upper layers from here only. */
4197 wma_send_msg(wma, WMA_AGGR_QOS_RSP, pAggrQosRspMsg, 0);
4198}
4199
4200/**
4201 * wma_add_ts_req() - send ADDTS request to fw
4202 * @wma: wma handle
4203 * @msg: ADDTS params
4204 *
4205 * Return: none
4206 */
4207void wma_add_ts_req(tp_wma_handle wma, tAddTsParams *msg)
4208{
Govind Singhaa64c242016-03-08 11:31:49 +05304209 struct add_ts_param cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004210
4211#ifdef FEATURE_WLAN_ESE
4212 /*
4213 * msmt_interval is in unit called TU (1 TU = 1024 us)
4214 * max value of msmt_interval cannot make resulting
4215 * interval_miliseconds overflow 32 bit
4216 */
4217 uint32_t intervalMiliseconds;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304218 ol_txrx_pdev_handle pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004219 if (NULL == pdev) {
4220 WMA_LOGE("%s: Failed to get pdev", __func__);
4221 goto err;
4222 }
4223
4224 intervalMiliseconds = (msg->tsm_interval * 1024) / 1000;
4225
4226 ol_tx_set_compute_interval(pdev, intervalMiliseconds);
4227#endif /* FEATURE_WLAN_ESE */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304228 msg->status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004229
Govind Singhaa64c242016-03-08 11:31:49 +05304230
4231 cmd.sme_session_id = msg->sme_session_id;
4232 cmd.tspec.tsinfo.traffic.userPrio =
4233 TID_TO_WME_AC(msg->tspec.tsinfo.traffic.userPrio);
4234 cmd.tspec.mediumTime = msg->tspec.mediumTime;
4235 if (wmi_unified_add_ts_cmd(wma->wmi_handle, &cmd))
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304236 msg->status = QDF_STATUS_E_FAILURE;
Govind Singhaa64c242016-03-08 11:31:49 +05304237
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004238#ifdef WLAN_FEATURE_ROAM_OFFLOAD
4239 if (msg->setRICparams == true)
4240 wma_set_ric_req(wma, msg, true);
4241#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
4242
4243err:
4244 wma_send_msg(wma, WMA_ADD_TS_RSP, msg, 0);
4245}
4246
4247/**
4248 * wma_enable_disable_packet_filter() - enable/disable packet filter in target
4249 * @wma: Pointer to wma handle
4250 * @vdev_id: vdev id
4251 * @enable: Flag to enable/disable packet filter
4252 *
4253 * Return: 0 for success or error code
4254 */
4255static int wma_enable_disable_packet_filter(tp_wma_handle wma,
4256 uint8_t vdev_id, bool enable)
4257{
Govind Singhaa64c242016-03-08 11:31:49 +05304258 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004259
Govind Singhaa64c242016-03-08 11:31:49 +05304260 ret = wmi_unified_enable_disable_packet_filter_cmd(wma->wmi_handle,
4261 vdev_id, enable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004262 if (ret)
4263 WMA_LOGE("Failed to send packet filter wmi cmd to fw");
4264
4265 return ret;
4266}
4267
4268/**
4269 * wma_config_packet_filter() - configure packet filter in target
4270 * @wma: Pointer to wma handle
4271 * @vdev_id: vdev id
4272 * @rcv_filter_param: Packet filter parameters
4273 * @filter_id: Filter id
4274 * @enable: Flag to add/delete packet filter configuration
4275 *
4276 * Return: 0 for success or error code
4277 */
4278static int wma_config_packet_filter(tp_wma_handle wma,
4279 uint8_t vdev_id, tSirRcvPktFilterCfgType *rcv_filter_param,
4280 uint8_t filter_id, bool enable)
4281{
Govind Singhaa64c242016-03-08 11:31:49 +05304282 int err;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004283
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004284 /* send the command along with data */
Govind Singhaa64c242016-03-08 11:31:49 +05304285 err = wmi_unified_config_packet_filter_cmd(wma->wmi_handle,
4286 vdev_id, (struct rcv_pkt_filter_config *)rcv_filter_param,
4287 filter_id, enable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004288 if (err) {
4289 WMA_LOGE("Failed to send pkt_filter cmd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004290 return -EIO;
4291 }
4292
4293 /* Enable packet filter */
4294 if (enable)
4295 wma_enable_disable_packet_filter(wma, vdev_id, true);
4296
4297 return 0;
4298}
4299
4300/**
4301 * wma_process_receive_filter_set_filter_req() - enable packet filter
4302 * @wma_handle: wma handle
4303 * @rcv_filter_param: filter params
4304 *
4305 * Return: 0 for success or error code
4306 */
4307int wma_process_receive_filter_set_filter_req(tp_wma_handle wma,
4308 tSirRcvPktFilterCfgType *rcv_filter_param)
4309{
4310 int ret = 0;
4311 uint8_t vdev_id;
4312
4313 /* Get the vdev id */
Srinivas Girigowda98530492015-11-20 17:39:24 -08004314 if (!wma_find_vdev_by_bssid(wma,
4315 rcv_filter_param->bssid.bytes, &vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004316 WMA_LOGE("vdev handle is invalid for %pM",
Srinivas Girigowda98530492015-11-20 17:39:24 -08004317 rcv_filter_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004318 return -EINVAL;
4319 }
4320
4321 ret = wma_config_packet_filter(wma, vdev_id, rcv_filter_param,
4322 rcv_filter_param->filterId, true);
4323
4324 return ret;
4325}
4326
4327/**
4328 * wma_process_receive_filter_clear_filter_req() - disable packet filter
4329 * @wma_handle: wma handle
4330 * @rcv_clear_param: filter params
4331 *
4332 * Return: 0 for success or error code
4333 */
4334int wma_process_receive_filter_clear_filter_req(tp_wma_handle wma,
4335 tSirRcvFltPktClearParam *rcv_clear_param)
4336{
4337 int ret = 0;
4338 uint8_t vdev_id;
4339
4340 /* Get the vdev id */
Srinivas Girigowda98530492015-11-20 17:39:24 -08004341 if (!wma_find_vdev_by_bssid(wma,
4342 rcv_clear_param->bssid.bytes, &vdev_id)) {
4343 WMA_LOGE("vdev handle is invalid for %pM",
4344 rcv_clear_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004345 return -EINVAL;
4346 }
4347
4348 ret = wma_config_packet_filter(wma, vdev_id, NULL,
4349 rcv_clear_param->filterId, false);
4350
4351 return ret;
4352}
4353
4354#ifdef FEATURE_WLAN_ESE
4355
4356#define TSM_DELAY_HISTROGRAM_BINS 4
4357/**
4358 * wma_process_tsm_stats_req() - process tsm stats request
4359 * @wma_handler - handle to wma
4360 * @pTsmStatsMsg - TSM stats struct that needs to be populated and
4361 * passed in message.
4362 *
4363 * A parallel function to WMA_ProcessTsmStatsReq for pronto. This
4364 * function fetches stats from data path APIs and post
4365 * WMA_TSM_STATS_RSP msg back to LIM.
4366 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304367 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004368 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304369QDF_STATUS wma_process_tsm_stats_req(tp_wma_handle wma_handler,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004370 void *pTsmStatsMsg)
4371{
4372 uint8_t counter;
4373 uint32_t queue_delay_microsec = 0;
4374 uint32_t tx_delay_microsec = 0;
4375 uint16_t packet_count = 0;
4376 uint16_t packet_loss_count = 0;
4377 tpAniTrafStrmMetrics pTsmMetric = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004378 tpAniGetTsmStatsReq pStats = (tpAniGetTsmStatsReq) pTsmStatsMsg;
4379 tpAniGetTsmStatsRsp pTsmRspParams = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004380 int tid = pStats->tid;
4381 /*
4382 * The number of histrogram bin report by data path api are different
4383 * than required by TSM, hence different (6) size array used
4384 */
4385 uint16_t bin_values[QCA_TX_DELAY_HIST_REPORT_BINS] = { 0, };
4386
Anurag Chouhan6d760662016-02-20 16:05:43 +05304387 ol_txrx_pdev_handle pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004388
4389 if (NULL == pdev) {
4390 WMA_LOGE("%s: Failed to get pdev", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304391 qdf_mem_free(pTsmStatsMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304392 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004393 }
4394
4395 /* get required values from data path APIs */
4396 ol_tx_delay(pdev, &queue_delay_microsec, &tx_delay_microsec, tid);
4397 ol_tx_delay_hist(pdev, bin_values, tid);
4398 ol_tx_packet_count(pdev, &packet_count, &packet_loss_count, tid);
4399
Srinivas Girigowda515a9ef2015-12-11 11:00:48 -08004400 pTsmRspParams = qdf_mem_malloc(sizeof(*pTsmRspParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004401 if (NULL == pTsmRspParams) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304402 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304403 "%s: QDF MEM Alloc Failure", __func__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304404 QDF_ASSERT(0);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304405 qdf_mem_free(pTsmStatsMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304406 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004407 }
4408 pTsmRspParams->staId = pStats->staId;
4409 pTsmRspParams->rc = eSIR_FAILURE;
4410 pTsmRspParams->tsmStatsReq = pStats;
4411 pTsmMetric = &pTsmRspParams->tsmMetrics;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004412 /* populate pTsmMetric */
4413 pTsmMetric->UplinkPktQueueDly = queue_delay_microsec;
4414 /* store only required number of bin values */
4415 for (counter = 0; counter < TSM_DELAY_HISTROGRAM_BINS; counter++) {
4416 pTsmMetric->UplinkPktQueueDlyHist[counter] =
4417 bin_values[counter];
4418 }
4419 pTsmMetric->UplinkPktTxDly = tx_delay_microsec;
4420 pTsmMetric->UplinkPktLoss = packet_loss_count;
4421 pTsmMetric->UplinkPktCount = packet_count;
4422
4423 /*
4424 * No need to populate roaming delay and roaming count as they are
4425 * being populated just before sending IAPP frame out
4426 */
4427 /* post this message to LIM/PE */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004428 wma_send_msg(wma_handler, WMA_TSM_STATS_RSP, (void *)pTsmRspParams, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304429 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004430}
4431
4432#endif /* FEATURE_WLAN_ESE */
4433
4434/**
4435 * wma_add_clear_mcbc_filter() - set mcast filter command to fw
4436 * @wma_handle: wma handle
4437 * @vdev_id: vdev id
4438 * @multicastAddr: mcast address
4439 * @clearList: clear list flag
4440 *
4441 * Return: 0 for success or error code
4442 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304443static QDF_STATUS wma_add_clear_mcbc_filter(tp_wma_handle wma_handle,
4444 uint8_t vdev_id,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304445 struct qdf_mac_addr multicast_addr,
Srinivas Girigowda98530492015-11-20 17:39:24 -08004446 bool clearList)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004447{
Himanshu Agarwal44195412016-03-09 13:03:54 +05304448 return wmi_unified_add_clear_mcbc_filter_cmd(wma_handle->wmi_handle,
4449 vdev_id, multicast_addr, clearList);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004450}
4451
4452/**
Rajeev Kumaref96e152016-04-15 18:10:33 -07004453 * wma_config_enhance_multicast_offload() - config enhance multicast offload
4454 * @wma_handle: wma handle
4455 * @vdev_id: vdev id
4456 * @action: enable or disable enhance multicast offload
4457 *
4458 * Return: none
4459 */
4460static void wma_config_enhance_multicast_offload(tp_wma_handle wma_handle,
4461 uint8_t vdev_id,
4462 uint8_t action)
4463{
4464 int status;
4465 wmi_buf_t buf;
4466 wmi_config_enhanced_mcast_filter_cmd_fixed_param *cmd;
4467
4468 buf = wmi_buf_alloc(wma_handle->wmi_handle, sizeof(*cmd));
4469 if (!buf) {
4470 WMA_LOGE("Failed to allocate buffer to send set key cmd");
4471 return;
4472 }
4473
4474 cmd = (wmi_config_enhanced_mcast_filter_cmd_fixed_param *)
4475 wmi_buf_data(buf);
4476
4477 WMITLV_SET_HDR(&cmd->tlv_header,
4478 WMITLV_TAG_STRUC_wmi_config_enhanced_mcast_filter_fixed_param,
4479 WMITLV_GET_STRUCT_TLVLEN(wmi_config_enhanced_mcast_filter_cmd_fixed_param));
4480
4481 cmd->vdev_id = vdev_id;
4482 cmd->enable = ((0 == action) ? ENHANCED_MCAST_FILTER_DISABLED :
4483 ENHANCED_MCAST_FILTER_ENABLED);
4484
4485 WMA_LOGD("%s: config enhance multicast offload action %d for vdev %d",
4486 __func__, action, vdev_id);
4487
4488 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
4489 sizeof(*cmd), WMI_CONFIG_ENHANCED_MCAST_FILTER_CMDID);
4490 if (status) {
4491 qdf_nbuf_free(buf);
4492 WMA_LOGE("%s:Failed to send WMI_CONFIG_ENHANCED_MCAST_FILTER_CMDID",
4493 __func__);
4494 }
4495
4496 return;
4497}
4498
4499/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004500 * wma_process_mcbc_set_filter_req() - process mcbc set filter request
4501 * @wma_handle: wma handle
4502 * @mcbc_param: mcbc params
4503 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304504 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004505 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304506QDF_STATUS wma_process_mcbc_set_filter_req(tp_wma_handle wma_handle,
Anurag Chouhance0dc992016-02-16 18:18:03 +05304507 tSirRcvFltMcAddrList *mcbc_param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004508{
4509 uint8_t vdev_id = 0;
4510 int i;
4511
4512 if (mcbc_param->ulMulticastAddrCnt <= 0) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004513 WMA_LOGW("Number of multicast addresses is 0");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304514 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004515 }
4516
Srinivas Girigowda98530492015-11-20 17:39:24 -08004517 if (!wma_find_vdev_by_addr(wma_handle,
4518 mcbc_param->self_macaddr.bytes, &vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004519 WMA_LOGE("%s: Failed to find vdev id for %pM", __func__,
Srinivas Girigowda98530492015-11-20 17:39:24 -08004520 mcbc_param->bssid.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304521 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004522 }
Rajeev Kumaref96e152016-04-15 18:10:33 -07004523
4524 /*
4525 * Configure enhance multicast offload feature for filtering out
4526 * multicast IP data packets transmitted using unicast MAC address
4527 */
4528 if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap,
4529 WMI_SERVICE_ENHANCED_MCAST_FILTER)) {
4530 WMA_LOGD("%s: FW supports enhance multicast offload", __func__);
4531 wma_config_enhance_multicast_offload(wma_handle, vdev_id,
4532 mcbc_param->action);
4533 } else {
4534 WMA_LOGD("%s: FW does not support enhance multicast offload",
4535 __func__);
4536 }
4537
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004538 /* set mcbc_param->action to clear MCList and reset
4539 * to configure the MCList in FW
4540 */
4541
4542 for (i = 0; i < mcbc_param->ulMulticastAddrCnt; i++) {
4543 wma_add_clear_mcbc_filter(wma_handle, vdev_id,
4544 mcbc_param->multicastAddr[i],
4545 (mcbc_param->action == 0));
4546 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304547 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004548}
4549
4550#ifdef WLAN_FEATURE_GTK_OFFLOAD
4551#define GTK_OFFLOAD_ENABLE 0
4552#define GTK_OFFLOAD_DISABLE 1
4553
4554/**
4555 * wma_gtk_offload_status_event() - GTK offload status event handler
4556 * @handle: wma handle
4557 * @event: event buffer
4558 * @len: buffer length
4559 *
4560 * Return: 0 for success or error code
4561 */
4562int wma_gtk_offload_status_event(void *handle, uint8_t *event,
4563 uint32_t len)
4564{
4565 tp_wma_handle wma = (tp_wma_handle) handle;
4566 WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param *status;
4567 WMI_GTK_OFFLOAD_STATUS_EVENTID_param_tlvs *param_buf;
4568 tpSirGtkOffloadGetInfoRspParams resp;
4569 cds_msg_t cds_msg;
4570 uint8_t *bssid;
4571
4572 WMA_LOGD("%s Enter", __func__);
4573
4574 param_buf = (WMI_GTK_OFFLOAD_STATUS_EVENTID_param_tlvs *) event;
4575 if (!param_buf) {
4576 WMA_LOGE("param_buf is NULL");
4577 return -EINVAL;
4578 }
4579
4580 status = (WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param *) param_buf->fixed_param;
4581
4582 if (len < sizeof(WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param)) {
4583 WMA_LOGE("Invalid length for GTK status");
4584 return -EINVAL;
4585 }
4586 bssid = wma_find_bssid_by_vdev_id(wma, status->vdev_id);
4587 if (!bssid) {
4588 WMA_LOGE("invalid bssid for vdev id %d", status->vdev_id);
4589 return -ENOENT;
4590 }
4591
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304592 resp = qdf_mem_malloc(sizeof(*resp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004593 if (!resp) {
4594 WMA_LOGE("%s: Failed to alloc response", __func__);
4595 return -ENOMEM;
4596 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304597 qdf_mem_zero(resp, sizeof(*resp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004598 resp->mesgType = eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP;
4599 resp->mesgLen = sizeof(*resp);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304600 resp->ulStatus = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004601 resp->ulTotalRekeyCount = status->refresh_cnt;
4602 /* TODO: Is the total rekey count and GTK rekey count same? */
4603 resp->ulGTKRekeyCount = status->refresh_cnt;
4604
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304605 qdf_mem_copy(&resp->ullKeyReplayCounter, &status->replay_counter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004606 GTK_REPLAY_COUNTER_BYTES);
4607
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304608 qdf_mem_copy(resp->bssid.bytes, bssid, IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004609
4610#ifdef IGTK_OFFLOAD
4611 /* TODO: Is the refresh count same for GTK and IGTK? */
4612 resp->ulIGTKRekeyCount = status->refresh_cnt;
4613#endif /* IGTK_OFFLOAD */
4614
4615 cds_msg.type = eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP;
4616 cds_msg.bodyptr = (void *)resp;
4617 cds_msg.bodyval = 0;
4618
4619 if (cds_mq_post_message(CDS_MQ_ID_SME, (cds_msg_t *) &cds_msg)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304620 != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004621 WMA_LOGE("Failed to post GTK response to SME");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304622 qdf_mem_free(resp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004623 return -EINVAL;
4624 }
4625
4626 WMA_LOGD("GTK: got target status with replay counter "
4627 "%02x%02x%02x%02x%02x%02x%02x%02x. vdev %d "
4628 "Refresh GTK %d times exchanges since last set operation",
4629 status->replay_counter[0],
4630 status->replay_counter[1],
4631 status->replay_counter[2],
4632 status->replay_counter[3],
4633 status->replay_counter[4],
4634 status->replay_counter[5],
4635 status->replay_counter[6],
4636 status->replay_counter[7],
4637 status->vdev_id, status->refresh_cnt);
4638
4639 WMA_LOGD("%s Exit", __func__);
4640
4641 return 0;
4642}
4643
4644/**
4645 * wma_send_gtk_offload_req() - send GTK offload command to fw
4646 * @wma: wma handle
4647 * @vdev_id: vdev id
4648 * @params: GTK offload parameters
4649 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304650 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004651 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304652static QDF_STATUS wma_send_gtk_offload_req(tp_wma_handle wma, uint8_t vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004653 tpSirGtkOffloadParams params)
4654{
Himanshu Agarwal44195412016-03-09 13:03:54 +05304655 struct gtk_offload_params offload_params = {0};
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304656 QDF_STATUS status = QDF_STATUS_SUCCESS;
Himanshu Agarwal44195412016-03-09 13:03:54 +05304657 bool enable_offload;
4658 uint32_t gtk_offload_opcode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004659
4660 WMA_LOGD("%s Enter", __func__);
4661
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004662 /* Request target to enable GTK offload */
4663 if (params->ulFlags == GTK_OFFLOAD_ENABLE) {
Himanshu Agarwal44195412016-03-09 13:03:54 +05304664 gtk_offload_opcode = GTK_OFFLOAD_ENABLE_OPCODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004665 wma->wow.gtk_err_enable[vdev_id] = true;
4666
4667 /* Copy the keys and replay counter */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304668 qdf_mem_copy(offload_params.aKCK, params->aKCK,
4669 GTK_OFFLOAD_KCK_BYTES);
4670 qdf_mem_copy(offload_params.aKEK, params->aKEK,
4671 GTK_OFFLOAD_KEK_BYTES);
4672 qdf_mem_copy(&offload_params.ullKeyReplayCounter,
4673 &params->ullKeyReplayCounter, GTK_REPLAY_COUNTER_BYTES);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004674 } else {
4675 wma->wow.gtk_err_enable[vdev_id] = false;
Himanshu Agarwal44195412016-03-09 13:03:54 +05304676 gtk_offload_opcode = GTK_OFFLOAD_DISABLE_OPCODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004677 }
4678
Himanshu Agarwal44195412016-03-09 13:03:54 +05304679 enable_offload = params->ulFlags;
4680
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004681 /* send the wmi command */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304682 status = wmi_unified_send_gtk_offload_cmd(wma->wmi_handle,
4683 vdev_id, &offload_params,
4684 enable_offload,
4685 gtk_offload_opcode);
4686 if (QDF_IS_STATUS_ERROR(status))
4687 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004688
Himanshu Agarwal44195412016-03-09 13:03:54 +05304689 WMA_LOGD("VDEVID: %d, GTK_FLAGS: x%x", vdev_id, gtk_offload_opcode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004690out:
4691 WMA_LOGD("%s Exit", __func__);
4692 return status;
4693}
4694
4695/**
4696 * wma_process_gtk_offload_req() - process GTK offload req from umac
4697 * @handle: wma handle
4698 * @params: GTK offload params
4699 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304700 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004701 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304702QDF_STATUS wma_process_gtk_offload_req(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004703 tpSirGtkOffloadParams params)
4704{
4705 uint8_t vdev_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304706 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004707
4708 WMA_LOGD("%s Enter", __func__);
4709
4710 /* Get the vdev id */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08004711 if (!wma_find_vdev_by_bssid(wma, params->bssid.bytes, &vdev_id)) {
4712 WMA_LOGE("vdev handle is invalid for %pM", params->bssid.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304713 status = QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004714 goto out;
4715 }
4716
4717 /* Validate vdev id */
Naveen Rawate9fb4ce2016-06-27 15:36:10 -07004718 if (vdev_id >= WMA_MAX_SUPPORTED_BSS) {
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08004719 WMA_LOGE("invalid vdev_id %d for %pM", vdev_id,
4720 params->bssid.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304721 status = QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004722 goto out;
4723 }
4724
4725 if ((params->ulFlags == GTK_OFFLOAD_ENABLE) &&
4726 (wma->wow.gtk_err_enable[vdev_id] == true)) {
4727 WMA_LOGE("%s GTK Offload already enabled. Disable it first "
4728 "vdev_id %d", __func__, vdev_id);
4729 params->ulFlags = GTK_OFFLOAD_DISABLE;
4730 status = wma_send_gtk_offload_req(wma, vdev_id, params);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304731 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004732 WMA_LOGE("%s Failed to disable GTK Offload", __func__);
4733 goto out;
4734 }
4735 WMA_LOGD("%s Enable GTK Offload again with updated inputs",
4736 __func__);
4737 params->ulFlags = GTK_OFFLOAD_ENABLE;
4738 }
4739 status = wma_send_gtk_offload_req(wma, vdev_id, params);
4740out:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304741 qdf_mem_free(params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004742 WMA_LOGD("%s Exit", __func__);
4743 return status;
4744}
4745
4746/**
4747 * wma_process_gtk_offload_getinfo_req() - send GTK offload cmd to fw
4748 * @wma: wma handle
4749 * @params: GTK offload params
4750 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304751 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004752 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304753QDF_STATUS wma_process_gtk_offload_getinfo_req(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004754 tpSirGtkOffloadGetInfoRspParams params)
4755{
4756 uint8_t vdev_id;
Himanshu Agarwal44195412016-03-09 13:03:54 +05304757 uint64_t offload_req_opcode;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304758 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004759
4760 WMA_LOGD("%s Enter", __func__);
4761
4762 /* Get the vdev id */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08004763 if (!wma_find_vdev_by_bssid(wma, params->bssid.bytes, &vdev_id)) {
4764 WMA_LOGE("vdev handle is invalid for %pM", params->bssid.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304765 status = QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004766 goto out;
4767 }
4768
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004769 /* Request for GTK offload status */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304770 offload_req_opcode = GTK_OFFLOAD_REQUEST_STATUS_OPCODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004771
4772 /* send the wmi command */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304773 status = wmi_unified_process_gtk_offload_getinfo_cmd(wma->wmi_handle,
4774 vdev_id, offload_req_opcode);
4775
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004776out:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304777 qdf_mem_free(params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004778 WMA_LOGD("%s Exit", __func__);
4779 return status;
4780}
4781#endif /* WLAN_FEATURE_GTK_OFFLOAD */
4782
4783/**
4784 * wma_enable_arp_ns_offload() - enable ARP NS offload
4785 * @wma: wma handle
4786 * @tpSirHostOffloadReq: offload request
Govind Singhaa64c242016-03-08 11:31:49 +05304787 * @arp_only: flag
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004788 *
4789 * To configure ARP NS off load data to firmware
4790 * when target goes to wow mode.
4791 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304792 * Return: QDF Status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004793 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304794QDF_STATUS wma_enable_arp_ns_offload(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004795 tpSirHostOffloadReq
Govind Singhaa64c242016-03-08 11:31:49 +05304796 pHostOffloadParams, bool arp_only)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004797{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004798 int32_t res;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004799 uint8_t vdev_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004800
4801 /* Get the vdev id */
Srinivas Girigowdab084b552015-11-24 12:39:12 -08004802 if (!wma_find_vdev_by_bssid(wma, pHostOffloadParams->bssid.bytes,
4803 &vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004804 WMA_LOGE("vdev handle is invalid for %pM",
Srinivas Girigowdab084b552015-11-24 12:39:12 -08004805 pHostOffloadParams->bssid.bytes);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304806 qdf_mem_free(pHostOffloadParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304807 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004808 }
4809
4810 if (!wma->interfaces[vdev_id].vdev_up) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004811 WMA_LOGE("vdev %d is not up skipping arp/ns offload", vdev_id);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304812 qdf_mem_free(pHostOffloadParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304813 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004814 }
4815
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004816
Govind Singhaa64c242016-03-08 11:31:49 +05304817 res = wmi_unified_enable_arp_ns_offload_cmd(wma->wmi_handle,
4818 (struct host_offload_req_param *)pHostOffloadParams,
4819 arp_only,
4820 vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004821 if (res) {
4822 WMA_LOGE("Failed to enable ARP NDP/NSffload");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304823 qdf_mem_free(pHostOffloadParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304824 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004825 }
4826
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304827 qdf_mem_free(pHostOffloadParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304828 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004829}
4830
4831/**
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08004832 * wma_process_cesium_enable_ind() - enables cesium functionality in target
4833 * @wma: wma handle
4834 *
4835 * Return: QDF status
4836 */
4837QDF_STATUS wma_process_cesium_enable_ind(tp_wma_handle wma)
4838{
4839 QDF_STATUS ret;
4840 int32_t vdev_id;
4841
4842 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
4843 if (vdev_id < 0) {
4844 WMA_LOGE("%s: IBSS vdev does not exist could not enable cesium",
4845 __func__);
4846 return QDF_STATUS_E_FAILURE;
4847 }
4848
4849 /* Send enable cesium command to target */
4850 WMA_LOGE("Enable cesium in target for vdevId %d ", vdev_id);
4851 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
4852 WMI_VDEV_PARAM_ENABLE_RMC, 1);
4853 if (ret) {
4854 WMA_LOGE("Enable cesium failed for vdevId %d", vdev_id);
4855 return QDF_STATUS_E_FAILURE;
4856 }
4857 return QDF_STATUS_SUCCESS;
4858}
4859
4860/**
4861 * wma_process_get_peer_info_req() - sends get peer info cmd to target
4862 * @wma: wma handle
4863 * @preq: get peer info request
4864 *
4865 * Return: QDF status
4866 */
4867QDF_STATUS wma_process_get_peer_info_req
4868 (tp_wma_handle wma, tSirIbssGetPeerInfoReqParams *pReq)
4869{
4870 int32_t ret;
4871 uint8_t *p;
4872 uint16_t len;
4873 wmi_buf_t buf;
4874 int32_t vdev_id;
4875 ol_txrx_pdev_handle pdev;
4876 struct ol_txrx_peer_t *peer;
4877 uint8_t peer_mac[IEEE80211_ADDR_LEN];
4878 wmi_peer_info_req_cmd_fixed_param *p_get_peer_info_cmd;
4879 uint8_t bcast_mac[IEEE80211_ADDR_LEN] = { 0xff, 0xff, 0xff,
4880 0xff, 0xff, 0xff };
4881
4882 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
4883 if (vdev_id < 0) {
4884 WMA_LOGE("%s: IBSS vdev does not exist could not get peer info",
4885 __func__);
4886 return QDF_STATUS_E_FAILURE;
4887 }
4888
4889 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
4890 if (NULL == pdev) {
4891 WMA_LOGE("%s: Failed to get pdev context", __func__);
4892 return QDF_STATUS_E_FAILURE;
4893 }
4894
4895 if (0xFF == pReq->staIdx) {
4896 /*get info for all peers */
4897 qdf_mem_copy(peer_mac, bcast_mac, IEEE80211_ADDR_LEN);
4898 } else {
4899 /*get info for a single peer */
4900 peer = ol_txrx_peer_find_by_local_id(pdev, pReq->staIdx);
4901 if (!peer) {
4902 WMA_LOGE("%s: Failed to get peer handle using peer id %d",
4903 __func__, pReq->staIdx);
4904 return QDF_STATUS_E_FAILURE;
4905 }
4906 WMA_LOGE("%s: staIdx %d peer mac: 0x%2x:0x%2x:0x%2x:0x%2x:0x%2x:0x%2x",
4907 __func__, pReq->staIdx, peer->mac_addr.raw[0],
4908 peer->mac_addr.raw[1], peer->mac_addr.raw[2],
4909 peer->mac_addr.raw[3], peer->mac_addr.raw[4],
4910 peer->mac_addr.raw[5]);
4911 qdf_mem_copy(peer_mac, peer->mac_addr.raw, IEEE80211_ADDR_LEN);
4912 }
4913
4914 len = sizeof(wmi_peer_info_req_cmd_fixed_param);
4915 buf = wmi_buf_alloc(wma->wmi_handle, len);
4916 if (!buf) {
4917 WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__);
4918 return QDF_STATUS_E_FAILURE;
4919 }
4920
4921 p = (uint8_t *) wmi_buf_data(buf);
4922 qdf_mem_zero(p, len);
4923 p_get_peer_info_cmd = (wmi_peer_info_req_cmd_fixed_param *) p;
4924
4925 WMITLV_SET_HDR(&p_get_peer_info_cmd->tlv_header,
4926 WMITLV_TAG_STRUC_wmi_peer_info_req_cmd_fixed_param,
4927 WMITLV_GET_STRUCT_TLVLEN
4928 (wmi_peer_info_req_cmd_fixed_param));
4929
4930 p_get_peer_info_cmd->vdev_id = vdev_id;
4931 WMI_CHAR_ARRAY_TO_MAC_ADDR(peer_mac,
4932 &p_get_peer_info_cmd->peer_mac_address);
4933
4934 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
4935 WMI_PEER_INFO_REQ_CMDID);
4936
4937 WMA_LOGE("IBSS get peer info cmd sent len: %d, vdev %d"
4938 " command id: %d, status: %d", len,
4939 p_get_peer_info_cmd->vdev_id, WMI_PEER_INFO_REQ_CMDID, ret);
4940
4941 return QDF_STATUS_SUCCESS;
4942}
4943
4944/**
4945 * wma_process_tx_fail_monitor_ind() - sends tx fail monitor cmd to target
4946 * @wma: wma handle
4947 * @pReq: tx fail monitor command params
4948 *
4949 * Return: QDF status
4950 */
4951QDF_STATUS wma_process_tx_fail_monitor_ind
4952 (tp_wma_handle wma, tAniTXFailMonitorInd *pReq)
4953{
4954 QDF_STATUS ret;
4955 int32_t vdev_id;
4956
4957 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
4958 if (vdev_id < 0) {
4959 WMA_LOGE("%s: IBSS vdev does not exist could not send fast tx fail"
4960 " monitor indication message to target", __func__);
4961 return QDF_STATUS_E_FAILURE;
4962 }
4963
4964 /* Send enable cesium command to target */
4965 WMA_LOGE("send fast tx fail monitor ind cmd target for vdevId %d val %d",
4966 vdev_id, pReq->tx_fail_count);
4967
4968 if (0 == pReq->tx_fail_count) {
4969 wma->hddTxFailCb = NULL;
4970 } else {
4971 wma->hddTxFailCb = pReq->txFailIndCallback;
4972 }
4973 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
4974 WMI_VDEV_PARAM_SET_IBSS_TX_FAIL_CNT_THR,
4975 pReq->tx_fail_count);
4976 if (ret) {
4977 WMA_LOGE("tx fail monitor failed for vdevId %d", vdev_id);
4978 return QDF_STATUS_E_FAILURE;
4979 }
4980
4981 return QDF_STATUS_SUCCESS;
4982}
4983
4984/**
4985 * wma_process_rmc_enable_ind() - enables RMC functionality in target
4986 * @wma: wma handle
4987 *
4988 * Return: QDF status
4989 */
4990QDF_STATUS wma_process_rmc_enable_ind(tp_wma_handle wma)
4991{
4992 int ret;
4993 uint8_t *p;
4994 uint16_t len;
4995 wmi_buf_t buf;
4996 int32_t vdev_id;
4997 wmi_rmc_set_mode_cmd_fixed_param *p_rmc_enable_cmd;
4998
4999 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
5000 if (vdev_id < 0) {
5001 WMA_LOGE("%s: IBSS vdev does not exist could not enable RMC",
5002 __func__);
5003 return QDF_STATUS_E_FAILURE;
5004 }
5005
5006 len = sizeof(wmi_rmc_set_mode_cmd_fixed_param);
5007 buf = wmi_buf_alloc(wma->wmi_handle, len);
5008 if (!buf) {
5009 WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__);
5010 return QDF_STATUS_E_FAILURE;
5011 }
5012
5013 p = (uint8_t *) wmi_buf_data(buf);
5014 qdf_mem_zero(p, len);
5015 p_rmc_enable_cmd = (wmi_rmc_set_mode_cmd_fixed_param *) p;
5016
5017 WMITLV_SET_HDR(&p_rmc_enable_cmd->tlv_header,
5018 WMITLV_TAG_STRUC_wmi_rmc_set_mode_cmd_fixed_param,
5019 WMITLV_GET_STRUCT_TLVLEN
5020 (wmi_rmc_set_mode_cmd_fixed_param));
5021
5022 p_rmc_enable_cmd->vdev_id = vdev_id;
5023 p_rmc_enable_cmd->enable_rmc = WMI_RMC_MODE_ENABLED;
5024
5025 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
5026 WMI_RMC_SET_MODE_CMDID);
5027
5028 WMA_LOGE("Enable RMC cmd sent len: %d, vdev %d" " command id: %d,"
5029 " status: %d", len, p_rmc_enable_cmd->vdev_id,
5030 WMI_RMC_SET_MODE_CMDID, ret);
5031
5032 return QDF_STATUS_SUCCESS;
5033}
5034
5035/**
5036 * wma_process_rmc_disable_ind() - disables rmc functionality in target
5037 * @wma: wma handle
5038 *
5039 * Return: QDF status
5040 */
5041QDF_STATUS wma_process_rmc_disable_ind(tp_wma_handle wma)
5042{
5043 int ret;
5044 uint8_t *p;
5045 uint16_t len;
5046 wmi_buf_t buf;
5047 int32_t vdev_id;
5048 wmi_rmc_set_mode_cmd_fixed_param *p_rmc_disable_cmd;
5049
5050 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
5051 if (vdev_id < 0) {
5052 WMA_LOGE("%s: IBSS vdev does not exist could not disable RMC",
5053 __func__);
5054 return QDF_STATUS_E_FAILURE;
5055 }
5056
5057 len = sizeof(wmi_rmc_set_mode_cmd_fixed_param);
5058 buf = wmi_buf_alloc(wma->wmi_handle, len);
5059 if (!buf) {
5060 WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__);
5061 return QDF_STATUS_E_FAILURE;
5062 }
5063
5064 p = (uint8_t *) wmi_buf_data(buf);
5065 qdf_mem_zero(p, len);
5066 p_rmc_disable_cmd = (wmi_rmc_set_mode_cmd_fixed_param *) p;
5067
5068 WMITLV_SET_HDR(&p_rmc_disable_cmd->tlv_header,
5069 WMITLV_TAG_STRUC_wmi_rmc_set_mode_cmd_fixed_param,
5070 WMITLV_GET_STRUCT_TLVLEN
5071 (wmi_rmc_set_mode_cmd_fixed_param));
5072
5073 p_rmc_disable_cmd->vdev_id = vdev_id;
5074 p_rmc_disable_cmd->enable_rmc = WMI_RMC_MODE_DISABLED;
5075
5076 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
5077 WMI_RMC_SET_MODE_CMDID);
5078
5079 WMA_LOGE("Disable RMC cmd sent len: %d, vdev %d" " command id: %d,"
5080 " status: %d", len, p_rmc_disable_cmd->vdev_id,
5081 WMI_RMC_SET_MODE_CMDID, ret);
5082
5083 return QDF_STATUS_SUCCESS;
5084}
5085
5086/**
5087 * wma_process_rmc_action_period_ind() - sends RMC action period to target
5088 * @wma: wma handle
5089 *
5090 * Return: QDF status
5091 */
5092QDF_STATUS wma_process_rmc_action_period_ind(tp_wma_handle wma)
5093{
5094 int ret;
5095 uint8_t *p;
5096 uint16_t len;
5097 uint32_t val;
5098 wmi_buf_t buf;
5099 int32_t vdev_id;
5100 wmi_rmc_set_action_period_cmd_fixed_param *p_rmc_cmd;
5101 struct sAniSirGlobal *mac = cds_get_context(QDF_MODULE_ID_PE);
5102
5103 if (NULL == mac) {
5104 WMA_LOGE("%s: MAC mac does not exist", __func__);
5105 return QDF_STATUS_E_FAILURE;
5106 }
5107
5108 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
5109 if (vdev_id < 0) {
5110 WMA_LOGE("%s: IBSS vdev does not exist could not send"
5111 " RMC action period to target", __func__);
5112 return QDF_STATUS_E_FAILURE;
5113 }
5114
5115 len = sizeof(wmi_rmc_set_action_period_cmd_fixed_param);
5116 buf = wmi_buf_alloc(wma->wmi_handle, len);
5117 if (!buf) {
5118 WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__);
5119 return QDF_STATUS_E_FAILURE;
5120 }
5121
5122 p = (uint8_t *) wmi_buf_data(buf);
5123 qdf_mem_zero(p, len);
5124 p_rmc_cmd = (wmi_rmc_set_action_period_cmd_fixed_param *) p;
5125
5126 WMITLV_SET_HDR(&p_rmc_cmd->tlv_header,
5127 WMITLV_TAG_STRUC_wmi_rmc_set_action_period_cmd_fixed_param,
5128 WMITLV_GET_STRUCT_TLVLEN
5129 (wmi_rmc_set_action_period_cmd_fixed_param));
5130
5131 if (wlan_cfg_get_int(mac, WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY, &val)
5132 != eSIR_SUCCESS) {
5133 WMA_LOGE("Failed to get value for RMC action period using default");
5134 val = WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_STADEF;
5135 }
5136
5137 p_rmc_cmd->vdev_id = vdev_id;
5138 p_rmc_cmd->periodicity_msec = val;
5139
5140 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
5141 WMI_RMC_SET_ACTION_PERIOD_CMDID);
5142
5143 WMA_LOGE("RMC action period %d cmd sent len: %d, vdev %d"
5144 " command id: %d, status: %d", p_rmc_cmd->periodicity_msec,
5145 len, p_rmc_cmd->vdev_id, WMI_RMC_SET_ACTION_PERIOD_CMDID, ret);
5146
5147 return QDF_STATUS_SUCCESS;
5148}
5149
5150/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005151 * wma_process_add_periodic_tx_ptrn_ind - add periodic tx ptrn
5152 * @handle: wma handle
5153 * @pAddPeriodicTxPtrnParams: tx ptrn params
5154 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305155 * Retrun: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005156 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305157QDF_STATUS wma_process_add_periodic_tx_ptrn_ind(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005158 tSirAddPeriodicTxPtrn *
5159 pAddPeriodicTxPtrnParams)
5160{
5161 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Himanshu Agarwal44195412016-03-09 13:03:54 +05305162 struct periodic_tx_pattern params;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005163 uint8_t vdev_id;
Himanshu Agarwal44195412016-03-09 13:03:54 +05305164
5165 qdf_mem_set(&params, sizeof(struct periodic_tx_pattern), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005166
5167 if (!wma_handle || !wma_handle->wmi_handle) {
5168 WMA_LOGE("%s: WMA is closed, can not issue fw add pattern cmd",
5169 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305170 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005171 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005172
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005173 if (!wma_find_vdev_by_addr(wma_handle,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005174 pAddPeriodicTxPtrnParams->mac_address.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005175 &vdev_id)) {
5176 WMA_LOGE("%s: Failed to find vdev id for %pM", __func__,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005177 pAddPeriodicTxPtrnParams->mac_address.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305178 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005179 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005180
Himanshu Agarwal44195412016-03-09 13:03:54 +05305181 params.ucPtrnId = pAddPeriodicTxPtrnParams->ucPtrnId;
5182 params.ucPtrnSize = pAddPeriodicTxPtrnParams->ucPtrnSize;
5183 params.usPtrnIntervalMs = pAddPeriodicTxPtrnParams->usPtrnIntervalMs;
5184 qdf_mem_copy(&params.mac_address,
5185 &pAddPeriodicTxPtrnParams->mac_address,
5186 sizeof(struct qdf_mac_addr));
5187 qdf_mem_copy(params.ucPattern, pAddPeriodicTxPtrnParams->ucPattern,
5188 params.ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005189
Himanshu Agarwal44195412016-03-09 13:03:54 +05305190 return wmi_unified_process_add_periodic_tx_ptrn_cmd(
5191 wma_handle->wmi_handle, &params, vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005192}
5193
5194/**
5195 * wma_process_del_periodic_tx_ptrn_ind - del periodic tx ptrn
5196 * @handle: wma handle
5197 * @pDelPeriodicTxPtrnParams: tx ptrn params
5198 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305199 * Retrun: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005200 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305201QDF_STATUS wma_process_del_periodic_tx_ptrn_ind(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005202 tSirDelPeriodicTxPtrn *
5203 pDelPeriodicTxPtrnParams)
5204{
5205 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005206 uint8_t vdev_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005207
5208 if (!wma_handle || !wma_handle->wmi_handle) {
5209 WMA_LOGE("%s: WMA is closed, can not issue Del Pattern cmd",
5210 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305211 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005212 }
Himanshu Agarwal44195412016-03-09 13:03:54 +05305213
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005214 if (!wma_find_vdev_by_addr(wma_handle,
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08005215 pDelPeriodicTxPtrnParams->mac_address.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005216 &vdev_id)) {
5217 WMA_LOGE("%s: Failed to find vdev id for %pM", __func__,
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08005218 pDelPeriodicTxPtrnParams->mac_address.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305219 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005220 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005221
Himanshu Agarwal44195412016-03-09 13:03:54 +05305222 return wmi_unified_process_del_periodic_tx_ptrn_cmd(
5223 wma_handle->wmi_handle, vdev_id,
5224 pDelPeriodicTxPtrnParams->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005225}
5226
5227#ifdef WLAN_FEATURE_STATS_EXT
5228/**
5229 * wma_stats_ext_req() - request ext stats from fw
5230 * @wma_ptr: wma handle
5231 * @preq: stats ext params
5232 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305233 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005234 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305235QDF_STATUS wma_stats_ext_req(void *wma_ptr, tpStatsExtRequest preq)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005236{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005237 tp_wma_handle wma = (tp_wma_handle) wma_ptr;
Krishna Kumaar Natarajan1b909d72016-06-06 15:02:18 -07005238 struct stats_ext_params *params;
5239 size_t params_len;
5240 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005241
Himanshu Agarwal44195412016-03-09 13:03:54 +05305242 if (!wma) {
5243 WMA_LOGE("%s: wma handle is NULL", __func__);
5244 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005245 }
5246
Krishna Kumaar Natarajan1b909d72016-06-06 15:02:18 -07005247 params_len = sizeof(*params) + preq->request_data_len;
5248 params = qdf_mem_malloc(params_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005249
Krishna Kumaar Natarajan1b909d72016-06-06 15:02:18 -07005250 if (params == NULL) {
5251 WMA_LOGE(FL("memory allocation failed"));
5252 return QDF_STATUS_E_NOMEM;
5253 }
5254
5255 params->vdev_id = preq->vdev_id;
5256 params->request_data_len = preq->request_data_len;
5257 if (preq->request_data_len > 0)
5258 qdf_mem_copy(params->request_data, preq->request_data,
5259 params->request_data_len);
5260
5261 status = wmi_unified_stats_ext_req_cmd(wma->wmi_handle, params);
5262 qdf_mem_free(params);
5263
5264 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005265}
5266
5267#endif /* WLAN_FEATURE_STATS_EXT */
5268
5269#ifdef WLAN_FEATURE_EXTWOW_SUPPORT
5270/**
5271 * wma_send_status_of_ext_wow() - send ext wow status to SME
5272 * @wma: wma handle
5273 * @status: status
5274 *
5275 * Return: none
5276 */
5277static void wma_send_status_of_ext_wow(tp_wma_handle wma, bool status)
5278{
5279 tSirReadyToExtWoWInd *ready_to_extwow;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305280 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005281 cds_msg_t cds_msg;
5282 uint8_t len;
5283
5284 WMA_LOGD("Posting ready to suspend indication to umac");
5285
5286 len = sizeof(tSirReadyToExtWoWInd);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305287 ready_to_extwow = (tSirReadyToExtWoWInd *) qdf_mem_malloc(len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005288
5289 if (NULL == ready_to_extwow) {
5290 WMA_LOGE("%s: Memory allocation failure", __func__);
5291 return;
5292 }
5293
5294 ready_to_extwow->mesgType = eWNI_SME_READY_TO_EXTWOW_IND;
5295 ready_to_extwow->mesgLen = len;
5296 ready_to_extwow->status = status;
5297
5298 cds_msg.type = eWNI_SME_READY_TO_EXTWOW_IND;
5299 cds_msg.bodyptr = (void *)ready_to_extwow;
5300 cds_msg.bodyval = 0;
5301
5302 vstatus = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305303 if (vstatus != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005304 WMA_LOGE("Failed to post ready to suspend");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305305 qdf_mem_free(ready_to_extwow);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005306 }
5307}
5308
5309/**
5310 * wma_enable_ext_wow() - enable ext wow in fw
5311 * @wma: wma handle
5312 * @params: ext wow params
5313 *
5314 * Return:0 for success or error code
5315 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05305316QDF_STATUS wma_enable_ext_wow(tp_wma_handle wma, tpSirExtWoWParams params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005317{
Himanshu Agarwal44195412016-03-09 13:03:54 +05305318 struct ext_wow_params wow_params = {0};
5319 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005320
Himanshu Agarwal44195412016-03-09 13:03:54 +05305321 if (!wma) {
5322 WMA_LOGE("%s: wma handle is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305323 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005324 }
5325
Himanshu Agarwal44195412016-03-09 13:03:54 +05305326 wow_params.vdev_id = params->vdev_id;
5327 wow_params.type = (enum wmi_ext_wow_type) params->type;
5328 wow_params.wakeup_pin_num = params->wakeup_pin_num;
5329
5330 status = wmi_unified_enable_ext_wow_cmd(wma->wmi_handle,
5331 &wow_params);
5332 if (QDF_IS_STATUS_ERROR(status))
5333 return status;
5334
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005335 wma_send_status_of_ext_wow(wma, true);
Himanshu Agarwal44195412016-03-09 13:03:54 +05305336 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005337
5338}
5339
5340/**
5341 * wma_set_app_type1_params_in_fw() - set app type1 params in fw
5342 * @wma: wma handle
5343 * @appType1Params: app type1 params
5344 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305345 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005346 */
5347int wma_set_app_type1_params_in_fw(tp_wma_handle wma,
5348 tpSirAppType1Params appType1Params)
5349{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005350 int ret;
5351
Govind Singhaa64c242016-03-08 11:31:49 +05305352 ret = wmi_unified_app_type1_params_in_fw_cmd(wma->wmi_handle,
5353 (struct app_type1_params *)appType1Params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005354 if (ret) {
5355 WMA_LOGE("%s: Failed to set APP TYPE1 PARAMS", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305356 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005357 }
5358
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305359 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005360}
5361
5362/**
5363 * wma_set_app_type2_params_in_fw() - set app type2 params in fw
5364 * @wma: wma handle
5365 * @appType2Params: app type2 params
5366 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305367 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005368 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05305369QDF_STATUS wma_set_app_type2_params_in_fw(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005370 tpSirAppType2Params appType2Params)
5371{
Himanshu Agarwal44195412016-03-09 13:03:54 +05305372 struct app_type2_params params = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005373
Himanshu Agarwal44195412016-03-09 13:03:54 +05305374 if (!wma) {
5375 WMA_LOGE("%s: wma handle is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305376 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005377 }
5378
Himanshu Agarwal44195412016-03-09 13:03:54 +05305379 params.vdev_id = appType2Params->vdev_id;
5380 params.rc4_key_len = appType2Params->rc4_key_len;
5381 qdf_mem_copy(params.rc4_key, appType2Params->rc4_key, 16);
5382 params.ip_id = appType2Params->ip_id;
5383 params.ip_device_ip = appType2Params->ip_device_ip;
5384 params.ip_server_ip = appType2Params->ip_server_ip;
5385 params.tcp_src_port = appType2Params->tcp_src_port;
5386 params.tcp_dst_port = appType2Params->tcp_dst_port;
5387 params.tcp_seq = appType2Params->tcp_seq;
5388 params.tcp_ack_seq = appType2Params->tcp_ack_seq;
5389 params.keepalive_init = appType2Params->keepalive_init;
5390 params.keepalive_min = appType2Params->keepalive_min;
5391 params.keepalive_max = appType2Params->keepalive_max;
5392 params.keepalive_inc = appType2Params->keepalive_inc;
5393 params.tcp_tx_timeout_val = appType2Params->tcp_tx_timeout_val;
5394 params.tcp_rx_timeout_val = appType2Params->tcp_rx_timeout_val;
5395 qdf_mem_copy(&params.gateway_mac, &appType2Params->gateway_mac,
5396 sizeof(struct qdf_mac_addr));
5397
5398 return wmi_unified_set_app_type2_params_in_fw_cmd(wma->wmi_handle,
5399 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005400
5401}
5402#endif /* WLAN_FEATURE_EXTWOW_SUPPORT */
5403
5404#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
5405/**
5406 * wma_auto_shutdown_event_handler() - process auto shutdown timer trigger
5407 * @handle: wma handle
5408 * @event: event buffer
5409 * @len: buffer length
5410 *
5411 * Return: 0 for success or error code
5412 */
5413int wma_auto_shutdown_event_handler(void *handle, uint8_t *event,
5414 uint32_t len)
5415{
5416 wmi_host_auto_shutdown_event_fixed_param *wmi_auto_sh_evt;
5417 WMI_HOST_AUTO_SHUTDOWN_EVENTID_param_tlvs *param_buf =
5418 (WMI_HOST_AUTO_SHUTDOWN_EVENTID_param_tlvs *)
5419 event;
5420
5421 if (!param_buf || !param_buf->fixed_param) {
5422 WMA_LOGE("%s:%d: Invalid Auto shutdown timer evt", __func__,
5423 __LINE__);
5424 return -EINVAL;
5425 }
5426
5427 wmi_auto_sh_evt = param_buf->fixed_param;
5428
5429 if (wmi_auto_sh_evt->shutdown_reason
5430 != WMI_HOST_AUTO_SHUTDOWN_REASON_TIMER_EXPIRY) {
5431 WMA_LOGE("%s:%d: Invalid Auto shutdown timer evt", __func__,
5432 __LINE__);
5433 return -EINVAL;
5434 }
5435
5436 WMA_LOGD("%s:%d: Auto Shutdown Evt: %d", __func__, __LINE__,
5437 wmi_auto_sh_evt->shutdown_reason);
5438 return wma_post_auto_shutdown_msg();
5439}
5440
5441/**
5442 * wma_set_auto_shutdown_timer_req() - sets auto shutdown timer in firmware
5443 * @wma: wma handle
5444 * @auto_sh_cmd: auto shutdown timer value
5445 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305446 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005447 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305448QDF_STATUS wma_set_auto_shutdown_timer_req(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005449 tSirAutoShutdownCmdParams *
5450 auto_sh_cmd)
5451{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005452 if (auto_sh_cmd == NULL) {
5453 WMA_LOGE("%s : Invalid Autoshutdown cfg cmd", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305454 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005455 }
5456
Himanshu Agarwal44195412016-03-09 13:03:54 +05305457 return wmi_unified_set_auto_shutdown_timer_cmd(wma_handle->wmi_handle,
5458 auto_sh_cmd->timer_val);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005459}
5460#endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
5461
5462#ifdef WLAN_FEATURE_NAN
5463/**
5464 * wma_nan_req() - to send nan request to target
5465 * @wma: wma_handle
5466 * @nan_req: request data which will be non-null
5467 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305468 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005469 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305470QDF_STATUS wma_nan_req(void *wma_ptr, tpNanRequest nan_req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005471{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005472 tp_wma_handle wma_handle = (tp_wma_handle) wma_ptr;
Krishna Kumaar Natarajan1b909d72016-06-06 15:02:18 -07005473 struct nan_req_params *params;
5474 size_t params_len;
5475 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005476
Himanshu Agarwal44195412016-03-09 13:03:54 +05305477 if (!wma_handle) {
5478 WMA_LOGE("%s: wma handle is NULL", __func__);
5479 return QDF_STATUS_E_FAILURE;
5480 }
Krishna Kumaar Natarajan1b909d72016-06-06 15:02:18 -07005481
5482 params_len = sizeof(*params) + nan_req->request_data_len;
5483 params = qdf_mem_malloc(params_len);
5484
5485 if (params == NULL) {
5486 WMA_LOGE(FL("memory allocation failed"));
5487 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005488 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005489
Krishna Kumaar Natarajan1b909d72016-06-06 15:02:18 -07005490 params->request_data_len = nan_req->request_data_len;
5491 if (params->request_data_len > 0)
5492 qdf_mem_copy(params->request_data, nan_req->request_data,
5493 params->request_data_len);
Himanshu Agarwal44195412016-03-09 13:03:54 +05305494
Krishna Kumaar Natarajan1b909d72016-06-06 15:02:18 -07005495 status = wmi_unified_nan_req_cmd(wma_handle->wmi_handle, params);
5496 qdf_mem_free(params);
5497
5498 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005499}
5500#endif /* WLAN_FEATURE_NAN */
5501
5502#ifdef DHCP_SERVER_OFFLOAD
5503/**
5504 * wma_process_dhcpserver_offload() - enable DHCP server offload
5505 * @wma_handle: wma handle
5506 * @pDhcpSrvOffloadInfo: DHCP server offload info
5507 *
5508 * Return: 0 for success or error code
5509 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05305510QDF_STATUS wma_process_dhcpserver_offload(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005511 tSirDhcpSrvOffloadInfo *
5512 pDhcpSrvOffloadInfo)
5513{
Himanshu Agarwal44195412016-03-09 13:03:54 +05305514 struct dhcp_offload_info_params params = {0};
5515 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005516
Himanshu Agarwal44195412016-03-09 13:03:54 +05305517 if (!wma_handle) {
5518 WMA_LOGE("%s: wma handle is NULL", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005519 return -EIO;
5520 }
Himanshu Agarwal44195412016-03-09 13:03:54 +05305521
5522 params.vdev_id = pDhcpSrvOffloadInfo->vdev_id;
5523 params.dhcpSrvOffloadEnabled =
5524 pDhcpSrvOffloadInfo->dhcpSrvOffloadEnabled;
5525 params.dhcpClientNum = pDhcpSrvOffloadInfo->dhcpClientNum;
5526 params.dhcpSrvIP = pDhcpSrvOffloadInfo->;
5527
5528 status = wmi_unified_process_dhcpserver_offload_cmd(
5529 wma_handle->wmi_handle, &params);
5530 if (QDF_IS_STATUS_ERROR(status))
5531 return status;
5532
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005533 WMA_LOGD("Set dhcp server offload to vdevId %d",
5534 pDhcpSrvOffloadInfo->vdev_id);
Himanshu Agarwal44195412016-03-09 13:03:54 +05305535 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005536}
5537#endif /* DHCP_SERVER_OFFLOAD */
5538
5539#ifdef WLAN_FEATURE_GPIO_LED_FLASHING
5540/**
5541 * wma_set_led_flashing() - set led flashing in fw
5542 * @wma_handle: wma handle
5543 * @flashing: flashing request
5544 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305545 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005546 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305547QDF_STATUS wma_set_led_flashing(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005548 tSirLedFlashingReq *flashing)
5549{
Govind Singhaa64c242016-03-08 11:31:49 +05305550 struct flashing_req_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005551
5552 if (!wma_handle || !wma_handle->wmi_handle) {
5553 WMA_LOGE(FL("WMA is closed, can not issue cmd"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305554 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005555 }
5556 if (!flashing) {
5557 WMA_LOGE(FL("invalid parameter: flashing"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305558 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005559 }
Govind Singhaa64c242016-03-08 11:31:49 +05305560 cmd.req_id = flashing->reqId;
5561 cmd.pattern_id = flashing->pattern_id;
5562 cmd.led_x0 = flashing->led_x0;
5563 cmd.led_x1 = flashing->led_x1;
5564 status = wmi_unified_set_led_flashing_cmd(wma_handle->wmi_handle,
5565 &cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005566 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305567 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005568 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305569 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005570}
5571#endif /* WLAN_FEATURE_GPIO_LED_FLASHING */
5572
5573#ifdef FEATURE_WLAN_CH_AVOID
5574/**
5575 * wma_channel_avoid_evt_handler() - process channel to avoid event from FW.
5576 * @handle: wma handle
5577 * @event: event buffer
5578 * @len: buffer length
5579 *
5580 * Return: 0 for success or error code
5581 */
5582int wma_channel_avoid_evt_handler(void *handle, uint8_t *event,
5583 uint32_t len)
5584{
5585 wmi_avoid_freq_ranges_event_fixed_param *afr_fixed_param;
5586 wmi_avoid_freq_range_desc *afr_desc;
5587 uint32_t num_freq_ranges, freq_range_idx;
5588 tSirChAvoidIndType *sca_indication;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305589 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005590 cds_msg_t sme_msg = { 0 };
5591 WMI_WLAN_FREQ_AVOID_EVENTID_param_tlvs *param_buf =
5592 (WMI_WLAN_FREQ_AVOID_EVENTID_param_tlvs *) event;
5593
5594 if (!param_buf) {
5595 WMA_LOGE("Invalid channel avoid event buffer");
5596 return -EINVAL;
5597 }
5598
5599 afr_fixed_param = param_buf->fixed_param;
5600 if (!afr_fixed_param) {
5601 WMA_LOGE("Invalid channel avoid event fixed param buffer");
5602 return -EINVAL;
5603 }
5604
5605 num_freq_ranges =
5606 (afr_fixed_param->num_freq_ranges >
5607 SIR_CH_AVOID_MAX_RANGE) ? SIR_CH_AVOID_MAX_RANGE :
5608 afr_fixed_param->num_freq_ranges;
5609
5610 WMA_LOGD("Channel avoid event received with %d ranges",
5611 num_freq_ranges);
5612 for (freq_range_idx = 0; freq_range_idx < num_freq_ranges;
5613 freq_range_idx++) {
5614 afr_desc = (wmi_avoid_freq_range_desc *)
5615 ((void *)param_buf->avd_freq_range +
5616 freq_range_idx * sizeof(wmi_avoid_freq_range_desc));
5617
5618 WMA_LOGD("range %d: tlv id = %u, start freq = %u, end freq = %u",
5619 freq_range_idx, afr_desc->tlv_header, afr_desc->start_freq,
5620 afr_desc->end_freq);
5621 }
5622
5623 sca_indication = (tSirChAvoidIndType *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305624 qdf_mem_malloc(sizeof(tSirChAvoidIndType));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005625 if (!sca_indication) {
5626 WMA_LOGE("Invalid channel avoid indication buffer");
5627 return -EINVAL;
5628 }
5629
5630 sca_indication->avoid_range_count = num_freq_ranges;
5631 for (freq_range_idx = 0; freq_range_idx < num_freq_ranges;
5632 freq_range_idx++) {
5633 afr_desc = (wmi_avoid_freq_range_desc *)
5634 ((void *)param_buf->avd_freq_range +
5635 freq_range_idx * sizeof(wmi_avoid_freq_range_desc));
5636 sca_indication->avoid_freq_range[freq_range_idx].start_freq =
5637 afr_desc->start_freq;
5638 sca_indication->avoid_freq_range[freq_range_idx].end_freq =
5639 afr_desc->end_freq;
5640 }
5641
5642 sme_msg.type = eWNI_SME_CH_AVOID_IND;
5643 sme_msg.bodyptr = sca_indication;
5644 sme_msg.bodyval = 0;
5645
Anurag Chouhan6d760662016-02-20 16:05:43 +05305646 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305647 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005648 WMA_LOGE("Fail to post eWNI_SME_CH_AVOID_IND msg to SME");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305649 qdf_mem_free(sca_indication);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005650 return -EINVAL;
5651 }
5652
5653 return 0;
5654}
5655
5656/**
5657 * wma_process_ch_avoid_update_req() - handles channel avoid update request
5658 * @wma_handle: wma handle
5659 * @ch_avoid_update_req: channel avoid update params
5660 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305661 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005662 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305663QDF_STATUS wma_process_ch_avoid_update_req(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005664 tSirChAvoidUpdateReq *
5665 ch_avoid_update_req)
5666{
Himanshu Agarwal44195412016-03-09 13:03:54 +05305667 QDF_STATUS status;
5668 if (!wma_handle) {
5669 WMA_LOGE("%s: wma handle is NULL", __func__);
5670 return QDF_STATUS_E_FAILURE;
5671 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005672 if (ch_avoid_update_req == NULL) {
5673 WMA_LOGE("%s : ch_avoid_update_req is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305674 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005675 }
5676
5677 WMA_LOGI("%s: WMA --> WMI_CHAN_AVOID_UPDATE", __func__);
5678
Himanshu Agarwal44195412016-03-09 13:03:54 +05305679 status = wmi_unified_process_ch_avoid_update_cmd(
5680 wma_handle->wmi_handle);
5681 if (QDF_IS_STATUS_ERROR(status))
5682 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005683
5684 WMA_LOGI("%s: WMA --> WMI_CHAN_AVOID_UPDATE sent through WMI",
5685 __func__);
Himanshu Agarwal44195412016-03-09 13:03:54 +05305686 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005687}
5688#endif /* FEATURE_WLAN_CH_AVOID */
5689
5690/**
5691 * wma_set_reg_domain() - set reg domain
5692 * @clientCtxt: client context
5693 * @regId: reg id
5694 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305695 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005696 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305697QDF_STATUS wma_set_reg_domain(void *clientCtxt, v_REGDOMAIN_t regId)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005698{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305699 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005700 cds_set_reg_domain(clientCtxt, regId))
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305701 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005702
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305703 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005704}
5705
5706/**
5707 * wma_send_regdomain_info_to_fw() - send regdomain info to fw
5708 * @reg_dmn: reg domain
5709 * @regdmn2G: 2G reg domain
5710 * @regdmn5G: 5G reg domain
5711 * @ctl2G: 2G test limit
5712 * @ctl5G: 5G test limit
5713 *
5714 * Return: none
5715 */
5716void wma_send_regdomain_info_to_fw(uint32_t reg_dmn, uint16_t regdmn2G,
5717 uint16_t regdmn5G, int8_t ctl2G,
5718 int8_t ctl5G)
5719{
Anurag Chouhan6d760662016-02-20 16:05:43 +05305720 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005721 int32_t cck_mask_val = 0;
Govind Singhd76a5b02016-03-08 15:12:14 +05305722 struct pdev_params pdev_param = {0};
Himanshu Agarwal44195412016-03-09 13:03:54 +05305723 QDF_STATUS ret = QDF_STATUS_SUCCESS;
5724 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005725
5726 if (NULL == wma) {
5727 WMA_LOGE("%s: wma context is NULL", __func__);
5728 return;
5729 }
5730
Himanshu Agarwal44195412016-03-09 13:03:54 +05305731 status = wmi_unified_send_regdomain_info_to_fw_cmd(wma->wmi_handle,
5732 reg_dmn, regdmn2G, regdmn5G, ctl2G, ctl5G);
5733 if (status == QDF_STATUS_E_NOMEM)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005734 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005735
Amar Singhal76b41322015-12-09 14:39:17 -08005736 if ((((reg_dmn & ~COUNTRY_ERD_FLAG) == CTRY_JAPAN14) ||
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005737 ((reg_dmn & ~COUNTRY_ERD_FLAG) == CTRY_KOREA_ROC)) &&
5738 (true == wma->tx_chain_mask_cck))
5739 cck_mask_val = 1;
5740
5741 cck_mask_val |= (wma->self_gen_frm_pwr << 16);
Govind Singhd76a5b02016-03-08 15:12:14 +05305742 pdev_param.param_id = WMI_PDEV_PARAM_TX_CHAIN_MASK_CCK;
5743 pdev_param.param_value = cck_mask_val;
5744 ret = wmi_unified_pdev_param_send(wma->wmi_handle,
5745 &pdev_param,
5746 WMA_WILDCARD_PDEV_ID);
5747
Himanshu Agarwal44195412016-03-09 13:03:54 +05305748 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005749 WMA_LOGE("failed to set PDEV tx_chain_mask_cck %d",
5750 ret);
5751
5752 return;
5753}
5754
5755/**
Houston Hoffmana76591b2015-11-10 16:52:05 -08005756 * wma_post_runtime_resume_msg() - post the resume request
5757 * @handle: validated wma handle
5758 *
5759 * request the MC thread unpaus the vdev and set resume dtim
5760 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305761 * Return: qdf status of the mq post
Houston Hoffmana76591b2015-11-10 16:52:05 -08005762 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305763static QDF_STATUS wma_post_runtime_resume_msg(WMA_HANDLE handle)
Houston Hoffmana76591b2015-11-10 16:52:05 -08005764{
5765 cds_msg_t resume_msg;
Houston Hoffmanc45db892015-11-13 19:59:25 -08005766 QDF_STATUS status;
5767 tp_wma_handle wma = (tp_wma_handle) handle;
5768
5769 qdf_runtime_pm_prevent_suspend(wma->wma_runtime_resume_lock);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005770
5771 resume_msg.bodyptr = NULL;
5772 resume_msg.type = WMA_RUNTIME_PM_RESUME_IND;
Houston Hoffmanc45db892015-11-13 19:59:25 -08005773
5774 status = cds_mq_post_message(QDF_MODULE_ID_WMA, &resume_msg);
5775
5776 if (!QDF_IS_STATUS_SUCCESS(status)) {
5777 WMA_LOGE("Failed to post Runtime PM Resume IND to VOS");
5778 qdf_runtime_pm_allow_suspend(wma->wma_runtime_resume_lock);
5779 }
5780
5781 return status;
Houston Hoffmana76591b2015-11-10 16:52:05 -08005782}
5783
5784/**
5785 * wma_post_runtime_suspend_msg() - post the suspend request
5786 * @handle: validated wma handle
5787 *
5788 * Requests for offloads to be configured for runtime suspend
5789 * on the MC thread
5790 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305791 * Return QDF_STATUS_E_AGAIN in case of timeout or QDF_STATUS_SUCCESS
Houston Hoffmana76591b2015-11-10 16:52:05 -08005792 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305793static QDF_STATUS wma_post_runtime_suspend_msg(WMA_HANDLE handle)
Houston Hoffmana76591b2015-11-10 16:52:05 -08005794{
5795 cds_msg_t cds_msg;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305796 QDF_STATUS qdf_status;
Houston Hoffmana76591b2015-11-10 16:52:05 -08005797 tp_wma_handle wma = (tp_wma_handle) handle;
5798
Anurag Chouhance0dc992016-02-16 18:18:03 +05305799 qdf_event_reset(&wma->runtime_suspend);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005800
5801 cds_msg.bodyptr = NULL;
5802 cds_msg.type = WMA_RUNTIME_PM_SUSPEND_IND;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305803 qdf_status = cds_mq_post_message(QDF_MODULE_ID_WMA, &cds_msg);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005804
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305805 if (qdf_status != QDF_STATUS_SUCCESS)
Houston Hoffmana76591b2015-11-10 16:52:05 -08005806 goto failure;
5807
Anurag Chouhance0dc992016-02-16 18:18:03 +05305808 if (qdf_wait_single_event(&wma->runtime_suspend,
Houston Hoffmana76591b2015-11-10 16:52:05 -08005809 WMA_TGT_SUSPEND_COMPLETE_TIMEOUT) !=
Anurag Chouhance0dc992016-02-16 18:18:03 +05305810 QDF_STATUS_SUCCESS) {
Houston Hoffmana76591b2015-11-10 16:52:05 -08005811 WMA_LOGE("Failed to get runtime suspend event");
Houston Hoffmanc45db892015-11-13 19:59:25 -08005812 goto msg_timed_out;
Houston Hoffmana76591b2015-11-10 16:52:05 -08005813 }
5814
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305815 return QDF_STATUS_SUCCESS;
Houston Hoffmana76591b2015-11-10 16:52:05 -08005816
Houston Hoffmanc45db892015-11-13 19:59:25 -08005817msg_timed_out:
5818 wma_post_runtime_resume_msg(wma);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005819failure:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305820 return QDF_STATUS_E_AGAIN;
Houston Hoffmana76591b2015-11-10 16:52:05 -08005821}
5822
5823/**
5824 * __wma_bus_suspend(): handles bus suspend for wma
5825 * @type: is this suspend part of runtime suspend or system suspend?
5826 *
5827 * Bails if a scan is in progress.
5828 * Calls the appropriate handlers based on configuration and event.
5829 *
5830 * Return: 0 for success or error code
5831 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05305832static int __wma_bus_suspend(enum qdf_suspend_type type)
Houston Hoffmana76591b2015-11-10 16:52:05 -08005833{
Anurag Chouhan6d760662016-02-20 16:05:43 +05305834 WMA_HANDLE handle = cds_get_context(QDF_MODULE_ID_WMA);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005835 if (NULL == handle) {
5836 WMA_LOGE("%s: wma context is NULL", __func__);
5837 return -EFAULT;
5838 }
5839
5840 if (wma_check_scan_in_progress(handle)) {
5841 WMA_LOGE("%s: Scan in progress. Aborting suspend", __func__);
5842 return -EBUSY;
5843 }
5844
Anurag Chouhan6d760662016-02-20 16:05:43 +05305845 if (type == QDF_RUNTIME_SUSPEND) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305846 QDF_STATUS status = wma_post_runtime_suspend_msg(handle);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005847 if (status)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305848 return qdf_status_to_os_return(status);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005849 }
5850
Anurag Chouhan6d760662016-02-20 16:05:43 +05305851 if (type == QDF_SYSTEM_SUSPEND)
Houston Hoffmana76591b2015-11-10 16:52:05 -08005852 WMA_LOGE("%s: wow mode selected %d", __func__,
5853 wma_is_wow_mode_selected(handle));
5854
5855 if (wma_is_wow_mode_selected(handle)) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305856 QDF_STATUS status = wma_enable_wow_in_fw(handle);
5857 return qdf_status_to_os_return(status);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005858 }
5859
5860 return wma_suspend_target(handle, 0);
5861}
5862
5863/**
5864 * wma_runtime_suspend() - handles runtime suspend request from hdd
5865 *
5866 * Calls the appropriate handler based on configuration and event.
5867 * Last busy marking should prevent race conditions between processing
5868 * of asyncronous fw events and the running of runtime suspend.
5869 * (eg. last busy marking should guarantee that any auth requests have
5870 * been processed)
5871 * Events comming from the host are not protected, but aren't expected
5872 * to be an issue.
5873 *
5874 * Return: 0 for success or error code
5875 */
5876int wma_runtime_suspend(void)
5877{
Anurag Chouhan6d760662016-02-20 16:05:43 +05305878 return __wma_bus_suspend(QDF_RUNTIME_SUSPEND);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005879}
5880
5881/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005882 * wma_bus_suspend() - handles bus suspend request from hdd
5883 *
5884 * Calls the appropriate handler based on configuration and event
5885 *
5886 * Return: 0 for success or error code
5887 */
5888int wma_bus_suspend(void)
5889{
Houston Hoffmana76591b2015-11-10 16:52:05 -08005890
Anurag Chouhan6d760662016-02-20 16:05:43 +05305891 return __wma_bus_suspend(QDF_SYSTEM_SUSPEND);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005892}
5893
5894/**
5895 * __wma_bus_resume() - bus resume for wma
5896 *
5897 * does the part of the bus resume common to bus and system suspend
5898 *
5899 * Return: os error code.
5900 */
5901int __wma_bus_resume(WMA_HANDLE handle)
5902{
5903 bool wow_mode = wma_is_wow_mode_selected(handle);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305904 QDF_STATUS status;
Houston Hoffmana76591b2015-11-10 16:52:05 -08005905
5906 WMA_LOGE("%s: wow mode %d", __func__, wow_mode);
5907
5908 if (!wow_mode)
Rajeev Kumar9be537e2016-04-25 17:35:33 -07005909 return qdf_status_to_os_return(wma_resume_target(handle));
Houston Hoffmana76591b2015-11-10 16:52:05 -08005910
5911 status = wma_disable_wow_in_fw(handle);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305912 return qdf_status_to_os_return(status);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005913}
5914
5915/**
5916 * wma_runtime_resume() - do the runtime resume operation for wma
5917 *
5918 * Return: os error code.
5919 */
5920int wma_runtime_resume(void)
5921{
5922 int ret;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305923 QDF_STATUS status;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305924 WMA_HANDLE handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005925 if (NULL == handle) {
5926 WMA_LOGE("%s: wma context is NULL", __func__);
5927 return -EFAULT;
5928 }
5929
Houston Hoffmana76591b2015-11-10 16:52:05 -08005930 ret = __wma_bus_resume(handle);
5931 if (ret)
5932 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005933
Houston Hoffmana76591b2015-11-10 16:52:05 -08005934 status = wma_post_runtime_resume_msg(handle);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305935 return qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005936}
5937
5938/**
5939 * wma_bus_resume() - handles bus resume request from hdd
5940 * @handle: valid wma handle
5941 *
5942 * Calls the appropriate handler based on configuration
5943 *
5944 * Return: 0 for success or error code
5945 */
5946int wma_bus_resume(void)
5947{
Anurag Chouhan6d760662016-02-20 16:05:43 +05305948 WMA_HANDLE handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005949 if (NULL == handle) {
5950 WMA_LOGE("%s: wma context is NULL", __func__);
5951 return -EFAULT;
5952 }
5953
Houston Hoffmana76591b2015-11-10 16:52:05 -08005954 return __wma_bus_resume(handle);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005955}
5956
5957/**
Manjunathappa Prakash7b67e622016-04-12 15:18:45 +05305958 * wma_suspend_target_timeout() - Handles the target suspend timeout
5959 * @is_self_recovery_enabled: Is self recovery enabled or not
5960 *
5961 * Return: NONE
5962 */
5963#ifdef QCA_WIFI_3_0_ADRASTEA
5964static inline void wma_suspend_target_timeout(bool is_self_recovery_enabled)
5965{
5966 if (cds_is_driver_recovering()) {
5967 WMA_LOGE("%s: recovery is in progress, ignore!", __func__);
5968 } else {
5969 if (is_self_recovery_enabled) {
5970 cds_trigger_recovery();
5971 } else {
5972 QDF_BUG(0);
5973 }
5974 }
5975}
5976#else /* ROME chipset */
5977static inline void wma_suspend_target_timeout(bool is_self_recovery_enabled)
5978{
5979 if (cds_is_load_or_unload_in_progress() || cds_is_driver_recovering()) {
5980 WMA_LOGE("%s: Unloading/Loading/recovery is in progress, Ignore!",
5981 __func__);
5982 } else {
5983 if (is_self_recovery_enabled) {
5984 cds_trigger_recovery();
5985 } else {
5986 QDF_BUG(0);
5987 }
5988 }
5989}
5990#endif
5991
5992/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005993 * wma_suspend_target() - suspend target
5994 * @handle: wma handle
5995 * @disable_target_intr: disable target interrupt
5996 *
Govind Singhd76a5b02016-03-08 15:12:14 +05305997 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005998 */
Govind Singhd76a5b02016-03-08 15:12:14 +05305999QDF_STATUS wma_suspend_target(WMA_HANDLE handle, int disable_target_intr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006000{
6001 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Komal Seelam3d202862016-02-24 18:43:24 +05306002 struct hif_opaque_softc *scn;
Govind Singhd76a5b02016-03-08 15:12:14 +05306003 QDF_STATUS status;
6004 struct suspend_params param = {0};
6005
Anurag Chouhan6d760662016-02-20 16:05:43 +05306006 tpAniSirGlobal pmac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006007
6008 if (!wma_handle || !wma_handle->wmi_handle) {
6009 WMA_LOGE("WMA is closed. can not issue suspend cmd");
Govind Singhd76a5b02016-03-08 15:12:14 +05306010 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006011 }
Yue Mae1a85f32015-10-20 18:12:45 -07006012
Yue Mae1a85f32015-10-20 18:12:45 -07006013 if (NULL == pmac) {
6014 WMA_LOGE("%s: Unable to get PE context", __func__);
Govind Singhd76a5b02016-03-08 15:12:14 +05306015 return QDF_STATUS_E_INVAL;
Yue Mae1a85f32015-10-20 18:12:45 -07006016 }
Houston Hoffman52ec6692016-04-21 16:36:45 -07006017
Anurag Chouhance0dc992016-02-16 18:18:03 +05306018 qdf_event_reset(&wma_handle->target_suspend);
Govind Singhd76a5b02016-03-08 15:12:14 +05306019 param.disable_target_intr = disable_target_intr;
6020 status = wmi_unified_suspend_send(wma_handle->wmi_handle,
6021 &param,
6022 WMA_WILDCARD_PDEV_ID);
6023 if (QDF_IS_STATUS_ERROR(status))
6024 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006025
6026 wmi_set_target_suspend(wma_handle->wmi_handle, true);
6027
Anurag Chouhance0dc992016-02-16 18:18:03 +05306028 if (qdf_wait_single_event(&wma_handle->target_suspend,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006029 WMA_TGT_SUSPEND_COMPLETE_TIMEOUT)
Anurag Chouhance0dc992016-02-16 18:18:03 +05306030 != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006031 WMA_LOGE("Failed to get ACK from firmware for pdev suspend");
6032 wmi_set_target_suspend(wma_handle->wmi_handle, false);
Manjunathappa Prakash7b67e622016-04-12 15:18:45 +05306033 wma_suspend_target_timeout(pmac->sme.enableSelfRecovery);
Govind Singhd76a5b02016-03-08 15:12:14 +05306034 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006035 }
6036
Anurag Chouhan6d760662016-02-20 16:05:43 +05306037 scn = cds_get_context(QDF_MODULE_ID_HIF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006038
6039 if (scn == NULL) {
6040 WMA_LOGE("%s: Failed to get HIF context", __func__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306041 QDF_ASSERT(0);
Govind Singhd76a5b02016-03-08 15:12:14 +05306042 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006043 }
6044
Govind Singhd76a5b02016-03-08 15:12:14 +05306045 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006046}
6047
6048/**
6049 * wma_target_suspend_acknowledge() - update target susspend status
Houston Hoffmana769ed32016-04-14 17:02:51 -07006050 * @context: HTC_INIT_INFO->context
6051 * @wow_nack: true when wow is rejected
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006052 *
6053 * Return: none
6054 */
Houston Hoffmana769ed32016-04-14 17:02:51 -07006055void wma_target_suspend_acknowledge(void *context, bool wow_nack)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006056{
Anurag Chouhan6d760662016-02-20 16:05:43 +05306057 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006058
6059 if (NULL == wma) {
6060 WMA_LOGE("%s: wma is NULL", __func__);
6061 return;
6062 }
6063
6064 wma->wow_nack = wow_nack;
Anurag Chouhance0dc992016-02-16 18:18:03 +05306065 qdf_event_set(&wma->target_suspend);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006066 if (wow_nack)
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306067 qdf_wake_lock_timeout_acquire(&wma->wow_wake_lock,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006068 WMA_WAKE_LOCK_TIMEOUT,
6069 WIFI_POWER_EVENT_WAKELOCK_WOW);
6070}
6071
6072/**
6073 * wma_resume_target() - resume target
6074 * @handle: wma handle
6075 *
Govind Singhd76a5b02016-03-08 15:12:14 +05306076 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006077 */
Govind Singhd76a5b02016-03-08 15:12:14 +05306078QDF_STATUS wma_resume_target(WMA_HANDLE handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006079{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006080 tp_wma_handle wma = (tp_wma_handle) handle;
Anurag Chouhance0dc992016-02-16 18:18:03 +05306081 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006082#ifdef CONFIG_CNSS
Anurag Chouhan6d760662016-02-20 16:05:43 +05306083 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006084 if (NULL == pMac) {
6085 WMA_LOGE("%s: Unable to get PE context", __func__);
Govind Singhd76a5b02016-03-08 15:12:14 +05306086 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006087 }
6088#endif /* CONFIG_CNSS */
6089
Anurag Chouhance0dc992016-02-16 18:18:03 +05306090 qdf_event_reset(&wma->wma_resume_event);
Govind Singhd76a5b02016-03-08 15:12:14 +05306091 qdf_status = wmi_unified_resume_send(wma->wmi_handle,
6092 WMA_WILDCARD_PDEV_ID);
6093 if (QDF_IS_STATUS_ERROR(qdf_status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006094 WMA_LOGE("Failed to send WMI_PDEV_RESUME_CMDID command");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006095
Anurag Chouhance0dc992016-02-16 18:18:03 +05306096 qdf_status = qdf_wait_single_event(&(wma->wma_resume_event),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006097 WMA_RESUME_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05306098 if (QDF_STATUS_SUCCESS != qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006099 WMA_LOGP("%s: Timeout waiting for resume event from FW",
6100 __func__);
6101 WMA_LOGP("%s: Pending commands %d credits %d", __func__,
6102 wmi_get_pending_cmds(wma->wmi_handle),
6103 wmi_get_host_credits(wma->wmi_handle));
Prashanth Bhatta9e143052015-12-04 11:56:47 -08006104 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006105#ifdef CONFIG_CNSS
6106 if (pMac->sme.enableSelfRecovery) {
6107 cds_trigger_recovery();
6108 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306109 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006110 }
6111#else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306112 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006113#endif /* CONFIG_CNSS */
6114 } else {
6115 WMA_LOGE("%s: SSR in progress, ignore resume timeout",
6116 __func__);
6117 }
6118 } else {
6119 WMA_LOGD("Host wakeup received");
6120 }
6121
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306122 if (QDF_STATUS_SUCCESS == qdf_status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006123 wmi_set_target_suspend(wma->wmi_handle, false);
6124
Houston Hoffman52ec6692016-04-21 16:36:45 -07006125 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006126}
6127
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006128#ifdef FEATURE_WLAN_TDLS
6129/**
6130 * wma_tdls_event_handler() - handle TDLS event
6131 * @handle: wma handle
6132 * @event: event buffer
6133 * @len: buffer length
6134 *
6135 * Return: 0 for success or error code
6136 */
6137int wma_tdls_event_handler(void *handle, uint8_t *event, uint32_t len)
6138{
6139 tp_wma_handle wma = (tp_wma_handle) handle;
6140 WMI_TDLS_PEER_EVENTID_param_tlvs *param_buf = NULL;
6141 wmi_tdls_peer_event_fixed_param *peer_event = NULL;
6142 tSirTdlsEventnotify *tdls_event;
6143
6144 if (!event) {
6145 WMA_LOGE("%s: event param null", __func__);
6146 return -EINVAL;
6147 }
6148
6149 param_buf = (WMI_TDLS_PEER_EVENTID_param_tlvs *) event;
6150 if (!param_buf) {
6151 WMA_LOGE("%s: received null buf from target", __func__);
6152 return -EINVAL;
6153 }
6154
6155 peer_event = param_buf->fixed_param;
6156 if (!peer_event) {
6157 WMA_LOGE("%s: received null event data from target", __func__);
6158 return -EINVAL;
6159 }
6160
6161 tdls_event = (tSirTdlsEventnotify *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306162 qdf_mem_malloc(sizeof(*tdls_event));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006163 if (!tdls_event) {
6164 WMA_LOGE("%s: failed to allocate memory for tdls_event",
6165 __func__);
6166 return -ENOMEM;
6167 }
6168
6169 tdls_event->sessionId = peer_event->vdev_id;
6170 WMI_MAC_ADDR_TO_CHAR_ARRAY(&peer_event->peer_macaddr,
Srinivas Girigowda4f593792015-11-19 15:33:42 -08006171 tdls_event->peermac.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006172
6173 switch (peer_event->peer_status) {
6174 case WMI_TDLS_SHOULD_DISCOVER:
6175 tdls_event->messageType = WMA_TDLS_SHOULD_DISCOVER_CMD;
6176 break;
6177 case WMI_TDLS_SHOULD_TEARDOWN:
6178 tdls_event->messageType = WMA_TDLS_SHOULD_TEARDOWN_CMD;
6179 break;
6180 case WMI_TDLS_PEER_DISCONNECTED:
6181 tdls_event->messageType = WMA_TDLS_PEER_DISCONNECTED_CMD;
6182 break;
Kabilan Kannan14ec97f2016-05-16 23:48:25 -07006183 case WMI_TDLS_CONNECTION_TRACKER_NOTIFICATION:
6184 tdls_event->messageType =
6185 WMA_TDLS_CONNECTION_TRACKER_NOTIFICATION_CMD;
6186 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006187 default:
6188 WMA_LOGE("%s: Discarding unknown tdls event(%d) from target",
6189 __func__, peer_event->peer_status);
6190 return -EINVAL;
6191 }
6192
6193 switch (peer_event->peer_reason) {
6194 case WMI_TDLS_TEARDOWN_REASON_TX:
6195 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_TX;
6196 break;
6197 case WMI_TDLS_TEARDOWN_REASON_RSSI:
6198 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_RSSI;
6199 break;
6200 case WMI_TDLS_TEARDOWN_REASON_SCAN:
6201 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_SCAN;
6202 break;
6203 case WMI_TDLS_DISCONNECTED_REASON_PEER_DELETE:
6204 tdls_event->peer_reason =
6205 eWNI_TDLS_DISCONNECTED_REASON_PEER_DELETE;
6206 break;
6207 case WMI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT:
6208 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT;
6209 break;
6210 case WMI_TDLS_TEARDOWN_REASON_BAD_PTR:
6211 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_BAD_PTR;
6212 break;
6213 case WMI_TDLS_TEARDOWN_REASON_NO_RESPONSE:
6214 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_NO_RESPONSE;
6215 break;
Kabilan Kannan14ec97f2016-05-16 23:48:25 -07006216 case WMI_TDLS_ENTER_BUF_STA:
6217 tdls_event->peer_reason = eWNI_TDLS_PEER_ENTER_BUF_STA;
6218 break;
6219 case WMI_TDLS_EXIT_BUF_STA:
6220 tdls_event->peer_reason = eWNI_TDLS_PEER_EXIT_BUF_STA;
6221 break;
6222 case WMI_TDLS_ENTER_BT_BUSY_MODE:
6223 tdls_event->peer_reason = eWNI_TDLS_ENTER_BT_BUSY_MODE;
6224 break;
6225 case WMI_TDLS_EXIT_BT_BUSY_MODE:
6226 tdls_event->peer_reason = eWNI_TDLS_EXIT_BT_BUSY_MODE;
6227 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006228 default:
6229 WMA_LOGE("%s: unknown reason(%d) in tdls event(%d) from target",
6230 __func__, peer_event->peer_reason,
6231 peer_event->peer_status);
6232 return -EINVAL;
6233 }
6234
6235 WMA_LOGD("%s: sending msg to umac, messageType: 0x%x, "
6236 "for peer: %pM, reason: %d, smesessionId: %d",
Srinivas Girigowda4f593792015-11-19 15:33:42 -08006237 __func__, tdls_event->messageType, tdls_event->peermac.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006238 tdls_event->peer_reason, tdls_event->sessionId);
6239
6240 wma_send_msg(wma, tdls_event->messageType, (void *)tdls_event, 0);
6241 return 0;
6242}
6243
6244/**
6245 * wma_set_tdls_offchan_mode() - set tdls off channel mode
6246 * @handle: wma handle
6247 * @chan_switch_params: Pointer to tdls channel switch parameter structure
6248 *
6249 * This function sets tdls off channel mode
6250 *
6251 * Return: 0 on success; Negative errno otherwise
6252 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05306253QDF_STATUS wma_set_tdls_offchan_mode(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006254 tdls_chan_switch_params *chan_switch_params)
6255{
6256 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Himanshu Agarwal44195412016-03-09 13:03:54 +05306257 struct tdls_channel_switch_params params = {0};
6258 QDF_STATUS ret = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006259
6260 if (!wma_handle || !wma_handle->wmi_handle) {
6261 WMA_LOGE(FL(
6262 "WMA is closed, can not issue tdls off channel cmd"
6263 ));
6264 ret = -EINVAL;
6265 goto end;
6266 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006267
Himanshu Agarwal44195412016-03-09 13:03:54 +05306268 params.vdev_id = chan_switch_params->vdev_id;
6269 params.tdls_off_ch_bw_offset =
6270 chan_switch_params->tdls_off_ch_bw_offset;
6271 params.tdls_off_ch = chan_switch_params->tdls_off_ch;
6272 params.tdls_sw_mode = chan_switch_params->tdls_sw_mode;
6273 params.oper_class = chan_switch_params->oper_class;
6274 params.is_responder = chan_switch_params->is_responder;
6275 qdf_mem_copy(params.peer_mac_addr, chan_switch_params->peer_mac_addr,
Krunal Soniab793342016-04-22 18:43:20 -07006276 IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006277
Himanshu Agarwal44195412016-03-09 13:03:54 +05306278 ret = wmi_unified_set_tdls_offchan_mode_cmd(wma_handle->wmi_handle,
6279 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006280
6281end:
6282 if (chan_switch_params)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306283 qdf_mem_free(chan_switch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006284 return ret;
6285}
6286
6287/**
6288 * wma_update_fw_tdls_state() - send enable/disable tdls for a vdev
6289 * @wma: wma handle
6290 * @pwmaTdlsparams: TDLS params
6291 *
6292 * Return: 0 for sucess or error code
6293 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05306294QDF_STATUS wma_update_fw_tdls_state(WMA_HANDLE handle, void *pwmaTdlsparams)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006295{
6296 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006297 t_wma_tdls_mode tdls_mode;
6298 t_wma_tdls_params *wma_tdls = (t_wma_tdls_params *) pwmaTdlsparams;
Himanshu Agarwal44195412016-03-09 13:03:54 +05306299 struct wmi_tdls_params params = {0};
6300 QDF_STATUS ret = QDF_STATUS_SUCCESS;
6301 uint8_t tdls_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006302
6303 if (!wma_handle || !wma_handle->wmi_handle) {
6304 WMA_LOGE("%s: WMA is closed, can not issue fw tdls state cmd",
6305 __func__);
6306 ret = -EINVAL;
6307 goto end_fw_tdls_state;
6308 }
6309
Himanshu Agarwal44195412016-03-09 13:03:54 +05306310 params.tdls_state = wma_tdls->tdls_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006311 tdls_mode = wma_tdls->tdls_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006312
6313 if (WMA_TDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == tdls_mode) {
Himanshu Agarwal44195412016-03-09 13:03:54 +05306314 tdls_state = WMI_TDLS_ENABLE_PASSIVE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006315 } else if (WMA_TDLS_SUPPORT_ENABLED == tdls_mode) {
Kabilan Kannan14ec97f2016-05-16 23:48:25 -07006316 tdls_state = WMI_TDLS_ENABLE_CONNECTION_TRACKER_IN_HOST;
Kabilan Kannan421714b2015-11-23 04:44:59 -08006317 } else if (WMA_TDLS_SUPPORT_ACTIVE_EXTERNAL_CONTROL == tdls_mode) {
Kabilan Kannan14ec97f2016-05-16 23:48:25 -07006318 tdls_state = WMI_TDLS_ENABLE_CONNECTION_TRACKER_IN_HOST;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006319 } else {
Himanshu Agarwal44195412016-03-09 13:03:54 +05306320 tdls_state = WMI_TDLS_DISABLE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006321 }
6322
Himanshu Agarwal44195412016-03-09 13:03:54 +05306323 params.vdev_id = wma_tdls->vdev_id;
6324 params.notification_interval_ms = wma_tdls->notification_interval_ms;
6325 params.tx_discovery_threshold = wma_tdls->tx_discovery_threshold;
6326 params.tx_teardown_threshold = wma_tdls->tx_teardown_threshold;
6327 params.rssi_teardown_threshold = wma_tdls->rssi_teardown_threshold;
6328 params.rssi_delta = wma_tdls->rssi_delta;
6329 params.tdls_options = wma_tdls->tdls_options;
6330 params.peer_traffic_ind_window = wma_tdls->peer_traffic_ind_window;
6331 params.peer_traffic_response_timeout =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006332 wma_tdls->peer_traffic_response_timeout;
Himanshu Agarwal44195412016-03-09 13:03:54 +05306333 params.puapsd_mask = wma_tdls->puapsd_mask;
6334 params.puapsd_inactivity_time = wma_tdls->puapsd_inactivity_time;
6335 params.puapsd_rx_frame_threshold =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006336 wma_tdls->puapsd_rx_frame_threshold;
Himanshu Agarwal44195412016-03-09 13:03:54 +05306337 params.teardown_notification_ms =
Kabilan Kannanca670be2015-11-23 01:56:12 -08006338 wma_tdls->teardown_notification_ms;
Himanshu Agarwal44195412016-03-09 13:03:54 +05306339 params.tdls_peer_kickout_threshold =
Kabilan Kannan421714b2015-11-23 04:44:59 -08006340 wma_tdls->tdls_peer_kickout_threshold;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006341
Himanshu Agarwal44195412016-03-09 13:03:54 +05306342 ret = wmi_unified_update_fw_tdls_state_cmd(wma_handle->wmi_handle,
6343 &params, tdls_state);
6344 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006345 goto end_fw_tdls_state;
Himanshu Agarwal44195412016-03-09 13:03:54 +05306346
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006347 WMA_LOGD("%s: vdev_id %d", __func__, wma_tdls->vdev_id);
6348
6349end_fw_tdls_state:
6350 if (pwmaTdlsparams)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306351 qdf_mem_free(pwmaTdlsparams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006352 return ret;
6353}
6354
6355/**
6356 * wma_update_tdls_peer_state() - update TDLS peer state
6357 * @handle: wma handle
6358 * @peerStateParams: TDLS peer state params
6359 *
6360 * Return: 0 for success or error code
6361 */
6362int wma_update_tdls_peer_state(WMA_HANDLE handle,
6363 tTdlsPeerStateParams *peerStateParams)
6364{
6365 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006366 uint32_t i;
6367 ol_txrx_pdev_handle pdev;
6368 uint8_t peer_id;
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07006369 ol_txrx_peer_handle peer;
6370 uint8_t *peer_mac_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006371 int ret = 0;
Kabilan Kannanc89fe712016-07-21 06:57:12 -07006372 uint32_t *ch_mhz = NULL;
Poddar, Siddarth5a91f5b2016-04-28 12:24:10 +05306373 bool restore_last_peer = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006374
6375 if (!wma_handle || !wma_handle->wmi_handle) {
6376 WMA_LOGE("%s: WMA is closed, can not issue cmd", __func__);
6377 ret = -EINVAL;
6378 goto end_tdls_peer_state;
6379 }
6380
6381 /* peer capability info is valid only when peer state is connected */
6382 if (WMA_TDLS_PEER_STATE_CONNECTED != peerStateParams->peerState) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306383 qdf_mem_zero(&peerStateParams->peerCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006384 sizeof(tTdlsPeerCapParams));
6385 }
6386
Kabilan Kannanc89fe712016-07-21 06:57:12 -07006387 if (peerStateParams->peerCap.peerChanLen) {
6388 ch_mhz = qdf_mem_malloc(sizeof(uint32_t) *
6389 peerStateParams->peerCap.peerChanLen);
6390 if (ch_mhz == NULL) {
6391 WMA_LOGE("%s: memory allocation failed", __func__);
6392 ret = -ENOMEM;
6393 goto end_tdls_peer_state;
6394 }
Naveen Rawat35804772016-06-27 15:40:28 -07006395 }
6396
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006397 for (i = 0; i < peerStateParams->peerCap.peerChanLen; ++i) {
Govind Singhaa64c242016-03-08 11:31:49 +05306398 ch_mhz[i] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006399 cds_chan_to_freq(peerStateParams->peerCap.peerChan[i].
6400 chanId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006401 }
6402
Govind Singhaa64c242016-03-08 11:31:49 +05306403 if (wmi_unified_update_tdls_peer_state_cmd(wma_handle->wmi_handle,
6404 (struct tdls_peer_state_params *)peerStateParams,
6405 ch_mhz)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006406 WMA_LOGE("%s: failed to send tdls peer update state command",
6407 __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006408 ret = -EIO;
6409 goto end_tdls_peer_state;
6410 }
6411
6412 /* in case of teardown, remove peer from fw */
6413 if (WMA_TDLS_PEER_STATE_TEARDOWN == peerStateParams->peerState) {
Anurag Chouhan6d760662016-02-20 16:05:43 +05306414 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006415 if (!pdev) {
6416 WMA_LOGE("%s: Failed to find pdev", __func__);
6417 ret = -EIO;
6418 goto end_tdls_peer_state;
6419 }
6420
6421 peer = ol_txrx_find_peer_by_addr(pdev,
6422 peerStateParams->peerMacAddr,
6423 &peer_id);
6424 if (!peer) {
6425 WMA_LOGE("%s: Failed to get peer handle using peer mac %pM",
6426 __func__, peerStateParams->peerMacAddr);
6427 ret = -EIO;
6428 goto end_tdls_peer_state;
6429 }
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07006430 peer_mac_addr = ol_txrx_peer_get_peer_mac_addr(peer);
Poddar, Siddarth5a91f5b2016-04-28 12:24:10 +05306431 restore_last_peer = is_vdev_restore_last_peer(peer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006432
6433 WMA_LOGD("%s: calling wma_remove_peer for peer " MAC_ADDRESS_STR
6434 " vdevId: %d", __func__,
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07006435 MAC_ADDR_ARRAY(peer_mac_addr),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006436 peerStateParams->vdevId);
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07006437 wma_remove_peer(wma_handle, peer_mac_addr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006438 peerStateParams->vdevId, peer, false);
Poddar, Siddarth5a91f5b2016-04-28 12:24:10 +05306439 ol_txrx_update_last_real_peer(pdev, peer, &peer_id,
6440 restore_last_peer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006441 }
6442
6443end_tdls_peer_state:
Kabilan Kannanc89fe712016-07-21 06:57:12 -07006444 if (ch_mhz)
6445 qdf_mem_free(ch_mhz);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006446 if (peerStateParams)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306447 qdf_mem_free(peerStateParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006448 return ret;
6449}
6450#endif /* FEATURE_WLAN_TDLS */
6451
6452
6453/**
6454 * wma_dfs_attach() - Attach DFS methods to the umac state.
6455 * @dfs_ic: ieee80211com ptr
6456 *
6457 * Return: Return ieee80211com ptr with updated info
6458 */
6459struct ieee80211com *wma_dfs_attach(struct ieee80211com *dfs_ic)
6460{
6461 /*Allocate memory for dfs_ic before passing it up to dfs_attach() */
6462 dfs_ic = (struct ieee80211com *)
6463 os_malloc(NULL, sizeof(struct ieee80211com), GFP_ATOMIC);
6464 if (dfs_ic == NULL) {
6465 WMA_LOGE("%s:Allocation of dfs_ic failed %zu",
6466 __func__, sizeof(struct ieee80211com));
6467 return NULL;
6468 }
6469 OS_MEMZERO(dfs_ic, sizeof(struct ieee80211com));
6470 /* DFS pattern matching hooks */
6471 dfs_ic->ic_dfs_attach = ol_if_dfs_attach;
6472 dfs_ic->ic_dfs_disable = ol_if_dfs_disable;
6473 dfs_ic->ic_find_channel = ieee80211_find_channel;
6474 dfs_ic->ic_dfs_enable = ol_if_dfs_enable;
6475 dfs_ic->ic_ieee2mhz = ieee80211_ieee2mhz;
6476
6477 /* Hardware facing hooks */
6478 dfs_ic->ic_get_ext_busy = ol_if_dfs_get_ext_busy;
6479 dfs_ic->ic_get_mib_cycle_counts_pct =
6480 ol_if_dfs_get_mib_cycle_counts_pct;
6481 dfs_ic->ic_get_TSF64 = ol_if_get_tsf64;
6482
6483 /* NOL related hooks */
6484 dfs_ic->ic_dfs_usenol = ol_if_dfs_usenol;
6485 /*
6486 * Hooks from wma/dfs/ back
6487 * into the PE/SME
6488 * and shared DFS code
6489 */
6490 dfs_ic->ic_dfs_notify_radar = ieee80211_mark_dfs;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306491 qdf_spinlock_create(&dfs_ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006492 /* Initializes DFS Data Structures and queues */
6493 dfs_attach(dfs_ic);
6494
6495 return dfs_ic;
6496}
6497
6498/**
6499 * wma_dfs_detach() - Detach DFS methods
6500 * @dfs_ic: ieee80211com ptr
6501 *
6502 * Return: none
6503 */
6504void wma_dfs_detach(struct ieee80211com *dfs_ic)
6505{
6506 dfs_detach(dfs_ic);
6507
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306508 qdf_spinlock_destroy(&dfs_ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006509 if (NULL != dfs_ic->ic_curchan) {
6510 OS_FREE(dfs_ic->ic_curchan);
6511 dfs_ic->ic_curchan = NULL;
6512 }
6513
6514 OS_FREE(dfs_ic);
6515}
6516
6517/**
6518 * wma_dfs_configure() - configure dfs
6519 * @ic: ieee80211com ptr
6520 *
6521 * Configures Radar Filters during
6522 * vdev start/channel change/regulatory domain
6523 * change.This Configuration enables to program
6524 * the DFS pattern matching module.
6525 *
6526 * Return: none
6527 */
6528void wma_dfs_configure(struct ieee80211com *ic)
6529{
6530 struct ath_dfs_radar_tab_info rinfo;
6531 int dfsdomain;
6532 int radar_enabled_status = 0;
6533 if (ic == NULL) {
6534 WMA_LOGE("%s: DFS ic is Invalid", __func__);
6535 return;
6536 }
6537
6538 dfsdomain = ic->current_dfs_regdomain;
6539
6540 /* Fetch current radar patterns from the lmac */
6541 OS_MEMZERO(&rinfo, sizeof(rinfo));
6542
6543 /*
6544 * Look up the current DFS
6545 * regulatory domain and decide
6546 * which radar pulses to use.
6547 */
6548 switch (dfsdomain) {
Amar Singhala7bb01b2016-01-27 11:31:59 -08006549 case DFS_FCC_REGION:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006550 WMA_LOGI("%s: DFS-FCC domain", __func__);
Amar Singhala7bb01b2016-01-27 11:31:59 -08006551 rinfo.dfsdomain = DFS_FCC_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006552 rinfo.dfs_radars = dfs_fcc_radars;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306553 rinfo.numradars = QDF_ARRAY_SIZE(dfs_fcc_radars);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006554 rinfo.b5pulses = dfs_fcc_bin5pulses;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306555 rinfo.numb5radars = QDF_ARRAY_SIZE(dfs_fcc_bin5pulses);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006556 break;
Amar Singhala7bb01b2016-01-27 11:31:59 -08006557 case DFS_ETSI_REGION:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006558 WMA_LOGI("%s: DFS-ETSI domain", __func__);
Amar Singhala7bb01b2016-01-27 11:31:59 -08006559 rinfo.dfsdomain = DFS_ETSI_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006560 rinfo.dfs_radars = dfs_etsi_radars;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306561 rinfo.numradars = QDF_ARRAY_SIZE(dfs_etsi_radars);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006562 rinfo.b5pulses = NULL;
6563 rinfo.numb5radars = 0;
6564 break;
Amar Singhala7bb01b2016-01-27 11:31:59 -08006565 case DFS_MKK_REGION:
6566 WMA_LOGI("%s: DFS-MKK domain", __func__);
6567 rinfo.dfsdomain = DFS_MKK_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006568 rinfo.dfs_radars = dfs_mkk4_radars;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306569 rinfo.numradars = QDF_ARRAY_SIZE(dfs_mkk4_radars);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006570 rinfo.b5pulses = dfs_jpn_bin5pulses;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306571 rinfo.numb5radars = QDF_ARRAY_SIZE(dfs_jpn_bin5pulses);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006572 break;
6573 default:
6574 WMA_LOGI("%s: DFS-UNINT domain", __func__);
Amar Singhala7bb01b2016-01-27 11:31:59 -08006575 rinfo.dfsdomain = DFS_UNINIT_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006576 rinfo.dfs_radars = NULL;
6577 rinfo.numradars = 0;
6578 rinfo.b5pulses = NULL;
6579 rinfo.numb5radars = 0;
6580 break;
6581 }
6582
6583 rinfo.dfs_pri_multiplier = ic->dfs_pri_multiplier;
6584
6585 /*
6586 * Set the regulatory domain,
6587 * radar pulse table and enable
6588 * radar events if required.
6589 * dfs_radar_enable() returns
6590 * 0 on success and non-zero
6591 * failure.
6592 */
6593 radar_enabled_status = dfs_radar_enable(ic, &rinfo);
6594 if (radar_enabled_status != DFS_STATUS_SUCCESS) {
6595 WMA_LOGE("%s[%d]: DFS- Radar Detection Enabling Failed",
6596 __func__, __LINE__);
6597 }
6598}
6599
6600/**
6601 * wma_dfs_configure_channel() - configure DFS channel
6602 * @dfs_ic: ieee80211com ptr
Siddarth Poddar17dc4712016-03-09 16:30:27 +05306603 * @band_center_freq1: center frequency 1
6604 * @band_center_freq2: center frequency 2
6605 * (valid only for 11ac vht 80plus80 mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006606 * @ req: vdev start request
6607 *
6608 * Set the Channel parameters in to DFS module
6609 * Also,configure the DFS radar filters for
6610 * matching the DFS phyerrors.
6611 *
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306612 * Return: dfs_ieee80211_channel / NULL for error
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006613 */
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306614struct dfs_ieee80211_channel *wma_dfs_configure_channel(
6615 struct ieee80211com *dfs_ic,
Siddarth Poddar17dc4712016-03-09 16:30:27 +05306616 uint32_t band_center_freq1,
6617 uint32_t band_center_freq2,
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306618 struct wma_vdev_start_req
6619 *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006620{
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006621 uint8_t ext_channel;
6622
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006623 if (dfs_ic == NULL) {
6624 WMA_LOGE("%s: DFS ic is Invalid", __func__);
6625 return NULL;
6626 }
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05306627
6628 if (!dfs_ic->ic_curchan) {
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306629 dfs_ic->ic_curchan = (struct dfs_ieee80211_channel *)os_malloc(
6630 NULL,
6631 sizeof(struct dfs_ieee80211_channel),
6632 GFP_ATOMIC);
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05306633 if (dfs_ic->ic_curchan == NULL) {
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306634 WMA_LOGE(
6635 "%s: allocation of dfs_ic->ic_curchan failed %zu",
6636 __func__, sizeof(struct dfs_ieee80211_channel));
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05306637 return NULL;
6638 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006639 }
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05306640
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306641 OS_MEMZERO(dfs_ic->ic_curchan, sizeof(struct dfs_ieee80211_channel));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006642
6643 dfs_ic->ic_curchan->ic_ieee = req->chan;
Siddarth Poddar17dc4712016-03-09 16:30:27 +05306644 dfs_ic->ic_curchan->ic_freq = cds_chan_to_freq(req->chan);
6645 dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg1 = band_center_freq1;
6646 dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg2 = band_center_freq2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006647 dfs_ic->ic_curchan->ic_pri_freq_center_freq_mhz_separation =
6648 dfs_ic->ic_curchan->ic_freq -
6649 dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg1;
6650
6651 if ((dfs_ic->ic_curchan->ic_ieee >= WMA_11A_CHANNEL_BEGIN) &&
6652 (dfs_ic->ic_curchan->ic_ieee <= WMA_11A_CHANNEL_END)) {
6653 dfs_ic->ic_curchan->ic_flags |= IEEE80211_CHAN_5GHZ;
6654 }
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006655
6656 switch (req->chan_width) {
6657 case CH_WIDTH_20MHZ:
6658 dfs_ic->ic_curchan->ic_flags |=
6659 (req->vht_capable ? IEEE80211_CHAN_VHT20 :
6660 IEEE80211_CHAN_HT20);
6661 break;
6662 case CH_WIDTH_40MHZ:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006663 if (req->chan < req->ch_center_freq_seg0)
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006664 dfs_ic->ic_curchan->ic_flags |=
6665 (req->vht_capable ?
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006666 IEEE80211_CHAN_VHT40PLUS :
6667 IEEE80211_CHAN_HT40PLUS);
6668 else
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006669 dfs_ic->ic_curchan->ic_flags |=
6670 (req->vht_capable ?
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006671 IEEE80211_CHAN_VHT40MINUS :
6672 IEEE80211_CHAN_HT40MINUS);
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006673 break;
6674 case CH_WIDTH_80MHZ:
6675 dfs_ic->ic_curchan->ic_flags |= IEEE80211_CHAN_VHT80;
6676 break;
6677 case CH_WIDTH_80P80MHZ:
Siddarth Poddar17dc4712016-03-09 16:30:27 +05306678 ext_channel = cds_freq_to_chan(band_center_freq2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006679 dfs_ic->ic_curchan->ic_flags |=
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006680 IEEE80211_CHAN_VHT80P80;
6681 dfs_ic->ic_curchan->ic_freq_ext =
Siddarth Poddar17dc4712016-03-09 16:30:27 +05306682 band_center_freq2;
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006683 dfs_ic->ic_curchan->ic_ieee_ext = ext_channel;
6684
6685 /* verify both the 80MHz are DFS bands or not */
Rajeev Kumara3f6c2d2016-04-15 12:47:41 -07006686 if ((CHANNEL_STATE_DFS ==
6687 cds_get_5g_bonded_channel_state(req->chan ,
6688 CH_WIDTH_80MHZ)) &&
6689 (CHANNEL_STATE_DFS == cds_get_5g_bonded_channel_state(
6690 ext_channel - WMA_80MHZ_START_CENTER_CH_DIFF,
6691 CH_WIDTH_80MHZ)))
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006692 dfs_ic->ic_curchan->ic_80p80_both_dfs = true;
6693 break;
6694 case CH_WIDTH_160MHZ:
6695 dfs_ic->ic_curchan->ic_flags |=
6696 IEEE80211_CHAN_VHT160;
6697 break;
6698 default:
6699 WMA_LOGE(
6700 "%s: Recieved a wrong channel width %d",
6701 __func__, req->chan_width);
6702 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006703 }
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006704
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006705 dfs_ic->ic_curchan->ic_flagext |= IEEE80211_CHAN_DFS;
6706
6707 if (req->oper_mode == BSS_OPERATIONAL_MODE_AP) {
6708 dfs_ic->ic_opmode = IEEE80211_M_HOSTAP;
6709 dfs_ic->vdev_id = req->vdev_id;
6710 }
6711
6712 dfs_ic->dfs_pri_multiplier = req->dfs_pri_multiplier;
6713
6714 /*
6715 * Configuring the DFS with current channel and the radar filters
6716 */
6717 wma_dfs_configure(dfs_ic);
6718 WMA_LOGI("%s: DFS- CHANNEL CONFIGURED", __func__);
6719 return dfs_ic->ic_curchan;
6720}
6721
6722
6723/**
6724 * wma_set_dfs_region() - set DFS region
6725 * @wma: wma handle
6726 *
6727 * Configure the DFS region for DFS radar filter initialization
6728 *
6729 * Return: none
6730 */
6731void wma_set_dfs_region(tp_wma_handle wma, uint8_t dfs_region)
6732{
6733 /* dfs information is passed */
Amar Singhala7bb01b2016-01-27 11:31:59 -08006734 if (dfs_region > DFS_MKK_REGION || dfs_region == DFS_UNINIT_REGION)
6735 /* assign DFS_FCC_REGION as default region*/
6736 wma->dfs_ic->current_dfs_regdomain = DFS_FCC_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006737 else
6738 wma->dfs_ic->current_dfs_regdomain = dfs_region;
6739
6740 WMA_LOGI("%s: DFS Region Domain: %d", __func__,
6741 wma->dfs_ic->current_dfs_regdomain);
6742}
6743
6744/**
6745 * wma_get_channels() - prepare dfs radar channel list
6746 * @ichan: channel
6747 * @chan_list: return channel list
6748 *
6749 * Return: return number of channels
6750 */
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306751int wma_get_channels(struct dfs_ieee80211_channel *ichan,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006752 struct wma_dfs_radar_channel_list *chan_list)
6753{
6754 uint8_t center_chan = cds_freq_to_chan(ichan->ic_vhtop_ch_freq_seg1);
Vishwajith Upendrabf673e72016-01-19 16:05:40 -08006755 int count = 0;
6756 int start_channel = 0;
6757 int loop;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006758
6759 chan_list->nchannels = 0;
6760
Vishwajith Upendrabf673e72016-01-19 16:05:40 -08006761 if (IEEE80211_IS_CHAN_11AC_VHT160(ichan)) {
6762 /*
6763 * In 160MHz channel width, need to
6764 * check if each of the 8 20MHz channel
6765 * is DFS before adding to the NOL list.
6766 * As it is possible that part of the
6767 * 160MHz can be Non-DFS channels.
6768 */
6769 start_channel = center_chan - WMA_160MHZ_START_CENTER_CH_DIFF;
6770 for (loop = 0; loop < WMA_DFS_MAX_20M_SUB_CH; loop++) {
6771 if (cds_get_channel_state(start_channel +
6772 (loop * WMA_NEXT_20MHZ_START_CH_DIFF)) ==
6773 CHANNEL_STATE_DFS) {
6774 chan_list->channels[count] = start_channel +
6775 (loop * WMA_NEXT_20MHZ_START_CH_DIFF);
6776 count++;
6777 }
6778 }
6779 chan_list->nchannels = count;
6780 } else if (IEEE80211_IS_CHAN_11AC_VHT80P80(ichan)) {
6781 chan_list->nchannels = 4;
6782 /*
6783 * If SAP is operating in 80p80 mode, either
6784 * one of the two 80 segments or both the 80
6785 * segments can be DFS channels, so need to
6786 * identify on which 80 segment radar has
6787 * been detected and only add those channels
6788 * to the NOL list. center frequency should be
6789 * based on the segment id passed as part of
6790 * channel information in radar indication.
6791 */
6792 if (ichan->ic_radar_found_segid == DFS_80P80_SEG1)
6793 center_chan =
6794 cds_freq_to_chan(ichan->ic_vhtop_ch_freq_seg2);
6795 chan_list->channels[0] = center_chan - 6;
6796 chan_list->channels[1] = center_chan - 2;
6797 chan_list->channels[2] = center_chan + 2;
6798 chan_list->channels[3] = center_chan + 6;
6799 } else if (IEEE80211_IS_CHAN_11AC_VHT80(ichan)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006800 chan_list->nchannels = 4;
6801 chan_list->channels[0] = center_chan - 6;
6802 chan_list->channels[1] = center_chan - 2;
6803 chan_list->channels[2] = center_chan + 2;
6804 chan_list->channels[3] = center_chan + 6;
6805 } else if (IEEE80211_IS_CHAN_11N_HT40(ichan) ||
6806 IEEE80211_IS_CHAN_11AC_VHT40(ichan)) {
6807 chan_list->nchannels = 2;
6808 chan_list->channels[0] = center_chan - 2;
6809 chan_list->channels[1] = center_chan + 2;
6810 } else {
6811 chan_list->nchannels = 1;
6812 chan_list->channels[0] = center_chan;
6813 }
6814
6815 return chan_list->nchannels;
6816}
6817
6818
6819/**
6820 * wma_dfs_indicate_radar() - Indicate Radar to SAP/HDD
6821 * @ic: ieee80211com ptr
6822 * @ichan: ieee 80211 channel
6823 *
6824 * Return: 0 for success or error code
6825 */
6826int wma_dfs_indicate_radar(struct ieee80211com *ic,
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306827 struct dfs_ieee80211_channel *ichan)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006828{
6829 tp_wma_handle wma;
6830 void *hdd_ctx;
6831 struct wma_dfs_radar_indication *radar_event;
6832 struct wma_dfs_radar_ind wma_radar_event;
6833 tpAniSirGlobal pmac = NULL;
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05306834 bool indication_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006835
Anurag Chouhan6d760662016-02-20 16:05:43 +05306836 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006837 if (wma == NULL) {
6838 WMA_LOGE("%s: DFS- Invalid wma", __func__);
6839 return -ENOENT;
6840 }
6841
Anurag Chouhan6d760662016-02-20 16:05:43 +05306842 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006843 pmac = (tpAniSirGlobal)
Anurag Chouhan6d760662016-02-20 16:05:43 +05306844 cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006845
6846 if (!pmac) {
6847 WMA_LOGE("%s: Invalid MAC handle", __func__);
6848 return -ENOENT;
6849 }
6850
6851 if (wma->dfs_ic != ic) {
6852 WMA_LOGE("%s:DFS- Invalid WMA handle", __func__);
6853 return -ENOENT;
6854 }
6855 radar_event = (struct wma_dfs_radar_indication *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306856 qdf_mem_malloc(sizeof(struct wma_dfs_radar_indication));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006857 if (radar_event == NULL) {
6858 WMA_LOGE("%s:DFS- Invalid radar_event", __func__);
6859 return -ENOMEM;
6860 }
6861
6862 /*
6863 * Do not post multiple Radar events on the same channel.
6864 * But, when DFS test mode is enabled, allow multiple dfs
6865 * radar events to be posted on the same channel.
6866 */
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306867 qdf_spin_lock_bh(&ic->chan_lock);
Edhar, Mahesh Kumar35d9b2e2015-10-26 17:06:23 +05306868 if (!pmac->sap.SapDfsInfo.disable_dfs_ch_switch)
6869 wma->dfs_ic->disable_phy_err_processing = true;
6870
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006871 if ((ichan->ic_ieee != (wma->dfs_ic->last_radar_found_chan)) ||
6872 (pmac->sap.SapDfsInfo.disable_dfs_ch_switch == true)) {
6873 wma->dfs_ic->last_radar_found_chan = ichan->ic_ieee;
6874 /* Indicate the radar event to HDD to stop the netif Tx queues */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006875 wma_radar_event.chan_freq = ichan->ic_freq;
6876 wma_radar_event.dfs_radar_status = WMA_DFS_RADAR_FOUND;
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05306877 indication_status =
6878 wma->dfs_radar_indication_cb(hdd_ctx, &wma_radar_event);
6879 if (indication_status == false) {
6880 WMA_LOGE("%s:Application triggered channel switch in progress!.. drop radar event indiaction to SAP",
6881 __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306882 qdf_mem_free(radar_event);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306883 qdf_spin_unlock_bh(&ic->chan_lock);
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05306884 return 0;
6885 }
6886
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006887 WMA_LOGE("%s:DFS- RADAR INDICATED TO HDD", __func__);
6888
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05306889 wma_radar_event.ieee_chan_number = ichan->ic_ieee;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006890 /*
6891 * Indicate to the radar event to SAP to
6892 * select a new channel and set CSA IE
6893 */
6894 radar_event->vdev_id = ic->vdev_id;
6895 wma_get_channels(ichan, &radar_event->chan_list);
6896 radar_event->dfs_radar_status = WMA_DFS_RADAR_FOUND;
6897 radar_event->use_nol = ic->ic_dfs_usenol(ic);
6898 wma_send_msg(wma, WMA_DFS_RADAR_IND, (void *)radar_event, 0);
6899 WMA_LOGE("%s:DFS- WMA_DFS_RADAR_IND Message Posted", __func__);
6900 }
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306901 qdf_spin_unlock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006902
6903 return 0;
6904}
6905
6906#ifdef WLAN_FEATURE_MEMDUMP
6907/*
6908 * wma_process_fw_mem_dump_req() - Function to request fw memory dump from
6909 * firmware
6910 * @wma: Pointer to WMA handle
6911 * @mem_dump_req: Pointer for mem_dump_req
6912 *
6913 * This function sends memory dump request to firmware
6914 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306915 * Return: QDF_STATUS_SUCCESS for success otherwise failure
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006916 *
6917 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306918QDF_STATUS wma_process_fw_mem_dump_req(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006919 struct fw_dump_req *mem_dump_req)
6920{
Govind Singhaa64c242016-03-08 11:31:49 +05306921 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006922
6923 if (!mem_dump_req || !wma) {
6924 WMA_LOGE(FL("input pointer is NULL"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306925 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006926 }
6927
Govind Singhaa64c242016-03-08 11:31:49 +05306928 ret = wmi_unified_process_fw_mem_dump_cmd(wma->wmi_handle,
6929 (struct fw_dump_req_param *) mem_dump_req);
6930 if (ret)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306931 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006932
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306933 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006934}
6935
6936/**
6937 * wma_fw_mem_dump_rsp() - send fw mem dump response to SME
6938 *
6939 * @req_id - request id.
6940 * @status - copy status from the firmware.
6941 *
6942 * This function is called by the memory dump response handler to
6943 * indicate SME that firmware dump copy is complete
6944 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306945 * Return: QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006946 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306947static QDF_STATUS wma_fw_mem_dump_rsp(uint32_t req_id, uint32_t status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006948{
6949 struct fw_dump_rsp *dump_rsp;
6950 cds_msg_t sme_msg = {0};
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306951 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006952
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306953 dump_rsp = qdf_mem_malloc(sizeof(*dump_rsp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006954
6955 if (!dump_rsp) {
6956 WMA_LOGE(FL("Memory allocation failed."));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306957 qdf_status = QDF_STATUS_E_NOMEM;
6958 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006959 }
6960
6961 WMA_LOGI(FL("FW memory dump copy complete status: %d for request: %d"),
6962 status, req_id);
6963
6964 dump_rsp->request_id = req_id;
6965 dump_rsp->dump_complete = status;
6966
6967 sme_msg.type = eWNI_SME_FW_DUMP_IND;
6968 sme_msg.bodyptr = dump_rsp;
6969 sme_msg.bodyval = 0;
6970
Anurag Chouhan6d760662016-02-20 16:05:43 +05306971 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306972 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006973 WMA_LOGE(FL("Fail to post fw mem dump ind msg"));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306974 qdf_mem_free(dump_rsp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006975 }
6976
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306977 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006978}
6979
6980/**
6981 * wma_fw_mem_dump_event_handler() - handles fw memory dump event
6982 *
6983 * @handle: pointer to wma handle.
6984 * @cmd_param_info: pointer to TLV info received in the event.
6985 * @len: length of data in @cmd_param_info
6986 *
6987 * This function is a handler for firmware memory dump event.
6988 *
6989 * Return: integer (0 for success and error code otherwise)
6990 */
6991int wma_fw_mem_dump_event_handler(void *handle, u_int8_t *cmd_param_info,
6992 u_int32_t len)
6993{
6994 WMI_UPDATE_FW_MEM_DUMP_EVENTID_param_tlvs *param_buf;
6995 wmi_update_fw_mem_dump_fixed_param *event;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306996 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006997
6998 param_buf =
6999 (WMI_UPDATE_FW_MEM_DUMP_EVENTID_param_tlvs *) cmd_param_info;
7000 if (!param_buf) {
7001 WMA_LOGA("%s: Invalid stats event", __func__);
7002 return -EINVAL;
7003 }
7004
7005 event = param_buf->fixed_param;
7006
7007 status = wma_fw_mem_dump_rsp(event->request_id,
7008 event->fw_mem_dump_complete);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307009 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007010 WMA_LOGE("Error posting FW MEM DUMP RSP.");
7011 return -EINVAL;
7012 }
7013
7014 WMA_LOGI("FW MEM DUMP RSP posted successfully");
7015 return 0;
7016}
7017#endif /* WLAN_FEATURE_MEMDUMP */
7018
7019/*
7020 * wma_process_set_ie_info() - Function to send IE info to firmware
7021 * @wma: Pointer to WMA handle
7022 * @ie_data: Pointer for ie data
7023 *
7024 * This function sends IE information to firmware
7025 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307026 * Return: QDF_STATUS_SUCCESS for success otherwise failure
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007027 *
7028 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307029QDF_STATUS wma_process_set_ie_info(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007030 struct vdev_ie_info *ie_info)
7031{
Govind Singhaa64c242016-03-08 11:31:49 +05307032 struct vdev_ie_info_param cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007033 int ret;
7034
7035 if (!ie_info || !wma) {
7036 WMA_LOGE(FL("input pointer is NULL"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307037 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007038 }
7039
7040 /* Validate the input */
7041 if (ie_info->length <= 0) {
7042 WMA_LOGE(FL("Invalid IE length"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307043 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007044 }
7045
Govind Singhaa64c242016-03-08 11:31:49 +05307046 cmd.vdev_id = ie_info->vdev_id;
7047 cmd.ie_id = ie_info->ie_id;
7048 cmd.length = ie_info->length;
7049 cmd.data = ie_info->data;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007050
Govind Singhaa64c242016-03-08 11:31:49 +05307051 ret = wmi_unified_process_set_ie_info_cmd(wma->wmi_handle,
7052 &cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007053
7054 return ret;
7055}
7056
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307057/**
7058 * wma_get_bpf_caps_event_handler() - Event handler for get bpf capability
7059 * @handle: WMA global handle
7060 * @cmd_param_info: command event data
7061 * @len: Length of @cmd_param_info
7062 *
7063 * Return: 0 on Success or Errno on failure
7064 */
7065int wma_get_bpf_caps_event_handler(void *handle,
7066 u_int8_t *cmd_param_info,
7067 u_int32_t len)
7068{
7069 WMI_BPF_CAPABILIY_INFO_EVENTID_param_tlvs *param_buf;
7070 wmi_bpf_capability_info_evt_fixed_param *event;
7071 struct sir_bpf_get_offload *bpf_get_offload;
7072 tpAniSirGlobal pmac = (tpAniSirGlobal)cds_get_context(
7073 QDF_MODULE_ID_PE);
7074
7075 if (!pmac) {
7076 WMA_LOGE("%s: Invalid pmac", __func__);
7077 return -EINVAL;
7078 }
7079 if (!pmac->sme.pbpf_get_offload_cb) {
7080 WMA_LOGE("%s: Callback not registered", __func__);
7081 return -EINVAL;
7082 }
7083
7084 param_buf = (WMI_BPF_CAPABILIY_INFO_EVENTID_param_tlvs *)cmd_param_info;
7085 event = param_buf->fixed_param;
7086 bpf_get_offload = qdf_mem_malloc(sizeof(*bpf_get_offload));
7087
7088 if (!bpf_get_offload) {
7089 WMA_LOGP("%s: Memory allocation failed.", __func__);
7090 return -ENOMEM;
7091 }
7092
7093 bpf_get_offload->bpf_version = event->bpf_version;
7094 bpf_get_offload->max_bpf_filters = event->max_bpf_filters;
7095 bpf_get_offload->max_bytes_for_bpf_inst =
7096 event->max_bytes_for_bpf_inst;
7097 WMA_LOGD("%s: BPF capabilities version: %d max bpf filter size: %d",
7098 __func__, bpf_get_offload->bpf_version,
7099 bpf_get_offload->max_bytes_for_bpf_inst);
7100
7101 WMA_LOGD("%s: sending bpf capabilities event to hdd", __func__);
7102 pmac->sme.pbpf_get_offload_cb(pmac->hHdd, bpf_get_offload);
7103 qdf_mem_free(bpf_get_offload);
7104 return 0;
7105}
7106
7107/**
7108 * wma_get_bpf_capabilities - Send get bpf capability to firmware
7109 * @wma_handle: wma handle
7110 *
7111 * Return: QDF_STATUS enumeration.
7112 */
7113QDF_STATUS wma_get_bpf_capabilities(tp_wma_handle wma)
7114{
7115 QDF_STATUS status = QDF_STATUS_SUCCESS;
7116 wmi_bpf_get_capability_cmd_fixed_param *cmd;
7117 wmi_buf_t wmi_buf;
7118 uint32_t len;
7119 u_int8_t *buf_ptr;
7120
7121 if (!wma || !wma->wmi_handle) {
7122 WMA_LOGE(FL("WMA is closed, can not issue get BPF capab"));
7123 return QDF_STATUS_E_INVAL;
7124 }
7125
7126 if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
7127 WMI_SERVICE_BPF_OFFLOAD)) {
7128 WMA_LOGE(FL("BPF cababilities feature bit not enabled"));
7129 return QDF_STATUS_E_FAILURE;
7130 }
7131
7132 len = sizeof(*cmd);
7133 wmi_buf = wmi_buf_alloc(wma->wmi_handle, len);
7134 if (!wmi_buf) {
7135 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
7136 return QDF_STATUS_E_NOMEM;
7137 }
7138
7139 buf_ptr = (u_int8_t *) wmi_buf_data(wmi_buf);
7140 cmd = (wmi_bpf_get_capability_cmd_fixed_param *) buf_ptr;
7141 WMITLV_SET_HDR(&cmd->tlv_header,
7142 WMITLV_TAG_STRUC_wmi_bpf_get_capability_cmd_fixed_param,
7143 WMITLV_GET_STRUCT_TLVLEN(
7144 wmi_bpf_get_capability_cmd_fixed_param));
7145
7146 if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len,
7147 WMI_BPF_GET_CAPABILITY_CMDID)) {
7148 WMA_LOGE(FL("Failed to send BPF capability command"));
7149 wmi_buf_free(wmi_buf);
7150 return QDF_STATUS_E_FAILURE;
7151 }
7152 return status;
7153}
7154
7155/**
7156 * wma_set_bpf_instructions - Set bpf instructions to firmware
7157 * @wma: wma handle
7158 * @bpf_set_offload: Bpf offload information to set to firmware
7159 *
7160 * Return: QDF_STATUS enumeration
7161 */
7162QDF_STATUS wma_set_bpf_instructions(tp_wma_handle wma,
7163 struct sir_bpf_set_offload *bpf_set_offload)
7164{
7165 wmi_bpf_set_vdev_instructions_cmd_fixed_param *cmd;
7166 wmi_buf_t wmi_buf;
7167 uint32_t len = 0, len_aligned = 0;
7168 u_int8_t *buf_ptr;
7169
7170 if (!wma || !wma->wmi_handle) {
7171 WMA_LOGE("%s: WMA is closed, can not issue set BPF capability",
7172 __func__);
7173 return QDF_STATUS_E_INVAL;
7174 }
7175
7176 if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
7177 WMI_SERVICE_BPF_OFFLOAD)) {
7178 WMA_LOGE(FL("BPF offload feature Disabled"));
7179 return QDF_STATUS_E_NOSUPPORT;
7180 }
7181
7182 if (bpf_set_offload->total_length) {
7183 len_aligned = roundup(bpf_set_offload->current_length,
7184 sizeof(A_UINT32));
7185 len = len_aligned + WMI_TLV_HDR_SIZE;
7186 }
7187
7188 len += sizeof(*cmd);
7189 wmi_buf = wmi_buf_alloc(wma->wmi_handle, len);
7190 if (!wmi_buf) {
7191 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
7192 return QDF_STATUS_E_NOMEM;
7193 }
7194
7195 buf_ptr = (u_int8_t *) wmi_buf_data(wmi_buf);
7196 cmd = (wmi_bpf_set_vdev_instructions_cmd_fixed_param *) buf_ptr;
7197
7198 WMITLV_SET_HDR(&cmd->tlv_header,
7199 WMITLV_TAG_STRUC_wmi_bpf_set_vdev_instructions_cmd_fixed_param,
7200 WMITLV_GET_STRUCT_TLVLEN(
7201 wmi_bpf_set_vdev_instructions_cmd_fixed_param));
7202 cmd->vdev_id = bpf_set_offload->session_id;
7203 cmd->filter_id = bpf_set_offload->filter_id;
7204 cmd->total_length = bpf_set_offload->total_length;
7205 cmd->current_offset = bpf_set_offload->current_offset;
7206 cmd->current_length = bpf_set_offload->current_length;
7207
7208 if (bpf_set_offload->total_length) {
7209 buf_ptr +=
7210 sizeof(wmi_bpf_set_vdev_instructions_cmd_fixed_param);
7211 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, len_aligned);
7212 buf_ptr += WMI_TLV_HDR_SIZE;
7213 qdf_mem_copy(buf_ptr, bpf_set_offload->program,
7214 bpf_set_offload->current_length);
7215 qdf_mem_free(bpf_set_offload->program);
7216 }
7217
7218 if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len,
7219 WMI_BPF_SET_VDEV_INSTRUCTIONS_CMDID)) {
7220 WMA_LOGE(FL("Failed to send config bpf instructions command"));
7221 wmi_buf_free(wmi_buf);
7222 return QDF_STATUS_E_FAILURE;
7223 }
7224 return QDF_STATUS_SUCCESS;
7225}
Peng Xu8fdaa492016-06-22 10:20:47 -07007226
7227/**
7228 * wma_p2p_lo_start() - P2P listen offload start
7229 * @params: p2p listen offload parameters
7230 *
7231 * This function sends WMI command to start P2P listen offload.
7232 *
7233 * Return: QDF_STATUS enumeration
7234 */
7235QDF_STATUS wma_p2p_lo_start(struct sir_p2p_lo_start *params)
7236{
7237 wmi_buf_t buf;
7238 wmi_p2p_lo_start_cmd_fixed_param *cmd;
7239 int32_t len = sizeof(*cmd);
7240 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
7241 uint8_t *buf_ptr;
7242 int ret;
Peng Xu4225c152016-07-14 21:18:14 -07007243 int device_types_len_aligned, probe_resp_len_aligned;
Peng Xu8fdaa492016-06-22 10:20:47 -07007244
7245 if (NULL == wma) {
7246 WMA_LOGE("%s: wma context is NULL", __func__);
7247 return QDF_STATUS_E_INVAL;
7248 }
7249
Peng Xu4225c152016-07-14 21:18:14 -07007250 device_types_len_aligned = qdf_roundup(params->dev_types_len,
7251 sizeof(A_UINT32));
7252 probe_resp_len_aligned = qdf_roundup(params->probe_resp_len,
7253 sizeof(A_UINT32));
7254
7255 len += 2 * WMI_TLV_HDR_SIZE + device_types_len_aligned +
7256 probe_resp_len_aligned;
Peng Xu8fdaa492016-06-22 10:20:47 -07007257
7258 buf = wmi_buf_alloc(wma->wmi_handle, len);
7259 if (!buf) {
7260 WMA_LOGP("%s: failed to allocate memory for p2p lo start",
7261 __func__);
7262 return QDF_STATUS_E_NOMEM;
7263 }
7264
7265 cmd = (wmi_p2p_lo_start_cmd_fixed_param *)wmi_buf_data(buf);
7266 buf_ptr = (uint8_t *) wmi_buf_data(buf);
7267
7268 WMITLV_SET_HDR(&cmd->tlv_header,
7269 WMITLV_TAG_STRUC_wmi_p2p_lo_start_cmd_fixed_param,
7270 WMITLV_GET_STRUCT_TLVLEN(
7271 wmi_p2p_lo_start_cmd_fixed_param));
7272
7273 cmd->vdev_id = params->vdev_id;
7274 cmd->ctl_flags = params->ctl_flags;
7275 cmd->channel = params->freq;
7276 cmd->period = params->period;
7277 cmd->interval = params->interval;
7278 cmd->count = params->count;
Peng Xu4225c152016-07-14 21:18:14 -07007279 cmd->device_types_len = params->dev_types_len;
7280 cmd->prob_resp_len = params->probe_resp_len;
Peng Xu8fdaa492016-06-22 10:20:47 -07007281
7282 buf_ptr += sizeof(wmi_p2p_lo_start_cmd_fixed_param);
7283 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE,
Peng Xu4225c152016-07-14 21:18:14 -07007284 device_types_len_aligned);
Peng Xu8fdaa492016-06-22 10:20:47 -07007285 buf_ptr += WMI_TLV_HDR_SIZE;
7286 qdf_mem_copy(buf_ptr, params->device_types, params->dev_types_len);
7287
Peng Xu4225c152016-07-14 21:18:14 -07007288 buf_ptr += device_types_len_aligned;
7289 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, probe_resp_len_aligned);
Peng Xu8fdaa492016-06-22 10:20:47 -07007290 buf_ptr += WMI_TLV_HDR_SIZE;
7291 qdf_mem_copy(buf_ptr, params->probe_resp_tmplt, params->probe_resp_len);
7292
7293 WMA_LOGI("%s: Sending WMI_P2P_LO_START command, channel=%d, period=%d, interval=%d, count=%d",
7294 __func__, cmd->channel, cmd->period,
7295 cmd->interval, cmd->count);
7296
7297 ret = wmi_unified_cmd_send(wma->wmi_handle,
7298 buf, len,
7299 WMI_P2P_LISTEN_OFFLOAD_START_CMDID);
7300 if (ret) {
7301 WMA_LOGE("Failed to send p2p lo start: %d", ret);
7302 wmi_buf_free(buf);
7303 }
7304
7305 WMA_LOGI("%s: Successfully sent WMI_P2P_LO_START", __func__);
7306 wma->interfaces[params->vdev_id].p2p_lo_in_progress = true;
7307
7308 return ret;
7309}
7310
7311/**
7312 * wma_p2p_lo_stop() - P2P listen offload stop
7313 * @vdev_id: vdev identifier
7314 *
7315 * This function sends WMI command to stop P2P listen offload.
7316 *
7317 * Return: QDF_STATUS enumeration
7318 */
7319QDF_STATUS wma_p2p_lo_stop(u_int32_t vdev_id)
7320{
7321 wmi_buf_t buf;
7322 wmi_p2p_lo_stop_cmd_fixed_param *cmd;
7323 int32_t len;
7324 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
7325 int ret;
7326
7327 if (NULL == wma) {
7328 WMA_LOGE("%s: wma context is NULL", __func__);
7329 return QDF_STATUS_E_INVAL;
7330 }
7331
7332 len = sizeof(*cmd);
7333 buf = wmi_buf_alloc(wma->wmi_handle, len);
7334 if (!buf) {
7335 WMA_LOGP("%s: failed to allocate memory for p2p lo stop",
7336 __func__);
7337 return QDF_STATUS_E_NOMEM;
7338 }
7339 cmd = (wmi_p2p_lo_stop_cmd_fixed_param *)wmi_buf_data(buf);
7340
7341 WMITLV_SET_HDR(&cmd->tlv_header,
7342 WMITLV_TAG_STRUC_wmi_p2p_lo_stop_cmd_fixed_param,
7343 WMITLV_GET_STRUCT_TLVLEN(
7344 wmi_p2p_lo_stop_cmd_fixed_param));
7345
7346 cmd->vdev_id = vdev_id;
7347
7348 WMA_LOGI("%s: Sending WMI_P2P_LO_STOP command", __func__);
7349
7350 ret = wmi_unified_cmd_send(wma->wmi_handle,
7351 buf, len,
7352 WMI_P2P_LISTEN_OFFLOAD_STOP_CMDID);
7353 if (ret) {
7354 WMA_LOGE("Failed to send p2p lo stop: %d", ret);
7355 wmi_buf_free(buf);
7356 }
7357
7358 WMA_LOGI("%s: Successfully sent WMI_P2P_LO_STOP", __func__);
7359 wma->interfaces[vdev_id].p2p_lo_in_progress = false;
7360
7361 return ret;
7362}
7363
7364/**
7365 * wma_p2p_lo_event_handler() - p2p lo event
7366 * @handle: the WMA handle
7367 * @event_buf: buffer with the event parameters
7368 * @len: length of the buffer
7369 *
7370 * This function receives P2P listen offload stop event from FW and
7371 * pass the event information to upper layer.
7372 *
7373 * Return: 0 on success
7374 */
7375int wma_p2p_lo_event_handler(void *handle, uint8_t *event_buf,
7376 uint32_t len)
7377{
7378 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
7379 struct sir_p2p_lo_event *event;
7380 WMI_P2P_LISTEN_OFFLOAD_STOPPED_EVENTID_param_tlvs *param_tlvs;
7381 wmi_p2p_lo_stopped_event_fixed_param *fix_param;
7382 tpAniSirGlobal p_mac = cds_get_context(QDF_MODULE_ID_PE);
7383
7384 if (!p_mac) {
7385 WMA_LOGE("%s: Invalid p_mac", __func__);
7386 return -EINVAL;
7387 }
7388
7389 if (!p_mac->sme.p2p_lo_event_callback) {
7390 WMA_LOGE("%s: Callback not registered", __func__);
7391 return -EINVAL;
7392 }
7393
7394 param_tlvs = (WMI_P2P_LISTEN_OFFLOAD_STOPPED_EVENTID_param_tlvs *)
7395 event_buf;
7396 fix_param = param_tlvs->fixed_param;
7397 event = qdf_mem_malloc(sizeof(*event));
7398 if (event == NULL) {
7399 WMA_LOGE("Event allocation failed");
7400 return -ENOMEM;
7401 }
7402 event->vdev_id = fix_param->vdev_id;
7403 event->reason_code = fix_param->reason;
7404
7405 p_mac->sme.p2p_lo_event_callback(p_mac->hHdd, event);
7406
7407 wma->interfaces[event->vdev_id].p2p_lo_in_progress = false;
7408
7409 return 0;
7410}