blob: ef525be6de37a02a691777b038442a031629f20f [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"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080046#include "wlan_tgt_def_config.h"
47
Nirav Shahcbc6d722016-03-01 16:24:53 +053048#include "qdf_nbuf.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053049#include "qdf_types.h"
Anurag Chouhan600c3a02016-03-01 10:33:54 +053050#include "qdf_mem.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080051#include "ol_txrx_peer_find.h"
52
53#include "wma_types.h"
54#include "lim_api.h"
55#include "lim_session_utils.h"
56
57#include "cds_utils.h"
58
59#if !defined(REMOVE_PKT_LOG)
60#include "pktlog_ac.h"
61#endif /* REMOVE_PKT_LOG */
62
63#include "dbglog_host.h"
64#include "csr_api.h"
65#include "ol_fw.h"
66
67#include "dfs.h"
68#include "radar_filters.h"
69#include "wma_internal.h"
70
71#ifndef ARRAY_LENGTH
72#define ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0]))
73#endif
74
75#define WMA_WOW_STA_WAKE_UP_EVENTS ((1 << WOW_CSA_IE_EVENT) |\
76 (1 << WOW_CLIENT_KICKOUT_EVENT) |\
77 (1 << WOW_PATTERN_MATCH_EVENT) |\
78 (1 << WOW_MAGIC_PKT_RECVD_EVENT) |\
79 (1 << WOW_DEAUTH_RECVD_EVENT) |\
80 (1 << WOW_DISASSOC_RECVD_EVENT) |\
81 (1 << WOW_BMISS_EVENT) |\
82 (1 << WOW_GTK_ERR_EVENT) |\
83 (1 << WOW_BETTER_AP_EVENT) |\
84 (1 << WOW_HTT_EVENT) |\
85 (1 << WOW_RA_MATCH_EVENT) |\
86 (1 << WOW_NLO_DETECTED_EVENT) |\
87 (1 << WOW_EXTSCAN_EVENT))\
88
89#define WMA_WOW_SAP_WAKE_UP_EVENTS ((1 << WOW_PROBE_REQ_WPS_IE_EVENT) |\
90 (1 << WOW_PATTERN_MATCH_EVENT) |\
91 (1 << WOW_AUTH_REQ_EVENT) |\
92 (1 << WOW_ASSOC_REQ_EVENT) |\
93 (1 << WOW_DEAUTH_RECVD_EVENT) |\
94 (1 << WOW_DISASSOC_RECVD_EVENT) |\
95 (1 << WOW_HTT_EVENT))\
96
97static const uint8_t arp_ptrn[] = {0x08, 0x06};
98static const uint8_t arp_mask[] = {0xff, 0xff};
99static const uint8_t ns_ptrn[] = {0x86, 0xDD};
100static const uint8_t discvr_ptrn[] = {0xe0, 0x00, 0x00, 0xf8};
101static const uint8_t discvr_mask[] = {0xf0, 0x00, 0x00, 0xf8};
102
103#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
104/**
105 * wma_post_auto_shutdown_msg() - to post auto shutdown event to sme
106 *
107 * Return: 0 for success or error code
108 */
109static int wma_post_auto_shutdown_msg(void)
110{
111 tSirAutoShutdownEvtParams *auto_sh_evt;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530112 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800113 cds_msg_t sme_msg = { 0 };
114
115 auto_sh_evt = (tSirAutoShutdownEvtParams *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530116 qdf_mem_malloc(sizeof(tSirAutoShutdownEvtParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800117 if (!auto_sh_evt) {
118 WMA_LOGE(FL("No Mem"));
119 return -ENOMEM;
120 }
121
122 auto_sh_evt->shutdown_reason =
123 WMI_HOST_AUTO_SHUTDOWN_REASON_TIMER_EXPIRY;
124 sme_msg.type = eWNI_SME_AUTO_SHUTDOWN_IND;
125 sme_msg.bodyptr = auto_sh_evt;
126 sme_msg.bodyval = 0;
127
Anurag Chouhan6d760662016-02-20 16:05:43 +0530128 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530129 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800130 WMA_LOGE("Fail to post eWNI_SME_AUTO_SHUTDOWN_IND msg to SME");
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530131 qdf_mem_free(auto_sh_evt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800132 return -EINVAL;
133 }
134
135 return 0;
136}
137#endif
138/**
139 * wma_send_snr_request() - send request to fw to get RSSI stats
140 * @wma_handle: wma handle
141 * @pGetRssiReq: get RSSI request
142 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530143 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800144 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530145QDF_STATUS wma_send_snr_request(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800146 void *pGetRssiReq)
147{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800148 tAniGetRssiReq *pRssiBkUp = NULL;
149
150 /* command is in progess */
151 if (NULL != wma_handle->pGetRssiReq)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530152 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800153
154 /* create a copy of csrRssiCallback to send rssi value
155 * after wmi event
156 */
157 if (pGetRssiReq) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530158 pRssiBkUp = qdf_mem_malloc(sizeof(tAniGetRssiReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800159 if (!pRssiBkUp) {
160 WMA_LOGE("Failed to allocate memory for tAniGetRssiReq");
161 wma_handle->pGetRssiReq = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530162 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800163 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530164 qdf_mem_set(pRssiBkUp, sizeof(tAniGetRssiReq), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800165 pRssiBkUp->sessionId =
166 ((tAniGetRssiReq *) pGetRssiReq)->sessionId;
167 pRssiBkUp->rssiCallback =
168 ((tAniGetRssiReq *) pGetRssiReq)->rssiCallback;
169 pRssiBkUp->pDevContext =
170 ((tAniGetRssiReq *) pGetRssiReq)->pDevContext;
171 wma_handle->pGetRssiReq = (void *)pRssiBkUp;
172 }
173
Govind Singhaa64c242016-03-08 11:31:49 +0530174 if (wmi_unified_snr_request_cmd(wma_handle->wmi_handle)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800175 WMA_LOGE("Failed to send host stats request to fw");
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530176 qdf_mem_free(pRssiBkUp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800177 wma_handle->pGetRssiReq = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530178 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800179 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530180 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800181}
182
183/**
184 * wma_get_snr() - get RSSI from fw
185 * @psnr_req: request params
186 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530187 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800188 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530189QDF_STATUS wma_get_snr(tAniGetSnrReq *psnr_req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800190{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800191 tAniGetSnrReq *psnr_req_bkp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800192 tp_wma_handle wma_handle = NULL;
193 struct wma_txrx_node *intr;
194
Anurag Chouhan6d760662016-02-20 16:05:43 +0530195 wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800196
197 if (NULL == wma_handle) {
198 WMA_LOGE("%s : Failed to get wma_handle", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530199 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800200 }
201
202 intr = &wma_handle->interfaces[psnr_req->sessionId];
203 /* command is in progess */
204 if (NULL != intr->psnr_req) {
205 WMA_LOGE("%s : previous snr request is pending", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530206 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800207 }
208
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530209 psnr_req_bkp = qdf_mem_malloc(sizeof(tAniGetSnrReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800210 if (!psnr_req_bkp) {
211 WMA_LOGE("Failed to allocate memory for tAniGetSnrReq");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530212 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800213 }
214
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530215 qdf_mem_set(psnr_req_bkp, sizeof(tAniGetSnrReq), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800216 psnr_req_bkp->staId = psnr_req->staId;
217 psnr_req_bkp->pDevContext = psnr_req->pDevContext;
218 psnr_req_bkp->snrCallback = psnr_req->snrCallback;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800219 intr->psnr_req = (void *)psnr_req_bkp;
Govind Singhaa64c242016-03-08 11:31:49 +0530220
221 if (wmi_unified_snr_cmd(wma_handle->wmi_handle,
222 psnr_req->sessionId)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800223 WMA_LOGE("Failed to send host stats request to fw");
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530224 qdf_mem_free(psnr_req_bkp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800225 intr->psnr_req = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530226 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800227 }
228
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530229 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800230}
231
232/**
233 * wma_process_link_status_req() - process link status request from UMAC
234 * @wma: wma handle
235 * @pGetLinkStatus: get link params
236 *
237 * Return: none
238 */
239void wma_process_link_status_req(tp_wma_handle wma,
240 tAniGetLinkStatus *pGetLinkStatus)
241{
Govind Singhaa64c242016-03-08 11:31:49 +0530242 struct link_status_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800243 struct wma_txrx_node *iface =
244 &wma->interfaces[pGetLinkStatus->sessionId];
245
246 if (iface->plink_status_req) {
247 WMA_LOGE("%s:previous link status request is pending,deleting the new request",
248 __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530249 qdf_mem_free(pGetLinkStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800250 return;
251 }
252
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800253 iface->plink_status_req = pGetLinkStatus;
Govind Singhaa64c242016-03-08 11:31:49 +0530254 cmd.session_id = pGetLinkStatus->sessionId;
255 if (wmi_unified_link_status_req_cmd(wma->wmi_handle, &cmd)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800256 WMA_LOGE("Failed to send WMI link status request to fw");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800257 iface->plink_status_req = NULL;
258 goto end;
259 }
260
261 return;
262
263end:
264 wma_post_link_status(pGetLinkStatus, LINK_STATUS_LEGACY);
265}
266
267#ifdef FEATURE_WLAN_LPHB
268/**
269 * wma_lphb_conf_hbenable() - enable command of LPHB configuration requests
270 * @wma_handle: WMA handle
271 * @lphb_conf_req: configuration info
272 * @by_user: whether this call is from user or cached resent
273 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530274 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800275 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530276QDF_STATUS wma_lphb_conf_hbenable(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800277 tSirLPHBReq *lphb_conf_req, bool by_user)
278{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530279 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800280 int status = 0;
281 tSirLPHBEnableStruct *ts_lphb_enable;
Govind Singhaa64c242016-03-08 11:31:49 +0530282 wmi_hb_set_enable_cmd_fixed_param hb_enable_fp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800283 int i;
284
285 if (lphb_conf_req == NULL) {
286 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530287 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800288 }
289
290 ts_lphb_enable = &(lphb_conf_req->params.lphbEnableReq);
291 WMA_LOGI("%s: WMA --> WMI_HB_SET_ENABLE enable=%d, item=%d, session=%d",
292 __func__,
293 ts_lphb_enable->enable,
294 ts_lphb_enable->item, ts_lphb_enable->session);
295
296 if ((ts_lphb_enable->item != 1) && (ts_lphb_enable->item != 2)) {
297 WMA_LOGE("%s : LPHB configuration wrong item %d",
298 __func__, ts_lphb_enable->item);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530299 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800300 }
301
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800302
303 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530304 hb_enable_fp.vdev_id = ts_lphb_enable->session;
305 hb_enable_fp.enable = ts_lphb_enable->enable;
306 hb_enable_fp.item = ts_lphb_enable->item;
307 hb_enable_fp.session = ts_lphb_enable->session;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800308
Govind Singhaa64c242016-03-08 11:31:49 +0530309 status = wmi_unified_lphb_config_hbenable_cmd(wma_handle->wmi_handle,
310 &hb_enable_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800311 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530312 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800313 goto error;
314 }
315
316 if (by_user) {
317 /* target already configured, now cache command status */
318 if (ts_lphb_enable->enable) {
319 i = ts_lphb_enable->item - 1;
320 wma_handle->wow.lphb_cache[i].cmd
321 = LPHB_SET_EN_PARAMS_INDID;
322 wma_handle->wow.lphb_cache[i].params.lphbEnableReq.
323 enable = ts_lphb_enable->enable;
324 wma_handle->wow.lphb_cache[i].params.lphbEnableReq.
325 item = ts_lphb_enable->item;
326 wma_handle->wow.lphb_cache[i].params.lphbEnableReq.
327 session = ts_lphb_enable->session;
328
329 WMA_LOGI("%s: cached LPHB status in WMA context for item %d",
330 __func__, i);
331 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530332 qdf_mem_zero((void *)&wma_handle->wow.lphb_cache,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800333 sizeof(wma_handle->wow.lphb_cache));
334 WMA_LOGI("%s: cleared all cached LPHB status in WMA context",
335 __func__);
336 }
337 }
338
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530339 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800340error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530341 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800342}
343
344/**
345 * wma_lphb_conf_tcp_params() - set tcp params of LPHB configuration requests
346 * @wma_handle: wma handle
347 * @lphb_conf_req: lphb config request
348 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530349 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800350 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530351QDF_STATUS wma_lphb_conf_tcp_params(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800352 tSirLPHBReq *lphb_conf_req)
353{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530354 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800355 int status = 0;
356 tSirLPHBTcpParamStruct *ts_lphb_tcp_param;
Govind Singhaa64c242016-03-08 11:31:49 +0530357 wmi_hb_set_tcp_params_cmd_fixed_param hb_tcp_params_fp = {0};
358
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800359
360 if (lphb_conf_req == NULL) {
361 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530362 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800363 }
364
365 ts_lphb_tcp_param = &(lphb_conf_req->params.lphbTcpParamReq);
Srinivas Girigowda9dc32cf2015-11-19 14:47:04 -0800366 WMA_LOGI("%s: WMA --> WMI_HB_SET_TCP_PARAMS srv_ip=%08x, "
367 "dev_ip=%08x, src_port=%d, dst_port=%d, timeout=%d, "
368 "session=%d, gateway_mac="MAC_ADDRESS_STR", timePeriodSec=%d, "
369 "tcpSn=%d", __func__, ts_lphb_tcp_param->srv_ip,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800370 ts_lphb_tcp_param->dev_ip, ts_lphb_tcp_param->src_port,
371 ts_lphb_tcp_param->dst_port, ts_lphb_tcp_param->timeout,
Srinivas Girigowda9dc32cf2015-11-19 14:47:04 -0800372 ts_lphb_tcp_param->session,
373 MAC_ADDR_ARRAY(ts_lphb_tcp_param->gateway_mac.bytes),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800374 ts_lphb_tcp_param->timePeriodSec, ts_lphb_tcp_param->tcpSn);
375
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800376 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530377 hb_tcp_params_fp.vdev_id = ts_lphb_tcp_param->session;
378 hb_tcp_params_fp.srv_ip = ts_lphb_tcp_param->srv_ip;
379 hb_tcp_params_fp.dev_ip = ts_lphb_tcp_param->dev_ip;
380 hb_tcp_params_fp.seq = ts_lphb_tcp_param->tcpSn;
381 hb_tcp_params_fp.src_port = ts_lphb_tcp_param->src_port;
382 hb_tcp_params_fp.dst_port = ts_lphb_tcp_param->dst_port;
383 hb_tcp_params_fp.interval = ts_lphb_tcp_param->timePeriodSec;
384 hb_tcp_params_fp.timeout = ts_lphb_tcp_param->timeout;
385 hb_tcp_params_fp.session = ts_lphb_tcp_param->session;
Srinivas Girigowda9dc32cf2015-11-19 14:47:04 -0800386 WMI_CHAR_ARRAY_TO_MAC_ADDR(ts_lphb_tcp_param->gateway_mac.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +0530387 &hb_tcp_params_fp.gateway_mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800388
Govind Singhaa64c242016-03-08 11:31:49 +0530389 status = wmi_unified_lphb_config_tcp_params_cmd(wma_handle->wmi_handle,
390 &hb_tcp_params_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800391 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530392 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800393 goto error;
394 }
395
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530396 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800397error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530398 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800399}
400
401/**
402 * wma_lphb_conf_tcp_pkt_filter() - configure tcp packet filter command of LPHB
403 * @wma_handle: wma handle
404 * @lphb_conf_req: lphb config request
405 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530406 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800407 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530408QDF_STATUS wma_lphb_conf_tcp_pkt_filter(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800409 tSirLPHBReq *lphb_conf_req)
410{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530411 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800412 int status = 0;
413 tSirLPHBTcpFilterStruct *ts_lphb_tcp_filter;
Govind Singhaa64c242016-03-08 11:31:49 +0530414 wmi_hb_set_tcp_pkt_filter_cmd_fixed_param hb_tcp_filter_fp = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800415
416 if (lphb_conf_req == NULL) {
417 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530418 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800419 }
420
421 ts_lphb_tcp_filter = &(lphb_conf_req->params.lphbTcpFilterReq);
422 WMA_LOGI("%s: WMA --> WMI_HB_SET_TCP_PKT_FILTER length=%d, offset=%d, session=%d, "
423 "filter=%2x:%2x:%2x:%2x:%2x:%2x ...", __func__,
424 ts_lphb_tcp_filter->length, ts_lphb_tcp_filter->offset,
425 ts_lphb_tcp_filter->session, ts_lphb_tcp_filter->filter[0],
426 ts_lphb_tcp_filter->filter[1], ts_lphb_tcp_filter->filter[2],
427 ts_lphb_tcp_filter->filter[3], ts_lphb_tcp_filter->filter[4],
428 ts_lphb_tcp_filter->filter[5]);
429
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800430 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530431 hb_tcp_filter_fp.vdev_id = ts_lphb_tcp_filter->session;
432 hb_tcp_filter_fp.length = ts_lphb_tcp_filter->length;
433 hb_tcp_filter_fp.offset = ts_lphb_tcp_filter->offset;
434 hb_tcp_filter_fp.session = ts_lphb_tcp_filter->session;
435 memcpy((void *)&hb_tcp_filter_fp.filter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800436 (void *)&ts_lphb_tcp_filter->filter,
437 WMI_WLAN_HB_MAX_FILTER_SIZE);
438
Govind Singhaa64c242016-03-08 11:31:49 +0530439 status = wmi_unified_lphb_config_tcp_pkt_filter_cmd(wma_handle->wmi_handle,
440 &hb_tcp_filter_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800441 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530442 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800443 goto error;
444 }
445
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530446 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800447error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530448 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800449}
450
451/**
452 * wma_lphb_conf_udp_params() - configure udp param command of LPHB
453 * @wma_handle: wma handle
454 * @lphb_conf_req: lphb config request
455 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530456 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800457 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530458QDF_STATUS wma_lphb_conf_udp_params(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800459 tSirLPHBReq *lphb_conf_req)
460{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530461 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800462 int status = 0;
463 tSirLPHBUdpParamStruct *ts_lphb_udp_param;
Govind Singhaa64c242016-03-08 11:31:49 +0530464 wmi_hb_set_udp_params_cmd_fixed_param hb_udp_params_fp = {0};
465
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800466
467 if (lphb_conf_req == NULL) {
468 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530469 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800470 }
471
472 ts_lphb_udp_param = &(lphb_conf_req->params.lphbUdpParamReq);
473 WMA_LOGI("%s: WMA --> WMI_HB_SET_UDP_PARAMS srv_ip=%d, dev_ip=%d, src_port=%d, "
474 "dst_port=%d, interval=%d, timeout=%d, session=%d, "
Srinivas Girigowda9eddfda2015-11-19 14:38:02 -0800475 "gateway_mac="MAC_ADDRESS_STR, __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800476 ts_lphb_udp_param->srv_ip, ts_lphb_udp_param->dev_ip,
477 ts_lphb_udp_param->src_port, ts_lphb_udp_param->dst_port,
478 ts_lphb_udp_param->interval, ts_lphb_udp_param->timeout,
Srinivas Girigowda9eddfda2015-11-19 14:38:02 -0800479 ts_lphb_udp_param->session,
480 MAC_ADDR_ARRAY(ts_lphb_udp_param->gateway_mac.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800481
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800482
483 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530484 hb_udp_params_fp.vdev_id = ts_lphb_udp_param->session;
485 hb_udp_params_fp.srv_ip = ts_lphb_udp_param->srv_ip;
486 hb_udp_params_fp.dev_ip = ts_lphb_udp_param->dev_ip;
487 hb_udp_params_fp.src_port = ts_lphb_udp_param->src_port;
488 hb_udp_params_fp.dst_port = ts_lphb_udp_param->dst_port;
489 hb_udp_params_fp.interval = ts_lphb_udp_param->interval;
490 hb_udp_params_fp.timeout = ts_lphb_udp_param->timeout;
491 hb_udp_params_fp.session = ts_lphb_udp_param->session;
Srinivas Girigowda9eddfda2015-11-19 14:38:02 -0800492 WMI_CHAR_ARRAY_TO_MAC_ADDR(ts_lphb_udp_param->gateway_mac.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +0530493 &hb_udp_params_fp.gateway_mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800494
Govind Singhaa64c242016-03-08 11:31:49 +0530495 status = wmi_unified_lphb_config_udp_params_cmd(wma_handle->wmi_handle,
496 &hb_udp_params_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800497 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530498 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800499 goto error;
500 }
501
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530502 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800503error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530504 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800505}
506
507/**
508 * wma_lphb_conf_udp_pkt_filter() - configure udp pkt filter command of LPHB
509 * @wma_handle: wma handle
510 * @lphb_conf_req: lphb config request
511 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530512 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800513 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530514QDF_STATUS wma_lphb_conf_udp_pkt_filter(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800515 tSirLPHBReq *lphb_conf_req)
516{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530517 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800518 int status = 0;
519 tSirLPHBUdpFilterStruct *ts_lphb_udp_filter;
Govind Singhaa64c242016-03-08 11:31:49 +0530520 wmi_hb_set_udp_pkt_filter_cmd_fixed_param hb_udp_filter_fp = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800521
522 if (lphb_conf_req == NULL) {
523 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530524 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800525 }
526
527 ts_lphb_udp_filter = &(lphb_conf_req->params.lphbUdpFilterReq);
528 WMA_LOGI("%s: WMA --> WMI_HB_SET_UDP_PKT_FILTER length=%d, offset=%d, session=%d, "
529 "filter=%2x:%2x:%2x:%2x:%2x:%2x ...", __func__,
530 ts_lphb_udp_filter->length, ts_lphb_udp_filter->offset,
531 ts_lphb_udp_filter->session, ts_lphb_udp_filter->filter[0],
532 ts_lphb_udp_filter->filter[1], ts_lphb_udp_filter->filter[2],
533 ts_lphb_udp_filter->filter[3], ts_lphb_udp_filter->filter[4],
534 ts_lphb_udp_filter->filter[5]);
535
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800536
537 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530538 hb_udp_filter_fp.vdev_id = ts_lphb_udp_filter->session;
539 hb_udp_filter_fp.length = ts_lphb_udp_filter->length;
540 hb_udp_filter_fp.offset = ts_lphb_udp_filter->offset;
541 hb_udp_filter_fp.session = ts_lphb_udp_filter->session;
542 memcpy((void *)&hb_udp_filter_fp.filter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800543 (void *)&ts_lphb_udp_filter->filter,
544 WMI_WLAN_HB_MAX_FILTER_SIZE);
545
Govind Singhaa64c242016-03-08 11:31:49 +0530546 status = wmi_unified_lphb_config_udp_pkt_filter_cmd(wma_handle->wmi_handle,
547 &hb_udp_filter_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800548 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530549 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800550 goto error;
551 }
552
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530553 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800554error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530555 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800556}
557
558/**
559 * wma_process_lphb_conf_req() - handle LPHB configuration requests
560 * @wma_handle: wma handle
561 * @lphb_conf_req: lphb config request
562 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530563 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800564 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530565QDF_STATUS wma_process_lphb_conf_req(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800566 tSirLPHBReq *lphb_conf_req)
567{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530568 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800569
570 if (lphb_conf_req == NULL) {
571 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530572 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800573 }
574
575 WMA_LOGI("%s : LPHB configuration cmd id is %d", __func__,
576 lphb_conf_req->cmd);
577 switch (lphb_conf_req->cmd) {
578 case LPHB_SET_EN_PARAMS_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530579 qdf_status = wma_lphb_conf_hbenable(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800580 lphb_conf_req, true);
581 break;
582
583 case LPHB_SET_TCP_PARAMS_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530584 qdf_status = wma_lphb_conf_tcp_params(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800585 lphb_conf_req);
586 break;
587
588 case LPHB_SET_TCP_PKT_FILTER_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530589 qdf_status = wma_lphb_conf_tcp_pkt_filter(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800590 lphb_conf_req);
591 break;
592
593 case LPHB_SET_UDP_PARAMS_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530594 qdf_status = wma_lphb_conf_udp_params(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800595 lphb_conf_req);
596 break;
597
598 case LPHB_SET_UDP_PKT_FILTER_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530599 qdf_status = wma_lphb_conf_udp_pkt_filter(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800600 lphb_conf_req);
601 break;
602
603 case LPHB_SET_NETWORK_INFO_INDID:
604 default:
605 break;
606 }
607
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530608 qdf_mem_free(lphb_conf_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530609 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800610}
611#endif /* FEATURE_WLAN_LPHB */
612
613/**
614 * wma_process_dhcp_ind() - process dhcp indication from SME
615 * @wma_handle: wma handle
616 * @ta_dhcp_ind: DHCP indication
617 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530618 * Return: QDF Status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800619 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530620QDF_STATUS wma_process_dhcp_ind(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800621 tAniDHCPInd *ta_dhcp_ind)
622{
623 uint8_t vdev_id;
624 int status = 0;
Govind Singhaa64c242016-03-08 11:31:49 +0530625 wmi_peer_set_param_cmd_fixed_param peer_set_param_fp = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800626
627 if (!ta_dhcp_ind) {
628 WMA_LOGE("%s : DHCP indication is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530629 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800630 }
631
Srinivas Girigowda296105a2015-09-24 16:31:16 -0700632 if (!wma_find_vdev_by_addr(wma_handle,
633 ta_dhcp_ind->adapterMacAddr.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800634 &vdev_id)) {
635 WMA_LOGE("%s: Failed to find vdev id for DHCP indication",
636 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530637 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800638 }
639
640 WMA_LOGI("%s: WMA --> WMI_PEER_SET_PARAM triggered by DHCP, "
641 "msgType=%s,"
642 "device_mode=%d, macAddr=" MAC_ADDRESS_STR,
643 __func__,
644 ta_dhcp_ind->msgType == WMA_DHCP_START_IND ?
645 "WMA_DHCP_START_IND" : "WMA_DHCP_STOP_IND",
646 ta_dhcp_ind->device_mode,
Srinivas Girigowda296105a2015-09-24 16:31:16 -0700647 MAC_ADDR_ARRAY(ta_dhcp_ind->peerMacAddr.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800648
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800649 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530650 peer_set_param_fp.vdev_id = vdev_id;
651 peer_set_param_fp.param_id = WMI_PEER_CRIT_PROTO_HINT_ENABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800652 if (WMA_DHCP_START_IND == ta_dhcp_ind->msgType)
Govind Singhaa64c242016-03-08 11:31:49 +0530653 peer_set_param_fp.param_value = 1;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800654 else
Govind Singhaa64c242016-03-08 11:31:49 +0530655 peer_set_param_fp.param_value = 0;
Srinivas Girigowda296105a2015-09-24 16:31:16 -0700656 WMI_CHAR_ARRAY_TO_MAC_ADDR(ta_dhcp_ind->peerMacAddr.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +0530657 &peer_set_param_fp.peer_macaddr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800658
Govind Singhaa64c242016-03-08 11:31:49 +0530659 status = wmi_unified_process_dhcp_ind(wma_handle->wmi_handle,
660 &peer_set_param_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800661 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530662 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800663 }
664
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530665 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800666}
667
668/**
669 * wma_chan_to_mode() - convert channel to phy mode
670 * @chan: channel number
671 * @chan_width: channel width
672 * @vht_capable: vht capable
673 * @dot11_mode: 802.11 mode
674 *
675 * Return: return phy mode
676 */
677WLAN_PHY_MODE wma_chan_to_mode(u8 chan, phy_ch_width chan_width,
678 u8 vht_capable, u8 dot11_mode)
679{
680 WLAN_PHY_MODE phymode = MODE_UNKNOWN;
681
682 /* 2.4 GHz band */
683 if ((chan >= WMA_11G_CHANNEL_BEGIN) && (chan <= WMA_11G_CHANNEL_END)) {
684 switch (chan_width) {
685 case CH_WIDTH_20MHZ:
686 /* In case of no channel bonding, use dot11_mode
687 * to set phy mode
688 */
689 switch (dot11_mode) {
690 case WNI_CFG_DOT11_MODE_11A:
691 phymode = MODE_11A;
692 break;
693 case WNI_CFG_DOT11_MODE_11B:
694 phymode = MODE_11B;
695 break;
696 case WNI_CFG_DOT11_MODE_11G:
697 phymode = MODE_11G;
698 break;
699 case WNI_CFG_DOT11_MODE_11G_ONLY:
700 phymode = MODE_11GONLY;
701 break;
702 default:
703 /* Configure MODE_11NG_HT20 for
704 * self vdev(for vht too)
705 */
706 phymode = MODE_11NG_HT20;
707 break;
708 }
709 break;
710 case CH_WIDTH_40MHZ:
711 phymode = vht_capable ? MODE_11AC_VHT40 :
712 MODE_11NG_HT40;
713 break;
714 default:
715 break;
716 }
717 }
718
719 /* 5 GHz band */
720 if ((chan >= WMA_11A_CHANNEL_BEGIN) && (chan <= WMA_11A_CHANNEL_END)) {
721 switch (chan_width) {
722 case CH_WIDTH_20MHZ:
723 phymode = vht_capable ? MODE_11AC_VHT20 :
724 MODE_11NA_HT20;
725 break;
726 case CH_WIDTH_40MHZ:
727 phymode = vht_capable ? MODE_11AC_VHT40 :
728 MODE_11NA_HT40;
729 break;
730 case CH_WIDTH_80MHZ:
731 phymode = MODE_11AC_VHT80;
732 break;
733#if CONFIG_160MHZ_SUPPORT != 0
734 case CH_WIDTH_160MHZ:
735 phymode = MODE_11AC_VHT160;
736 break;
737 case CH_WIDTH_80P80MHZ:
738 phymode = MODE_11AC_VHT80_80;
739 break;
740#endif
741
742 default:
743 break;
744 }
745 }
746
747 /* 5.9 GHz Band */
748 if ((chan >= WMA_11P_CHANNEL_BEGIN) && (chan <= WMA_11P_CHANNEL_END))
749 /* Only Legacy Modulation Schemes are supported */
750 phymode = MODE_11A;
751
752 WMA_LOGD("%s: phymode %d channel %d ch_width %d vht_capable %d "
753 "dot11_mode %d", __func__, phymode, chan,
754 chan_width, vht_capable, dot11_mode);
755
756 return phymode;
757}
758
759/**
760 * wma_get_link_speed() -send command to get linkspeed
761 * @handle: wma handle
762 * @pLinkSpeed: link speed info
763 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530764 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800765 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530766QDF_STATUS wma_get_link_speed(WMA_HANDLE handle, tSirLinkSpeedInfo *pLinkSpeed)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800767{
768 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhaa64c242016-03-08 11:31:49 +0530769 wmi_mac_addr peer_macaddr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800770
771 if (!wma_handle || !wma_handle->wmi_handle) {
772 WMA_LOGE("%s: WMA is closed, can not issue get link speed cmd",
773 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530774 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800775 }
776 if (!WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap,
777 WMI_SERVICE_ESTIMATE_LINKSPEED)) {
778 WMA_LOGE("%s: Linkspeed feature bit not enabled"
779 " Sending value 0 as link speed.", __func__);
780 wma_send_link_speed(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530781 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800782 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800783
784 /* Copy the peer macaddress to the wma buffer */
Srinivas Girigowdadccab9a2015-11-19 14:31:14 -0800785 WMI_CHAR_ARRAY_TO_MAC_ADDR(pLinkSpeed->peer_macaddr.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +0530786 &peer_macaddr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800787
788 WMA_LOGD("%s: pLinkSpeed->peerMacAddr: %pM, "
789 "peer_macaddr.mac_addr31to0: 0x%x, peer_macaddr.mac_addr47to32: 0x%x",
Srinivas Girigowdadccab9a2015-11-19 14:31:14 -0800790 __func__, pLinkSpeed->peer_macaddr.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +0530791 peer_macaddr.mac_addr31to0,
792 peer_macaddr.mac_addr47to32);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800793
Govind Singhaa64c242016-03-08 11:31:49 +0530794 if (wmi_unified_get_link_speed_cmd(wma_handle->wmi_handle,
795 peer_macaddr)) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530796 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800797 }
Govind Singhaa64c242016-03-08 11:31:49 +0530798
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530799 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800800}
801
802#ifdef FEATURE_GREEN_AP
803
804/**
Ryan Hsu3c8f79f2015-12-02 16:45:09 -0800805 * wma_egap_info_status_event() - egap info status event
806 * @handle: pointer to wma handler
807 * @event: pointer to event
808 * @len: len of the event
809 *
810 * Return: 0 for success, otherwise appropriate error code
811 */
812static int wma_egap_info_status_event(void *handle, u_int8_t *event,
813 uint32_t len)
814{
815 WMI_TX_PAUSE_EVENTID_param_tlvs *param_buf;
816 wmi_ap_ps_egap_info_event_fixed_param *egap_info_event;
817 wmi_ap_ps_egap_info_chainmask_list *chainmask_event;
818 u_int8_t *buf_ptr;
819
820 param_buf = (WMI_TX_PAUSE_EVENTID_param_tlvs *)event;
821 if (!param_buf) {
822 WMA_LOGE("Invalid EGAP Info status event buffer");
823 return -EINVAL;
824 }
825
826 egap_info_event = (wmi_ap_ps_egap_info_event_fixed_param *)
827 param_buf->fixed_param;
828 buf_ptr = (uint8_t *)egap_info_event;
829 buf_ptr += sizeof(wmi_ap_ps_egap_info_event_fixed_param);
830 chainmask_event = (wmi_ap_ps_egap_info_chainmask_list *)buf_ptr;
831
832 WMA_LOGI("mac_id: %d, status: %d, tx_mask: %x, rx_mask: %d",
833 chainmask_event->mac_id,
834 egap_info_event->status,
835 chainmask_event->tx_chainmask,
836 chainmask_event->rx_chainmask);
837 return 0;
838}
839
840/**
841 * wma_send_egap_conf_params() - send wmi cmd of egap configuration params
842 * @wma_handle: wma handler
843 * @egap_params: pointer to egap_params
844 *
845 * Return: 0 for success, otherwise appropriate error code
846 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530847QDF_STATUS wma_send_egap_conf_params(WMA_HANDLE handle,
Ryan Hsu3c8f79f2015-12-02 16:45:09 -0800848 struct egap_conf_params *egap_params)
849{
850 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhaa64c242016-03-08 11:31:49 +0530851 wmi_ap_ps_egap_param_cmd_fixed_param cmd = {0};
Ryan Hsu3c8f79f2015-12-02 16:45:09 -0800852 int32_t err;
853
Govind Singhaa64c242016-03-08 11:31:49 +0530854 cmd.enable = egap_params->enable;
855 cmd.inactivity_time = egap_params->inactivity_time;
856 cmd.wait_time = egap_params->wait_time;
857 cmd.flags = egap_params->flags;
858 err = wmi_unified_egap_conf_params_cmd(wma_handle->wmi_handle, &cmd);
Ryan Hsu3c8f79f2015-12-02 16:45:09 -0800859 if (err) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530860 return QDF_STATUS_E_FAILURE;
Ryan Hsu3c8f79f2015-12-02 16:45:09 -0800861 }
Govind Singhaa64c242016-03-08 11:31:49 +0530862
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530863 return QDF_STATUS_SUCCESS;
Ryan Hsu3c8f79f2015-12-02 16:45:09 -0800864}
865
866/**
867 * wma_setup_egap_support() - setup the EGAP support flag
868 * @tgt_cfg: pointer to hdd target configuration
869 * @egap_support: EGAP support flag
870 *
871 * Return: None
872 */
873void wma_setup_egap_support(struct wma_tgt_cfg *tgt_cfg, WMA_HANDLE handle)
874{
875 tp_wma_handle wma_handle = (tp_wma_handle) handle;
876
877 if (tgt_cfg && wma_handle)
878 tgt_cfg->egap_support = wma_handle->egap_support;
879}
880
881/**
882 * wma_register_egap_event_handle() - register the EGAP event handle
883 * @wma_handle: wma handler
884 *
885 * Return: None
886 */
887void wma_register_egap_event_handle(WMA_HANDLE handle)
888{
889 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhd76a5b02016-03-08 15:12:14 +0530890 QDF_STATUS status;
Ryan Hsu3c8f79f2015-12-02 16:45:09 -0800891
892 if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap,
893 WMI_SERVICE_EGAP)) {
894 status = wmi_unified_register_event_handler(
895 wma_handle->wmi_handle,
896 WMI_AP_PS_EGAP_INFO_EVENTID,
Govind Singhd76a5b02016-03-08 15:12:14 +0530897 wma_egap_info_status_event,
898 WMA_RX_SERIALIZER_CTX);
899 if (QDF_IS_STATUS_ERROR(status)) {
Ryan Hsu3c8f79f2015-12-02 16:45:09 -0800900 WMA_LOGE("Failed to register Enhance Green AP event");
901 wma_handle->egap_support = false;
902 } else {
903 WMA_LOGI("Set the Enhance Green AP event handler");
904 wma_handle->egap_support = true;
905 }
906 } else
907 wma_handle->egap_support = false;
908}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800909#endif /* FEATURE_GREEN_AP */
910
Govind Singha471e5e2015-10-12 17:11:14 +0530911/**
Govind Singhaa64c242016-03-08 11:31:49 +0530912 * wma_unified_fw_profiling_cmd() - send FW profiling cmd to WLAN FW
Govind Singha471e5e2015-10-12 17:11:14 +0530913 * @wma: wma handle
914 * @cmd: Profiling command index
915 * @value1: parameter1 value
916 * @value2: parameter2 value
917 *
918 * Return: 0 for success else error code
919 */
Govind Singhaa64c242016-03-08 11:31:49 +0530920QDF_STATUS wma_unified_fw_profiling_cmd(wmi_unified_t wmi_handle,
Govind Singha471e5e2015-10-12 17:11:14 +0530921 uint32_t cmd, uint32_t value1, uint32_t value2)
922{
Govind Singha471e5e2015-10-12 17:11:14 +0530923 int ret;
Govind Singha471e5e2015-10-12 17:11:14 +0530924
Govind Singhaa64c242016-03-08 11:31:49 +0530925 ret = wmi_unified_fw_profiling_data_cmd(wmi_handle, cmd,
926 value1, value2);
927 if (ret) {
928 WMA_LOGE("enable cmd Failed for id %d value %d",
929 value1, value2);
930 return ret;
Govind Singha471e5e2015-10-12 17:11:14 +0530931 }
932
Govind Singhaa64c242016-03-08 11:31:49 +0530933 return QDF_STATUS_SUCCESS;
Govind Singha471e5e2015-10-12 17:11:14 +0530934}
935
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800936#ifdef FEATURE_WLAN_LPHB
937/**
938 * wma_lphb_handler() - send LPHB indication to SME
939 * @wma: wma handle
940 * @event: event handler
941 *
942 * Return: 0 for success or error code
943 */
944static int wma_lphb_handler(tp_wma_handle wma, uint8_t *event)
945{
946 wmi_hb_ind_event_fixed_param *hb_fp;
947 tSirLPHBInd *slphb_indication;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530948 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800949 cds_msg_t sme_msg = { 0 };
950
951 hb_fp = (wmi_hb_ind_event_fixed_param *) event;
952 if (!hb_fp) {
953 WMA_LOGE("Invalid wmi_hb_ind_event_fixed_param buffer");
954 return -EINVAL;
955 }
956
957 WMA_LOGD("lphb indication received with vdev_id=%d, session=%d, reason=%d",
958 hb_fp->vdev_id, hb_fp->session, hb_fp->reason);
959
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530960 slphb_indication = (tSirLPHBInd *) qdf_mem_malloc(sizeof(tSirLPHBInd));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800961
962 if (!slphb_indication) {
963 WMA_LOGE("Invalid LPHB indication buffer");
964 return -ENOMEM;
965 }
966
967 slphb_indication->sessionIdx = hb_fp->session;
968 slphb_indication->protocolType = hb_fp->reason;
969 slphb_indication->eventReason = hb_fp->reason;
970
971 sme_msg.type = eWNI_SME_LPHB_IND;
972 sme_msg.bodyptr = slphb_indication;
973 sme_msg.bodyval = 0;
974
Anurag Chouhan6d760662016-02-20 16:05:43 +0530975 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530976 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800977 WMA_LOGE("Fail to post eWNI_SME_LPHB_IND msg to SME");
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530978 qdf_mem_free(slphb_indication);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800979 return -EINVAL;
980 }
981
982 return 0;
983}
984#endif /* FEATURE_WLAN_LPHB */
985
986#ifdef FEATURE_WLAN_RA_FILTERING
987/**
988 * wma_wow_sta_ra_filter() - set RA filter pattern in fw
989 * @wma: wma handle
990 * @vdev_id: vdev id
991 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530992 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800993 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530994static QDF_STATUS wma_wow_sta_ra_filter(tp_wma_handle wma, uint8_t vdev_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800995{
996
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800997 struct wma_txrx_node *iface;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800998 int ret;
Govind Singhaa64c242016-03-08 11:31:49 +0530999 uint8_t default_pattern;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001000
1001 iface = &wma->interfaces[vdev_id];
1002
Govind Singhaa64c242016-03-08 11:31:49 +05301003 default_pattern = iface->num_wow_default_patterns++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001004
1005 WMA_LOGD("%s: send RA rate limit [%d] to fw vdev = %d", __func__,
1006 wma->RArateLimitInterval, vdev_id);
1007
Govind Singhaa64c242016-03-08 11:31:49 +05301008 ret = wmi_unified_wow_sta_ra_filter_cmd(wma->wmi_handle, vdev_id,
1009 default_pattern, wma->RArateLimitInterval);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001010 if (ret) {
1011 WMA_LOGE("%s: Failed to send RA rate limit to fw", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001012 iface->num_wow_default_patterns--;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301013 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001014 }
1015
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301016 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001017
1018}
1019#endif /* FEATURE_WLAN_RA_FILTERING */
1020
1021/**
1022 * wmi_unified_nat_keepalive_enable() - enable NAT keepalive filter
1023 * @wma: wma handle
1024 * @vdev_id: vdev id
1025 *
1026 * Return: 0 for success or error code
1027 */
1028int wmi_unified_nat_keepalive_enable(tp_wma_handle wma, uint8_t vdev_id)
1029{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001030
Govind Singhaa64c242016-03-08 11:31:49 +05301031 if (wmi_unified_nat_keepalive_en_cmd(wma->wmi_handle, vdev_id))
1032 return QDF_STATUS_E_FAILURE;
1033
1034 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001035}
1036
1037/**
Govind Singhd76a5b02016-03-08 15:12:14 +05301038 * wma_unified_csa_offload_enable() - sen CSA offload enable command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001039 * @wma: wma handle
1040 * @vdev_id: vdev id
1041 *
1042 * Return: 0 for success or error code
1043 */
Govind Singhd76a5b02016-03-08 15:12:14 +05301044int wma_unified_csa_offload_enable(tp_wma_handle wma, uint8_t vdev_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001045{
Govind Singhaa64c242016-03-08 11:31:49 +05301046 if (wmi_unified_csa_offload_enable(wma->wmi_handle,
1047 vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001048 WMA_LOGP("%s: Failed to send CSA offload enable command",
1049 __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001050 return -EIO;
1051 }
Govind Singhaa64c242016-03-08 11:31:49 +05301052
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001053 return 0;
1054}
1055
1056#ifdef WLAN_FEATURE_NAN
1057/**
1058 * wma_nan_rsp_event_handler() - Function is used to handle nan response
1059 * @handle: wma handle
1060 * @event_buf: event buffer
1061 * @len: length of buffer
1062 *
1063 * Return: 0 for success or error code
1064 */
1065int wma_nan_rsp_event_handler(void *handle, uint8_t *event_buf,
1066 uint32_t len)
1067{
1068 WMI_NAN_EVENTID_param_tlvs *param_buf;
1069 tSirNanEvent *nan_rsp_event;
1070 wmi_nan_event_hdr *nan_rsp_event_hdr;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301071 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001072 cds_msg_t cds_msg;
1073 uint8_t *buf_ptr;
1074 uint32_t alloc_len;
1075
1076 /*
1077 * This is how received event_buf looks like
1078 *
1079 * <-------------------- event_buf ----------------------------------->
1080 *
1081 * <--wmi_nan_event_hdr--><---WMI_TLV_HDR_SIZE---><----- data -------->
1082 *
1083 * +-----------+---------+-----------------------+--------------------+
1084 * | tlv_header| data_len| WMITLV_TAG_ARRAY_BYTE | nan_rsp_event_data |
1085 * +-----------+---------+-----------------------+--------------------+
1086 */
1087
1088 WMA_LOGD("%s: Posting NaN response event to SME", __func__);
1089 param_buf = (WMI_NAN_EVENTID_param_tlvs *) event_buf;
1090 if (!param_buf) {
1091 WMA_LOGE("%s: Invalid nan response event buf", __func__);
1092 return -EINVAL;
1093 }
1094 nan_rsp_event_hdr = param_buf->fixed_param;
1095 buf_ptr = (uint8_t *) nan_rsp_event_hdr;
1096 alloc_len = sizeof(tSirNanEvent);
1097 alloc_len += nan_rsp_event_hdr->data_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301098 nan_rsp_event = (tSirNanEvent *) qdf_mem_malloc(alloc_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001099 if (NULL == nan_rsp_event) {
1100 WMA_LOGE("%s: Memory allocation failure", __func__);
1101 return -ENOMEM;
1102 }
1103
1104 nan_rsp_event->event_data_len = nan_rsp_event_hdr->data_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301105 qdf_mem_copy(nan_rsp_event->event_data, buf_ptr +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001106 sizeof(wmi_nan_event_hdr) + WMI_TLV_HDR_SIZE,
1107 nan_rsp_event->event_data_len);
1108 cds_msg.type = eWNI_SME_NAN_EVENT;
1109 cds_msg.bodyptr = (void *)nan_rsp_event;
1110 cds_msg.bodyval = 0;
1111
1112 status = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301113 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001114 WMA_LOGE("%s: Failed to post NaN response event to SME",
1115 __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301116 qdf_mem_free(nan_rsp_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001117 return -EFAULT;
1118 }
1119 WMA_LOGD("%s: NaN response event Posted to SME", __func__);
1120 return 0;
1121}
1122#endif /* WLAN_FEATURE_NAN */
1123
1124/**
1125 * wma_csa_offload_handler() - CSA event handler
1126 * @handle: wma handle
1127 * @event: event buffer
1128 * @len: buffer length
1129 *
1130 * This event is sent by firmware when it receives CSA IE.
1131 *
1132 * Return: 0 for success or error code
1133 */
1134int wma_csa_offload_handler(void *handle, uint8_t *event, uint32_t len)
1135{
1136 tp_wma_handle wma = (tp_wma_handle) handle;
1137 WMI_CSA_HANDLING_EVENTID_param_tlvs *param_buf;
1138 wmi_csa_event_fixed_param *csa_event;
1139 uint8_t bssid[IEEE80211_ADDR_LEN];
1140 uint8_t vdev_id = 0;
1141 uint8_t cur_chan = 0;
1142 struct ieee80211_channelswitch_ie *csa_ie;
1143 tpCSAOffloadParams csa_offload_event;
1144 struct ieee80211_extendedchannelswitch_ie *xcsa_ie;
1145 struct ieee80211_ie_wide_bw_switch *wb_ie;
1146 struct wma_txrx_node *intr = wma->interfaces;
1147
1148 param_buf = (WMI_CSA_HANDLING_EVENTID_param_tlvs *) event;
1149
1150 WMA_LOGD("%s: Enter", __func__);
1151 if (!param_buf) {
1152 WMA_LOGE("Invalid csa event buffer");
1153 return -EINVAL;
1154 }
1155 csa_event = param_buf->fixed_param;
1156 WMI_MAC_ADDR_TO_CHAR_ARRAY(&csa_event->i_addr2, &bssid[0]);
1157
1158 if (wma_find_vdev_by_bssid(wma, bssid, &vdev_id) == NULL) {
1159 WMA_LOGE("Invalid bssid received %s:%d", __func__, __LINE__);
1160 return -EINVAL;
1161 }
1162
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301163 csa_offload_event = qdf_mem_malloc(sizeof(*csa_offload_event));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001164 if (!csa_offload_event) {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05301165 WMA_LOGE("QDF MEM Alloc Failed for csa_offload_event");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001166 return -EINVAL;
1167 }
1168
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301169 qdf_mem_zero(csa_offload_event, sizeof(*csa_offload_event));
1170 qdf_mem_copy(csa_offload_event->bssId, &bssid, IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001171
1172 if (csa_event->ies_present_flag & WMI_CSA_IE_PRESENT) {
1173 csa_ie = (struct ieee80211_channelswitch_ie *)
1174 (&csa_event->csa_ie[0]);
1175 csa_offload_event->channel = csa_ie->newchannel;
1176 csa_offload_event->switchmode = csa_ie->switchmode;
1177 } else if (csa_event->ies_present_flag & WMI_XCSA_IE_PRESENT) {
1178 xcsa_ie = (struct ieee80211_extendedchannelswitch_ie *)
1179 (&csa_event->xcsa_ie[0]);
1180 csa_offload_event->channel = xcsa_ie->newchannel;
1181 csa_offload_event->switchmode = xcsa_ie->switchmode;
Gupta, Kapil121bf212015-11-25 19:21:29 +05301182 csa_offload_event->new_op_class = xcsa_ie->newClass;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001183 } else {
1184 WMA_LOGE("CSA Event error: No CSA IE present");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301185 qdf_mem_free(csa_offload_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001186 return -EINVAL;
1187 }
1188
1189 if (csa_event->ies_present_flag & WMI_WBW_IE_PRESENT) {
1190 wb_ie = (struct ieee80211_ie_wide_bw_switch *)
1191 (&csa_event->wb_ie[0]);
1192 csa_offload_event->new_ch_width = wb_ie->new_ch_width;
1193 csa_offload_event->new_ch_freq_seg1 = wb_ie->new_ch_freq_seg1;
1194 csa_offload_event->new_ch_freq_seg2 = wb_ie->new_ch_freq_seg2;
1195 }
1196
1197 csa_offload_event->ies_present_flag = csa_event->ies_present_flag;
1198
1199 WMA_LOGD("CSA: New Channel = %d BSSID:%pM",
1200 csa_offload_event->channel, csa_offload_event->bssId);
1201
1202 cur_chan = cds_freq_to_chan(intr[vdev_id].mhz);
1203 /*
1204 * basic sanity check: requested channel should not be 0
1205 * and equal to home channel
1206 */
1207 if ((0 == csa_offload_event->channel) ||
1208 (cur_chan == csa_offload_event->channel)) {
1209 WMA_LOGE("CSA Event with channel %d. Ignore !!",
1210 csa_offload_event->channel);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301211 qdf_mem_free(csa_offload_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001212 return -EINVAL;
1213 }
1214 wma->interfaces[vdev_id].is_channel_switch = true;
1215 wma_send_msg(wma, WMA_CSA_OFFLOAD_EVENT, (void *)csa_offload_event, 0);
1216 return 0;
1217}
1218
1219#ifdef FEATURE_OEM_DATA_SUPPORT
1220
1221/**
1222 * wma_oem_capability_event_callback() - OEM capability event handler
1223 * @handle: wma handle
1224 * @datap: data ptr
1225 * @len: data length
1226 *
1227 * Return: 0 for success or error code
1228 */
1229int wma_oem_capability_event_callback(void *handle,
1230 uint8_t *datap, uint32_t len)
1231{
1232 tp_wma_handle wma = (tp_wma_handle) handle;
1233 WMI_OEM_CAPABILITY_EVENTID_param_tlvs *param_buf;
1234 uint8_t *data;
1235 uint32_t datalen;
1236 uint32_t *msg_subtype;
1237 tStartOemDataRsp *pStartOemDataRsp;
1238
1239 param_buf = (WMI_OEM_CAPABILITY_EVENTID_param_tlvs *) datap;
1240 if (!param_buf) {
1241 WMA_LOGE("%s: Received NULL buf ptr from FW", __func__);
1242 return -ENOMEM;
1243 }
1244
1245 data = param_buf->data;
1246 datalen = param_buf->num_data;
1247
1248 if (!data) {
1249 WMA_LOGE("%s: Received NULL data from FW", __func__);
1250 return -EINVAL;
1251 }
1252
1253 /* wma puts 4 bytes prefix for msg subtype, so length
1254 * of data received from target should be 4 bytes less
1255 * then max allowed
1256 */
1257 if (datalen > (OEM_DATA_RSP_SIZE - 4)) {
1258 WMA_LOGE("%s: Received data len (%d) exceeds max value (%d)",
1259 __func__, datalen, (OEM_DATA_RSP_SIZE - 4));
1260 return -EINVAL;
1261 }
1262
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301263 pStartOemDataRsp = qdf_mem_malloc(sizeof(*pStartOemDataRsp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001264 if (!pStartOemDataRsp) {
1265 WMA_LOGE("%s: Failed to alloc pStartOemDataRsp", __func__);
1266 return -ENOMEM;
1267 }
1268
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301269 qdf_mem_zero(pStartOemDataRsp, sizeof(tStartOemDataRsp));
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001270 pStartOemDataRsp->target_rsp = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001271 msg_subtype = (uint32_t *) (&pStartOemDataRsp->oemDataRsp[0]);
1272 *msg_subtype = WMI_OEM_CAPABILITY_RSP;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301273 qdf_mem_copy(&pStartOemDataRsp->oemDataRsp[4], data, datalen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001274
1275 WMA_LOGI("%s: Sending WMA_START_OEM_DATA_RSP, data len (%d)",
1276 __func__, datalen);
1277
1278 wma_send_msg(wma, WMA_START_OEM_DATA_RSP, (void *)pStartOemDataRsp, 0);
1279 return 0;
1280}
1281
1282/**
1283 * wma_oem_measurement_report_event_callback() - OEM measurement report handler
1284 * @handle: wma handle
1285 * @datap: data ptr
1286 * @len: data length
1287 *
1288 * Return: 0 for success or error code
1289 */
1290int wma_oem_measurement_report_event_callback(void *handle,
1291 uint8_t *datap,
1292 uint32_t len)
1293{
1294 tp_wma_handle wma = (tp_wma_handle) handle;
1295 WMI_OEM_MEASUREMENT_REPORT_EVENTID_param_tlvs *param_buf;
1296 uint8_t *data;
1297 uint32_t datalen;
1298 uint32_t *msg_subtype;
1299 tStartOemDataRsp *pStartOemDataRsp;
1300
1301 param_buf = (WMI_OEM_MEASUREMENT_REPORT_EVENTID_param_tlvs *) datap;
1302 if (!param_buf) {
1303 WMA_LOGE("%s: Received NULL buf ptr from FW", __func__);
1304 return -ENOMEM;
1305 }
1306
1307 data = param_buf->data;
1308 datalen = param_buf->num_data;
1309
1310 if (!data) {
1311 WMA_LOGE("%s: Received NULL data from FW", __func__);
1312 return -EINVAL;
1313 }
1314
1315 /* wma puts 4 bytes prefix for msg subtype, so length
1316 * of data received from target should be 4 bytes less
1317 * then max allowed
1318 */
1319 if (datalen > (OEM_DATA_RSP_SIZE - 4)) {
1320 WMA_LOGE("%s: Received data len (%d) exceeds max value (%d)",
1321 __func__, datalen, (OEM_DATA_RSP_SIZE - 4));
1322 return -EINVAL;
1323 }
1324
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301325 pStartOemDataRsp = qdf_mem_malloc(sizeof(*pStartOemDataRsp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001326 if (!pStartOemDataRsp) {
1327 WMA_LOGE("%s: Failed to alloc pStartOemDataRsp", __func__);
1328 return -ENOMEM;
1329 }
1330
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301331 qdf_mem_zero(pStartOemDataRsp, sizeof(tStartOemDataRsp));
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001332 pStartOemDataRsp->target_rsp = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001333 msg_subtype = (uint32_t *) (&pStartOemDataRsp->oemDataRsp[0]);
1334 *msg_subtype = WMI_OEM_MEASUREMENT_RSP;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301335 qdf_mem_copy(&pStartOemDataRsp->oemDataRsp[4], data, datalen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001336
1337 WMA_LOGI("%s: Sending WMA_START_OEM_DATA_RSP, data len (%d)",
1338 __func__, datalen);
1339
1340 wma_send_msg(wma, WMA_START_OEM_DATA_RSP, (void *)pStartOemDataRsp, 0);
1341 return 0;
1342}
1343
1344/**
1345 * wma_oem_error_report_event_callback() - OEM error report handler
1346 * @handle: wma handle
1347 * @datap: data ptr
1348 * @len: data length
1349 *
1350 * Return: 0 for success or error code
1351 */
1352int wma_oem_error_report_event_callback(void *handle,
1353 uint8_t *datap, uint32_t len)
1354{
1355 tp_wma_handle wma = (tp_wma_handle) handle;
1356 WMI_OEM_ERROR_REPORT_EVENTID_param_tlvs *param_buf;
1357 uint8_t *data;
1358 uint32_t datalen;
1359 uint32_t *msg_subtype;
1360 tStartOemDataRsp *pStartOemDataRsp;
1361
1362 param_buf = (WMI_OEM_ERROR_REPORT_EVENTID_param_tlvs *) datap;
1363 if (!param_buf) {
1364 WMA_LOGE("%s: Received NULL buf ptr from FW", __func__);
1365 return -ENOMEM;
1366 }
1367
1368 data = param_buf->data;
1369 datalen = param_buf->num_data;
1370
1371 if (!data) {
1372 WMA_LOGE("%s: Received NULL data from FW", __func__);
1373 return -EINVAL;
1374 }
1375
1376 /* wma puts 4 bytes prefix for msg subtype, so length
1377 * of data received from target should be 4 bytes less
1378 * then max allowed
1379 */
1380 if (datalen > (OEM_DATA_RSP_SIZE - 4)) {
1381 WMA_LOGE("%s: Received data len (%d) exceeds max value (%d)",
1382 __func__, datalen, (OEM_DATA_RSP_SIZE - 4));
1383 return -EINVAL;
1384 }
1385
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301386 pStartOemDataRsp = qdf_mem_malloc(sizeof(*pStartOemDataRsp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001387 if (!pStartOemDataRsp) {
1388 WMA_LOGE("%s: Failed to alloc pStartOemDataRsp", __func__);
1389 return -ENOMEM;
1390 }
1391
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301392 qdf_mem_zero(pStartOemDataRsp, sizeof(tStartOemDataRsp));
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001393 pStartOemDataRsp->target_rsp = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001394 msg_subtype = (uint32_t *) (&pStartOemDataRsp->oemDataRsp[0]);
1395 *msg_subtype = WMI_OEM_ERROR_REPORT_RSP;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301396 qdf_mem_copy(&pStartOemDataRsp->oemDataRsp[4], data, datalen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001397
1398 WMA_LOGI("%s: Sending WMA_START_OEM_DATA_RSP, data len (%d)",
1399 __func__, datalen);
1400
1401 wma_send_msg(wma, WMA_START_OEM_DATA_RSP, (void *)pStartOemDataRsp, 0);
1402 return 0;
1403}
1404
1405/**
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001406 * wma_oem_data_response_handler() - OEM data response event handler
1407 * @handle: wma handle
1408 * @datap: data ptr
1409 * @len: data length
1410 *
1411 * Return: 0 for success or error code
1412 */
1413int wma_oem_data_response_handler(void *handle,
1414 uint8_t *datap, uint32_t len)
1415{
1416 tp_wma_handle wma = (tp_wma_handle) handle;
1417 WMI_OEM_RESPONSE_EVENTID_param_tlvs *param_buf;
1418 uint8_t *data;
1419 uint32_t datalen;
1420 tStartOemDataRsp *oem_data_rsp;
1421
1422 param_buf = (WMI_OEM_RESPONSE_EVENTID_param_tlvs *) datap;
1423 if (!param_buf) {
1424 WMA_LOGE(FL("Received NULL buf ptr from FW"));
1425 return -ENOMEM;
1426 }
1427
1428 data = param_buf->data;
1429 datalen = param_buf->num_data;
1430
1431 if (!data) {
1432 WMA_LOGE(FL("Received NULL data from FW"));
1433 return -EINVAL;
1434 }
1435
1436 if (datalen > OEM_DATA_RSP_SIZE) {
1437 WMA_LOGE(FL("Received data len %d exceeds max value %d"),
1438 datalen, OEM_DATA_RSP_SIZE);
1439 return -EINVAL;
1440 }
1441
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301442 oem_data_rsp = qdf_mem_malloc(sizeof(*oem_data_rsp));
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001443 if (!oem_data_rsp) {
1444 WMA_LOGE(FL("Failed to alloc oem_data_rsp"));
1445 return -ENOMEM;
1446 }
1447
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301448 qdf_mem_zero(oem_data_rsp, sizeof(tStartOemDataRsp));
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001449 oem_data_rsp->target_rsp = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301450 qdf_mem_copy(&oem_data_rsp->oemDataRsp[0], data, datalen);
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001451
1452 WMA_LOGI(FL("Sending WMA_START_OEM_DATA_RSP, data len %d"), datalen);
1453
1454 wma_send_msg(wma, WMA_START_OEM_DATA_RSP, (void *)oem_data_rsp, 0);
1455 return 0;
1456}
1457
1458/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001459 * wma_start_oem_data_req() - start OEM data request to target
1460 * @wma_handle: wma handle
1461 * @startOemDataReq: start request params
1462 *
1463 * Return: none
1464 */
1465void wma_start_oem_data_req(tp_wma_handle wma_handle,
1466 tStartOemDataReq *startOemDataReq)
1467{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001468 int ret = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001469 tStartOemDataRsp *pStartOemDataRsp;
1470
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001471 WMA_LOGD(FL("Send OEM Data Request to target"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001472
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001473 if (!startOemDataReq && !startOemDataReq->data) {
1474 WMA_LOGE(FL("startOemDataReq is null"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001475 goto out;
1476 }
1477
1478 if (!wma_handle || !wma_handle->wmi_handle) {
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001479 WMA_LOGE(FL("WMA - closed, can not send Oem data request cmd"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001480 return;
1481 }
1482
Govind Singhaa64c242016-03-08 11:31:49 +05301483 ret = wmi_unified_start_oem_data_cmd(wma_handle->wmi_handle,
1484 startOemDataReq->data_len,
1485 startOemDataReq->data);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001486
1487 if (ret != EOK) {
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001488 WMA_LOGE(FL(":wmi cmd send failed"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001489 }
1490
1491out:
1492 /* free oem data req buffer received from UMAC */
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001493 if (startOemDataReq) {
1494 if (startOemDataReq->data)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301495 qdf_mem_free(startOemDataReq->data);
1496 qdf_mem_free(startOemDataReq);
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001497 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001498
1499 /* Now send data resp back to PE/SME with message sub-type of
1500 * WMI_OEM_INTERNAL_RSP. This is required so that PE/SME clears
1501 * up pending active command. Later when desired oem response(s)
1502 * comes as wmi event from target then those shall be passed
1503 * to oem application
1504 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301505 pStartOemDataRsp = qdf_mem_malloc(sizeof(*pStartOemDataRsp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001506 if (!pStartOemDataRsp) {
1507 WMA_LOGE("%s:failed to allocate memory for OEM Data Resp to PE",
1508 __func__);
1509 return;
1510 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301511 qdf_mem_zero(pStartOemDataRsp, sizeof(tStartOemDataRsp));
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001512 pStartOemDataRsp->target_rsp = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001513
1514 WMA_LOGI("%s: Sending WMA_START_OEM_DATA_RSP to clear up PE/SME pending cmd",
1515 __func__);
1516
1517 wma_send_msg(wma_handle, WMA_START_OEM_DATA_RSP,
1518 (void *)pStartOemDataRsp, 0);
1519
1520 return;
1521}
1522#endif /* FEATURE_OEM_DATA_SUPPORT */
1523
1524
1525/**
1526 * wma_unified_dfs_radar_rx_event_handler() - dfs radar rx event handler
1527 * @handle: wma handle
1528 * @data: data buffer
1529 * @datalen: data length
1530 *
1531 * WMI handler for WMI_DFS_RADAR_EVENTID
1532 * This handler is registered for handling
1533 * filtered DFS Phyerror. This handler is
1534 * will be invoked only when DFS Phyerr
1535 * filtering offload is enabled.
1536 *
1537 * Return: 1 for Success and 0 for error
1538 */
1539static int wma_unified_dfs_radar_rx_event_handler(void *handle,
1540 uint8_t *data,
1541 uint32_t datalen)
1542{
1543 tp_wma_handle wma = (tp_wma_handle) handle;
1544 struct ieee80211com *ic;
1545 struct ath_dfs *dfs;
1546 struct dfs_event *event;
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05301547 struct dfs_ieee80211_channel *chan;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001548 int empty;
1549 int do_check_chirp = 0;
1550 int is_hw_chirp = 0;
1551 int is_sw_chirp = 0;
1552 int is_pri = 0;
1553
1554 WMI_DFS_RADAR_EVENTID_param_tlvs *param_tlvs;
1555 wmi_dfs_radar_event_fixed_param *radar_event;
1556
1557 ic = wma->dfs_ic;
1558 if (NULL == ic) {
1559 WMA_LOGE("%s: dfs_ic is NULL ", __func__);
1560 return 0;
1561 }
1562
1563 dfs = (struct ath_dfs *)ic->ic_dfs;
1564 param_tlvs = (WMI_DFS_RADAR_EVENTID_param_tlvs *) data;
1565
1566 if (NULL == dfs) {
1567 WMA_LOGE("%s: dfs is NULL ", __func__);
1568 return 0;
1569 }
1570 /*
1571 * This parameter holds the number
1572 * of phyerror interrupts to the host
1573 * after the phyerrors have passed through
1574 * false detect filters in the firmware.
1575 */
1576 dfs->dfs_phyerr_count++;
1577
1578 if (!param_tlvs) {
1579 WMA_LOGE("%s: Received NULL data from FW", __func__);
1580 return 0;
1581 }
1582
1583 radar_event = param_tlvs->fixed_param;
1584
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301585 qdf_spin_lock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001586 chan = ic->ic_curchan;
Edhar, Mahesh Kumar35d9b2e2015-10-26 17:06:23 +05301587 if (ic->disable_phy_err_processing) {
1588 WMA_LOGD("%s: radar indication done,drop phyerror event",
1589 __func__);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301590 qdf_spin_unlock_bh(&ic->chan_lock);
Edhar, Mahesh Kumar35d9b2e2015-10-26 17:06:23 +05301591 return 0;
1592 }
1593
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001594 if (CHANNEL_STATE_DFS != cds_get_channel_state(chan->ic_ieee)) {
1595 WMA_LOGE
1596 ("%s: Invalid DFS Phyerror event. Channel=%d is Non-DFS",
1597 __func__, chan->ic_ieee);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301598 qdf_spin_unlock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001599 return 0;
1600 }
1601
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301602 qdf_spin_unlock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001603 dfs->ath_dfs_stats.total_phy_errors++;
1604
1605 if (dfs->dfs_caps.ath_chip_is_bb_tlv) {
1606 do_check_chirp = 1;
1607 is_pri = 1;
1608 is_hw_chirp = radar_event->pulse_is_chirp;
1609
1610 if ((uint32_t) dfs->dfs_phyerr_freq_min >
1611 radar_event->pulse_center_freq) {
1612 dfs->dfs_phyerr_freq_min =
1613 (int)radar_event->pulse_center_freq;
1614 }
1615
1616 if (dfs->dfs_phyerr_freq_max <
1617 (int)radar_event->pulse_center_freq) {
1618 dfs->dfs_phyerr_freq_max =
1619 (int)radar_event->pulse_center_freq;
1620 }
1621 }
1622
1623 /*
1624 * Now, add the parsed, checked and filtered
1625 * radar phyerror event radar pulse event list.
1626 * This event will then be processed by
1627 * dfs_radar_processevent() to see if the pattern
1628 * of pulses in radar pulse list match any radar
1629 * singnature in the current regulatory domain.
1630 */
1631
1632 ATH_DFSEVENTQ_LOCK(dfs);
1633 empty = STAILQ_EMPTY(&(dfs->dfs_eventq));
1634 ATH_DFSEVENTQ_UNLOCK(dfs);
1635 if (empty) {
1636 return 0;
1637 }
1638 /*
1639 * Add the event to the list, if there's space.
1640 */
1641 ATH_DFSEVENTQ_LOCK(dfs);
1642 event = STAILQ_FIRST(&(dfs->dfs_eventq));
1643 if (event == NULL) {
1644 ATH_DFSEVENTQ_UNLOCK(dfs);
1645 WMA_LOGE("%s: No more space left for queuing DFS Phyerror events",
1646 __func__);
1647 return 0;
1648 }
1649 STAILQ_REMOVE_HEAD(&(dfs->dfs_eventq), re_list);
1650 ATH_DFSEVENTQ_UNLOCK(dfs);
1651 dfs->dfs_phyerr_queued_count++;
1652 dfs->dfs_phyerr_w53_counter++;
1653 event->re_dur = (uint8_t) radar_event->pulse_duration;
1654 event->re_rssi = radar_event->rssi;
1655 event->re_ts = radar_event->pulse_detect_ts & DFS_TSMASK;
1656 event->re_full_ts = (((uint64_t) radar_event->upload_fullts_high) << 32)
1657 | radar_event->upload_fullts_low;
1658
1659 /*
1660 * Index of peak magnitude
1661 */
1662 event->sidx = radar_event->peak_sidx;
1663
1664 /*
1665 * Handle chirp flags.
1666 */
1667 if (do_check_chirp) {
1668 event->re_flags |= DFS_EVENT_CHECKCHIRP;
1669 if (is_hw_chirp) {
1670 event->re_flags |= DFS_EVENT_HW_CHIRP;
1671 }
1672 if (is_sw_chirp) {
1673 event->re_flags |= DFS_EVENT_SW_CHIRP;
1674 }
1675 }
1676 /*
1677 * Correctly set which channel is being reported on
1678 */
1679 if (is_pri) {
1680 event->re_chanindex = (uint8_t) dfs->dfs_curchan_radindex;
1681 } else {
1682 if (dfs->dfs_extchan_radindex == -1) {
1683 WMA_LOGI("%s phyerr on ext channel", __func__);
1684 }
1685 event->re_chanindex = (uint8_t) dfs->dfs_extchan_radindex;
1686 WMA_LOGI("%s:New extension channel event is added to queue",
1687 __func__);
1688 }
1689
1690 ATH_DFSQ_LOCK(dfs);
1691
1692 STAILQ_INSERT_TAIL(&(dfs->dfs_radarq), event, re_list);
1693
1694 empty = STAILQ_EMPTY(&dfs->dfs_radarq);
1695
1696 ATH_DFSQ_UNLOCK(dfs);
1697
1698 if (!empty && !dfs->ath_radar_tasksched) {
1699 dfs->ath_radar_tasksched = 1;
1700 OS_SET_TIMER(&dfs->ath_dfs_task_timer, 0);
1701 }
1702
1703 return 1;
1704
1705}
1706
1707/**
1708 * wma_unified_phyerr_rx_event_handler() - phyerr event handler
1709 * @handle: wma handle
1710 * @data: data buffer
1711 * @datalen: buffer length
1712 *
1713 * WMI Handler for WMI_PHYERR_EVENTID event from firmware.
1714 * This handler is currently handling only DFS phy errors.
1715 * This handler will be invoked only when the DFS phyerror
1716 * filtering offload is disabled.
1717 *
1718 * Return: 1:Success, 0:Failure
1719 */
1720static int wma_unified_phyerr_rx_event_handler(void *handle,
1721 uint8_t *data, uint32_t datalen)
1722{
1723 tp_wma_handle wma = (tp_wma_handle) handle;
1724 WMI_PHYERR_EVENTID_param_tlvs *param_tlvs;
1725 wmi_comb_phyerr_rx_hdr *pe_hdr;
1726 uint8_t *bufp;
1727 wmi_single_phyerr_rx_event *ev;
1728 struct ieee80211com *ic = wma->dfs_ic;
Anurag Chouhan6d760662016-02-20 16:05:43 +05301729 qdf_size_t n;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001730 A_UINT64 tsf64 = 0;
1731 int phy_err_code = 0;
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08001732 A_UINT32 phy_err_mask = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001733 int error = 0;
1734 tpAniSirGlobal mac_ctx =
Anurag Chouhan6d760662016-02-20 16:05:43 +05301735 (tpAniSirGlobal)cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001736 bool enable_log = false;
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08001737 int max_dfs_buf_length = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001738
1739 if (NULL == mac_ctx) {
1740 WMA_LOGE("%s: mac_ctx is NULL", __func__);
1741 return 0;
1742 }
1743 enable_log = mac_ctx->sap.enable_dfs_phy_error_logs;
1744
1745 param_tlvs = (WMI_PHYERR_EVENTID_param_tlvs *) data;
1746
1747 if (!param_tlvs) {
1748 WMA_LOGE("%s: Received NULL data from FW", __func__);
1749 return 0;
1750 }
1751
1752 pe_hdr = param_tlvs->hdr;
1753 if (pe_hdr == NULL) {
1754 WMA_LOGE("%s: Received Data PE Header is NULL", __func__);
1755 return 0;
1756 }
1757
1758 /* Ensure it's at least the size of the header */
1759 if (datalen < sizeof(*pe_hdr)) {
1760 WMA_LOGE("%s: Expected minimum size %zu, received %d",
1761 __func__, sizeof(*pe_hdr), datalen);
1762 return 0;
1763 }
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08001764 /*
1765 * The max buffer lenght is larger for DFS-3 than DFS-2.
1766 * So, accordingly use the correct max buffer size.
1767 */
1768 if (wma->hw_bd_id != WMI_HWBD_QCA6174)
1769 max_dfs_buf_length = DFS3_MAX_BUF_LENGTH;
1770 else
1771 max_dfs_buf_length = DFS_MAX_BUF_LENGTH;
1772
1773 if (pe_hdr->buf_len > max_dfs_buf_length) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001774 WMA_LOGE("%s: Received Invalid Phyerror event buffer length = %d"
1775 "Maximum allowed buf length = %d", __func__,
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08001776 pe_hdr->buf_len, max_dfs_buf_length);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001777
1778 return 0;
1779 }
1780
1781 /*
1782 * Reconstruct the 64 bit event TSF. This isn't from the MAC, it's
1783 * at the time the event was sent to us, the TSF value will be
1784 * in the future.
1785 */
1786 tsf64 = pe_hdr->tsf_l32;
1787 tsf64 |= (((uint64_t) pe_hdr->tsf_u32) << 32);
1788
1789 /*
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08001790 * Check the HW board ID to figure out
1791 * if DFS-3 is supported. In DFS-3
1792 * phyerror mask indicates the type of
1793 * phyerror, whereas in DFS-2 phyerrorcode
1794 * indicates the type of phyerror. If the
1795 * board is NOT WMI_HWBD_QCA6174, for now
1796 * assume that it supports DFS-3.
1797 */
1798 if (wma->hw_bd_id != WMI_HWBD_QCA6174) {
1799 phy_err_mask = pe_hdr->rsPhyErrMask0;
1800 WMA_LOGD("%s: DFS-3 phyerror mask = 0x%x",
1801 __func__, phy_err_mask);
1802 }
1803
1804 /*
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001805 * Loop over the bufp, extracting out phyerrors
1806 * wmi_unified_comb_phyerr_rx_event.bufp is a char pointer,
1807 * which isn't correct here - what we have received here
1808 * is an array of TLV-style PHY errors.
1809 */
1810 n = 0; /* Start just after the header */
1811 bufp = param_tlvs->bufp;
1812 while (n < pe_hdr->buf_len) {
1813 /* ensure there's at least space for the header */
1814 if ((pe_hdr->buf_len - n) < sizeof(ev->hdr)) {
1815 WMA_LOGE("%s: Not enough space.(datalen=%d, n=%zu, hdr=%zu bytes",
1816 __func__, pe_hdr->buf_len, n, sizeof(ev->hdr));
1817 error = 1;
1818 break;
1819 }
1820 /*
1821 * Obtain a pointer to the beginning of the current event.
1822 * data[0] is the beginning of the WMI payload.
1823 */
1824 ev = (wmi_single_phyerr_rx_event *) &bufp[n];
1825
1826 /*
1827 * Sanity check the buffer length of the event against
1828 * what we currently have.
1829 * Since buf_len is 32 bits, we check if it overflows
1830 * a large 32 bit value. It's not 0x7fffffff because
1831 * we increase n by (buf_len + sizeof(hdr)), which would
1832 * in itself cause n to overflow.
1833 * If "int" is 64 bits then this becomes a moot point.
1834 */
1835 if (ev->hdr.buf_len > 0x7f000000) {
1836 WMA_LOGE("%s:buf_len is garbage (0x%x)", __func__,
1837 ev->hdr.buf_len);
1838 error = 1;
1839 break;
1840 }
1841 if (n + ev->hdr.buf_len > pe_hdr->buf_len) {
1842 WMA_LOGE("%s: buf_len exceeds available space n=%zu,"
1843 "buf_len=%d, datalen=%d",
1844 __func__, n, ev->hdr.buf_len, pe_hdr->buf_len);
1845 error = 1;
1846 break;
1847 }
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08001848 /*
1849 * If the board id is WMI_HWBD_QCA6174
1850 * then it supports only DFS-2. So, fetch
1851 * phyerror code in order to know the type
1852 * of phyerror.
1853 */
1854 if (wma->hw_bd_id == WMI_HWBD_QCA6174) {
1855 phy_err_code = WMI_UNIFIED_PHYERRCODE_GET(&ev->hdr);
1856 WMA_LOGD("%s: DFS-2 phyerror code = 0x%x",
1857 __func__, phy_err_code);
1858 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001859
1860 /*
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08001861 * phy_err_code is set for DFS-2 and phy_err_mask
1862 * is set for DFS-3. Checking both to support
1863 * compatability for older platforms.
1864 * If the phyerror or phyerrmask category matches,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001865 * pass radar events to the dfs pattern matching code.
1866 * Don't pass radar events with no buffer payload.
1867 */
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08001868 if (((phy_err_mask & WMI_PHY_ERROR_MASK0_RADAR) ||
1869 (phy_err_mask & WMI_PHY_ERROR_MASK0_FALSE_RADAR_EXT)) ||
1870 (phy_err_code == WMA_DFS2_PHYERROR_CODE ||
1871 phy_err_code == WMA_DFS2_FALSE_RADAR_EXT)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001872 if (ev->hdr.buf_len > 0) {
1873 /* Calling in to the DFS module to process the phyerr */
1874 dfs_process_phyerr(ic, &ev->bufp[0],
1875 ev->hdr.buf_len,
1876 WMI_UNIFIED_RSSI_COMB_GET
1877 (&ev->hdr) & 0xff,
1878 /* Extension RSSI */
1879 WMI_UNIFIED_RSSI_COMB_GET
1880 (&ev->hdr) & 0xff,
1881 ev->hdr.tsf_timestamp,
1882 tsf64, enable_log);
1883 }
1884 }
1885
1886 /*
1887 * Advance the buffer pointer to the next PHY error.
1888 * buflen is the length of this payload, so we need to
1889 * advance past the current header _AND_ the payload.
1890 */
1891 n += sizeof(*ev) + ev->hdr.buf_len;
1892
1893 } /*end while() */
1894 if (error)
1895 return 0;
1896 else
1897 return 1;
1898}
1899
1900/**
1901 * wma_register_dfs_event_handler() - register dfs event handler
1902 * @wma_handle: wma handle
1903 *
1904 * Register appropriate dfs phyerror event handler
1905 * based on phyerror filtering offload is enabled
1906 * or disabled.
1907 *
1908 * Return: none
1909 */
1910void wma_register_dfs_event_handler(tp_wma_handle wma_handle)
1911{
1912 if (NULL == wma_handle) {
1913 WMA_LOGE("%s:wma_handle is NULL", __func__);
1914 return;
1915 }
1916
1917 if (false == wma_handle->dfs_phyerr_filter_offload) {
1918 /*
1919 * Register the wma_unified_phyerr_rx_event_handler
1920 * for filtering offload disabled case to handle
1921 * the DFS phyerrors.
1922 */
1923 WMA_LOGD("%s:Phyerror Filtering offload is Disabled in ini",
1924 __func__);
1925 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Govind Singhd76a5b02016-03-08 15:12:14 +05301926 WMI_PHYERR_EVENTID,
1927 wma_unified_phyerr_rx_event_handler,
1928 WMA_RX_WORK_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001929 WMA_LOGD("%s: WMI_PHYERR_EVENTID event handler registered",
1930 __func__);
1931 } else {
1932 WMA_LOGD("%s:Phyerror Filtering offload is Enabled in ini",
1933 __func__);
1934 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Govind Singhd76a5b02016-03-08 15:12:14 +05301935 WMI_DFS_RADAR_EVENTID,
1936 wma_unified_dfs_radar_rx_event_handler,
1937 WMA_RX_WORK_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001938 WMA_LOGD("%s:WMI_DFS_RADAR_EVENTID event handler registered",
1939 __func__);
1940 }
1941
1942 return;
1943}
1944
1945
1946/**
1947 * wma_unified_dfs_phyerr_filter_offload_enable() - enable dfs phyerr filter
1948 * @wma_handle: wma handle
1949 *
1950 * Send WMI_DFS_PHYERR_FILTER_ENA_CMDID or
1951 * WMI_DFS_PHYERR_FILTER_DIS_CMDID command
1952 * to firmware based on phyerr filtering
1953 * offload status.
1954 *
1955 * Return: 1 success, 0 failure
1956 */
1957int
1958wma_unified_dfs_phyerr_filter_offload_enable(tp_wma_handle wma_handle)
1959{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001960 int ret;
1961
1962 if (NULL == wma_handle) {
1963 WMA_LOGE("%s:wma_handle is NULL", __func__);
1964 return 0;
1965 }
1966
Govind Singhaa64c242016-03-08 11:31:49 +05301967 ret = wmi_unified_dfs_phyerr_filter_offload_en_cmd(wma_handle->wmi_handle,
1968 wma_handle->dfs_phyerr_filter_offload);
1969 if (ret)
1970 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001971
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001972
Govind Singhaa64c242016-03-08 11:31:49 +05301973 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001974}
1975
1976#if !defined(REMOVE_PKT_LOG)
1977/**
1978 * wma_pktlog_wmi_send_cmd() - send pktlog enable/disable command to target
1979 * @handle: wma handle
1980 * @params: pktlog params
1981 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05301982 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001983 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301984QDF_STATUS wma_pktlog_wmi_send_cmd(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001985 struct ath_pktlog_wmi_params *params)
1986{
1987 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhaa64c242016-03-08 11:31:49 +05301988 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001989
1990 /*Check if packet log is enabled in cfg.ini */
1991 if (!cds_is_packet_log_enabled()) {
1992 WMA_LOGE("%s:pkt log is not enabled in cfg.ini", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301993 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001994 }
1995
Govind Singhaa64c242016-03-08 11:31:49 +05301996 ret = wmi_unified_pktlog_wmi_send_cmd(wma_handle->wmi_handle,
1997 params->pktlog_event,
1998 params->cmd_id);
1999 if (ret)
2000 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002001
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002002
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302003 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002004}
2005#endif /* REMOVE_PKT_LOG */
2006
2007static void wma_send_status_to_suspend_ind(tp_wma_handle wma, bool suspended)
2008{
2009 tSirReadyToSuspendInd *ready_to_suspend;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302010 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002011 cds_msg_t cds_msg;
2012 uint8_t len;
2013
2014 WMA_LOGD("Posting ready to suspend indication to umac");
2015
2016 len = sizeof(tSirReadyToSuspendInd);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302017 ready_to_suspend = (tSirReadyToSuspendInd *) qdf_mem_malloc(len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002018
2019 if (NULL == ready_to_suspend) {
2020 WMA_LOGE("%s: Memory allocation failure", __func__);
2021 return;
2022 }
2023
2024 ready_to_suspend->mesgType = eWNI_SME_READY_TO_SUSPEND_IND;
2025 ready_to_suspend->mesgLen = len;
2026 ready_to_suspend->suspended = suspended;
2027
2028 cds_msg.type = eWNI_SME_READY_TO_SUSPEND_IND;
2029 cds_msg.bodyptr = (void *)ready_to_suspend;
2030 cds_msg.bodyval = 0;
2031
2032 status = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302033 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002034 WMA_LOGE("Failed to post ready to suspend");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302035 qdf_mem_free(ready_to_suspend);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002036 }
2037}
2038
2039/**
2040 * wma_wow_wake_reason_str() - Converts wow wakeup reason code to text format
2041 * @wake_reason - WOW wake reason
2042 *
2043 * Return: reason code in string format
2044 */
2045static const u8 *wma_wow_wake_reason_str(A_INT32 wake_reason)
2046{
2047 switch (wake_reason) {
2048 case WOW_REASON_UNSPECIFIED:
2049 return "UNSPECIFIED";
2050 case WOW_REASON_NLOD:
2051 return "NLOD";
2052 case WOW_REASON_AP_ASSOC_LOST:
2053 return "AP_ASSOC_LOST";
2054 case WOW_REASON_LOW_RSSI:
2055 return "LOW_RSSI";
2056 case WOW_REASON_DEAUTH_RECVD:
2057 return "DEAUTH_RECVD";
2058 case WOW_REASON_DISASSOC_RECVD:
2059 return "DISASSOC_RECVD";
2060 case WOW_REASON_GTK_HS_ERR:
2061 return "GTK_HS_ERR";
2062 case WOW_REASON_EAP_REQ:
2063 return "EAP_REQ";
2064 case WOW_REASON_FOURWAY_HS_RECV:
2065 return "FOURWAY_HS_RECV";
2066 case WOW_REASON_TIMER_INTR_RECV:
2067 return "TIMER_INTR_RECV";
2068 case WOW_REASON_PATTERN_MATCH_FOUND:
2069 return "PATTERN_MATCH_FOUND";
2070 case WOW_REASON_RECV_MAGIC_PATTERN:
2071 return "RECV_MAGIC_PATTERN";
2072 case WOW_REASON_P2P_DISC:
2073 return "P2P_DISC";
2074#ifdef FEATURE_WLAN_LPHB
2075 case WOW_REASON_WLAN_HB:
2076 return "WLAN_HB";
2077#endif /* FEATURE_WLAN_LPHB */
2078
2079 case WOW_REASON_CSA_EVENT:
2080 return "CSA_EVENT";
2081 case WOW_REASON_PROBE_REQ_WPS_IE_RECV:
2082 return "PROBE_REQ_RECV";
2083 case WOW_REASON_AUTH_REQ_RECV:
2084 return "AUTH_REQ_RECV";
2085 case WOW_REASON_ASSOC_REQ_RECV:
2086 return "ASSOC_REQ_RECV";
2087 case WOW_REASON_HTT_EVENT:
2088 return "WOW_REASON_HTT_EVENT";
2089#ifdef FEATURE_WLAN_RA_FILTERING
2090 case WOW_REASON_RA_MATCH:
2091 return "WOW_REASON_RA_MATCH";
2092#endif /* FEATURE_WLAN_RA_FILTERING */
2093 case WOW_REASON_BEACON_RECV:
2094 return "WOW_REASON_IBSS_BEACON_RECV";
2095#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
2096 case WOW_REASON_HOST_AUTO_SHUTDOWN:
2097 return "WOW_REASON_HOST_AUTO_SHUTDOWN";
2098#endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
2099#ifdef WLAN_FEATURE_ROAM_OFFLOAD
2100 case WOW_REASON_ROAM_HO:
2101 return "WOW_REASON_ROAM_HO";
2102#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
2103#ifdef FEATURE_WLAN_EXTSCAN
2104 case WOW_REASON_EXTSCAN:
2105 return "WOW_REASON_EXTSCAN";
2106#endif
2107 case WOW_REASON_RSSI_BREACH_EVENT:
2108 return "WOW_REASON_RSSI_BREACH_EVENT";
Srinivas Girigowdae80cea92015-11-23 11:33:57 -08002109 case WOW_REASON_NLO_SCAN_COMPLETE:
2110 return "WOW_REASON_NLO_SCAN_COMPLETE";
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002111 }
2112 return "unknown";
2113}
2114
2115/**
2116 * wma_wow_wake_up_stats_display() - display wow wake up stats
2117 * @wma: Pointer to wma handle
2118 *
2119 * Return: none
2120 */
2121static void wma_wow_wake_up_stats_display(tp_wma_handle wma)
2122{
2123 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",
2124 wma->wow_ucast_wake_up_count,
2125 wma->wow_bcast_wake_up_count,
2126 wma->wow_ipv4_mcast_wake_up_count,
2127 wma->wow_ipv6_mcast_wake_up_count,
2128 wma->wow_ipv6_mcast_ra_stats,
2129 wma->wow_ipv6_mcast_ns_stats,
2130 wma->wow_ipv6_mcast_na_stats,
2131 wma->wow_pno_match_wake_up_count,
2132 wma->wow_pno_complete_wake_up_count,
2133 wma->wow_gscan_wake_up_count,
2134 wma->wow_low_rssi_wake_up_count,
2135 wma->wow_rssi_breach_wake_up_count);
2136
2137 return;
2138}
2139
2140/**
2141 * wma_wow_ipv6_mcast_stats() - ipv6 mcast wake up stats
2142 * @wma: Pointer to wma handle
2143 * @data: Pointer to pattern match data
2144 *
2145 * Return: none
2146 */
2147static void wma_wow_ipv6_mcast_stats(tp_wma_handle wma, uint8_t *data)
2148{
2149 static const uint8_t ipv6_mcast[] = {0x86, 0xDD};
2150
2151 if (!memcmp(ipv6_mcast, (data + WMA_ETHER_TYPE_OFFSET),
2152 sizeof(ipv6_mcast))) {
2153 if (WMA_ICMP_V6_HEADER_TYPE ==
2154 *(data + WMA_ICMP_V6_HEADER_OFFSET)) {
2155 if (WMA_ICMP_V6_RA_TYPE ==
2156 *(data + WMA_ICMP_V6_TYPE_OFFSET))
2157 wma->wow_ipv6_mcast_ra_stats++;
2158 else if (WMA_ICMP_V6_NS_TYPE ==
2159 *(data + WMA_ICMP_V6_TYPE_OFFSET))
2160 wma->wow_ipv6_mcast_ns_stats++;
2161 else if (WMA_ICMP_V6_NA_TYPE ==
2162 *(data + WMA_ICMP_V6_TYPE_OFFSET))
2163 wma->wow_ipv6_mcast_na_stats++;
2164 else
2165 WMA_LOGA("ICMP V6 type : 0x%x",
2166 *(data + WMA_ICMP_V6_TYPE_OFFSET));
2167 } else {
2168 WMA_LOGA("ICMP_V6 header 0x%x",
2169 *(data + WMA_ICMP_V6_HEADER_OFFSET));
2170 }
2171 } else {
2172 WMA_LOGA("Ethertype x%x:0x%x",
2173 *(data + WMA_ETHER_TYPE_OFFSET),
2174 *(data + WMA_ETHER_TYPE_OFFSET + 1));
2175 }
2176
2177 return;
2178}
2179
2180/**
2181 * wma_wow_wake_up_stats() - maintain wow pattern match wake up stats
2182 * @wma: Pointer to wma handle
2183 * @data: Pointer to pattern match data
2184 * @len: Pattern match data length
2185 * @event: Wake up event
2186 *
2187 * Return: none
2188 */
2189static void wma_wow_wake_up_stats(tp_wma_handle wma, uint8_t *data,
2190 int32_t len, WOW_WAKE_REASON_TYPE event)
2191{
2192 switch (event) {
2193
2194 case WOW_REASON_PATTERN_MATCH_FOUND:
2195 if (WMA_BCAST_MAC_ADDR == *data) {
2196 wma->wow_bcast_wake_up_count++;
2197 } else if (WMA_MCAST_IPV4_MAC_ADDR == *data) {
2198 wma->wow_ipv4_mcast_wake_up_count++;
2199 } else if (WMA_MCAST_IPV6_MAC_ADDR == *data) {
2200 wma->wow_ipv6_mcast_wake_up_count++;
2201 if (len > WMA_ICMP_V6_TYPE_OFFSET)
2202 wma_wow_ipv6_mcast_stats(wma, data);
2203 else
2204 WMA_LOGA("ICMP_V6 data len %d", len);
2205 } else {
2206 wma->wow_ucast_wake_up_count++;
2207 }
2208 break;
2209
2210 case WOW_REASON_RA_MATCH:
2211 wma->wow_ipv6_mcast_ra_stats++;
2212 break;
2213
2214 case WOW_REASON_NLOD:
2215 wma->wow_pno_match_wake_up_count++;
2216 break;
2217
2218 case WOW_REASON_NLO_SCAN_COMPLETE:
2219 wma->wow_pno_complete_wake_up_count++;
2220 break;
2221
2222 case WOW_REASON_LOW_RSSI:
2223 wma->wow_low_rssi_wake_up_count++;
2224 break;
2225
2226 case WOW_REASON_EXTSCAN:
2227 wma->wow_gscan_wake_up_count++;
2228 break;
2229
2230 case WOW_REASON_RSSI_BREACH_EVENT:
2231 wma->wow_rssi_breach_wake_up_count++;
2232 break;
2233
2234 default:
2235 WMA_LOGE("Unknown wake up reason");
2236 break;
2237 }
2238
2239 wma_wow_wake_up_stats_display(wma);
2240 return;
2241}
2242
2243/**
2244 * wma_wow_wakeup_host_event() - wakeup host event handler
2245 * @handle: wma handle
2246 * @event: event data
2247 * @len: buffer length
2248 *
2249 * Handler to catch wow wakeup host event. This event will have
2250 * reason why the firmware has woken the host.
2251 *
2252 * Return: 0 for success or error
2253 */
2254int wma_wow_wakeup_host_event(void *handle, uint8_t *event,
2255 uint32_t len)
2256{
2257 tp_wma_handle wma = (tp_wma_handle) handle;
2258 WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *param_buf;
2259 WOW_EVENT_INFO_fixed_param *wake_info;
2260#ifdef FEATURE_WLAN_SCAN_PNO
2261 struct wma_txrx_node *node;
2262#endif /* FEATURE_WLAN_SCAN_PNO */
2263 uint32_t wake_lock_duration = 0;
2264 uint32_t wow_buf_pkt_len = 0;
2265
2266 param_buf = (WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *) event;
2267 if (!param_buf) {
2268 WMA_LOGE("Invalid wow wakeup host event buf");
2269 return -EINVAL;
2270 }
2271
2272 wake_info = param_buf->fixed_param;
2273
2274 WMA_LOGA("WOW wakeup host event received (reason: %s(%d)) for vdev %d",
2275 wma_wow_wake_reason_str(wake_info->wake_reason),
2276 wake_info->wake_reason, wake_info->vdev_id);
2277
Anurag Chouhance0dc992016-02-16 18:18:03 +05302278 qdf_event_set(&wma->wma_resume_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002279
2280 switch (wake_info->wake_reason) {
2281 case WOW_REASON_AUTH_REQ_RECV:
2282 wake_lock_duration = WMA_AUTH_REQ_RECV_WAKE_LOCK_TIMEOUT;
2283 break;
2284
2285 case WOW_REASON_ASSOC_REQ_RECV:
2286 wake_lock_duration = WMA_ASSOC_REQ_RECV_WAKE_LOCK_DURATION;
2287 break;
2288
2289 case WOW_REASON_DEAUTH_RECVD:
2290 wake_lock_duration = WMA_DEAUTH_RECV_WAKE_LOCK_DURATION;
2291 break;
2292
2293 case WOW_REASON_DISASSOC_RECVD:
2294 wake_lock_duration = WMA_DISASSOC_RECV_WAKE_LOCK_DURATION;
2295 break;
2296
2297 case WOW_REASON_AP_ASSOC_LOST:
2298 wake_lock_duration = WMA_BMISS_EVENT_WAKE_LOCK_DURATION;
2299 WMA_LOGA("Beacon miss indication on vdev %x",
2300 wake_info->vdev_id);
2301 wma_beacon_miss_handler(wma, wake_info->vdev_id);
2302 break;
2303#ifdef FEATURE_WLAN_RA_FILTERING
2304 case WOW_REASON_RA_MATCH:
2305 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_RA_MATCH);
2306 break;
2307#endif /* FEATURE_WLAN_RA_FILTERING */
2308#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
2309 case WOW_REASON_HOST_AUTO_SHUTDOWN:
2310 wake_lock_duration = WMA_AUTO_SHUTDOWN_WAKE_LOCK_DURATION;
2311 WMA_LOGA("Received WOW Auto Shutdown trigger in suspend");
2312 if (wma_post_auto_shutdown_msg())
2313 return -EINVAL;
2314 break;
2315#endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
2316#ifdef FEATURE_WLAN_SCAN_PNO
2317 case WOW_REASON_NLOD:
2318 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_NLOD);
2319 node = &wma->interfaces[wake_info->vdev_id];
2320 if (node) {
2321 WMA_LOGD("NLO match happened");
2322 node->nlo_match_evt_received = true;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302323 qdf_wake_lock_timeout_acquire(&wma->pno_wake_lock,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002324 WMA_PNO_MATCH_WAKE_LOCK_TIMEOUT,
2325 WIFI_POWER_EVENT_WAKELOCK_PNO);
Srinivas Girigowdae80cea92015-11-23 11:33:57 -08002326 }
2327 break;
2328
2329 case WOW_REASON_NLO_SCAN_COMPLETE:
2330 {
2331 WMI_NLO_SCAN_COMPLETE_EVENTID_param_tlvs param;
2332
2333 WMA_LOGD("Host woken up due to pno scan complete reason");
2334
2335 /* First 4-bytes of wow_packet_buffer is the length */
2336 if (param_buf->wow_packet_buffer) {
2337 param.fixed_param = (wmi_nlo_event *)
2338 (param_buf->wow_packet_buffer + 4);
2339 wma_nlo_scan_cmp_evt_handler(handle,
2340 (u_int8_t *)&param, sizeof(param));
2341 } else
2342 WMA_LOGD("No wow_packet_buffer present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002343 }
2344 break;
2345#endif /* FEATURE_WLAN_SCAN_PNO */
2346
2347 case WOW_REASON_CSA_EVENT:
2348 {
2349 WMI_CSA_HANDLING_EVENTID_param_tlvs param;
2350 WMA_LOGD("Host woken up because of CSA IE");
2351 param.fixed_param = (wmi_csa_event_fixed_param *)
2352 (((uint8_t *) wake_info)
2353 + sizeof(WOW_EVENT_INFO_fixed_param)
2354 + WOW_CSA_EVENT_OFFSET);
2355 wma_csa_offload_handler(handle, (uint8_t *) &param,
2356 sizeof(param));
2357 }
2358 break;
2359
2360#ifdef FEATURE_WLAN_LPHB
2361 case WOW_REASON_WLAN_HB:
2362 wma_lphb_handler(wma, (uint8_t *) param_buf->hb_indevt);
2363 break;
2364#endif /* FEATURE_WLAN_LPHB */
2365
2366 case WOW_REASON_HTT_EVENT:
2367 break;
2368 case WOW_REASON_PATTERN_MATCH_FOUND:
2369 wma_wow_wake_up_stats_display(wma);
2370 WMA_LOGD("Wake up for Rx packet, dump starting from ethernet hdr");
2371 if (param_buf->wow_packet_buffer) {
2372 /* First 4-bytes of wow_packet_buffer is the length */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302373 qdf_mem_copy((uint8_t *) &wow_buf_pkt_len,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002374 param_buf->wow_packet_buffer, 4);
2375 wma_wow_wake_up_stats(wma,
2376 param_buf->wow_packet_buffer + 4,
2377 wow_buf_pkt_len,
2378 WOW_REASON_PATTERN_MATCH_FOUND);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302379 qdf_trace_hex_dump(QDF_MODULE_ID_WMA,
2380 QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002381 param_buf->wow_packet_buffer + 4,
2382 wow_buf_pkt_len);
2383 } else {
2384 WMA_LOGE("No wow packet buffer present");
2385 }
2386 break;
2387
2388 case WOW_REASON_LOW_RSSI:
2389 {
2390 /* WOW_REASON_LOW_RSSI is used for all roaming events.
2391 * WMI_ROAM_REASON_BETTER_AP, WMI_ROAM_REASON_BMISS,
2392 * WMI_ROAM_REASON_SUITABLE_AP will be handled by
2393 * wma_roam_event_callback().
2394 */
2395 WMI_ROAM_EVENTID_param_tlvs param;
2396 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_LOW_RSSI);
2397 if (param_buf->wow_packet_buffer) {
2398 /* Roam event is embedded in wow_packet_buffer */
2399 WMA_LOGD("Host woken up because of roam event");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302400 qdf_mem_copy((uint8_t *) &wow_buf_pkt_len,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002401 param_buf->wow_packet_buffer, 4);
2402 WMA_LOGD("wow_packet_buffer dump");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302403 qdf_trace_hex_dump(QDF_MODULE_ID_WMA,
2404 QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002405 param_buf->wow_packet_buffer,
2406 wow_buf_pkt_len);
2407 if (wow_buf_pkt_len >= sizeof(param)) {
2408 param.fixed_param =
2409 (wmi_roam_event_fixed_param *)
2410 (param_buf->wow_packet_buffer + 4);
2411 wma_roam_event_callback(handle,
2412 (uint8_t *) &
2413 param,
2414 sizeof(param));
2415 } else {
2416 WMA_LOGE("Wrong length for roam event = %d bytes",
2417 wow_buf_pkt_len);
2418 }
2419 } else {
2420 /* No wow_packet_buffer means a better AP beacon
2421 * will follow in a later event.
2422 */
2423 WMA_LOGD("Host woken up because of better AP beacon");
2424 }
2425 break;
2426 }
2427 case WOW_REASON_CLIENT_KICKOUT_EVENT:
2428 {
2429 WMI_PEER_STA_KICKOUT_EVENTID_param_tlvs param;
2430 if (param_buf->wow_packet_buffer) {
2431 /* station kickout event embedded in wow_packet_buffer */
2432 WMA_LOGD("Host woken up because of sta_kickout event");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302433 qdf_mem_copy((u_int8_t *) &wow_buf_pkt_len,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002434 param_buf->wow_packet_buffer, 4);
2435 WMA_LOGD("wow_packet_buffer dump");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302436 qdf_trace_hex_dump(QDF_MODULE_ID_WMA,
2437 QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002438 param_buf->wow_packet_buffer, wow_buf_pkt_len);
2439 if (wow_buf_pkt_len >= sizeof(param)) {
2440 param.fixed_param = (wmi_peer_sta_kickout_event_fixed_param *)
2441 (param_buf->wow_packet_buffer + 4);
2442 wma_peer_sta_kickout_event_handler(handle,
2443 (u_int8_t *)&param, sizeof(param));
2444 } else {
2445 WMA_LOGE("Wrong length for sta_kickout event = %d bytes",
2446 wow_buf_pkt_len);
2447 }
2448 } else {
2449 WMA_LOGD("No wow_packet_buffer present");
2450 }
2451 break;
2452 }
2453#ifdef FEATURE_WLAN_EXTSCAN
2454 case WOW_REASON_EXTSCAN:
2455 WMA_LOGD("Host woken up because of extscan reason");
2456 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_EXTSCAN);
2457 if (param_buf->wow_packet_buffer) {
2458 wow_buf_pkt_len =
2459 *(uint32_t *)param_buf->wow_packet_buffer;
2460 wma_extscan_wow_event_callback(handle,
2461 (u_int8_t *)(param_buf->wow_packet_buffer + 4),
2462 wow_buf_pkt_len);
2463 } else
2464 WMA_LOGE("wow_packet_buffer is empty");
2465 break;
2466#endif
2467 case WOW_REASON_RSSI_BREACH_EVENT:
2468 {
2469 WMI_RSSI_BREACH_EVENTID_param_tlvs param;
2470
2471 wma_wow_wake_up_stats(wma, NULL, 0,
2472 WOW_REASON_RSSI_BREACH_EVENT);
2473 WMA_LOGD("Host woken up because of rssi breach reason");
2474 /* rssi breach event is embedded in wow_packet_buffer */
2475 if (param_buf->wow_packet_buffer) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302476 qdf_mem_copy((u_int8_t *) &wow_buf_pkt_len,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002477 param_buf->wow_packet_buffer, 4);
2478 if (wow_buf_pkt_len >= sizeof(param)) {
2479 param.fixed_param =
2480 (wmi_rssi_breach_event_fixed_param *)
2481 (param_buf->wow_packet_buffer + 4);
2482 wma_rssi_breached_event_handler(handle,
2483 (u_int8_t *)&param,
2484 sizeof(param));
2485 } else {
2486 WMA_LOGE("%s: Wrong length: %d bytes",
2487 __func__, wow_buf_pkt_len);
2488 }
2489 } else
2490 WMA_LOGD("No wow_packet_buffer present");
2491 }
2492 break;
2493 default:
2494 break;
2495 }
2496
2497 if (wake_lock_duration) {
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302498 qdf_wake_lock_timeout_acquire(&wma->wow_wake_lock,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002499 wake_lock_duration,
2500 WIFI_POWER_EVENT_WAKELOCK_WOW);
2501 WMA_LOGA("Holding %d msec wake_lock", wake_lock_duration);
2502 }
2503
2504 return 0;
2505}
2506
2507/**
2508 * wma_pdev_resume_event_handler() - PDEV resume event handler
2509 * @handle: wma handle
2510 * @event: event data
2511 * @len: buffer length
2512 *
2513 * Return: 0 for success or error
2514 */
2515int wma_pdev_resume_event_handler(void *handle, uint8_t *event, uint32_t len)
2516{
2517 tp_wma_handle wma = (tp_wma_handle) handle;
2518
2519 WMA_LOGA("Received PDEV resume event");
2520
Anurag Chouhance0dc992016-02-16 18:18:03 +05302521 qdf_event_set(&wma->wma_resume_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002522
2523 return 0;
2524}
2525/**
2526 * wma_set_wow_bus_suspend() - set suspend flag
2527 * @wma: wma handle
2528 * @val: value
2529 *
2530 * Return: none
2531 */
2532static inline void wma_set_wow_bus_suspend(tp_wma_handle wma, int val)
2533{
2534
Anurag Chouhan8e0ccd32016-02-19 15:30:20 +05302535 qdf_atomic_set(&wma->is_wow_bus_suspended, val);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002536}
2537
2538
2539
2540/**
2541 * wma_add_wow_wakeup_event() - Configures wow wakeup events.
2542 * @wma: wma handle
2543 * @vdev_id: vdev id
2544 * @bitmap: Event bitmap
2545 * @enable: enable/disable
2546 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302547 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002548 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302549static QDF_STATUS wma_add_wow_wakeup_event(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002550 uint32_t vdev_id,
2551 uint32_t bitmap,
2552 bool enable)
2553{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002554 int ret;
2555
Govind Singhaa64c242016-03-08 11:31:49 +05302556 ret = wmi_unified_add_wow_wakeup_event_cmd(wma->wmi_handle, vdev_id,
2557 enable, bitmap);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002558 if (ret) {
2559 WMA_LOGE("Failed to config wow wakeup event");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302560 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002561 }
2562
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302563 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002564}
2565
2566/**
2567 * wma_send_wow_patterns_to_fw() - Sends WOW patterns to FW.
2568 * @wma: wma handle
2569 * @vdev_id: vdev id
2570 * @ptrn_id: pattern id
2571 * @ptrn: pattern
2572 * @ptrn_len: pattern length
2573 * @ptrn_offset: pattern offset
2574 * @mask: mask
2575 * @mask_len: mask length
2576 * @user: true for user configured pattern and false for default pattern
2577 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302578 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002579 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302580static QDF_STATUS wma_send_wow_patterns_to_fw(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002581 uint8_t vdev_id, uint8_t ptrn_id,
2582 const uint8_t *ptrn, uint8_t ptrn_len,
2583 uint8_t ptrn_offset, const uint8_t *mask,
2584 uint8_t mask_len, bool user)
2585{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002586 struct wma_txrx_node *iface;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002587 int ret;
Govind Singhaa64c242016-03-08 11:31:49 +05302588 uint8_t default_patterns;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002589
2590 iface = &wma->interfaces[vdev_id];
Govind Singhaa64c242016-03-08 11:31:49 +05302591 default_patterns = iface->num_wow_default_patterns++;
2592 ret = wmi_unified_wow_patterns_to_fw_cmd(wma->wmi_handle,
2593 vdev_id, ptrn_id, ptrn,
2594 ptrn_len, ptrn_offset, mask,
2595 mask_len, user, default_patterns);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002596 if (ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002597 if (!user)
2598 iface->num_wow_default_patterns--;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302599 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002600 }
2601
2602 if (user)
2603 iface->num_wow_user_patterns++;
2604
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302605 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002606}
2607
2608/**
2609 * wma_wow_ap() - set WOW patterns in ap mode
2610 * @wma: wma handle
2611 * @vdev_id: vdev id
2612 *
2613 * Configures default WOW pattern for the given vdev_id which is in AP mode.
2614 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302615 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002616 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302617static QDF_STATUS wma_wow_ap(tp_wma_handle wma, uint8_t vdev_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002618{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302619 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002620 uint8_t arp_offset = 20;
2621 uint8_t mac_mask[IEEE80211_ADDR_LEN];
2622
2623 /* Setup unicast pkt pattern */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302624 qdf_mem_set(&mac_mask, IEEE80211_ADDR_LEN, 0xFF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002625 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
2626 wma->interfaces[vdev_id].addr,
2627 IEEE80211_ADDR_LEN, 0, mac_mask,
2628 IEEE80211_ADDR_LEN, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302629 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002630 WMA_LOGE("Failed to add WOW unicast pattern ret %d", ret);
2631 return ret;
2632 }
2633
2634 /*
2635 * Setup all ARP pkt pattern. This is dummy pattern hence the length
2636 * is zero
2637 */
2638 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
2639 arp_ptrn, 0, arp_offset, arp_mask, 0, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302640 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002641 WMA_LOGE("Failed to add WOW ARP pattern ret %d", ret);
2642 return ret;
2643 }
2644
2645 return ret;
2646}
2647
2648/**
2649 * wma_wow_sta() - set WOW patterns in sta mode
2650 * @wma: wma handle
2651 * @vdev_id: vdev id
2652 *
2653 * Configures default WOW pattern for the given vdev_id which is in sta mode.
2654 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302655 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002656 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302657static QDF_STATUS wma_wow_sta(tp_wma_handle wma, uint8_t vdev_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002658{
2659 uint8_t arp_offset = 12;
2660 uint8_t discvr_offset = 30;
2661 uint8_t mac_mask[IEEE80211_ADDR_LEN];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302662 QDF_STATUS ret = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002663
2664 /* Setup unicast pkt pattern */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302665 qdf_mem_set(&mac_mask, IEEE80211_ADDR_LEN, 0xFF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002666 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
2667 wma->interfaces[vdev_id].addr,
2668 IEEE80211_ADDR_LEN, 0, mac_mask,
2669 IEEE80211_ADDR_LEN, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302670 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002671 WMA_LOGE("Failed to add WOW unicast pattern ret %d", ret);
2672 return ret;
2673 }
2674
2675 /*
2676 * Setup multicast pattern for mDNS 224.0.0.251,
2677 * SSDP 239.255.255.250 and LLMNR 224.0.0.252
2678 */
2679 if (wma->ssdp) {
2680 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
2681 discvr_ptrn, sizeof(discvr_ptrn), discvr_offset,
2682 discvr_mask, sizeof(discvr_ptrn), false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302683 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002684 WMA_LOGE("Failed to add WOW mDNS/SSDP/LLMNR pattern");
2685 return ret;
2686 }
2687 } else
2688 WMA_LOGD("mDNS, SSDP, LLMNR patterns are disabled from ini");
2689
2690 /* when arp offload or ns offloaded is disabled
2691 * from ini file, configure broad cast arp pattern
2692 * to fw, so that host can wake up
2693 */
2694 if (!(wma->ol_ini_info & 0x1)) {
2695 /* Setup all ARP pkt pattern */
2696 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
2697 arp_ptrn, sizeof(arp_ptrn), arp_offset,
2698 arp_mask, sizeof(arp_mask), false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302699 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002700 WMA_LOGE("Failed to add WOW ARP pattern");
2701 return ret;
2702 }
2703 }
2704
2705 /* for NS or NDP offload packets */
2706 if (!(wma->ol_ini_info & 0x2)) {
2707 /* Setup all NS pkt pattern */
2708 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
2709 ns_ptrn, sizeof(arp_ptrn), arp_offset,
2710 arp_mask, sizeof(arp_mask), false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302711 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002712 WMA_LOGE("Failed to add WOW NS pattern");
2713 return ret;
2714 }
2715 }
2716
2717 return ret;
2718}
2719
2720/**
2721 * wma_register_wow_default_patterns() - register default wow patterns with fw
2722 * @handle: Pointer to wma handle
2723 * @vdev_id: vdev id
2724 *
2725 * WoW default wake up pattern rule is:
2726 * - For STA & P2P CLI mode register for same STA specific wow patterns
2727 * - For SAP/P2P GO & IBSS mode register for same SAP specific wow patterns
2728 *
2729 * Return: none
2730 */
2731void wma_register_wow_default_patterns(WMA_HANDLE handle, uint8_t vdev_id)
2732{
2733 tp_wma_handle wma = handle;
2734 struct wma_txrx_node *iface;
2735
2736 if (vdev_id > wma->max_bssid) {
2737 WMA_LOGE("Invalid vdev id %d", vdev_id);
2738 return;
2739 }
2740 iface = &wma->interfaces[vdev_id];
2741
2742 if (iface->ptrn_match_enable) {
Houston Hoffman79b4af22015-10-06 12:01:08 -07002743 if (wma_is_vdev_in_beaconning_mode(wma, vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002744 /* Configure SAP/GO/IBSS mode default wow patterns */
2745 WMA_LOGI("Config SAP specific default wow patterns vdev_id %d",
2746 vdev_id);
2747 wma_wow_ap(wma, vdev_id);
2748 } else {
2749 /* Configure STA/P2P CLI mode default wow patterns */
2750 WMA_LOGI("Config STA specific default wow patterns vdev_id %d",
2751 vdev_id);
2752 wma_wow_sta(wma, vdev_id);
2753 if (wma->IsRArateLimitEnabled) {
2754 WMA_LOGI("Config STA RA limit wow patterns vdev_id %d",
2755 vdev_id);
2756 wma_wow_sta_ra_filter(wma, vdev_id);
2757 }
2758 }
2759 }
2760
2761 return;
2762}
2763
2764/**
2765 * wma_register_wow_wakeup_events() - register vdev specific wake events with fw
2766 * @handle: Pointer to wma handle
2767 * @vdev_id: vdev Id
2768 * @vdev_type: vdev type
2769 * @vdev_subtype: vdev sub type
2770 *
2771 * WoW wake up event rule is following:
2772 * 1) STA mode and P2P CLI mode wake up events are same
2773 * 2) SAP mode and P2P GO mode wake up events are same
2774 * 3) IBSS mode wake events are same as STA mode plus WOW_BEACON_EVENT
2775 *
2776 * Return: none
2777 */
2778void wma_register_wow_wakeup_events(WMA_HANDLE handle,
2779 uint8_t vdev_id,
2780 uint8_t vdev_type,
2781 uint8_t vdev_subtype)
2782{
2783 tp_wma_handle wma = handle;
2784 uint32_t event_bitmap;
2785
2786 WMA_LOGI("vdev_type %d vdev_subtype %d vdev_id %d", vdev_type,
2787 vdev_subtype, vdev_id);
2788
2789 if ((WMI_VDEV_TYPE_STA == vdev_type) ||
2790 ((WMI_VDEV_TYPE_AP == vdev_type) &&
2791 (WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE == vdev_subtype))) {
2792 /* Configure STA/P2P CLI mode specific default wake up events */
2793 event_bitmap = WMA_WOW_STA_WAKE_UP_EVENTS;
2794 WMA_LOGI("STA specific default wake up event 0x%x vdev id %d",
2795 event_bitmap, vdev_id);
2796 } else if (WMI_VDEV_TYPE_IBSS == vdev_type) {
2797 /* Configure IBSS mode specific default wake up events */
2798 event_bitmap = (WMA_WOW_STA_WAKE_UP_EVENTS |
2799 (1 << WOW_BEACON_EVENT));
2800 WMA_LOGI("IBSS specific default wake up event 0x%x vdev id %d",
2801 event_bitmap, vdev_id);
2802 } else if (WMI_VDEV_TYPE_AP == vdev_type) {
2803 /* Configure SAP/GO mode specific default wake up events */
2804 event_bitmap = WMA_WOW_SAP_WAKE_UP_EVENTS;
2805 WMA_LOGI("SAP specific default wake up event 0x%x vdev id %d",
2806 event_bitmap, vdev_id);
2807 } else {
2808 WMA_LOGE("unknown type %d subtype %d", vdev_type, vdev_subtype);
2809 return;
2810 }
2811
2812 wma_add_wow_wakeup_event(wma, vdev_id, event_bitmap, true);
2813
2814 return;
2815}
2816
2817/**
2818 * wma_enable_disable_wakeup_event() - Configures wow wakeup events
2819 * @wma: wma handle
2820 * @vdev_id: vdev id
2821 * @bitmap: Event bitmap
2822 * @enable: enable/disable
2823 *
2824 * Return: none
2825 */
2826void wma_enable_disable_wakeup_event(WMA_HANDLE handle,
2827 uint32_t vdev_id,
2828 uint32_t bitmap,
2829 bool enable)
2830{
2831 tp_wma_handle wma = handle;
2832
2833 WMA_LOGI("vdev_id %d wake up event 0x%x enable %d",
2834 vdev_id, bitmap, enable);
2835 wma_add_wow_wakeup_event(wma, vdev_id, bitmap, enable);
2836}
2837
2838/**
2839 * wma_enable_wow_in_fw() - wnable wow in fw
2840 * @wma: wma handle
2841 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302842 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002843 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302844QDF_STATUS wma_enable_wow_in_fw(WMA_HANDLE handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002845{
2846 tp_wma_handle wma = handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002847 int ret;
Komal Seelam3d202862016-02-24 18:43:24 +05302848 struct hif_opaque_softc *scn;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002849 int host_credits;
2850 int wmi_pending_cmds;
Govind Singhd76a5b02016-03-08 15:12:14 +05302851 struct wow_cmd_params param = {0};
2852
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002853#ifdef CONFIG_CNSS
Anurag Chouhan6d760662016-02-20 16:05:43 +05302854 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002855
2856 if (NULL == pMac) {
2857 WMA_LOGE("%s: Unable to get PE context", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302858 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002859 }
2860#endif /* CONFIG_CNSS */
2861
Anurag Chouhance0dc992016-02-16 18:18:03 +05302862 qdf_event_reset(&wma->target_suspend);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002863 wma->wow_nack = 0;
2864
2865 host_credits = wmi_get_host_credits(wma->wmi_handle);
2866 wmi_pending_cmds = wmi_get_pending_cmds(wma->wmi_handle);
2867
2868 WMA_LOGD("Credits:%d; Pending_Cmds: %d",
2869 host_credits, wmi_pending_cmds);
2870
2871 if (host_credits < WMI_WOW_REQUIRED_CREDITS) {
2872 WMA_LOGE("%s: Host Doesn't have enough credits to Post WMI_WOW_ENABLE_CMDID! "
2873 "Credits:%d, pending_cmds:%d\n", __func__, host_credits,
2874 wmi_pending_cmds);
2875#ifndef QCA_WIFI_3_0_EMU
2876 goto error;
2877#endif
2878 }
2879
Govind Singhd76a5b02016-03-08 15:12:14 +05302880 param.enable = true;
2881 param.can_suspend_link = hif_can_suspend_link(wma->htc_handle);
2882 ret = wmi_unified_wow_enable_send(wma->wmi_handle, &param,
2883 WMA_WILDCARD_PDEV_ID);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002884 if (ret) {
2885 WMA_LOGE("Failed to enable wow in fw");
2886 goto error;
2887 }
2888
2889 wmi_set_target_suspend(wma->wmi_handle, true);
2890
Anurag Chouhance0dc992016-02-16 18:18:03 +05302891 if (qdf_wait_single_event(&wma->target_suspend,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002892 WMA_TGT_SUSPEND_COMPLETE_TIMEOUT)
Anurag Chouhance0dc992016-02-16 18:18:03 +05302893 != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002894 WMA_LOGE("Failed to receive WoW Enable Ack from FW");
2895 WMA_LOGE("Credits:%d; Pending_Cmds: %d",
2896 wmi_get_host_credits(wma->wmi_handle),
2897 wmi_get_pending_cmds(wma->wmi_handle));
Prashanth Bhatta9e143052015-12-04 11:56:47 -08002898 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002899#ifdef CONFIG_CNSS
Yue Ma455aff62015-10-20 18:29:16 -07002900 if (pMac->sme.enableSelfRecovery) {
2901 cds_trigger_recovery();
2902 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302903 QDF_BUG(0);
Yue Ma455aff62015-10-20 18:29:16 -07002904 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002905#else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302906 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002907#endif /* CONFIG_CNSS */
Yue Ma455aff62015-10-20 18:29:16 -07002908 } else {
2909 WMA_LOGE("%s: LOGP is in progress, ignore!", __func__);
2910 }
2911
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002912 wmi_set_target_suspend(wma->wmi_handle, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302913 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002914 }
2915
2916 if (wma->wow_nack) {
2917 WMA_LOGE("FW not ready to WOW");
2918 wmi_set_target_suspend(wma->wmi_handle, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302919 return QDF_STATUS_E_AGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002920 }
2921
2922 host_credits = wmi_get_host_credits(wma->wmi_handle);
2923 wmi_pending_cmds = wmi_get_pending_cmds(wma->wmi_handle);
2924
2925 if (host_credits < WMI_WOW_REQUIRED_CREDITS) {
2926 WMA_LOGE("%s: No Credits after HTC ACK:%d, pending_cmds:%d, "
2927 "cannot resume back", __func__, host_credits,
2928 wmi_pending_cmds);
2929 htc_dump_counter_info(wma->htc_handle);
Prashanth Bhatta9e143052015-12-04 11:56:47 -08002930 if (!cds_is_driver_recovering())
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302931 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002932 else
2933 WMA_LOGE("%s: SSR in progress, ignore no credit issue",
2934 __func__);
2935 }
2936
2937 WMA_LOGD("WOW enabled successfully in fw: credits:%d"
2938 "pending_cmds: %d", host_credits, wmi_pending_cmds);
2939
Anurag Chouhan6d760662016-02-20 16:05:43 +05302940 scn = cds_get_context(QDF_MODULE_ID_HIF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002941
2942 if (scn == NULL) {
2943 WMA_LOGE("%s: Failed to get HIF context", __func__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302944 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302945 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002946 }
2947
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002948 wma->wow.wow_enable_cmd_sent = true;
2949
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302950 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002951
2952error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302953 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002954}
2955
2956/**
2957 * wma_resume_req() - clear configured wow patterns in fw
2958 * @wma: wma handle
Houston Hoffmana76591b2015-11-10 16:52:05 -08002959 * @type: type of suspend
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002960 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302961 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002962 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05302963QDF_STATUS wma_resume_req(tp_wma_handle wma, enum qdf_suspend_type type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002964{
Anurag Chouhan6d760662016-02-20 16:05:43 +05302965 if (type == QDF_SYSTEM_SUSPEND) {
Houston Hoffmana76591b2015-11-10 16:52:05 -08002966 wma->no_of_resume_ind++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002967
Houston Hoffmana76591b2015-11-10 16:52:05 -08002968 if (wma->no_of_resume_ind < wma_get_vdev_count(wma))
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302969 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002970
Houston Hoffmana76591b2015-11-10 16:52:05 -08002971 wma->no_of_resume_ind = 0;
2972 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002973
2974 /* Reset the DTIM Parameters */
2975 wma_set_resume_dtim(wma);
2976 /* need to reset if hif_pci_suspend_fails */
2977 wma_set_wow_bus_suspend(wma, 0);
2978 /* unpause the vdev if left paused and hif_pci_suspend fails */
2979 wma_unpause_vdev(wma);
2980
Houston Hoffman1460fa32015-11-18 02:36:30 -08002981 wmi_set_runtime_pm_inprogress(wma->wmi_handle, false);
2982
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302983 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002984}
2985
2986/**
2987 * wma_wow_delete_pattern() - delete wow pattern in target
2988 * @wma: wma handle
2989 * @ptrn_id: pattern id
2990 * @vdev_id: vdev id
2991 * @user: true for user pattern and false for default pattern
2992 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302993 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002994 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302995static QDF_STATUS wma_wow_delete_pattern(tp_wma_handle wma, uint8_t ptrn_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002996 uint8_t vdev_id, bool user)
2997{
Govind Singhaa64c242016-03-08 11:31:49 +05302998
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002999 struct wma_txrx_node *iface;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003000 int ret;
3001
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003002 iface = &wma->interfaces[vdev_id];
Govind Singhaa64c242016-03-08 11:31:49 +05303003 ret = wmi_unified_wow_delete_pattern_cmd(wma->wmi_handle, ptrn_id,
3004 vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003005 if (ret) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303006 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003007 }
3008
3009 if (user)
3010 iface->num_wow_user_patterns--;
3011
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303012 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003013}
3014
3015/**
3016 * wma_wow_add_pattern() - add wow pattern in target
3017 * @wma: wma handle
3018 * @ptrn: wow pattern
3019 *
3020 * This function does following:
3021 * 1) Delete all default patterns of the vdev
3022 * 2) Add received wow patterns for given vdev in target.
3023 *
3024 * Target is responsible for caching wow patterns accross multiple
3025 * suspend/resumes until the pattern is deleted by user
3026 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303027 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003028 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303029QDF_STATUS wma_wow_add_pattern(tp_wma_handle wma, struct wow_add_pattern *ptrn)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003030{
3031 uint8_t id;
3032 uint8_t bit_to_check, pos;
3033 struct wma_txrx_node *iface;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303034 QDF_STATUS ret = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003035 uint8_t new_mask[SIR_WOWL_BCAST_PATTERN_MAX_SIZE];
3036
3037 if (ptrn->session_id > wma->max_bssid) {
3038 WMA_LOGE("Invalid vdev id (%d)", ptrn->session_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303039 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003040 }
3041
3042 iface = &wma->interfaces[ptrn->session_id];
3043
3044 /* clear all default patterns cofigured by wma */
3045 for (id = 0; id < iface->num_wow_default_patterns; id++)
3046 wma_wow_delete_pattern(wma, id, ptrn->session_id, false);
3047
3048 iface->num_wow_default_patterns = 0;
3049
3050 WMA_LOGI("Add user passed wow pattern id %d vdev id %d",
3051 ptrn->pattern_id, ptrn->session_id);
3052 /*
3053 * Convert received pattern mask value from bit representation
3054 * to byte representation.
3055 *
3056 * For example, received value from umac,
3057 *
3058 * Mask value : A1 (equivalent binary is "1010 0001")
3059 * Pattern value : 12:00:13:00:00:00:00:44
3060 *
3061 * The value which goes to FW after the conversion from this
3062 * function (1 in mask value will become FF and 0 will
3063 * become 00),
3064 *
3065 * Mask value : FF:00:FF:00:0:00:00:FF
3066 * Pattern value : 12:00:13:00:00:00:00:44
3067 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303068 qdf_mem_zero(new_mask, sizeof(new_mask));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003069 for (pos = 0; pos < ptrn->pattern_size; pos++) {
3070 bit_to_check = (WMA_NUM_BITS_IN_BYTE - 1) -
3071 (pos % WMA_NUM_BITS_IN_BYTE);
3072 bit_to_check = 0x1 << bit_to_check;
3073 if (ptrn->pattern_mask[pos / WMA_NUM_BITS_IN_BYTE] &
3074 bit_to_check)
3075 new_mask[pos] = WMA_WOW_PTRN_MASK_VALID;
3076 }
3077
3078 ret = wma_send_wow_patterns_to_fw(wma, ptrn->session_id,
3079 ptrn->pattern_id,
3080 ptrn->pattern, ptrn->pattern_size,
3081 ptrn->pattern_byte_offset, new_mask,
3082 ptrn->pattern_size, true);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303083 if (ret != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003084 WMA_LOGE("Failed to add wow pattern %d", ptrn->pattern_id);
3085
3086 return ret;
3087}
3088
3089/**
3090 * wma_wow_delete_user_pattern() - delete user configured wow pattern in target
3091 * @wma: wma handle
3092 * @ptrn: wow pattern
3093 *
3094 * This function does following:
3095 * 1) Deletes a particular user configured wow pattern in target
3096 * 2) After deleting all user wow patterns add default wow patterns
3097 * specific to that vdev.
3098 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303099 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003100 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303101QDF_STATUS wma_wow_delete_user_pattern(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003102 struct wow_delete_pattern *pattern)
3103{
3104 struct wma_txrx_node *iface;
3105
3106 if (pattern->session_id > wma->max_bssid) {
3107 WMA_LOGE("Invalid vdev id %d", pattern->session_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303108 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003109 }
3110
3111 iface = &wma->interfaces[pattern->session_id];
3112 if (iface->num_wow_user_patterns <= 0) {
3113 WMA_LOGE("No valid user pattern. Num user pattern %u vdev %d",
3114 iface->num_wow_user_patterns, pattern->session_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303115 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003116 }
3117
3118 WMA_LOGI("Delete user passed wow pattern id %d total user pattern %d",
3119 pattern->pattern_id, iface->num_wow_user_patterns);
3120
3121 wma_wow_delete_pattern(wma, pattern->pattern_id,
3122 pattern->session_id, true);
3123
3124 /* configure default patterns once all user patterns are deleted */
3125 if (!iface->num_wow_user_patterns)
3126 wma_register_wow_default_patterns(wma, pattern->session_id);
3127
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303128 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003129}
3130
3131/**
3132 * wma_wow_enter() - store enable/disable status for pattern
3133 * @wma: wma handle
3134 * @info: wow parameters
3135 *
3136 * Records pattern enable/disable status locally. This choice will
3137 * take effect when the driver enter into suspend state.
3138 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303139 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003140 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303141QDF_STATUS wma_wow_enter(tp_wma_handle wma, tpSirHalWowlEnterParams info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003142{
3143 struct wma_txrx_node *iface;
3144
3145 WMA_LOGD("wow enable req received for vdev id: %d", info->sessionId);
3146
3147 if (info->sessionId > wma->max_bssid) {
3148 WMA_LOGE("Invalid vdev id (%d)", info->sessionId);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303149 qdf_mem_free(info);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303150 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003151 }
3152
3153 iface = &wma->interfaces[info->sessionId];
3154 iface->ptrn_match_enable = info->ucPatternFilteringEnable ?
3155 true : false;
3156 wma->wow.magic_ptrn_enable = info->ucMagicPktEnable ? true : false;
3157 wma->wow.deauth_enable = info->ucWowDeauthRcv ? true : false;
3158 wma->wow.disassoc_enable = info->ucWowDeauthRcv ? true : false;
3159 wma->wow.bmiss_enable = info->ucWowMaxMissedBeacons ? true : false;
3160
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303161 qdf_mem_free(info);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003162
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303163 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003164}
3165
3166/**
3167 * wma_wow_exit() - clear all wma states
3168 * @wma: wma handle
3169 * @info: wow params
3170 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303171 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003172 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303173QDF_STATUS wma_wow_exit(tp_wma_handle wma, tpSirHalWowlExitParams info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003174{
3175 struct wma_txrx_node *iface;
3176
3177 WMA_LOGD("wow disable req received for vdev id: %d", info->sessionId);
3178
3179 if (info->sessionId > wma->max_bssid) {
3180 WMA_LOGE("Invalid vdev id (%d)", info->sessionId);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303181 qdf_mem_free(info);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303182 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003183 }
3184
3185 iface = &wma->interfaces[info->sessionId];
3186 iface->ptrn_match_enable = false;
3187 wma->wow.magic_ptrn_enable = false;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303188 qdf_mem_free(info);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003189
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303190 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003191}
3192
3193/**
Houston Hoffmana76591b2015-11-10 16:52:05 -08003194 * wma_calculate_and_update_conn_state(): calculate each interfaces conn state
3195 * @wma: validated wma handle
3196 *
3197 * Identifies any vdev that is up and not in ap mode as connected.
3198 * stores this in the interfaces conn_state varible.
3199 */
3200void wma_calculate_and_update_conn_state(tp_wma_handle wma)
3201{
3202 int i;
3203 for (i = 0; i < wma->max_bssid; i++) {
3204 wma->interfaces[i].conn_state =
3205 !!(wma->interfaces[i].vdev_up &&
3206 !wma_is_vdev_in_ap_mode(wma, i));
3207 }
3208}
3209
3210/**
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003211 * wma_update_conn_state(): synchronize wma & hdd
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003212 * @wma: wma handle
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003213 * @conn_state: boolean array to populate
3214 * @len: validation parameter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003215 *
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003216 * populate interfaces conn_state with true if the interface
3217 * is a connected client and wow will configure a pattern.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003218 */
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003219void wma_update_conn_state(tp_wma_handle wma, uint32_t conn_mask)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003220{
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003221 int i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003222 for (i = 0; i < wma->max_bssid; i++) {
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003223 if (conn_mask & (1 << i))
3224 wma->interfaces[i].conn_state = true;
3225 else
3226 wma->interfaces[i].conn_state = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003227 }
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003228
3229 if (wma->wow.magic_ptrn_enable)
3230 return;
3231
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003232 for (i = 0; i < wma->max_bssid; i++) {
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003233 if (!wma->interfaces[i].ptrn_match_enable)
3234 wma->interfaces[i].conn_state = false;
3235 }
3236}
3237
3238/**
3239 * wma_is_beaconning_vdev_up(): check if a beaconning vdev is up
3240 * @wma: wma handle
3241 *
3242 * Return TRUE if beaconning vdev is up
3243 */
3244static inline
3245bool wma_is_beaconning_vdev_up(tp_wma_handle wma)
3246{
3247 int i;
3248 for (i = 0; i < wma->max_bssid; i++) {
3249 if (wma_is_vdev_in_beaconning_mode(wma, i)
3250 && wma->interfaces[i].vdev_up)
3251 return true;
3252 }
3253 return false;
3254}
3255
3256/**
3257 * wma_support_wow_for_beaconing: wow query for beaconning
3258 * @wma: wma handle
3259 *
3260 * Need to configure wow to enable beaconning offload when
3261 * a beaconing vdev is up and beaonning offload is configured.
3262 *
3263 * Return: true if we need to enable wow for beaconning offload
3264 */
3265static inline
3266bool wma_support_wow_for_beaconing(tp_wma_handle wma)
3267{
3268 if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
3269 WMI_SERVICE_BEACON_OFFLOAD)) {
3270 if (wma_is_beaconning_vdev_up(wma))
3271 return true;
3272 }
3273 return false;
3274}
3275
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003276#ifdef FEATURE_WLAN_SCAN_PNO
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003277/**
3278 * wma_is_pnoscan_in_progress(): check if a pnoscan is in progress
3279 * @wma: wma handle
3280 * @vdev_id: vdev_id
3281 *
3282 * Return: TRUE/FALSE
3283 */
3284static inline
3285bool wma_is_pnoscan_in_progress(tp_wma_handle wma, int vdev_id)
3286{
3287 return wma->interfaces[vdev_id].pno_in_progress;
3288}
Houston Hoffman345fa402015-12-16 11:28:51 -08003289
3290/**
3291 * wma_is_pnoscan_match_found(): check if a scan match was found
3292 * @wma: wma handle
3293 * @vdev_id: vdev_id
3294 *
3295 * Return: TRUE/FALSE
3296 */
3297static inline
3298bool wma_is_pnoscan_match_found(tp_wma_handle wma, int vdev_id)
3299{
3300 return wma->interfaces[vdev_id].nlo_match_evt_received;
3301}
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003302#else
3303/**
3304 * wma_is_pnoscan_in_progress(): dummy
3305 *
Houston Hoffman345fa402015-12-16 11:28:51 -08003306 * Return: False since no pnoscan cannot be in progress
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003307 * when feature flag is not defined.
3308 */
3309bool wma_is_pnoscan_in_progress(tp_wma_handle wma, int vdev_id)
3310{
3311 return FALSE;
3312}
Houston Hoffman345fa402015-12-16 11:28:51 -08003313
3314/**
3315 * wma_is_pnoscan_match_found(): dummy
3316 * @wma: wma handle
3317 * @vdev_id: vdev_id
3318 *
3319 * Return: False since no pnoscan cannot occur
3320 * when feature flag is not defined.
3321 */
3322static inline
3323bool wma_is_pnoscan_match_found(tp_wma_handle wma, int vdev_id)
3324{
3325 return FALSE;
3326}
Houston Hoffman61667962015-12-15 20:15:41 -08003327#endif
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003328
3329#ifdef FEATURE_WLAN_EXTSCAN
3330static inline
3331/**
3332 * wma_is_extscan_in_progress(): check if an extscan is in progress
3333 * @wma: wma handle
3334 * @vdev_id: vdev_id
3335 *
3336 * Return: TRUE/FALSvE
3337 */
3338bool wma_is_extscan_in_progress(tp_wma_handle wma, int vdev_id)
3339{
3340 return wma->interfaces[vdev_id].extscan_in_progress;
3341}
3342#else
3343/**
3344 * wma_is_extscan_in_progress(): dummy
3345 *
3346 * Return: False since no extscan can be in progress
3347 * when feature flag is not defined.
3348 */
3349bool wma_is_extscan_in_progress(tp_wma_handle wma, int vdev_id)
3350{
3351 return false;
3352}
3353#endif
3354
3355/**
3356 * wma_is_wow_applicable(): should enable wow
3357 * @wma: wma handle
3358 *
3359 * Enable WOW if any one of the condition meets,
3360 * 1) Is any one of vdev in beaconning mode (in AP mode) ?
3361 * 2) Is any one of vdev in connected state (in STA mode) ?
3362 * 3) Is PNO in progress in any one of vdev ?
3363 * 4) Is Extscan in progress in any one of vdev ?
3364 *
3365 * Return: true if wma needs to configure wow.
3366 */
3367bool wma_is_wow_applicable(tp_wma_handle wma)
3368{
3369 int vdev_id;
3370 if (wma_support_wow_for_beaconing(wma)) {
3371 WMA_LOGD("vdev is in beaconning mode, enabling wow");
3372 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003373 }
3374
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003375 for (vdev_id = 0; vdev_id < wma->max_bssid; vdev_id++) {
3376 if (wma->interfaces[vdev_id].conn_state) {
3377 WMA_LOGD("STA is connected, enabling wow");
3378 return true;
3379 } else if (wma_is_pnoscan_in_progress(wma, vdev_id)) {
3380 WMA_LOGD("PNO is in progress, enabling wow");
3381 return true;
3382 } else if (wma_is_extscan_in_progress(wma, vdev_id)) {
3383 WMA_LOGD("EXT is in progress, enabling wow");
3384 return true;
3385 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003386 }
3387
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003388 WMA_LOGD("All vdev are in disconnected state and pno/extscan is not in progress, skipping wow");
3389 return true;
3390}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003391
Houston Hoffman345fa402015-12-16 11:28:51 -08003392/**
3393 * wma_configure_dynamic_wake_events(): configure dyanmic wake events
3394 * @wma: wma handle
3395 *
3396 * Some wake events need to be enabled dynamically. Controll those here.
3397 *
3398 * Return: none
3399 */
3400void wma_configure_dynamic_wake_events(tp_wma_handle wma)
3401{
3402 int vdev_id;
3403 int enable_mask;
3404 int disable_mask;
3405
3406 for (vdev_id = 0; vdev_id < wma->max_bssid; vdev_id++) {
3407 enable_mask = 0;
3408 disable_mask = 0;
3409
3410 if (wma_is_pnoscan_in_progress(wma, vdev_id)) {
3411 if (wma_is_pnoscan_match_found(wma, vdev_id))
3412 enable_mask |=
3413 (1 << WOW_NLO_SCAN_COMPLETE_EVENT);
3414 else
3415 disable_mask |=
3416 (1 << WOW_NLO_SCAN_COMPLETE_EVENT);
3417 }
3418
3419 if (enable_mask != 0)
3420 wma_enable_disable_wakeup_event(wma, vdev_id,
3421 enable_mask, true);
3422 if (disable_mask != 0)
3423 wma_enable_disable_wakeup_event(wma, vdev_id,
3424 disable_mask, false);
3425 }
3426}
3427
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003428#ifdef FEATURE_WLAN_LPHB
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003429/**
3430 * wma_apply_lphb(): apply cached LPHB settings
3431 * @wma: wma handle
3432 *
3433 * LPHB cache, if any item was enabled, should be
3434 * applied.
3435 */
3436static inline
3437void wma_apply_lphb(tp_wma_handle wma)
3438{
3439 int i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003440 WMA_LOGD("%s: checking LPHB cache", __func__);
3441 for (i = 0; i < 2; i++) {
3442 if (wma->wow.lphb_cache[i].params.lphbEnableReq.enable) {
3443 WMA_LOGD("%s: LPHB cache for item %d is marked as enable",
3444 __func__, i + 1);
3445 wma_lphb_conf_hbenable(wma, &(wma->wow.lphb_cache[i]),
3446 false);
3447 }
3448 }
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003449}
3450#else
3451void wma_apply_lphb(tp_wma_handle wma) {}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003452#endif /* FEATURE_WLAN_LPHB */
3453
Houston Hoffmana76591b2015-11-10 16:52:05 -08003454static void wma_notify_suspend_req_procesed(tp_wma_handle wma,
Anurag Chouhan6d760662016-02-20 16:05:43 +05303455 enum qdf_suspend_type type)
Houston Hoffmana76591b2015-11-10 16:52:05 -08003456{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303457 if (type == QDF_SYSTEM_SUSPEND)
Houston Hoffmana76591b2015-11-10 16:52:05 -08003458 wma_send_status_to_suspend_ind(wma, true);
Anurag Chouhan6d760662016-02-20 16:05:43 +05303459 else if (type == QDF_RUNTIME_SUSPEND)
Anurag Chouhance0dc992016-02-16 18:18:03 +05303460 qdf_event_set(&wma->runtime_suspend);
Houston Hoffmana76591b2015-11-10 16:52:05 -08003461}
3462
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003463/**
3464 * wma_suspend_req() - Handles suspend indication request received from umac.
3465 * @wma: wma handle
Houston Hoffmana76591b2015-11-10 16:52:05 -08003466 * @type: type of suspend
3467 *
3468 * The type controlls how we notify the indicator that the indication has
3469 * been processed
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003470 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303471 * Return: QDF status
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003472 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05303473QDF_STATUS wma_suspend_req(tp_wma_handle wma, enum qdf_suspend_type type)
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003474{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303475 if (type == QDF_RUNTIME_SUSPEND)
Houston Hoffman1460fa32015-11-18 02:36:30 -08003476 wmi_set_runtime_pm_inprogress(wma->wmi_handle, true);
3477
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003478 if (wma_is_wow_applicable(wma)) {
3479 WMA_LOGE("WOW Suspend");
3480 wma_apply_lphb(wma);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003481
Houston Hoffman345fa402015-12-16 11:28:51 -08003482 wma_configure_dynamic_wake_events(wma);
3483
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003484 wma->wow.wow_enable = true;
3485 wma->wow.wow_enable_cmd_sent = false;
3486 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003487
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003488 /* Set the Suspend DTIM Parameters */
3489 wma_set_suspend_dtim(wma);
Houston Hoffmana76591b2015-11-10 16:52:05 -08003490
3491 wma_notify_suspend_req_procesed(wma, type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003492
3493 /* to handle race between hif_pci_suspend and
3494 * unpause/pause tx handler
3495 */
3496 wma_set_wow_bus_suspend(wma, 1);
3497
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303498 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003499}
3500
3501/**
3502 * wma_send_host_wakeup_ind_to_fw() - send wakeup ind to fw
3503 * @wma: wma handle
3504 *
3505 * Sends host wakeup indication to FW. On receiving this indication,
3506 * FW will come out of WOW.
3507 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303508 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003509 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303510static QDF_STATUS wma_send_host_wakeup_ind_to_fw(tp_wma_handle wma)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003511{
Anurag Chouhance0dc992016-02-16 18:18:03 +05303512 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003513 int ret;
3514#ifdef CONFIG_CNSS
Anurag Chouhan6d760662016-02-20 16:05:43 +05303515 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003516 if (NULL == pMac) {
3517 WMA_LOGE("%s: Unable to get PE context", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303518 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003519 }
3520#endif /* CONFIG_CNSS */
3521
Anurag Chouhance0dc992016-02-16 18:18:03 +05303522 qdf_event_reset(&wma->wma_resume_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003523
Govind Singhaa64c242016-03-08 11:31:49 +05303524 ret = wmi_unified_host_wakeup_ind_to_fw_cmd(wma->wmi_handle);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003525 if (ret) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303526 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003527 }
3528
3529 WMA_LOGD("Host wakeup indication sent to fw");
3530
Anurag Chouhance0dc992016-02-16 18:18:03 +05303531 qdf_status = qdf_wait_single_event(&(wma->wma_resume_event),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003532 WMA_RESUME_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05303533 if (QDF_STATUS_SUCCESS != qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003534 WMA_LOGP("%s: Timeout waiting for resume event from FW",
3535 __func__);
3536 WMA_LOGP("%s: Pending commands %d credits %d", __func__,
3537 wmi_get_pending_cmds(wma->wmi_handle),
3538 wmi_get_host_credits(wma->wmi_handle));
Prashanth Bhatta9e143052015-12-04 11:56:47 -08003539 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003540#ifdef CONFIG_CNSS
3541 if (pMac->sme.enableSelfRecovery) {
3542 cds_trigger_recovery();
3543 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303544 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003545 }
3546#else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303547 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003548#endif /* CONFIG_CNSS */
3549 } else {
3550 WMA_LOGE("%s: SSR in progress, ignore resume timeout",
3551 __func__);
3552 }
3553 } else {
3554 WMA_LOGD("Host wakeup received");
3555 }
3556
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303557 if (QDF_STATUS_SUCCESS == qdf_status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003558 wmi_set_target_suspend(wma->wmi_handle, false);
3559
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303560 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003561}
3562
3563/**
3564 * wma_disable_wow_in_fw() - Disable wow in PCIe resume context.
3565 * @handle: wma handle
3566 *
3567 * Return: 0 for success or error code
3568 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303569QDF_STATUS wma_disable_wow_in_fw(WMA_HANDLE handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003570{
3571 tp_wma_handle wma = handle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303572 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003573
3574 if (!wma->wow.wow_enable || !wma->wow.wow_enable_cmd_sent)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303575 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003576
3577 ret = wma_send_host_wakeup_ind_to_fw(wma);
3578
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303579 if (ret != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003580 return ret;
3581
3582 wma->wow.wow_enable = false;
3583 wma->wow.wow_enable_cmd_sent = false;
3584
3585 /* To allow the tx pause/unpause events */
3586 wma_set_wow_bus_suspend(wma, 0);
3587 /* Unpause the vdev as we are resuming */
3588 wma_unpause_vdev(wma);
3589
3590 return ret;
3591}
3592
3593#ifdef WLAN_FEATURE_LPSS
3594/**
3595 * wma_is_lpass_enabled() - check if lpass is enabled
3596 * @handle: Pointer to wma handle
3597 *
3598 * WoW is needed if LPASS or NaN feature is enabled in INI because
3599 * target can't wake up itself if its put in PDEV suspend when LPASS
3600 * or NaN features are supported
3601 *
3602 * Return: true if lpass is enabled else false
3603 */
3604bool static wma_is_lpass_enabled(tp_wma_handle wma)
3605{
3606 if (wma->is_lpass_enabled)
3607 return true;
3608 else
3609 return false;
3610}
3611#else
3612bool static wma_is_lpass_enabled(tp_wma_handle wma)
3613{
3614 return false;
3615}
3616#endif
3617
3618#ifdef WLAN_FEATURE_NAN
3619/**
3620 * wma_is_nan_enabled() - check if NaN is enabled
3621 * @handle: Pointer to wma handle
3622 *
3623 * WoW is needed if LPASS or NaN feature is enabled in INI because
3624 * target can't wake up itself if its put in PDEV suspend when LPASS
3625 * or NaN features are supported
3626 *
3627 * Return: true if NaN is enabled else false
3628 */
3629bool static wma_is_nan_enabled(tp_wma_handle wma)
3630{
3631 if (wma->is_nan_enabled)
3632 return true;
3633 else
3634 return false;
3635}
3636#else
3637bool static wma_is_nan_enabled(tp_wma_handle wma)
3638{
3639 return false;
3640}
3641#endif
3642
3643/**
3644 * wma_is_wow_mode_selected() - check if wow needs to be enabled in fw
3645 * @handle: Pointer to wma handle
3646 *
3647 * If lpass is enabled then always do wow else check wow_enable config
3648 *
3649 * Return: true is wow mode is needed else false
3650 */
Houston Hoffmana76591b2015-11-10 16:52:05 -08003651bool wma_is_wow_mode_selected(WMA_HANDLE handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003652{
3653 tp_wma_handle wma = (tp_wma_handle) handle;
3654
3655 if (wma_is_lpass_enabled(wma)) {
3656 WMA_LOGD("LPASS is enabled select WoW");
3657 return true;
3658 } else if (wma_is_nan_enabled(wma)) {
3659 WMA_LOGD("NAN is enabled select WoW");
3660 return true;
3661 } else {
3662 WMA_LOGD("WoW enable %d", wma->wow.wow_enable);
3663 return wma->wow.wow_enable;
3664 }
3665}
3666
3667/**
3668 * wma_del_ts_req() - send DELTS request to fw
3669 * @wma: wma handle
3670 * @msg: delts params
3671 *
3672 * Return: none
3673 */
3674void wma_del_ts_req(tp_wma_handle wma, tDelTsParams *msg)
3675{
Govind Singhaa64c242016-03-08 11:31:49 +05303676 if (wmi_unified_del_ts_cmd(wma->wmi_handle,
3677 msg->sessionId,
3678 TID_TO_WME_AC(msg->userPrio))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003679 WMA_LOGP("%s: Failed to send vdev DELTS command", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003680 }
Govind Singhaa64c242016-03-08 11:31:49 +05303681
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003682#ifdef WLAN_FEATURE_ROAM_OFFLOAD
3683 if (msg->setRICparams == true)
3684 wma_set_ric_req(wma, msg, false);
3685#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
3686
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303687 qdf_mem_free(msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003688}
3689
3690/**
3691 * wma_aggr_qos_req() - send aggr qos request to fw
3692 * @wma: handle to wma
3693 * @pAggrQosRspMsg - combined struct for all ADD_TS requests.
3694 *
3695 * A function to handle WMA_AGGR_QOS_REQ. This will send out
3696 * ADD_TS requestes to firmware in loop for all the ACs with
3697 * active flow.
3698 *
3699 * Return: none
3700 */
3701void wma_aggr_qos_req(tp_wma_handle wma,
3702 tAggrAddTsParams *pAggrQosRspMsg)
3703{
Govind Singhaa64c242016-03-08 11:31:49 +05303704 wmi_unified_aggr_qos_cmd(wma->wmi_handle,
3705 (struct aggr_add_ts_param *)pAggrQosRspMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003706 /* send reponse to upper layers from here only. */
3707 wma_send_msg(wma, WMA_AGGR_QOS_RSP, pAggrQosRspMsg, 0);
3708}
3709
3710/**
3711 * wma_add_ts_req() - send ADDTS request to fw
3712 * @wma: wma handle
3713 * @msg: ADDTS params
3714 *
3715 * Return: none
3716 */
3717void wma_add_ts_req(tp_wma_handle wma, tAddTsParams *msg)
3718{
Govind Singhaa64c242016-03-08 11:31:49 +05303719 struct add_ts_param cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003720
3721#ifdef FEATURE_WLAN_ESE
3722 /*
3723 * msmt_interval is in unit called TU (1 TU = 1024 us)
3724 * max value of msmt_interval cannot make resulting
3725 * interval_miliseconds overflow 32 bit
3726 */
3727 uint32_t intervalMiliseconds;
Anurag Chouhan6d760662016-02-20 16:05:43 +05303728 ol_txrx_pdev_handle pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003729 if (NULL == pdev) {
3730 WMA_LOGE("%s: Failed to get pdev", __func__);
3731 goto err;
3732 }
3733
3734 intervalMiliseconds = (msg->tsm_interval * 1024) / 1000;
3735
3736 ol_tx_set_compute_interval(pdev, intervalMiliseconds);
3737#endif /* FEATURE_WLAN_ESE */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303738 msg->status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003739
Govind Singhaa64c242016-03-08 11:31:49 +05303740
3741 cmd.sme_session_id = msg->sme_session_id;
3742 cmd.tspec.tsinfo.traffic.userPrio =
3743 TID_TO_WME_AC(msg->tspec.tsinfo.traffic.userPrio);
3744 cmd.tspec.mediumTime = msg->tspec.mediumTime;
3745 if (wmi_unified_add_ts_cmd(wma->wmi_handle, &cmd))
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303746 msg->status = QDF_STATUS_E_FAILURE;
Govind Singhaa64c242016-03-08 11:31:49 +05303747
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003748#ifdef WLAN_FEATURE_ROAM_OFFLOAD
3749 if (msg->setRICparams == true)
3750 wma_set_ric_req(wma, msg, true);
3751#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
3752
3753err:
3754 wma_send_msg(wma, WMA_ADD_TS_RSP, msg, 0);
3755}
3756
3757/**
3758 * wma_enable_disable_packet_filter() - enable/disable packet filter in target
3759 * @wma: Pointer to wma handle
3760 * @vdev_id: vdev id
3761 * @enable: Flag to enable/disable packet filter
3762 *
3763 * Return: 0 for success or error code
3764 */
3765static int wma_enable_disable_packet_filter(tp_wma_handle wma,
3766 uint8_t vdev_id, bool enable)
3767{
Govind Singhaa64c242016-03-08 11:31:49 +05303768 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003769
Govind Singhaa64c242016-03-08 11:31:49 +05303770 ret = wmi_unified_enable_disable_packet_filter_cmd(wma->wmi_handle,
3771 vdev_id, enable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003772 if (ret)
3773 WMA_LOGE("Failed to send packet filter wmi cmd to fw");
3774
3775 return ret;
3776}
3777
3778/**
3779 * wma_config_packet_filter() - configure packet filter in target
3780 * @wma: Pointer to wma handle
3781 * @vdev_id: vdev id
3782 * @rcv_filter_param: Packet filter parameters
3783 * @filter_id: Filter id
3784 * @enable: Flag to add/delete packet filter configuration
3785 *
3786 * Return: 0 for success or error code
3787 */
3788static int wma_config_packet_filter(tp_wma_handle wma,
3789 uint8_t vdev_id, tSirRcvPktFilterCfgType *rcv_filter_param,
3790 uint8_t filter_id, bool enable)
3791{
Govind Singhaa64c242016-03-08 11:31:49 +05303792 int err;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003793
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003794 /* send the command along with data */
Govind Singhaa64c242016-03-08 11:31:49 +05303795 err = wmi_unified_config_packet_filter_cmd(wma->wmi_handle,
3796 vdev_id, (struct rcv_pkt_filter_config *)rcv_filter_param,
3797 filter_id, enable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003798 if (err) {
3799 WMA_LOGE("Failed to send pkt_filter cmd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003800 return -EIO;
3801 }
3802
3803 /* Enable packet filter */
3804 if (enable)
3805 wma_enable_disable_packet_filter(wma, vdev_id, true);
3806
3807 return 0;
3808}
3809
3810/**
3811 * wma_process_receive_filter_set_filter_req() - enable packet filter
3812 * @wma_handle: wma handle
3813 * @rcv_filter_param: filter params
3814 *
3815 * Return: 0 for success or error code
3816 */
3817int wma_process_receive_filter_set_filter_req(tp_wma_handle wma,
3818 tSirRcvPktFilterCfgType *rcv_filter_param)
3819{
3820 int ret = 0;
3821 uint8_t vdev_id;
3822
3823 /* Get the vdev id */
Srinivas Girigowda98530492015-11-20 17:39:24 -08003824 if (!wma_find_vdev_by_bssid(wma,
3825 rcv_filter_param->bssid.bytes, &vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003826 WMA_LOGE("vdev handle is invalid for %pM",
Srinivas Girigowda98530492015-11-20 17:39:24 -08003827 rcv_filter_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003828 return -EINVAL;
3829 }
3830
3831 ret = wma_config_packet_filter(wma, vdev_id, rcv_filter_param,
3832 rcv_filter_param->filterId, true);
3833
3834 return ret;
3835}
3836
3837/**
3838 * wma_process_receive_filter_clear_filter_req() - disable packet filter
3839 * @wma_handle: wma handle
3840 * @rcv_clear_param: filter params
3841 *
3842 * Return: 0 for success or error code
3843 */
3844int wma_process_receive_filter_clear_filter_req(tp_wma_handle wma,
3845 tSirRcvFltPktClearParam *rcv_clear_param)
3846{
3847 int ret = 0;
3848 uint8_t vdev_id;
3849
3850 /* Get the vdev id */
Srinivas Girigowda98530492015-11-20 17:39:24 -08003851 if (!wma_find_vdev_by_bssid(wma,
3852 rcv_clear_param->bssid.bytes, &vdev_id)) {
3853 WMA_LOGE("vdev handle is invalid for %pM",
3854 rcv_clear_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003855 return -EINVAL;
3856 }
3857
3858 ret = wma_config_packet_filter(wma, vdev_id, NULL,
3859 rcv_clear_param->filterId, false);
3860
3861 return ret;
3862}
3863
3864#ifdef FEATURE_WLAN_ESE
3865
3866#define TSM_DELAY_HISTROGRAM_BINS 4
3867/**
3868 * wma_process_tsm_stats_req() - process tsm stats request
3869 * @wma_handler - handle to wma
3870 * @pTsmStatsMsg - TSM stats struct that needs to be populated and
3871 * passed in message.
3872 *
3873 * A parallel function to WMA_ProcessTsmStatsReq for pronto. This
3874 * function fetches stats from data path APIs and post
3875 * WMA_TSM_STATS_RSP msg back to LIM.
3876 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303877 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003878 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303879QDF_STATUS wma_process_tsm_stats_req(tp_wma_handle wma_handler,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003880 void *pTsmStatsMsg)
3881{
3882 uint8_t counter;
3883 uint32_t queue_delay_microsec = 0;
3884 uint32_t tx_delay_microsec = 0;
3885 uint16_t packet_count = 0;
3886 uint16_t packet_loss_count = 0;
3887 tpAniTrafStrmMetrics pTsmMetric = NULL;
3888#ifdef FEATURE_WLAN_ESE_UPLOAD
3889 tpAniGetTsmStatsReq pStats = (tpAniGetTsmStatsReq) pTsmStatsMsg;
3890 tpAniGetTsmStatsRsp pTsmRspParams = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003891#endif /* FEATURE_WLAN_ESE_UPLOAD */
3892 int tid = pStats->tid;
3893 /*
3894 * The number of histrogram bin report by data path api are different
3895 * than required by TSM, hence different (6) size array used
3896 */
3897 uint16_t bin_values[QCA_TX_DELAY_HIST_REPORT_BINS] = { 0, };
3898
Anurag Chouhan6d760662016-02-20 16:05:43 +05303899 ol_txrx_pdev_handle pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003900
3901 if (NULL == pdev) {
3902 WMA_LOGE("%s: Failed to get pdev", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303903 qdf_mem_free(pTsmStatsMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303904 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003905 }
3906
3907 /* get required values from data path APIs */
3908 ol_tx_delay(pdev, &queue_delay_microsec, &tx_delay_microsec, tid);
3909 ol_tx_delay_hist(pdev, bin_values, tid);
3910 ol_tx_packet_count(pdev, &packet_count, &packet_loss_count, tid);
3911
3912#ifdef FEATURE_WLAN_ESE_UPLOAD
3913 pTsmRspParams =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303914 (tpAniGetTsmStatsRsp) qdf_mem_malloc(sizeof(tAniGetTsmStatsRsp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003915 if (NULL == pTsmRspParams) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303916 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303917 "%s: QDF MEM Alloc Failure", __func__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303918 QDF_ASSERT(0);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303919 qdf_mem_free(pTsmStatsMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303920 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003921 }
3922 pTsmRspParams->staId = pStats->staId;
3923 pTsmRspParams->rc = eSIR_FAILURE;
3924 pTsmRspParams->tsmStatsReq = pStats;
3925 pTsmMetric = &pTsmRspParams->tsmMetrics;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003926#endif /* FEATURE_WLAN_ESE_UPLOAD */
3927 /* populate pTsmMetric */
3928 pTsmMetric->UplinkPktQueueDly = queue_delay_microsec;
3929 /* store only required number of bin values */
3930 for (counter = 0; counter < TSM_DELAY_HISTROGRAM_BINS; counter++) {
3931 pTsmMetric->UplinkPktQueueDlyHist[counter] =
3932 bin_values[counter];
3933 }
3934 pTsmMetric->UplinkPktTxDly = tx_delay_microsec;
3935 pTsmMetric->UplinkPktLoss = packet_loss_count;
3936 pTsmMetric->UplinkPktCount = packet_count;
3937
3938 /*
3939 * No need to populate roaming delay and roaming count as they are
3940 * being populated just before sending IAPP frame out
3941 */
3942 /* post this message to LIM/PE */
3943#ifdef FEATURE_WLAN_ESE_UPLOAD
3944 wma_send_msg(wma_handler, WMA_TSM_STATS_RSP, (void *)pTsmRspParams, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003945#endif /* FEATURE_WLAN_ESE_UPLOAD */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303946 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003947}
3948
3949#endif /* FEATURE_WLAN_ESE */
3950
3951/**
3952 * wma_add_clear_mcbc_filter() - set mcast filter command to fw
3953 * @wma_handle: wma handle
3954 * @vdev_id: vdev id
3955 * @multicastAddr: mcast address
3956 * @clearList: clear list flag
3957 *
3958 * Return: 0 for success or error code
3959 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05303960static QDF_STATUS wma_add_clear_mcbc_filter(tp_wma_handle wma_handle,
3961 uint8_t vdev_id,
Anurag Chouhan6d760662016-02-20 16:05:43 +05303962 struct qdf_mac_addr multicast_addr,
Srinivas Girigowda98530492015-11-20 17:39:24 -08003963 bool clearList)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003964{
Himanshu Agarwal44195412016-03-09 13:03:54 +05303965 return wmi_unified_add_clear_mcbc_filter_cmd(wma_handle->wmi_handle,
3966 vdev_id, multicast_addr, clearList);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003967}
3968
3969/**
3970 * wma_process_mcbc_set_filter_req() - process mcbc set filter request
3971 * @wma_handle: wma handle
3972 * @mcbc_param: mcbc params
3973 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303974 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003975 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303976QDF_STATUS wma_process_mcbc_set_filter_req(tp_wma_handle wma_handle,
Anurag Chouhance0dc992016-02-16 18:18:03 +05303977 tSirRcvFltMcAddrList *mcbc_param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003978{
3979 uint8_t vdev_id = 0;
3980 int i;
3981
3982 if (mcbc_param->ulMulticastAddrCnt <= 0) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08003983 WMA_LOGW("Number of multicast addresses is 0");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303984 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003985 }
3986
Srinivas Girigowda98530492015-11-20 17:39:24 -08003987 if (!wma_find_vdev_by_addr(wma_handle,
3988 mcbc_param->self_macaddr.bytes, &vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003989 WMA_LOGE("%s: Failed to find vdev id for %pM", __func__,
Srinivas Girigowda98530492015-11-20 17:39:24 -08003990 mcbc_param->bssid.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303991 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003992 }
3993 /* set mcbc_param->action to clear MCList and reset
3994 * to configure the MCList in FW
3995 */
3996
3997 for (i = 0; i < mcbc_param->ulMulticastAddrCnt; i++) {
3998 wma_add_clear_mcbc_filter(wma_handle, vdev_id,
3999 mcbc_param->multicastAddr[i],
4000 (mcbc_param->action == 0));
4001 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304002 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004003}
4004
4005#ifdef WLAN_FEATURE_GTK_OFFLOAD
4006#define GTK_OFFLOAD_ENABLE 0
4007#define GTK_OFFLOAD_DISABLE 1
4008
4009/**
4010 * wma_gtk_offload_status_event() - GTK offload status event handler
4011 * @handle: wma handle
4012 * @event: event buffer
4013 * @len: buffer length
4014 *
4015 * Return: 0 for success or error code
4016 */
4017int wma_gtk_offload_status_event(void *handle, uint8_t *event,
4018 uint32_t len)
4019{
4020 tp_wma_handle wma = (tp_wma_handle) handle;
4021 WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param *status;
4022 WMI_GTK_OFFLOAD_STATUS_EVENTID_param_tlvs *param_buf;
4023 tpSirGtkOffloadGetInfoRspParams resp;
4024 cds_msg_t cds_msg;
4025 uint8_t *bssid;
4026
4027 WMA_LOGD("%s Enter", __func__);
4028
4029 param_buf = (WMI_GTK_OFFLOAD_STATUS_EVENTID_param_tlvs *) event;
4030 if (!param_buf) {
4031 WMA_LOGE("param_buf is NULL");
4032 return -EINVAL;
4033 }
4034
4035 status = (WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param *) param_buf->fixed_param;
4036
4037 if (len < sizeof(WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param)) {
4038 WMA_LOGE("Invalid length for GTK status");
4039 return -EINVAL;
4040 }
4041 bssid = wma_find_bssid_by_vdev_id(wma, status->vdev_id);
4042 if (!bssid) {
4043 WMA_LOGE("invalid bssid for vdev id %d", status->vdev_id);
4044 return -ENOENT;
4045 }
4046
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304047 resp = qdf_mem_malloc(sizeof(*resp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004048 if (!resp) {
4049 WMA_LOGE("%s: Failed to alloc response", __func__);
4050 return -ENOMEM;
4051 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304052 qdf_mem_zero(resp, sizeof(*resp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004053 resp->mesgType = eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP;
4054 resp->mesgLen = sizeof(*resp);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304055 resp->ulStatus = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004056 resp->ulTotalRekeyCount = status->refresh_cnt;
4057 /* TODO: Is the total rekey count and GTK rekey count same? */
4058 resp->ulGTKRekeyCount = status->refresh_cnt;
4059
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304060 qdf_mem_copy(&resp->ullKeyReplayCounter, &status->replay_counter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004061 GTK_REPLAY_COUNTER_BYTES);
4062
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304063 qdf_mem_copy(resp->bssid.bytes, bssid, IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004064
4065#ifdef IGTK_OFFLOAD
4066 /* TODO: Is the refresh count same for GTK and IGTK? */
4067 resp->ulIGTKRekeyCount = status->refresh_cnt;
4068#endif /* IGTK_OFFLOAD */
4069
4070 cds_msg.type = eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP;
4071 cds_msg.bodyptr = (void *)resp;
4072 cds_msg.bodyval = 0;
4073
4074 if (cds_mq_post_message(CDS_MQ_ID_SME, (cds_msg_t *) &cds_msg)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304075 != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004076 WMA_LOGE("Failed to post GTK response to SME");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304077 qdf_mem_free(resp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004078 return -EINVAL;
4079 }
4080
4081 WMA_LOGD("GTK: got target status with replay counter "
4082 "%02x%02x%02x%02x%02x%02x%02x%02x. vdev %d "
4083 "Refresh GTK %d times exchanges since last set operation",
4084 status->replay_counter[0],
4085 status->replay_counter[1],
4086 status->replay_counter[2],
4087 status->replay_counter[3],
4088 status->replay_counter[4],
4089 status->replay_counter[5],
4090 status->replay_counter[6],
4091 status->replay_counter[7],
4092 status->vdev_id, status->refresh_cnt);
4093
4094 WMA_LOGD("%s Exit", __func__);
4095
4096 return 0;
4097}
4098
4099/**
4100 * wma_send_gtk_offload_req() - send GTK offload command to fw
4101 * @wma: wma handle
4102 * @vdev_id: vdev id
4103 * @params: GTK offload parameters
4104 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304105 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004106 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304107static QDF_STATUS wma_send_gtk_offload_req(tp_wma_handle wma, uint8_t vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004108 tpSirGtkOffloadParams params)
4109{
Himanshu Agarwal44195412016-03-09 13:03:54 +05304110 struct gtk_offload_params offload_params = {0};
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304111 QDF_STATUS status = QDF_STATUS_SUCCESS;
Himanshu Agarwal44195412016-03-09 13:03:54 +05304112 bool enable_offload;
4113 uint32_t gtk_offload_opcode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004114
4115 WMA_LOGD("%s Enter", __func__);
4116
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004117 /* Request target to enable GTK offload */
4118 if (params->ulFlags == GTK_OFFLOAD_ENABLE) {
Himanshu Agarwal44195412016-03-09 13:03:54 +05304119 gtk_offload_opcode = GTK_OFFLOAD_ENABLE_OPCODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004120 wma->wow.gtk_err_enable[vdev_id] = true;
4121
4122 /* Copy the keys and replay counter */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304123 qdf_mem_copy(offload_params.aKCK, params->aKCK,
4124 GTK_OFFLOAD_KCK_BYTES);
4125 qdf_mem_copy(offload_params.aKEK, params->aKEK,
4126 GTK_OFFLOAD_KEK_BYTES);
4127 qdf_mem_copy(&offload_params.ullKeyReplayCounter,
4128 &params->ullKeyReplayCounter, GTK_REPLAY_COUNTER_BYTES);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004129 } else {
4130 wma->wow.gtk_err_enable[vdev_id] = false;
Himanshu Agarwal44195412016-03-09 13:03:54 +05304131 gtk_offload_opcode = GTK_OFFLOAD_DISABLE_OPCODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004132 }
4133
Himanshu Agarwal44195412016-03-09 13:03:54 +05304134 enable_offload = params->ulFlags;
4135
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004136 /* send the wmi command */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304137 status = wmi_unified_send_gtk_offload_cmd(wma->wmi_handle,
4138 vdev_id, &offload_params,
4139 enable_offload,
4140 gtk_offload_opcode);
4141 if (QDF_IS_STATUS_ERROR(status))
4142 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004143
Himanshu Agarwal44195412016-03-09 13:03:54 +05304144 WMA_LOGD("VDEVID: %d, GTK_FLAGS: x%x", vdev_id, gtk_offload_opcode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004145out:
4146 WMA_LOGD("%s Exit", __func__);
4147 return status;
4148}
4149
4150/**
4151 * wma_process_gtk_offload_req() - process GTK offload req from umac
4152 * @handle: wma handle
4153 * @params: GTK offload params
4154 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304155 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004156 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304157QDF_STATUS wma_process_gtk_offload_req(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004158 tpSirGtkOffloadParams params)
4159{
4160 uint8_t vdev_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304161 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004162
4163 WMA_LOGD("%s Enter", __func__);
4164
4165 /* Get the vdev id */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08004166 if (!wma_find_vdev_by_bssid(wma, params->bssid.bytes, &vdev_id)) {
4167 WMA_LOGE("vdev handle is invalid for %pM", params->bssid.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304168 status = QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004169 goto out;
4170 }
4171
4172 /* Validate vdev id */
4173 if (vdev_id >= wma->max_bssid) {
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08004174 WMA_LOGE("invalid vdev_id %d for %pM", vdev_id,
4175 params->bssid.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304176 status = QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004177 goto out;
4178 }
4179
4180 if ((params->ulFlags == GTK_OFFLOAD_ENABLE) &&
4181 (wma->wow.gtk_err_enable[vdev_id] == true)) {
4182 WMA_LOGE("%s GTK Offload already enabled. Disable it first "
4183 "vdev_id %d", __func__, vdev_id);
4184 params->ulFlags = GTK_OFFLOAD_DISABLE;
4185 status = wma_send_gtk_offload_req(wma, vdev_id, params);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304186 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004187 WMA_LOGE("%s Failed to disable GTK Offload", __func__);
4188 goto out;
4189 }
4190 WMA_LOGD("%s Enable GTK Offload again with updated inputs",
4191 __func__);
4192 params->ulFlags = GTK_OFFLOAD_ENABLE;
4193 }
4194 status = wma_send_gtk_offload_req(wma, vdev_id, params);
4195out:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304196 qdf_mem_free(params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004197 WMA_LOGD("%s Exit", __func__);
4198 return status;
4199}
4200
4201/**
4202 * wma_process_gtk_offload_getinfo_req() - send GTK offload cmd to fw
4203 * @wma: wma handle
4204 * @params: GTK offload params
4205 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304206 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004207 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304208QDF_STATUS wma_process_gtk_offload_getinfo_req(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004209 tpSirGtkOffloadGetInfoRspParams params)
4210{
4211 uint8_t vdev_id;
Himanshu Agarwal44195412016-03-09 13:03:54 +05304212 uint64_t offload_req_opcode;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304213 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004214
4215 WMA_LOGD("%s Enter", __func__);
4216
4217 /* Get the vdev id */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08004218 if (!wma_find_vdev_by_bssid(wma, params->bssid.bytes, &vdev_id)) {
4219 WMA_LOGE("vdev handle is invalid for %pM", params->bssid.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304220 status = QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004221 goto out;
4222 }
4223
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004224 /* Request for GTK offload status */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304225 offload_req_opcode = GTK_OFFLOAD_REQUEST_STATUS_OPCODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004226
4227 /* send the wmi command */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304228 status = wmi_unified_process_gtk_offload_getinfo_cmd(wma->wmi_handle,
4229 vdev_id, offload_req_opcode);
4230
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004231out:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304232 qdf_mem_free(params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004233 WMA_LOGD("%s Exit", __func__);
4234 return status;
4235}
4236#endif /* WLAN_FEATURE_GTK_OFFLOAD */
4237
4238/**
4239 * wma_enable_arp_ns_offload() - enable ARP NS offload
4240 * @wma: wma handle
4241 * @tpSirHostOffloadReq: offload request
Govind Singhaa64c242016-03-08 11:31:49 +05304242 * @arp_only: flag
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004243 *
4244 * To configure ARP NS off load data to firmware
4245 * when target goes to wow mode.
4246 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304247 * Return: QDF Status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004248 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304249QDF_STATUS wma_enable_arp_ns_offload(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004250 tpSirHostOffloadReq
Govind Singhaa64c242016-03-08 11:31:49 +05304251 pHostOffloadParams, bool arp_only)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004252{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004253 int32_t res;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004254 uint8_t vdev_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004255
4256 /* Get the vdev id */
Srinivas Girigowdab084b552015-11-24 12:39:12 -08004257 if (!wma_find_vdev_by_bssid(wma, pHostOffloadParams->bssid.bytes,
4258 &vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004259 WMA_LOGE("vdev handle is invalid for %pM",
Srinivas Girigowdab084b552015-11-24 12:39:12 -08004260 pHostOffloadParams->bssid.bytes);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304261 qdf_mem_free(pHostOffloadParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304262 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004263 }
4264
4265 if (!wma->interfaces[vdev_id].vdev_up) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004266 WMA_LOGE("vdev %d is not up skipping arp/ns offload", vdev_id);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304267 qdf_mem_free(pHostOffloadParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304268 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004269 }
4270
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004271
Govind Singhaa64c242016-03-08 11:31:49 +05304272 res = wmi_unified_enable_arp_ns_offload_cmd(wma->wmi_handle,
4273 (struct host_offload_req_param *)pHostOffloadParams,
4274 arp_only,
4275 vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004276 if (res) {
4277 WMA_LOGE("Failed to enable ARP NDP/NSffload");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304278 qdf_mem_free(pHostOffloadParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304279 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004280 }
4281
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304282 qdf_mem_free(pHostOffloadParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304283 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004284}
4285
4286/**
4287 * wma_process_add_periodic_tx_ptrn_ind - add periodic tx ptrn
4288 * @handle: wma handle
4289 * @pAddPeriodicTxPtrnParams: tx ptrn params
4290 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304291 * Retrun: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004292 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304293QDF_STATUS wma_process_add_periodic_tx_ptrn_ind(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004294 tSirAddPeriodicTxPtrn *
4295 pAddPeriodicTxPtrnParams)
4296{
4297 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Himanshu Agarwal44195412016-03-09 13:03:54 +05304298 struct periodic_tx_pattern params;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004299 uint8_t vdev_id;
Himanshu Agarwal44195412016-03-09 13:03:54 +05304300
4301 qdf_mem_set(&params, sizeof(struct periodic_tx_pattern), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004302
4303 if (!wma_handle || !wma_handle->wmi_handle) {
4304 WMA_LOGE("%s: WMA is closed, can not issue fw add pattern cmd",
4305 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304306 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004307 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004308
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004309 if (!wma_find_vdev_by_addr(wma_handle,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004310 pAddPeriodicTxPtrnParams->mac_address.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004311 &vdev_id)) {
4312 WMA_LOGE("%s: Failed to find vdev id for %pM", __func__,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004313 pAddPeriodicTxPtrnParams->mac_address.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304314 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004315 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004316
Himanshu Agarwal44195412016-03-09 13:03:54 +05304317 params.ucPtrnId = pAddPeriodicTxPtrnParams->ucPtrnId;
4318 params.ucPtrnSize = pAddPeriodicTxPtrnParams->ucPtrnSize;
4319 params.usPtrnIntervalMs = pAddPeriodicTxPtrnParams->usPtrnIntervalMs;
4320 qdf_mem_copy(&params.mac_address,
4321 &pAddPeriodicTxPtrnParams->mac_address,
4322 sizeof(struct qdf_mac_addr));
4323 qdf_mem_copy(params.ucPattern, pAddPeriodicTxPtrnParams->ucPattern,
4324 params.ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004325
Himanshu Agarwal44195412016-03-09 13:03:54 +05304326 return wmi_unified_process_add_periodic_tx_ptrn_cmd(
4327 wma_handle->wmi_handle, &params, vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004328}
4329
4330/**
4331 * wma_process_del_periodic_tx_ptrn_ind - del periodic tx ptrn
4332 * @handle: wma handle
4333 * @pDelPeriodicTxPtrnParams: tx ptrn params
4334 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304335 * Retrun: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004336 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304337QDF_STATUS wma_process_del_periodic_tx_ptrn_ind(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004338 tSirDelPeriodicTxPtrn *
4339 pDelPeriodicTxPtrnParams)
4340{
4341 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004342 uint8_t vdev_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004343
4344 if (!wma_handle || !wma_handle->wmi_handle) {
4345 WMA_LOGE("%s: WMA is closed, can not issue Del Pattern cmd",
4346 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304347 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004348 }
Himanshu Agarwal44195412016-03-09 13:03:54 +05304349
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004350 if (!wma_find_vdev_by_addr(wma_handle,
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08004351 pDelPeriodicTxPtrnParams->mac_address.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004352 &vdev_id)) {
4353 WMA_LOGE("%s: Failed to find vdev id for %pM", __func__,
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08004354 pDelPeriodicTxPtrnParams->mac_address.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304355 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004356 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004357
Himanshu Agarwal44195412016-03-09 13:03:54 +05304358 return wmi_unified_process_del_periodic_tx_ptrn_cmd(
4359 wma_handle->wmi_handle, vdev_id,
4360 pDelPeriodicTxPtrnParams->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004361}
4362
4363#ifdef WLAN_FEATURE_STATS_EXT
4364/**
4365 * wma_stats_ext_req() - request ext stats from fw
4366 * @wma_ptr: wma handle
4367 * @preq: stats ext params
4368 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304369 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004370 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304371QDF_STATUS wma_stats_ext_req(void *wma_ptr, tpStatsExtRequest preq)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004372{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004373 tp_wma_handle wma = (tp_wma_handle) wma_ptr;
Himanshu Agarwal44195412016-03-09 13:03:54 +05304374 struct stats_ext_params params = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004375
Himanshu Agarwal44195412016-03-09 13:03:54 +05304376 if (!wma) {
4377 WMA_LOGE("%s: wma handle is NULL", __func__);
4378 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004379 }
4380
Himanshu Agarwal44195412016-03-09 13:03:54 +05304381 params.vdev_id = preq->vdev_id;
4382 params.request_data_len = preq->request_data_len;
4383 qdf_mem_copy(params.request_data, preq->request_data,
4384 params.request_data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004385
Himanshu Agarwal44195412016-03-09 13:03:54 +05304386 return wmi_unified_stats_ext_req_cmd(wma->wmi_handle,
4387 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004388}
4389
4390#endif /* WLAN_FEATURE_STATS_EXT */
4391
4392#ifdef WLAN_FEATURE_EXTWOW_SUPPORT
4393/**
4394 * wma_send_status_of_ext_wow() - send ext wow status to SME
4395 * @wma: wma handle
4396 * @status: status
4397 *
4398 * Return: none
4399 */
4400static void wma_send_status_of_ext_wow(tp_wma_handle wma, bool status)
4401{
4402 tSirReadyToExtWoWInd *ready_to_extwow;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304403 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004404 cds_msg_t cds_msg;
4405 uint8_t len;
4406
4407 WMA_LOGD("Posting ready to suspend indication to umac");
4408
4409 len = sizeof(tSirReadyToExtWoWInd);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304410 ready_to_extwow = (tSirReadyToExtWoWInd *) qdf_mem_malloc(len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004411
4412 if (NULL == ready_to_extwow) {
4413 WMA_LOGE("%s: Memory allocation failure", __func__);
4414 return;
4415 }
4416
4417 ready_to_extwow->mesgType = eWNI_SME_READY_TO_EXTWOW_IND;
4418 ready_to_extwow->mesgLen = len;
4419 ready_to_extwow->status = status;
4420
4421 cds_msg.type = eWNI_SME_READY_TO_EXTWOW_IND;
4422 cds_msg.bodyptr = (void *)ready_to_extwow;
4423 cds_msg.bodyval = 0;
4424
4425 vstatus = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304426 if (vstatus != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004427 WMA_LOGE("Failed to post ready to suspend");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304428 qdf_mem_free(ready_to_extwow);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004429 }
4430}
4431
4432/**
4433 * wma_enable_ext_wow() - enable ext wow in fw
4434 * @wma: wma handle
4435 * @params: ext wow params
4436 *
4437 * Return:0 for success or error code
4438 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304439QDF_STATUS wma_enable_ext_wow(tp_wma_handle wma, tpSirExtWoWParams params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004440{
Himanshu Agarwal44195412016-03-09 13:03:54 +05304441 struct ext_wow_params wow_params = {0};
4442 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004443
Himanshu Agarwal44195412016-03-09 13:03:54 +05304444 if (!wma) {
4445 WMA_LOGE("%s: wma handle is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304446 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004447 }
4448
Himanshu Agarwal44195412016-03-09 13:03:54 +05304449 wow_params.vdev_id = params->vdev_id;
4450 wow_params.type = (enum wmi_ext_wow_type) params->type;
4451 wow_params.wakeup_pin_num = params->wakeup_pin_num;
4452
4453 status = wmi_unified_enable_ext_wow_cmd(wma->wmi_handle,
4454 &wow_params);
4455 if (QDF_IS_STATUS_ERROR(status))
4456 return status;
4457
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004458 wma_send_status_of_ext_wow(wma, true);
Himanshu Agarwal44195412016-03-09 13:03:54 +05304459 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004460
4461}
4462
4463/**
4464 * wma_set_app_type1_params_in_fw() - set app type1 params in fw
4465 * @wma: wma handle
4466 * @appType1Params: app type1 params
4467 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304468 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004469 */
4470int wma_set_app_type1_params_in_fw(tp_wma_handle wma,
4471 tpSirAppType1Params appType1Params)
4472{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004473 int ret;
4474
Govind Singhaa64c242016-03-08 11:31:49 +05304475 ret = wmi_unified_app_type1_params_in_fw_cmd(wma->wmi_handle,
4476 (struct app_type1_params *)appType1Params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004477 if (ret) {
4478 WMA_LOGE("%s: Failed to set APP TYPE1 PARAMS", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304479 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004480 }
4481
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304482 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004483}
4484
4485/**
4486 * wma_set_app_type2_params_in_fw() - set app type2 params in fw
4487 * @wma: wma handle
4488 * @appType2Params: app type2 params
4489 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304490 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004491 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304492QDF_STATUS wma_set_app_type2_params_in_fw(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004493 tpSirAppType2Params appType2Params)
4494{
Himanshu Agarwal44195412016-03-09 13:03:54 +05304495 struct app_type2_params params = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004496
Himanshu Agarwal44195412016-03-09 13:03:54 +05304497 if (!wma) {
4498 WMA_LOGE("%s: wma handle is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304499 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004500 }
4501
Himanshu Agarwal44195412016-03-09 13:03:54 +05304502 params.vdev_id = appType2Params->vdev_id;
4503 params.rc4_key_len = appType2Params->rc4_key_len;
4504 qdf_mem_copy(params.rc4_key, appType2Params->rc4_key, 16);
4505 params.ip_id = appType2Params->ip_id;
4506 params.ip_device_ip = appType2Params->ip_device_ip;
4507 params.ip_server_ip = appType2Params->ip_server_ip;
4508 params.tcp_src_port = appType2Params->tcp_src_port;
4509 params.tcp_dst_port = appType2Params->tcp_dst_port;
4510 params.tcp_seq = appType2Params->tcp_seq;
4511 params.tcp_ack_seq = appType2Params->tcp_ack_seq;
4512 params.keepalive_init = appType2Params->keepalive_init;
4513 params.keepalive_min = appType2Params->keepalive_min;
4514 params.keepalive_max = appType2Params->keepalive_max;
4515 params.keepalive_inc = appType2Params->keepalive_inc;
4516 params.tcp_tx_timeout_val = appType2Params->tcp_tx_timeout_val;
4517 params.tcp_rx_timeout_val = appType2Params->tcp_rx_timeout_val;
4518 qdf_mem_copy(&params.gateway_mac, &appType2Params->gateway_mac,
4519 sizeof(struct qdf_mac_addr));
4520
4521 return wmi_unified_set_app_type2_params_in_fw_cmd(wma->wmi_handle,
4522 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004523
4524}
4525#endif /* WLAN_FEATURE_EXTWOW_SUPPORT */
4526
4527#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
4528/**
4529 * wma_auto_shutdown_event_handler() - process auto shutdown timer trigger
4530 * @handle: wma handle
4531 * @event: event buffer
4532 * @len: buffer length
4533 *
4534 * Return: 0 for success or error code
4535 */
4536int wma_auto_shutdown_event_handler(void *handle, uint8_t *event,
4537 uint32_t len)
4538{
4539 wmi_host_auto_shutdown_event_fixed_param *wmi_auto_sh_evt;
4540 WMI_HOST_AUTO_SHUTDOWN_EVENTID_param_tlvs *param_buf =
4541 (WMI_HOST_AUTO_SHUTDOWN_EVENTID_param_tlvs *)
4542 event;
4543
4544 if (!param_buf || !param_buf->fixed_param) {
4545 WMA_LOGE("%s:%d: Invalid Auto shutdown timer evt", __func__,
4546 __LINE__);
4547 return -EINVAL;
4548 }
4549
4550 wmi_auto_sh_evt = param_buf->fixed_param;
4551
4552 if (wmi_auto_sh_evt->shutdown_reason
4553 != WMI_HOST_AUTO_SHUTDOWN_REASON_TIMER_EXPIRY) {
4554 WMA_LOGE("%s:%d: Invalid Auto shutdown timer evt", __func__,
4555 __LINE__);
4556 return -EINVAL;
4557 }
4558
4559 WMA_LOGD("%s:%d: Auto Shutdown Evt: %d", __func__, __LINE__,
4560 wmi_auto_sh_evt->shutdown_reason);
4561 return wma_post_auto_shutdown_msg();
4562}
4563
4564/**
4565 * wma_set_auto_shutdown_timer_req() - sets auto shutdown timer in firmware
4566 * @wma: wma handle
4567 * @auto_sh_cmd: auto shutdown timer value
4568 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304569 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004570 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304571QDF_STATUS wma_set_auto_shutdown_timer_req(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004572 tSirAutoShutdownCmdParams *
4573 auto_sh_cmd)
4574{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004575 if (auto_sh_cmd == NULL) {
4576 WMA_LOGE("%s : Invalid Autoshutdown cfg cmd", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304577 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004578 }
4579
Himanshu Agarwal44195412016-03-09 13:03:54 +05304580 return wmi_unified_set_auto_shutdown_timer_cmd(wma_handle->wmi_handle,
4581 auto_sh_cmd->timer_val);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004582}
4583#endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
4584
4585#ifdef WLAN_FEATURE_NAN
4586/**
4587 * wma_nan_req() - to send nan request to target
4588 * @wma: wma_handle
4589 * @nan_req: request data which will be non-null
4590 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304591 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004592 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304593QDF_STATUS wma_nan_req(void *wma_ptr, tpNanRequest nan_req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004594{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004595 tp_wma_handle wma_handle = (tp_wma_handle) wma_ptr;
Himanshu Agarwal44195412016-03-09 13:03:54 +05304596 struct nan_req_params params = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004597
Himanshu Agarwal44195412016-03-09 13:03:54 +05304598 if (!wma_handle) {
4599 WMA_LOGE("%s: wma handle is NULL", __func__);
4600 return QDF_STATUS_E_FAILURE;
4601 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004602 if (!nan_req) {
4603 WMA_LOGE("%s:nan req is not valid", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304604 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004605 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004606
Himanshu Agarwal44195412016-03-09 13:03:54 +05304607 params.request_data_len = nan_req->request_data_len;
4608 qdf_mem_copy(params.request_data, nan_req->request_data,
4609 params.request_data_len);
4610
4611 return wmi_unified_nan_req_cmd(wma_handle->wmi_handle,
4612 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004613}
4614#endif /* WLAN_FEATURE_NAN */
4615
4616#ifdef DHCP_SERVER_OFFLOAD
4617/**
4618 * wma_process_dhcpserver_offload() - enable DHCP server offload
4619 * @wma_handle: wma handle
4620 * @pDhcpSrvOffloadInfo: DHCP server offload info
4621 *
4622 * Return: 0 for success or error code
4623 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304624QDF_STATUS wma_process_dhcpserver_offload(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004625 tSirDhcpSrvOffloadInfo *
4626 pDhcpSrvOffloadInfo)
4627{
Himanshu Agarwal44195412016-03-09 13:03:54 +05304628 struct dhcp_offload_info_params params = {0};
4629 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004630
Himanshu Agarwal44195412016-03-09 13:03:54 +05304631 if (!wma_handle) {
4632 WMA_LOGE("%s: wma handle is NULL", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004633 return -EIO;
4634 }
Himanshu Agarwal44195412016-03-09 13:03:54 +05304635
4636 params.vdev_id = pDhcpSrvOffloadInfo->vdev_id;
4637 params.dhcpSrvOffloadEnabled =
4638 pDhcpSrvOffloadInfo->dhcpSrvOffloadEnabled;
4639 params.dhcpClientNum = pDhcpSrvOffloadInfo->dhcpClientNum;
4640 params.dhcpSrvIP = pDhcpSrvOffloadInfo->;
4641
4642 status = wmi_unified_process_dhcpserver_offload_cmd(
4643 wma_handle->wmi_handle, &params);
4644 if (QDF_IS_STATUS_ERROR(status))
4645 return status;
4646
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004647 WMA_LOGD("Set dhcp server offload to vdevId %d",
4648 pDhcpSrvOffloadInfo->vdev_id);
Himanshu Agarwal44195412016-03-09 13:03:54 +05304649 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004650}
4651#endif /* DHCP_SERVER_OFFLOAD */
4652
4653#ifdef WLAN_FEATURE_GPIO_LED_FLASHING
4654/**
4655 * wma_set_led_flashing() - set led flashing in fw
4656 * @wma_handle: wma handle
4657 * @flashing: flashing request
4658 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304659 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004660 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304661QDF_STATUS wma_set_led_flashing(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004662 tSirLedFlashingReq *flashing)
4663{
Govind Singhaa64c242016-03-08 11:31:49 +05304664 struct flashing_req_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004665
4666 if (!wma_handle || !wma_handle->wmi_handle) {
4667 WMA_LOGE(FL("WMA is closed, can not issue cmd"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304668 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004669 }
4670 if (!flashing) {
4671 WMA_LOGE(FL("invalid parameter: flashing"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304672 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004673 }
Govind Singhaa64c242016-03-08 11:31:49 +05304674 cmd.req_id = flashing->reqId;
4675 cmd.pattern_id = flashing->pattern_id;
4676 cmd.led_x0 = flashing->led_x0;
4677 cmd.led_x1 = flashing->led_x1;
4678 status = wmi_unified_set_led_flashing_cmd(wma_handle->wmi_handle,
4679 &cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004680 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304681 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004682 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304683 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004684}
4685#endif /* WLAN_FEATURE_GPIO_LED_FLASHING */
4686
4687#ifdef FEATURE_WLAN_CH_AVOID
4688/**
4689 * wma_channel_avoid_evt_handler() - process channel to avoid event from FW.
4690 * @handle: wma handle
4691 * @event: event buffer
4692 * @len: buffer length
4693 *
4694 * Return: 0 for success or error code
4695 */
4696int wma_channel_avoid_evt_handler(void *handle, uint8_t *event,
4697 uint32_t len)
4698{
4699 wmi_avoid_freq_ranges_event_fixed_param *afr_fixed_param;
4700 wmi_avoid_freq_range_desc *afr_desc;
4701 uint32_t num_freq_ranges, freq_range_idx;
4702 tSirChAvoidIndType *sca_indication;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304703 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004704 cds_msg_t sme_msg = { 0 };
4705 WMI_WLAN_FREQ_AVOID_EVENTID_param_tlvs *param_buf =
4706 (WMI_WLAN_FREQ_AVOID_EVENTID_param_tlvs *) event;
4707
4708 if (!param_buf) {
4709 WMA_LOGE("Invalid channel avoid event buffer");
4710 return -EINVAL;
4711 }
4712
4713 afr_fixed_param = param_buf->fixed_param;
4714 if (!afr_fixed_param) {
4715 WMA_LOGE("Invalid channel avoid event fixed param buffer");
4716 return -EINVAL;
4717 }
4718
4719 num_freq_ranges =
4720 (afr_fixed_param->num_freq_ranges >
4721 SIR_CH_AVOID_MAX_RANGE) ? SIR_CH_AVOID_MAX_RANGE :
4722 afr_fixed_param->num_freq_ranges;
4723
4724 WMA_LOGD("Channel avoid event received with %d ranges",
4725 num_freq_ranges);
4726 for (freq_range_idx = 0; freq_range_idx < num_freq_ranges;
4727 freq_range_idx++) {
4728 afr_desc = (wmi_avoid_freq_range_desc *)
4729 ((void *)param_buf->avd_freq_range +
4730 freq_range_idx * sizeof(wmi_avoid_freq_range_desc));
4731
4732 WMA_LOGD("range %d: tlv id = %u, start freq = %u, end freq = %u",
4733 freq_range_idx, afr_desc->tlv_header, afr_desc->start_freq,
4734 afr_desc->end_freq);
4735 }
4736
4737 sca_indication = (tSirChAvoidIndType *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304738 qdf_mem_malloc(sizeof(tSirChAvoidIndType));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004739 if (!sca_indication) {
4740 WMA_LOGE("Invalid channel avoid indication buffer");
4741 return -EINVAL;
4742 }
4743
4744 sca_indication->avoid_range_count = num_freq_ranges;
4745 for (freq_range_idx = 0; freq_range_idx < num_freq_ranges;
4746 freq_range_idx++) {
4747 afr_desc = (wmi_avoid_freq_range_desc *)
4748 ((void *)param_buf->avd_freq_range +
4749 freq_range_idx * sizeof(wmi_avoid_freq_range_desc));
4750 sca_indication->avoid_freq_range[freq_range_idx].start_freq =
4751 afr_desc->start_freq;
4752 sca_indication->avoid_freq_range[freq_range_idx].end_freq =
4753 afr_desc->end_freq;
4754 }
4755
4756 sme_msg.type = eWNI_SME_CH_AVOID_IND;
4757 sme_msg.bodyptr = sca_indication;
4758 sme_msg.bodyval = 0;
4759
Anurag Chouhan6d760662016-02-20 16:05:43 +05304760 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304761 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004762 WMA_LOGE("Fail to post eWNI_SME_CH_AVOID_IND msg to SME");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304763 qdf_mem_free(sca_indication);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004764 return -EINVAL;
4765 }
4766
4767 return 0;
4768}
4769
4770/**
4771 * wma_process_ch_avoid_update_req() - handles channel avoid update request
4772 * @wma_handle: wma handle
4773 * @ch_avoid_update_req: channel avoid update params
4774 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304775 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004776 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304777QDF_STATUS wma_process_ch_avoid_update_req(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004778 tSirChAvoidUpdateReq *
4779 ch_avoid_update_req)
4780{
Himanshu Agarwal44195412016-03-09 13:03:54 +05304781 QDF_STATUS status;
4782 if (!wma_handle) {
4783 WMA_LOGE("%s: wma handle is NULL", __func__);
4784 return QDF_STATUS_E_FAILURE;
4785 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004786 if (ch_avoid_update_req == NULL) {
4787 WMA_LOGE("%s : ch_avoid_update_req is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304788 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004789 }
4790
4791 WMA_LOGI("%s: WMA --> WMI_CHAN_AVOID_UPDATE", __func__);
4792
Himanshu Agarwal44195412016-03-09 13:03:54 +05304793 status = wmi_unified_process_ch_avoid_update_cmd(
4794 wma_handle->wmi_handle);
4795 if (QDF_IS_STATUS_ERROR(status))
4796 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004797
4798 WMA_LOGI("%s: WMA --> WMI_CHAN_AVOID_UPDATE sent through WMI",
4799 __func__);
Himanshu Agarwal44195412016-03-09 13:03:54 +05304800 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004801}
4802#endif /* FEATURE_WLAN_CH_AVOID */
4803
4804/**
4805 * wma_set_reg_domain() - set reg domain
4806 * @clientCtxt: client context
4807 * @regId: reg id
4808 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304809 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004810 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304811QDF_STATUS wma_set_reg_domain(void *clientCtxt, v_REGDOMAIN_t regId)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004812{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304813 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004814 cds_set_reg_domain(clientCtxt, regId))
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304815 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004816
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304817 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004818}
4819
4820/**
4821 * wma_send_regdomain_info_to_fw() - send regdomain info to fw
4822 * @reg_dmn: reg domain
4823 * @regdmn2G: 2G reg domain
4824 * @regdmn5G: 5G reg domain
4825 * @ctl2G: 2G test limit
4826 * @ctl5G: 5G test limit
4827 *
4828 * Return: none
4829 */
4830void wma_send_regdomain_info_to_fw(uint32_t reg_dmn, uint16_t regdmn2G,
4831 uint16_t regdmn5G, int8_t ctl2G,
4832 int8_t ctl5G)
4833{
Anurag Chouhan6d760662016-02-20 16:05:43 +05304834 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004835 int32_t cck_mask_val = 0;
Govind Singhd76a5b02016-03-08 15:12:14 +05304836 struct pdev_params pdev_param = {0};
Himanshu Agarwal44195412016-03-09 13:03:54 +05304837 QDF_STATUS ret = QDF_STATUS_SUCCESS;
4838 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004839
4840 if (NULL == wma) {
4841 WMA_LOGE("%s: wma context is NULL", __func__);
4842 return;
4843 }
4844
Himanshu Agarwal44195412016-03-09 13:03:54 +05304845 status = wmi_unified_send_regdomain_info_to_fw_cmd(wma->wmi_handle,
4846 reg_dmn, regdmn2G, regdmn5G, ctl2G, ctl5G);
4847 if (status == QDF_STATUS_E_NOMEM)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004848 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004849
4850 if ((((reg_dmn & ~COUNTRY_ERD_FLAG) == CTRY_JAPAN) ||
4851 ((reg_dmn & ~COUNTRY_ERD_FLAG) == CTRY_KOREA_ROC)) &&
4852 (true == wma->tx_chain_mask_cck))
4853 cck_mask_val = 1;
4854
4855 cck_mask_val |= (wma->self_gen_frm_pwr << 16);
Govind Singhd76a5b02016-03-08 15:12:14 +05304856 pdev_param.param_id = WMI_PDEV_PARAM_TX_CHAIN_MASK_CCK;
4857 pdev_param.param_value = cck_mask_val;
4858 ret = wmi_unified_pdev_param_send(wma->wmi_handle,
4859 &pdev_param,
4860 WMA_WILDCARD_PDEV_ID);
4861
Himanshu Agarwal44195412016-03-09 13:03:54 +05304862 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004863 WMA_LOGE("failed to set PDEV tx_chain_mask_cck %d",
4864 ret);
4865
4866 return;
4867}
4868
4869/**
Houston Hoffmana76591b2015-11-10 16:52:05 -08004870 * wma_post_runtime_resume_msg() - post the resume request
4871 * @handle: validated wma handle
4872 *
4873 * request the MC thread unpaus the vdev and set resume dtim
4874 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304875 * Return: qdf status of the mq post
Houston Hoffmana76591b2015-11-10 16:52:05 -08004876 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304877static QDF_STATUS wma_post_runtime_resume_msg(WMA_HANDLE handle)
Houston Hoffmana76591b2015-11-10 16:52:05 -08004878{
4879 cds_msg_t resume_msg;
4880
4881 resume_msg.bodyptr = NULL;
4882 resume_msg.type = WMA_RUNTIME_PM_RESUME_IND;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304883 return cds_mq_post_message(QDF_MODULE_ID_WMA, &resume_msg);
Houston Hoffmana76591b2015-11-10 16:52:05 -08004884}
4885
4886/**
4887 * wma_post_runtime_suspend_msg() - post the suspend request
4888 * @handle: validated wma handle
4889 *
4890 * Requests for offloads to be configured for runtime suspend
4891 * on the MC thread
4892 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304893 * Return QDF_STATUS_E_AGAIN in case of timeout or QDF_STATUS_SUCCESS
Houston Hoffmana76591b2015-11-10 16:52:05 -08004894 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304895static QDF_STATUS wma_post_runtime_suspend_msg(WMA_HANDLE handle)
Houston Hoffmana76591b2015-11-10 16:52:05 -08004896{
4897 cds_msg_t cds_msg;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304898 QDF_STATUS qdf_status;
Houston Hoffmana76591b2015-11-10 16:52:05 -08004899 tp_wma_handle wma = (tp_wma_handle) handle;
4900
Anurag Chouhance0dc992016-02-16 18:18:03 +05304901 qdf_event_reset(&wma->runtime_suspend);
Houston Hoffmana76591b2015-11-10 16:52:05 -08004902
4903 cds_msg.bodyptr = NULL;
4904 cds_msg.type = WMA_RUNTIME_PM_SUSPEND_IND;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304905 qdf_status = cds_mq_post_message(QDF_MODULE_ID_WMA, &cds_msg);
Houston Hoffmana76591b2015-11-10 16:52:05 -08004906
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304907 if (qdf_status != QDF_STATUS_SUCCESS)
Houston Hoffmana76591b2015-11-10 16:52:05 -08004908 goto failure;
4909
Anurag Chouhance0dc992016-02-16 18:18:03 +05304910 if (qdf_wait_single_event(&wma->runtime_suspend,
Houston Hoffmana76591b2015-11-10 16:52:05 -08004911 WMA_TGT_SUSPEND_COMPLETE_TIMEOUT) !=
Anurag Chouhance0dc992016-02-16 18:18:03 +05304912 QDF_STATUS_SUCCESS) {
Houston Hoffmana76591b2015-11-10 16:52:05 -08004913 WMA_LOGE("Failed to get runtime suspend event");
4914 goto failure;
4915 }
4916
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304917 return QDF_STATUS_SUCCESS;
Houston Hoffmana76591b2015-11-10 16:52:05 -08004918
4919failure:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304920 return QDF_STATUS_E_AGAIN;
Houston Hoffmana76591b2015-11-10 16:52:05 -08004921}
4922
4923/**
4924 * __wma_bus_suspend(): handles bus suspend for wma
4925 * @type: is this suspend part of runtime suspend or system suspend?
4926 *
4927 * Bails if a scan is in progress.
4928 * Calls the appropriate handlers based on configuration and event.
4929 *
4930 * Return: 0 for success or error code
4931 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05304932static int __wma_bus_suspend(enum qdf_suspend_type type)
Houston Hoffmana76591b2015-11-10 16:52:05 -08004933{
Anurag Chouhan6d760662016-02-20 16:05:43 +05304934 WMA_HANDLE handle = cds_get_context(QDF_MODULE_ID_WMA);
Houston Hoffmana76591b2015-11-10 16:52:05 -08004935 if (NULL == handle) {
4936 WMA_LOGE("%s: wma context is NULL", __func__);
4937 return -EFAULT;
4938 }
4939
4940 if (wma_check_scan_in_progress(handle)) {
4941 WMA_LOGE("%s: Scan in progress. Aborting suspend", __func__);
4942 return -EBUSY;
4943 }
4944
Anurag Chouhan6d760662016-02-20 16:05:43 +05304945 if (type == QDF_RUNTIME_SUSPEND) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304946 QDF_STATUS status = wma_post_runtime_suspend_msg(handle);
Houston Hoffmana76591b2015-11-10 16:52:05 -08004947 if (status)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304948 return qdf_status_to_os_return(status);
Houston Hoffmana76591b2015-11-10 16:52:05 -08004949 }
4950
Anurag Chouhan6d760662016-02-20 16:05:43 +05304951 if (type == QDF_SYSTEM_SUSPEND)
Houston Hoffmana76591b2015-11-10 16:52:05 -08004952 WMA_LOGE("%s: wow mode selected %d", __func__,
4953 wma_is_wow_mode_selected(handle));
4954
4955 if (wma_is_wow_mode_selected(handle)) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304956 QDF_STATUS status = wma_enable_wow_in_fw(handle);
4957 return qdf_status_to_os_return(status);
Houston Hoffmana76591b2015-11-10 16:52:05 -08004958 }
4959
4960 return wma_suspend_target(handle, 0);
4961}
4962
4963/**
4964 * wma_runtime_suspend() - handles runtime suspend request from hdd
4965 *
4966 * Calls the appropriate handler based on configuration and event.
4967 * Last busy marking should prevent race conditions between processing
4968 * of asyncronous fw events and the running of runtime suspend.
4969 * (eg. last busy marking should guarantee that any auth requests have
4970 * been processed)
4971 * Events comming from the host are not protected, but aren't expected
4972 * to be an issue.
4973 *
4974 * Return: 0 for success or error code
4975 */
4976int wma_runtime_suspend(void)
4977{
Anurag Chouhan6d760662016-02-20 16:05:43 +05304978 return __wma_bus_suspend(QDF_RUNTIME_SUSPEND);
Houston Hoffmana76591b2015-11-10 16:52:05 -08004979}
4980
4981/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004982 * wma_bus_suspend() - handles bus suspend request from hdd
4983 *
4984 * Calls the appropriate handler based on configuration and event
4985 *
4986 * Return: 0 for success or error code
4987 */
4988int wma_bus_suspend(void)
4989{
Houston Hoffmana76591b2015-11-10 16:52:05 -08004990
Anurag Chouhan6d760662016-02-20 16:05:43 +05304991 return __wma_bus_suspend(QDF_SYSTEM_SUSPEND);
Houston Hoffmana76591b2015-11-10 16:52:05 -08004992}
4993
4994/**
4995 * __wma_bus_resume() - bus resume for wma
4996 *
4997 * does the part of the bus resume common to bus and system suspend
4998 *
4999 * Return: os error code.
5000 */
5001int __wma_bus_resume(WMA_HANDLE handle)
5002{
5003 bool wow_mode = wma_is_wow_mode_selected(handle);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305004 QDF_STATUS status;
Houston Hoffmana76591b2015-11-10 16:52:05 -08005005
5006 WMA_LOGE("%s: wow mode %d", __func__, wow_mode);
5007
5008 if (!wow_mode)
5009 return wma_resume_target(handle);
5010
5011 status = wma_disable_wow_in_fw(handle);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305012 return qdf_status_to_os_return(status);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005013}
5014
5015/**
5016 * wma_runtime_resume() - do the runtime resume operation for wma
5017 *
5018 * Return: os error code.
5019 */
5020int wma_runtime_resume(void)
5021{
5022 int ret;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305023 QDF_STATUS status;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305024 WMA_HANDLE handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005025 if (NULL == handle) {
5026 WMA_LOGE("%s: wma context is NULL", __func__);
5027 return -EFAULT;
5028 }
5029
Houston Hoffmana76591b2015-11-10 16:52:05 -08005030 ret = __wma_bus_resume(handle);
5031 if (ret)
5032 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005033
Houston Hoffmana76591b2015-11-10 16:52:05 -08005034 status = wma_post_runtime_resume_msg(handle);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305035 return qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005036}
5037
5038/**
5039 * wma_bus_resume() - handles bus resume request from hdd
5040 * @handle: valid wma handle
5041 *
5042 * Calls the appropriate handler based on configuration
5043 *
5044 * Return: 0 for success or error code
5045 */
5046int wma_bus_resume(void)
5047{
Anurag Chouhan6d760662016-02-20 16:05:43 +05305048 WMA_HANDLE handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005049 if (NULL == handle) {
5050 WMA_LOGE("%s: wma context is NULL", __func__);
5051 return -EFAULT;
5052 }
5053
Houston Hoffmana76591b2015-11-10 16:52:05 -08005054 return __wma_bus_resume(handle);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005055}
5056
5057/**
5058 * wma_suspend_target() - suspend target
5059 * @handle: wma handle
5060 * @disable_target_intr: disable target interrupt
5061 *
Govind Singhd76a5b02016-03-08 15:12:14 +05305062 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005063 */
Govind Singhd76a5b02016-03-08 15:12:14 +05305064QDF_STATUS wma_suspend_target(WMA_HANDLE handle, int disable_target_intr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005065{
5066 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Komal Seelam3d202862016-02-24 18:43:24 +05305067 struct hif_opaque_softc *scn;
Govind Singhd76a5b02016-03-08 15:12:14 +05305068 QDF_STATUS status;
5069 struct suspend_params param = {0};
5070
Yue Mae1a85f32015-10-20 18:12:45 -07005071#ifdef CONFIG_CNSS
Anurag Chouhan6d760662016-02-20 16:05:43 +05305072 tpAniSirGlobal pmac = cds_get_context(QDF_MODULE_ID_PE);
Yue Mae1a85f32015-10-20 18:12:45 -07005073#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005074
5075 if (!wma_handle || !wma_handle->wmi_handle) {
5076 WMA_LOGE("WMA is closed. can not issue suspend cmd");
Govind Singhd76a5b02016-03-08 15:12:14 +05305077 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005078 }
Yue Mae1a85f32015-10-20 18:12:45 -07005079
5080#ifdef CONFIG_CNSS
5081 if (NULL == pmac) {
5082 WMA_LOGE("%s: Unable to get PE context", __func__);
Govind Singhd76a5b02016-03-08 15:12:14 +05305083 return QDF_STATUS_E_INVAL;
Yue Mae1a85f32015-10-20 18:12:45 -07005084 }
5085#endif
Anurag Chouhance0dc992016-02-16 18:18:03 +05305086 qdf_event_reset(&wma_handle->target_suspend);
Govind Singhd76a5b02016-03-08 15:12:14 +05305087 param.disable_target_intr = disable_target_intr;
5088 status = wmi_unified_suspend_send(wma_handle->wmi_handle,
5089 &param,
5090 WMA_WILDCARD_PDEV_ID);
5091 if (QDF_IS_STATUS_ERROR(status))
5092 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005093
5094 wmi_set_target_suspend(wma_handle->wmi_handle, true);
5095
Anurag Chouhance0dc992016-02-16 18:18:03 +05305096 if (qdf_wait_single_event(&wma_handle->target_suspend,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005097 WMA_TGT_SUSPEND_COMPLETE_TIMEOUT)
Anurag Chouhance0dc992016-02-16 18:18:03 +05305098 != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005099 WMA_LOGE("Failed to get ACK from firmware for pdev suspend");
5100 wmi_set_target_suspend(wma_handle->wmi_handle, false);
Yue Mae1a85f32015-10-20 18:12:45 -07005101#ifdef CONFIG_CNSS
Prashanth Bhatta9e143052015-12-04 11:56:47 -08005102 if (!cds_is_driver_recovering()) {
Yue Ma455aff62015-10-20 18:29:16 -07005103 if (pmac->sme.enableSelfRecovery) {
5104 cds_trigger_recovery();
5105 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305106 QDF_BUG(0);
Yue Ma455aff62015-10-20 18:29:16 -07005107 }
Yue Mae1a85f32015-10-20 18:12:45 -07005108 } else {
Yue Ma455aff62015-10-20 18:29:16 -07005109 WMA_LOGE("%s: LOGP is in progress, ignore!", __func__);
Yue Mae1a85f32015-10-20 18:12:45 -07005110 }
5111#endif
Govind Singhd76a5b02016-03-08 15:12:14 +05305112 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005113 }
5114
Anurag Chouhan6d760662016-02-20 16:05:43 +05305115 scn = cds_get_context(QDF_MODULE_ID_HIF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005116
5117 if (scn == NULL) {
5118 WMA_LOGE("%s: Failed to get HIF context", __func__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305119 QDF_ASSERT(0);
Govind Singhd76a5b02016-03-08 15:12:14 +05305120 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005121 }
5122
Govind Singhd76a5b02016-03-08 15:12:14 +05305123 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005124}
5125
5126/**
5127 * wma_target_suspend_acknowledge() - update target susspend status
5128 * @context: wma context
5129 *
5130 * Return: none
5131 */
5132void wma_target_suspend_acknowledge(void *context)
5133{
Anurag Chouhan6d760662016-02-20 16:05:43 +05305134 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005135 int wow_nack = *((int *)context);
5136
5137 if (NULL == wma) {
5138 WMA_LOGE("%s: wma is NULL", __func__);
5139 return;
5140 }
5141
5142 wma->wow_nack = wow_nack;
Anurag Chouhance0dc992016-02-16 18:18:03 +05305143 qdf_event_set(&wma->target_suspend);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005144 if (wow_nack)
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305145 qdf_wake_lock_timeout_acquire(&wma->wow_wake_lock,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005146 WMA_WAKE_LOCK_TIMEOUT,
5147 WIFI_POWER_EVENT_WAKELOCK_WOW);
5148}
5149
5150/**
5151 * wma_resume_target() - resume target
5152 * @handle: wma handle
5153 *
Govind Singhd76a5b02016-03-08 15:12:14 +05305154 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005155 */
Govind Singhd76a5b02016-03-08 15:12:14 +05305156QDF_STATUS wma_resume_target(WMA_HANDLE handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005157{
5158 int ret;
5159 tp_wma_handle wma = (tp_wma_handle) handle;
Anurag Chouhance0dc992016-02-16 18:18:03 +05305160 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005161#ifdef CONFIG_CNSS
Anurag Chouhan6d760662016-02-20 16:05:43 +05305162 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005163 if (NULL == pMac) {
5164 WMA_LOGE("%s: Unable to get PE context", __func__);
Govind Singhd76a5b02016-03-08 15:12:14 +05305165 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005166 }
5167#endif /* CONFIG_CNSS */
5168
Anurag Chouhance0dc992016-02-16 18:18:03 +05305169 qdf_event_reset(&wma->wma_resume_event);
Govind Singhd76a5b02016-03-08 15:12:14 +05305170 qdf_status = wmi_unified_resume_send(wma->wmi_handle,
5171 WMA_WILDCARD_PDEV_ID);
5172 if (QDF_IS_STATUS_ERROR(qdf_status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005173 WMA_LOGE("Failed to send WMI_PDEV_RESUME_CMDID command");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005174
Anurag Chouhance0dc992016-02-16 18:18:03 +05305175 qdf_status = qdf_wait_single_event(&(wma->wma_resume_event),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005176 WMA_RESUME_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05305177 if (QDF_STATUS_SUCCESS != qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005178 WMA_LOGP("%s: Timeout waiting for resume event from FW",
5179 __func__);
5180 WMA_LOGP("%s: Pending commands %d credits %d", __func__,
5181 wmi_get_pending_cmds(wma->wmi_handle),
5182 wmi_get_host_credits(wma->wmi_handle));
Prashanth Bhatta9e143052015-12-04 11:56:47 -08005183 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005184#ifdef CONFIG_CNSS
5185 if (pMac->sme.enableSelfRecovery) {
5186 cds_trigger_recovery();
5187 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305188 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005189 }
5190#else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305191 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005192#endif /* CONFIG_CNSS */
5193 } else {
5194 WMA_LOGE("%s: SSR in progress, ignore resume timeout",
5195 __func__);
5196 }
5197 } else {
5198 WMA_LOGD("Host wakeup received");
5199 }
5200
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305201 if (QDF_STATUS_SUCCESS == qdf_status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005202 wmi_set_target_suspend(wma->wmi_handle, false);
5203
5204 return ret;
5205}
5206
5207/**
5208 * wma_get_modeselect() - get modeSelect flag based on phy_capability
5209 * @wma: wma handle
5210 * @modeSelect: mode Select
5211 *
5212 * Return: none
5213 */
5214void wma_get_modeselect(tp_wma_handle wma, uint32_t *modeSelect)
5215{
5216
5217 switch (wma->phy_capability) {
5218 case WMI_11G_CAPABILITY:
5219 case WMI_11NG_CAPABILITY:
5220 *modeSelect &= ~(REGDMN_MODE_11A | REGDMN_MODE_TURBO |
5221 REGDMN_MODE_108A | REGDMN_MODE_11A_HALF_RATE |
5222 REGDMN_MODE_11A_QUARTER_RATE |
5223 REGDMN_MODE_11NA_HT20 |
5224 REGDMN_MODE_11NA_HT40PLUS |
5225 REGDMN_MODE_11NA_HT40MINUS |
5226 REGDMN_MODE_11AC_VHT20 |
5227 REGDMN_MODE_11AC_VHT40PLUS |
5228 REGDMN_MODE_11AC_VHT40MINUS |
5229 REGDMN_MODE_11AC_VHT80);
5230 break;
5231 case WMI_11A_CAPABILITY:
5232 case WMI_11NA_CAPABILITY:
5233 case WMI_11AC_CAPABILITY:
5234 *modeSelect &= ~(REGDMN_MODE_11B | REGDMN_MODE_11G |
5235 REGDMN_MODE_108G | REGDMN_MODE_11NG_HT20 |
5236 REGDMN_MODE_11NG_HT40PLUS |
5237 REGDMN_MODE_11NG_HT40MINUS |
5238 REGDMN_MODE_11AC_VHT20_2G |
5239 REGDMN_MODE_11AC_VHT40_2G |
5240 REGDMN_MODE_11AC_VHT80_2G);
5241 break;
5242 }
5243}
5244
5245
5246#ifdef FEATURE_WLAN_TDLS
5247/**
5248 * wma_tdls_event_handler() - handle TDLS event
5249 * @handle: wma handle
5250 * @event: event buffer
5251 * @len: buffer length
5252 *
5253 * Return: 0 for success or error code
5254 */
5255int wma_tdls_event_handler(void *handle, uint8_t *event, uint32_t len)
5256{
5257 tp_wma_handle wma = (tp_wma_handle) handle;
5258 WMI_TDLS_PEER_EVENTID_param_tlvs *param_buf = NULL;
5259 wmi_tdls_peer_event_fixed_param *peer_event = NULL;
5260 tSirTdlsEventnotify *tdls_event;
5261
5262 if (!event) {
5263 WMA_LOGE("%s: event param null", __func__);
5264 return -EINVAL;
5265 }
5266
5267 param_buf = (WMI_TDLS_PEER_EVENTID_param_tlvs *) event;
5268 if (!param_buf) {
5269 WMA_LOGE("%s: received null buf from target", __func__);
5270 return -EINVAL;
5271 }
5272
5273 peer_event = param_buf->fixed_param;
5274 if (!peer_event) {
5275 WMA_LOGE("%s: received null event data from target", __func__);
5276 return -EINVAL;
5277 }
5278
5279 tdls_event = (tSirTdlsEventnotify *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305280 qdf_mem_malloc(sizeof(*tdls_event));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005281 if (!tdls_event) {
5282 WMA_LOGE("%s: failed to allocate memory for tdls_event",
5283 __func__);
5284 return -ENOMEM;
5285 }
5286
5287 tdls_event->sessionId = peer_event->vdev_id;
5288 WMI_MAC_ADDR_TO_CHAR_ARRAY(&peer_event->peer_macaddr,
Srinivas Girigowda4f593792015-11-19 15:33:42 -08005289 tdls_event->peermac.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005290
5291 switch (peer_event->peer_status) {
5292 case WMI_TDLS_SHOULD_DISCOVER:
5293 tdls_event->messageType = WMA_TDLS_SHOULD_DISCOVER_CMD;
5294 break;
5295 case WMI_TDLS_SHOULD_TEARDOWN:
5296 tdls_event->messageType = WMA_TDLS_SHOULD_TEARDOWN_CMD;
5297 break;
5298 case WMI_TDLS_PEER_DISCONNECTED:
5299 tdls_event->messageType = WMA_TDLS_PEER_DISCONNECTED_CMD;
5300 break;
5301 default:
5302 WMA_LOGE("%s: Discarding unknown tdls event(%d) from target",
5303 __func__, peer_event->peer_status);
5304 return -EINVAL;
5305 }
5306
5307 switch (peer_event->peer_reason) {
5308 case WMI_TDLS_TEARDOWN_REASON_TX:
5309 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_TX;
5310 break;
5311 case WMI_TDLS_TEARDOWN_REASON_RSSI:
5312 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_RSSI;
5313 break;
5314 case WMI_TDLS_TEARDOWN_REASON_SCAN:
5315 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_SCAN;
5316 break;
5317 case WMI_TDLS_DISCONNECTED_REASON_PEER_DELETE:
5318 tdls_event->peer_reason =
5319 eWNI_TDLS_DISCONNECTED_REASON_PEER_DELETE;
5320 break;
5321 case WMI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT:
5322 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT;
5323 break;
5324 case WMI_TDLS_TEARDOWN_REASON_BAD_PTR:
5325 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_BAD_PTR;
5326 break;
5327 case WMI_TDLS_TEARDOWN_REASON_NO_RESPONSE:
5328 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_NO_RESPONSE;
5329 break;
5330 default:
5331 WMA_LOGE("%s: unknown reason(%d) in tdls event(%d) from target",
5332 __func__, peer_event->peer_reason,
5333 peer_event->peer_status);
5334 return -EINVAL;
5335 }
5336
5337 WMA_LOGD("%s: sending msg to umac, messageType: 0x%x, "
5338 "for peer: %pM, reason: %d, smesessionId: %d",
Srinivas Girigowda4f593792015-11-19 15:33:42 -08005339 __func__, tdls_event->messageType, tdls_event->peermac.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005340 tdls_event->peer_reason, tdls_event->sessionId);
5341
5342 wma_send_msg(wma, tdls_event->messageType, (void *)tdls_event, 0);
5343 return 0;
5344}
5345
5346/**
5347 * wma_set_tdls_offchan_mode() - set tdls off channel mode
5348 * @handle: wma handle
5349 * @chan_switch_params: Pointer to tdls channel switch parameter structure
5350 *
5351 * This function sets tdls off channel mode
5352 *
5353 * Return: 0 on success; Negative errno otherwise
5354 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05305355QDF_STATUS wma_set_tdls_offchan_mode(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005356 tdls_chan_switch_params *chan_switch_params)
5357{
5358 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Himanshu Agarwal44195412016-03-09 13:03:54 +05305359 struct tdls_channel_switch_params params = {0};
5360 QDF_STATUS ret = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005361
5362 if (!wma_handle || !wma_handle->wmi_handle) {
5363 WMA_LOGE(FL(
5364 "WMA is closed, can not issue tdls off channel cmd"
5365 ));
5366 ret = -EINVAL;
5367 goto end;
5368 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005369
Himanshu Agarwal44195412016-03-09 13:03:54 +05305370 params.vdev_id = chan_switch_params->vdev_id;
5371 params.tdls_off_ch_bw_offset =
5372 chan_switch_params->tdls_off_ch_bw_offset;
5373 params.tdls_off_ch = chan_switch_params->tdls_off_ch;
5374 params.tdls_sw_mode = chan_switch_params->tdls_sw_mode;
5375 params.oper_class = chan_switch_params->oper_class;
5376 params.is_responder = chan_switch_params->is_responder;
5377 qdf_mem_copy(params.peer_mac_addr, chan_switch_params->peer_mac_addr,
5378 WMI_ETH_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005379
Himanshu Agarwal44195412016-03-09 13:03:54 +05305380 ret = wmi_unified_set_tdls_offchan_mode_cmd(wma_handle->wmi_handle,
5381 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005382
5383end:
5384 if (chan_switch_params)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305385 qdf_mem_free(chan_switch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005386 return ret;
5387}
5388
5389/**
5390 * wma_update_fw_tdls_state() - send enable/disable tdls for a vdev
5391 * @wma: wma handle
5392 * @pwmaTdlsparams: TDLS params
5393 *
5394 * Return: 0 for sucess or error code
5395 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05305396QDF_STATUS wma_update_fw_tdls_state(WMA_HANDLE handle, void *pwmaTdlsparams)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005397{
5398 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005399 t_wma_tdls_mode tdls_mode;
5400 t_wma_tdls_params *wma_tdls = (t_wma_tdls_params *) pwmaTdlsparams;
Himanshu Agarwal44195412016-03-09 13:03:54 +05305401 struct wmi_tdls_params params = {0};
5402 QDF_STATUS ret = QDF_STATUS_SUCCESS;
5403 uint8_t tdls_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005404
5405 if (!wma_handle || !wma_handle->wmi_handle) {
5406 WMA_LOGE("%s: WMA is closed, can not issue fw tdls state cmd",
5407 __func__);
5408 ret = -EINVAL;
5409 goto end_fw_tdls_state;
5410 }
5411
Himanshu Agarwal44195412016-03-09 13:03:54 +05305412 params.tdls_state = wma_tdls->tdls_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005413 tdls_mode = wma_tdls->tdls_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005414
5415 if (WMA_TDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == tdls_mode) {
Himanshu Agarwal44195412016-03-09 13:03:54 +05305416 tdls_state = WMI_TDLS_ENABLE_PASSIVE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005417 } else if (WMA_TDLS_SUPPORT_ENABLED == tdls_mode) {
Himanshu Agarwal44195412016-03-09 13:03:54 +05305418 tdls_state = WMI_TDLS_ENABLE_ACTIVE;
Kabilan Kannan421714b2015-11-23 04:44:59 -08005419 } else if (WMA_TDLS_SUPPORT_ACTIVE_EXTERNAL_CONTROL == tdls_mode) {
Himanshu Agarwal44195412016-03-09 13:03:54 +05305420 tdls_state = WMI_TDLS_ENABLE_ACTIVE_EXTERNAL_CONTROL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005421 } else {
Himanshu Agarwal44195412016-03-09 13:03:54 +05305422 tdls_state = WMI_TDLS_DISABLE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005423 }
5424
Himanshu Agarwal44195412016-03-09 13:03:54 +05305425 params.vdev_id = wma_tdls->vdev_id;
5426 params.notification_interval_ms = wma_tdls->notification_interval_ms;
5427 params.tx_discovery_threshold = wma_tdls->tx_discovery_threshold;
5428 params.tx_teardown_threshold = wma_tdls->tx_teardown_threshold;
5429 params.rssi_teardown_threshold = wma_tdls->rssi_teardown_threshold;
5430 params.rssi_delta = wma_tdls->rssi_delta;
5431 params.tdls_options = wma_tdls->tdls_options;
5432 params.peer_traffic_ind_window = wma_tdls->peer_traffic_ind_window;
5433 params.peer_traffic_response_timeout =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005434 wma_tdls->peer_traffic_response_timeout;
Himanshu Agarwal44195412016-03-09 13:03:54 +05305435 params.puapsd_mask = wma_tdls->puapsd_mask;
5436 params.puapsd_inactivity_time = wma_tdls->puapsd_inactivity_time;
5437 params.puapsd_rx_frame_threshold =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005438 wma_tdls->puapsd_rx_frame_threshold;
Himanshu Agarwal44195412016-03-09 13:03:54 +05305439 params.teardown_notification_ms =
Kabilan Kannanca670be2015-11-23 01:56:12 -08005440 wma_tdls->teardown_notification_ms;
Himanshu Agarwal44195412016-03-09 13:03:54 +05305441 params.tdls_peer_kickout_threshold =
Kabilan Kannan421714b2015-11-23 04:44:59 -08005442 wma_tdls->tdls_peer_kickout_threshold;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005443
Himanshu Agarwal44195412016-03-09 13:03:54 +05305444 ret = wmi_unified_update_fw_tdls_state_cmd(wma_handle->wmi_handle,
5445 &params, tdls_state);
5446 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005447 goto end_fw_tdls_state;
Himanshu Agarwal44195412016-03-09 13:03:54 +05305448
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005449 WMA_LOGD("%s: vdev_id %d", __func__, wma_tdls->vdev_id);
5450
5451end_fw_tdls_state:
5452 if (pwmaTdlsparams)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305453 qdf_mem_free(pwmaTdlsparams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005454 return ret;
5455}
5456
5457/**
5458 * wma_update_tdls_peer_state() - update TDLS peer state
5459 * @handle: wma handle
5460 * @peerStateParams: TDLS peer state params
5461 *
5462 * Return: 0 for success or error code
5463 */
5464int wma_update_tdls_peer_state(WMA_HANDLE handle,
5465 tTdlsPeerStateParams *peerStateParams)
5466{
5467 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005468 uint32_t i;
5469 ol_txrx_pdev_handle pdev;
5470 uint8_t peer_id;
5471 struct ol_txrx_peer_t *peer;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005472 int ret = 0;
Govind Singhaa64c242016-03-08 11:31:49 +05305473 uint32_t *ch_mhz;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005474
5475 if (!wma_handle || !wma_handle->wmi_handle) {
5476 WMA_LOGE("%s: WMA is closed, can not issue cmd", __func__);
5477 ret = -EINVAL;
5478 goto end_tdls_peer_state;
5479 }
5480
5481 /* peer capability info is valid only when peer state is connected */
5482 if (WMA_TDLS_PEER_STATE_CONNECTED != peerStateParams->peerState) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305483 qdf_mem_zero(&peerStateParams->peerCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005484 sizeof(tTdlsPeerCapParams));
5485 }
5486
Govind Singhaa64c242016-03-08 11:31:49 +05305487 ch_mhz = qdf_mem_malloc(sizeof(uint32_t) *
5488 peerStateParams->peerCap.peerChanLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005489 for (i = 0; i < peerStateParams->peerCap.peerChanLen; ++i) {
Govind Singhaa64c242016-03-08 11:31:49 +05305490 ch_mhz[i] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005491 cds_chan_to_freq(peerStateParams->peerCap.peerChan[i].
5492 chanId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005493 }
5494
Govind Singhaa64c242016-03-08 11:31:49 +05305495 if (wmi_unified_update_tdls_peer_state_cmd(wma_handle->wmi_handle,
5496 (struct tdls_peer_state_params *)peerStateParams,
5497 ch_mhz)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005498 WMA_LOGE("%s: failed to send tdls peer update state command",
5499 __func__);
Govind Singhaa64c242016-03-08 11:31:49 +05305500 qdf_mem_free(ch_mhz);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005501 ret = -EIO;
5502 goto end_tdls_peer_state;
5503 }
5504
Govind Singhaa64c242016-03-08 11:31:49 +05305505 qdf_mem_free(ch_mhz);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005506 /* in case of teardown, remove peer from fw */
5507 if (WMA_TDLS_PEER_STATE_TEARDOWN == peerStateParams->peerState) {
Anurag Chouhan6d760662016-02-20 16:05:43 +05305508 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005509 if (!pdev) {
5510 WMA_LOGE("%s: Failed to find pdev", __func__);
5511 ret = -EIO;
5512 goto end_tdls_peer_state;
5513 }
5514
5515 peer = ol_txrx_find_peer_by_addr(pdev,
5516 peerStateParams->peerMacAddr,
5517 &peer_id);
5518 if (!peer) {
5519 WMA_LOGE("%s: Failed to get peer handle using peer mac %pM",
5520 __func__, peerStateParams->peerMacAddr);
5521 ret = -EIO;
5522 goto end_tdls_peer_state;
5523 }
5524
5525 WMA_LOGD("%s: calling wma_remove_peer for peer " MAC_ADDRESS_STR
5526 " vdevId: %d", __func__,
5527 MAC_ADDR_ARRAY(peer->mac_addr.raw),
5528 peerStateParams->vdevId);
5529 wma_remove_peer(wma_handle, peer->mac_addr.raw,
5530 peerStateParams->vdevId, peer, false);
5531 }
5532
5533end_tdls_peer_state:
5534 if (peerStateParams)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305535 qdf_mem_free(peerStateParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005536 return ret;
5537}
5538#endif /* FEATURE_WLAN_TDLS */
5539
5540
5541/**
5542 * wma_dfs_attach() - Attach DFS methods to the umac state.
5543 * @dfs_ic: ieee80211com ptr
5544 *
5545 * Return: Return ieee80211com ptr with updated info
5546 */
5547struct ieee80211com *wma_dfs_attach(struct ieee80211com *dfs_ic)
5548{
5549 /*Allocate memory for dfs_ic before passing it up to dfs_attach() */
5550 dfs_ic = (struct ieee80211com *)
5551 os_malloc(NULL, sizeof(struct ieee80211com), GFP_ATOMIC);
5552 if (dfs_ic == NULL) {
5553 WMA_LOGE("%s:Allocation of dfs_ic failed %zu",
5554 __func__, sizeof(struct ieee80211com));
5555 return NULL;
5556 }
5557 OS_MEMZERO(dfs_ic, sizeof(struct ieee80211com));
5558 /* DFS pattern matching hooks */
5559 dfs_ic->ic_dfs_attach = ol_if_dfs_attach;
5560 dfs_ic->ic_dfs_disable = ol_if_dfs_disable;
5561 dfs_ic->ic_find_channel = ieee80211_find_channel;
5562 dfs_ic->ic_dfs_enable = ol_if_dfs_enable;
5563 dfs_ic->ic_ieee2mhz = ieee80211_ieee2mhz;
5564
5565 /* Hardware facing hooks */
5566 dfs_ic->ic_get_ext_busy = ol_if_dfs_get_ext_busy;
5567 dfs_ic->ic_get_mib_cycle_counts_pct =
5568 ol_if_dfs_get_mib_cycle_counts_pct;
5569 dfs_ic->ic_get_TSF64 = ol_if_get_tsf64;
5570
5571 /* NOL related hooks */
5572 dfs_ic->ic_dfs_usenol = ol_if_dfs_usenol;
5573 /*
5574 * Hooks from wma/dfs/ back
5575 * into the PE/SME
5576 * and shared DFS code
5577 */
5578 dfs_ic->ic_dfs_notify_radar = ieee80211_mark_dfs;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305579 qdf_spinlock_create(&dfs_ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005580 /* Initializes DFS Data Structures and queues */
5581 dfs_attach(dfs_ic);
5582
5583 return dfs_ic;
5584}
5585
5586/**
5587 * wma_dfs_detach() - Detach DFS methods
5588 * @dfs_ic: ieee80211com ptr
5589 *
5590 * Return: none
5591 */
5592void wma_dfs_detach(struct ieee80211com *dfs_ic)
5593{
5594 dfs_detach(dfs_ic);
5595
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305596 qdf_spinlock_destroy(&dfs_ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005597 if (NULL != dfs_ic->ic_curchan) {
5598 OS_FREE(dfs_ic->ic_curchan);
5599 dfs_ic->ic_curchan = NULL;
5600 }
5601
5602 OS_FREE(dfs_ic);
5603}
5604
5605/**
5606 * wma_dfs_configure() - configure dfs
5607 * @ic: ieee80211com ptr
5608 *
5609 * Configures Radar Filters during
5610 * vdev start/channel change/regulatory domain
5611 * change.This Configuration enables to program
5612 * the DFS pattern matching module.
5613 *
5614 * Return: none
5615 */
5616void wma_dfs_configure(struct ieee80211com *ic)
5617{
5618 struct ath_dfs_radar_tab_info rinfo;
5619 int dfsdomain;
5620 int radar_enabled_status = 0;
5621 if (ic == NULL) {
5622 WMA_LOGE("%s: DFS ic is Invalid", __func__);
5623 return;
5624 }
5625
5626 dfsdomain = ic->current_dfs_regdomain;
5627
5628 /* Fetch current radar patterns from the lmac */
5629 OS_MEMZERO(&rinfo, sizeof(rinfo));
5630
5631 /*
5632 * Look up the current DFS
5633 * regulatory domain and decide
5634 * which radar pulses to use.
5635 */
5636 switch (dfsdomain) {
5637 case DFS_FCC_DOMAIN:
5638 WMA_LOGI("%s: DFS-FCC domain", __func__);
5639 rinfo.dfsdomain = DFS_FCC_DOMAIN;
5640 rinfo.dfs_radars = dfs_fcc_radars;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305641 rinfo.numradars = QDF_ARRAY_SIZE(dfs_fcc_radars);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005642 rinfo.b5pulses = dfs_fcc_bin5pulses;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305643 rinfo.numb5radars = QDF_ARRAY_SIZE(dfs_fcc_bin5pulses);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005644 break;
5645 case DFS_ETSI_DOMAIN:
5646 WMA_LOGI("%s: DFS-ETSI domain", __func__);
5647 rinfo.dfsdomain = DFS_ETSI_DOMAIN;
5648 rinfo.dfs_radars = dfs_etsi_radars;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305649 rinfo.numradars = QDF_ARRAY_SIZE(dfs_etsi_radars);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005650 rinfo.b5pulses = NULL;
5651 rinfo.numb5radars = 0;
5652 break;
5653 case DFS_MKK4_DOMAIN:
5654 WMA_LOGI("%s: DFS-MKK4 domain", __func__);
5655 rinfo.dfsdomain = DFS_MKK4_DOMAIN;
5656 rinfo.dfs_radars = dfs_mkk4_radars;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305657 rinfo.numradars = QDF_ARRAY_SIZE(dfs_mkk4_radars);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005658 rinfo.b5pulses = dfs_jpn_bin5pulses;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305659 rinfo.numb5radars = QDF_ARRAY_SIZE(dfs_jpn_bin5pulses);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005660 break;
5661 default:
5662 WMA_LOGI("%s: DFS-UNINT domain", __func__);
5663 rinfo.dfsdomain = DFS_UNINIT_DOMAIN;
5664 rinfo.dfs_radars = NULL;
5665 rinfo.numradars = 0;
5666 rinfo.b5pulses = NULL;
5667 rinfo.numb5radars = 0;
5668 break;
5669 }
5670
5671 rinfo.dfs_pri_multiplier = ic->dfs_pri_multiplier;
5672
5673 /*
5674 * Set the regulatory domain,
5675 * radar pulse table and enable
5676 * radar events if required.
5677 * dfs_radar_enable() returns
5678 * 0 on success and non-zero
5679 * failure.
5680 */
5681 radar_enabled_status = dfs_radar_enable(ic, &rinfo);
5682 if (radar_enabled_status != DFS_STATUS_SUCCESS) {
5683 WMA_LOGE("%s[%d]: DFS- Radar Detection Enabling Failed",
5684 __func__, __LINE__);
5685 }
5686}
5687
5688/**
5689 * wma_dfs_configure_channel() - configure DFS channel
5690 * @dfs_ic: ieee80211com ptr
Siddarth Poddar17dc4712016-03-09 16:30:27 +05305691 * @band_center_freq1: center frequency 1
5692 * @band_center_freq2: center frequency 2
5693 * (valid only for 11ac vht 80plus80 mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005694 * @ req: vdev start request
5695 *
5696 * Set the Channel parameters in to DFS module
5697 * Also,configure the DFS radar filters for
5698 * matching the DFS phyerrors.
5699 *
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05305700 * Return: dfs_ieee80211_channel / NULL for error
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005701 */
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05305702struct dfs_ieee80211_channel *wma_dfs_configure_channel(
5703 struct ieee80211com *dfs_ic,
Siddarth Poddar17dc4712016-03-09 16:30:27 +05305704 uint32_t band_center_freq1,
5705 uint32_t band_center_freq2,
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05305706 struct wma_vdev_start_req
5707 *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005708{
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08005709 uint8_t ext_channel;
5710
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005711 if (dfs_ic == NULL) {
5712 WMA_LOGE("%s: DFS ic is Invalid", __func__);
5713 return NULL;
5714 }
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05305715
5716 if (!dfs_ic->ic_curchan) {
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05305717 dfs_ic->ic_curchan = (struct dfs_ieee80211_channel *)os_malloc(
5718 NULL,
5719 sizeof(struct dfs_ieee80211_channel),
5720 GFP_ATOMIC);
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05305721 if (dfs_ic->ic_curchan == NULL) {
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05305722 WMA_LOGE(
5723 "%s: allocation of dfs_ic->ic_curchan failed %zu",
5724 __func__, sizeof(struct dfs_ieee80211_channel));
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05305725 return NULL;
5726 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005727 }
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05305728
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05305729 OS_MEMZERO(dfs_ic->ic_curchan, sizeof(struct dfs_ieee80211_channel));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005730
5731 dfs_ic->ic_curchan->ic_ieee = req->chan;
Siddarth Poddar17dc4712016-03-09 16:30:27 +05305732 dfs_ic->ic_curchan->ic_freq = cds_chan_to_freq(req->chan);
5733 dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg1 = band_center_freq1;
5734 dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg2 = band_center_freq2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005735 dfs_ic->ic_curchan->ic_pri_freq_center_freq_mhz_separation =
5736 dfs_ic->ic_curchan->ic_freq -
5737 dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg1;
5738
5739 if ((dfs_ic->ic_curchan->ic_ieee >= WMA_11A_CHANNEL_BEGIN) &&
5740 (dfs_ic->ic_curchan->ic_ieee <= WMA_11A_CHANNEL_END)) {
5741 dfs_ic->ic_curchan->ic_flags |= IEEE80211_CHAN_5GHZ;
5742 }
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08005743
5744 switch (req->chan_width) {
5745 case CH_WIDTH_20MHZ:
5746 dfs_ic->ic_curchan->ic_flags |=
5747 (req->vht_capable ? IEEE80211_CHAN_VHT20 :
5748 IEEE80211_CHAN_HT20);
5749 break;
5750 case CH_WIDTH_40MHZ:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005751 if (req->chan < req->ch_center_freq_seg0)
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08005752 dfs_ic->ic_curchan->ic_flags |=
5753 (req->vht_capable ?
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005754 IEEE80211_CHAN_VHT40PLUS :
5755 IEEE80211_CHAN_HT40PLUS);
5756 else
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08005757 dfs_ic->ic_curchan->ic_flags |=
5758 (req->vht_capable ?
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005759 IEEE80211_CHAN_VHT40MINUS :
5760 IEEE80211_CHAN_HT40MINUS);
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08005761 break;
5762 case CH_WIDTH_80MHZ:
5763 dfs_ic->ic_curchan->ic_flags |= IEEE80211_CHAN_VHT80;
5764 break;
5765 case CH_WIDTH_80P80MHZ:
Siddarth Poddar17dc4712016-03-09 16:30:27 +05305766 ext_channel = cds_freq_to_chan(band_center_freq2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005767 dfs_ic->ic_curchan->ic_flags |=
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08005768 IEEE80211_CHAN_VHT80P80;
5769 dfs_ic->ic_curchan->ic_freq_ext =
Siddarth Poddar17dc4712016-03-09 16:30:27 +05305770 band_center_freq2;
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08005771 dfs_ic->ic_curchan->ic_ieee_ext = ext_channel;
5772
5773 /* verify both the 80MHz are DFS bands or not */
5774 if ((CHANNEL_STATE_DFS ==
5775 cds_get_bonded_channel_state(req->chan ,
5776 CH_WIDTH_80MHZ)) &&
5777 (CHANNEL_STATE_DFS ==
5778 cds_get_bonded_channel_state(
5779 ext_channel - 6 ,
5780 CH_WIDTH_80MHZ)))
5781 dfs_ic->ic_curchan->ic_80p80_both_dfs = true;
5782 break;
5783 case CH_WIDTH_160MHZ:
5784 dfs_ic->ic_curchan->ic_flags |=
5785 IEEE80211_CHAN_VHT160;
5786 break;
5787 default:
5788 WMA_LOGE(
5789 "%s: Recieved a wrong channel width %d",
5790 __func__, req->chan_width);
5791 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005792 }
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08005793
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005794 dfs_ic->ic_curchan->ic_flagext |= IEEE80211_CHAN_DFS;
5795
5796 if (req->oper_mode == BSS_OPERATIONAL_MODE_AP) {
5797 dfs_ic->ic_opmode = IEEE80211_M_HOSTAP;
5798 dfs_ic->vdev_id = req->vdev_id;
5799 }
5800
5801 dfs_ic->dfs_pri_multiplier = req->dfs_pri_multiplier;
5802
5803 /*
5804 * Configuring the DFS with current channel and the radar filters
5805 */
5806 wma_dfs_configure(dfs_ic);
5807 WMA_LOGI("%s: DFS- CHANNEL CONFIGURED", __func__);
5808 return dfs_ic->ic_curchan;
5809}
5810
5811
5812/**
5813 * wma_set_dfs_region() - set DFS region
5814 * @wma: wma handle
5815 *
5816 * Configure the DFS region for DFS radar filter initialization
5817 *
5818 * Return: none
5819 */
5820void wma_set_dfs_region(tp_wma_handle wma, uint8_t dfs_region)
5821{
5822 /* dfs information is passed */
5823 if (dfs_region > DFS_MKK4_DOMAIN || dfs_region == DFS_UNINIT_DOMAIN)
5824 /* assign DFS_FCC_DOMAIN as default domain*/
5825 wma->dfs_ic->current_dfs_regdomain = DFS_FCC_DOMAIN;
5826 else
5827 wma->dfs_ic->current_dfs_regdomain = dfs_region;
5828
5829 WMA_LOGI("%s: DFS Region Domain: %d", __func__,
5830 wma->dfs_ic->current_dfs_regdomain);
5831}
5832
5833/**
5834 * wma_get_channels() - prepare dfs radar channel list
5835 * @ichan: channel
5836 * @chan_list: return channel list
5837 *
5838 * Return: return number of channels
5839 */
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05305840int wma_get_channels(struct dfs_ieee80211_channel *ichan,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005841 struct wma_dfs_radar_channel_list *chan_list)
5842{
5843 uint8_t center_chan = cds_freq_to_chan(ichan->ic_vhtop_ch_freq_seg1);
5844
5845 chan_list->nchannels = 0;
5846
5847 if (IEEE80211_IS_CHAN_11AC_VHT80(ichan)) {
5848 chan_list->nchannels = 4;
5849 chan_list->channels[0] = center_chan - 6;
5850 chan_list->channels[1] = center_chan - 2;
5851 chan_list->channels[2] = center_chan + 2;
5852 chan_list->channels[3] = center_chan + 6;
5853 } else if (IEEE80211_IS_CHAN_11N_HT40(ichan) ||
5854 IEEE80211_IS_CHAN_11AC_VHT40(ichan)) {
5855 chan_list->nchannels = 2;
5856 chan_list->channels[0] = center_chan - 2;
5857 chan_list->channels[1] = center_chan + 2;
5858 } else {
5859 chan_list->nchannels = 1;
5860 chan_list->channels[0] = center_chan;
5861 }
5862
5863 return chan_list->nchannels;
5864}
5865
5866
5867/**
5868 * wma_dfs_indicate_radar() - Indicate Radar to SAP/HDD
5869 * @ic: ieee80211com ptr
5870 * @ichan: ieee 80211 channel
5871 *
5872 * Return: 0 for success or error code
5873 */
5874int wma_dfs_indicate_radar(struct ieee80211com *ic,
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05305875 struct dfs_ieee80211_channel *ichan)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005876{
5877 tp_wma_handle wma;
5878 void *hdd_ctx;
5879 struct wma_dfs_radar_indication *radar_event;
5880 struct wma_dfs_radar_ind wma_radar_event;
5881 tpAniSirGlobal pmac = NULL;
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05305882 bool indication_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005883
Anurag Chouhan6d760662016-02-20 16:05:43 +05305884 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005885 if (wma == NULL) {
5886 WMA_LOGE("%s: DFS- Invalid wma", __func__);
5887 return -ENOENT;
5888 }
5889
Anurag Chouhan6d760662016-02-20 16:05:43 +05305890 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005891 pmac = (tpAniSirGlobal)
Anurag Chouhan6d760662016-02-20 16:05:43 +05305892 cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005893
5894 if (!pmac) {
5895 WMA_LOGE("%s: Invalid MAC handle", __func__);
5896 return -ENOENT;
5897 }
5898
5899 if (wma->dfs_ic != ic) {
5900 WMA_LOGE("%s:DFS- Invalid WMA handle", __func__);
5901 return -ENOENT;
5902 }
5903 radar_event = (struct wma_dfs_radar_indication *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305904 qdf_mem_malloc(sizeof(struct wma_dfs_radar_indication));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005905 if (radar_event == NULL) {
5906 WMA_LOGE("%s:DFS- Invalid radar_event", __func__);
5907 return -ENOMEM;
5908 }
5909
5910 /*
5911 * Do not post multiple Radar events on the same channel.
5912 * But, when DFS test mode is enabled, allow multiple dfs
5913 * radar events to be posted on the same channel.
5914 */
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305915 qdf_spin_lock_bh(&ic->chan_lock);
Edhar, Mahesh Kumar35d9b2e2015-10-26 17:06:23 +05305916 if (!pmac->sap.SapDfsInfo.disable_dfs_ch_switch)
5917 wma->dfs_ic->disable_phy_err_processing = true;
5918
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005919 if ((ichan->ic_ieee != (wma->dfs_ic->last_radar_found_chan)) ||
5920 (pmac->sap.SapDfsInfo.disable_dfs_ch_switch == true)) {
5921 wma->dfs_ic->last_radar_found_chan = ichan->ic_ieee;
5922 /* Indicate the radar event to HDD to stop the netif Tx queues */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005923 wma_radar_event.chan_freq = ichan->ic_freq;
5924 wma_radar_event.dfs_radar_status = WMA_DFS_RADAR_FOUND;
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05305925 indication_status =
5926 wma->dfs_radar_indication_cb(hdd_ctx, &wma_radar_event);
5927 if (indication_status == false) {
5928 WMA_LOGE("%s:Application triggered channel switch in progress!.. drop radar event indiaction to SAP",
5929 __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305930 qdf_mem_free(radar_event);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305931 qdf_spin_unlock_bh(&ic->chan_lock);
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05305932 return 0;
5933 }
5934
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005935 WMA_LOGE("%s:DFS- RADAR INDICATED TO HDD", __func__);
5936
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05305937 wma_radar_event.ieee_chan_number = ichan->ic_ieee;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005938 /*
5939 * Indicate to the radar event to SAP to
5940 * select a new channel and set CSA IE
5941 */
5942 radar_event->vdev_id = ic->vdev_id;
5943 wma_get_channels(ichan, &radar_event->chan_list);
5944 radar_event->dfs_radar_status = WMA_DFS_RADAR_FOUND;
5945 radar_event->use_nol = ic->ic_dfs_usenol(ic);
5946 wma_send_msg(wma, WMA_DFS_RADAR_IND, (void *)radar_event, 0);
5947 WMA_LOGE("%s:DFS- WMA_DFS_RADAR_IND Message Posted", __func__);
5948 }
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305949 qdf_spin_unlock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005950
5951 return 0;
5952}
5953
5954#ifdef WLAN_FEATURE_MEMDUMP
5955/*
5956 * wma_process_fw_mem_dump_req() - Function to request fw memory dump from
5957 * firmware
5958 * @wma: Pointer to WMA handle
5959 * @mem_dump_req: Pointer for mem_dump_req
5960 *
5961 * This function sends memory dump request to firmware
5962 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305963 * Return: QDF_STATUS_SUCCESS for success otherwise failure
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005964 *
5965 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305966QDF_STATUS wma_process_fw_mem_dump_req(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005967 struct fw_dump_req *mem_dump_req)
5968{
Govind Singhaa64c242016-03-08 11:31:49 +05305969 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005970
5971 if (!mem_dump_req || !wma) {
5972 WMA_LOGE(FL("input pointer is NULL"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305973 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005974 }
5975
Govind Singhaa64c242016-03-08 11:31:49 +05305976 ret = wmi_unified_process_fw_mem_dump_cmd(wma->wmi_handle,
5977 (struct fw_dump_req_param *) mem_dump_req);
5978 if (ret)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305979 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005980
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305981 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005982}
5983
5984/**
5985 * wma_fw_mem_dump_rsp() - send fw mem dump response to SME
5986 *
5987 * @req_id - request id.
5988 * @status - copy status from the firmware.
5989 *
5990 * This function is called by the memory dump response handler to
5991 * indicate SME that firmware dump copy is complete
5992 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305993 * Return: QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005994 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305995static QDF_STATUS wma_fw_mem_dump_rsp(uint32_t req_id, uint32_t status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005996{
5997 struct fw_dump_rsp *dump_rsp;
5998 cds_msg_t sme_msg = {0};
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305999 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006000
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306001 dump_rsp = qdf_mem_malloc(sizeof(*dump_rsp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006002
6003 if (!dump_rsp) {
6004 WMA_LOGE(FL("Memory allocation failed."));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306005 qdf_status = QDF_STATUS_E_NOMEM;
6006 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006007 }
6008
6009 WMA_LOGI(FL("FW memory dump copy complete status: %d for request: %d"),
6010 status, req_id);
6011
6012 dump_rsp->request_id = req_id;
6013 dump_rsp->dump_complete = status;
6014
6015 sme_msg.type = eWNI_SME_FW_DUMP_IND;
6016 sme_msg.bodyptr = dump_rsp;
6017 sme_msg.bodyval = 0;
6018
Anurag Chouhan6d760662016-02-20 16:05:43 +05306019 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306020 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006021 WMA_LOGE(FL("Fail to post fw mem dump ind msg"));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306022 qdf_mem_free(dump_rsp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006023 }
6024
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306025 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006026}
6027
6028/**
6029 * wma_fw_mem_dump_event_handler() - handles fw memory dump event
6030 *
6031 * @handle: pointer to wma handle.
6032 * @cmd_param_info: pointer to TLV info received in the event.
6033 * @len: length of data in @cmd_param_info
6034 *
6035 * This function is a handler for firmware memory dump event.
6036 *
6037 * Return: integer (0 for success and error code otherwise)
6038 */
6039int wma_fw_mem_dump_event_handler(void *handle, u_int8_t *cmd_param_info,
6040 u_int32_t len)
6041{
6042 WMI_UPDATE_FW_MEM_DUMP_EVENTID_param_tlvs *param_buf;
6043 wmi_update_fw_mem_dump_fixed_param *event;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306044 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006045
6046 param_buf =
6047 (WMI_UPDATE_FW_MEM_DUMP_EVENTID_param_tlvs *) cmd_param_info;
6048 if (!param_buf) {
6049 WMA_LOGA("%s: Invalid stats event", __func__);
6050 return -EINVAL;
6051 }
6052
6053 event = param_buf->fixed_param;
6054
6055 status = wma_fw_mem_dump_rsp(event->request_id,
6056 event->fw_mem_dump_complete);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306057 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006058 WMA_LOGE("Error posting FW MEM DUMP RSP.");
6059 return -EINVAL;
6060 }
6061
6062 WMA_LOGI("FW MEM DUMP RSP posted successfully");
6063 return 0;
6064}
6065#endif /* WLAN_FEATURE_MEMDUMP */
6066
6067/*
6068 * wma_process_set_ie_info() - Function to send IE info to firmware
6069 * @wma: Pointer to WMA handle
6070 * @ie_data: Pointer for ie data
6071 *
6072 * This function sends IE information to firmware
6073 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306074 * Return: QDF_STATUS_SUCCESS for success otherwise failure
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006075 *
6076 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306077QDF_STATUS wma_process_set_ie_info(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006078 struct vdev_ie_info *ie_info)
6079{
Govind Singhaa64c242016-03-08 11:31:49 +05306080 struct vdev_ie_info_param cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006081 int ret;
6082
6083 if (!ie_info || !wma) {
6084 WMA_LOGE(FL("input pointer is NULL"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306085 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006086 }
6087
6088 /* Validate the input */
6089 if (ie_info->length <= 0) {
6090 WMA_LOGE(FL("Invalid IE length"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306091 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006092 }
6093
Govind Singhaa64c242016-03-08 11:31:49 +05306094 cmd.vdev_id = ie_info->vdev_id;
6095 cmd.ie_id = ie_info->ie_id;
6096 cmd.length = ie_info->length;
6097 cmd.data = ie_info->data;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006098
Govind Singhaa64c242016-03-08 11:31:49 +05306099 ret = wmi_unified_process_set_ie_info_cmd(wma->wmi_handle,
6100 &cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006101
6102 return ret;
6103}
6104