blob: 89185a0b3ab5301ac21a53274b8e1669a46d49fd [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) |\
Selvaraj, Sridhar172cabc2016-07-05 15:19:24 +053091 (1 << WOW_EXTSCAN_EVENT)) |\
92 (1 << WOW_OEM_RESPONSE_EVENT)\
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080093
94#define WMA_WOW_SAP_WAKE_UP_EVENTS ((1 << WOW_PROBE_REQ_WPS_IE_EVENT) |\
95 (1 << WOW_PATTERN_MATCH_EVENT) |\
96 (1 << WOW_AUTH_REQ_EVENT) |\
97 (1 << WOW_ASSOC_REQ_EVENT) |\
98 (1 << WOW_DEAUTH_RECVD_EVENT) |\
99 (1 << WOW_DISASSOC_RECVD_EVENT) |\
100 (1 << WOW_HTT_EVENT))\
101
102static const uint8_t arp_ptrn[] = {0x08, 0x06};
103static const uint8_t arp_mask[] = {0xff, 0xff};
104static const uint8_t ns_ptrn[] = {0x86, 0xDD};
105static const uint8_t discvr_ptrn[] = {0xe0, 0x00, 0x00, 0xf8};
106static const uint8_t discvr_mask[] = {0xf0, 0x00, 0x00, 0xf8};
107
108#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
109/**
110 * wma_post_auto_shutdown_msg() - to post auto shutdown event to sme
111 *
112 * Return: 0 for success or error code
113 */
114static int wma_post_auto_shutdown_msg(void)
115{
116 tSirAutoShutdownEvtParams *auto_sh_evt;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530117 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800118 cds_msg_t sme_msg = { 0 };
119
120 auto_sh_evt = (tSirAutoShutdownEvtParams *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530121 qdf_mem_malloc(sizeof(tSirAutoShutdownEvtParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800122 if (!auto_sh_evt) {
123 WMA_LOGE(FL("No Mem"));
124 return -ENOMEM;
125 }
126
127 auto_sh_evt->shutdown_reason =
128 WMI_HOST_AUTO_SHUTDOWN_REASON_TIMER_EXPIRY;
129 sme_msg.type = eWNI_SME_AUTO_SHUTDOWN_IND;
130 sme_msg.bodyptr = auto_sh_evt;
131 sme_msg.bodyval = 0;
132
Anurag Chouhan6d760662016-02-20 16:05:43 +0530133 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530134 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800135 WMA_LOGE("Fail to post eWNI_SME_AUTO_SHUTDOWN_IND msg to SME");
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530136 qdf_mem_free(auto_sh_evt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800137 return -EINVAL;
138 }
139
140 return 0;
141}
142#endif
143/**
144 * wma_send_snr_request() - send request to fw to get RSSI stats
145 * @wma_handle: wma handle
146 * @pGetRssiReq: get RSSI request
147 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530148 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800149 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530150QDF_STATUS wma_send_snr_request(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800151 void *pGetRssiReq)
152{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800153 tAniGetRssiReq *pRssiBkUp = NULL;
154
155 /* command is in progess */
156 if (NULL != wma_handle->pGetRssiReq)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530157 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800158
159 /* create a copy of csrRssiCallback to send rssi value
160 * after wmi event
161 */
162 if (pGetRssiReq) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530163 pRssiBkUp = qdf_mem_malloc(sizeof(tAniGetRssiReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800164 if (!pRssiBkUp) {
165 WMA_LOGE("Failed to allocate memory for tAniGetRssiReq");
166 wma_handle->pGetRssiReq = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530167 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800168 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530169 qdf_mem_set(pRssiBkUp, sizeof(tAniGetRssiReq), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800170 pRssiBkUp->sessionId =
171 ((tAniGetRssiReq *) pGetRssiReq)->sessionId;
172 pRssiBkUp->rssiCallback =
173 ((tAniGetRssiReq *) pGetRssiReq)->rssiCallback;
174 pRssiBkUp->pDevContext =
175 ((tAniGetRssiReq *) pGetRssiReq)->pDevContext;
176 wma_handle->pGetRssiReq = (void *)pRssiBkUp;
177 }
178
Govind Singhaa64c242016-03-08 11:31:49 +0530179 if (wmi_unified_snr_request_cmd(wma_handle->wmi_handle)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800180 WMA_LOGE("Failed to send host stats request to fw");
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530181 qdf_mem_free(pRssiBkUp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800182 wma_handle->pGetRssiReq = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530183 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800184 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530185 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800186}
187
188/**
189 * wma_get_snr() - get RSSI from fw
190 * @psnr_req: request params
191 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530192 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800193 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530194QDF_STATUS wma_get_snr(tAniGetSnrReq *psnr_req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800195{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800196 tAniGetSnrReq *psnr_req_bkp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800197 tp_wma_handle wma_handle = NULL;
198 struct wma_txrx_node *intr;
199
Anurag Chouhan6d760662016-02-20 16:05:43 +0530200 wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800201
202 if (NULL == wma_handle) {
203 WMA_LOGE("%s : Failed to get wma_handle", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530204 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800205 }
206
207 intr = &wma_handle->interfaces[psnr_req->sessionId];
208 /* command is in progess */
209 if (NULL != intr->psnr_req) {
210 WMA_LOGE("%s : previous snr request is pending", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530211 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800212 }
213
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530214 psnr_req_bkp = qdf_mem_malloc(sizeof(tAniGetSnrReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800215 if (!psnr_req_bkp) {
216 WMA_LOGE("Failed to allocate memory for tAniGetSnrReq");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530217 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800218 }
219
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530220 qdf_mem_set(psnr_req_bkp, sizeof(tAniGetSnrReq), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800221 psnr_req_bkp->staId = psnr_req->staId;
222 psnr_req_bkp->pDevContext = psnr_req->pDevContext;
223 psnr_req_bkp->snrCallback = psnr_req->snrCallback;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800224 intr->psnr_req = (void *)psnr_req_bkp;
Govind Singhaa64c242016-03-08 11:31:49 +0530225
226 if (wmi_unified_snr_cmd(wma_handle->wmi_handle,
227 psnr_req->sessionId)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800228 WMA_LOGE("Failed to send host stats request to fw");
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530229 qdf_mem_free(psnr_req_bkp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800230 intr->psnr_req = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530231 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800232 }
233
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530234 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800235}
236
237/**
238 * wma_process_link_status_req() - process link status request from UMAC
239 * @wma: wma handle
240 * @pGetLinkStatus: get link params
241 *
242 * Return: none
243 */
244void wma_process_link_status_req(tp_wma_handle wma,
245 tAniGetLinkStatus *pGetLinkStatus)
246{
Govind Singhaa64c242016-03-08 11:31:49 +0530247 struct link_status_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800248 struct wma_txrx_node *iface =
249 &wma->interfaces[pGetLinkStatus->sessionId];
250
251 if (iface->plink_status_req) {
252 WMA_LOGE("%s:previous link status request is pending,deleting the new request",
253 __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530254 qdf_mem_free(pGetLinkStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800255 return;
256 }
257
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800258 iface->plink_status_req = pGetLinkStatus;
Govind Singhaa64c242016-03-08 11:31:49 +0530259 cmd.session_id = pGetLinkStatus->sessionId;
260 if (wmi_unified_link_status_req_cmd(wma->wmi_handle, &cmd)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800261 WMA_LOGE("Failed to send WMI link status request to fw");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800262 iface->plink_status_req = NULL;
263 goto end;
264 }
265
266 return;
267
268end:
269 wma_post_link_status(pGetLinkStatus, LINK_STATUS_LEGACY);
270}
271
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700272#ifdef WLAN_FEATURE_TSF
273/**
274 * wma_vdev_tsf_handler() - handle tsf event indicated by FW
275 * @handle: wma context
276 * @data: event buffer
277 * @data len: length of event buffer
278 *
279 * Return: 0 on success
280 */
281int wma_vdev_tsf_handler(void *handle, uint8_t *data, uint32_t data_len)
282{
283 cds_msg_t tsf_msg = {0};
284 WMI_VDEV_TSF_REPORT_EVENTID_param_tlvs *param_buf;
285 wmi_vdev_tsf_report_event_fixed_param *tsf_event;
286 struct stsf *ptsf;
287
288 if (data == NULL) {
289 WMA_LOGE("%s: invalid pointer", __func__);
290 return -EINVAL;
291 }
292 ptsf = qdf_mem_malloc(sizeof(*ptsf));
293 if (NULL == ptsf) {
294 WMA_LOGE("%s: failed to allocate tsf data structure", __func__);
295 return -ENOMEM;
296 }
297
298 param_buf = (WMI_VDEV_TSF_REPORT_EVENTID_param_tlvs *)data;
299 tsf_event = param_buf->fixed_param;
300
301 ptsf->vdev_id = tsf_event->vdev_id;
302 ptsf->tsf_low = tsf_event->tsf_low;
303 ptsf->tsf_high = tsf_event->tsf_high;
Manikandan Mohan5356c2b2016-04-03 15:51:35 -0700304 ptsf->soc_timer_low = tsf_event->qtimer_low;
305 ptsf->soc_timer_high = tsf_event->qtimer_high;
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700306
307 WMA_LOGD("%s: receive WMI_VDEV_TSF_REPORT_EVENTID ", __func__);
308 WMA_LOGD("%s: vdev_id = %u,tsf_low =%u, tsf_high = %u", __func__,
309 ptsf->vdev_id, ptsf->tsf_low, ptsf->tsf_high);
310
311 tsf_msg.type = eWNI_SME_TSF_EVENT;
312 tsf_msg.bodyptr = ptsf;
313 tsf_msg.bodyval = 0;
314
315 if (QDF_STATUS_SUCCESS !=
316 cds_mq_post_message(CDS_MQ_ID_SME, &tsf_msg)) {
317
318 WMA_LOGP("%s: Failed to post eWNI_SME_TSF_EVENT", __func__);
319 qdf_mem_free(ptsf);
320 return -EINVAL;
321 }
322 return 0;
323}
324
Manikandan Mohan5356c2b2016-04-03 15:51:35 -0700325#ifdef QCA_WIFI_3_0
326#define TSF_FW_ACTION_CMD TSF_TSTAMP_QTIMER_CAPTURE_REQ
327#else
328#define TSF_FW_ACTION_CMD TSF_TSTAMP_CAPTURE_REQ
329#endif
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700330/**
331 * wma_capture_tsf() - send wmi to fw to capture tsf
332 * @wma_handle: wma handler
333 * @vdev_id: vdev id
334 *
335 * Return: wmi send state
336 */
337QDF_STATUS wma_capture_tsf(tp_wma_handle wma_handle, uint32_t vdev_id)
338{
339 QDF_STATUS status = QDF_STATUS_SUCCESS;
340 wmi_buf_t buf;
341 wmi_vdev_tsf_tstamp_action_cmd_fixed_param *cmd;
342 int ret;
343 int len = sizeof(*cmd);
344
345 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
346 if (!buf) {
347 WMA_LOGP("%s: failed to allocate memory for cap tsf cmd",
348 __func__);
349 return QDF_STATUS_E_NOMEM;
350 }
351
352 cmd = (wmi_vdev_tsf_tstamp_action_cmd_fixed_param *) wmi_buf_data(buf);
353 cmd->vdev_id = vdev_id;
Manikandan Mohan5356c2b2016-04-03 15:51:35 -0700354 cmd->tsf_action = TSF_FW_ACTION_CMD;
355 WMA_LOGD("%s :vdev_id %u, tsf_cmd: %d", __func__, cmd->vdev_id,
356 cmd->tsf_action);
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700357
358 WMITLV_SET_HDR(&cmd->tlv_header,
359 WMITLV_TAG_STRUC_wmi_vdev_tsf_tstamp_action_cmd_fixed_param,
360 WMITLV_GET_STRUCT_TLVLEN(
361 wmi_vdev_tsf_tstamp_action_cmd_fixed_param));
362
363 ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
364 WMI_VDEV_TSF_TSTAMP_ACTION_CMDID);
365 if (ret != EOK) {
366 WMA_LOGE("wmi_unified_cmd_send returned Error %d", status);
367 status = QDF_STATUS_E_FAILURE;
368 goto error;
369 }
370
371 return QDF_STATUS_SUCCESS;
372
373error:
374 if (buf)
375 wmi_buf_free(buf);
376 return status;
377}
378
379/**
380 * wma_reset_tsf_gpio() - send wmi to fw to reset GPIO
381 * @wma_handle: wma handler
382 * @vdev_id: vdev id
383 *
384 * Return: wmi send state
385 */
386QDF_STATUS wma_reset_tsf_gpio(tp_wma_handle wma_handle, uint32_t vdev_id)
387{
388 QDF_STATUS status = QDF_STATUS_SUCCESS;
389 wmi_buf_t buf;
390 wmi_vdev_tsf_tstamp_action_cmd_fixed_param *cmd;
391 int ret;
392 int len = sizeof(*cmd);
393 uint8_t *buf_ptr;
394
395 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
396 if (!buf) {
397 WMA_LOGP("%s: failed to allocate memory for reset tsf gpio",
398 __func__);
399 return QDF_STATUS_E_NOMEM;
400 }
401
402 buf_ptr = (uint8_t *) wmi_buf_data(buf);
403 cmd = (wmi_vdev_tsf_tstamp_action_cmd_fixed_param *) buf_ptr;
404 cmd->vdev_id = vdev_id;
405 cmd->tsf_action = TSF_TSTAMP_CAPTURE_RESET;
406
407 WMA_LOGD("%s :vdev_id %u, TSF_TSTAMP_CAPTURE_RESET", __func__,
408 cmd->vdev_id);
409
410 WMITLV_SET_HDR(&cmd->tlv_header,
411 WMITLV_TAG_STRUC_wmi_vdev_tsf_tstamp_action_cmd_fixed_param,
412 WMITLV_GET_STRUCT_TLVLEN(
413 wmi_vdev_tsf_tstamp_action_cmd_fixed_param));
414
415 ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
416 WMI_VDEV_TSF_TSTAMP_ACTION_CMDID);
417
418 if (ret != EOK) {
419 WMA_LOGE("wmi_unified_cmd_send returned Error %d", status);
420 status = QDF_STATUS_E_FAILURE;
421 goto error;
422 }
423 return QDF_STATUS_SUCCESS;
424
425error:
426 if (buf)
427 wmi_buf_free(buf);
428 return status;
429}
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700430
Manikandan Mohan976e7562016-03-15 16:33:31 -0700431/**
432 * wma_set_tsf_gpio_pin() - send wmi cmd to configure gpio pin
433 * @handle: wma handler
434 * @pin: GPIO pin id
435 *
436 * Return: QDF_STATUS
437 */
438QDF_STATUS wma_set_tsf_gpio_pin(WMA_HANDLE handle, uint32_t pin)
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700439{
Manikandan Mohan976e7562016-03-15 16:33:31 -0700440 tp_wma_handle wma = (tp_wma_handle)handle;
441 struct pdev_params pdev_param = {0};
442 int32_t ret;
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700443
Manikandan Mohan976e7562016-03-15 16:33:31 -0700444 if (!wma || !wma->wmi_handle) {
445 WMA_LOGE("%s: WMA is closed, can not set gpio", __func__);
446 return QDF_STATUS_E_INVAL;
447 }
448
449 WMA_LOGD("%s: set tsf gpio pin: %d", __func__, pin);
450
451 pdev_param.param_id = WMI_PDEV_PARAM_WNTS_CONFIG;
452 pdev_param.param_value = pin;
453 ret = wmi_unified_pdev_param_send(wma->wmi_handle,
454 &pdev_param,
455 WMA_WILDCARD_PDEV_ID);
456 if (ret) {
457 WMA_LOGE("%s: Failed to set tsf gpio pin (%d)", __func__, ret);
458 return QDF_STATUS_E_FAILURE;
459 }
460 return QDF_STATUS_SUCCESS;
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700461}
462#endif
463
Manikandan Mohan80dea792016-04-28 16:36:48 -0700464/**
465 * wma_set_wisa_params(): Set WISA features related params in FW
466 * @wma_handle: WMA handle
467 * @wisa: Pointer to WISA param struct
468 *
469 * Return: CDF status
470 */
471QDF_STATUS wma_set_wisa_params(tp_wma_handle wma_handle,
472 struct sir_wisa_params *wisa)
473{
474 QDF_STATUS status = QDF_STATUS_SUCCESS;
475 wmi_buf_t buf;
476 wmi_vdev_wisa_cmd_fixed_param *cmd;
477 int ret, len = sizeof(*cmd);
478
479 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
480 if (!buf) {
481 WMA_LOGP("%s: failed to allocate memory for WISA params",
482 __func__);
483 return QDF_STATUS_E_NOMEM;
484 }
485
486 cmd = (wmi_vdev_wisa_cmd_fixed_param *) wmi_buf_data(buf);
487 cmd->wisa_mode = wisa->mode;
488 cmd->vdev_id = wisa->vdev_id;
489
490 WMITLV_SET_HDR(&cmd->tlv_header,
491 WMITLV_TAG_STRUC_wmi_vdev_wisa_cmd_fixed_param,
492 WMITLV_GET_STRUCT_TLVLEN(
493 wmi_vdev_wisa_cmd_fixed_param));
494
495 ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
496 WMI_VDEV_WISA_CMDID);
497 if (ret != EOK) {
498 WMA_LOGE("wmi_unified_cmd_send returned Error %d", status);
499 status = QDF_STATUS_E_FAILURE;
500 goto error;
501 }
502 return QDF_STATUS_SUCCESS;
503
504error:
505 wmi_buf_free(buf);
506 return status;
507}
508
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800509#ifdef FEATURE_WLAN_LPHB
510/**
511 * wma_lphb_conf_hbenable() - enable command of LPHB configuration requests
512 * @wma_handle: WMA handle
513 * @lphb_conf_req: configuration info
514 * @by_user: whether this call is from user or cached resent
515 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530516 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800517 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530518QDF_STATUS wma_lphb_conf_hbenable(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800519 tSirLPHBReq *lphb_conf_req, bool by_user)
520{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530521 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800522 int status = 0;
523 tSirLPHBEnableStruct *ts_lphb_enable;
Govind Singhaa64c242016-03-08 11:31:49 +0530524 wmi_hb_set_enable_cmd_fixed_param hb_enable_fp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800525 int i;
526
527 if (lphb_conf_req == NULL) {
528 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530529 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800530 }
531
532 ts_lphb_enable = &(lphb_conf_req->params.lphbEnableReq);
533 WMA_LOGI("%s: WMA --> WMI_HB_SET_ENABLE enable=%d, item=%d, session=%d",
534 __func__,
535 ts_lphb_enable->enable,
536 ts_lphb_enable->item, ts_lphb_enable->session);
537
538 if ((ts_lphb_enable->item != 1) && (ts_lphb_enable->item != 2)) {
539 WMA_LOGE("%s : LPHB configuration wrong item %d",
540 __func__, ts_lphb_enable->item);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530541 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800542 }
543
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800544
545 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530546 hb_enable_fp.vdev_id = ts_lphb_enable->session;
547 hb_enable_fp.enable = ts_lphb_enable->enable;
548 hb_enable_fp.item = ts_lphb_enable->item;
549 hb_enable_fp.session = ts_lphb_enable->session;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800550
Govind Singhaa64c242016-03-08 11:31:49 +0530551 status = wmi_unified_lphb_config_hbenable_cmd(wma_handle->wmi_handle,
552 &hb_enable_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800553 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530554 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800555 goto error;
556 }
557
558 if (by_user) {
559 /* target already configured, now cache command status */
560 if (ts_lphb_enable->enable) {
561 i = ts_lphb_enable->item - 1;
562 wma_handle->wow.lphb_cache[i].cmd
563 = LPHB_SET_EN_PARAMS_INDID;
564 wma_handle->wow.lphb_cache[i].params.lphbEnableReq.
565 enable = ts_lphb_enable->enable;
566 wma_handle->wow.lphb_cache[i].params.lphbEnableReq.
567 item = ts_lphb_enable->item;
568 wma_handle->wow.lphb_cache[i].params.lphbEnableReq.
569 session = ts_lphb_enable->session;
570
571 WMA_LOGI("%s: cached LPHB status in WMA context for item %d",
572 __func__, i);
573 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530574 qdf_mem_zero((void *)&wma_handle->wow.lphb_cache,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800575 sizeof(wma_handle->wow.lphb_cache));
576 WMA_LOGI("%s: cleared all cached LPHB status in WMA context",
577 __func__);
578 }
579 }
580
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530581 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800582error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530583 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800584}
585
586/**
587 * wma_lphb_conf_tcp_params() - set tcp params of LPHB configuration requests
588 * @wma_handle: wma handle
589 * @lphb_conf_req: lphb config request
590 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530591 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800592 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530593QDF_STATUS wma_lphb_conf_tcp_params(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800594 tSirLPHBReq *lphb_conf_req)
595{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530596 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800597 int status = 0;
598 tSirLPHBTcpParamStruct *ts_lphb_tcp_param;
Govind Singhaa64c242016-03-08 11:31:49 +0530599 wmi_hb_set_tcp_params_cmd_fixed_param hb_tcp_params_fp = {0};
600
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800601
602 if (lphb_conf_req == NULL) {
603 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530604 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800605 }
606
607 ts_lphb_tcp_param = &(lphb_conf_req->params.lphbTcpParamReq);
Srinivas Girigowda9dc32cf2015-11-19 14:47:04 -0800608 WMA_LOGI("%s: WMA --> WMI_HB_SET_TCP_PARAMS srv_ip=%08x, "
609 "dev_ip=%08x, src_port=%d, dst_port=%d, timeout=%d, "
610 "session=%d, gateway_mac="MAC_ADDRESS_STR", timePeriodSec=%d, "
611 "tcpSn=%d", __func__, ts_lphb_tcp_param->srv_ip,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800612 ts_lphb_tcp_param->dev_ip, ts_lphb_tcp_param->src_port,
613 ts_lphb_tcp_param->dst_port, ts_lphb_tcp_param->timeout,
Srinivas Girigowda9dc32cf2015-11-19 14:47:04 -0800614 ts_lphb_tcp_param->session,
615 MAC_ADDR_ARRAY(ts_lphb_tcp_param->gateway_mac.bytes),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800616 ts_lphb_tcp_param->timePeriodSec, ts_lphb_tcp_param->tcpSn);
617
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800618 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530619 hb_tcp_params_fp.vdev_id = ts_lphb_tcp_param->session;
620 hb_tcp_params_fp.srv_ip = ts_lphb_tcp_param->srv_ip;
621 hb_tcp_params_fp.dev_ip = ts_lphb_tcp_param->dev_ip;
622 hb_tcp_params_fp.seq = ts_lphb_tcp_param->tcpSn;
623 hb_tcp_params_fp.src_port = ts_lphb_tcp_param->src_port;
624 hb_tcp_params_fp.dst_port = ts_lphb_tcp_param->dst_port;
625 hb_tcp_params_fp.interval = ts_lphb_tcp_param->timePeriodSec;
626 hb_tcp_params_fp.timeout = ts_lphb_tcp_param->timeout;
627 hb_tcp_params_fp.session = ts_lphb_tcp_param->session;
Srinivas Girigowda9dc32cf2015-11-19 14:47:04 -0800628 WMI_CHAR_ARRAY_TO_MAC_ADDR(ts_lphb_tcp_param->gateway_mac.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +0530629 &hb_tcp_params_fp.gateway_mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800630
Govind Singhaa64c242016-03-08 11:31:49 +0530631 status = wmi_unified_lphb_config_tcp_params_cmd(wma_handle->wmi_handle,
632 &hb_tcp_params_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800633 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530634 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800635 goto error;
636 }
637
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530638 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800639error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530640 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800641}
642
643/**
644 * wma_lphb_conf_tcp_pkt_filter() - configure tcp packet filter command of LPHB
645 * @wma_handle: wma handle
646 * @lphb_conf_req: lphb config request
647 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530648 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800649 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530650QDF_STATUS wma_lphb_conf_tcp_pkt_filter(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800651 tSirLPHBReq *lphb_conf_req)
652{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530653 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800654 int status = 0;
655 tSirLPHBTcpFilterStruct *ts_lphb_tcp_filter;
Govind Singhaa64c242016-03-08 11:31:49 +0530656 wmi_hb_set_tcp_pkt_filter_cmd_fixed_param hb_tcp_filter_fp = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800657
658 if (lphb_conf_req == NULL) {
659 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530660 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800661 }
662
663 ts_lphb_tcp_filter = &(lphb_conf_req->params.lphbTcpFilterReq);
664 WMA_LOGI("%s: WMA --> WMI_HB_SET_TCP_PKT_FILTER length=%d, offset=%d, session=%d, "
665 "filter=%2x:%2x:%2x:%2x:%2x:%2x ...", __func__,
666 ts_lphb_tcp_filter->length, ts_lphb_tcp_filter->offset,
667 ts_lphb_tcp_filter->session, ts_lphb_tcp_filter->filter[0],
668 ts_lphb_tcp_filter->filter[1], ts_lphb_tcp_filter->filter[2],
669 ts_lphb_tcp_filter->filter[3], ts_lphb_tcp_filter->filter[4],
670 ts_lphb_tcp_filter->filter[5]);
671
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800672 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530673 hb_tcp_filter_fp.vdev_id = ts_lphb_tcp_filter->session;
674 hb_tcp_filter_fp.length = ts_lphb_tcp_filter->length;
675 hb_tcp_filter_fp.offset = ts_lphb_tcp_filter->offset;
676 hb_tcp_filter_fp.session = ts_lphb_tcp_filter->session;
677 memcpy((void *)&hb_tcp_filter_fp.filter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800678 (void *)&ts_lphb_tcp_filter->filter,
679 WMI_WLAN_HB_MAX_FILTER_SIZE);
680
Govind Singhaa64c242016-03-08 11:31:49 +0530681 status = wmi_unified_lphb_config_tcp_pkt_filter_cmd(wma_handle->wmi_handle,
682 &hb_tcp_filter_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800683 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530684 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800685 goto error;
686 }
687
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530688 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800689error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530690 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800691}
692
693/**
694 * wma_lphb_conf_udp_params() - configure udp param command of LPHB
695 * @wma_handle: wma handle
696 * @lphb_conf_req: lphb config request
697 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530698 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800699 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530700QDF_STATUS wma_lphb_conf_udp_params(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800701 tSirLPHBReq *lphb_conf_req)
702{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530703 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800704 int status = 0;
705 tSirLPHBUdpParamStruct *ts_lphb_udp_param;
Govind Singhaa64c242016-03-08 11:31:49 +0530706 wmi_hb_set_udp_params_cmd_fixed_param hb_udp_params_fp = {0};
707
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800708
709 if (lphb_conf_req == NULL) {
710 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530711 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800712 }
713
714 ts_lphb_udp_param = &(lphb_conf_req->params.lphbUdpParamReq);
715 WMA_LOGI("%s: WMA --> WMI_HB_SET_UDP_PARAMS srv_ip=%d, dev_ip=%d, src_port=%d, "
716 "dst_port=%d, interval=%d, timeout=%d, session=%d, "
Srinivas Girigowda9eddfda2015-11-19 14:38:02 -0800717 "gateway_mac="MAC_ADDRESS_STR, __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800718 ts_lphb_udp_param->srv_ip, ts_lphb_udp_param->dev_ip,
719 ts_lphb_udp_param->src_port, ts_lphb_udp_param->dst_port,
720 ts_lphb_udp_param->interval, ts_lphb_udp_param->timeout,
Srinivas Girigowda9eddfda2015-11-19 14:38:02 -0800721 ts_lphb_udp_param->session,
722 MAC_ADDR_ARRAY(ts_lphb_udp_param->gateway_mac.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800723
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800724
725 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530726 hb_udp_params_fp.vdev_id = ts_lphb_udp_param->session;
727 hb_udp_params_fp.srv_ip = ts_lphb_udp_param->srv_ip;
728 hb_udp_params_fp.dev_ip = ts_lphb_udp_param->dev_ip;
729 hb_udp_params_fp.src_port = ts_lphb_udp_param->src_port;
730 hb_udp_params_fp.dst_port = ts_lphb_udp_param->dst_port;
731 hb_udp_params_fp.interval = ts_lphb_udp_param->interval;
732 hb_udp_params_fp.timeout = ts_lphb_udp_param->timeout;
733 hb_udp_params_fp.session = ts_lphb_udp_param->session;
Srinivas Girigowda9eddfda2015-11-19 14:38:02 -0800734 WMI_CHAR_ARRAY_TO_MAC_ADDR(ts_lphb_udp_param->gateway_mac.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +0530735 &hb_udp_params_fp.gateway_mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800736
Govind Singhaa64c242016-03-08 11:31:49 +0530737 status = wmi_unified_lphb_config_udp_params_cmd(wma_handle->wmi_handle,
738 &hb_udp_params_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800739 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530740 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800741 goto error;
742 }
743
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530744 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800745error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530746 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800747}
748
749/**
750 * wma_lphb_conf_udp_pkt_filter() - configure udp pkt filter command of LPHB
751 * @wma_handle: wma handle
752 * @lphb_conf_req: lphb config request
753 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530754 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800755 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530756QDF_STATUS wma_lphb_conf_udp_pkt_filter(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800757 tSirLPHBReq *lphb_conf_req)
758{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530759 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800760 int status = 0;
761 tSirLPHBUdpFilterStruct *ts_lphb_udp_filter;
Govind Singhaa64c242016-03-08 11:31:49 +0530762 wmi_hb_set_udp_pkt_filter_cmd_fixed_param hb_udp_filter_fp = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800763
764 if (lphb_conf_req == NULL) {
765 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530766 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800767 }
768
769 ts_lphb_udp_filter = &(lphb_conf_req->params.lphbUdpFilterReq);
770 WMA_LOGI("%s: WMA --> WMI_HB_SET_UDP_PKT_FILTER length=%d, offset=%d, session=%d, "
771 "filter=%2x:%2x:%2x:%2x:%2x:%2x ...", __func__,
772 ts_lphb_udp_filter->length, ts_lphb_udp_filter->offset,
773 ts_lphb_udp_filter->session, ts_lphb_udp_filter->filter[0],
774 ts_lphb_udp_filter->filter[1], ts_lphb_udp_filter->filter[2],
775 ts_lphb_udp_filter->filter[3], ts_lphb_udp_filter->filter[4],
776 ts_lphb_udp_filter->filter[5]);
777
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800778
779 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530780 hb_udp_filter_fp.vdev_id = ts_lphb_udp_filter->session;
781 hb_udp_filter_fp.length = ts_lphb_udp_filter->length;
782 hb_udp_filter_fp.offset = ts_lphb_udp_filter->offset;
783 hb_udp_filter_fp.session = ts_lphb_udp_filter->session;
784 memcpy((void *)&hb_udp_filter_fp.filter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800785 (void *)&ts_lphb_udp_filter->filter,
786 WMI_WLAN_HB_MAX_FILTER_SIZE);
787
Govind Singhaa64c242016-03-08 11:31:49 +0530788 status = wmi_unified_lphb_config_udp_pkt_filter_cmd(wma_handle->wmi_handle,
789 &hb_udp_filter_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800790 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530791 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800792 goto error;
793 }
794
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530795 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800796error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530797 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800798}
799
800/**
801 * wma_process_lphb_conf_req() - handle LPHB configuration requests
802 * @wma_handle: wma handle
803 * @lphb_conf_req: lphb config request
804 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530805 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800806 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530807QDF_STATUS wma_process_lphb_conf_req(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800808 tSirLPHBReq *lphb_conf_req)
809{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530810 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800811
812 if (lphb_conf_req == NULL) {
813 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530814 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800815 }
816
817 WMA_LOGI("%s : LPHB configuration cmd id is %d", __func__,
818 lphb_conf_req->cmd);
819 switch (lphb_conf_req->cmd) {
820 case LPHB_SET_EN_PARAMS_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530821 qdf_status = wma_lphb_conf_hbenable(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800822 lphb_conf_req, true);
823 break;
824
825 case LPHB_SET_TCP_PARAMS_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530826 qdf_status = wma_lphb_conf_tcp_params(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800827 lphb_conf_req);
828 break;
829
830 case LPHB_SET_TCP_PKT_FILTER_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530831 qdf_status = wma_lphb_conf_tcp_pkt_filter(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800832 lphb_conf_req);
833 break;
834
835 case LPHB_SET_UDP_PARAMS_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530836 qdf_status = wma_lphb_conf_udp_params(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800837 lphb_conf_req);
838 break;
839
840 case LPHB_SET_UDP_PKT_FILTER_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530841 qdf_status = wma_lphb_conf_udp_pkt_filter(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800842 lphb_conf_req);
843 break;
844
845 case LPHB_SET_NETWORK_INFO_INDID:
846 default:
847 break;
848 }
849
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530850 qdf_mem_free(lphb_conf_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530851 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800852}
853#endif /* FEATURE_WLAN_LPHB */
854
855/**
856 * wma_process_dhcp_ind() - process dhcp indication from SME
857 * @wma_handle: wma handle
858 * @ta_dhcp_ind: DHCP indication
859 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530860 * Return: QDF Status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800861 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530862QDF_STATUS wma_process_dhcp_ind(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800863 tAniDHCPInd *ta_dhcp_ind)
864{
865 uint8_t vdev_id;
866 int status = 0;
Govind Singhaa64c242016-03-08 11:31:49 +0530867 wmi_peer_set_param_cmd_fixed_param peer_set_param_fp = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800868
869 if (!ta_dhcp_ind) {
870 WMA_LOGE("%s : DHCP indication is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530871 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800872 }
873
Srinivas Girigowda296105a2015-09-24 16:31:16 -0700874 if (!wma_find_vdev_by_addr(wma_handle,
875 ta_dhcp_ind->adapterMacAddr.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800876 &vdev_id)) {
877 WMA_LOGE("%s: Failed to find vdev id for DHCP indication",
878 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530879 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800880 }
881
882 WMA_LOGI("%s: WMA --> WMI_PEER_SET_PARAM triggered by DHCP, "
883 "msgType=%s,"
884 "device_mode=%d, macAddr=" MAC_ADDRESS_STR,
885 __func__,
886 ta_dhcp_ind->msgType == WMA_DHCP_START_IND ?
887 "WMA_DHCP_START_IND" : "WMA_DHCP_STOP_IND",
888 ta_dhcp_ind->device_mode,
Srinivas Girigowda296105a2015-09-24 16:31:16 -0700889 MAC_ADDR_ARRAY(ta_dhcp_ind->peerMacAddr.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800890
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800891 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530892 peer_set_param_fp.vdev_id = vdev_id;
893 peer_set_param_fp.param_id = WMI_PEER_CRIT_PROTO_HINT_ENABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800894 if (WMA_DHCP_START_IND == ta_dhcp_ind->msgType)
Govind Singhaa64c242016-03-08 11:31:49 +0530895 peer_set_param_fp.param_value = 1;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800896 else
Govind Singhaa64c242016-03-08 11:31:49 +0530897 peer_set_param_fp.param_value = 0;
Srinivas Girigowda296105a2015-09-24 16:31:16 -0700898 WMI_CHAR_ARRAY_TO_MAC_ADDR(ta_dhcp_ind->peerMacAddr.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +0530899 &peer_set_param_fp.peer_macaddr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800900
Govind Singhaa64c242016-03-08 11:31:49 +0530901 status = wmi_unified_process_dhcp_ind(wma_handle->wmi_handle,
902 &peer_set_param_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800903 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530904 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800905 }
906
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530907 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800908}
909
910/**
Amar Singhal046eb8a2016-05-05 12:50:15 -0700911 * wma_chan_phy__mode() - get WLAN_PHY_MODE for channel
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800912 * @chan: channel number
Amar Singhal046eb8a2016-05-05 12:50:15 -0700913 * @chan_width: maximum channel width possible
914 * @dot11_mode: maximum phy_mode possible
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800915 *
Amar Singhal046eb8a2016-05-05 12:50:15 -0700916 * Return: return WLAN_PHY_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800917 */
Amar Singhal046eb8a2016-05-05 12:50:15 -0700918WLAN_PHY_MODE wma_chan_phy_mode(u8 chan, enum phy_ch_width chan_width,
919 u8 dot11_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800920{
921 WLAN_PHY_MODE phymode = MODE_UNKNOWN;
Amar Singhal046eb8a2016-05-05 12:50:15 -0700922 uint16_t bw_val = cds_bw_value(chan_width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800923
Amar Singhal046eb8a2016-05-05 12:50:15 -0700924 if (CDS_IS_CHANNEL_24GHZ(chan)) {
925 if (((CH_WIDTH_5MHZ == chan_width) ||
926 (CH_WIDTH_10MHZ == chan_width)) &&
927 ((WNI_CFG_DOT11_MODE_11B == dot11_mode) ||
928 (WNI_CFG_DOT11_MODE_11G == dot11_mode) ||
929 (WNI_CFG_DOT11_MODE_11N == dot11_mode) ||
930 (WNI_CFG_DOT11_MODE_ALL == dot11_mode) ||
931 (WNI_CFG_DOT11_MODE_11AC == dot11_mode)))
932 phymode = MODE_11G;
933 else {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800934 switch (dot11_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800935 case WNI_CFG_DOT11_MODE_11B:
Amar Singhal046eb8a2016-05-05 12:50:15 -0700936 if ((20 == bw_val) ||
937 (40 == bw_val))
938 phymode = MODE_11B;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800939 break;
940 case WNI_CFG_DOT11_MODE_11G:
Amar Singhal046eb8a2016-05-05 12:50:15 -0700941 if ((20 == bw_val) ||
942 (40 == bw_val))
943 phymode = MODE_11G;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800944 break;
945 case WNI_CFG_DOT11_MODE_11G_ONLY:
Amar Singhal046eb8a2016-05-05 12:50:15 -0700946 if ((20 == bw_val) ||
947 (40 == bw_val))
948 phymode = MODE_11GONLY;
949 break;
950 case WNI_CFG_DOT11_MODE_11N:
951 case WNI_CFG_DOT11_MODE_11N_ONLY:
952 if (20 == bw_val)
953 phymode = MODE_11NG_HT20;
954 else if (40 == bw_val)
955 phymode = MODE_11NG_HT40;
956 break;
957 case WNI_CFG_DOT11_MODE_ALL:
958 case WNI_CFG_DOT11_MODE_11AC:
959 case WNI_CFG_DOT11_MODE_11AC_ONLY:
960 if (20 == bw_val)
961 phymode = MODE_11AC_VHT20_2G;
962 else if (40 == bw_val)
963 phymode = MODE_11AC_VHT40_2G;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800964 break;
965 default:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800966 break;
967 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800968 }
Amar Singhal046eb8a2016-05-05 12:50:15 -0700969 } else if (CDS_IS_CHANNEL_DSRC(chan))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800970 phymode = MODE_11A;
Amar Singhal046eb8a2016-05-05 12:50:15 -0700971 else {
972 if (((CH_WIDTH_5MHZ == chan_width) ||
973 (CH_WIDTH_10MHZ == chan_width)) &&
974 ((WNI_CFG_DOT11_MODE_11A == dot11_mode) ||
975 (WNI_CFG_DOT11_MODE_11N == dot11_mode) ||
976 (WNI_CFG_DOT11_MODE_ALL == dot11_mode) ||
977 (WNI_CFG_DOT11_MODE_11AC == dot11_mode)))
978 phymode = MODE_11A;
979 else {
980 switch (dot11_mode) {
981 case WNI_CFG_DOT11_MODE_11A:
982 if (0 < bw_val)
983 phymode = MODE_11A;
984 break;
985 case WNI_CFG_DOT11_MODE_11N:
986 case WNI_CFG_DOT11_MODE_11N_ONLY:
987 if (20 == bw_val)
988 phymode = MODE_11NA_HT20;
989 else if (40 <= bw_val)
990 phymode = MODE_11NA_HT40;
991 break;
992 case WNI_CFG_DOT11_MODE_ALL:
993 case WNI_CFG_DOT11_MODE_11AC:
994 case WNI_CFG_DOT11_MODE_11AC_ONLY:
995 if (20 == bw_val)
996 phymode = MODE_11AC_VHT20;
997 else if (40 == bw_val)
998 phymode = MODE_11AC_VHT40;
999 else if (80 == bw_val)
1000 phymode = MODE_11AC_VHT80;
1001 else if (CH_WIDTH_160MHZ == chan_width)
1002 phymode = MODE_11AC_VHT160;
1003 else if (CH_WIDTH_80P80MHZ == chan_width)
1004 phymode = MODE_11AC_VHT80_80;
1005 break;
1006 default:
1007 break;
1008 }
1009 }
1010 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001011
Amar Singhal046eb8a2016-05-05 12:50:15 -07001012 WMA_LOGD("%s: phymode %d channel %d ch_width %d"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001013 "dot11_mode %d", __func__, phymode, chan,
Amar Singhal046eb8a2016-05-05 12:50:15 -07001014 chan_width, dot11_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001015
Amar Singhal046eb8a2016-05-05 12:50:15 -07001016 QDF_ASSERT(MODE_UNKNOWN != phymode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001017 return phymode;
1018}
1019
1020/**
1021 * wma_get_link_speed() -send command to get linkspeed
1022 * @handle: wma handle
1023 * @pLinkSpeed: link speed info
1024 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05301025 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001026 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301027QDF_STATUS wma_get_link_speed(WMA_HANDLE handle, tSirLinkSpeedInfo *pLinkSpeed)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001028{
1029 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhaa64c242016-03-08 11:31:49 +05301030 wmi_mac_addr peer_macaddr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001031
1032 if (!wma_handle || !wma_handle->wmi_handle) {
1033 WMA_LOGE("%s: WMA is closed, can not issue get link speed cmd",
1034 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301035 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001036 }
1037 if (!WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap,
1038 WMI_SERVICE_ESTIMATE_LINKSPEED)) {
1039 WMA_LOGE("%s: Linkspeed feature bit not enabled"
1040 " Sending value 0 as link speed.", __func__);
1041 wma_send_link_speed(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301042 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001043 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001044
1045 /* Copy the peer macaddress to the wma buffer */
Srinivas Girigowdadccab9a2015-11-19 14:31:14 -08001046 WMI_CHAR_ARRAY_TO_MAC_ADDR(pLinkSpeed->peer_macaddr.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +05301047 &peer_macaddr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001048
1049 WMA_LOGD("%s: pLinkSpeed->peerMacAddr: %pM, "
1050 "peer_macaddr.mac_addr31to0: 0x%x, peer_macaddr.mac_addr47to32: 0x%x",
Srinivas Girigowdadccab9a2015-11-19 14:31:14 -08001051 __func__, pLinkSpeed->peer_macaddr.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +05301052 peer_macaddr.mac_addr31to0,
1053 peer_macaddr.mac_addr47to32);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001054
Govind Singhaa64c242016-03-08 11:31:49 +05301055 if (wmi_unified_get_link_speed_cmd(wma_handle->wmi_handle,
1056 peer_macaddr)) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301057 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001058 }
Govind Singhaa64c242016-03-08 11:31:49 +05301059
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301060 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001061}
1062
Gupta, Kapil4cb1d7d2016-04-16 18:16:25 -07001063/**
1064* wma_add_beacon_filter() - Issue WMI command to set beacon filter
1065* @wma: wma handler
1066* @filter_params: beacon_filter_param to set
1067*
1068* Return: Return QDF_STATUS
1069*/
1070QDF_STATUS wma_add_beacon_filter(WMA_HANDLE handle,
1071 struct beacon_filter_param *filter_params)
1072{
1073 int i;
1074 wmi_buf_t wmi_buf;
1075 u_int8_t *buf;
1076 A_UINT32 *ie_map;
1077 int ret;
1078 tp_wma_handle wma = (tp_wma_handle) handle;
1079 wmi_add_bcn_filter_cmd_fixed_param *cmd;
1080 int len = sizeof(wmi_add_bcn_filter_cmd_fixed_param);
1081
1082 len += WMI_TLV_HDR_SIZE;
1083 len += BCN_FLT_MAX_ELEMS_IE_LIST*sizeof(A_UINT32);
1084
1085 if (!wma || !wma->wmi_handle) {
1086 WMA_LOGE("%s: WMA is closed, can not issue set beacon filter",
1087 __func__);
1088 return QDF_STATUS_E_INVAL;
1089 }
1090
1091 wmi_buf = wmi_buf_alloc(wma->wmi_handle, len);
1092 if (!wmi_buf) {
1093 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
1094 return QDF_STATUS_E_NOMEM;
1095 }
1096
1097 buf = (u_int8_t *) wmi_buf_data(wmi_buf);
1098
1099 cmd = (wmi_add_bcn_filter_cmd_fixed_param *)wmi_buf_data(wmi_buf);
1100 cmd->vdev_id = filter_params->vdev_id;
1101
1102 WMITLV_SET_HDR(&cmd->tlv_header,
1103 WMITLV_TAG_STRUC_wmi_add_bcn_filter_cmd_fixed_param,
1104 WMITLV_GET_STRUCT_TLVLEN(
1105 wmi_add_bcn_filter_cmd_fixed_param));
1106
1107 buf += sizeof(wmi_add_bcn_filter_cmd_fixed_param);
1108
1109 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_UINT32,
1110 (BCN_FLT_MAX_ELEMS_IE_LIST * sizeof(u_int32_t)));
1111
1112 ie_map = (A_UINT32 *)(buf + WMI_TLV_HDR_SIZE);
1113 for (i = 0; i < BCN_FLT_MAX_ELEMS_IE_LIST; i++) {
1114 ie_map[i] = filter_params->ie_map[i];
1115 WMA_LOGD("beacon filter ie map = %u", ie_map[i]);
1116 }
1117
1118 ret = wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len,
1119 WMI_ADD_BCN_FILTER_CMDID);
1120 if (ret) {
1121 WMA_LOGE("Failed to send wmi add beacon filter = %d",
1122 ret);
1123 wmi_buf_free(wmi_buf);
1124 return QDF_STATUS_E_FAILURE;
1125 }
1126 WMA_LOGD("added beacon filter = %d", ret);
1127
1128 return QDF_STATUS_SUCCESS;
1129}
1130
1131/**
1132* wma_remove_beacon_filter() - Issue WMI command to remove beacon filter
1133* @wma: wma handler
1134* @filter_params: beacon_filter_params
1135*
1136* Return: Return QDF_STATUS
1137*/
1138QDF_STATUS wma_remove_beacon_filter(WMA_HANDLE handle,
1139 struct beacon_filter_param *filter_params)
1140{
1141 wmi_buf_t buf;
1142 tp_wma_handle wma = (tp_wma_handle) handle;
1143 wmi_rmv_bcn_filter_cmd_fixed_param *cmd;
1144 int len = sizeof(wmi_rmv_bcn_filter_cmd_fixed_param);
1145 int ret;
1146
1147 if (!wma || !wma->wmi_handle) {
1148 WMA_LOGE("%s: WMA is closed, cannot issue remove beacon filter",
1149 __func__);
1150 return QDF_STATUS_E_INVAL;
1151 }
1152
1153 buf = wmi_buf_alloc(wma->wmi_handle, len);
1154 if (!buf) {
1155 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
1156 return QDF_STATUS_E_NOMEM;
1157 }
1158 cmd = (wmi_rmv_bcn_filter_cmd_fixed_param *)wmi_buf_data(buf);
1159 cmd->vdev_id = filter_params->vdev_id;
1160
1161 WMITLV_SET_HDR(&cmd->tlv_header,
1162 WMITLV_TAG_STRUC_wmi_rmv_bcn_filter_cmd_fixed_param,
1163 WMITLV_GET_STRUCT_TLVLEN(
1164 wmi_rmv_bcn_filter_cmd_fixed_param));
1165
1166 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
1167 WMI_RMV_BCN_FILTER_CMDID);
1168 if (ret) {
1169 WMA_LOGE("Failed to send wmi remove beacon filter = %d",
1170 ret);
1171 wmi_buf_free(buf);
1172 return QDF_STATUS_E_FAILURE;
1173 }
1174 WMA_LOGD("removed beacon filter = %d", ret);
1175
1176 return QDF_STATUS_SUCCESS;
1177}
1178
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05301179/**
1180 * wma_send_adapt_dwelltime_params() - send adaptive dwelltime configuration
1181 * params to firmware
1182 * @wma_handle: wma handler
1183 * @dwelltime_params: pointer to dwelltime_params
1184 *
1185 * Return: QDF_STATUS_SUCCESS on success and QDF failure reason code for failure
1186 */
1187QDF_STATUS wma_send_adapt_dwelltime_params(WMA_HANDLE handle,
1188 struct adaptive_dwelltime_params *dwelltime_params)
1189{
1190 tp_wma_handle wma_handle = (tp_wma_handle) handle;
1191 struct wmi_adaptive_dwelltime_params wmi_param = {0};
1192 int32_t err;
1193
1194 wmi_param.is_enabled = dwelltime_params->is_enabled;
1195 wmi_param.dwelltime_mode = dwelltime_params->dwelltime_mode;
1196 wmi_param.lpf_weight = dwelltime_params->lpf_weight;
1197 wmi_param.passive_mon_intval = dwelltime_params->passive_mon_intval;
1198 wmi_param.wifi_act_threshold = dwelltime_params->wifi_act_threshold;
1199 err = wmi_unified_send_adapt_dwelltime_params_cmd(wma_handle->
1200 wmi_handle, &wmi_param);
1201 if (err)
1202 return QDF_STATUS_E_FAILURE;
1203
1204 return QDF_STATUS_SUCCESS;
1205}
Gupta, Kapil4cb1d7d2016-04-16 18:16:25 -07001206
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001207#ifdef FEATURE_GREEN_AP
1208
1209/**
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001210 * wma_egap_info_status_event() - egap info status event
1211 * @handle: pointer to wma handler
1212 * @event: pointer to event
1213 * @len: len of the event
1214 *
1215 * Return: 0 for success, otherwise appropriate error code
1216 */
1217static int wma_egap_info_status_event(void *handle, u_int8_t *event,
1218 uint32_t len)
1219{
1220 WMI_TX_PAUSE_EVENTID_param_tlvs *param_buf;
1221 wmi_ap_ps_egap_info_event_fixed_param *egap_info_event;
1222 wmi_ap_ps_egap_info_chainmask_list *chainmask_event;
1223 u_int8_t *buf_ptr;
1224
1225 param_buf = (WMI_TX_PAUSE_EVENTID_param_tlvs *)event;
1226 if (!param_buf) {
1227 WMA_LOGE("Invalid EGAP Info status event buffer");
1228 return -EINVAL;
1229 }
1230
1231 egap_info_event = (wmi_ap_ps_egap_info_event_fixed_param *)
1232 param_buf->fixed_param;
1233 buf_ptr = (uint8_t *)egap_info_event;
1234 buf_ptr += sizeof(wmi_ap_ps_egap_info_event_fixed_param);
1235 chainmask_event = (wmi_ap_ps_egap_info_chainmask_list *)buf_ptr;
1236
1237 WMA_LOGI("mac_id: %d, status: %d, tx_mask: %x, rx_mask: %d",
1238 chainmask_event->mac_id,
1239 egap_info_event->status,
1240 chainmask_event->tx_chainmask,
1241 chainmask_event->rx_chainmask);
1242 return 0;
1243}
1244
1245/**
1246 * wma_send_egap_conf_params() - send wmi cmd of egap configuration params
1247 * @wma_handle: wma handler
1248 * @egap_params: pointer to egap_params
1249 *
1250 * Return: 0 for success, otherwise appropriate error code
1251 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301252QDF_STATUS wma_send_egap_conf_params(WMA_HANDLE handle,
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001253 struct egap_conf_params *egap_params)
1254{
1255 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhaa64c242016-03-08 11:31:49 +05301256 wmi_ap_ps_egap_param_cmd_fixed_param cmd = {0};
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001257 int32_t err;
1258
Govind Singhaa64c242016-03-08 11:31:49 +05301259 cmd.enable = egap_params->enable;
1260 cmd.inactivity_time = egap_params->inactivity_time;
1261 cmd.wait_time = egap_params->wait_time;
1262 cmd.flags = egap_params->flags;
1263 err = wmi_unified_egap_conf_params_cmd(wma_handle->wmi_handle, &cmd);
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001264 if (err) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301265 return QDF_STATUS_E_FAILURE;
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001266 }
Govind Singhaa64c242016-03-08 11:31:49 +05301267
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301268 return QDF_STATUS_SUCCESS;
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001269}
1270
1271/**
1272 * wma_setup_egap_support() - setup the EGAP support flag
1273 * @tgt_cfg: pointer to hdd target configuration
1274 * @egap_support: EGAP support flag
1275 *
1276 * Return: None
1277 */
1278void wma_setup_egap_support(struct wma_tgt_cfg *tgt_cfg, WMA_HANDLE handle)
1279{
1280 tp_wma_handle wma_handle = (tp_wma_handle) handle;
1281
1282 if (tgt_cfg && wma_handle)
1283 tgt_cfg->egap_support = wma_handle->egap_support;
1284}
1285
1286/**
1287 * wma_register_egap_event_handle() - register the EGAP event handle
1288 * @wma_handle: wma handler
1289 *
1290 * Return: None
1291 */
1292void wma_register_egap_event_handle(WMA_HANDLE handle)
1293{
1294 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhd76a5b02016-03-08 15:12:14 +05301295 QDF_STATUS status;
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001296
1297 if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap,
1298 WMI_SERVICE_EGAP)) {
1299 status = wmi_unified_register_event_handler(
1300 wma_handle->wmi_handle,
1301 WMI_AP_PS_EGAP_INFO_EVENTID,
Govind Singhd76a5b02016-03-08 15:12:14 +05301302 wma_egap_info_status_event,
1303 WMA_RX_SERIALIZER_CTX);
1304 if (QDF_IS_STATUS_ERROR(status)) {
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001305 WMA_LOGE("Failed to register Enhance Green AP event");
1306 wma_handle->egap_support = false;
1307 } else {
1308 WMA_LOGI("Set the Enhance Green AP event handler");
1309 wma_handle->egap_support = true;
1310 }
1311 } else
1312 wma_handle->egap_support = false;
1313}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001314#endif /* FEATURE_GREEN_AP */
1315
Govind Singha471e5e2015-10-12 17:11:14 +05301316/**
Govind Singhaa64c242016-03-08 11:31:49 +05301317 * wma_unified_fw_profiling_cmd() - send FW profiling cmd to WLAN FW
Govind Singha471e5e2015-10-12 17:11:14 +05301318 * @wma: wma handle
1319 * @cmd: Profiling command index
1320 * @value1: parameter1 value
1321 * @value2: parameter2 value
1322 *
1323 * Return: 0 for success else error code
1324 */
Govind Singhaa64c242016-03-08 11:31:49 +05301325QDF_STATUS wma_unified_fw_profiling_cmd(wmi_unified_t wmi_handle,
Govind Singha471e5e2015-10-12 17:11:14 +05301326 uint32_t cmd, uint32_t value1, uint32_t value2)
1327{
Govind Singha471e5e2015-10-12 17:11:14 +05301328 int ret;
Govind Singha471e5e2015-10-12 17:11:14 +05301329
Govind Singhaa64c242016-03-08 11:31:49 +05301330 ret = wmi_unified_fw_profiling_data_cmd(wmi_handle, cmd,
1331 value1, value2);
1332 if (ret) {
1333 WMA_LOGE("enable cmd Failed for id %d value %d",
1334 value1, value2);
1335 return ret;
Govind Singha471e5e2015-10-12 17:11:14 +05301336 }
1337
Govind Singhaa64c242016-03-08 11:31:49 +05301338 return QDF_STATUS_SUCCESS;
Govind Singha471e5e2015-10-12 17:11:14 +05301339}
1340
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001341#ifdef FEATURE_WLAN_LPHB
1342/**
1343 * wma_lphb_handler() - send LPHB indication to SME
1344 * @wma: wma handle
1345 * @event: event handler
1346 *
1347 * Return: 0 for success or error code
1348 */
1349static int wma_lphb_handler(tp_wma_handle wma, uint8_t *event)
1350{
1351 wmi_hb_ind_event_fixed_param *hb_fp;
1352 tSirLPHBInd *slphb_indication;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301353 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001354 cds_msg_t sme_msg = { 0 };
1355
1356 hb_fp = (wmi_hb_ind_event_fixed_param *) event;
1357 if (!hb_fp) {
1358 WMA_LOGE("Invalid wmi_hb_ind_event_fixed_param buffer");
1359 return -EINVAL;
1360 }
1361
1362 WMA_LOGD("lphb indication received with vdev_id=%d, session=%d, reason=%d",
1363 hb_fp->vdev_id, hb_fp->session, hb_fp->reason);
1364
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301365 slphb_indication = (tSirLPHBInd *) qdf_mem_malloc(sizeof(tSirLPHBInd));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001366
1367 if (!slphb_indication) {
1368 WMA_LOGE("Invalid LPHB indication buffer");
1369 return -ENOMEM;
1370 }
1371
1372 slphb_indication->sessionIdx = hb_fp->session;
1373 slphb_indication->protocolType = hb_fp->reason;
1374 slphb_indication->eventReason = hb_fp->reason;
1375
1376 sme_msg.type = eWNI_SME_LPHB_IND;
1377 sme_msg.bodyptr = slphb_indication;
1378 sme_msg.bodyval = 0;
1379
Anurag Chouhan6d760662016-02-20 16:05:43 +05301380 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301381 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001382 WMA_LOGE("Fail to post eWNI_SME_LPHB_IND msg to SME");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301383 qdf_mem_free(slphb_indication);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001384 return -EINVAL;
1385 }
1386
1387 return 0;
1388}
1389#endif /* FEATURE_WLAN_LPHB */
1390
1391#ifdef FEATURE_WLAN_RA_FILTERING
1392/**
1393 * wma_wow_sta_ra_filter() - set RA filter pattern in fw
1394 * @wma: wma handle
1395 * @vdev_id: vdev id
1396 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05301397 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001398 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301399static QDF_STATUS wma_wow_sta_ra_filter(tp_wma_handle wma, uint8_t vdev_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001400{
1401
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001402 struct wma_txrx_node *iface;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001403 int ret;
Govind Singhaa64c242016-03-08 11:31:49 +05301404 uint8_t default_pattern;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001405
1406 iface = &wma->interfaces[vdev_id];
1407
Govind Singhaa64c242016-03-08 11:31:49 +05301408 default_pattern = iface->num_wow_default_patterns++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001409
1410 WMA_LOGD("%s: send RA rate limit [%d] to fw vdev = %d", __func__,
1411 wma->RArateLimitInterval, vdev_id);
1412
Govind Singhaa64c242016-03-08 11:31:49 +05301413 ret = wmi_unified_wow_sta_ra_filter_cmd(wma->wmi_handle, vdev_id,
1414 default_pattern, wma->RArateLimitInterval);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001415 if (ret) {
1416 WMA_LOGE("%s: Failed to send RA rate limit to fw", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001417 iface->num_wow_default_patterns--;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301418 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001419 }
1420
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301421 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001422
1423}
1424#endif /* FEATURE_WLAN_RA_FILTERING */
1425
1426/**
1427 * wmi_unified_nat_keepalive_enable() - enable NAT keepalive filter
1428 * @wma: wma handle
1429 * @vdev_id: vdev id
1430 *
1431 * Return: 0 for success or error code
1432 */
1433int wmi_unified_nat_keepalive_enable(tp_wma_handle wma, uint8_t vdev_id)
1434{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001435
Govind Singhaa64c242016-03-08 11:31:49 +05301436 if (wmi_unified_nat_keepalive_en_cmd(wma->wmi_handle, vdev_id))
1437 return QDF_STATUS_E_FAILURE;
1438
1439 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001440}
1441
1442/**
Govind Singhd76a5b02016-03-08 15:12:14 +05301443 * wma_unified_csa_offload_enable() - sen CSA offload enable command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001444 * @wma: wma handle
1445 * @vdev_id: vdev id
1446 *
1447 * Return: 0 for success or error code
1448 */
Govind Singhd76a5b02016-03-08 15:12:14 +05301449int wma_unified_csa_offload_enable(tp_wma_handle wma, uint8_t vdev_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001450{
Govind Singhaa64c242016-03-08 11:31:49 +05301451 if (wmi_unified_csa_offload_enable(wma->wmi_handle,
1452 vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001453 WMA_LOGP("%s: Failed to send CSA offload enable command",
1454 __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001455 return -EIO;
1456 }
Govind Singhaa64c242016-03-08 11:31:49 +05301457
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001458 return 0;
1459}
1460
1461#ifdef WLAN_FEATURE_NAN
1462/**
1463 * wma_nan_rsp_event_handler() - Function is used to handle nan response
1464 * @handle: wma handle
1465 * @event_buf: event buffer
1466 * @len: length of buffer
1467 *
1468 * Return: 0 for success or error code
1469 */
1470int wma_nan_rsp_event_handler(void *handle, uint8_t *event_buf,
1471 uint32_t len)
1472{
1473 WMI_NAN_EVENTID_param_tlvs *param_buf;
1474 tSirNanEvent *nan_rsp_event;
1475 wmi_nan_event_hdr *nan_rsp_event_hdr;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301476 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001477 cds_msg_t cds_msg;
1478 uint8_t *buf_ptr;
1479 uint32_t alloc_len;
1480
1481 /*
1482 * This is how received event_buf looks like
1483 *
1484 * <-------------------- event_buf ----------------------------------->
1485 *
1486 * <--wmi_nan_event_hdr--><---WMI_TLV_HDR_SIZE---><----- data -------->
1487 *
1488 * +-----------+---------+-----------------------+--------------------+
1489 * | tlv_header| data_len| WMITLV_TAG_ARRAY_BYTE | nan_rsp_event_data |
1490 * +-----------+---------+-----------------------+--------------------+
1491 */
1492
1493 WMA_LOGD("%s: Posting NaN response event to SME", __func__);
1494 param_buf = (WMI_NAN_EVENTID_param_tlvs *) event_buf;
1495 if (!param_buf) {
1496 WMA_LOGE("%s: Invalid nan response event buf", __func__);
1497 return -EINVAL;
1498 }
1499 nan_rsp_event_hdr = param_buf->fixed_param;
1500 buf_ptr = (uint8_t *) nan_rsp_event_hdr;
1501 alloc_len = sizeof(tSirNanEvent);
1502 alloc_len += nan_rsp_event_hdr->data_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301503 nan_rsp_event = (tSirNanEvent *) qdf_mem_malloc(alloc_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001504 if (NULL == nan_rsp_event) {
1505 WMA_LOGE("%s: Memory allocation failure", __func__);
1506 return -ENOMEM;
1507 }
1508
1509 nan_rsp_event->event_data_len = nan_rsp_event_hdr->data_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301510 qdf_mem_copy(nan_rsp_event->event_data, buf_ptr +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001511 sizeof(wmi_nan_event_hdr) + WMI_TLV_HDR_SIZE,
1512 nan_rsp_event->event_data_len);
1513 cds_msg.type = eWNI_SME_NAN_EVENT;
1514 cds_msg.bodyptr = (void *)nan_rsp_event;
1515 cds_msg.bodyval = 0;
1516
1517 status = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301518 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001519 WMA_LOGE("%s: Failed to post NaN response event to SME",
1520 __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301521 qdf_mem_free(nan_rsp_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001522 return -EFAULT;
1523 }
1524 WMA_LOGD("%s: NaN response event Posted to SME", __func__);
1525 return 0;
1526}
Naveen Rawatc9f09522016-05-12 14:02:42 -07001527#else
1528int wma_nan_rsp_event_handler(void *handle, uint8_t *event_buf,
1529 uint32_t len)
1530{
1531 return 0;
1532}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001533#endif /* WLAN_FEATURE_NAN */
1534
1535/**
1536 * wma_csa_offload_handler() - CSA event handler
1537 * @handle: wma handle
1538 * @event: event buffer
1539 * @len: buffer length
1540 *
1541 * This event is sent by firmware when it receives CSA IE.
1542 *
1543 * Return: 0 for success or error code
1544 */
1545int wma_csa_offload_handler(void *handle, uint8_t *event, uint32_t len)
1546{
1547 tp_wma_handle wma = (tp_wma_handle) handle;
1548 WMI_CSA_HANDLING_EVENTID_param_tlvs *param_buf;
1549 wmi_csa_event_fixed_param *csa_event;
1550 uint8_t bssid[IEEE80211_ADDR_LEN];
1551 uint8_t vdev_id = 0;
1552 uint8_t cur_chan = 0;
1553 struct ieee80211_channelswitch_ie *csa_ie;
Chandrasekaran, Manishekar5c19dc52016-02-04 14:58:26 +05301554 struct csa_offload_params *csa_offload_event;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001555 struct ieee80211_extendedchannelswitch_ie *xcsa_ie;
1556 struct ieee80211_ie_wide_bw_switch *wb_ie;
1557 struct wma_txrx_node *intr = wma->interfaces;
1558
1559 param_buf = (WMI_CSA_HANDLING_EVENTID_param_tlvs *) event;
1560
1561 WMA_LOGD("%s: Enter", __func__);
1562 if (!param_buf) {
1563 WMA_LOGE("Invalid csa event buffer");
1564 return -EINVAL;
1565 }
1566 csa_event = param_buf->fixed_param;
1567 WMI_MAC_ADDR_TO_CHAR_ARRAY(&csa_event->i_addr2, &bssid[0]);
1568
1569 if (wma_find_vdev_by_bssid(wma, bssid, &vdev_id) == NULL) {
1570 WMA_LOGE("Invalid bssid received %s:%d", __func__, __LINE__);
1571 return -EINVAL;
1572 }
1573
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301574 csa_offload_event = qdf_mem_malloc(sizeof(*csa_offload_event));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001575 if (!csa_offload_event) {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05301576 WMA_LOGE("QDF MEM Alloc Failed for csa_offload_event");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001577 return -EINVAL;
1578 }
1579
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301580 qdf_mem_zero(csa_offload_event, sizeof(*csa_offload_event));
1581 qdf_mem_copy(csa_offload_event->bssId, &bssid, IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001582
1583 if (csa_event->ies_present_flag & WMI_CSA_IE_PRESENT) {
1584 csa_ie = (struct ieee80211_channelswitch_ie *)
1585 (&csa_event->csa_ie[0]);
1586 csa_offload_event->channel = csa_ie->newchannel;
Chandrasekaran, Manishekar5c19dc52016-02-04 14:58:26 +05301587 csa_offload_event->switch_mode = csa_ie->switchmode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001588 } else if (csa_event->ies_present_flag & WMI_XCSA_IE_PRESENT) {
1589 xcsa_ie = (struct ieee80211_extendedchannelswitch_ie *)
1590 (&csa_event->xcsa_ie[0]);
1591 csa_offload_event->channel = xcsa_ie->newchannel;
Chandrasekaran, Manishekar5c19dc52016-02-04 14:58:26 +05301592 csa_offload_event->switch_mode = xcsa_ie->switchmode;
Gupta, Kapil121bf212015-11-25 19:21:29 +05301593 csa_offload_event->new_op_class = xcsa_ie->newClass;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001594 } else {
1595 WMA_LOGE("CSA Event error: No CSA IE present");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301596 qdf_mem_free(csa_offload_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001597 return -EINVAL;
1598 }
1599
1600 if (csa_event->ies_present_flag & WMI_WBW_IE_PRESENT) {
1601 wb_ie = (struct ieee80211_ie_wide_bw_switch *)
1602 (&csa_event->wb_ie[0]);
1603 csa_offload_event->new_ch_width = wb_ie->new_ch_width;
1604 csa_offload_event->new_ch_freq_seg1 = wb_ie->new_ch_freq_seg1;
1605 csa_offload_event->new_ch_freq_seg2 = wb_ie->new_ch_freq_seg2;
1606 }
1607
1608 csa_offload_event->ies_present_flag = csa_event->ies_present_flag;
1609
1610 WMA_LOGD("CSA: New Channel = %d BSSID:%pM",
1611 csa_offload_event->channel, csa_offload_event->bssId);
1612
1613 cur_chan = cds_freq_to_chan(intr[vdev_id].mhz);
1614 /*
1615 * basic sanity check: requested channel should not be 0
1616 * and equal to home channel
1617 */
1618 if ((0 == csa_offload_event->channel) ||
1619 (cur_chan == csa_offload_event->channel)) {
1620 WMA_LOGE("CSA Event with channel %d. Ignore !!",
1621 csa_offload_event->channel);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301622 qdf_mem_free(csa_offload_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001623 return -EINVAL;
1624 }
1625 wma->interfaces[vdev_id].is_channel_switch = true;
1626 wma_send_msg(wma, WMA_CSA_OFFLOAD_EVENT, (void *)csa_offload_event, 0);
1627 return 0;
1628}
1629
1630#ifdef FEATURE_OEM_DATA_SUPPORT
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001631/**
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001632 * wma_oem_data_response_handler() - OEM data response event handler
1633 * @handle: wma handle
1634 * @datap: data ptr
1635 * @len: data length
1636 *
1637 * Return: 0 for success or error code
1638 */
1639int wma_oem_data_response_handler(void *handle,
1640 uint8_t *datap, uint32_t len)
1641{
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001642 WMI_OEM_RESPONSE_EVENTID_param_tlvs *param_buf;
1643 uint8_t *data;
1644 uint32_t datalen;
Krishna Kumaar Natarajanc1fa17d2016-08-03 14:19:20 -07001645 struct oem_data_rsp *oem_rsp;
Krishna Kumaar Natarajan73ea9f22016-06-30 18:38:47 -07001646 tpAniSirGlobal pmac = cds_get_context(QDF_MODULE_ID_PE);
1647
1648 if (!pmac) {
1649 WMA_LOGE(FL("Invalid pmac"));
1650 return -EINVAL;
1651 }
1652
Krishna Kumaar Natarajanbbbf2ef2016-08-03 14:06:26 -07001653 if (!pmac->sme.oem_data_rsp_callback) {
Krishna Kumaar Natarajan73ea9f22016-06-30 18:38:47 -07001654 WMA_LOGE(FL("Callback not registered"));
1655 return -EINVAL;
1656 }
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001657
1658 param_buf = (WMI_OEM_RESPONSE_EVENTID_param_tlvs *) datap;
1659 if (!param_buf) {
1660 WMA_LOGE(FL("Received NULL buf ptr from FW"));
1661 return -ENOMEM;
1662 }
1663
1664 data = param_buf->data;
1665 datalen = param_buf->num_data;
1666
1667 if (!data) {
1668 WMA_LOGE(FL("Received NULL data from FW"));
1669 return -EINVAL;
1670 }
1671
1672 if (datalen > OEM_DATA_RSP_SIZE) {
1673 WMA_LOGE(FL("Received data len %d exceeds max value %d"),
1674 datalen, OEM_DATA_RSP_SIZE);
1675 return -EINVAL;
1676 }
1677
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001678 oem_rsp = qdf_mem_malloc(sizeof(*oem_rsp));
1679 if (!oem_rsp) {
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001680 WMA_LOGE(FL("Failed to alloc oem_data_rsp"));
1681 return -ENOMEM;
1682 }
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001683 oem_rsp->rsp_len = datalen;
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001684 if (oem_rsp->rsp_len) {
Krishna Kumaar Natarajan73ea9f22016-06-30 18:38:47 -07001685 oem_rsp->data = qdf_mem_malloc(oem_rsp->rsp_len);
1686 if (!oem_rsp->data) {
1687 WMA_LOGE(FL("malloc failed for data"));
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001688 qdf_mem_free(oem_rsp);
1689 return -ENOMEM;
1690 }
1691 } else {
1692 WMA_LOGE(FL("Invalid rsp length: %d"),
1693 oem_rsp->rsp_len);
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001694 qdf_mem_free(oem_rsp);
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001695 return -EINVAL;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001696 }
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001697
Krishna Kumaar Natarajan73ea9f22016-06-30 18:38:47 -07001698 qdf_mem_copy(oem_rsp->data, data, datalen);
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001699
Krishna Kumaar Natarajan73ea9f22016-06-30 18:38:47 -07001700 WMA_LOGI(FL("Sending OEM_DATA_RSP(len: %d) to upper layer"), datalen);
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001701
Krishna Kumaar Natarajanbbbf2ef2016-08-03 14:06:26 -07001702 pmac->sme.oem_data_rsp_callback(oem_rsp);
Krishna Kumaar Natarajan73ea9f22016-06-30 18:38:47 -07001703
1704 if (oem_rsp->data)
1705 qdf_mem_free(oem_rsp->data);
1706 qdf_mem_free(oem_rsp);
1707
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001708 return 0;
1709}
1710
1711/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001712 * wma_start_oem_data_req() - start OEM data request to target
1713 * @wma_handle: wma handle
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -07001714 * @oem_data_req: start request params
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001715 *
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -07001716 * Return: QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001717 */
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -07001718QDF_STATUS wma_start_oem_data_req(tp_wma_handle wma_handle,
Krishna Kumaar Natarajanc1fa17d2016-08-03 14:19:20 -07001719 struct oem_data_req *oem_data_req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001720{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001721 int ret = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001722
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001723 WMA_LOGD(FL("Send OEM Data Request to target"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001724
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -07001725 if (!oem_data_req || !oem_data_req->data) {
1726 WMA_LOGE(FL("oem_data_req is null"));
1727 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001728 }
1729
1730 if (!wma_handle || !wma_handle->wmi_handle) {
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001731 WMA_LOGE(FL("WMA - closed, can not send Oem data request cmd"));
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -07001732 qdf_mem_free(oem_data_req->data);
1733 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001734 }
1735
Govind Singhaa64c242016-03-08 11:31:49 +05301736 ret = wmi_unified_start_oem_data_cmd(wma_handle->wmi_handle,
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -07001737 oem_data_req->data_len,
1738 oem_data_req->data);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001739
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -07001740 if (!QDF_IS_STATUS_SUCCESS(ret))
1741 WMA_LOGE(FL("wmi cmd send failed"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001742
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -07001743 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001744}
1745#endif /* FEATURE_OEM_DATA_SUPPORT */
1746
1747
1748/**
1749 * wma_unified_dfs_radar_rx_event_handler() - dfs radar rx event handler
1750 * @handle: wma handle
1751 * @data: data buffer
1752 * @datalen: data length
1753 *
1754 * WMI handler for WMI_DFS_RADAR_EVENTID
1755 * This handler is registered for handling
1756 * filtered DFS Phyerror. This handler is
1757 * will be invoked only when DFS Phyerr
1758 * filtering offload is enabled.
1759 *
1760 * Return: 1 for Success and 0 for error
1761 */
1762static int wma_unified_dfs_radar_rx_event_handler(void *handle,
1763 uint8_t *data,
1764 uint32_t datalen)
1765{
1766 tp_wma_handle wma = (tp_wma_handle) handle;
1767 struct ieee80211com *ic;
1768 struct ath_dfs *dfs;
1769 struct dfs_event *event;
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05301770 struct dfs_ieee80211_channel *chan;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001771 int empty;
1772 int do_check_chirp = 0;
1773 int is_hw_chirp = 0;
1774 int is_sw_chirp = 0;
1775 int is_pri = 0;
Vishwajith Upendrabf673e72016-01-19 16:05:40 -08001776 bool is_ch_dfs = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001777
1778 WMI_DFS_RADAR_EVENTID_param_tlvs *param_tlvs;
1779 wmi_dfs_radar_event_fixed_param *radar_event;
1780
1781 ic = wma->dfs_ic;
1782 if (NULL == ic) {
1783 WMA_LOGE("%s: dfs_ic is NULL ", __func__);
1784 return 0;
1785 }
1786
1787 dfs = (struct ath_dfs *)ic->ic_dfs;
1788 param_tlvs = (WMI_DFS_RADAR_EVENTID_param_tlvs *) data;
1789
1790 if (NULL == dfs) {
1791 WMA_LOGE("%s: dfs is NULL ", __func__);
1792 return 0;
1793 }
1794 /*
1795 * This parameter holds the number
1796 * of phyerror interrupts to the host
1797 * after the phyerrors have passed through
1798 * false detect filters in the firmware.
1799 */
1800 dfs->dfs_phyerr_count++;
1801
1802 if (!param_tlvs) {
1803 WMA_LOGE("%s: Received NULL data from FW", __func__);
1804 return 0;
1805 }
1806
1807 radar_event = param_tlvs->fixed_param;
1808
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301809 qdf_spin_lock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001810 chan = ic->ic_curchan;
Edhar, Mahesh Kumar35d9b2e2015-10-26 17:06:23 +05301811 if (ic->disable_phy_err_processing) {
1812 WMA_LOGD("%s: radar indication done,drop phyerror event",
1813 __func__);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301814 qdf_spin_unlock_bh(&ic->chan_lock);
Edhar, Mahesh Kumar35d9b2e2015-10-26 17:06:23 +05301815 return 0;
1816 }
1817
Vishwajith Upendrabf673e72016-01-19 16:05:40 -08001818 if (IEEE80211_IS_CHAN_11AC_VHT160(chan)) {
1819 is_ch_dfs = true;
1820 } else if (IEEE80211_IS_CHAN_11AC_VHT80P80(chan)) {
1821 if (cds_get_channel_state(chan->ic_ieee) == CHANNEL_STATE_DFS ||
1822 cds_get_channel_state(chan->ic_ieee_ext -
1823 WMA_80MHZ_START_CENTER_CH_DIFF) ==
1824 CHANNEL_STATE_DFS)
1825 is_ch_dfs = true;
1826 } else {
1827 if (cds_get_channel_state(chan->ic_ieee) == CHANNEL_STATE_DFS)
1828 is_ch_dfs = true;
1829 }
1830 if (!is_ch_dfs) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001831 WMA_LOGE
1832 ("%s: Invalid DFS Phyerror event. Channel=%d is Non-DFS",
1833 __func__, chan->ic_ieee);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301834 qdf_spin_unlock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001835 return 0;
1836 }
1837
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301838 qdf_spin_unlock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001839 dfs->ath_dfs_stats.total_phy_errors++;
1840
1841 if (dfs->dfs_caps.ath_chip_is_bb_tlv) {
1842 do_check_chirp = 1;
1843 is_pri = 1;
1844 is_hw_chirp = radar_event->pulse_is_chirp;
1845
1846 if ((uint32_t) dfs->dfs_phyerr_freq_min >
1847 radar_event->pulse_center_freq) {
1848 dfs->dfs_phyerr_freq_min =
1849 (int)radar_event->pulse_center_freq;
1850 }
1851
1852 if (dfs->dfs_phyerr_freq_max <
1853 (int)radar_event->pulse_center_freq) {
1854 dfs->dfs_phyerr_freq_max =
1855 (int)radar_event->pulse_center_freq;
1856 }
1857 }
1858
1859 /*
1860 * Now, add the parsed, checked and filtered
1861 * radar phyerror event radar pulse event list.
1862 * This event will then be processed by
1863 * dfs_radar_processevent() to see if the pattern
1864 * of pulses in radar pulse list match any radar
1865 * singnature in the current regulatory domain.
1866 */
1867
1868 ATH_DFSEVENTQ_LOCK(dfs);
1869 empty = STAILQ_EMPTY(&(dfs->dfs_eventq));
1870 ATH_DFSEVENTQ_UNLOCK(dfs);
1871 if (empty) {
1872 return 0;
1873 }
1874 /*
1875 * Add the event to the list, if there's space.
1876 */
1877 ATH_DFSEVENTQ_LOCK(dfs);
1878 event = STAILQ_FIRST(&(dfs->dfs_eventq));
1879 if (event == NULL) {
1880 ATH_DFSEVENTQ_UNLOCK(dfs);
1881 WMA_LOGE("%s: No more space left for queuing DFS Phyerror events",
1882 __func__);
1883 return 0;
1884 }
1885 STAILQ_REMOVE_HEAD(&(dfs->dfs_eventq), re_list);
1886 ATH_DFSEVENTQ_UNLOCK(dfs);
1887 dfs->dfs_phyerr_queued_count++;
1888 dfs->dfs_phyerr_w53_counter++;
1889 event->re_dur = (uint8_t) radar_event->pulse_duration;
1890 event->re_rssi = radar_event->rssi;
1891 event->re_ts = radar_event->pulse_detect_ts & DFS_TSMASK;
1892 event->re_full_ts = (((uint64_t) radar_event->upload_fullts_high) << 32)
1893 | radar_event->upload_fullts_low;
1894
1895 /*
1896 * Index of peak magnitude
1897 */
1898 event->sidx = radar_event->peak_sidx;
1899
1900 /*
1901 * Handle chirp flags.
1902 */
1903 if (do_check_chirp) {
1904 event->re_flags |= DFS_EVENT_CHECKCHIRP;
1905 if (is_hw_chirp) {
1906 event->re_flags |= DFS_EVENT_HW_CHIRP;
1907 }
1908 if (is_sw_chirp) {
1909 event->re_flags |= DFS_EVENT_SW_CHIRP;
1910 }
1911 }
1912 /*
1913 * Correctly set which channel is being reported on
1914 */
1915 if (is_pri) {
1916 event->re_chanindex = (uint8_t) dfs->dfs_curchan_radindex;
1917 } else {
1918 if (dfs->dfs_extchan_radindex == -1) {
1919 WMA_LOGI("%s phyerr on ext channel", __func__);
1920 }
1921 event->re_chanindex = (uint8_t) dfs->dfs_extchan_radindex;
1922 WMA_LOGI("%s:New extension channel event is added to queue",
1923 __func__);
1924 }
1925
1926 ATH_DFSQ_LOCK(dfs);
1927
1928 STAILQ_INSERT_TAIL(&(dfs->dfs_radarq), event, re_list);
1929
1930 empty = STAILQ_EMPTY(&dfs->dfs_radarq);
1931
1932 ATH_DFSQ_UNLOCK(dfs);
1933
1934 if (!empty && !dfs->ath_radar_tasksched) {
1935 dfs->ath_radar_tasksched = 1;
1936 OS_SET_TIMER(&dfs->ath_dfs_task_timer, 0);
1937 }
1938
1939 return 1;
1940
1941}
1942
1943/**
1944 * wma_unified_phyerr_rx_event_handler() - phyerr event handler
1945 * @handle: wma handle
1946 * @data: data buffer
1947 * @datalen: buffer length
1948 *
1949 * WMI Handler for WMI_PHYERR_EVENTID event from firmware.
1950 * This handler is currently handling only DFS phy errors.
1951 * This handler will be invoked only when the DFS phyerror
1952 * filtering offload is disabled.
1953 *
1954 * Return: 1:Success, 0:Failure
1955 */
1956static int wma_unified_phyerr_rx_event_handler(void *handle,
1957 uint8_t *data, uint32_t datalen)
1958{
1959 tp_wma_handle wma = (tp_wma_handle) handle;
1960 WMI_PHYERR_EVENTID_param_tlvs *param_tlvs;
1961 wmi_comb_phyerr_rx_hdr *pe_hdr;
1962 uint8_t *bufp;
1963 wmi_single_phyerr_rx_event *ev;
1964 struct ieee80211com *ic = wma->dfs_ic;
Anurag Chouhan6d760662016-02-20 16:05:43 +05301965 qdf_size_t n;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001966 A_UINT64 tsf64 = 0;
1967 int phy_err_code = 0;
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08001968 A_UINT32 phy_err_mask = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001969 int error = 0;
1970 tpAniSirGlobal mac_ctx =
Anurag Chouhan6d760662016-02-20 16:05:43 +05301971 (tpAniSirGlobal)cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001972 bool enable_log = false;
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08001973 int max_dfs_buf_length = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001974
1975 if (NULL == mac_ctx) {
1976 WMA_LOGE("%s: mac_ctx is NULL", __func__);
1977 return 0;
1978 }
1979 enable_log = mac_ctx->sap.enable_dfs_phy_error_logs;
1980
1981 param_tlvs = (WMI_PHYERR_EVENTID_param_tlvs *) data;
1982
1983 if (!param_tlvs) {
1984 WMA_LOGE("%s: Received NULL data from FW", __func__);
1985 return 0;
1986 }
1987
1988 pe_hdr = param_tlvs->hdr;
1989 if (pe_hdr == NULL) {
1990 WMA_LOGE("%s: Received Data PE Header is NULL", __func__);
1991 return 0;
1992 }
1993
1994 /* Ensure it's at least the size of the header */
1995 if (datalen < sizeof(*pe_hdr)) {
1996 WMA_LOGE("%s: Expected minimum size %zu, received %d",
1997 __func__, sizeof(*pe_hdr), datalen);
1998 return 0;
1999 }
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002000 /*
2001 * The max buffer lenght is larger for DFS-3 than DFS-2.
2002 * So, accordingly use the correct max buffer size.
2003 */
2004 if (wma->hw_bd_id != WMI_HWBD_QCA6174)
2005 max_dfs_buf_length = DFS3_MAX_BUF_LENGTH;
2006 else
2007 max_dfs_buf_length = DFS_MAX_BUF_LENGTH;
2008
2009 if (pe_hdr->buf_len > max_dfs_buf_length) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002010 WMA_LOGE("%s: Received Invalid Phyerror event buffer length = %d"
2011 "Maximum allowed buf length = %d", __func__,
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002012 pe_hdr->buf_len, max_dfs_buf_length);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002013
2014 return 0;
2015 }
2016
2017 /*
2018 * Reconstruct the 64 bit event TSF. This isn't from the MAC, it's
2019 * at the time the event was sent to us, the TSF value will be
2020 * in the future.
2021 */
2022 tsf64 = pe_hdr->tsf_l32;
2023 tsf64 |= (((uint64_t) pe_hdr->tsf_u32) << 32);
2024
2025 /*
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002026 * Check the HW board ID to figure out
2027 * if DFS-3 is supported. In DFS-3
2028 * phyerror mask indicates the type of
2029 * phyerror, whereas in DFS-2 phyerrorcode
2030 * indicates the type of phyerror. If the
2031 * board is NOT WMI_HWBD_QCA6174, for now
2032 * assume that it supports DFS-3.
2033 */
2034 if (wma->hw_bd_id != WMI_HWBD_QCA6174) {
2035 phy_err_mask = pe_hdr->rsPhyErrMask0;
2036 WMA_LOGD("%s: DFS-3 phyerror mask = 0x%x",
2037 __func__, phy_err_mask);
2038 }
2039
2040 /*
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002041 * Loop over the bufp, extracting out phyerrors
2042 * wmi_unified_comb_phyerr_rx_event.bufp is a char pointer,
2043 * which isn't correct here - what we have received here
2044 * is an array of TLV-style PHY errors.
2045 */
2046 n = 0; /* Start just after the header */
2047 bufp = param_tlvs->bufp;
2048 while (n < pe_hdr->buf_len) {
2049 /* ensure there's at least space for the header */
2050 if ((pe_hdr->buf_len - n) < sizeof(ev->hdr)) {
2051 WMA_LOGE("%s: Not enough space.(datalen=%d, n=%zu, hdr=%zu bytes",
2052 __func__, pe_hdr->buf_len, n, sizeof(ev->hdr));
2053 error = 1;
2054 break;
2055 }
2056 /*
2057 * Obtain a pointer to the beginning of the current event.
2058 * data[0] is the beginning of the WMI payload.
2059 */
2060 ev = (wmi_single_phyerr_rx_event *) &bufp[n];
2061
2062 /*
2063 * Sanity check the buffer length of the event against
2064 * what we currently have.
2065 * Since buf_len is 32 bits, we check if it overflows
2066 * a large 32 bit value. It's not 0x7fffffff because
2067 * we increase n by (buf_len + sizeof(hdr)), which would
2068 * in itself cause n to overflow.
2069 * If "int" is 64 bits then this becomes a moot point.
2070 */
2071 if (ev->hdr.buf_len > 0x7f000000) {
2072 WMA_LOGE("%s:buf_len is garbage (0x%x)", __func__,
2073 ev->hdr.buf_len);
2074 error = 1;
2075 break;
2076 }
2077 if (n + ev->hdr.buf_len > pe_hdr->buf_len) {
2078 WMA_LOGE("%s: buf_len exceeds available space n=%zu,"
2079 "buf_len=%d, datalen=%d",
2080 __func__, n, ev->hdr.buf_len, pe_hdr->buf_len);
2081 error = 1;
2082 break;
2083 }
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002084 /*
2085 * If the board id is WMI_HWBD_QCA6174
2086 * then it supports only DFS-2. So, fetch
2087 * phyerror code in order to know the type
2088 * of phyerror.
2089 */
2090 if (wma->hw_bd_id == WMI_HWBD_QCA6174) {
2091 phy_err_code = WMI_UNIFIED_PHYERRCODE_GET(&ev->hdr);
2092 WMA_LOGD("%s: DFS-2 phyerror code = 0x%x",
2093 __func__, phy_err_code);
2094 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002095
2096 /*
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002097 * phy_err_code is set for DFS-2 and phy_err_mask
2098 * is set for DFS-3. Checking both to support
2099 * compatability for older platforms.
2100 * If the phyerror or phyerrmask category matches,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002101 * pass radar events to the dfs pattern matching code.
2102 * Don't pass radar events with no buffer payload.
2103 */
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002104 if (((phy_err_mask & WMI_PHY_ERROR_MASK0_RADAR) ||
2105 (phy_err_mask & WMI_PHY_ERROR_MASK0_FALSE_RADAR_EXT)) ||
2106 (phy_err_code == WMA_DFS2_PHYERROR_CODE ||
2107 phy_err_code == WMA_DFS2_FALSE_RADAR_EXT)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002108 if (ev->hdr.buf_len > 0) {
2109 /* Calling in to the DFS module to process the phyerr */
2110 dfs_process_phyerr(ic, &ev->bufp[0],
2111 ev->hdr.buf_len,
2112 WMI_UNIFIED_RSSI_COMB_GET
2113 (&ev->hdr) & 0xff,
2114 /* Extension RSSI */
2115 WMI_UNIFIED_RSSI_COMB_GET
2116 (&ev->hdr) & 0xff,
2117 ev->hdr.tsf_timestamp,
2118 tsf64, enable_log);
2119 }
2120 }
2121
2122 /*
2123 * Advance the buffer pointer to the next PHY error.
2124 * buflen is the length of this payload, so we need to
2125 * advance past the current header _AND_ the payload.
2126 */
2127 n += sizeof(*ev) + ev->hdr.buf_len;
2128
2129 } /*end while() */
2130 if (error)
2131 return 0;
2132 else
2133 return 1;
2134}
2135
2136/**
2137 * wma_register_dfs_event_handler() - register dfs event handler
2138 * @wma_handle: wma handle
2139 *
2140 * Register appropriate dfs phyerror event handler
2141 * based on phyerror filtering offload is enabled
2142 * or disabled.
2143 *
2144 * Return: none
2145 */
2146void wma_register_dfs_event_handler(tp_wma_handle wma_handle)
2147{
2148 if (NULL == wma_handle) {
2149 WMA_LOGE("%s:wma_handle is NULL", __func__);
2150 return;
2151 }
2152
2153 if (false == wma_handle->dfs_phyerr_filter_offload) {
2154 /*
2155 * Register the wma_unified_phyerr_rx_event_handler
2156 * for filtering offload disabled case to handle
2157 * the DFS phyerrors.
2158 */
2159 WMA_LOGD("%s:Phyerror Filtering offload is Disabled in ini",
2160 __func__);
2161 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Govind Singhd76a5b02016-03-08 15:12:14 +05302162 WMI_PHYERR_EVENTID,
2163 wma_unified_phyerr_rx_event_handler,
2164 WMA_RX_WORK_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002165 WMA_LOGD("%s: WMI_PHYERR_EVENTID event handler registered",
2166 __func__);
2167 } else {
2168 WMA_LOGD("%s:Phyerror Filtering offload is Enabled in ini",
2169 __func__);
2170 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Govind Singhd76a5b02016-03-08 15:12:14 +05302171 WMI_DFS_RADAR_EVENTID,
2172 wma_unified_dfs_radar_rx_event_handler,
2173 WMA_RX_WORK_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002174 WMA_LOGD("%s:WMI_DFS_RADAR_EVENTID event handler registered",
2175 __func__);
2176 }
2177
2178 return;
2179}
2180
2181
2182/**
2183 * wma_unified_dfs_phyerr_filter_offload_enable() - enable dfs phyerr filter
2184 * @wma_handle: wma handle
2185 *
2186 * Send WMI_DFS_PHYERR_FILTER_ENA_CMDID or
2187 * WMI_DFS_PHYERR_FILTER_DIS_CMDID command
2188 * to firmware based on phyerr filtering
2189 * offload status.
2190 *
2191 * Return: 1 success, 0 failure
2192 */
2193int
2194wma_unified_dfs_phyerr_filter_offload_enable(tp_wma_handle wma_handle)
2195{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002196 int ret;
2197
2198 if (NULL == wma_handle) {
2199 WMA_LOGE("%s:wma_handle is NULL", __func__);
2200 return 0;
2201 }
2202
Govind Singhaa64c242016-03-08 11:31:49 +05302203 ret = wmi_unified_dfs_phyerr_filter_offload_en_cmd(wma_handle->wmi_handle,
2204 wma_handle->dfs_phyerr_filter_offload);
2205 if (ret)
2206 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002207
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002208
Govind Singhaa64c242016-03-08 11:31:49 +05302209 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002210}
2211
2212#if !defined(REMOVE_PKT_LOG)
2213/**
2214 * wma_pktlog_wmi_send_cmd() - send pktlog enable/disable command to target
2215 * @handle: wma handle
2216 * @params: pktlog params
2217 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302218 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002219 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302220QDF_STATUS wma_pktlog_wmi_send_cmd(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002221 struct ath_pktlog_wmi_params *params)
2222{
2223 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhaa64c242016-03-08 11:31:49 +05302224 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002225
2226 /*Check if packet log is enabled in cfg.ini */
2227 if (!cds_is_packet_log_enabled()) {
2228 WMA_LOGE("%s:pkt log is not enabled in cfg.ini", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302229 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002230 }
2231
Govind Singhaa64c242016-03-08 11:31:49 +05302232 ret = wmi_unified_pktlog_wmi_send_cmd(wma_handle->wmi_handle,
2233 params->pktlog_event,
2234 params->cmd_id);
2235 if (ret)
2236 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002237
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002238
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302239 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002240}
2241#endif /* REMOVE_PKT_LOG */
2242
2243static void wma_send_status_to_suspend_ind(tp_wma_handle wma, bool suspended)
2244{
2245 tSirReadyToSuspendInd *ready_to_suspend;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302246 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002247 cds_msg_t cds_msg;
2248 uint8_t len;
2249
2250 WMA_LOGD("Posting ready to suspend indication to umac");
2251
2252 len = sizeof(tSirReadyToSuspendInd);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302253 ready_to_suspend = (tSirReadyToSuspendInd *) qdf_mem_malloc(len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002254
2255 if (NULL == ready_to_suspend) {
2256 WMA_LOGE("%s: Memory allocation failure", __func__);
2257 return;
2258 }
2259
2260 ready_to_suspend->mesgType = eWNI_SME_READY_TO_SUSPEND_IND;
2261 ready_to_suspend->mesgLen = len;
2262 ready_to_suspend->suspended = suspended;
2263
2264 cds_msg.type = eWNI_SME_READY_TO_SUSPEND_IND;
2265 cds_msg.bodyptr = (void *)ready_to_suspend;
2266 cds_msg.bodyval = 0;
2267
2268 status = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302269 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002270 WMA_LOGE("Failed to post ready to suspend");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302271 qdf_mem_free(ready_to_suspend);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002272 }
2273}
2274
2275/**
2276 * wma_wow_wake_reason_str() - Converts wow wakeup reason code to text format
2277 * @wake_reason - WOW wake reason
2278 *
2279 * Return: reason code in string format
2280 */
2281static const u8 *wma_wow_wake_reason_str(A_INT32 wake_reason)
2282{
2283 switch (wake_reason) {
2284 case WOW_REASON_UNSPECIFIED:
2285 return "UNSPECIFIED";
2286 case WOW_REASON_NLOD:
2287 return "NLOD";
2288 case WOW_REASON_AP_ASSOC_LOST:
2289 return "AP_ASSOC_LOST";
2290 case WOW_REASON_LOW_RSSI:
2291 return "LOW_RSSI";
2292 case WOW_REASON_DEAUTH_RECVD:
2293 return "DEAUTH_RECVD";
2294 case WOW_REASON_DISASSOC_RECVD:
2295 return "DISASSOC_RECVD";
2296 case WOW_REASON_GTK_HS_ERR:
2297 return "GTK_HS_ERR";
2298 case WOW_REASON_EAP_REQ:
2299 return "EAP_REQ";
2300 case WOW_REASON_FOURWAY_HS_RECV:
2301 return "FOURWAY_HS_RECV";
2302 case WOW_REASON_TIMER_INTR_RECV:
2303 return "TIMER_INTR_RECV";
2304 case WOW_REASON_PATTERN_MATCH_FOUND:
2305 return "PATTERN_MATCH_FOUND";
2306 case WOW_REASON_RECV_MAGIC_PATTERN:
2307 return "RECV_MAGIC_PATTERN";
2308 case WOW_REASON_P2P_DISC:
2309 return "P2P_DISC";
2310#ifdef FEATURE_WLAN_LPHB
2311 case WOW_REASON_WLAN_HB:
2312 return "WLAN_HB";
2313#endif /* FEATURE_WLAN_LPHB */
2314
2315 case WOW_REASON_CSA_EVENT:
2316 return "CSA_EVENT";
2317 case WOW_REASON_PROBE_REQ_WPS_IE_RECV:
2318 return "PROBE_REQ_RECV";
2319 case WOW_REASON_AUTH_REQ_RECV:
2320 return "AUTH_REQ_RECV";
2321 case WOW_REASON_ASSOC_REQ_RECV:
2322 return "ASSOC_REQ_RECV";
2323 case WOW_REASON_HTT_EVENT:
2324 return "WOW_REASON_HTT_EVENT";
2325#ifdef FEATURE_WLAN_RA_FILTERING
2326 case WOW_REASON_RA_MATCH:
2327 return "WOW_REASON_RA_MATCH";
2328#endif /* FEATURE_WLAN_RA_FILTERING */
2329 case WOW_REASON_BEACON_RECV:
2330 return "WOW_REASON_IBSS_BEACON_RECV";
2331#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
2332 case WOW_REASON_HOST_AUTO_SHUTDOWN:
2333 return "WOW_REASON_HOST_AUTO_SHUTDOWN";
2334#endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
2335#ifdef WLAN_FEATURE_ROAM_OFFLOAD
2336 case WOW_REASON_ROAM_HO:
2337 return "WOW_REASON_ROAM_HO";
2338#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
2339#ifdef FEATURE_WLAN_EXTSCAN
2340 case WOW_REASON_EXTSCAN:
2341 return "WOW_REASON_EXTSCAN";
2342#endif
2343 case WOW_REASON_RSSI_BREACH_EVENT:
2344 return "WOW_REASON_RSSI_BREACH_EVENT";
Srinivas Girigowdae80cea92015-11-23 11:33:57 -08002345 case WOW_REASON_NLO_SCAN_COMPLETE:
2346 return "WOW_REASON_NLO_SCAN_COMPLETE";
Naveen Rawatc9f09522016-05-12 14:02:42 -07002347 case WOW_REASON_NAN_EVENT:
2348 return "WOW_REASON_NAN_EVENT";
Selvaraj, Sridhar172cabc2016-07-05 15:19:24 +05302349 case WOW_REASON_OEM_RESPONSE_EVENT:
2350 return "WOW_OEM_RESPONSE_EVENT";
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002351 }
2352 return "unknown";
2353}
2354
2355/**
2356 * wma_wow_wake_up_stats_display() - display wow wake up stats
2357 * @wma: Pointer to wma handle
2358 *
2359 * Return: none
2360 */
2361static void wma_wow_wake_up_stats_display(tp_wma_handle wma)
2362{
Selvaraj, Sridhar172cabc2016-07-05 15:19:24 +05302363 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 oem %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002364 wma->wow_ucast_wake_up_count,
2365 wma->wow_bcast_wake_up_count,
2366 wma->wow_ipv4_mcast_wake_up_count,
2367 wma->wow_ipv6_mcast_wake_up_count,
2368 wma->wow_ipv6_mcast_ra_stats,
2369 wma->wow_ipv6_mcast_ns_stats,
2370 wma->wow_ipv6_mcast_na_stats,
2371 wma->wow_pno_match_wake_up_count,
2372 wma->wow_pno_complete_wake_up_count,
2373 wma->wow_gscan_wake_up_count,
2374 wma->wow_low_rssi_wake_up_count,
Selvaraj, Sridhar172cabc2016-07-05 15:19:24 +05302375 wma->wow_rssi_breach_wake_up_count,
2376 wma->wow_oem_response_wake_up_count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002377
2378 return;
2379}
2380
2381/**
2382 * wma_wow_ipv6_mcast_stats() - ipv6 mcast wake up stats
2383 * @wma: Pointer to wma handle
2384 * @data: Pointer to pattern match data
2385 *
2386 * Return: none
2387 */
2388static void wma_wow_ipv6_mcast_stats(tp_wma_handle wma, uint8_t *data)
2389{
2390 static const uint8_t ipv6_mcast[] = {0x86, 0xDD};
2391
2392 if (!memcmp(ipv6_mcast, (data + WMA_ETHER_TYPE_OFFSET),
2393 sizeof(ipv6_mcast))) {
2394 if (WMA_ICMP_V6_HEADER_TYPE ==
2395 *(data + WMA_ICMP_V6_HEADER_OFFSET)) {
2396 if (WMA_ICMP_V6_RA_TYPE ==
2397 *(data + WMA_ICMP_V6_TYPE_OFFSET))
2398 wma->wow_ipv6_mcast_ra_stats++;
2399 else if (WMA_ICMP_V6_NS_TYPE ==
2400 *(data + WMA_ICMP_V6_TYPE_OFFSET))
2401 wma->wow_ipv6_mcast_ns_stats++;
2402 else if (WMA_ICMP_V6_NA_TYPE ==
2403 *(data + WMA_ICMP_V6_TYPE_OFFSET))
2404 wma->wow_ipv6_mcast_na_stats++;
2405 else
2406 WMA_LOGA("ICMP V6 type : 0x%x",
2407 *(data + WMA_ICMP_V6_TYPE_OFFSET));
2408 } else {
2409 WMA_LOGA("ICMP_V6 header 0x%x",
2410 *(data + WMA_ICMP_V6_HEADER_OFFSET));
2411 }
2412 } else {
2413 WMA_LOGA("Ethertype x%x:0x%x",
2414 *(data + WMA_ETHER_TYPE_OFFSET),
2415 *(data + WMA_ETHER_TYPE_OFFSET + 1));
2416 }
2417
2418 return;
2419}
2420
2421/**
2422 * wma_wow_wake_up_stats() - maintain wow pattern match wake up stats
2423 * @wma: Pointer to wma handle
2424 * @data: Pointer to pattern match data
2425 * @len: Pattern match data length
2426 * @event: Wake up event
2427 *
2428 * Return: none
2429 */
2430static void wma_wow_wake_up_stats(tp_wma_handle wma, uint8_t *data,
2431 int32_t len, WOW_WAKE_REASON_TYPE event)
2432{
2433 switch (event) {
2434
2435 case WOW_REASON_PATTERN_MATCH_FOUND:
2436 if (WMA_BCAST_MAC_ADDR == *data) {
2437 wma->wow_bcast_wake_up_count++;
2438 } else if (WMA_MCAST_IPV4_MAC_ADDR == *data) {
2439 wma->wow_ipv4_mcast_wake_up_count++;
2440 } else if (WMA_MCAST_IPV6_MAC_ADDR == *data) {
2441 wma->wow_ipv6_mcast_wake_up_count++;
2442 if (len > WMA_ICMP_V6_TYPE_OFFSET)
2443 wma_wow_ipv6_mcast_stats(wma, data);
2444 else
2445 WMA_LOGA("ICMP_V6 data len %d", len);
2446 } else {
2447 wma->wow_ucast_wake_up_count++;
2448 }
2449 break;
2450
2451 case WOW_REASON_RA_MATCH:
2452 wma->wow_ipv6_mcast_ra_stats++;
2453 break;
2454
2455 case WOW_REASON_NLOD:
2456 wma->wow_pno_match_wake_up_count++;
2457 break;
2458
2459 case WOW_REASON_NLO_SCAN_COMPLETE:
2460 wma->wow_pno_complete_wake_up_count++;
2461 break;
2462
2463 case WOW_REASON_LOW_RSSI:
2464 wma->wow_low_rssi_wake_up_count++;
2465 break;
2466
2467 case WOW_REASON_EXTSCAN:
2468 wma->wow_gscan_wake_up_count++;
2469 break;
2470
2471 case WOW_REASON_RSSI_BREACH_EVENT:
2472 wma->wow_rssi_breach_wake_up_count++;
2473 break;
Selvaraj, Sridhar172cabc2016-07-05 15:19:24 +05302474 case WOW_REASON_OEM_RESPONSE_EVENT:
2475 wma->wow_oem_response_wake_up_count++;
2476 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002477
2478 default:
2479 WMA_LOGE("Unknown wake up reason");
2480 break;
2481 }
2482
2483 wma_wow_wake_up_stats_display(wma);
2484 return;
2485}
2486
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07002487#ifdef FEATURE_WLAN_EXTSCAN
2488/**
2489 * wma_extscan_get_eventid_from_tlvtag() - map tlv tag to corresponding event id
2490 * @tag: WMI TLV tag
2491 *
2492 * Return:
2493 * 0 if TLV tag is invalid
2494 * else return corresponding WMI event id
2495 */
2496static int wma_extscan_get_eventid_from_tlvtag(uint32_t tag)
2497{
2498 uint32_t event_id;
2499
2500 switch (tag) {
2501 case WMITLV_TAG_STRUC_wmi_extscan_start_stop_event_fixed_param:
2502 event_id = WMI_EXTSCAN_START_STOP_EVENTID;
2503 break;
2504
2505 case WMITLV_TAG_STRUC_wmi_extscan_operation_event_fixed_param:
2506 event_id = WMI_EXTSCAN_OPERATION_EVENTID;
2507 break;
2508
2509 case WMITLV_TAG_STRUC_wmi_extscan_table_usage_event_fixed_param:
2510 event_id = WMI_EXTSCAN_TABLE_USAGE_EVENTID;
2511 break;
2512
2513 case WMITLV_TAG_STRUC_wmi_extscan_cached_results_event_fixed_param:
2514 event_id = WMI_EXTSCAN_CACHED_RESULTS_EVENTID;
2515 break;
2516
2517 case WMITLV_TAG_STRUC_wmi_extscan_wlan_change_results_event_fixed_param:
2518 event_id = WMI_EXTSCAN_WLAN_CHANGE_RESULTS_EVENTID;
2519 break;
2520
2521 case WMITLV_TAG_STRUC_wmi_extscan_hotlist_match_event_fixed_param:
2522 event_id = WMI_EXTSCAN_HOTLIST_MATCH_EVENTID;
2523 break;
2524
2525 case WMITLV_TAG_STRUC_wmi_extscan_capabilities_event_fixed_param:
2526 event_id = WMI_EXTSCAN_CAPABILITIES_EVENTID;
2527 break;
2528
2529 case WMITLV_TAG_STRUC_wmi_extscan_hotlist_ssid_match_event_fixed_param:
2530 event_id = WMI_EXTSCAN_HOTLIST_SSID_MATCH_EVENTID;
2531 break;
2532
2533 default:
2534 event_id = 0;
2535 WMA_LOGE("%s: Unknown tag: %d", __func__, tag);
2536 break;
2537 }
2538
2539 WMA_LOGI("%s: For tag %d WMI event 0x%x", __func__, tag, event_id);
2540 return event_id;
2541}
2542#else
2543static int wma_extscan_get_eventid_from_tlvtag(uint32_t tag)
2544{
2545 return 0;
2546}
2547#endif
2548
2549/**
2550 * wow_get_wmi_eventid() - map reason or tlv tag to corresponding event id
2551 * @tag: WMI TLV tag
2552 * @reason: WOW reason
2553 *
2554 * WOW reason type is primarily used to find the ID. If there could be
2555 * multiple events that can be sent as a WOW event with same reason
2556 * then tlv tag is used to identify the corresponding event.
2557 *
2558 * Return:
2559 * 0 if TLV tag/reason is invalid
2560 * else return corresponding WMI event id
2561 */
2562static int wow_get_wmi_eventid(int32_t reason, uint32_t tag)
2563{
2564 uint32_t event_id;
2565
2566 switch (reason) {
2567 case WOW_REASON_NLO_SCAN_COMPLETE:
2568 event_id = WMI_NLO_SCAN_COMPLETE_EVENTID;
2569 break;
2570 case WOW_REASON_CSA_EVENT:
2571 event_id = WMI_CSA_HANDLING_EVENTID;
2572 break;
2573 case WOW_REASON_LOW_RSSI:
2574 event_id = WMI_ROAM_EVENTID;
2575 break;
2576 case WOW_REASON_CLIENT_KICKOUT_EVENT:
2577 event_id = WMI_PEER_STA_KICKOUT_EVENTID;
2578 break;
2579 case WOW_REASON_EXTSCAN:
2580 event_id = wma_extscan_get_eventid_from_tlvtag(tag);
2581 break;
2582 case WOW_REASON_RSSI_BREACH_EVENT:
2583 event_id = WMI_RSSI_BREACH_EVENTID;
2584 break;
2585 case WOW_REASON_NAN_EVENT:
2586 event_id = WMI_NAN_EVENTID;
2587 break;
2588 default:
2589 WMA_LOGD(FL("Unexpected WOW reason : %s(%d)"),
2590 wma_wow_wake_reason_str(reason), reason);
2591 event_id = 0;
2592 break;
2593 }
2594
2595 return event_id;
2596}
2597
2598/**
2599 * tlv_check_required() - tells whether to check the wow packet buffer
2600 * for proper TLV structure.
2601 * @reason: WOW reason
2602 *
2603 * In most cases, wow wake up event carries the actual event buffer in
2604 * wow_packet_buffer with some exceptions. This function is used to
2605 * determine when to check for the TLVs in wow_packet_buffer.
2606 *
2607 * Return: true if check is required and false otherwise.
2608 */
2609static bool tlv_check_required(int32_t reason)
2610{
2611 switch (reason) {
2612 case WOW_REASON_PATTERN_MATCH_FOUND:
2613 return false;
2614 default:
2615 return true;
2616 }
2617}
2618
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002619/**
2620 * wma_wow_wakeup_host_event() - wakeup host event handler
2621 * @handle: wma handle
2622 * @event: event data
2623 * @len: buffer length
2624 *
2625 * Handler to catch wow wakeup host event. This event will have
2626 * reason why the firmware has woken the host.
2627 *
2628 * Return: 0 for success or error
2629 */
2630int wma_wow_wakeup_host_event(void *handle, uint8_t *event,
2631 uint32_t len)
2632{
2633 tp_wma_handle wma = (tp_wma_handle) handle;
2634 WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *param_buf;
2635 WOW_EVENT_INFO_fixed_param *wake_info;
2636#ifdef FEATURE_WLAN_SCAN_PNO
2637 struct wma_txrx_node *node;
2638#endif /* FEATURE_WLAN_SCAN_PNO */
2639 uint32_t wake_lock_duration = 0;
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07002640 void *wmi_cmd_struct_ptr = NULL;
2641 uint32_t tlv_hdr, tag, wow_buf_pkt_len = 0, event_id = 0;
2642 int tlv_ok_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002643
2644 param_buf = (WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *) event;
2645 if (!param_buf) {
2646 WMA_LOGE("Invalid wow wakeup host event buf");
2647 return -EINVAL;
2648 }
2649
2650 wake_info = param_buf->fixed_param;
2651
2652 WMA_LOGA("WOW wakeup host event received (reason: %s(%d)) for vdev %d",
2653 wma_wow_wake_reason_str(wake_info->wake_reason),
2654 wake_info->wake_reason, wake_info->vdev_id);
2655
Anurag Chouhance0dc992016-02-16 18:18:03 +05302656 qdf_event_set(&wma->wma_resume_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002657
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07002658 if (param_buf->wow_packet_buffer &&
2659 tlv_check_required(wake_info->wake_reason)) {
2660 /*
2661 * In case of wow_packet_buffer, first 4 bytes is the length.
2662 * Following the length is the actual buffer.
2663 */
2664 wow_buf_pkt_len = *(uint32_t *)param_buf->wow_packet_buffer;
2665 tlv_hdr = WMITLV_GET_HDR(
2666 (uint8_t *)param_buf->wow_packet_buffer + 4);
2667
2668 tag = WMITLV_GET_TLVTAG(tlv_hdr);
2669 event_id = wow_get_wmi_eventid(wake_info->wake_reason, tag);
2670 if (!event_id) {
2671 WMA_LOGE(FL("Unable to find matching ID"));
2672 return -EINVAL;
2673 }
2674
2675 tlv_ok_status = wmitlv_check_and_pad_event_tlvs(
2676 handle, param_buf->wow_packet_buffer + 4,
2677 wow_buf_pkt_len, event_id,
2678 &wmi_cmd_struct_ptr);
2679
2680 if (tlv_ok_status != 0) {
2681 WMA_LOGE(FL("Invalid TLVs, Length:%d event_id:%d status: %d"),
2682 wow_buf_pkt_len, event_id, tlv_ok_status);
2683 return -EINVAL;
2684 }
2685 }
2686
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002687 switch (wake_info->wake_reason) {
2688 case WOW_REASON_AUTH_REQ_RECV:
2689 wake_lock_duration = WMA_AUTH_REQ_RECV_WAKE_LOCK_TIMEOUT;
2690 break;
2691
2692 case WOW_REASON_ASSOC_REQ_RECV:
2693 wake_lock_duration = WMA_ASSOC_REQ_RECV_WAKE_LOCK_DURATION;
2694 break;
2695
2696 case WOW_REASON_DEAUTH_RECVD:
2697 wake_lock_duration = WMA_DEAUTH_RECV_WAKE_LOCK_DURATION;
2698 break;
2699
2700 case WOW_REASON_DISASSOC_RECVD:
2701 wake_lock_duration = WMA_DISASSOC_RECV_WAKE_LOCK_DURATION;
2702 break;
2703
2704 case WOW_REASON_AP_ASSOC_LOST:
2705 wake_lock_duration = WMA_BMISS_EVENT_WAKE_LOCK_DURATION;
2706 WMA_LOGA("Beacon miss indication on vdev %x",
2707 wake_info->vdev_id);
2708 wma_beacon_miss_handler(wma, wake_info->vdev_id);
2709 break;
2710#ifdef FEATURE_WLAN_RA_FILTERING
2711 case WOW_REASON_RA_MATCH:
2712 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_RA_MATCH);
2713 break;
2714#endif /* FEATURE_WLAN_RA_FILTERING */
2715#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
2716 case WOW_REASON_HOST_AUTO_SHUTDOWN:
2717 wake_lock_duration = WMA_AUTO_SHUTDOWN_WAKE_LOCK_DURATION;
2718 WMA_LOGA("Received WOW Auto Shutdown trigger in suspend");
2719 if (wma_post_auto_shutdown_msg())
2720 return -EINVAL;
2721 break;
2722#endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
2723#ifdef FEATURE_WLAN_SCAN_PNO
2724 case WOW_REASON_NLOD:
2725 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_NLOD);
2726 node = &wma->interfaces[wake_info->vdev_id];
2727 if (node) {
2728 WMA_LOGD("NLO match happened");
2729 node->nlo_match_evt_received = true;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302730 qdf_wake_lock_timeout_acquire(&wma->pno_wake_lock,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002731 WMA_PNO_MATCH_WAKE_LOCK_TIMEOUT,
2732 WIFI_POWER_EVENT_WAKELOCK_PNO);
Srinivas Girigowdae80cea92015-11-23 11:33:57 -08002733 }
2734 break;
2735
2736 case WOW_REASON_NLO_SCAN_COMPLETE:
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07002737 WMA_LOGD("Host woken up due to pno scan complete reason");
2738 if (param_buf->wow_packet_buffer)
2739 wma_nlo_scan_cmp_evt_handler(handle,
2740 wmi_cmd_struct_ptr, wow_buf_pkt_len);
2741 else
2742 WMA_LOGD("No wow_packet_buffer present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002743 break;
2744#endif /* FEATURE_WLAN_SCAN_PNO */
2745
2746 case WOW_REASON_CSA_EVENT:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002747 WMA_LOGD("Host woken up because of CSA IE");
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07002748 wma_csa_offload_handler(handle, wmi_cmd_struct_ptr,
2749 wow_buf_pkt_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002750 break;
2751
2752#ifdef FEATURE_WLAN_LPHB
2753 case WOW_REASON_WLAN_HB:
2754 wma_lphb_handler(wma, (uint8_t *) param_buf->hb_indevt);
2755 break;
2756#endif /* FEATURE_WLAN_LPHB */
2757
2758 case WOW_REASON_HTT_EVENT:
2759 break;
2760 case WOW_REASON_PATTERN_MATCH_FOUND:
2761 wma_wow_wake_up_stats_display(wma);
2762 WMA_LOGD("Wake up for Rx packet, dump starting from ethernet hdr");
2763 if (param_buf->wow_packet_buffer) {
2764 /* First 4-bytes of wow_packet_buffer is the length */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302765 qdf_mem_copy((uint8_t *) &wow_buf_pkt_len,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002766 param_buf->wow_packet_buffer, 4);
2767 wma_wow_wake_up_stats(wma,
2768 param_buf->wow_packet_buffer + 4,
2769 wow_buf_pkt_len,
2770 WOW_REASON_PATTERN_MATCH_FOUND);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302771 qdf_trace_hex_dump(QDF_MODULE_ID_WMA,
2772 QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002773 param_buf->wow_packet_buffer + 4,
2774 wow_buf_pkt_len);
2775 } else {
2776 WMA_LOGE("No wow packet buffer present");
2777 }
2778 break;
2779
2780 case WOW_REASON_LOW_RSSI:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002781 /* WOW_REASON_LOW_RSSI is used for all roaming events.
2782 * WMI_ROAM_REASON_BETTER_AP, WMI_ROAM_REASON_BMISS,
2783 * WMI_ROAM_REASON_SUITABLE_AP will be handled by
2784 * wma_roam_event_callback().
2785 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002786 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_LOW_RSSI);
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07002787 WMA_LOGD("Host woken up because of roam event");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002788 if (param_buf->wow_packet_buffer) {
2789 /* Roam event is embedded in wow_packet_buffer */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002790 WMA_LOGD("wow_packet_buffer dump");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302791 qdf_trace_hex_dump(QDF_MODULE_ID_WMA,
2792 QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002793 param_buf->wow_packet_buffer,
2794 wow_buf_pkt_len);
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07002795 wma_roam_event_callback(handle, wmi_cmd_struct_ptr,
2796 wow_buf_pkt_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002797 } else {
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07002798 /*
2799 * No wow_packet_buffer means a better AP beacon
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002800 * will follow in a later event.
2801 */
2802 WMA_LOGD("Host woken up because of better AP beacon");
2803 }
2804 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002805 case WOW_REASON_CLIENT_KICKOUT_EVENT:
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07002806 WMA_LOGD("Host woken up because of sta_kickout event");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002807 if (param_buf->wow_packet_buffer) {
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07002808 WMA_LOGD("wow_packet_buffer dump");
2809 qdf_trace_hex_dump(QDF_MODULE_ID_WMA,
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302810 QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002811 param_buf->wow_packet_buffer, wow_buf_pkt_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002812 wma_peer_sta_kickout_event_handler(handle,
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07002813 wmi_cmd_struct_ptr, wow_buf_pkt_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002814 } else {
2815 WMA_LOGD("No wow_packet_buffer present");
2816 }
2817 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002818#ifdef FEATURE_WLAN_EXTSCAN
2819 case WOW_REASON_EXTSCAN:
2820 WMA_LOGD("Host woken up because of extscan reason");
2821 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_EXTSCAN);
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07002822 if (param_buf->wow_packet_buffer)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002823 wma_extscan_wow_event_callback(handle,
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07002824 wmi_cmd_struct_ptr, wow_buf_pkt_len);
2825 else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002826 WMA_LOGE("wow_packet_buffer is empty");
2827 break;
2828#endif
2829 case WOW_REASON_RSSI_BREACH_EVENT:
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07002830 wma_wow_wake_up_stats(wma, NULL, 0,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002831 WOW_REASON_RSSI_BREACH_EVENT);
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07002832 WMA_LOGD("Host woken up because of rssi breach reason");
2833 /* rssi breach event is embedded in wow_packet_buffer */
2834 if (param_buf->wow_packet_buffer)
2835 wma_rssi_breached_event_handler(handle,
2836 wmi_cmd_struct_ptr, wow_buf_pkt_len);
2837 else
2838 WMA_LOGD("No wow_packet_buffer present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002839 break;
Naveen Rawatc9f09522016-05-12 14:02:42 -07002840 case WOW_REASON_NAN_EVENT:
2841 WMA_LOGA("Host woken up due to NAN event reason");
2842 wma_nan_rsp_event_handler(handle,
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07002843 wmi_cmd_struct_ptr, wow_buf_pkt_len);
Naveen Rawatc9f09522016-05-12 14:02:42 -07002844 break;
Naveen Rawate82c1f32016-06-22 15:34:36 -07002845 case WOW_REASON_NAN_DATA:
2846 WMA_LOGD(FL("Host woken up for NAN data path event from FW"));
2847 if (param_buf->wow_packet_buffer) {
2848 wow_buf_pkt_len =
2849 *(uint32_t *)param_buf->wow_packet_buffer;
2850 WMA_LOGD(FL("wow_packet_buffer dump"));
2851 qdf_trace_hex_dump(QDF_MODULE_ID_WMA,
2852 QDF_TRACE_LEVEL_DEBUG,
2853 param_buf->wow_packet_buffer,
2854 wow_buf_pkt_len);
2855 wma_ndp_wow_event_callback(handle,
2856 (param_buf->wow_packet_buffer + 4),
2857 wow_buf_pkt_len);
2858 } else {
2859 WMA_LOGE(FL("wow_packet_buffer is empty"));
2860 }
2861 break;
Selvaraj, Sridhar172cabc2016-07-05 15:19:24 +05302862 case WOW_REASON_OEM_RESPONSE_EVENT:
2863 wma_wow_wake_up_stats(wma, NULL, 0,
2864 WOW_REASON_OEM_RESPONSE_EVENT);
2865 /*
2866 * Actual OEM Response event will follow after this
2867 * WOW Wakeup event
2868 */
2869 WMA_LOGD(FL("Host woken up for OEM Response event"));
2870 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002871 default:
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07002872 WMA_LOGE(FL("WOW reason %s(%d)- not handled"),
2873 wma_wow_wake_reason_str(wake_info->wake_reason),
2874 wake_info->wake_reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002875 break;
2876 }
2877
2878 if (wake_lock_duration) {
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302879 qdf_wake_lock_timeout_acquire(&wma->wow_wake_lock,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002880 wake_lock_duration,
2881 WIFI_POWER_EVENT_WAKELOCK_WOW);
2882 WMA_LOGA("Holding %d msec wake_lock", wake_lock_duration);
2883 }
2884
Krishna Kumaar Natarajan36e5aa02016-07-02 17:44:25 -07002885 wmitlv_free_allocated_event_tlvs(event_id, &wmi_cmd_struct_ptr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002886 return 0;
2887}
2888
2889/**
2890 * wma_pdev_resume_event_handler() - PDEV resume event handler
2891 * @handle: wma handle
2892 * @event: event data
2893 * @len: buffer length
2894 *
2895 * Return: 0 for success or error
2896 */
2897int wma_pdev_resume_event_handler(void *handle, uint8_t *event, uint32_t len)
2898{
2899 tp_wma_handle wma = (tp_wma_handle) handle;
2900
2901 WMA_LOGA("Received PDEV resume event");
2902
Anurag Chouhance0dc992016-02-16 18:18:03 +05302903 qdf_event_set(&wma->wma_resume_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002904
2905 return 0;
2906}
2907/**
2908 * wma_set_wow_bus_suspend() - set suspend flag
2909 * @wma: wma handle
2910 * @val: value
2911 *
2912 * Return: none
2913 */
2914static inline void wma_set_wow_bus_suspend(tp_wma_handle wma, int val)
2915{
2916
Anurag Chouhan8e0ccd32016-02-19 15:30:20 +05302917 qdf_atomic_set(&wma->is_wow_bus_suspended, val);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002918}
2919
2920
2921
2922/**
2923 * wma_add_wow_wakeup_event() - Configures wow wakeup events.
2924 * @wma: wma handle
2925 * @vdev_id: vdev id
2926 * @bitmap: Event bitmap
2927 * @enable: enable/disable
2928 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302929 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002930 */
Naveen Rawate82c1f32016-06-22 15:34:36 -07002931QDF_STATUS wma_add_wow_wakeup_event(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002932 uint32_t vdev_id,
2933 uint32_t bitmap,
2934 bool enable)
2935{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002936 int ret;
2937
Govind Singhaa64c242016-03-08 11:31:49 +05302938 ret = wmi_unified_add_wow_wakeup_event_cmd(wma->wmi_handle, vdev_id,
Rajeev Kumar4002e5b2016-06-22 12:01:15 -07002939 bitmap, enable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002940 if (ret) {
2941 WMA_LOGE("Failed to config wow wakeup event");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302942 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002943 }
2944
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302945 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002946}
2947
2948/**
2949 * wma_send_wow_patterns_to_fw() - Sends WOW patterns to FW.
2950 * @wma: wma handle
2951 * @vdev_id: vdev id
2952 * @ptrn_id: pattern id
2953 * @ptrn: pattern
2954 * @ptrn_len: pattern length
2955 * @ptrn_offset: pattern offset
2956 * @mask: mask
2957 * @mask_len: mask length
2958 * @user: true for user configured pattern and false for default pattern
2959 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302960 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002961 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302962static QDF_STATUS wma_send_wow_patterns_to_fw(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002963 uint8_t vdev_id, uint8_t ptrn_id,
2964 const uint8_t *ptrn, uint8_t ptrn_len,
2965 uint8_t ptrn_offset, const uint8_t *mask,
2966 uint8_t mask_len, bool user)
2967{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002968 struct wma_txrx_node *iface;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002969 int ret;
Govind Singhaa64c242016-03-08 11:31:49 +05302970 uint8_t default_patterns;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002971
2972 iface = &wma->interfaces[vdev_id];
Govind Singhaa64c242016-03-08 11:31:49 +05302973 default_patterns = iface->num_wow_default_patterns++;
2974 ret = wmi_unified_wow_patterns_to_fw_cmd(wma->wmi_handle,
2975 vdev_id, ptrn_id, ptrn,
2976 ptrn_len, ptrn_offset, mask,
2977 mask_len, user, default_patterns);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002978 if (ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002979 if (!user)
2980 iface->num_wow_default_patterns--;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302981 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002982 }
2983
2984 if (user)
2985 iface->num_wow_user_patterns++;
2986
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302987 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002988}
2989
2990/**
2991 * wma_wow_ap() - set WOW patterns in ap mode
2992 * @wma: wma handle
2993 * @vdev_id: vdev id
2994 *
2995 * Configures default WOW pattern for the given vdev_id which is in AP mode.
2996 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302997 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002998 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302999static QDF_STATUS wma_wow_ap(tp_wma_handle wma, uint8_t vdev_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003000{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303001 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003002 uint8_t arp_offset = 20;
3003 uint8_t mac_mask[IEEE80211_ADDR_LEN];
3004
3005 /* Setup unicast pkt pattern */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303006 qdf_mem_set(&mac_mask, IEEE80211_ADDR_LEN, 0xFF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003007 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
3008 wma->interfaces[vdev_id].addr,
3009 IEEE80211_ADDR_LEN, 0, mac_mask,
3010 IEEE80211_ADDR_LEN, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303011 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003012 WMA_LOGE("Failed to add WOW unicast pattern ret %d", ret);
3013 return ret;
3014 }
3015
3016 /*
3017 * Setup all ARP pkt pattern. This is dummy pattern hence the length
3018 * is zero
3019 */
3020 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
3021 arp_ptrn, 0, arp_offset, arp_mask, 0, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303022 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003023 WMA_LOGE("Failed to add WOW ARP pattern ret %d", ret);
3024 return ret;
3025 }
3026
3027 return ret;
3028}
3029
3030/**
Komal Seelam9764a842016-05-24 11:07:23 +05303031 * wma_configure_wow_ssdp() - API to configure WoW SSDP
3032 * @wma: WMA Handle
3033 * @vdev_id: Vdev Id
3034 *
3035 * API to configure SSDP pattern as WoW pattern
3036 *
3037 * Return: Success/Failure
3038 */
3039static QDF_STATUS wma_configure_wow_ssdp(tp_wma_handle wma, uint8_t vdev_id)
3040{
3041 QDF_STATUS status = QDF_STATUS_SUCCESS;
3042 uint8_t discvr_offset = 30;
3043
3044 status = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
3045 discvr_ptrn, sizeof(discvr_ptrn), discvr_offset,
3046 discvr_mask, sizeof(discvr_ptrn), false);
3047
3048 if (status != QDF_STATUS_SUCCESS)
3049 WMA_LOGE("Failed to add WOW mDNS/SSDP/LLMNR pattern");
3050
3051 return status;
3052}
3053
3054/**
3055 * wma_configure_mc_ssdp() - API to configure SSDP address as MC list
3056 * @wma: WMA Handle
3057 * @vdev_id: Vdev Id
3058 *
3059 * SSDP address 239.255.255.250 is converted to Multicast Mac address
3060 * and configure it to FW. Firmware will apply this pattern on the incoming
3061 * packets to filter them out during chatter/wow mode.
3062 *
3063 * Return: Success/Failure
3064 */
3065static QDF_STATUS wma_configure_mc_ssdp(tp_wma_handle wma, uint8_t vdev_id)
3066{
3067 WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param *cmd;
3068 wmi_buf_t buf;
3069 const tSirMacAddr ssdp_addr = {0x01, 0x00, 0x5e, 0x7f, 0xff, 0xfa};
3070 int ret;
3071 WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param fixed_param;
3072 uint32_t tag =
3073 WMITLV_TAG_STRUC_WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param;
3074
3075 buf = wmi_buf_alloc(wma->wmi_handle, sizeof(*cmd));
3076 if (!buf) {
3077 WMA_LOGE("%s No Memory for MC address", __func__);
3078 return QDF_STATUS_E_NOMEM;
3079 }
3080
3081 cmd = (WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param *) wmi_buf_data(buf);
3082
3083 WMITLV_SET_HDR(&cmd->tlv_header, tag,
3084 WMITLV_GET_STRUCT_TLVLEN(fixed_param));
3085
3086 cmd->action = WMI_MCAST_FILTER_SET;
3087 cmd->vdev_id = vdev_id;
3088 WMI_CHAR_ARRAY_TO_MAC_ADDR(ssdp_addr, &cmd->mcastbdcastaddr);
3089 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, sizeof(*cmd),
3090 WMI_SET_MCASTBCAST_FILTER_CMDID);
3091 if (ret != QDF_STATUS_SUCCESS) {
3092 WMA_LOGE("%s Failed to configure FW with SSDP MC address",
3093 __func__);
3094 wmi_buf_free(buf);
3095 return QDF_STATUS_E_FAILURE;
3096 }
3097
3098 return QDF_STATUS_SUCCESS;
3099}
3100
3101/**
3102 * wma_configure_ssdp() - API to Configure SSDP pattern to FW
3103 * @wma: WMA Handle
3104 * @vdev_id: VDEV ID
3105 *
3106 * Setup multicast pattern for mDNS 224.0.0.251, SSDP 239.255.255.250 and LLMNR
3107 * 224.0.0.252
3108 *
3109 * Return: Success/Failure.
3110 */
3111static QDF_STATUS wma_configure_ssdp(tp_wma_handle wma, uint8_t vdev_id)
3112{
3113 if (!wma->ssdp) {
3114 WMA_LOGD("mDNS, SSDP, LLMNR patterns are disabled from ini");
3115 return QDF_STATUS_SUCCESS;
3116 }
3117
3118 WMA_LOGD("%s, enable_mc_list:%d", __func__, wma->enable_mc_list);
3119
3120 if (wma->enable_mc_list)
3121 return wma_configure_mc_ssdp(wma, vdev_id);
3122
3123 return wma_configure_wow_ssdp(wma, vdev_id);
3124}
3125
3126/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003127 * wma_wow_sta() - set WOW patterns in sta mode
3128 * @wma: wma handle
3129 * @vdev_id: vdev id
3130 *
3131 * Configures default WOW pattern for the given vdev_id which is in sta mode.
3132 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303133 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003134 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303135static QDF_STATUS wma_wow_sta(tp_wma_handle wma, uint8_t vdev_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003136{
3137 uint8_t arp_offset = 12;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003138 uint8_t mac_mask[IEEE80211_ADDR_LEN];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303139 QDF_STATUS ret = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003140
3141 /* Setup unicast pkt pattern */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303142 qdf_mem_set(&mac_mask, IEEE80211_ADDR_LEN, 0xFF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003143 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
3144 wma->interfaces[vdev_id].addr,
3145 IEEE80211_ADDR_LEN, 0, mac_mask,
3146 IEEE80211_ADDR_LEN, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303147 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003148 WMA_LOGE("Failed to add WOW unicast pattern ret %d", ret);
3149 return ret;
3150 }
3151
Komal Seelam9764a842016-05-24 11:07:23 +05303152 ret = wma_configure_ssdp(wma, vdev_id);
3153 if (ret != QDF_STATUS_SUCCESS)
3154 WMA_LOGE("Failed to configure SSDP patterns to FW");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003155
3156 /* when arp offload or ns offloaded is disabled
3157 * from ini file, configure broad cast arp pattern
3158 * to fw, so that host can wake up
3159 */
3160 if (!(wma->ol_ini_info & 0x1)) {
3161 /* Setup all ARP pkt pattern */
3162 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
3163 arp_ptrn, sizeof(arp_ptrn), arp_offset,
3164 arp_mask, sizeof(arp_mask), false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303165 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003166 WMA_LOGE("Failed to add WOW ARP pattern");
3167 return ret;
3168 }
3169 }
3170
3171 /* for NS or NDP offload packets */
3172 if (!(wma->ol_ini_info & 0x2)) {
3173 /* Setup all NS pkt pattern */
3174 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
3175 ns_ptrn, sizeof(arp_ptrn), arp_offset,
3176 arp_mask, sizeof(arp_mask), false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303177 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003178 WMA_LOGE("Failed to add WOW NS pattern");
3179 return ret;
3180 }
3181 }
3182
3183 return ret;
3184}
3185
3186/**
3187 * wma_register_wow_default_patterns() - register default wow patterns with fw
3188 * @handle: Pointer to wma handle
3189 * @vdev_id: vdev id
3190 *
3191 * WoW default wake up pattern rule is:
3192 * - For STA & P2P CLI mode register for same STA specific wow patterns
3193 * - For SAP/P2P GO & IBSS mode register for same SAP specific wow patterns
3194 *
3195 * Return: none
3196 */
3197void wma_register_wow_default_patterns(WMA_HANDLE handle, uint8_t vdev_id)
3198{
3199 tp_wma_handle wma = handle;
3200 struct wma_txrx_node *iface;
3201
3202 if (vdev_id > wma->max_bssid) {
3203 WMA_LOGE("Invalid vdev id %d", vdev_id);
3204 return;
3205 }
3206 iface = &wma->interfaces[vdev_id];
3207
3208 if (iface->ptrn_match_enable) {
Houston Hoffman79b4af22015-10-06 12:01:08 -07003209 if (wma_is_vdev_in_beaconning_mode(wma, vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003210 /* Configure SAP/GO/IBSS mode default wow patterns */
3211 WMA_LOGI("Config SAP specific default wow patterns vdev_id %d",
3212 vdev_id);
3213 wma_wow_ap(wma, vdev_id);
3214 } else {
3215 /* Configure STA/P2P CLI mode default wow patterns */
3216 WMA_LOGI("Config STA specific default wow patterns vdev_id %d",
3217 vdev_id);
3218 wma_wow_sta(wma, vdev_id);
3219 if (wma->IsRArateLimitEnabled) {
3220 WMA_LOGI("Config STA RA limit wow patterns vdev_id %d",
3221 vdev_id);
3222 wma_wow_sta_ra_filter(wma, vdev_id);
3223 }
3224 }
3225 }
3226
3227 return;
3228}
3229
3230/**
3231 * wma_register_wow_wakeup_events() - register vdev specific wake events with fw
3232 * @handle: Pointer to wma handle
3233 * @vdev_id: vdev Id
3234 * @vdev_type: vdev type
3235 * @vdev_subtype: vdev sub type
3236 *
3237 * WoW wake up event rule is following:
3238 * 1) STA mode and P2P CLI mode wake up events are same
3239 * 2) SAP mode and P2P GO mode wake up events are same
3240 * 3) IBSS mode wake events are same as STA mode plus WOW_BEACON_EVENT
3241 *
3242 * Return: none
3243 */
3244void wma_register_wow_wakeup_events(WMA_HANDLE handle,
3245 uint8_t vdev_id,
3246 uint8_t vdev_type,
3247 uint8_t vdev_subtype)
3248{
3249 tp_wma_handle wma = handle;
3250 uint32_t event_bitmap;
3251
3252 WMA_LOGI("vdev_type %d vdev_subtype %d vdev_id %d", vdev_type,
3253 vdev_subtype, vdev_id);
3254
3255 if ((WMI_VDEV_TYPE_STA == vdev_type) ||
3256 ((WMI_VDEV_TYPE_AP == vdev_type) &&
3257 (WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE == vdev_subtype))) {
3258 /* Configure STA/P2P CLI mode specific default wake up events */
3259 event_bitmap = WMA_WOW_STA_WAKE_UP_EVENTS;
3260 WMA_LOGI("STA specific default wake up event 0x%x vdev id %d",
3261 event_bitmap, vdev_id);
3262 } else if (WMI_VDEV_TYPE_IBSS == vdev_type) {
3263 /* Configure IBSS mode specific default wake up events */
3264 event_bitmap = (WMA_WOW_STA_WAKE_UP_EVENTS |
3265 (1 << WOW_BEACON_EVENT));
3266 WMA_LOGI("IBSS specific default wake up event 0x%x vdev id %d",
3267 event_bitmap, vdev_id);
3268 } else if (WMI_VDEV_TYPE_AP == vdev_type) {
3269 /* Configure SAP/GO mode specific default wake up events */
3270 event_bitmap = WMA_WOW_SAP_WAKE_UP_EVENTS;
3271 WMA_LOGI("SAP specific default wake up event 0x%x vdev id %d",
3272 event_bitmap, vdev_id);
Naveen Rawate82c1f32016-06-22 15:34:36 -07003273 } else if (WMI_VDEV_TYPE_NDI == vdev_type) {
3274 /*
3275 * Configure NAN data path specific default wake up events.
3276 * Following routine sends the command to firmware.
3277 */
3278 wma_ndp_add_wow_wakeup_event(wma, vdev_id);
3279 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003280 } else {
3281 WMA_LOGE("unknown type %d subtype %d", vdev_type, vdev_subtype);
3282 return;
3283 }
3284
3285 wma_add_wow_wakeup_event(wma, vdev_id, event_bitmap, true);
3286
3287 return;
3288}
3289
3290/**
3291 * wma_enable_disable_wakeup_event() - Configures wow wakeup events
3292 * @wma: wma handle
3293 * @vdev_id: vdev id
3294 * @bitmap: Event bitmap
3295 * @enable: enable/disable
3296 *
3297 * Return: none
3298 */
3299void wma_enable_disable_wakeup_event(WMA_HANDLE handle,
3300 uint32_t vdev_id,
3301 uint32_t bitmap,
3302 bool enable)
3303{
3304 tp_wma_handle wma = handle;
3305
3306 WMA_LOGI("vdev_id %d wake up event 0x%x enable %d",
3307 vdev_id, bitmap, enable);
3308 wma_add_wow_wakeup_event(wma, vdev_id, bitmap, enable);
3309}
3310
3311/**
3312 * wma_enable_wow_in_fw() - wnable wow in fw
3313 * @wma: wma handle
3314 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303315 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003316 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303317QDF_STATUS wma_enable_wow_in_fw(WMA_HANDLE handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003318{
3319 tp_wma_handle wma = handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003320 int ret;
Komal Seelam3d202862016-02-24 18:43:24 +05303321 struct hif_opaque_softc *scn;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003322 int host_credits;
3323 int wmi_pending_cmds;
Govind Singhd76a5b02016-03-08 15:12:14 +05303324 struct wow_cmd_params param = {0};
3325
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003326#ifdef CONFIG_CNSS
Anurag Chouhan6d760662016-02-20 16:05:43 +05303327 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003328
3329 if (NULL == pMac) {
3330 WMA_LOGE("%s: Unable to get PE context", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303331 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003332 }
3333#endif /* CONFIG_CNSS */
3334
Anurag Chouhance0dc992016-02-16 18:18:03 +05303335 qdf_event_reset(&wma->target_suspend);
Houston Hoffmana769ed32016-04-14 17:02:51 -07003336 wma->wow_nack = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003337
3338 host_credits = wmi_get_host_credits(wma->wmi_handle);
3339 wmi_pending_cmds = wmi_get_pending_cmds(wma->wmi_handle);
3340
3341 WMA_LOGD("Credits:%d; Pending_Cmds: %d",
3342 host_credits, wmi_pending_cmds);
3343
3344 if (host_credits < WMI_WOW_REQUIRED_CREDITS) {
3345 WMA_LOGE("%s: Host Doesn't have enough credits to Post WMI_WOW_ENABLE_CMDID! "
3346 "Credits:%d, pending_cmds:%d\n", __func__, host_credits,
3347 wmi_pending_cmds);
3348#ifndef QCA_WIFI_3_0_EMU
3349 goto error;
3350#endif
3351 }
3352
Govind Singhd76a5b02016-03-08 15:12:14 +05303353 param.enable = true;
Houston Hoffman77f0e342016-07-25 13:28:10 -07003354 param.can_suspend_link = htc_can_suspend_link(wma->htc_handle);
Govind Singhd76a5b02016-03-08 15:12:14 +05303355 ret = wmi_unified_wow_enable_send(wma->wmi_handle, &param,
3356 WMA_WILDCARD_PDEV_ID);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003357 if (ret) {
3358 WMA_LOGE("Failed to enable wow in fw");
3359 goto error;
3360 }
3361
3362 wmi_set_target_suspend(wma->wmi_handle, true);
3363
Anurag Chouhance0dc992016-02-16 18:18:03 +05303364 if (qdf_wait_single_event(&wma->target_suspend,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003365 WMA_TGT_SUSPEND_COMPLETE_TIMEOUT)
Anurag Chouhance0dc992016-02-16 18:18:03 +05303366 != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003367 WMA_LOGE("Failed to receive WoW Enable Ack from FW");
3368 WMA_LOGE("Credits:%d; Pending_Cmds: %d",
3369 wmi_get_host_credits(wma->wmi_handle),
3370 wmi_get_pending_cmds(wma->wmi_handle));
Prashanth Bhatta9e143052015-12-04 11:56:47 -08003371 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003372#ifdef CONFIG_CNSS
Yue Ma455aff62015-10-20 18:29:16 -07003373 if (pMac->sme.enableSelfRecovery) {
3374 cds_trigger_recovery();
3375 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303376 QDF_BUG(0);
Yue Ma455aff62015-10-20 18:29:16 -07003377 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003378#else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303379 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003380#endif /* CONFIG_CNSS */
Yue Ma455aff62015-10-20 18:29:16 -07003381 } else {
3382 WMA_LOGE("%s: LOGP is in progress, ignore!", __func__);
3383 }
3384
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003385 wmi_set_target_suspend(wma->wmi_handle, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303386 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003387 }
3388
3389 if (wma->wow_nack) {
3390 WMA_LOGE("FW not ready to WOW");
3391 wmi_set_target_suspend(wma->wmi_handle, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303392 return QDF_STATUS_E_AGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003393 }
3394
3395 host_credits = wmi_get_host_credits(wma->wmi_handle);
3396 wmi_pending_cmds = wmi_get_pending_cmds(wma->wmi_handle);
3397
3398 if (host_credits < WMI_WOW_REQUIRED_CREDITS) {
3399 WMA_LOGE("%s: No Credits after HTC ACK:%d, pending_cmds:%d, "
3400 "cannot resume back", __func__, host_credits,
3401 wmi_pending_cmds);
3402 htc_dump_counter_info(wma->htc_handle);
Prashanth Bhatta9e143052015-12-04 11:56:47 -08003403 if (!cds_is_driver_recovering())
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303404 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003405 else
3406 WMA_LOGE("%s: SSR in progress, ignore no credit issue",
3407 __func__);
3408 }
3409
3410 WMA_LOGD("WOW enabled successfully in fw: credits:%d"
3411 "pending_cmds: %d", host_credits, wmi_pending_cmds);
3412
Anurag Chouhan6d760662016-02-20 16:05:43 +05303413 scn = cds_get_context(QDF_MODULE_ID_HIF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003414
3415 if (scn == NULL) {
3416 WMA_LOGE("%s: Failed to get HIF context", __func__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303417 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303418 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003419 }
3420
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003421 wma->wow.wow_enable_cmd_sent = true;
3422
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303423 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003424
3425error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303426 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003427}
3428
3429/**
3430 * wma_resume_req() - clear configured wow patterns in fw
3431 * @wma: wma handle
Houston Hoffmana76591b2015-11-10 16:52:05 -08003432 * @type: type of suspend
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003433 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303434 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003435 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05303436QDF_STATUS wma_resume_req(tp_wma_handle wma, enum qdf_suspend_type type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003437{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303438 if (type == QDF_SYSTEM_SUSPEND) {
Houston Hoffmana76591b2015-11-10 16:52:05 -08003439 wma->no_of_resume_ind++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003440
Houston Hoffmana76591b2015-11-10 16:52:05 -08003441 if (wma->no_of_resume_ind < wma_get_vdev_count(wma))
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303442 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003443
Houston Hoffmana76591b2015-11-10 16:52:05 -08003444 wma->no_of_resume_ind = 0;
3445 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003446
3447 /* Reset the DTIM Parameters */
3448 wma_set_resume_dtim(wma);
3449 /* need to reset if hif_pci_suspend_fails */
3450 wma_set_wow_bus_suspend(wma, 0);
3451 /* unpause the vdev if left paused and hif_pci_suspend fails */
3452 wma_unpause_vdev(wma);
3453
Houston Hoffman1460fa32015-11-18 02:36:30 -08003454 wmi_set_runtime_pm_inprogress(wma->wmi_handle, false);
3455
Houston Hoffmanc45db892015-11-13 19:59:25 -08003456 if (type == QDF_RUNTIME_SUSPEND)
3457 qdf_runtime_pm_allow_suspend(wma->wma_runtime_resume_lock);
3458
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303459 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003460}
3461
3462/**
3463 * wma_wow_delete_pattern() - delete wow pattern in target
3464 * @wma: wma handle
3465 * @ptrn_id: pattern id
3466 * @vdev_id: vdev id
3467 * @user: true for user pattern and false for default pattern
3468 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303469 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003470 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303471static QDF_STATUS wma_wow_delete_pattern(tp_wma_handle wma, uint8_t ptrn_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003472 uint8_t vdev_id, bool user)
3473{
Govind Singhaa64c242016-03-08 11:31:49 +05303474
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003475 struct wma_txrx_node *iface;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003476 int ret;
3477
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003478 iface = &wma->interfaces[vdev_id];
Govind Singhaa64c242016-03-08 11:31:49 +05303479 ret = wmi_unified_wow_delete_pattern_cmd(wma->wmi_handle, ptrn_id,
3480 vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003481 if (ret) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303482 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003483 }
3484
3485 if (user)
3486 iface->num_wow_user_patterns--;
3487
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303488 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003489}
3490
3491/**
3492 * wma_wow_add_pattern() - add wow pattern in target
3493 * @wma: wma handle
3494 * @ptrn: wow pattern
3495 *
3496 * This function does following:
3497 * 1) Delete all default patterns of the vdev
3498 * 2) Add received wow patterns for given vdev in target.
3499 *
3500 * Target is responsible for caching wow patterns accross multiple
3501 * suspend/resumes until the pattern is deleted by user
3502 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303503 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003504 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303505QDF_STATUS wma_wow_add_pattern(tp_wma_handle wma, struct wow_add_pattern *ptrn)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003506{
3507 uint8_t id;
3508 uint8_t bit_to_check, pos;
3509 struct wma_txrx_node *iface;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303510 QDF_STATUS ret = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003511 uint8_t new_mask[SIR_WOWL_BCAST_PATTERN_MAX_SIZE];
3512
3513 if (ptrn->session_id > wma->max_bssid) {
3514 WMA_LOGE("Invalid vdev id (%d)", ptrn->session_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303515 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003516 }
3517
3518 iface = &wma->interfaces[ptrn->session_id];
3519
3520 /* clear all default patterns cofigured by wma */
3521 for (id = 0; id < iface->num_wow_default_patterns; id++)
3522 wma_wow_delete_pattern(wma, id, ptrn->session_id, false);
3523
3524 iface->num_wow_default_patterns = 0;
3525
3526 WMA_LOGI("Add user passed wow pattern id %d vdev id %d",
3527 ptrn->pattern_id, ptrn->session_id);
3528 /*
3529 * Convert received pattern mask value from bit representation
3530 * to byte representation.
3531 *
3532 * For example, received value from umac,
3533 *
3534 * Mask value : A1 (equivalent binary is "1010 0001")
3535 * Pattern value : 12:00:13:00:00:00:00:44
3536 *
3537 * The value which goes to FW after the conversion from this
3538 * function (1 in mask value will become FF and 0 will
3539 * become 00),
3540 *
3541 * Mask value : FF:00:FF:00:0:00:00:FF
3542 * Pattern value : 12:00:13:00:00:00:00:44
3543 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303544 qdf_mem_zero(new_mask, sizeof(new_mask));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003545 for (pos = 0; pos < ptrn->pattern_size; pos++) {
3546 bit_to_check = (WMA_NUM_BITS_IN_BYTE - 1) -
3547 (pos % WMA_NUM_BITS_IN_BYTE);
3548 bit_to_check = 0x1 << bit_to_check;
3549 if (ptrn->pattern_mask[pos / WMA_NUM_BITS_IN_BYTE] &
3550 bit_to_check)
3551 new_mask[pos] = WMA_WOW_PTRN_MASK_VALID;
3552 }
3553
3554 ret = wma_send_wow_patterns_to_fw(wma, ptrn->session_id,
3555 ptrn->pattern_id,
3556 ptrn->pattern, ptrn->pattern_size,
3557 ptrn->pattern_byte_offset, new_mask,
3558 ptrn->pattern_size, true);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303559 if (ret != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003560 WMA_LOGE("Failed to add wow pattern %d", ptrn->pattern_id);
3561
3562 return ret;
3563}
3564
3565/**
3566 * wma_wow_delete_user_pattern() - delete user configured wow pattern in target
3567 * @wma: wma handle
3568 * @ptrn: wow pattern
3569 *
3570 * This function does following:
3571 * 1) Deletes a particular user configured wow pattern in target
3572 * 2) After deleting all user wow patterns add default wow patterns
3573 * specific to that vdev.
3574 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303575 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003576 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303577QDF_STATUS wma_wow_delete_user_pattern(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003578 struct wow_delete_pattern *pattern)
3579{
3580 struct wma_txrx_node *iface;
3581
3582 if (pattern->session_id > wma->max_bssid) {
3583 WMA_LOGE("Invalid vdev id %d", pattern->session_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303584 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003585 }
3586
3587 iface = &wma->interfaces[pattern->session_id];
3588 if (iface->num_wow_user_patterns <= 0) {
3589 WMA_LOGE("No valid user pattern. Num user pattern %u vdev %d",
3590 iface->num_wow_user_patterns, pattern->session_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303591 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003592 }
3593
3594 WMA_LOGI("Delete user passed wow pattern id %d total user pattern %d",
3595 pattern->pattern_id, iface->num_wow_user_patterns);
3596
3597 wma_wow_delete_pattern(wma, pattern->pattern_id,
3598 pattern->session_id, true);
3599
3600 /* configure default patterns once all user patterns are deleted */
3601 if (!iface->num_wow_user_patterns)
3602 wma_register_wow_default_patterns(wma, pattern->session_id);
3603
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303604 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003605}
3606
3607/**
3608 * wma_wow_enter() - store enable/disable status for pattern
3609 * @wma: wma handle
3610 * @info: wow parameters
3611 *
3612 * Records pattern enable/disable status locally. This choice will
3613 * take effect when the driver enter into suspend state.
3614 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303615 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003616 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303617QDF_STATUS wma_wow_enter(tp_wma_handle wma, tpSirHalWowlEnterParams info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003618{
3619 struct wma_txrx_node *iface;
3620
3621 WMA_LOGD("wow enable req received for vdev id: %d", info->sessionId);
3622
3623 if (info->sessionId > wma->max_bssid) {
3624 WMA_LOGE("Invalid vdev id (%d)", info->sessionId);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303625 qdf_mem_free(info);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303626 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003627 }
3628
3629 iface = &wma->interfaces[info->sessionId];
3630 iface->ptrn_match_enable = info->ucPatternFilteringEnable ?
3631 true : false;
3632 wma->wow.magic_ptrn_enable = info->ucMagicPktEnable ? true : false;
3633 wma->wow.deauth_enable = info->ucWowDeauthRcv ? true : false;
3634 wma->wow.disassoc_enable = info->ucWowDeauthRcv ? true : false;
3635 wma->wow.bmiss_enable = info->ucWowMaxMissedBeacons ? true : false;
3636
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303637 qdf_mem_free(info);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003638
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303639 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003640}
3641
3642/**
3643 * wma_wow_exit() - clear all wma states
3644 * @wma: wma handle
3645 * @info: wow params
3646 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303647 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003648 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303649QDF_STATUS wma_wow_exit(tp_wma_handle wma, tpSirHalWowlExitParams info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003650{
3651 struct wma_txrx_node *iface;
3652
3653 WMA_LOGD("wow disable req received for vdev id: %d", info->sessionId);
3654
3655 if (info->sessionId > wma->max_bssid) {
3656 WMA_LOGE("Invalid vdev id (%d)", info->sessionId);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303657 qdf_mem_free(info);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303658 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003659 }
3660
3661 iface = &wma->interfaces[info->sessionId];
3662 iface->ptrn_match_enable = false;
3663 wma->wow.magic_ptrn_enable = false;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303664 qdf_mem_free(info);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003665
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303666 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003667}
3668
3669/**
Houston Hoffmana76591b2015-11-10 16:52:05 -08003670 * wma_calculate_and_update_conn_state(): calculate each interfaces conn state
3671 * @wma: validated wma handle
3672 *
3673 * Identifies any vdev that is up and not in ap mode as connected.
3674 * stores this in the interfaces conn_state varible.
3675 */
3676void wma_calculate_and_update_conn_state(tp_wma_handle wma)
3677{
3678 int i;
3679 for (i = 0; i < wma->max_bssid; i++) {
3680 wma->interfaces[i].conn_state =
3681 !!(wma->interfaces[i].vdev_up &&
3682 !wma_is_vdev_in_ap_mode(wma, i));
3683 }
3684}
3685
3686/**
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003687 * wma_update_conn_state(): synchronize wma & hdd
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003688 * @wma: wma handle
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003689 * @conn_state: boolean array to populate
3690 * @len: validation parameter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003691 *
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003692 * populate interfaces conn_state with true if the interface
3693 * is a connected client and wow will configure a pattern.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003694 */
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003695void wma_update_conn_state(tp_wma_handle wma, uint32_t conn_mask)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003696{
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003697 int i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003698 for (i = 0; i < wma->max_bssid; i++) {
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003699 if (conn_mask & (1 << i))
3700 wma->interfaces[i].conn_state = true;
3701 else
3702 wma->interfaces[i].conn_state = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003703 }
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003704
3705 if (wma->wow.magic_ptrn_enable)
3706 return;
3707
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003708 for (i = 0; i < wma->max_bssid; i++) {
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003709 if (!wma->interfaces[i].ptrn_match_enable)
3710 wma->interfaces[i].conn_state = false;
3711 }
3712}
3713
3714/**
3715 * wma_is_beaconning_vdev_up(): check if a beaconning vdev is up
3716 * @wma: wma handle
3717 *
3718 * Return TRUE if beaconning vdev is up
3719 */
3720static inline
3721bool wma_is_beaconning_vdev_up(tp_wma_handle wma)
3722{
3723 int i;
3724 for (i = 0; i < wma->max_bssid; i++) {
3725 if (wma_is_vdev_in_beaconning_mode(wma, i)
3726 && wma->interfaces[i].vdev_up)
3727 return true;
3728 }
3729 return false;
3730}
3731
3732/**
3733 * wma_support_wow_for_beaconing: wow query for beaconning
3734 * @wma: wma handle
3735 *
3736 * Need to configure wow to enable beaconning offload when
3737 * a beaconing vdev is up and beaonning offload is configured.
3738 *
3739 * Return: true if we need to enable wow for beaconning offload
3740 */
3741static inline
3742bool wma_support_wow_for_beaconing(tp_wma_handle wma)
3743{
3744 if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
3745 WMI_SERVICE_BEACON_OFFLOAD)) {
3746 if (wma_is_beaconning_vdev_up(wma))
3747 return true;
3748 }
3749 return false;
3750}
3751
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003752#ifdef FEATURE_WLAN_SCAN_PNO
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003753/**
3754 * wma_is_pnoscan_in_progress(): check if a pnoscan is in progress
3755 * @wma: wma handle
3756 * @vdev_id: vdev_id
3757 *
3758 * Return: TRUE/FALSE
3759 */
3760static inline
3761bool wma_is_pnoscan_in_progress(tp_wma_handle wma, int vdev_id)
3762{
3763 return wma->interfaces[vdev_id].pno_in_progress;
3764}
Houston Hoffman345fa402015-12-16 11:28:51 -08003765
3766/**
3767 * wma_is_pnoscan_match_found(): check if a scan match was found
3768 * @wma: wma handle
3769 * @vdev_id: vdev_id
3770 *
3771 * Return: TRUE/FALSE
3772 */
3773static inline
3774bool wma_is_pnoscan_match_found(tp_wma_handle wma, int vdev_id)
3775{
3776 return wma->interfaces[vdev_id].nlo_match_evt_received;
3777}
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003778#else
3779/**
3780 * wma_is_pnoscan_in_progress(): dummy
3781 *
Houston Hoffman345fa402015-12-16 11:28:51 -08003782 * Return: False since no pnoscan cannot be in progress
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003783 * when feature flag is not defined.
3784 */
3785bool wma_is_pnoscan_in_progress(tp_wma_handle wma, int vdev_id)
3786{
3787 return FALSE;
3788}
Houston Hoffman345fa402015-12-16 11:28:51 -08003789
3790/**
3791 * wma_is_pnoscan_match_found(): dummy
3792 * @wma: wma handle
3793 * @vdev_id: vdev_id
3794 *
3795 * Return: False since no pnoscan cannot occur
3796 * when feature flag is not defined.
3797 */
3798static inline
3799bool wma_is_pnoscan_match_found(tp_wma_handle wma, int vdev_id)
3800{
3801 return FALSE;
3802}
Houston Hoffman61667962015-12-15 20:15:41 -08003803#endif
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003804
3805#ifdef FEATURE_WLAN_EXTSCAN
3806static inline
3807/**
3808 * wma_is_extscan_in_progress(): check if an extscan is in progress
3809 * @wma: wma handle
3810 * @vdev_id: vdev_id
3811 *
3812 * Return: TRUE/FALSvE
3813 */
3814bool wma_is_extscan_in_progress(tp_wma_handle wma, int vdev_id)
3815{
3816 return wma->interfaces[vdev_id].extscan_in_progress;
3817}
3818#else
3819/**
3820 * wma_is_extscan_in_progress(): dummy
3821 *
3822 * Return: False since no extscan can be in progress
3823 * when feature flag is not defined.
3824 */
3825bool wma_is_extscan_in_progress(tp_wma_handle wma, int vdev_id)
3826{
3827 return false;
3828}
3829#endif
3830
3831/**
Peng Xu8fdaa492016-06-22 10:20:47 -07003832 * wma_is_p2plo_in_progress(): check if P2P listen offload is in progress
3833 * @wma: wma handle
3834 * @vdev_id: vdev_id
3835 *
3836 * This function is to check if p2p listen offload is in progress,
3837 * true: p2p listen offload in progress
3838 * false: otherwise
3839 *
3840 * Return: TRUE/FALSE
3841 */
3842static inline
3843bool wma_is_p2plo_in_progress(tp_wma_handle wma, int vdev_id)
3844{
3845 return wma->interfaces[vdev_id].p2p_lo_in_progress;
3846}
3847
3848/**
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003849 * wma_is_wow_applicable(): should enable wow
3850 * @wma: wma handle
3851 *
3852 * Enable WOW if any one of the condition meets,
3853 * 1) Is any one of vdev in beaconning mode (in AP mode) ?
3854 * 2) Is any one of vdev in connected state (in STA mode) ?
3855 * 3) Is PNO in progress in any one of vdev ?
3856 * 4) Is Extscan in progress in any one of vdev ?
Peng Xu8fdaa492016-06-22 10:20:47 -07003857 * 5) Is P2P listen offload in any one of vdev?
Naveen Rawate82c1f32016-06-22 15:34:36 -07003858 * 6) Is any vdev in NAN data mode? BSS is already started at the
3859 * the time of device creation. It is ready to accept data
3860 * requests.
Rajeev Kumaraea89632016-02-02 18:02:32 -08003861 * If none of above conditions is true then return false
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003862 *
Rajeev Kumaraea89632016-02-02 18:02:32 -08003863 * Return: true if wma needs to configure wow false otherwise.
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003864 */
3865bool wma_is_wow_applicable(tp_wma_handle wma)
3866{
3867 int vdev_id;
3868 if (wma_support_wow_for_beaconing(wma)) {
3869 WMA_LOGD("vdev is in beaconning mode, enabling wow");
3870 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003871 }
3872
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003873 for (vdev_id = 0; vdev_id < wma->max_bssid; vdev_id++) {
3874 if (wma->interfaces[vdev_id].conn_state) {
3875 WMA_LOGD("STA is connected, enabling wow");
3876 return true;
3877 } else if (wma_is_pnoscan_in_progress(wma, vdev_id)) {
3878 WMA_LOGD("PNO is in progress, enabling wow");
3879 return true;
3880 } else if (wma_is_extscan_in_progress(wma, vdev_id)) {
3881 WMA_LOGD("EXT is in progress, enabling wow");
3882 return true;
Peng Xu8fdaa492016-06-22 10:20:47 -07003883 } else if (wma_is_p2plo_in_progress(wma, vdev_id)) {
3884 WMA_LOGD("P2P LO is in progress, enabling wow");
3885 return true;
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003886 }
Naveen Rawate82c1f32016-06-22 15:34:36 -07003887 if (WMA_IS_VDEV_IN_NDI_MODE(wma->interfaces, vdev_id)) {
3888 WMA_LOGD("vdev %d is in NAN data mode, enabling wow",
3889 vdev_id);
3890 return true;
3891 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003892 }
3893
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003894 WMA_LOGD("All vdev are in disconnected state and pno/extscan is not in progress, skipping wow");
Rajeev Kumaraea89632016-02-02 18:02:32 -08003895 return false;
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003896}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003897
Houston Hoffman345fa402015-12-16 11:28:51 -08003898/**
3899 * wma_configure_dynamic_wake_events(): configure dyanmic wake events
3900 * @wma: wma handle
3901 *
3902 * Some wake events need to be enabled dynamically. Controll those here.
3903 *
3904 * Return: none
3905 */
3906void wma_configure_dynamic_wake_events(tp_wma_handle wma)
3907{
3908 int vdev_id;
3909 int enable_mask;
3910 int disable_mask;
3911
3912 for (vdev_id = 0; vdev_id < wma->max_bssid; vdev_id++) {
3913 enable_mask = 0;
3914 disable_mask = 0;
3915
3916 if (wma_is_pnoscan_in_progress(wma, vdev_id)) {
3917 if (wma_is_pnoscan_match_found(wma, vdev_id))
3918 enable_mask |=
3919 (1 << WOW_NLO_SCAN_COMPLETE_EVENT);
3920 else
3921 disable_mask |=
3922 (1 << WOW_NLO_SCAN_COMPLETE_EVENT);
3923 }
3924
3925 if (enable_mask != 0)
3926 wma_enable_disable_wakeup_event(wma, vdev_id,
3927 enable_mask, true);
3928 if (disable_mask != 0)
3929 wma_enable_disable_wakeup_event(wma, vdev_id,
3930 disable_mask, false);
3931 }
3932}
3933
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003934#ifdef FEATURE_WLAN_LPHB
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003935/**
3936 * wma_apply_lphb(): apply cached LPHB settings
3937 * @wma: wma handle
3938 *
3939 * LPHB cache, if any item was enabled, should be
3940 * applied.
3941 */
3942static inline
3943void wma_apply_lphb(tp_wma_handle wma)
3944{
3945 int i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003946 WMA_LOGD("%s: checking LPHB cache", __func__);
3947 for (i = 0; i < 2; i++) {
3948 if (wma->wow.lphb_cache[i].params.lphbEnableReq.enable) {
3949 WMA_LOGD("%s: LPHB cache for item %d is marked as enable",
3950 __func__, i + 1);
3951 wma_lphb_conf_hbenable(wma, &(wma->wow.lphb_cache[i]),
3952 false);
3953 }
3954 }
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003955}
3956#else
3957void wma_apply_lphb(tp_wma_handle wma) {}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003958#endif /* FEATURE_WLAN_LPHB */
3959
Houston Hoffmana76591b2015-11-10 16:52:05 -08003960static void wma_notify_suspend_req_procesed(tp_wma_handle wma,
Anurag Chouhan6d760662016-02-20 16:05:43 +05303961 enum qdf_suspend_type type)
Houston Hoffmana76591b2015-11-10 16:52:05 -08003962{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303963 if (type == QDF_SYSTEM_SUSPEND)
Houston Hoffmana76591b2015-11-10 16:52:05 -08003964 wma_send_status_to_suspend_ind(wma, true);
Anurag Chouhan6d760662016-02-20 16:05:43 +05303965 else if (type == QDF_RUNTIME_SUSPEND)
Anurag Chouhance0dc992016-02-16 18:18:03 +05303966 qdf_event_set(&wma->runtime_suspend);
Houston Hoffmana76591b2015-11-10 16:52:05 -08003967}
3968
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003969/**
3970 * wma_suspend_req() - Handles suspend indication request received from umac.
3971 * @wma: wma handle
Houston Hoffmana76591b2015-11-10 16:52:05 -08003972 * @type: type of suspend
3973 *
3974 * The type controlls how we notify the indicator that the indication has
3975 * been processed
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003976 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303977 * Return: QDF status
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003978 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05303979QDF_STATUS wma_suspend_req(tp_wma_handle wma, enum qdf_suspend_type type)
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003980{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303981 if (type == QDF_RUNTIME_SUSPEND)
Houston Hoffman1460fa32015-11-18 02:36:30 -08003982 wmi_set_runtime_pm_inprogress(wma->wmi_handle, true);
3983
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003984 if (wma_is_wow_applicable(wma)) {
3985 WMA_LOGE("WOW Suspend");
3986 wma_apply_lphb(wma);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003987
Houston Hoffman345fa402015-12-16 11:28:51 -08003988 wma_configure_dynamic_wake_events(wma);
3989
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003990 wma->wow.wow_enable = true;
3991 wma->wow.wow_enable_cmd_sent = false;
3992 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003993
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003994 /* Set the Suspend DTIM Parameters */
3995 wma_set_suspend_dtim(wma);
Houston Hoffmana76591b2015-11-10 16:52:05 -08003996
3997 wma_notify_suspend_req_procesed(wma, type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003998
3999 /* to handle race between hif_pci_suspend and
4000 * unpause/pause tx handler
4001 */
4002 wma_set_wow_bus_suspend(wma, 1);
4003
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304004 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004005}
4006
4007/**
4008 * wma_send_host_wakeup_ind_to_fw() - send wakeup ind to fw
4009 * @wma: wma handle
4010 *
4011 * Sends host wakeup indication to FW. On receiving this indication,
4012 * FW will come out of WOW.
4013 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304014 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004015 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304016static QDF_STATUS wma_send_host_wakeup_ind_to_fw(tp_wma_handle wma)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004017{
Anurag Chouhance0dc992016-02-16 18:18:03 +05304018 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004019 int ret;
4020#ifdef CONFIG_CNSS
Anurag Chouhan6d760662016-02-20 16:05:43 +05304021 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004022 if (NULL == pMac) {
4023 WMA_LOGE("%s: Unable to get PE context", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304024 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004025 }
4026#endif /* CONFIG_CNSS */
4027
Anurag Chouhance0dc992016-02-16 18:18:03 +05304028 qdf_event_reset(&wma->wma_resume_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004029
Govind Singhaa64c242016-03-08 11:31:49 +05304030 ret = wmi_unified_host_wakeup_ind_to_fw_cmd(wma->wmi_handle);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004031 if (ret) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304032 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004033 }
4034
4035 WMA_LOGD("Host wakeup indication sent to fw");
4036
Anurag Chouhance0dc992016-02-16 18:18:03 +05304037 qdf_status = qdf_wait_single_event(&(wma->wma_resume_event),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004038 WMA_RESUME_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05304039 if (QDF_STATUS_SUCCESS != qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004040 WMA_LOGP("%s: Timeout waiting for resume event from FW",
4041 __func__);
4042 WMA_LOGP("%s: Pending commands %d credits %d", __func__,
4043 wmi_get_pending_cmds(wma->wmi_handle),
4044 wmi_get_host_credits(wma->wmi_handle));
Prashanth Bhatta9e143052015-12-04 11:56:47 -08004045 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004046#ifdef CONFIG_CNSS
4047 if (pMac->sme.enableSelfRecovery) {
4048 cds_trigger_recovery();
4049 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304050 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004051 }
4052#else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304053 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004054#endif /* CONFIG_CNSS */
4055 } else {
4056 WMA_LOGE("%s: SSR in progress, ignore resume timeout",
4057 __func__);
4058 }
4059 } else {
4060 WMA_LOGD("Host wakeup received");
4061 }
4062
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304063 if (QDF_STATUS_SUCCESS == qdf_status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004064 wmi_set_target_suspend(wma->wmi_handle, false);
4065
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304066 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004067}
4068
4069/**
4070 * wma_disable_wow_in_fw() - Disable wow in PCIe resume context.
4071 * @handle: wma handle
4072 *
4073 * Return: 0 for success or error code
4074 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304075QDF_STATUS wma_disable_wow_in_fw(WMA_HANDLE handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004076{
4077 tp_wma_handle wma = handle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304078 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004079
4080 if (!wma->wow.wow_enable || !wma->wow.wow_enable_cmd_sent)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304081 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004082
4083 ret = wma_send_host_wakeup_ind_to_fw(wma);
4084
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304085 if (ret != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004086 return ret;
4087
4088 wma->wow.wow_enable = false;
4089 wma->wow.wow_enable_cmd_sent = false;
4090
4091 /* To allow the tx pause/unpause events */
4092 wma_set_wow_bus_suspend(wma, 0);
4093 /* Unpause the vdev as we are resuming */
4094 wma_unpause_vdev(wma);
4095
4096 return ret;
4097}
4098
4099#ifdef WLAN_FEATURE_LPSS
4100/**
4101 * wma_is_lpass_enabled() - check if lpass is enabled
4102 * @handle: Pointer to wma handle
4103 *
4104 * WoW is needed if LPASS or NaN feature is enabled in INI because
4105 * target can't wake up itself if its put in PDEV suspend when LPASS
4106 * or NaN features are supported
4107 *
4108 * Return: true if lpass is enabled else false
4109 */
4110bool static wma_is_lpass_enabled(tp_wma_handle wma)
4111{
4112 if (wma->is_lpass_enabled)
4113 return true;
4114 else
4115 return false;
4116}
4117#else
4118bool static wma_is_lpass_enabled(tp_wma_handle wma)
4119{
4120 return false;
4121}
4122#endif
4123
4124#ifdef WLAN_FEATURE_NAN
4125/**
4126 * wma_is_nan_enabled() - check if NaN is enabled
4127 * @handle: Pointer to wma handle
4128 *
4129 * WoW is needed if LPASS or NaN feature is enabled in INI because
4130 * target can't wake up itself if its put in PDEV suspend when LPASS
4131 * or NaN features are supported
4132 *
4133 * Return: true if NaN is enabled else false
4134 */
4135bool static wma_is_nan_enabled(tp_wma_handle wma)
4136{
4137 if (wma->is_nan_enabled)
4138 return true;
4139 else
4140 return false;
4141}
4142#else
4143bool static wma_is_nan_enabled(tp_wma_handle wma)
4144{
4145 return false;
4146}
4147#endif
4148
4149/**
4150 * wma_is_wow_mode_selected() - check if wow needs to be enabled in fw
4151 * @handle: Pointer to wma handle
4152 *
4153 * If lpass is enabled then always do wow else check wow_enable config
4154 *
4155 * Return: true is wow mode is needed else false
4156 */
Houston Hoffmana76591b2015-11-10 16:52:05 -08004157bool wma_is_wow_mode_selected(WMA_HANDLE handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004158{
4159 tp_wma_handle wma = (tp_wma_handle) handle;
4160
4161 if (wma_is_lpass_enabled(wma)) {
4162 WMA_LOGD("LPASS is enabled select WoW");
4163 return true;
4164 } else if (wma_is_nan_enabled(wma)) {
4165 WMA_LOGD("NAN is enabled select WoW");
4166 return true;
4167 } else {
4168 WMA_LOGD("WoW enable %d", wma->wow.wow_enable);
4169 return wma->wow.wow_enable;
4170 }
4171}
4172
4173/**
4174 * wma_del_ts_req() - send DELTS request to fw
4175 * @wma: wma handle
4176 * @msg: delts params
4177 *
4178 * Return: none
4179 */
4180void wma_del_ts_req(tp_wma_handle wma, tDelTsParams *msg)
4181{
Govind Singhaa64c242016-03-08 11:31:49 +05304182 if (wmi_unified_del_ts_cmd(wma->wmi_handle,
4183 msg->sessionId,
4184 TID_TO_WME_AC(msg->userPrio))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004185 WMA_LOGP("%s: Failed to send vdev DELTS command", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004186 }
Govind Singhaa64c242016-03-08 11:31:49 +05304187
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004188#ifdef WLAN_FEATURE_ROAM_OFFLOAD
4189 if (msg->setRICparams == true)
4190 wma_set_ric_req(wma, msg, false);
4191#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
4192
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304193 qdf_mem_free(msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004194}
4195
4196/**
4197 * wma_aggr_qos_req() - send aggr qos request to fw
4198 * @wma: handle to wma
4199 * @pAggrQosRspMsg - combined struct for all ADD_TS requests.
4200 *
4201 * A function to handle WMA_AGGR_QOS_REQ. This will send out
4202 * ADD_TS requestes to firmware in loop for all the ACs with
4203 * active flow.
4204 *
4205 * Return: none
4206 */
4207void wma_aggr_qos_req(tp_wma_handle wma,
4208 tAggrAddTsParams *pAggrQosRspMsg)
4209{
Govind Singhaa64c242016-03-08 11:31:49 +05304210 wmi_unified_aggr_qos_cmd(wma->wmi_handle,
4211 (struct aggr_add_ts_param *)pAggrQosRspMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004212 /* send reponse to upper layers from here only. */
4213 wma_send_msg(wma, WMA_AGGR_QOS_RSP, pAggrQosRspMsg, 0);
4214}
4215
4216/**
4217 * wma_add_ts_req() - send ADDTS request to fw
4218 * @wma: wma handle
4219 * @msg: ADDTS params
4220 *
4221 * Return: none
4222 */
4223void wma_add_ts_req(tp_wma_handle wma, tAddTsParams *msg)
4224{
Govind Singhaa64c242016-03-08 11:31:49 +05304225 struct add_ts_param cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004226
4227#ifdef FEATURE_WLAN_ESE
4228 /*
4229 * msmt_interval is in unit called TU (1 TU = 1024 us)
4230 * max value of msmt_interval cannot make resulting
4231 * interval_miliseconds overflow 32 bit
4232 */
4233 uint32_t intervalMiliseconds;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304234 ol_txrx_pdev_handle pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004235 if (NULL == pdev) {
4236 WMA_LOGE("%s: Failed to get pdev", __func__);
4237 goto err;
4238 }
4239
4240 intervalMiliseconds = (msg->tsm_interval * 1024) / 1000;
4241
4242 ol_tx_set_compute_interval(pdev, intervalMiliseconds);
4243#endif /* FEATURE_WLAN_ESE */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304244 msg->status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004245
Govind Singhaa64c242016-03-08 11:31:49 +05304246
4247 cmd.sme_session_id = msg->sme_session_id;
4248 cmd.tspec.tsinfo.traffic.userPrio =
4249 TID_TO_WME_AC(msg->tspec.tsinfo.traffic.userPrio);
4250 cmd.tspec.mediumTime = msg->tspec.mediumTime;
4251 if (wmi_unified_add_ts_cmd(wma->wmi_handle, &cmd))
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304252 msg->status = QDF_STATUS_E_FAILURE;
Govind Singhaa64c242016-03-08 11:31:49 +05304253
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004254#ifdef WLAN_FEATURE_ROAM_OFFLOAD
4255 if (msg->setRICparams == true)
4256 wma_set_ric_req(wma, msg, true);
4257#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
4258
4259err:
4260 wma_send_msg(wma, WMA_ADD_TS_RSP, msg, 0);
4261}
4262
4263/**
4264 * wma_enable_disable_packet_filter() - enable/disable packet filter in target
4265 * @wma: Pointer to wma handle
4266 * @vdev_id: vdev id
4267 * @enable: Flag to enable/disable packet filter
4268 *
4269 * Return: 0 for success or error code
4270 */
4271static int wma_enable_disable_packet_filter(tp_wma_handle wma,
4272 uint8_t vdev_id, bool enable)
4273{
Govind Singhaa64c242016-03-08 11:31:49 +05304274 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004275
Govind Singhaa64c242016-03-08 11:31:49 +05304276 ret = wmi_unified_enable_disable_packet_filter_cmd(wma->wmi_handle,
4277 vdev_id, enable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004278 if (ret)
4279 WMA_LOGE("Failed to send packet filter wmi cmd to fw");
4280
4281 return ret;
4282}
4283
4284/**
4285 * wma_config_packet_filter() - configure packet filter in target
4286 * @wma: Pointer to wma handle
4287 * @vdev_id: vdev id
4288 * @rcv_filter_param: Packet filter parameters
4289 * @filter_id: Filter id
4290 * @enable: Flag to add/delete packet filter configuration
4291 *
4292 * Return: 0 for success or error code
4293 */
4294static int wma_config_packet_filter(tp_wma_handle wma,
4295 uint8_t vdev_id, tSirRcvPktFilterCfgType *rcv_filter_param,
4296 uint8_t filter_id, bool enable)
4297{
Govind Singhaa64c242016-03-08 11:31:49 +05304298 int err;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004299
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004300 /* send the command along with data */
Govind Singhaa64c242016-03-08 11:31:49 +05304301 err = wmi_unified_config_packet_filter_cmd(wma->wmi_handle,
4302 vdev_id, (struct rcv_pkt_filter_config *)rcv_filter_param,
4303 filter_id, enable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004304 if (err) {
4305 WMA_LOGE("Failed to send pkt_filter cmd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004306 return -EIO;
4307 }
4308
4309 /* Enable packet filter */
4310 if (enable)
4311 wma_enable_disable_packet_filter(wma, vdev_id, true);
4312
4313 return 0;
4314}
4315
4316/**
4317 * wma_process_receive_filter_set_filter_req() - enable packet filter
4318 * @wma_handle: wma handle
4319 * @rcv_filter_param: filter params
4320 *
4321 * Return: 0 for success or error code
4322 */
4323int wma_process_receive_filter_set_filter_req(tp_wma_handle wma,
4324 tSirRcvPktFilterCfgType *rcv_filter_param)
4325{
4326 int ret = 0;
4327 uint8_t vdev_id;
4328
4329 /* Get the vdev id */
Srinivas Girigowda98530492015-11-20 17:39:24 -08004330 if (!wma_find_vdev_by_bssid(wma,
4331 rcv_filter_param->bssid.bytes, &vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004332 WMA_LOGE("vdev handle is invalid for %pM",
Srinivas Girigowda98530492015-11-20 17:39:24 -08004333 rcv_filter_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004334 return -EINVAL;
4335 }
4336
4337 ret = wma_config_packet_filter(wma, vdev_id, rcv_filter_param,
4338 rcv_filter_param->filterId, true);
4339
4340 return ret;
4341}
4342
4343/**
4344 * wma_process_receive_filter_clear_filter_req() - disable packet filter
4345 * @wma_handle: wma handle
4346 * @rcv_clear_param: filter params
4347 *
4348 * Return: 0 for success or error code
4349 */
4350int wma_process_receive_filter_clear_filter_req(tp_wma_handle wma,
4351 tSirRcvFltPktClearParam *rcv_clear_param)
4352{
4353 int ret = 0;
4354 uint8_t vdev_id;
4355
4356 /* Get the vdev id */
Srinivas Girigowda98530492015-11-20 17:39:24 -08004357 if (!wma_find_vdev_by_bssid(wma,
4358 rcv_clear_param->bssid.bytes, &vdev_id)) {
4359 WMA_LOGE("vdev handle is invalid for %pM",
4360 rcv_clear_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004361 return -EINVAL;
4362 }
4363
4364 ret = wma_config_packet_filter(wma, vdev_id, NULL,
4365 rcv_clear_param->filterId, false);
4366
4367 return ret;
4368}
4369
4370#ifdef FEATURE_WLAN_ESE
4371
4372#define TSM_DELAY_HISTROGRAM_BINS 4
4373/**
4374 * wma_process_tsm_stats_req() - process tsm stats request
4375 * @wma_handler - handle to wma
4376 * @pTsmStatsMsg - TSM stats struct that needs to be populated and
4377 * passed in message.
4378 *
4379 * A parallel function to WMA_ProcessTsmStatsReq for pronto. This
4380 * function fetches stats from data path APIs and post
4381 * WMA_TSM_STATS_RSP msg back to LIM.
4382 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304383 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004384 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304385QDF_STATUS wma_process_tsm_stats_req(tp_wma_handle wma_handler,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004386 void *pTsmStatsMsg)
4387{
4388 uint8_t counter;
4389 uint32_t queue_delay_microsec = 0;
4390 uint32_t tx_delay_microsec = 0;
4391 uint16_t packet_count = 0;
4392 uint16_t packet_loss_count = 0;
4393 tpAniTrafStrmMetrics pTsmMetric = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004394 tpAniGetTsmStatsReq pStats = (tpAniGetTsmStatsReq) pTsmStatsMsg;
4395 tpAniGetTsmStatsRsp pTsmRspParams = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004396 int tid = pStats->tid;
4397 /*
4398 * The number of histrogram bin report by data path api are different
4399 * than required by TSM, hence different (6) size array used
4400 */
4401 uint16_t bin_values[QCA_TX_DELAY_HIST_REPORT_BINS] = { 0, };
4402
Anurag Chouhan6d760662016-02-20 16:05:43 +05304403 ol_txrx_pdev_handle pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004404
4405 if (NULL == pdev) {
4406 WMA_LOGE("%s: Failed to get pdev", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304407 qdf_mem_free(pTsmStatsMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304408 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004409 }
4410
4411 /* get required values from data path APIs */
4412 ol_tx_delay(pdev, &queue_delay_microsec, &tx_delay_microsec, tid);
4413 ol_tx_delay_hist(pdev, bin_values, tid);
4414 ol_tx_packet_count(pdev, &packet_count, &packet_loss_count, tid);
4415
Srinivas Girigowda515a9ef2015-12-11 11:00:48 -08004416 pTsmRspParams = qdf_mem_malloc(sizeof(*pTsmRspParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004417 if (NULL == pTsmRspParams) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304418 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304419 "%s: QDF MEM Alloc Failure", __func__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304420 QDF_ASSERT(0);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304421 qdf_mem_free(pTsmStatsMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304422 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004423 }
4424 pTsmRspParams->staId = pStats->staId;
4425 pTsmRspParams->rc = eSIR_FAILURE;
4426 pTsmRspParams->tsmStatsReq = pStats;
4427 pTsmMetric = &pTsmRspParams->tsmMetrics;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004428 /* populate pTsmMetric */
4429 pTsmMetric->UplinkPktQueueDly = queue_delay_microsec;
4430 /* store only required number of bin values */
4431 for (counter = 0; counter < TSM_DELAY_HISTROGRAM_BINS; counter++) {
4432 pTsmMetric->UplinkPktQueueDlyHist[counter] =
4433 bin_values[counter];
4434 }
4435 pTsmMetric->UplinkPktTxDly = tx_delay_microsec;
4436 pTsmMetric->UplinkPktLoss = packet_loss_count;
4437 pTsmMetric->UplinkPktCount = packet_count;
4438
4439 /*
4440 * No need to populate roaming delay and roaming count as they are
4441 * being populated just before sending IAPP frame out
4442 */
4443 /* post this message to LIM/PE */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004444 wma_send_msg(wma_handler, WMA_TSM_STATS_RSP, (void *)pTsmRspParams, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304445 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004446}
4447
4448#endif /* FEATURE_WLAN_ESE */
4449
4450/**
4451 * wma_add_clear_mcbc_filter() - set mcast filter command to fw
4452 * @wma_handle: wma handle
4453 * @vdev_id: vdev id
4454 * @multicastAddr: mcast address
4455 * @clearList: clear list flag
4456 *
4457 * Return: 0 for success or error code
4458 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304459static QDF_STATUS wma_add_clear_mcbc_filter(tp_wma_handle wma_handle,
4460 uint8_t vdev_id,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304461 struct qdf_mac_addr multicast_addr,
Srinivas Girigowda98530492015-11-20 17:39:24 -08004462 bool clearList)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004463{
Himanshu Agarwal44195412016-03-09 13:03:54 +05304464 return wmi_unified_add_clear_mcbc_filter_cmd(wma_handle->wmi_handle,
4465 vdev_id, multicast_addr, clearList);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004466}
4467
4468/**
Rajeev Kumaref96e152016-04-15 18:10:33 -07004469 * wma_config_enhance_multicast_offload() - config enhance multicast offload
4470 * @wma_handle: wma handle
4471 * @vdev_id: vdev id
4472 * @action: enable or disable enhance multicast offload
4473 *
4474 * Return: none
4475 */
4476static void wma_config_enhance_multicast_offload(tp_wma_handle wma_handle,
4477 uint8_t vdev_id,
4478 uint8_t action)
4479{
4480 int status;
4481 wmi_buf_t buf;
4482 wmi_config_enhanced_mcast_filter_cmd_fixed_param *cmd;
4483
4484 buf = wmi_buf_alloc(wma_handle->wmi_handle, sizeof(*cmd));
4485 if (!buf) {
4486 WMA_LOGE("Failed to allocate buffer to send set key cmd");
4487 return;
4488 }
4489
4490 cmd = (wmi_config_enhanced_mcast_filter_cmd_fixed_param *)
4491 wmi_buf_data(buf);
4492
4493 WMITLV_SET_HDR(&cmd->tlv_header,
4494 WMITLV_TAG_STRUC_wmi_config_enhanced_mcast_filter_fixed_param,
4495 WMITLV_GET_STRUCT_TLVLEN(wmi_config_enhanced_mcast_filter_cmd_fixed_param));
4496
4497 cmd->vdev_id = vdev_id;
4498 cmd->enable = ((0 == action) ? ENHANCED_MCAST_FILTER_DISABLED :
4499 ENHANCED_MCAST_FILTER_ENABLED);
4500
4501 WMA_LOGD("%s: config enhance multicast offload action %d for vdev %d",
4502 __func__, action, vdev_id);
4503
4504 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
4505 sizeof(*cmd), WMI_CONFIG_ENHANCED_MCAST_FILTER_CMDID);
4506 if (status) {
4507 qdf_nbuf_free(buf);
4508 WMA_LOGE("%s:Failed to send WMI_CONFIG_ENHANCED_MCAST_FILTER_CMDID",
4509 __func__);
4510 }
4511
4512 return;
4513}
4514
4515/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004516 * wma_process_mcbc_set_filter_req() - process mcbc set filter request
4517 * @wma_handle: wma handle
4518 * @mcbc_param: mcbc params
4519 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304520 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004521 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304522QDF_STATUS wma_process_mcbc_set_filter_req(tp_wma_handle wma_handle,
Anurag Chouhance0dc992016-02-16 18:18:03 +05304523 tSirRcvFltMcAddrList *mcbc_param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004524{
4525 uint8_t vdev_id = 0;
4526 int i;
4527
4528 if (mcbc_param->ulMulticastAddrCnt <= 0) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004529 WMA_LOGW("Number of multicast addresses is 0");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304530 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004531 }
4532
Srinivas Girigowda98530492015-11-20 17:39:24 -08004533 if (!wma_find_vdev_by_addr(wma_handle,
4534 mcbc_param->self_macaddr.bytes, &vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004535 WMA_LOGE("%s: Failed to find vdev id for %pM", __func__,
Srinivas Girigowda98530492015-11-20 17:39:24 -08004536 mcbc_param->bssid.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304537 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004538 }
Rajeev Kumaref96e152016-04-15 18:10:33 -07004539
4540 /*
4541 * Configure enhance multicast offload feature for filtering out
4542 * multicast IP data packets transmitted using unicast MAC address
4543 */
4544 if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap,
4545 WMI_SERVICE_ENHANCED_MCAST_FILTER)) {
4546 WMA_LOGD("%s: FW supports enhance multicast offload", __func__);
4547 wma_config_enhance_multicast_offload(wma_handle, vdev_id,
4548 mcbc_param->action);
4549 } else {
4550 WMA_LOGD("%s: FW does not support enhance multicast offload",
4551 __func__);
4552 }
4553
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004554 /* set mcbc_param->action to clear MCList and reset
4555 * to configure the MCList in FW
4556 */
4557
4558 for (i = 0; i < mcbc_param->ulMulticastAddrCnt; i++) {
4559 wma_add_clear_mcbc_filter(wma_handle, vdev_id,
4560 mcbc_param->multicastAddr[i],
4561 (mcbc_param->action == 0));
4562 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304563 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004564}
4565
4566#ifdef WLAN_FEATURE_GTK_OFFLOAD
4567#define GTK_OFFLOAD_ENABLE 0
4568#define GTK_OFFLOAD_DISABLE 1
4569
4570/**
4571 * wma_gtk_offload_status_event() - GTK offload status event handler
4572 * @handle: wma handle
4573 * @event: event buffer
4574 * @len: buffer length
4575 *
4576 * Return: 0 for success or error code
4577 */
4578int wma_gtk_offload_status_event(void *handle, uint8_t *event,
4579 uint32_t len)
4580{
4581 tp_wma_handle wma = (tp_wma_handle) handle;
4582 WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param *status;
4583 WMI_GTK_OFFLOAD_STATUS_EVENTID_param_tlvs *param_buf;
4584 tpSirGtkOffloadGetInfoRspParams resp;
4585 cds_msg_t cds_msg;
4586 uint8_t *bssid;
4587
4588 WMA_LOGD("%s Enter", __func__);
4589
4590 param_buf = (WMI_GTK_OFFLOAD_STATUS_EVENTID_param_tlvs *) event;
4591 if (!param_buf) {
4592 WMA_LOGE("param_buf is NULL");
4593 return -EINVAL;
4594 }
4595
4596 status = (WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param *) param_buf->fixed_param;
4597
4598 if (len < sizeof(WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param)) {
4599 WMA_LOGE("Invalid length for GTK status");
4600 return -EINVAL;
4601 }
4602 bssid = wma_find_bssid_by_vdev_id(wma, status->vdev_id);
4603 if (!bssid) {
4604 WMA_LOGE("invalid bssid for vdev id %d", status->vdev_id);
4605 return -ENOENT;
4606 }
4607
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304608 resp = qdf_mem_malloc(sizeof(*resp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004609 if (!resp) {
4610 WMA_LOGE("%s: Failed to alloc response", __func__);
4611 return -ENOMEM;
4612 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304613 qdf_mem_zero(resp, sizeof(*resp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004614 resp->mesgType = eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP;
4615 resp->mesgLen = sizeof(*resp);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304616 resp->ulStatus = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004617 resp->ulTotalRekeyCount = status->refresh_cnt;
4618 /* TODO: Is the total rekey count and GTK rekey count same? */
4619 resp->ulGTKRekeyCount = status->refresh_cnt;
4620
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304621 qdf_mem_copy(&resp->ullKeyReplayCounter, &status->replay_counter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004622 GTK_REPLAY_COUNTER_BYTES);
4623
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304624 qdf_mem_copy(resp->bssid.bytes, bssid, IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004625
4626#ifdef IGTK_OFFLOAD
4627 /* TODO: Is the refresh count same for GTK and IGTK? */
4628 resp->ulIGTKRekeyCount = status->refresh_cnt;
4629#endif /* IGTK_OFFLOAD */
4630
4631 cds_msg.type = eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP;
4632 cds_msg.bodyptr = (void *)resp;
4633 cds_msg.bodyval = 0;
4634
4635 if (cds_mq_post_message(CDS_MQ_ID_SME, (cds_msg_t *) &cds_msg)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304636 != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004637 WMA_LOGE("Failed to post GTK response to SME");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304638 qdf_mem_free(resp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004639 return -EINVAL;
4640 }
4641
4642 WMA_LOGD("GTK: got target status with replay counter "
4643 "%02x%02x%02x%02x%02x%02x%02x%02x. vdev %d "
4644 "Refresh GTK %d times exchanges since last set operation",
4645 status->replay_counter[0],
4646 status->replay_counter[1],
4647 status->replay_counter[2],
4648 status->replay_counter[3],
4649 status->replay_counter[4],
4650 status->replay_counter[5],
4651 status->replay_counter[6],
4652 status->replay_counter[7],
4653 status->vdev_id, status->refresh_cnt);
4654
4655 WMA_LOGD("%s Exit", __func__);
4656
4657 return 0;
4658}
4659
4660/**
4661 * wma_send_gtk_offload_req() - send GTK offload command to fw
4662 * @wma: wma handle
4663 * @vdev_id: vdev id
4664 * @params: GTK offload parameters
4665 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304666 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004667 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304668static QDF_STATUS wma_send_gtk_offload_req(tp_wma_handle wma, uint8_t vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004669 tpSirGtkOffloadParams params)
4670{
Himanshu Agarwal44195412016-03-09 13:03:54 +05304671 struct gtk_offload_params offload_params = {0};
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304672 QDF_STATUS status = QDF_STATUS_SUCCESS;
Himanshu Agarwal44195412016-03-09 13:03:54 +05304673 bool enable_offload;
4674 uint32_t gtk_offload_opcode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004675
4676 WMA_LOGD("%s Enter", __func__);
4677
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004678 /* Request target to enable GTK offload */
4679 if (params->ulFlags == GTK_OFFLOAD_ENABLE) {
Himanshu Agarwal44195412016-03-09 13:03:54 +05304680 gtk_offload_opcode = GTK_OFFLOAD_ENABLE_OPCODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004681 wma->wow.gtk_err_enable[vdev_id] = true;
4682
4683 /* Copy the keys and replay counter */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304684 qdf_mem_copy(offload_params.aKCK, params->aKCK,
4685 GTK_OFFLOAD_KCK_BYTES);
4686 qdf_mem_copy(offload_params.aKEK, params->aKEK,
4687 GTK_OFFLOAD_KEK_BYTES);
4688 qdf_mem_copy(&offload_params.ullKeyReplayCounter,
4689 &params->ullKeyReplayCounter, GTK_REPLAY_COUNTER_BYTES);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004690 } else {
4691 wma->wow.gtk_err_enable[vdev_id] = false;
Himanshu Agarwal44195412016-03-09 13:03:54 +05304692 gtk_offload_opcode = GTK_OFFLOAD_DISABLE_OPCODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004693 }
4694
Himanshu Agarwal44195412016-03-09 13:03:54 +05304695 enable_offload = params->ulFlags;
4696
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004697 /* send the wmi command */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304698 status = wmi_unified_send_gtk_offload_cmd(wma->wmi_handle,
4699 vdev_id, &offload_params,
4700 enable_offload,
4701 gtk_offload_opcode);
4702 if (QDF_IS_STATUS_ERROR(status))
4703 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004704
Himanshu Agarwal44195412016-03-09 13:03:54 +05304705 WMA_LOGD("VDEVID: %d, GTK_FLAGS: x%x", vdev_id, gtk_offload_opcode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004706out:
4707 WMA_LOGD("%s Exit", __func__);
4708 return status;
4709}
4710
4711/**
4712 * wma_process_gtk_offload_req() - process GTK offload req from umac
4713 * @handle: wma handle
4714 * @params: GTK offload params
4715 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304716 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004717 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304718QDF_STATUS wma_process_gtk_offload_req(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004719 tpSirGtkOffloadParams params)
4720{
4721 uint8_t vdev_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304722 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004723
4724 WMA_LOGD("%s Enter", __func__);
4725
4726 /* Get the vdev id */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08004727 if (!wma_find_vdev_by_bssid(wma, params->bssid.bytes, &vdev_id)) {
4728 WMA_LOGE("vdev handle is invalid for %pM", params->bssid.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304729 status = QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004730 goto out;
4731 }
4732
4733 /* Validate vdev id */
Naveen Rawate9fb4ce2016-06-27 15:36:10 -07004734 if (vdev_id >= WMA_MAX_SUPPORTED_BSS) {
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08004735 WMA_LOGE("invalid vdev_id %d for %pM", vdev_id,
4736 params->bssid.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304737 status = QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004738 goto out;
4739 }
4740
4741 if ((params->ulFlags == GTK_OFFLOAD_ENABLE) &&
4742 (wma->wow.gtk_err_enable[vdev_id] == true)) {
4743 WMA_LOGE("%s GTK Offload already enabled. Disable it first "
4744 "vdev_id %d", __func__, vdev_id);
4745 params->ulFlags = GTK_OFFLOAD_DISABLE;
4746 status = wma_send_gtk_offload_req(wma, vdev_id, params);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304747 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004748 WMA_LOGE("%s Failed to disable GTK Offload", __func__);
4749 goto out;
4750 }
4751 WMA_LOGD("%s Enable GTK Offload again with updated inputs",
4752 __func__);
4753 params->ulFlags = GTK_OFFLOAD_ENABLE;
4754 }
4755 status = wma_send_gtk_offload_req(wma, vdev_id, params);
4756out:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304757 qdf_mem_free(params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004758 WMA_LOGD("%s Exit", __func__);
4759 return status;
4760}
4761
4762/**
4763 * wma_process_gtk_offload_getinfo_req() - send GTK offload cmd to fw
4764 * @wma: wma handle
4765 * @params: GTK offload params
4766 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304767 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004768 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304769QDF_STATUS wma_process_gtk_offload_getinfo_req(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004770 tpSirGtkOffloadGetInfoRspParams params)
4771{
4772 uint8_t vdev_id;
Himanshu Agarwal44195412016-03-09 13:03:54 +05304773 uint64_t offload_req_opcode;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304774 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004775
4776 WMA_LOGD("%s Enter", __func__);
4777
4778 /* Get the vdev id */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08004779 if (!wma_find_vdev_by_bssid(wma, params->bssid.bytes, &vdev_id)) {
4780 WMA_LOGE("vdev handle is invalid for %pM", params->bssid.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304781 status = QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004782 goto out;
4783 }
4784
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004785 /* Request for GTK offload status */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304786 offload_req_opcode = GTK_OFFLOAD_REQUEST_STATUS_OPCODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004787
4788 /* send the wmi command */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304789 status = wmi_unified_process_gtk_offload_getinfo_cmd(wma->wmi_handle,
4790 vdev_id, offload_req_opcode);
4791
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004792out:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304793 qdf_mem_free(params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004794 WMA_LOGD("%s Exit", __func__);
4795 return status;
4796}
4797#endif /* WLAN_FEATURE_GTK_OFFLOAD */
4798
4799/**
4800 * wma_enable_arp_ns_offload() - enable ARP NS offload
4801 * @wma: wma handle
4802 * @tpSirHostOffloadReq: offload request
Govind Singhaa64c242016-03-08 11:31:49 +05304803 * @arp_only: flag
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004804 *
4805 * To configure ARP NS off load data to firmware
4806 * when target goes to wow mode.
4807 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304808 * Return: QDF Status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004809 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304810QDF_STATUS wma_enable_arp_ns_offload(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004811 tpSirHostOffloadReq
Govind Singhaa64c242016-03-08 11:31:49 +05304812 pHostOffloadParams, bool arp_only)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004813{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004814 int32_t res;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004815 uint8_t vdev_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004816
4817 /* Get the vdev id */
Srinivas Girigowdab084b552015-11-24 12:39:12 -08004818 if (!wma_find_vdev_by_bssid(wma, pHostOffloadParams->bssid.bytes,
4819 &vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004820 WMA_LOGE("vdev handle is invalid for %pM",
Srinivas Girigowdab084b552015-11-24 12:39:12 -08004821 pHostOffloadParams->bssid.bytes);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304822 qdf_mem_free(pHostOffloadParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304823 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004824 }
4825
4826 if (!wma->interfaces[vdev_id].vdev_up) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004827 WMA_LOGE("vdev %d is not up skipping arp/ns offload", vdev_id);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304828 qdf_mem_free(pHostOffloadParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304829 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004830 }
4831
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004832
Govind Singhaa64c242016-03-08 11:31:49 +05304833 res = wmi_unified_enable_arp_ns_offload_cmd(wma->wmi_handle,
4834 (struct host_offload_req_param *)pHostOffloadParams,
4835 arp_only,
4836 vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004837 if (res) {
4838 WMA_LOGE("Failed to enable ARP NDP/NSffload");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304839 qdf_mem_free(pHostOffloadParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304840 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004841 }
4842
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304843 qdf_mem_free(pHostOffloadParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304844 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004845}
4846
4847/**
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08004848 * wma_process_cesium_enable_ind() - enables cesium functionality in target
4849 * @wma: wma handle
4850 *
4851 * Return: QDF status
4852 */
4853QDF_STATUS wma_process_cesium_enable_ind(tp_wma_handle wma)
4854{
4855 QDF_STATUS ret;
4856 int32_t vdev_id;
4857
4858 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
4859 if (vdev_id < 0) {
4860 WMA_LOGE("%s: IBSS vdev does not exist could not enable cesium",
4861 __func__);
4862 return QDF_STATUS_E_FAILURE;
4863 }
4864
4865 /* Send enable cesium command to target */
4866 WMA_LOGE("Enable cesium in target for vdevId %d ", vdev_id);
4867 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
4868 WMI_VDEV_PARAM_ENABLE_RMC, 1);
4869 if (ret) {
4870 WMA_LOGE("Enable cesium failed for vdevId %d", vdev_id);
4871 return QDF_STATUS_E_FAILURE;
4872 }
4873 return QDF_STATUS_SUCCESS;
4874}
4875
4876/**
4877 * wma_process_get_peer_info_req() - sends get peer info cmd to target
4878 * @wma: wma handle
4879 * @preq: get peer info request
4880 *
4881 * Return: QDF status
4882 */
4883QDF_STATUS wma_process_get_peer_info_req
4884 (tp_wma_handle wma, tSirIbssGetPeerInfoReqParams *pReq)
4885{
4886 int32_t ret;
4887 uint8_t *p;
4888 uint16_t len;
4889 wmi_buf_t buf;
4890 int32_t vdev_id;
4891 ol_txrx_pdev_handle pdev;
4892 struct ol_txrx_peer_t *peer;
4893 uint8_t peer_mac[IEEE80211_ADDR_LEN];
4894 wmi_peer_info_req_cmd_fixed_param *p_get_peer_info_cmd;
4895 uint8_t bcast_mac[IEEE80211_ADDR_LEN] = { 0xff, 0xff, 0xff,
4896 0xff, 0xff, 0xff };
4897
4898 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
4899 if (vdev_id < 0) {
4900 WMA_LOGE("%s: IBSS vdev does not exist could not get peer info",
4901 __func__);
4902 return QDF_STATUS_E_FAILURE;
4903 }
4904
4905 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
4906 if (NULL == pdev) {
4907 WMA_LOGE("%s: Failed to get pdev context", __func__);
4908 return QDF_STATUS_E_FAILURE;
4909 }
4910
4911 if (0xFF == pReq->staIdx) {
4912 /*get info for all peers */
4913 qdf_mem_copy(peer_mac, bcast_mac, IEEE80211_ADDR_LEN);
4914 } else {
4915 /*get info for a single peer */
4916 peer = ol_txrx_peer_find_by_local_id(pdev, pReq->staIdx);
4917 if (!peer) {
4918 WMA_LOGE("%s: Failed to get peer handle using peer id %d",
4919 __func__, pReq->staIdx);
4920 return QDF_STATUS_E_FAILURE;
4921 }
4922 WMA_LOGE("%s: staIdx %d peer mac: 0x%2x:0x%2x:0x%2x:0x%2x:0x%2x:0x%2x",
4923 __func__, pReq->staIdx, peer->mac_addr.raw[0],
4924 peer->mac_addr.raw[1], peer->mac_addr.raw[2],
4925 peer->mac_addr.raw[3], peer->mac_addr.raw[4],
4926 peer->mac_addr.raw[5]);
4927 qdf_mem_copy(peer_mac, peer->mac_addr.raw, IEEE80211_ADDR_LEN);
4928 }
4929
4930 len = sizeof(wmi_peer_info_req_cmd_fixed_param);
4931 buf = wmi_buf_alloc(wma->wmi_handle, len);
4932 if (!buf) {
4933 WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__);
4934 return QDF_STATUS_E_FAILURE;
4935 }
4936
4937 p = (uint8_t *) wmi_buf_data(buf);
4938 qdf_mem_zero(p, len);
4939 p_get_peer_info_cmd = (wmi_peer_info_req_cmd_fixed_param *) p;
4940
4941 WMITLV_SET_HDR(&p_get_peer_info_cmd->tlv_header,
4942 WMITLV_TAG_STRUC_wmi_peer_info_req_cmd_fixed_param,
4943 WMITLV_GET_STRUCT_TLVLEN
4944 (wmi_peer_info_req_cmd_fixed_param));
4945
4946 p_get_peer_info_cmd->vdev_id = vdev_id;
4947 WMI_CHAR_ARRAY_TO_MAC_ADDR(peer_mac,
4948 &p_get_peer_info_cmd->peer_mac_address);
4949
4950 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
4951 WMI_PEER_INFO_REQ_CMDID);
4952
4953 WMA_LOGE("IBSS get peer info cmd sent len: %d, vdev %d"
4954 " command id: %d, status: %d", len,
4955 p_get_peer_info_cmd->vdev_id, WMI_PEER_INFO_REQ_CMDID, ret);
4956
4957 return QDF_STATUS_SUCCESS;
4958}
4959
4960/**
4961 * wma_process_tx_fail_monitor_ind() - sends tx fail monitor cmd to target
4962 * @wma: wma handle
4963 * @pReq: tx fail monitor command params
4964 *
4965 * Return: QDF status
4966 */
4967QDF_STATUS wma_process_tx_fail_monitor_ind
4968 (tp_wma_handle wma, tAniTXFailMonitorInd *pReq)
4969{
4970 QDF_STATUS ret;
4971 int32_t vdev_id;
4972
4973 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
4974 if (vdev_id < 0) {
4975 WMA_LOGE("%s: IBSS vdev does not exist could not send fast tx fail"
4976 " monitor indication message to target", __func__);
4977 return QDF_STATUS_E_FAILURE;
4978 }
4979
4980 /* Send enable cesium command to target */
4981 WMA_LOGE("send fast tx fail monitor ind cmd target for vdevId %d val %d",
4982 vdev_id, pReq->tx_fail_count);
4983
4984 if (0 == pReq->tx_fail_count) {
4985 wma->hddTxFailCb = NULL;
4986 } else {
4987 wma->hddTxFailCb = pReq->txFailIndCallback;
4988 }
4989 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
4990 WMI_VDEV_PARAM_SET_IBSS_TX_FAIL_CNT_THR,
4991 pReq->tx_fail_count);
4992 if (ret) {
4993 WMA_LOGE("tx fail monitor failed for vdevId %d", vdev_id);
4994 return QDF_STATUS_E_FAILURE;
4995 }
4996
4997 return QDF_STATUS_SUCCESS;
4998}
4999
5000/**
5001 * wma_process_rmc_enable_ind() - enables RMC functionality in target
5002 * @wma: wma handle
5003 *
5004 * Return: QDF status
5005 */
5006QDF_STATUS wma_process_rmc_enable_ind(tp_wma_handle wma)
5007{
5008 int ret;
5009 uint8_t *p;
5010 uint16_t len;
5011 wmi_buf_t buf;
5012 int32_t vdev_id;
5013 wmi_rmc_set_mode_cmd_fixed_param *p_rmc_enable_cmd;
5014
5015 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
5016 if (vdev_id < 0) {
5017 WMA_LOGE("%s: IBSS vdev does not exist could not enable RMC",
5018 __func__);
5019 return QDF_STATUS_E_FAILURE;
5020 }
5021
5022 len = sizeof(wmi_rmc_set_mode_cmd_fixed_param);
5023 buf = wmi_buf_alloc(wma->wmi_handle, len);
5024 if (!buf) {
5025 WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__);
5026 return QDF_STATUS_E_FAILURE;
5027 }
5028
5029 p = (uint8_t *) wmi_buf_data(buf);
5030 qdf_mem_zero(p, len);
5031 p_rmc_enable_cmd = (wmi_rmc_set_mode_cmd_fixed_param *) p;
5032
5033 WMITLV_SET_HDR(&p_rmc_enable_cmd->tlv_header,
5034 WMITLV_TAG_STRUC_wmi_rmc_set_mode_cmd_fixed_param,
5035 WMITLV_GET_STRUCT_TLVLEN
5036 (wmi_rmc_set_mode_cmd_fixed_param));
5037
5038 p_rmc_enable_cmd->vdev_id = vdev_id;
5039 p_rmc_enable_cmd->enable_rmc = WMI_RMC_MODE_ENABLED;
5040
5041 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
5042 WMI_RMC_SET_MODE_CMDID);
5043
5044 WMA_LOGE("Enable RMC cmd sent len: %d, vdev %d" " command id: %d,"
5045 " status: %d", len, p_rmc_enable_cmd->vdev_id,
5046 WMI_RMC_SET_MODE_CMDID, ret);
5047
5048 return QDF_STATUS_SUCCESS;
5049}
5050
5051/**
5052 * wma_process_rmc_disable_ind() - disables rmc functionality in target
5053 * @wma: wma handle
5054 *
5055 * Return: QDF status
5056 */
5057QDF_STATUS wma_process_rmc_disable_ind(tp_wma_handle wma)
5058{
5059 int ret;
5060 uint8_t *p;
5061 uint16_t len;
5062 wmi_buf_t buf;
5063 int32_t vdev_id;
5064 wmi_rmc_set_mode_cmd_fixed_param *p_rmc_disable_cmd;
5065
5066 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
5067 if (vdev_id < 0) {
5068 WMA_LOGE("%s: IBSS vdev does not exist could not disable RMC",
5069 __func__);
5070 return QDF_STATUS_E_FAILURE;
5071 }
5072
5073 len = sizeof(wmi_rmc_set_mode_cmd_fixed_param);
5074 buf = wmi_buf_alloc(wma->wmi_handle, len);
5075 if (!buf) {
5076 WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__);
5077 return QDF_STATUS_E_FAILURE;
5078 }
5079
5080 p = (uint8_t *) wmi_buf_data(buf);
5081 qdf_mem_zero(p, len);
5082 p_rmc_disable_cmd = (wmi_rmc_set_mode_cmd_fixed_param *) p;
5083
5084 WMITLV_SET_HDR(&p_rmc_disable_cmd->tlv_header,
5085 WMITLV_TAG_STRUC_wmi_rmc_set_mode_cmd_fixed_param,
5086 WMITLV_GET_STRUCT_TLVLEN
5087 (wmi_rmc_set_mode_cmd_fixed_param));
5088
5089 p_rmc_disable_cmd->vdev_id = vdev_id;
5090 p_rmc_disable_cmd->enable_rmc = WMI_RMC_MODE_DISABLED;
5091
5092 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
5093 WMI_RMC_SET_MODE_CMDID);
5094
5095 WMA_LOGE("Disable RMC cmd sent len: %d, vdev %d" " command id: %d,"
5096 " status: %d", len, p_rmc_disable_cmd->vdev_id,
5097 WMI_RMC_SET_MODE_CMDID, ret);
5098
5099 return QDF_STATUS_SUCCESS;
5100}
5101
5102/**
5103 * wma_process_rmc_action_period_ind() - sends RMC action period to target
5104 * @wma: wma handle
5105 *
5106 * Return: QDF status
5107 */
5108QDF_STATUS wma_process_rmc_action_period_ind(tp_wma_handle wma)
5109{
5110 int ret;
5111 uint8_t *p;
5112 uint16_t len;
5113 uint32_t val;
5114 wmi_buf_t buf;
5115 int32_t vdev_id;
5116 wmi_rmc_set_action_period_cmd_fixed_param *p_rmc_cmd;
5117 struct sAniSirGlobal *mac = cds_get_context(QDF_MODULE_ID_PE);
5118
5119 if (NULL == mac) {
5120 WMA_LOGE("%s: MAC mac does not exist", __func__);
5121 return QDF_STATUS_E_FAILURE;
5122 }
5123
5124 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
5125 if (vdev_id < 0) {
5126 WMA_LOGE("%s: IBSS vdev does not exist could not send"
5127 " RMC action period to target", __func__);
5128 return QDF_STATUS_E_FAILURE;
5129 }
5130
5131 len = sizeof(wmi_rmc_set_action_period_cmd_fixed_param);
5132 buf = wmi_buf_alloc(wma->wmi_handle, len);
5133 if (!buf) {
5134 WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__);
5135 return QDF_STATUS_E_FAILURE;
5136 }
5137
5138 p = (uint8_t *) wmi_buf_data(buf);
5139 qdf_mem_zero(p, len);
5140 p_rmc_cmd = (wmi_rmc_set_action_period_cmd_fixed_param *) p;
5141
5142 WMITLV_SET_HDR(&p_rmc_cmd->tlv_header,
5143 WMITLV_TAG_STRUC_wmi_rmc_set_action_period_cmd_fixed_param,
5144 WMITLV_GET_STRUCT_TLVLEN
5145 (wmi_rmc_set_action_period_cmd_fixed_param));
5146
5147 if (wlan_cfg_get_int(mac, WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY, &val)
5148 != eSIR_SUCCESS) {
5149 WMA_LOGE("Failed to get value for RMC action period using default");
5150 val = WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_STADEF;
5151 }
5152
5153 p_rmc_cmd->vdev_id = vdev_id;
5154 p_rmc_cmd->periodicity_msec = val;
5155
5156 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
5157 WMI_RMC_SET_ACTION_PERIOD_CMDID);
5158
5159 WMA_LOGE("RMC action period %d cmd sent len: %d, vdev %d"
5160 " command id: %d, status: %d", p_rmc_cmd->periodicity_msec,
5161 len, p_rmc_cmd->vdev_id, WMI_RMC_SET_ACTION_PERIOD_CMDID, ret);
5162
5163 return QDF_STATUS_SUCCESS;
5164}
5165
5166/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005167 * wma_process_add_periodic_tx_ptrn_ind - add periodic tx ptrn
5168 * @handle: wma handle
5169 * @pAddPeriodicTxPtrnParams: tx ptrn params
5170 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305171 * Retrun: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005172 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305173QDF_STATUS wma_process_add_periodic_tx_ptrn_ind(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005174 tSirAddPeriodicTxPtrn *
5175 pAddPeriodicTxPtrnParams)
5176{
5177 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Himanshu Agarwal44195412016-03-09 13:03:54 +05305178 struct periodic_tx_pattern params;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005179 uint8_t vdev_id;
Himanshu Agarwal44195412016-03-09 13:03:54 +05305180
5181 qdf_mem_set(&params, sizeof(struct periodic_tx_pattern), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005182
5183 if (!wma_handle || !wma_handle->wmi_handle) {
5184 WMA_LOGE("%s: WMA is closed, can not issue fw add pattern cmd",
5185 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305186 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005187 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005188
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005189 if (!wma_find_vdev_by_addr(wma_handle,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005190 pAddPeriodicTxPtrnParams->mac_address.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005191 &vdev_id)) {
5192 WMA_LOGE("%s: Failed to find vdev id for %pM", __func__,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005193 pAddPeriodicTxPtrnParams->mac_address.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305194 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005195 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005196
Himanshu Agarwal44195412016-03-09 13:03:54 +05305197 params.ucPtrnId = pAddPeriodicTxPtrnParams->ucPtrnId;
5198 params.ucPtrnSize = pAddPeriodicTxPtrnParams->ucPtrnSize;
5199 params.usPtrnIntervalMs = pAddPeriodicTxPtrnParams->usPtrnIntervalMs;
5200 qdf_mem_copy(&params.mac_address,
5201 &pAddPeriodicTxPtrnParams->mac_address,
5202 sizeof(struct qdf_mac_addr));
5203 qdf_mem_copy(params.ucPattern, pAddPeriodicTxPtrnParams->ucPattern,
5204 params.ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005205
Himanshu Agarwal44195412016-03-09 13:03:54 +05305206 return wmi_unified_process_add_periodic_tx_ptrn_cmd(
5207 wma_handle->wmi_handle, &params, vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005208}
5209
5210/**
5211 * wma_process_del_periodic_tx_ptrn_ind - del periodic tx ptrn
5212 * @handle: wma handle
5213 * @pDelPeriodicTxPtrnParams: tx ptrn params
5214 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305215 * Retrun: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005216 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305217QDF_STATUS wma_process_del_periodic_tx_ptrn_ind(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005218 tSirDelPeriodicTxPtrn *
5219 pDelPeriodicTxPtrnParams)
5220{
5221 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005222 uint8_t vdev_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005223
5224 if (!wma_handle || !wma_handle->wmi_handle) {
5225 WMA_LOGE("%s: WMA is closed, can not issue Del Pattern cmd",
5226 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305227 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005228 }
Himanshu Agarwal44195412016-03-09 13:03:54 +05305229
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005230 if (!wma_find_vdev_by_addr(wma_handle,
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08005231 pDelPeriodicTxPtrnParams->mac_address.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005232 &vdev_id)) {
5233 WMA_LOGE("%s: Failed to find vdev id for %pM", __func__,
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08005234 pDelPeriodicTxPtrnParams->mac_address.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305235 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005236 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005237
Himanshu Agarwal44195412016-03-09 13:03:54 +05305238 return wmi_unified_process_del_periodic_tx_ptrn_cmd(
5239 wma_handle->wmi_handle, vdev_id,
5240 pDelPeriodicTxPtrnParams->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005241}
5242
5243#ifdef WLAN_FEATURE_STATS_EXT
5244/**
5245 * wma_stats_ext_req() - request ext stats from fw
5246 * @wma_ptr: wma handle
5247 * @preq: stats ext params
5248 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305249 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005250 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305251QDF_STATUS wma_stats_ext_req(void *wma_ptr, tpStatsExtRequest preq)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005252{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005253 tp_wma_handle wma = (tp_wma_handle) wma_ptr;
Krishna Kumaar Natarajan1b909d72016-06-06 15:02:18 -07005254 struct stats_ext_params *params;
5255 size_t params_len;
5256 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005257
Himanshu Agarwal44195412016-03-09 13:03:54 +05305258 if (!wma) {
5259 WMA_LOGE("%s: wma handle is NULL", __func__);
5260 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005261 }
5262
Krishna Kumaar Natarajan1b909d72016-06-06 15:02:18 -07005263 params_len = sizeof(*params) + preq->request_data_len;
5264 params = qdf_mem_malloc(params_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005265
Krishna Kumaar Natarajan1b909d72016-06-06 15:02:18 -07005266 if (params == NULL) {
5267 WMA_LOGE(FL("memory allocation failed"));
5268 return QDF_STATUS_E_NOMEM;
5269 }
5270
5271 params->vdev_id = preq->vdev_id;
5272 params->request_data_len = preq->request_data_len;
5273 if (preq->request_data_len > 0)
5274 qdf_mem_copy(params->request_data, preq->request_data,
5275 params->request_data_len);
5276
5277 status = wmi_unified_stats_ext_req_cmd(wma->wmi_handle, params);
5278 qdf_mem_free(params);
5279
5280 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005281}
5282
5283#endif /* WLAN_FEATURE_STATS_EXT */
5284
5285#ifdef WLAN_FEATURE_EXTWOW_SUPPORT
5286/**
5287 * wma_send_status_of_ext_wow() - send ext wow status to SME
5288 * @wma: wma handle
5289 * @status: status
5290 *
5291 * Return: none
5292 */
5293static void wma_send_status_of_ext_wow(tp_wma_handle wma, bool status)
5294{
5295 tSirReadyToExtWoWInd *ready_to_extwow;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305296 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005297 cds_msg_t cds_msg;
5298 uint8_t len;
5299
5300 WMA_LOGD("Posting ready to suspend indication to umac");
5301
5302 len = sizeof(tSirReadyToExtWoWInd);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305303 ready_to_extwow = (tSirReadyToExtWoWInd *) qdf_mem_malloc(len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005304
5305 if (NULL == ready_to_extwow) {
5306 WMA_LOGE("%s: Memory allocation failure", __func__);
5307 return;
5308 }
5309
5310 ready_to_extwow->mesgType = eWNI_SME_READY_TO_EXTWOW_IND;
5311 ready_to_extwow->mesgLen = len;
5312 ready_to_extwow->status = status;
5313
5314 cds_msg.type = eWNI_SME_READY_TO_EXTWOW_IND;
5315 cds_msg.bodyptr = (void *)ready_to_extwow;
5316 cds_msg.bodyval = 0;
5317
5318 vstatus = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305319 if (vstatus != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005320 WMA_LOGE("Failed to post ready to suspend");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305321 qdf_mem_free(ready_to_extwow);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005322 }
5323}
5324
5325/**
5326 * wma_enable_ext_wow() - enable ext wow in fw
5327 * @wma: wma handle
5328 * @params: ext wow params
5329 *
5330 * Return:0 for success or error code
5331 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05305332QDF_STATUS wma_enable_ext_wow(tp_wma_handle wma, tpSirExtWoWParams params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005333{
Himanshu Agarwal44195412016-03-09 13:03:54 +05305334 struct ext_wow_params wow_params = {0};
5335 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005336
Himanshu Agarwal44195412016-03-09 13:03:54 +05305337 if (!wma) {
5338 WMA_LOGE("%s: wma handle is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305339 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005340 }
5341
Himanshu Agarwal44195412016-03-09 13:03:54 +05305342 wow_params.vdev_id = params->vdev_id;
5343 wow_params.type = (enum wmi_ext_wow_type) params->type;
5344 wow_params.wakeup_pin_num = params->wakeup_pin_num;
5345
5346 status = wmi_unified_enable_ext_wow_cmd(wma->wmi_handle,
5347 &wow_params);
5348 if (QDF_IS_STATUS_ERROR(status))
5349 return status;
5350
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005351 wma_send_status_of_ext_wow(wma, true);
Himanshu Agarwal44195412016-03-09 13:03:54 +05305352 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005353
5354}
5355
5356/**
5357 * wma_set_app_type1_params_in_fw() - set app type1 params in fw
5358 * @wma: wma handle
5359 * @appType1Params: app type1 params
5360 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305361 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005362 */
5363int wma_set_app_type1_params_in_fw(tp_wma_handle wma,
5364 tpSirAppType1Params appType1Params)
5365{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005366 int ret;
5367
Govind Singhaa64c242016-03-08 11:31:49 +05305368 ret = wmi_unified_app_type1_params_in_fw_cmd(wma->wmi_handle,
5369 (struct app_type1_params *)appType1Params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005370 if (ret) {
5371 WMA_LOGE("%s: Failed to set APP TYPE1 PARAMS", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305372 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005373 }
5374
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305375 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005376}
5377
5378/**
5379 * wma_set_app_type2_params_in_fw() - set app type2 params in fw
5380 * @wma: wma handle
5381 * @appType2Params: app type2 params
5382 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305383 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005384 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05305385QDF_STATUS wma_set_app_type2_params_in_fw(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005386 tpSirAppType2Params appType2Params)
5387{
Himanshu Agarwal44195412016-03-09 13:03:54 +05305388 struct app_type2_params params = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005389
Himanshu Agarwal44195412016-03-09 13:03:54 +05305390 if (!wma) {
5391 WMA_LOGE("%s: wma handle is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305392 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005393 }
5394
Himanshu Agarwal44195412016-03-09 13:03:54 +05305395 params.vdev_id = appType2Params->vdev_id;
5396 params.rc4_key_len = appType2Params->rc4_key_len;
5397 qdf_mem_copy(params.rc4_key, appType2Params->rc4_key, 16);
5398 params.ip_id = appType2Params->ip_id;
5399 params.ip_device_ip = appType2Params->ip_device_ip;
5400 params.ip_server_ip = appType2Params->ip_server_ip;
5401 params.tcp_src_port = appType2Params->tcp_src_port;
5402 params.tcp_dst_port = appType2Params->tcp_dst_port;
5403 params.tcp_seq = appType2Params->tcp_seq;
5404 params.tcp_ack_seq = appType2Params->tcp_ack_seq;
5405 params.keepalive_init = appType2Params->keepalive_init;
5406 params.keepalive_min = appType2Params->keepalive_min;
5407 params.keepalive_max = appType2Params->keepalive_max;
5408 params.keepalive_inc = appType2Params->keepalive_inc;
5409 params.tcp_tx_timeout_val = appType2Params->tcp_tx_timeout_val;
5410 params.tcp_rx_timeout_val = appType2Params->tcp_rx_timeout_val;
5411 qdf_mem_copy(&params.gateway_mac, &appType2Params->gateway_mac,
5412 sizeof(struct qdf_mac_addr));
5413
5414 return wmi_unified_set_app_type2_params_in_fw_cmd(wma->wmi_handle,
5415 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005416
5417}
5418#endif /* WLAN_FEATURE_EXTWOW_SUPPORT */
5419
5420#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
5421/**
5422 * wma_auto_shutdown_event_handler() - process auto shutdown timer trigger
5423 * @handle: wma handle
5424 * @event: event buffer
5425 * @len: buffer length
5426 *
5427 * Return: 0 for success or error code
5428 */
5429int wma_auto_shutdown_event_handler(void *handle, uint8_t *event,
5430 uint32_t len)
5431{
5432 wmi_host_auto_shutdown_event_fixed_param *wmi_auto_sh_evt;
5433 WMI_HOST_AUTO_SHUTDOWN_EVENTID_param_tlvs *param_buf =
5434 (WMI_HOST_AUTO_SHUTDOWN_EVENTID_param_tlvs *)
5435 event;
5436
5437 if (!param_buf || !param_buf->fixed_param) {
5438 WMA_LOGE("%s:%d: Invalid Auto shutdown timer evt", __func__,
5439 __LINE__);
5440 return -EINVAL;
5441 }
5442
5443 wmi_auto_sh_evt = param_buf->fixed_param;
5444
5445 if (wmi_auto_sh_evt->shutdown_reason
5446 != WMI_HOST_AUTO_SHUTDOWN_REASON_TIMER_EXPIRY) {
5447 WMA_LOGE("%s:%d: Invalid Auto shutdown timer evt", __func__,
5448 __LINE__);
5449 return -EINVAL;
5450 }
5451
5452 WMA_LOGD("%s:%d: Auto Shutdown Evt: %d", __func__, __LINE__,
5453 wmi_auto_sh_evt->shutdown_reason);
5454 return wma_post_auto_shutdown_msg();
5455}
5456
5457/**
5458 * wma_set_auto_shutdown_timer_req() - sets auto shutdown timer in firmware
5459 * @wma: wma handle
5460 * @auto_sh_cmd: auto shutdown timer value
5461 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305462 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005463 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305464QDF_STATUS wma_set_auto_shutdown_timer_req(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005465 tSirAutoShutdownCmdParams *
5466 auto_sh_cmd)
5467{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005468 if (auto_sh_cmd == NULL) {
5469 WMA_LOGE("%s : Invalid Autoshutdown cfg cmd", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305470 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005471 }
5472
Himanshu Agarwal44195412016-03-09 13:03:54 +05305473 return wmi_unified_set_auto_shutdown_timer_cmd(wma_handle->wmi_handle,
5474 auto_sh_cmd->timer_val);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005475}
5476#endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
5477
5478#ifdef WLAN_FEATURE_NAN
5479/**
5480 * wma_nan_req() - to send nan request to target
5481 * @wma: wma_handle
5482 * @nan_req: request data which will be non-null
5483 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305484 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005485 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305486QDF_STATUS wma_nan_req(void *wma_ptr, tpNanRequest nan_req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005487{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005488 tp_wma_handle wma_handle = (tp_wma_handle) wma_ptr;
Krishna Kumaar Natarajan1b909d72016-06-06 15:02:18 -07005489 struct nan_req_params *params;
5490 size_t params_len;
5491 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005492
Himanshu Agarwal44195412016-03-09 13:03:54 +05305493 if (!wma_handle) {
5494 WMA_LOGE("%s: wma handle is NULL", __func__);
5495 return QDF_STATUS_E_FAILURE;
5496 }
Krishna Kumaar Natarajan1b909d72016-06-06 15:02:18 -07005497
5498 params_len = sizeof(*params) + nan_req->request_data_len;
5499 params = qdf_mem_malloc(params_len);
5500
5501 if (params == NULL) {
5502 WMA_LOGE(FL("memory allocation failed"));
5503 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005504 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005505
Krishna Kumaar Natarajan1b909d72016-06-06 15:02:18 -07005506 params->request_data_len = nan_req->request_data_len;
5507 if (params->request_data_len > 0)
5508 qdf_mem_copy(params->request_data, nan_req->request_data,
5509 params->request_data_len);
Himanshu Agarwal44195412016-03-09 13:03:54 +05305510
Krishna Kumaar Natarajan1b909d72016-06-06 15:02:18 -07005511 status = wmi_unified_nan_req_cmd(wma_handle->wmi_handle, params);
5512 qdf_mem_free(params);
5513
5514 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005515}
5516#endif /* WLAN_FEATURE_NAN */
5517
5518#ifdef DHCP_SERVER_OFFLOAD
5519/**
5520 * wma_process_dhcpserver_offload() - enable DHCP server offload
5521 * @wma_handle: wma handle
5522 * @pDhcpSrvOffloadInfo: DHCP server offload info
5523 *
5524 * Return: 0 for success or error code
5525 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05305526QDF_STATUS wma_process_dhcpserver_offload(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005527 tSirDhcpSrvOffloadInfo *
5528 pDhcpSrvOffloadInfo)
5529{
Himanshu Agarwal44195412016-03-09 13:03:54 +05305530 struct dhcp_offload_info_params params = {0};
5531 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005532
Himanshu Agarwal44195412016-03-09 13:03:54 +05305533 if (!wma_handle) {
5534 WMA_LOGE("%s: wma handle is NULL", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005535 return -EIO;
5536 }
Himanshu Agarwal44195412016-03-09 13:03:54 +05305537
5538 params.vdev_id = pDhcpSrvOffloadInfo->vdev_id;
5539 params.dhcpSrvOffloadEnabled =
5540 pDhcpSrvOffloadInfo->dhcpSrvOffloadEnabled;
5541 params.dhcpClientNum = pDhcpSrvOffloadInfo->dhcpClientNum;
5542 params.dhcpSrvIP = pDhcpSrvOffloadInfo->;
5543
5544 status = wmi_unified_process_dhcpserver_offload_cmd(
5545 wma_handle->wmi_handle, &params);
5546 if (QDF_IS_STATUS_ERROR(status))
5547 return status;
5548
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005549 WMA_LOGD("Set dhcp server offload to vdevId %d",
5550 pDhcpSrvOffloadInfo->vdev_id);
Himanshu Agarwal44195412016-03-09 13:03:54 +05305551 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005552}
5553#endif /* DHCP_SERVER_OFFLOAD */
5554
5555#ifdef WLAN_FEATURE_GPIO_LED_FLASHING
5556/**
5557 * wma_set_led_flashing() - set led flashing in fw
5558 * @wma_handle: wma handle
5559 * @flashing: flashing request
5560 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305561 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005562 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305563QDF_STATUS wma_set_led_flashing(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005564 tSirLedFlashingReq *flashing)
5565{
Govind Singhaa64c242016-03-08 11:31:49 +05305566 struct flashing_req_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005567
5568 if (!wma_handle || !wma_handle->wmi_handle) {
5569 WMA_LOGE(FL("WMA is closed, can not issue cmd"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305570 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005571 }
5572 if (!flashing) {
5573 WMA_LOGE(FL("invalid parameter: flashing"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305574 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005575 }
Govind Singhaa64c242016-03-08 11:31:49 +05305576 cmd.req_id = flashing->reqId;
5577 cmd.pattern_id = flashing->pattern_id;
5578 cmd.led_x0 = flashing->led_x0;
5579 cmd.led_x1 = flashing->led_x1;
5580 status = wmi_unified_set_led_flashing_cmd(wma_handle->wmi_handle,
5581 &cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005582 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305583 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005584 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305585 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005586}
5587#endif /* WLAN_FEATURE_GPIO_LED_FLASHING */
5588
5589#ifdef FEATURE_WLAN_CH_AVOID
5590/**
5591 * wma_channel_avoid_evt_handler() - process channel to avoid event from FW.
5592 * @handle: wma handle
5593 * @event: event buffer
5594 * @len: buffer length
5595 *
5596 * Return: 0 for success or error code
5597 */
5598int wma_channel_avoid_evt_handler(void *handle, uint8_t *event,
5599 uint32_t len)
5600{
5601 wmi_avoid_freq_ranges_event_fixed_param *afr_fixed_param;
5602 wmi_avoid_freq_range_desc *afr_desc;
5603 uint32_t num_freq_ranges, freq_range_idx;
5604 tSirChAvoidIndType *sca_indication;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305605 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005606 cds_msg_t sme_msg = { 0 };
5607 WMI_WLAN_FREQ_AVOID_EVENTID_param_tlvs *param_buf =
5608 (WMI_WLAN_FREQ_AVOID_EVENTID_param_tlvs *) event;
5609
5610 if (!param_buf) {
5611 WMA_LOGE("Invalid channel avoid event buffer");
5612 return -EINVAL;
5613 }
5614
5615 afr_fixed_param = param_buf->fixed_param;
5616 if (!afr_fixed_param) {
5617 WMA_LOGE("Invalid channel avoid event fixed param buffer");
5618 return -EINVAL;
5619 }
5620
5621 num_freq_ranges =
5622 (afr_fixed_param->num_freq_ranges >
5623 SIR_CH_AVOID_MAX_RANGE) ? SIR_CH_AVOID_MAX_RANGE :
5624 afr_fixed_param->num_freq_ranges;
5625
5626 WMA_LOGD("Channel avoid event received with %d ranges",
5627 num_freq_ranges);
5628 for (freq_range_idx = 0; freq_range_idx < num_freq_ranges;
5629 freq_range_idx++) {
5630 afr_desc = (wmi_avoid_freq_range_desc *)
5631 ((void *)param_buf->avd_freq_range +
5632 freq_range_idx * sizeof(wmi_avoid_freq_range_desc));
5633
5634 WMA_LOGD("range %d: tlv id = %u, start freq = %u, end freq = %u",
5635 freq_range_idx, afr_desc->tlv_header, afr_desc->start_freq,
5636 afr_desc->end_freq);
5637 }
5638
5639 sca_indication = (tSirChAvoidIndType *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305640 qdf_mem_malloc(sizeof(tSirChAvoidIndType));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005641 if (!sca_indication) {
5642 WMA_LOGE("Invalid channel avoid indication buffer");
5643 return -EINVAL;
5644 }
5645
5646 sca_indication->avoid_range_count = num_freq_ranges;
5647 for (freq_range_idx = 0; freq_range_idx < num_freq_ranges;
5648 freq_range_idx++) {
5649 afr_desc = (wmi_avoid_freq_range_desc *)
5650 ((void *)param_buf->avd_freq_range +
5651 freq_range_idx * sizeof(wmi_avoid_freq_range_desc));
5652 sca_indication->avoid_freq_range[freq_range_idx].start_freq =
5653 afr_desc->start_freq;
5654 sca_indication->avoid_freq_range[freq_range_idx].end_freq =
5655 afr_desc->end_freq;
5656 }
5657
5658 sme_msg.type = eWNI_SME_CH_AVOID_IND;
5659 sme_msg.bodyptr = sca_indication;
5660 sme_msg.bodyval = 0;
5661
Anurag Chouhan6d760662016-02-20 16:05:43 +05305662 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305663 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005664 WMA_LOGE("Fail to post eWNI_SME_CH_AVOID_IND msg to SME");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305665 qdf_mem_free(sca_indication);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005666 return -EINVAL;
5667 }
5668
5669 return 0;
5670}
5671
5672/**
5673 * wma_process_ch_avoid_update_req() - handles channel avoid update request
5674 * @wma_handle: wma handle
5675 * @ch_avoid_update_req: channel avoid update params
5676 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305677 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005678 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305679QDF_STATUS wma_process_ch_avoid_update_req(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005680 tSirChAvoidUpdateReq *
5681 ch_avoid_update_req)
5682{
Himanshu Agarwal44195412016-03-09 13:03:54 +05305683 QDF_STATUS status;
5684 if (!wma_handle) {
5685 WMA_LOGE("%s: wma handle is NULL", __func__);
5686 return QDF_STATUS_E_FAILURE;
5687 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005688 if (ch_avoid_update_req == NULL) {
5689 WMA_LOGE("%s : ch_avoid_update_req is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305690 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005691 }
5692
5693 WMA_LOGI("%s: WMA --> WMI_CHAN_AVOID_UPDATE", __func__);
5694
Himanshu Agarwal44195412016-03-09 13:03:54 +05305695 status = wmi_unified_process_ch_avoid_update_cmd(
5696 wma_handle->wmi_handle);
5697 if (QDF_IS_STATUS_ERROR(status))
5698 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005699
5700 WMA_LOGI("%s: WMA --> WMI_CHAN_AVOID_UPDATE sent through WMI",
5701 __func__);
Himanshu Agarwal44195412016-03-09 13:03:54 +05305702 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005703}
5704#endif /* FEATURE_WLAN_CH_AVOID */
5705
5706/**
5707 * wma_set_reg_domain() - set reg domain
5708 * @clientCtxt: client context
5709 * @regId: reg id
5710 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305711 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005712 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305713QDF_STATUS wma_set_reg_domain(void *clientCtxt, v_REGDOMAIN_t regId)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005714{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305715 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005716 cds_set_reg_domain(clientCtxt, regId))
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305717 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005718
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305719 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005720}
5721
5722/**
5723 * wma_send_regdomain_info_to_fw() - send regdomain info to fw
5724 * @reg_dmn: reg domain
5725 * @regdmn2G: 2G reg domain
5726 * @regdmn5G: 5G reg domain
5727 * @ctl2G: 2G test limit
5728 * @ctl5G: 5G test limit
5729 *
5730 * Return: none
5731 */
5732void wma_send_regdomain_info_to_fw(uint32_t reg_dmn, uint16_t regdmn2G,
5733 uint16_t regdmn5G, int8_t ctl2G,
5734 int8_t ctl5G)
5735{
Anurag Chouhan6d760662016-02-20 16:05:43 +05305736 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005737 int32_t cck_mask_val = 0;
Govind Singhd76a5b02016-03-08 15:12:14 +05305738 struct pdev_params pdev_param = {0};
Himanshu Agarwal44195412016-03-09 13:03:54 +05305739 QDF_STATUS ret = QDF_STATUS_SUCCESS;
5740 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005741
5742 if (NULL == wma) {
5743 WMA_LOGE("%s: wma context is NULL", __func__);
5744 return;
5745 }
5746
Himanshu Agarwal44195412016-03-09 13:03:54 +05305747 status = wmi_unified_send_regdomain_info_to_fw_cmd(wma->wmi_handle,
5748 reg_dmn, regdmn2G, regdmn5G, ctl2G, ctl5G);
5749 if (status == QDF_STATUS_E_NOMEM)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005750 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005751
Amar Singhal76b41322015-12-09 14:39:17 -08005752 if ((((reg_dmn & ~COUNTRY_ERD_FLAG) == CTRY_JAPAN14) ||
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005753 ((reg_dmn & ~COUNTRY_ERD_FLAG) == CTRY_KOREA_ROC)) &&
5754 (true == wma->tx_chain_mask_cck))
5755 cck_mask_val = 1;
5756
5757 cck_mask_val |= (wma->self_gen_frm_pwr << 16);
Govind Singhd76a5b02016-03-08 15:12:14 +05305758 pdev_param.param_id = WMI_PDEV_PARAM_TX_CHAIN_MASK_CCK;
5759 pdev_param.param_value = cck_mask_val;
5760 ret = wmi_unified_pdev_param_send(wma->wmi_handle,
5761 &pdev_param,
5762 WMA_WILDCARD_PDEV_ID);
5763
Himanshu Agarwal44195412016-03-09 13:03:54 +05305764 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005765 WMA_LOGE("failed to set PDEV tx_chain_mask_cck %d",
5766 ret);
5767
5768 return;
5769}
5770
5771/**
Houston Hoffmana76591b2015-11-10 16:52:05 -08005772 * wma_post_runtime_resume_msg() - post the resume request
5773 * @handle: validated wma handle
5774 *
5775 * request the MC thread unpaus the vdev and set resume dtim
5776 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305777 * Return: qdf status of the mq post
Houston Hoffmana76591b2015-11-10 16:52:05 -08005778 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305779static QDF_STATUS wma_post_runtime_resume_msg(WMA_HANDLE handle)
Houston Hoffmana76591b2015-11-10 16:52:05 -08005780{
5781 cds_msg_t resume_msg;
Houston Hoffmanc45db892015-11-13 19:59:25 -08005782 QDF_STATUS status;
5783 tp_wma_handle wma = (tp_wma_handle) handle;
5784
5785 qdf_runtime_pm_prevent_suspend(wma->wma_runtime_resume_lock);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005786
5787 resume_msg.bodyptr = NULL;
5788 resume_msg.type = WMA_RUNTIME_PM_RESUME_IND;
Houston Hoffmanc45db892015-11-13 19:59:25 -08005789
5790 status = cds_mq_post_message(QDF_MODULE_ID_WMA, &resume_msg);
5791
5792 if (!QDF_IS_STATUS_SUCCESS(status)) {
5793 WMA_LOGE("Failed to post Runtime PM Resume IND to VOS");
5794 qdf_runtime_pm_allow_suspend(wma->wma_runtime_resume_lock);
5795 }
5796
5797 return status;
Houston Hoffmana76591b2015-11-10 16:52:05 -08005798}
5799
5800/**
5801 * wma_post_runtime_suspend_msg() - post the suspend request
5802 * @handle: validated wma handle
5803 *
5804 * Requests for offloads to be configured for runtime suspend
5805 * on the MC thread
5806 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305807 * Return QDF_STATUS_E_AGAIN in case of timeout or QDF_STATUS_SUCCESS
Houston Hoffmana76591b2015-11-10 16:52:05 -08005808 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305809static QDF_STATUS wma_post_runtime_suspend_msg(WMA_HANDLE handle)
Houston Hoffmana76591b2015-11-10 16:52:05 -08005810{
5811 cds_msg_t cds_msg;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305812 QDF_STATUS qdf_status;
Houston Hoffmana76591b2015-11-10 16:52:05 -08005813 tp_wma_handle wma = (tp_wma_handle) handle;
5814
Anurag Chouhance0dc992016-02-16 18:18:03 +05305815 qdf_event_reset(&wma->runtime_suspend);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005816
5817 cds_msg.bodyptr = NULL;
5818 cds_msg.type = WMA_RUNTIME_PM_SUSPEND_IND;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305819 qdf_status = cds_mq_post_message(QDF_MODULE_ID_WMA, &cds_msg);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005820
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305821 if (qdf_status != QDF_STATUS_SUCCESS)
Houston Hoffmana76591b2015-11-10 16:52:05 -08005822 goto failure;
5823
Anurag Chouhance0dc992016-02-16 18:18:03 +05305824 if (qdf_wait_single_event(&wma->runtime_suspend,
Houston Hoffmana76591b2015-11-10 16:52:05 -08005825 WMA_TGT_SUSPEND_COMPLETE_TIMEOUT) !=
Anurag Chouhance0dc992016-02-16 18:18:03 +05305826 QDF_STATUS_SUCCESS) {
Houston Hoffmana76591b2015-11-10 16:52:05 -08005827 WMA_LOGE("Failed to get runtime suspend event");
Houston Hoffmanc45db892015-11-13 19:59:25 -08005828 goto msg_timed_out;
Houston Hoffmana76591b2015-11-10 16:52:05 -08005829 }
5830
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305831 return QDF_STATUS_SUCCESS;
Houston Hoffmana76591b2015-11-10 16:52:05 -08005832
Houston Hoffmanc45db892015-11-13 19:59:25 -08005833msg_timed_out:
5834 wma_post_runtime_resume_msg(wma);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005835failure:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305836 return QDF_STATUS_E_AGAIN;
Houston Hoffmana76591b2015-11-10 16:52:05 -08005837}
5838
5839/**
5840 * __wma_bus_suspend(): handles bus suspend for wma
5841 * @type: is this suspend part of runtime suspend or system suspend?
5842 *
5843 * Bails if a scan is in progress.
5844 * Calls the appropriate handlers based on configuration and event.
5845 *
5846 * Return: 0 for success or error code
5847 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05305848static int __wma_bus_suspend(enum qdf_suspend_type type)
Houston Hoffmana76591b2015-11-10 16:52:05 -08005849{
Anurag Chouhan6d760662016-02-20 16:05:43 +05305850 WMA_HANDLE handle = cds_get_context(QDF_MODULE_ID_WMA);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005851 if (NULL == handle) {
5852 WMA_LOGE("%s: wma context is NULL", __func__);
5853 return -EFAULT;
5854 }
5855
5856 if (wma_check_scan_in_progress(handle)) {
5857 WMA_LOGE("%s: Scan in progress. Aborting suspend", __func__);
5858 return -EBUSY;
5859 }
5860
Anurag Chouhan6d760662016-02-20 16:05:43 +05305861 if (type == QDF_RUNTIME_SUSPEND) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305862 QDF_STATUS status = wma_post_runtime_suspend_msg(handle);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005863 if (status)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305864 return qdf_status_to_os_return(status);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005865 }
5866
Anurag Chouhan6d760662016-02-20 16:05:43 +05305867 if (type == QDF_SYSTEM_SUSPEND)
Houston Hoffmana76591b2015-11-10 16:52:05 -08005868 WMA_LOGE("%s: wow mode selected %d", __func__,
5869 wma_is_wow_mode_selected(handle));
5870
5871 if (wma_is_wow_mode_selected(handle)) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305872 QDF_STATUS status = wma_enable_wow_in_fw(handle);
5873 return qdf_status_to_os_return(status);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005874 }
5875
5876 return wma_suspend_target(handle, 0);
5877}
5878
5879/**
5880 * wma_runtime_suspend() - handles runtime suspend request from hdd
5881 *
5882 * Calls the appropriate handler based on configuration and event.
5883 * Last busy marking should prevent race conditions between processing
5884 * of asyncronous fw events and the running of runtime suspend.
5885 * (eg. last busy marking should guarantee that any auth requests have
5886 * been processed)
5887 * Events comming from the host are not protected, but aren't expected
5888 * to be an issue.
5889 *
5890 * Return: 0 for success or error code
5891 */
5892int wma_runtime_suspend(void)
5893{
Anurag Chouhan6d760662016-02-20 16:05:43 +05305894 return __wma_bus_suspend(QDF_RUNTIME_SUSPEND);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005895}
5896
5897/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005898 * wma_bus_suspend() - handles bus suspend request from hdd
5899 *
5900 * Calls the appropriate handler based on configuration and event
5901 *
5902 * Return: 0 for success or error code
5903 */
5904int wma_bus_suspend(void)
5905{
Houston Hoffmana76591b2015-11-10 16:52:05 -08005906
Anurag Chouhan6d760662016-02-20 16:05:43 +05305907 return __wma_bus_suspend(QDF_SYSTEM_SUSPEND);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005908}
5909
5910/**
5911 * __wma_bus_resume() - bus resume for wma
5912 *
5913 * does the part of the bus resume common to bus and system suspend
5914 *
5915 * Return: os error code.
5916 */
5917int __wma_bus_resume(WMA_HANDLE handle)
5918{
5919 bool wow_mode = wma_is_wow_mode_selected(handle);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305920 QDF_STATUS status;
Houston Hoffmana76591b2015-11-10 16:52:05 -08005921
5922 WMA_LOGE("%s: wow mode %d", __func__, wow_mode);
5923
5924 if (!wow_mode)
Rajeev Kumar9be537e2016-04-25 17:35:33 -07005925 return qdf_status_to_os_return(wma_resume_target(handle));
Houston Hoffmana76591b2015-11-10 16:52:05 -08005926
5927 status = wma_disable_wow_in_fw(handle);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305928 return qdf_status_to_os_return(status);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005929}
5930
5931/**
5932 * wma_runtime_resume() - do the runtime resume operation for wma
5933 *
5934 * Return: os error code.
5935 */
5936int wma_runtime_resume(void)
5937{
5938 int ret;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305939 QDF_STATUS status;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305940 WMA_HANDLE handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005941 if (NULL == handle) {
5942 WMA_LOGE("%s: wma context is NULL", __func__);
5943 return -EFAULT;
5944 }
5945
Houston Hoffmana76591b2015-11-10 16:52:05 -08005946 ret = __wma_bus_resume(handle);
5947 if (ret)
5948 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005949
Houston Hoffmana76591b2015-11-10 16:52:05 -08005950 status = wma_post_runtime_resume_msg(handle);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305951 return qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005952}
5953
5954/**
5955 * wma_bus_resume() - handles bus resume request from hdd
5956 * @handle: valid wma handle
5957 *
5958 * Calls the appropriate handler based on configuration
5959 *
5960 * Return: 0 for success or error code
5961 */
5962int wma_bus_resume(void)
5963{
Anurag Chouhan6d760662016-02-20 16:05:43 +05305964 WMA_HANDLE handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005965 if (NULL == handle) {
5966 WMA_LOGE("%s: wma context is NULL", __func__);
5967 return -EFAULT;
5968 }
5969
Houston Hoffmana76591b2015-11-10 16:52:05 -08005970 return __wma_bus_resume(handle);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005971}
5972
5973/**
Manjunathappa Prakash7b67e622016-04-12 15:18:45 +05305974 * wma_suspend_target_timeout() - Handles the target suspend timeout
5975 * @is_self_recovery_enabled: Is self recovery enabled or not
5976 *
5977 * Return: NONE
5978 */
5979#ifdef QCA_WIFI_3_0_ADRASTEA
5980static inline void wma_suspend_target_timeout(bool is_self_recovery_enabled)
5981{
5982 if (cds_is_driver_recovering()) {
5983 WMA_LOGE("%s: recovery is in progress, ignore!", __func__);
5984 } else {
5985 if (is_self_recovery_enabled) {
5986 cds_trigger_recovery();
5987 } else {
5988 QDF_BUG(0);
5989 }
5990 }
5991}
5992#else /* ROME chipset */
5993static inline void wma_suspend_target_timeout(bool is_self_recovery_enabled)
5994{
5995 if (cds_is_load_or_unload_in_progress() || cds_is_driver_recovering()) {
5996 WMA_LOGE("%s: Unloading/Loading/recovery is in progress, Ignore!",
5997 __func__);
5998 } else {
5999 if (is_self_recovery_enabled) {
6000 cds_trigger_recovery();
6001 } else {
6002 QDF_BUG(0);
6003 }
6004 }
6005}
6006#endif
6007
6008/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006009 * wma_suspend_target() - suspend target
6010 * @handle: wma handle
6011 * @disable_target_intr: disable target interrupt
6012 *
Govind Singhd76a5b02016-03-08 15:12:14 +05306013 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006014 */
Govind Singhd76a5b02016-03-08 15:12:14 +05306015QDF_STATUS wma_suspend_target(WMA_HANDLE handle, int disable_target_intr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006016{
6017 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Komal Seelam3d202862016-02-24 18:43:24 +05306018 struct hif_opaque_softc *scn;
Govind Singhd76a5b02016-03-08 15:12:14 +05306019 QDF_STATUS status;
6020 struct suspend_params param = {0};
6021
Anurag Chouhan6d760662016-02-20 16:05:43 +05306022 tpAniSirGlobal pmac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006023
6024 if (!wma_handle || !wma_handle->wmi_handle) {
6025 WMA_LOGE("WMA is closed. can not issue suspend cmd");
Govind Singhd76a5b02016-03-08 15:12:14 +05306026 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006027 }
Yue Mae1a85f32015-10-20 18:12:45 -07006028
Yue Mae1a85f32015-10-20 18:12:45 -07006029 if (NULL == pmac) {
6030 WMA_LOGE("%s: Unable to get PE context", __func__);
Govind Singhd76a5b02016-03-08 15:12:14 +05306031 return QDF_STATUS_E_INVAL;
Yue Mae1a85f32015-10-20 18:12:45 -07006032 }
Houston Hoffman52ec6692016-04-21 16:36:45 -07006033
Anurag Chouhance0dc992016-02-16 18:18:03 +05306034 qdf_event_reset(&wma_handle->target_suspend);
Govind Singhd76a5b02016-03-08 15:12:14 +05306035 param.disable_target_intr = disable_target_intr;
6036 status = wmi_unified_suspend_send(wma_handle->wmi_handle,
6037 &param,
6038 WMA_WILDCARD_PDEV_ID);
6039 if (QDF_IS_STATUS_ERROR(status))
6040 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006041
6042 wmi_set_target_suspend(wma_handle->wmi_handle, true);
6043
Anurag Chouhance0dc992016-02-16 18:18:03 +05306044 if (qdf_wait_single_event(&wma_handle->target_suspend,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006045 WMA_TGT_SUSPEND_COMPLETE_TIMEOUT)
Anurag Chouhance0dc992016-02-16 18:18:03 +05306046 != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006047 WMA_LOGE("Failed to get ACK from firmware for pdev suspend");
6048 wmi_set_target_suspend(wma_handle->wmi_handle, false);
Manjunathappa Prakash7b67e622016-04-12 15:18:45 +05306049 wma_suspend_target_timeout(pmac->sme.enableSelfRecovery);
Govind Singhd76a5b02016-03-08 15:12:14 +05306050 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006051 }
6052
Anurag Chouhan6d760662016-02-20 16:05:43 +05306053 scn = cds_get_context(QDF_MODULE_ID_HIF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006054
6055 if (scn == NULL) {
6056 WMA_LOGE("%s: Failed to get HIF context", __func__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306057 QDF_ASSERT(0);
Govind Singhd76a5b02016-03-08 15:12:14 +05306058 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006059 }
6060
Govind Singhd76a5b02016-03-08 15:12:14 +05306061 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006062}
6063
6064/**
6065 * wma_target_suspend_acknowledge() - update target susspend status
Houston Hoffmana769ed32016-04-14 17:02:51 -07006066 * @context: HTC_INIT_INFO->context
6067 * @wow_nack: true when wow is rejected
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006068 *
6069 * Return: none
6070 */
Houston Hoffmana769ed32016-04-14 17:02:51 -07006071void wma_target_suspend_acknowledge(void *context, bool wow_nack)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006072{
Anurag Chouhan6d760662016-02-20 16:05:43 +05306073 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006074
6075 if (NULL == wma) {
6076 WMA_LOGE("%s: wma is NULL", __func__);
6077 return;
6078 }
6079
6080 wma->wow_nack = wow_nack;
Anurag Chouhance0dc992016-02-16 18:18:03 +05306081 qdf_event_set(&wma->target_suspend);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006082 if (wow_nack)
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306083 qdf_wake_lock_timeout_acquire(&wma->wow_wake_lock,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006084 WMA_WAKE_LOCK_TIMEOUT,
6085 WIFI_POWER_EVENT_WAKELOCK_WOW);
6086}
6087
6088/**
6089 * wma_resume_target() - resume target
6090 * @handle: wma handle
6091 *
Govind Singhd76a5b02016-03-08 15:12:14 +05306092 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006093 */
Govind Singhd76a5b02016-03-08 15:12:14 +05306094QDF_STATUS wma_resume_target(WMA_HANDLE handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006095{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006096 tp_wma_handle wma = (tp_wma_handle) handle;
Anurag Chouhance0dc992016-02-16 18:18:03 +05306097 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006098#ifdef CONFIG_CNSS
Anurag Chouhan6d760662016-02-20 16:05:43 +05306099 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006100 if (NULL == pMac) {
6101 WMA_LOGE("%s: Unable to get PE context", __func__);
Govind Singhd76a5b02016-03-08 15:12:14 +05306102 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006103 }
6104#endif /* CONFIG_CNSS */
6105
Anurag Chouhance0dc992016-02-16 18:18:03 +05306106 qdf_event_reset(&wma->wma_resume_event);
Govind Singhd76a5b02016-03-08 15:12:14 +05306107 qdf_status = wmi_unified_resume_send(wma->wmi_handle,
6108 WMA_WILDCARD_PDEV_ID);
6109 if (QDF_IS_STATUS_ERROR(qdf_status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006110 WMA_LOGE("Failed to send WMI_PDEV_RESUME_CMDID command");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006111
Anurag Chouhance0dc992016-02-16 18:18:03 +05306112 qdf_status = qdf_wait_single_event(&(wma->wma_resume_event),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006113 WMA_RESUME_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05306114 if (QDF_STATUS_SUCCESS != qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006115 WMA_LOGP("%s: Timeout waiting for resume event from FW",
6116 __func__);
6117 WMA_LOGP("%s: Pending commands %d credits %d", __func__,
6118 wmi_get_pending_cmds(wma->wmi_handle),
6119 wmi_get_host_credits(wma->wmi_handle));
Prashanth Bhatta9e143052015-12-04 11:56:47 -08006120 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006121#ifdef CONFIG_CNSS
6122 if (pMac->sme.enableSelfRecovery) {
6123 cds_trigger_recovery();
6124 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306125 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006126 }
6127#else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306128 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006129#endif /* CONFIG_CNSS */
6130 } else {
6131 WMA_LOGE("%s: SSR in progress, ignore resume timeout",
6132 __func__);
6133 }
6134 } else {
6135 WMA_LOGD("Host wakeup received");
6136 }
6137
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306138 if (QDF_STATUS_SUCCESS == qdf_status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006139 wmi_set_target_suspend(wma->wmi_handle, false);
6140
Houston Hoffman52ec6692016-04-21 16:36:45 -07006141 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006142}
6143
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006144#ifdef FEATURE_WLAN_TDLS
6145/**
6146 * wma_tdls_event_handler() - handle TDLS event
6147 * @handle: wma handle
6148 * @event: event buffer
6149 * @len: buffer length
6150 *
6151 * Return: 0 for success or error code
6152 */
6153int wma_tdls_event_handler(void *handle, uint8_t *event, uint32_t len)
6154{
6155 tp_wma_handle wma = (tp_wma_handle) handle;
6156 WMI_TDLS_PEER_EVENTID_param_tlvs *param_buf = NULL;
6157 wmi_tdls_peer_event_fixed_param *peer_event = NULL;
6158 tSirTdlsEventnotify *tdls_event;
6159
6160 if (!event) {
6161 WMA_LOGE("%s: event param null", __func__);
6162 return -EINVAL;
6163 }
6164
6165 param_buf = (WMI_TDLS_PEER_EVENTID_param_tlvs *) event;
6166 if (!param_buf) {
6167 WMA_LOGE("%s: received null buf from target", __func__);
6168 return -EINVAL;
6169 }
6170
6171 peer_event = param_buf->fixed_param;
6172 if (!peer_event) {
6173 WMA_LOGE("%s: received null event data from target", __func__);
6174 return -EINVAL;
6175 }
6176
6177 tdls_event = (tSirTdlsEventnotify *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306178 qdf_mem_malloc(sizeof(*tdls_event));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006179 if (!tdls_event) {
6180 WMA_LOGE("%s: failed to allocate memory for tdls_event",
6181 __func__);
6182 return -ENOMEM;
6183 }
6184
6185 tdls_event->sessionId = peer_event->vdev_id;
6186 WMI_MAC_ADDR_TO_CHAR_ARRAY(&peer_event->peer_macaddr,
Srinivas Girigowda4f593792015-11-19 15:33:42 -08006187 tdls_event->peermac.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006188
6189 switch (peer_event->peer_status) {
6190 case WMI_TDLS_SHOULD_DISCOVER:
6191 tdls_event->messageType = WMA_TDLS_SHOULD_DISCOVER_CMD;
6192 break;
6193 case WMI_TDLS_SHOULD_TEARDOWN:
6194 tdls_event->messageType = WMA_TDLS_SHOULD_TEARDOWN_CMD;
6195 break;
6196 case WMI_TDLS_PEER_DISCONNECTED:
6197 tdls_event->messageType = WMA_TDLS_PEER_DISCONNECTED_CMD;
6198 break;
Kabilan Kannan14ec97f2016-05-16 23:48:25 -07006199 case WMI_TDLS_CONNECTION_TRACKER_NOTIFICATION:
6200 tdls_event->messageType =
6201 WMA_TDLS_CONNECTION_TRACKER_NOTIFICATION_CMD;
6202 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006203 default:
6204 WMA_LOGE("%s: Discarding unknown tdls event(%d) from target",
6205 __func__, peer_event->peer_status);
6206 return -EINVAL;
6207 }
6208
6209 switch (peer_event->peer_reason) {
6210 case WMI_TDLS_TEARDOWN_REASON_TX:
6211 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_TX;
6212 break;
6213 case WMI_TDLS_TEARDOWN_REASON_RSSI:
6214 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_RSSI;
6215 break;
6216 case WMI_TDLS_TEARDOWN_REASON_SCAN:
6217 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_SCAN;
6218 break;
6219 case WMI_TDLS_DISCONNECTED_REASON_PEER_DELETE:
6220 tdls_event->peer_reason =
6221 eWNI_TDLS_DISCONNECTED_REASON_PEER_DELETE;
6222 break;
6223 case WMI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT:
6224 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT;
6225 break;
6226 case WMI_TDLS_TEARDOWN_REASON_BAD_PTR:
6227 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_BAD_PTR;
6228 break;
6229 case WMI_TDLS_TEARDOWN_REASON_NO_RESPONSE:
6230 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_NO_RESPONSE;
6231 break;
Kabilan Kannan14ec97f2016-05-16 23:48:25 -07006232 case WMI_TDLS_ENTER_BUF_STA:
6233 tdls_event->peer_reason = eWNI_TDLS_PEER_ENTER_BUF_STA;
6234 break;
6235 case WMI_TDLS_EXIT_BUF_STA:
6236 tdls_event->peer_reason = eWNI_TDLS_PEER_EXIT_BUF_STA;
6237 break;
6238 case WMI_TDLS_ENTER_BT_BUSY_MODE:
6239 tdls_event->peer_reason = eWNI_TDLS_ENTER_BT_BUSY_MODE;
6240 break;
6241 case WMI_TDLS_EXIT_BT_BUSY_MODE:
6242 tdls_event->peer_reason = eWNI_TDLS_EXIT_BT_BUSY_MODE;
6243 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006244 default:
6245 WMA_LOGE("%s: unknown reason(%d) in tdls event(%d) from target",
6246 __func__, peer_event->peer_reason,
6247 peer_event->peer_status);
6248 return -EINVAL;
6249 }
6250
6251 WMA_LOGD("%s: sending msg to umac, messageType: 0x%x, "
6252 "for peer: %pM, reason: %d, smesessionId: %d",
Srinivas Girigowda4f593792015-11-19 15:33:42 -08006253 __func__, tdls_event->messageType, tdls_event->peermac.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006254 tdls_event->peer_reason, tdls_event->sessionId);
6255
6256 wma_send_msg(wma, tdls_event->messageType, (void *)tdls_event, 0);
6257 return 0;
6258}
6259
6260/**
6261 * wma_set_tdls_offchan_mode() - set tdls off channel mode
6262 * @handle: wma handle
6263 * @chan_switch_params: Pointer to tdls channel switch parameter structure
6264 *
6265 * This function sets tdls off channel mode
6266 *
6267 * Return: 0 on success; Negative errno otherwise
6268 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05306269QDF_STATUS wma_set_tdls_offchan_mode(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006270 tdls_chan_switch_params *chan_switch_params)
6271{
6272 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Himanshu Agarwal44195412016-03-09 13:03:54 +05306273 struct tdls_channel_switch_params params = {0};
6274 QDF_STATUS ret = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006275
6276 if (!wma_handle || !wma_handle->wmi_handle) {
6277 WMA_LOGE(FL(
6278 "WMA is closed, can not issue tdls off channel cmd"
6279 ));
6280 ret = -EINVAL;
6281 goto end;
6282 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006283
Himanshu Agarwal44195412016-03-09 13:03:54 +05306284 params.vdev_id = chan_switch_params->vdev_id;
6285 params.tdls_off_ch_bw_offset =
6286 chan_switch_params->tdls_off_ch_bw_offset;
6287 params.tdls_off_ch = chan_switch_params->tdls_off_ch;
6288 params.tdls_sw_mode = chan_switch_params->tdls_sw_mode;
6289 params.oper_class = chan_switch_params->oper_class;
6290 params.is_responder = chan_switch_params->is_responder;
6291 qdf_mem_copy(params.peer_mac_addr, chan_switch_params->peer_mac_addr,
Krunal Soniab793342016-04-22 18:43:20 -07006292 IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006293
Himanshu Agarwal44195412016-03-09 13:03:54 +05306294 ret = wmi_unified_set_tdls_offchan_mode_cmd(wma_handle->wmi_handle,
6295 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006296
6297end:
6298 if (chan_switch_params)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306299 qdf_mem_free(chan_switch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006300 return ret;
6301}
6302
6303/**
6304 * wma_update_fw_tdls_state() - send enable/disable tdls for a vdev
6305 * @wma: wma handle
6306 * @pwmaTdlsparams: TDLS params
6307 *
6308 * Return: 0 for sucess or error code
6309 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05306310QDF_STATUS wma_update_fw_tdls_state(WMA_HANDLE handle, void *pwmaTdlsparams)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006311{
6312 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006313 t_wma_tdls_mode tdls_mode;
6314 t_wma_tdls_params *wma_tdls = (t_wma_tdls_params *) pwmaTdlsparams;
Himanshu Agarwal44195412016-03-09 13:03:54 +05306315 struct wmi_tdls_params params = {0};
6316 QDF_STATUS ret = QDF_STATUS_SUCCESS;
6317 uint8_t tdls_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006318
6319 if (!wma_handle || !wma_handle->wmi_handle) {
6320 WMA_LOGE("%s: WMA is closed, can not issue fw tdls state cmd",
6321 __func__);
6322 ret = -EINVAL;
6323 goto end_fw_tdls_state;
6324 }
6325
Himanshu Agarwal44195412016-03-09 13:03:54 +05306326 params.tdls_state = wma_tdls->tdls_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006327 tdls_mode = wma_tdls->tdls_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006328
6329 if (WMA_TDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == tdls_mode) {
Himanshu Agarwal44195412016-03-09 13:03:54 +05306330 tdls_state = WMI_TDLS_ENABLE_PASSIVE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006331 } else if (WMA_TDLS_SUPPORT_ENABLED == tdls_mode) {
Kabilan Kannan14ec97f2016-05-16 23:48:25 -07006332 tdls_state = WMI_TDLS_ENABLE_CONNECTION_TRACKER_IN_HOST;
Kabilan Kannan421714b2015-11-23 04:44:59 -08006333 } else if (WMA_TDLS_SUPPORT_ACTIVE_EXTERNAL_CONTROL == tdls_mode) {
Kabilan Kannan14ec97f2016-05-16 23:48:25 -07006334 tdls_state = WMI_TDLS_ENABLE_CONNECTION_TRACKER_IN_HOST;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006335 } else {
Himanshu Agarwal44195412016-03-09 13:03:54 +05306336 tdls_state = WMI_TDLS_DISABLE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006337 }
6338
Himanshu Agarwal44195412016-03-09 13:03:54 +05306339 params.vdev_id = wma_tdls->vdev_id;
6340 params.notification_interval_ms = wma_tdls->notification_interval_ms;
6341 params.tx_discovery_threshold = wma_tdls->tx_discovery_threshold;
6342 params.tx_teardown_threshold = wma_tdls->tx_teardown_threshold;
6343 params.rssi_teardown_threshold = wma_tdls->rssi_teardown_threshold;
6344 params.rssi_delta = wma_tdls->rssi_delta;
6345 params.tdls_options = wma_tdls->tdls_options;
6346 params.peer_traffic_ind_window = wma_tdls->peer_traffic_ind_window;
6347 params.peer_traffic_response_timeout =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006348 wma_tdls->peer_traffic_response_timeout;
Himanshu Agarwal44195412016-03-09 13:03:54 +05306349 params.puapsd_mask = wma_tdls->puapsd_mask;
6350 params.puapsd_inactivity_time = wma_tdls->puapsd_inactivity_time;
6351 params.puapsd_rx_frame_threshold =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006352 wma_tdls->puapsd_rx_frame_threshold;
Himanshu Agarwal44195412016-03-09 13:03:54 +05306353 params.teardown_notification_ms =
Kabilan Kannanca670be2015-11-23 01:56:12 -08006354 wma_tdls->teardown_notification_ms;
Himanshu Agarwal44195412016-03-09 13:03:54 +05306355 params.tdls_peer_kickout_threshold =
Kabilan Kannan421714b2015-11-23 04:44:59 -08006356 wma_tdls->tdls_peer_kickout_threshold;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006357
Himanshu Agarwal44195412016-03-09 13:03:54 +05306358 ret = wmi_unified_update_fw_tdls_state_cmd(wma_handle->wmi_handle,
6359 &params, tdls_state);
6360 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006361 goto end_fw_tdls_state;
Himanshu Agarwal44195412016-03-09 13:03:54 +05306362
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006363 WMA_LOGD("%s: vdev_id %d", __func__, wma_tdls->vdev_id);
6364
6365end_fw_tdls_state:
6366 if (pwmaTdlsparams)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306367 qdf_mem_free(pwmaTdlsparams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006368 return ret;
6369}
6370
6371/**
6372 * wma_update_tdls_peer_state() - update TDLS peer state
6373 * @handle: wma handle
6374 * @peerStateParams: TDLS peer state params
6375 *
6376 * Return: 0 for success or error code
6377 */
6378int wma_update_tdls_peer_state(WMA_HANDLE handle,
6379 tTdlsPeerStateParams *peerStateParams)
6380{
6381 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006382 uint32_t i;
6383 ol_txrx_pdev_handle pdev;
6384 uint8_t peer_id;
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07006385 ol_txrx_peer_handle peer;
6386 uint8_t *peer_mac_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006387 int ret = 0;
Kabilan Kannanc89fe712016-07-21 06:57:12 -07006388 uint32_t *ch_mhz = NULL;
Poddar, Siddarth5a91f5b2016-04-28 12:24:10 +05306389 bool restore_last_peer = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006390
6391 if (!wma_handle || !wma_handle->wmi_handle) {
6392 WMA_LOGE("%s: WMA is closed, can not issue cmd", __func__);
6393 ret = -EINVAL;
6394 goto end_tdls_peer_state;
6395 }
6396
6397 /* peer capability info is valid only when peer state is connected */
6398 if (WMA_TDLS_PEER_STATE_CONNECTED != peerStateParams->peerState) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306399 qdf_mem_zero(&peerStateParams->peerCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006400 sizeof(tTdlsPeerCapParams));
6401 }
6402
Kabilan Kannanc89fe712016-07-21 06:57:12 -07006403 if (peerStateParams->peerCap.peerChanLen) {
6404 ch_mhz = qdf_mem_malloc(sizeof(uint32_t) *
6405 peerStateParams->peerCap.peerChanLen);
6406 if (ch_mhz == NULL) {
6407 WMA_LOGE("%s: memory allocation failed", __func__);
6408 ret = -ENOMEM;
6409 goto end_tdls_peer_state;
6410 }
Naveen Rawat35804772016-06-27 15:40:28 -07006411 }
6412
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006413 for (i = 0; i < peerStateParams->peerCap.peerChanLen; ++i) {
Govind Singhaa64c242016-03-08 11:31:49 +05306414 ch_mhz[i] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006415 cds_chan_to_freq(peerStateParams->peerCap.peerChan[i].
6416 chanId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006417 }
6418
Govind Singhaa64c242016-03-08 11:31:49 +05306419 if (wmi_unified_update_tdls_peer_state_cmd(wma_handle->wmi_handle,
6420 (struct tdls_peer_state_params *)peerStateParams,
6421 ch_mhz)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006422 WMA_LOGE("%s: failed to send tdls peer update state command",
6423 __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006424 ret = -EIO;
6425 goto end_tdls_peer_state;
6426 }
6427
6428 /* in case of teardown, remove peer from fw */
6429 if (WMA_TDLS_PEER_STATE_TEARDOWN == peerStateParams->peerState) {
Anurag Chouhan6d760662016-02-20 16:05:43 +05306430 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006431 if (!pdev) {
6432 WMA_LOGE("%s: Failed to find pdev", __func__);
6433 ret = -EIO;
6434 goto end_tdls_peer_state;
6435 }
6436
6437 peer = ol_txrx_find_peer_by_addr(pdev,
6438 peerStateParams->peerMacAddr,
6439 &peer_id);
6440 if (!peer) {
6441 WMA_LOGE("%s: Failed to get peer handle using peer mac %pM",
6442 __func__, peerStateParams->peerMacAddr);
6443 ret = -EIO;
6444 goto end_tdls_peer_state;
6445 }
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07006446 peer_mac_addr = ol_txrx_peer_get_peer_mac_addr(peer);
Poddar, Siddarth5a91f5b2016-04-28 12:24:10 +05306447 restore_last_peer = is_vdev_restore_last_peer(peer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006448
6449 WMA_LOGD("%s: calling wma_remove_peer for peer " MAC_ADDRESS_STR
6450 " vdevId: %d", __func__,
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07006451 MAC_ADDR_ARRAY(peer_mac_addr),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006452 peerStateParams->vdevId);
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07006453 wma_remove_peer(wma_handle, peer_mac_addr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006454 peerStateParams->vdevId, peer, false);
Poddar, Siddarth5a91f5b2016-04-28 12:24:10 +05306455 ol_txrx_update_last_real_peer(pdev, peer, &peer_id,
6456 restore_last_peer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006457 }
6458
6459end_tdls_peer_state:
Kabilan Kannanc89fe712016-07-21 06:57:12 -07006460 if (ch_mhz)
6461 qdf_mem_free(ch_mhz);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006462 if (peerStateParams)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306463 qdf_mem_free(peerStateParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006464 return ret;
6465}
6466#endif /* FEATURE_WLAN_TDLS */
6467
6468
6469/**
6470 * wma_dfs_attach() - Attach DFS methods to the umac state.
6471 * @dfs_ic: ieee80211com ptr
6472 *
6473 * Return: Return ieee80211com ptr with updated info
6474 */
6475struct ieee80211com *wma_dfs_attach(struct ieee80211com *dfs_ic)
6476{
6477 /*Allocate memory for dfs_ic before passing it up to dfs_attach() */
6478 dfs_ic = (struct ieee80211com *)
6479 os_malloc(NULL, sizeof(struct ieee80211com), GFP_ATOMIC);
6480 if (dfs_ic == NULL) {
6481 WMA_LOGE("%s:Allocation of dfs_ic failed %zu",
6482 __func__, sizeof(struct ieee80211com));
6483 return NULL;
6484 }
6485 OS_MEMZERO(dfs_ic, sizeof(struct ieee80211com));
6486 /* DFS pattern matching hooks */
6487 dfs_ic->ic_dfs_attach = ol_if_dfs_attach;
6488 dfs_ic->ic_dfs_disable = ol_if_dfs_disable;
6489 dfs_ic->ic_find_channel = ieee80211_find_channel;
6490 dfs_ic->ic_dfs_enable = ol_if_dfs_enable;
6491 dfs_ic->ic_ieee2mhz = ieee80211_ieee2mhz;
6492
6493 /* Hardware facing hooks */
6494 dfs_ic->ic_get_ext_busy = ol_if_dfs_get_ext_busy;
6495 dfs_ic->ic_get_mib_cycle_counts_pct =
6496 ol_if_dfs_get_mib_cycle_counts_pct;
6497 dfs_ic->ic_get_TSF64 = ol_if_get_tsf64;
6498
6499 /* NOL related hooks */
6500 dfs_ic->ic_dfs_usenol = ol_if_dfs_usenol;
6501 /*
6502 * Hooks from wma/dfs/ back
6503 * into the PE/SME
6504 * and shared DFS code
6505 */
6506 dfs_ic->ic_dfs_notify_radar = ieee80211_mark_dfs;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306507 qdf_spinlock_create(&dfs_ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006508 /* Initializes DFS Data Structures and queues */
6509 dfs_attach(dfs_ic);
6510
6511 return dfs_ic;
6512}
6513
6514/**
6515 * wma_dfs_detach() - Detach DFS methods
6516 * @dfs_ic: ieee80211com ptr
6517 *
6518 * Return: none
6519 */
6520void wma_dfs_detach(struct ieee80211com *dfs_ic)
6521{
6522 dfs_detach(dfs_ic);
6523
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306524 qdf_spinlock_destroy(&dfs_ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006525 if (NULL != dfs_ic->ic_curchan) {
6526 OS_FREE(dfs_ic->ic_curchan);
6527 dfs_ic->ic_curchan = NULL;
6528 }
6529
6530 OS_FREE(dfs_ic);
6531}
6532
6533/**
6534 * wma_dfs_configure() - configure dfs
6535 * @ic: ieee80211com ptr
6536 *
6537 * Configures Radar Filters during
6538 * vdev start/channel change/regulatory domain
6539 * change.This Configuration enables to program
6540 * the DFS pattern matching module.
6541 *
6542 * Return: none
6543 */
6544void wma_dfs_configure(struct ieee80211com *ic)
6545{
6546 struct ath_dfs_radar_tab_info rinfo;
6547 int dfsdomain;
6548 int radar_enabled_status = 0;
6549 if (ic == NULL) {
6550 WMA_LOGE("%s: DFS ic is Invalid", __func__);
6551 return;
6552 }
6553
6554 dfsdomain = ic->current_dfs_regdomain;
6555
6556 /* Fetch current radar patterns from the lmac */
6557 OS_MEMZERO(&rinfo, sizeof(rinfo));
6558
6559 /*
6560 * Look up the current DFS
6561 * regulatory domain and decide
6562 * which radar pulses to use.
6563 */
6564 switch (dfsdomain) {
Amar Singhala7bb01b2016-01-27 11:31:59 -08006565 case DFS_FCC_REGION:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006566 WMA_LOGI("%s: DFS-FCC domain", __func__);
Amar Singhala7bb01b2016-01-27 11:31:59 -08006567 rinfo.dfsdomain = DFS_FCC_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006568 rinfo.dfs_radars = dfs_fcc_radars;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306569 rinfo.numradars = QDF_ARRAY_SIZE(dfs_fcc_radars);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006570 rinfo.b5pulses = dfs_fcc_bin5pulses;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306571 rinfo.numb5radars = QDF_ARRAY_SIZE(dfs_fcc_bin5pulses);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006572 break;
Amar Singhala7bb01b2016-01-27 11:31:59 -08006573 case DFS_ETSI_REGION:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006574 WMA_LOGI("%s: DFS-ETSI domain", __func__);
Amar Singhala7bb01b2016-01-27 11:31:59 -08006575 rinfo.dfsdomain = DFS_ETSI_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006576 rinfo.dfs_radars = dfs_etsi_radars;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306577 rinfo.numradars = QDF_ARRAY_SIZE(dfs_etsi_radars);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006578 rinfo.b5pulses = NULL;
6579 rinfo.numb5radars = 0;
6580 break;
Amar Singhala7bb01b2016-01-27 11:31:59 -08006581 case DFS_MKK_REGION:
6582 WMA_LOGI("%s: DFS-MKK domain", __func__);
6583 rinfo.dfsdomain = DFS_MKK_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006584 rinfo.dfs_radars = dfs_mkk4_radars;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306585 rinfo.numradars = QDF_ARRAY_SIZE(dfs_mkk4_radars);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006586 rinfo.b5pulses = dfs_jpn_bin5pulses;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306587 rinfo.numb5radars = QDF_ARRAY_SIZE(dfs_jpn_bin5pulses);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006588 break;
6589 default:
6590 WMA_LOGI("%s: DFS-UNINT domain", __func__);
Amar Singhala7bb01b2016-01-27 11:31:59 -08006591 rinfo.dfsdomain = DFS_UNINIT_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006592 rinfo.dfs_radars = NULL;
6593 rinfo.numradars = 0;
6594 rinfo.b5pulses = NULL;
6595 rinfo.numb5radars = 0;
6596 break;
6597 }
6598
6599 rinfo.dfs_pri_multiplier = ic->dfs_pri_multiplier;
6600
6601 /*
6602 * Set the regulatory domain,
6603 * radar pulse table and enable
6604 * radar events if required.
6605 * dfs_radar_enable() returns
6606 * 0 on success and non-zero
6607 * failure.
6608 */
6609 radar_enabled_status = dfs_radar_enable(ic, &rinfo);
6610 if (radar_enabled_status != DFS_STATUS_SUCCESS) {
6611 WMA_LOGE("%s[%d]: DFS- Radar Detection Enabling Failed",
6612 __func__, __LINE__);
6613 }
6614}
6615
6616/**
6617 * wma_dfs_configure_channel() - configure DFS channel
6618 * @dfs_ic: ieee80211com ptr
Siddarth Poddar17dc4712016-03-09 16:30:27 +05306619 * @band_center_freq1: center frequency 1
6620 * @band_center_freq2: center frequency 2
6621 * (valid only for 11ac vht 80plus80 mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006622 * @ req: vdev start request
6623 *
6624 * Set the Channel parameters in to DFS module
6625 * Also,configure the DFS radar filters for
6626 * matching the DFS phyerrors.
6627 *
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306628 * Return: dfs_ieee80211_channel / NULL for error
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006629 */
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306630struct dfs_ieee80211_channel *wma_dfs_configure_channel(
6631 struct ieee80211com *dfs_ic,
Siddarth Poddar17dc4712016-03-09 16:30:27 +05306632 uint32_t band_center_freq1,
6633 uint32_t band_center_freq2,
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306634 struct wma_vdev_start_req
6635 *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006636{
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006637 uint8_t ext_channel;
6638
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006639 if (dfs_ic == NULL) {
6640 WMA_LOGE("%s: DFS ic is Invalid", __func__);
6641 return NULL;
6642 }
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05306643
6644 if (!dfs_ic->ic_curchan) {
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306645 dfs_ic->ic_curchan = (struct dfs_ieee80211_channel *)os_malloc(
6646 NULL,
6647 sizeof(struct dfs_ieee80211_channel),
6648 GFP_ATOMIC);
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05306649 if (dfs_ic->ic_curchan == NULL) {
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306650 WMA_LOGE(
6651 "%s: allocation of dfs_ic->ic_curchan failed %zu",
6652 __func__, sizeof(struct dfs_ieee80211_channel));
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05306653 return NULL;
6654 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006655 }
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05306656
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306657 OS_MEMZERO(dfs_ic->ic_curchan, sizeof(struct dfs_ieee80211_channel));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006658
6659 dfs_ic->ic_curchan->ic_ieee = req->chan;
Siddarth Poddar17dc4712016-03-09 16:30:27 +05306660 dfs_ic->ic_curchan->ic_freq = cds_chan_to_freq(req->chan);
6661 dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg1 = band_center_freq1;
6662 dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg2 = band_center_freq2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006663 dfs_ic->ic_curchan->ic_pri_freq_center_freq_mhz_separation =
6664 dfs_ic->ic_curchan->ic_freq -
6665 dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg1;
6666
6667 if ((dfs_ic->ic_curchan->ic_ieee >= WMA_11A_CHANNEL_BEGIN) &&
6668 (dfs_ic->ic_curchan->ic_ieee <= WMA_11A_CHANNEL_END)) {
6669 dfs_ic->ic_curchan->ic_flags |= IEEE80211_CHAN_5GHZ;
6670 }
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006671
6672 switch (req->chan_width) {
6673 case CH_WIDTH_20MHZ:
6674 dfs_ic->ic_curchan->ic_flags |=
6675 (req->vht_capable ? IEEE80211_CHAN_VHT20 :
6676 IEEE80211_CHAN_HT20);
6677 break;
6678 case CH_WIDTH_40MHZ:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006679 if (req->chan < req->ch_center_freq_seg0)
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006680 dfs_ic->ic_curchan->ic_flags |=
6681 (req->vht_capable ?
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006682 IEEE80211_CHAN_VHT40PLUS :
6683 IEEE80211_CHAN_HT40PLUS);
6684 else
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006685 dfs_ic->ic_curchan->ic_flags |=
6686 (req->vht_capable ?
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006687 IEEE80211_CHAN_VHT40MINUS :
6688 IEEE80211_CHAN_HT40MINUS);
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006689 break;
6690 case CH_WIDTH_80MHZ:
6691 dfs_ic->ic_curchan->ic_flags |= IEEE80211_CHAN_VHT80;
6692 break;
6693 case CH_WIDTH_80P80MHZ:
Siddarth Poddar17dc4712016-03-09 16:30:27 +05306694 ext_channel = cds_freq_to_chan(band_center_freq2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006695 dfs_ic->ic_curchan->ic_flags |=
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006696 IEEE80211_CHAN_VHT80P80;
6697 dfs_ic->ic_curchan->ic_freq_ext =
Siddarth Poddar17dc4712016-03-09 16:30:27 +05306698 band_center_freq2;
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006699 dfs_ic->ic_curchan->ic_ieee_ext = ext_channel;
6700
6701 /* verify both the 80MHz are DFS bands or not */
Rajeev Kumara3f6c2d2016-04-15 12:47:41 -07006702 if ((CHANNEL_STATE_DFS ==
6703 cds_get_5g_bonded_channel_state(req->chan ,
6704 CH_WIDTH_80MHZ)) &&
6705 (CHANNEL_STATE_DFS == cds_get_5g_bonded_channel_state(
6706 ext_channel - WMA_80MHZ_START_CENTER_CH_DIFF,
6707 CH_WIDTH_80MHZ)))
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006708 dfs_ic->ic_curchan->ic_80p80_both_dfs = true;
6709 break;
6710 case CH_WIDTH_160MHZ:
6711 dfs_ic->ic_curchan->ic_flags |=
6712 IEEE80211_CHAN_VHT160;
6713 break;
6714 default:
6715 WMA_LOGE(
6716 "%s: Recieved a wrong channel width %d",
6717 __func__, req->chan_width);
6718 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006719 }
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006720
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006721 dfs_ic->ic_curchan->ic_flagext |= IEEE80211_CHAN_DFS;
6722
6723 if (req->oper_mode == BSS_OPERATIONAL_MODE_AP) {
6724 dfs_ic->ic_opmode = IEEE80211_M_HOSTAP;
6725 dfs_ic->vdev_id = req->vdev_id;
6726 }
6727
6728 dfs_ic->dfs_pri_multiplier = req->dfs_pri_multiplier;
6729
6730 /*
6731 * Configuring the DFS with current channel and the radar filters
6732 */
6733 wma_dfs_configure(dfs_ic);
6734 WMA_LOGI("%s: DFS- CHANNEL CONFIGURED", __func__);
6735 return dfs_ic->ic_curchan;
6736}
6737
6738
6739/**
6740 * wma_set_dfs_region() - set DFS region
6741 * @wma: wma handle
6742 *
6743 * Configure the DFS region for DFS radar filter initialization
6744 *
6745 * Return: none
6746 */
6747void wma_set_dfs_region(tp_wma_handle wma, uint8_t dfs_region)
6748{
6749 /* dfs information is passed */
Amar Singhala7bb01b2016-01-27 11:31:59 -08006750 if (dfs_region > DFS_MKK_REGION || dfs_region == DFS_UNINIT_REGION)
6751 /* assign DFS_FCC_REGION as default region*/
6752 wma->dfs_ic->current_dfs_regdomain = DFS_FCC_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006753 else
6754 wma->dfs_ic->current_dfs_regdomain = dfs_region;
6755
6756 WMA_LOGI("%s: DFS Region Domain: %d", __func__,
6757 wma->dfs_ic->current_dfs_regdomain);
6758}
6759
6760/**
6761 * wma_get_channels() - prepare dfs radar channel list
6762 * @ichan: channel
6763 * @chan_list: return channel list
6764 *
6765 * Return: return number of channels
6766 */
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306767int wma_get_channels(struct dfs_ieee80211_channel *ichan,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006768 struct wma_dfs_radar_channel_list *chan_list)
6769{
6770 uint8_t center_chan = cds_freq_to_chan(ichan->ic_vhtop_ch_freq_seg1);
Vishwajith Upendrabf673e72016-01-19 16:05:40 -08006771 int count = 0;
6772 int start_channel = 0;
6773 int loop;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006774
6775 chan_list->nchannels = 0;
6776
Vishwajith Upendrabf673e72016-01-19 16:05:40 -08006777 if (IEEE80211_IS_CHAN_11AC_VHT160(ichan)) {
6778 /*
6779 * In 160MHz channel width, need to
6780 * check if each of the 8 20MHz channel
6781 * is DFS before adding to the NOL list.
6782 * As it is possible that part of the
6783 * 160MHz can be Non-DFS channels.
6784 */
6785 start_channel = center_chan - WMA_160MHZ_START_CENTER_CH_DIFF;
6786 for (loop = 0; loop < WMA_DFS_MAX_20M_SUB_CH; loop++) {
6787 if (cds_get_channel_state(start_channel +
6788 (loop * WMA_NEXT_20MHZ_START_CH_DIFF)) ==
6789 CHANNEL_STATE_DFS) {
6790 chan_list->channels[count] = start_channel +
6791 (loop * WMA_NEXT_20MHZ_START_CH_DIFF);
6792 count++;
6793 }
6794 }
6795 chan_list->nchannels = count;
6796 } else if (IEEE80211_IS_CHAN_11AC_VHT80P80(ichan)) {
6797 chan_list->nchannels = 4;
6798 /*
6799 * If SAP is operating in 80p80 mode, either
6800 * one of the two 80 segments or both the 80
6801 * segments can be DFS channels, so need to
6802 * identify on which 80 segment radar has
6803 * been detected and only add those channels
6804 * to the NOL list. center frequency should be
6805 * based on the segment id passed as part of
6806 * channel information in radar indication.
6807 */
6808 if (ichan->ic_radar_found_segid == DFS_80P80_SEG1)
6809 center_chan =
6810 cds_freq_to_chan(ichan->ic_vhtop_ch_freq_seg2);
6811 chan_list->channels[0] = center_chan - 6;
6812 chan_list->channels[1] = center_chan - 2;
6813 chan_list->channels[2] = center_chan + 2;
6814 chan_list->channels[3] = center_chan + 6;
6815 } else if (IEEE80211_IS_CHAN_11AC_VHT80(ichan)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006816 chan_list->nchannels = 4;
6817 chan_list->channels[0] = center_chan - 6;
6818 chan_list->channels[1] = center_chan - 2;
6819 chan_list->channels[2] = center_chan + 2;
6820 chan_list->channels[3] = center_chan + 6;
6821 } else if (IEEE80211_IS_CHAN_11N_HT40(ichan) ||
6822 IEEE80211_IS_CHAN_11AC_VHT40(ichan)) {
6823 chan_list->nchannels = 2;
6824 chan_list->channels[0] = center_chan - 2;
6825 chan_list->channels[1] = center_chan + 2;
6826 } else {
6827 chan_list->nchannels = 1;
6828 chan_list->channels[0] = center_chan;
6829 }
6830
6831 return chan_list->nchannels;
6832}
6833
6834
6835/**
6836 * wma_dfs_indicate_radar() - Indicate Radar to SAP/HDD
6837 * @ic: ieee80211com ptr
6838 * @ichan: ieee 80211 channel
6839 *
6840 * Return: 0 for success or error code
6841 */
6842int wma_dfs_indicate_radar(struct ieee80211com *ic,
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306843 struct dfs_ieee80211_channel *ichan)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006844{
6845 tp_wma_handle wma;
6846 void *hdd_ctx;
6847 struct wma_dfs_radar_indication *radar_event;
6848 struct wma_dfs_radar_ind wma_radar_event;
6849 tpAniSirGlobal pmac = NULL;
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05306850 bool indication_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006851
Anurag Chouhan6d760662016-02-20 16:05:43 +05306852 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006853 if (wma == NULL) {
6854 WMA_LOGE("%s: DFS- Invalid wma", __func__);
6855 return -ENOENT;
6856 }
6857
Anurag Chouhan6d760662016-02-20 16:05:43 +05306858 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006859 pmac = (tpAniSirGlobal)
Anurag Chouhan6d760662016-02-20 16:05:43 +05306860 cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006861
6862 if (!pmac) {
6863 WMA_LOGE("%s: Invalid MAC handle", __func__);
6864 return -ENOENT;
6865 }
6866
6867 if (wma->dfs_ic != ic) {
6868 WMA_LOGE("%s:DFS- Invalid WMA handle", __func__);
6869 return -ENOENT;
6870 }
6871 radar_event = (struct wma_dfs_radar_indication *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306872 qdf_mem_malloc(sizeof(struct wma_dfs_radar_indication));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006873 if (radar_event == NULL) {
6874 WMA_LOGE("%s:DFS- Invalid radar_event", __func__);
6875 return -ENOMEM;
6876 }
6877
6878 /*
6879 * Do not post multiple Radar events on the same channel.
6880 * But, when DFS test mode is enabled, allow multiple dfs
6881 * radar events to be posted on the same channel.
6882 */
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306883 qdf_spin_lock_bh(&ic->chan_lock);
Edhar, Mahesh Kumar35d9b2e2015-10-26 17:06:23 +05306884 if (!pmac->sap.SapDfsInfo.disable_dfs_ch_switch)
6885 wma->dfs_ic->disable_phy_err_processing = true;
6886
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006887 if ((ichan->ic_ieee != (wma->dfs_ic->last_radar_found_chan)) ||
6888 (pmac->sap.SapDfsInfo.disable_dfs_ch_switch == true)) {
6889 wma->dfs_ic->last_radar_found_chan = ichan->ic_ieee;
6890 /* Indicate the radar event to HDD to stop the netif Tx queues */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006891 wma_radar_event.chan_freq = ichan->ic_freq;
6892 wma_radar_event.dfs_radar_status = WMA_DFS_RADAR_FOUND;
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05306893 indication_status =
6894 wma->dfs_radar_indication_cb(hdd_ctx, &wma_radar_event);
6895 if (indication_status == false) {
6896 WMA_LOGE("%s:Application triggered channel switch in progress!.. drop radar event indiaction to SAP",
6897 __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306898 qdf_mem_free(radar_event);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306899 qdf_spin_unlock_bh(&ic->chan_lock);
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05306900 return 0;
6901 }
6902
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006903 WMA_LOGE("%s:DFS- RADAR INDICATED TO HDD", __func__);
6904
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05306905 wma_radar_event.ieee_chan_number = ichan->ic_ieee;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006906 /*
6907 * Indicate to the radar event to SAP to
6908 * select a new channel and set CSA IE
6909 */
6910 radar_event->vdev_id = ic->vdev_id;
6911 wma_get_channels(ichan, &radar_event->chan_list);
6912 radar_event->dfs_radar_status = WMA_DFS_RADAR_FOUND;
6913 radar_event->use_nol = ic->ic_dfs_usenol(ic);
6914 wma_send_msg(wma, WMA_DFS_RADAR_IND, (void *)radar_event, 0);
6915 WMA_LOGE("%s:DFS- WMA_DFS_RADAR_IND Message Posted", __func__);
6916 }
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306917 qdf_spin_unlock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006918
6919 return 0;
6920}
6921
6922#ifdef WLAN_FEATURE_MEMDUMP
6923/*
6924 * wma_process_fw_mem_dump_req() - Function to request fw memory dump from
6925 * firmware
6926 * @wma: Pointer to WMA handle
6927 * @mem_dump_req: Pointer for mem_dump_req
6928 *
6929 * This function sends memory dump request to firmware
6930 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306931 * Return: QDF_STATUS_SUCCESS for success otherwise failure
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006932 *
6933 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306934QDF_STATUS wma_process_fw_mem_dump_req(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006935 struct fw_dump_req *mem_dump_req)
6936{
Govind Singhaa64c242016-03-08 11:31:49 +05306937 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006938
6939 if (!mem_dump_req || !wma) {
6940 WMA_LOGE(FL("input pointer is NULL"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306941 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006942 }
6943
Govind Singhaa64c242016-03-08 11:31:49 +05306944 ret = wmi_unified_process_fw_mem_dump_cmd(wma->wmi_handle,
6945 (struct fw_dump_req_param *) mem_dump_req);
6946 if (ret)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306947 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006948
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306949 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006950}
6951
6952/**
6953 * wma_fw_mem_dump_rsp() - send fw mem dump response to SME
6954 *
6955 * @req_id - request id.
6956 * @status - copy status from the firmware.
6957 *
6958 * This function is called by the memory dump response handler to
6959 * indicate SME that firmware dump copy is complete
6960 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306961 * Return: QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006962 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306963static QDF_STATUS wma_fw_mem_dump_rsp(uint32_t req_id, uint32_t status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006964{
6965 struct fw_dump_rsp *dump_rsp;
6966 cds_msg_t sme_msg = {0};
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306967 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006968
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306969 dump_rsp = qdf_mem_malloc(sizeof(*dump_rsp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006970
6971 if (!dump_rsp) {
6972 WMA_LOGE(FL("Memory allocation failed."));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306973 qdf_status = QDF_STATUS_E_NOMEM;
6974 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006975 }
6976
6977 WMA_LOGI(FL("FW memory dump copy complete status: %d for request: %d"),
6978 status, req_id);
6979
6980 dump_rsp->request_id = req_id;
6981 dump_rsp->dump_complete = status;
6982
6983 sme_msg.type = eWNI_SME_FW_DUMP_IND;
6984 sme_msg.bodyptr = dump_rsp;
6985 sme_msg.bodyval = 0;
6986
Anurag Chouhan6d760662016-02-20 16:05:43 +05306987 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306988 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006989 WMA_LOGE(FL("Fail to post fw mem dump ind msg"));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306990 qdf_mem_free(dump_rsp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006991 }
6992
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306993 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006994}
6995
6996/**
6997 * wma_fw_mem_dump_event_handler() - handles fw memory dump event
6998 *
6999 * @handle: pointer to wma handle.
7000 * @cmd_param_info: pointer to TLV info received in the event.
7001 * @len: length of data in @cmd_param_info
7002 *
7003 * This function is a handler for firmware memory dump event.
7004 *
7005 * Return: integer (0 for success and error code otherwise)
7006 */
7007int wma_fw_mem_dump_event_handler(void *handle, u_int8_t *cmd_param_info,
7008 u_int32_t len)
7009{
7010 WMI_UPDATE_FW_MEM_DUMP_EVENTID_param_tlvs *param_buf;
7011 wmi_update_fw_mem_dump_fixed_param *event;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307012 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007013
7014 param_buf =
7015 (WMI_UPDATE_FW_MEM_DUMP_EVENTID_param_tlvs *) cmd_param_info;
7016 if (!param_buf) {
7017 WMA_LOGA("%s: Invalid stats event", __func__);
7018 return -EINVAL;
7019 }
7020
7021 event = param_buf->fixed_param;
7022
7023 status = wma_fw_mem_dump_rsp(event->request_id,
7024 event->fw_mem_dump_complete);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307025 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007026 WMA_LOGE("Error posting FW MEM DUMP RSP.");
7027 return -EINVAL;
7028 }
7029
7030 WMA_LOGI("FW MEM DUMP RSP posted successfully");
7031 return 0;
7032}
7033#endif /* WLAN_FEATURE_MEMDUMP */
7034
7035/*
7036 * wma_process_set_ie_info() - Function to send IE info to firmware
7037 * @wma: Pointer to WMA handle
7038 * @ie_data: Pointer for ie data
7039 *
7040 * This function sends IE information to firmware
7041 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307042 * Return: QDF_STATUS_SUCCESS for success otherwise failure
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007043 *
7044 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307045QDF_STATUS wma_process_set_ie_info(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007046 struct vdev_ie_info *ie_info)
7047{
Govind Singhaa64c242016-03-08 11:31:49 +05307048 struct vdev_ie_info_param cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007049 int ret;
7050
7051 if (!ie_info || !wma) {
7052 WMA_LOGE(FL("input pointer is NULL"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307053 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007054 }
7055
7056 /* Validate the input */
7057 if (ie_info->length <= 0) {
7058 WMA_LOGE(FL("Invalid IE length"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307059 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007060 }
7061
Govind Singhaa64c242016-03-08 11:31:49 +05307062 cmd.vdev_id = ie_info->vdev_id;
7063 cmd.ie_id = ie_info->ie_id;
7064 cmd.length = ie_info->length;
7065 cmd.data = ie_info->data;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007066
Govind Singhaa64c242016-03-08 11:31:49 +05307067 ret = wmi_unified_process_set_ie_info_cmd(wma->wmi_handle,
7068 &cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007069
7070 return ret;
7071}
7072
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307073/**
7074 * wma_get_bpf_caps_event_handler() - Event handler for get bpf capability
7075 * @handle: WMA global handle
7076 * @cmd_param_info: command event data
7077 * @len: Length of @cmd_param_info
7078 *
7079 * Return: 0 on Success or Errno on failure
7080 */
7081int wma_get_bpf_caps_event_handler(void *handle,
7082 u_int8_t *cmd_param_info,
7083 u_int32_t len)
7084{
7085 WMI_BPF_CAPABILIY_INFO_EVENTID_param_tlvs *param_buf;
7086 wmi_bpf_capability_info_evt_fixed_param *event;
7087 struct sir_bpf_get_offload *bpf_get_offload;
7088 tpAniSirGlobal pmac = (tpAniSirGlobal)cds_get_context(
7089 QDF_MODULE_ID_PE);
7090
7091 if (!pmac) {
7092 WMA_LOGE("%s: Invalid pmac", __func__);
7093 return -EINVAL;
7094 }
7095 if (!pmac->sme.pbpf_get_offload_cb) {
7096 WMA_LOGE("%s: Callback not registered", __func__);
7097 return -EINVAL;
7098 }
7099
7100 param_buf = (WMI_BPF_CAPABILIY_INFO_EVENTID_param_tlvs *)cmd_param_info;
7101 event = param_buf->fixed_param;
7102 bpf_get_offload = qdf_mem_malloc(sizeof(*bpf_get_offload));
7103
7104 if (!bpf_get_offload) {
7105 WMA_LOGP("%s: Memory allocation failed.", __func__);
7106 return -ENOMEM;
7107 }
7108
7109 bpf_get_offload->bpf_version = event->bpf_version;
7110 bpf_get_offload->max_bpf_filters = event->max_bpf_filters;
7111 bpf_get_offload->max_bytes_for_bpf_inst =
7112 event->max_bytes_for_bpf_inst;
7113 WMA_LOGD("%s: BPF capabilities version: %d max bpf filter size: %d",
7114 __func__, bpf_get_offload->bpf_version,
7115 bpf_get_offload->max_bytes_for_bpf_inst);
7116
7117 WMA_LOGD("%s: sending bpf capabilities event to hdd", __func__);
7118 pmac->sme.pbpf_get_offload_cb(pmac->hHdd, bpf_get_offload);
7119 qdf_mem_free(bpf_get_offload);
7120 return 0;
7121}
7122
7123/**
7124 * wma_get_bpf_capabilities - Send get bpf capability to firmware
7125 * @wma_handle: wma handle
7126 *
7127 * Return: QDF_STATUS enumeration.
7128 */
7129QDF_STATUS wma_get_bpf_capabilities(tp_wma_handle wma)
7130{
7131 QDF_STATUS status = QDF_STATUS_SUCCESS;
7132 wmi_bpf_get_capability_cmd_fixed_param *cmd;
7133 wmi_buf_t wmi_buf;
7134 uint32_t len;
7135 u_int8_t *buf_ptr;
7136
7137 if (!wma || !wma->wmi_handle) {
7138 WMA_LOGE(FL("WMA is closed, can not issue get BPF capab"));
7139 return QDF_STATUS_E_INVAL;
7140 }
7141
7142 if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
7143 WMI_SERVICE_BPF_OFFLOAD)) {
7144 WMA_LOGE(FL("BPF cababilities feature bit not enabled"));
7145 return QDF_STATUS_E_FAILURE;
7146 }
7147
7148 len = sizeof(*cmd);
7149 wmi_buf = wmi_buf_alloc(wma->wmi_handle, len);
7150 if (!wmi_buf) {
7151 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
7152 return QDF_STATUS_E_NOMEM;
7153 }
7154
7155 buf_ptr = (u_int8_t *) wmi_buf_data(wmi_buf);
7156 cmd = (wmi_bpf_get_capability_cmd_fixed_param *) buf_ptr;
7157 WMITLV_SET_HDR(&cmd->tlv_header,
7158 WMITLV_TAG_STRUC_wmi_bpf_get_capability_cmd_fixed_param,
7159 WMITLV_GET_STRUCT_TLVLEN(
7160 wmi_bpf_get_capability_cmd_fixed_param));
7161
7162 if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len,
7163 WMI_BPF_GET_CAPABILITY_CMDID)) {
7164 WMA_LOGE(FL("Failed to send BPF capability command"));
7165 wmi_buf_free(wmi_buf);
7166 return QDF_STATUS_E_FAILURE;
7167 }
7168 return status;
7169}
7170
7171/**
7172 * wma_set_bpf_instructions - Set bpf instructions to firmware
7173 * @wma: wma handle
7174 * @bpf_set_offload: Bpf offload information to set to firmware
7175 *
7176 * Return: QDF_STATUS enumeration
7177 */
7178QDF_STATUS wma_set_bpf_instructions(tp_wma_handle wma,
7179 struct sir_bpf_set_offload *bpf_set_offload)
7180{
7181 wmi_bpf_set_vdev_instructions_cmd_fixed_param *cmd;
7182 wmi_buf_t wmi_buf;
7183 uint32_t len = 0, len_aligned = 0;
7184 u_int8_t *buf_ptr;
7185
7186 if (!wma || !wma->wmi_handle) {
7187 WMA_LOGE("%s: WMA is closed, can not issue set BPF capability",
7188 __func__);
7189 return QDF_STATUS_E_INVAL;
7190 }
7191
7192 if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
7193 WMI_SERVICE_BPF_OFFLOAD)) {
7194 WMA_LOGE(FL("BPF offload feature Disabled"));
7195 return QDF_STATUS_E_NOSUPPORT;
7196 }
7197
7198 if (bpf_set_offload->total_length) {
7199 len_aligned = roundup(bpf_set_offload->current_length,
7200 sizeof(A_UINT32));
7201 len = len_aligned + WMI_TLV_HDR_SIZE;
7202 }
7203
7204 len += sizeof(*cmd);
7205 wmi_buf = wmi_buf_alloc(wma->wmi_handle, len);
7206 if (!wmi_buf) {
7207 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
7208 return QDF_STATUS_E_NOMEM;
7209 }
7210
7211 buf_ptr = (u_int8_t *) wmi_buf_data(wmi_buf);
7212 cmd = (wmi_bpf_set_vdev_instructions_cmd_fixed_param *) buf_ptr;
7213
7214 WMITLV_SET_HDR(&cmd->tlv_header,
7215 WMITLV_TAG_STRUC_wmi_bpf_set_vdev_instructions_cmd_fixed_param,
7216 WMITLV_GET_STRUCT_TLVLEN(
7217 wmi_bpf_set_vdev_instructions_cmd_fixed_param));
7218 cmd->vdev_id = bpf_set_offload->session_id;
7219 cmd->filter_id = bpf_set_offload->filter_id;
7220 cmd->total_length = bpf_set_offload->total_length;
7221 cmd->current_offset = bpf_set_offload->current_offset;
7222 cmd->current_length = bpf_set_offload->current_length;
7223
7224 if (bpf_set_offload->total_length) {
7225 buf_ptr +=
7226 sizeof(wmi_bpf_set_vdev_instructions_cmd_fixed_param);
7227 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, len_aligned);
7228 buf_ptr += WMI_TLV_HDR_SIZE;
7229 qdf_mem_copy(buf_ptr, bpf_set_offload->program,
7230 bpf_set_offload->current_length);
7231 qdf_mem_free(bpf_set_offload->program);
7232 }
7233
7234 if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len,
7235 WMI_BPF_SET_VDEV_INSTRUCTIONS_CMDID)) {
7236 WMA_LOGE(FL("Failed to send config bpf instructions command"));
7237 wmi_buf_free(wmi_buf);
7238 return QDF_STATUS_E_FAILURE;
7239 }
7240 return QDF_STATUS_SUCCESS;
7241}
Peng Xu8fdaa492016-06-22 10:20:47 -07007242
7243/**
7244 * wma_p2p_lo_start() - P2P listen offload start
7245 * @params: p2p listen offload parameters
7246 *
7247 * This function sends WMI command to start P2P listen offload.
7248 *
7249 * Return: QDF_STATUS enumeration
7250 */
7251QDF_STATUS wma_p2p_lo_start(struct sir_p2p_lo_start *params)
7252{
7253 wmi_buf_t buf;
7254 wmi_p2p_lo_start_cmd_fixed_param *cmd;
7255 int32_t len = sizeof(*cmd);
7256 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
7257 uint8_t *buf_ptr;
7258 int ret;
Peng Xu4225c152016-07-14 21:18:14 -07007259 int device_types_len_aligned, probe_resp_len_aligned;
Peng Xu8fdaa492016-06-22 10:20:47 -07007260
7261 if (NULL == wma) {
7262 WMA_LOGE("%s: wma context is NULL", __func__);
7263 return QDF_STATUS_E_INVAL;
7264 }
7265
Peng Xu4225c152016-07-14 21:18:14 -07007266 device_types_len_aligned = qdf_roundup(params->dev_types_len,
7267 sizeof(A_UINT32));
7268 probe_resp_len_aligned = qdf_roundup(params->probe_resp_len,
7269 sizeof(A_UINT32));
7270
7271 len += 2 * WMI_TLV_HDR_SIZE + device_types_len_aligned +
7272 probe_resp_len_aligned;
Peng Xu8fdaa492016-06-22 10:20:47 -07007273
7274 buf = wmi_buf_alloc(wma->wmi_handle, len);
7275 if (!buf) {
7276 WMA_LOGP("%s: failed to allocate memory for p2p lo start",
7277 __func__);
7278 return QDF_STATUS_E_NOMEM;
7279 }
7280
7281 cmd = (wmi_p2p_lo_start_cmd_fixed_param *)wmi_buf_data(buf);
7282 buf_ptr = (uint8_t *) wmi_buf_data(buf);
7283
7284 WMITLV_SET_HDR(&cmd->tlv_header,
7285 WMITLV_TAG_STRUC_wmi_p2p_lo_start_cmd_fixed_param,
7286 WMITLV_GET_STRUCT_TLVLEN(
7287 wmi_p2p_lo_start_cmd_fixed_param));
7288
7289 cmd->vdev_id = params->vdev_id;
7290 cmd->ctl_flags = params->ctl_flags;
7291 cmd->channel = params->freq;
7292 cmd->period = params->period;
7293 cmd->interval = params->interval;
7294 cmd->count = params->count;
Peng Xu4225c152016-07-14 21:18:14 -07007295 cmd->device_types_len = params->dev_types_len;
7296 cmd->prob_resp_len = params->probe_resp_len;
Peng Xu8fdaa492016-06-22 10:20:47 -07007297
7298 buf_ptr += sizeof(wmi_p2p_lo_start_cmd_fixed_param);
7299 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE,
Peng Xu4225c152016-07-14 21:18:14 -07007300 device_types_len_aligned);
Peng Xu8fdaa492016-06-22 10:20:47 -07007301 buf_ptr += WMI_TLV_HDR_SIZE;
7302 qdf_mem_copy(buf_ptr, params->device_types, params->dev_types_len);
7303
Peng Xu4225c152016-07-14 21:18:14 -07007304 buf_ptr += device_types_len_aligned;
7305 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, probe_resp_len_aligned);
Peng Xu8fdaa492016-06-22 10:20:47 -07007306 buf_ptr += WMI_TLV_HDR_SIZE;
7307 qdf_mem_copy(buf_ptr, params->probe_resp_tmplt, params->probe_resp_len);
7308
7309 WMA_LOGI("%s: Sending WMI_P2P_LO_START command, channel=%d, period=%d, interval=%d, count=%d",
7310 __func__, cmd->channel, cmd->period,
7311 cmd->interval, cmd->count);
7312
7313 ret = wmi_unified_cmd_send(wma->wmi_handle,
7314 buf, len,
7315 WMI_P2P_LISTEN_OFFLOAD_START_CMDID);
7316 if (ret) {
7317 WMA_LOGE("Failed to send p2p lo start: %d", ret);
7318 wmi_buf_free(buf);
7319 }
7320
7321 WMA_LOGI("%s: Successfully sent WMI_P2P_LO_START", __func__);
7322 wma->interfaces[params->vdev_id].p2p_lo_in_progress = true;
7323
7324 return ret;
7325}
7326
7327/**
7328 * wma_p2p_lo_stop() - P2P listen offload stop
7329 * @vdev_id: vdev identifier
7330 *
7331 * This function sends WMI command to stop P2P listen offload.
7332 *
7333 * Return: QDF_STATUS enumeration
7334 */
7335QDF_STATUS wma_p2p_lo_stop(u_int32_t vdev_id)
7336{
7337 wmi_buf_t buf;
7338 wmi_p2p_lo_stop_cmd_fixed_param *cmd;
7339 int32_t len;
7340 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
7341 int ret;
7342
7343 if (NULL == wma) {
7344 WMA_LOGE("%s: wma context is NULL", __func__);
7345 return QDF_STATUS_E_INVAL;
7346 }
7347
7348 len = sizeof(*cmd);
7349 buf = wmi_buf_alloc(wma->wmi_handle, len);
7350 if (!buf) {
7351 WMA_LOGP("%s: failed to allocate memory for p2p lo stop",
7352 __func__);
7353 return QDF_STATUS_E_NOMEM;
7354 }
7355 cmd = (wmi_p2p_lo_stop_cmd_fixed_param *)wmi_buf_data(buf);
7356
7357 WMITLV_SET_HDR(&cmd->tlv_header,
7358 WMITLV_TAG_STRUC_wmi_p2p_lo_stop_cmd_fixed_param,
7359 WMITLV_GET_STRUCT_TLVLEN(
7360 wmi_p2p_lo_stop_cmd_fixed_param));
7361
7362 cmd->vdev_id = vdev_id;
7363
7364 WMA_LOGI("%s: Sending WMI_P2P_LO_STOP command", __func__);
7365
7366 ret = wmi_unified_cmd_send(wma->wmi_handle,
7367 buf, len,
7368 WMI_P2P_LISTEN_OFFLOAD_STOP_CMDID);
7369 if (ret) {
7370 WMA_LOGE("Failed to send p2p lo stop: %d", ret);
7371 wmi_buf_free(buf);
7372 }
7373
7374 WMA_LOGI("%s: Successfully sent WMI_P2P_LO_STOP", __func__);
7375 wma->interfaces[vdev_id].p2p_lo_in_progress = false;
7376
7377 return ret;
7378}
7379
7380/**
7381 * wma_p2p_lo_event_handler() - p2p lo event
7382 * @handle: the WMA handle
7383 * @event_buf: buffer with the event parameters
7384 * @len: length of the buffer
7385 *
7386 * This function receives P2P listen offload stop event from FW and
7387 * pass the event information to upper layer.
7388 *
7389 * Return: 0 on success
7390 */
7391int wma_p2p_lo_event_handler(void *handle, uint8_t *event_buf,
7392 uint32_t len)
7393{
7394 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
7395 struct sir_p2p_lo_event *event;
7396 WMI_P2P_LISTEN_OFFLOAD_STOPPED_EVENTID_param_tlvs *param_tlvs;
7397 wmi_p2p_lo_stopped_event_fixed_param *fix_param;
7398 tpAniSirGlobal p_mac = cds_get_context(QDF_MODULE_ID_PE);
7399
7400 if (!p_mac) {
7401 WMA_LOGE("%s: Invalid p_mac", __func__);
7402 return -EINVAL;
7403 }
7404
7405 if (!p_mac->sme.p2p_lo_event_callback) {
7406 WMA_LOGE("%s: Callback not registered", __func__);
7407 return -EINVAL;
7408 }
7409
7410 param_tlvs = (WMI_P2P_LISTEN_OFFLOAD_STOPPED_EVENTID_param_tlvs *)
7411 event_buf;
7412 fix_param = param_tlvs->fixed_param;
7413 event = qdf_mem_malloc(sizeof(*event));
7414 if (event == NULL) {
7415 WMA_LOGE("Event allocation failed");
7416 return -ENOMEM;
7417 }
7418 event->vdev_id = fix_param->vdev_id;
7419 event->reason_code = fix_param->reason;
7420
7421 p_mac->sme.p2p_lo_event_callback(p_mac->hHdd, event);
7422
7423 wma->interfaces[event->vdev_id].p2p_lo_in_progress = false;
7424
7425 return 0;
7426}