blob: 447aa417635b33ca97e7faecb0f4684fef8ae9a8 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Ryan Hsuf75bd242015-12-17 12:22:02 -08002 * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/**
29 * DOC: wma_features.c
30 * This file contains different features related functions like WoW,
31 * Offloads, TDLS etc.
32 */
33
34/* Header files */
35
36#include "wma.h"
37#include "wma_api.h"
38#include "cds_api.h"
39#include "wmi_unified_api.h"
40#include "wlan_qct_sys.h"
41#include "wni_api.h"
42#include "ani_global.h"
43#include "wmi_unified.h"
44#include "wni_cfg.h"
45#include "cfg_api.h"
Manjunathappa Prakash3454fd62016-04-01 08:52:06 -070046#include "ol_txrx_ctrl_api.h"
47#include <cdp_txrx_tx_delay.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080048#include "wlan_tgt_def_config.h"
Manjunathappa Prakash3454fd62016-04-01 08:52:06 -070049#include <cdp_txrx_peer_ops.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080050
Nirav Shahcbc6d722016-03-01 16:24:53 +053051#include "qdf_nbuf.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053052#include "qdf_types.h"
Anurag Chouhan600c3a02016-03-01 10:33:54 +053053#include "qdf_mem.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080054#include "ol_txrx_peer_find.h"
55
56#include "wma_types.h"
57#include "lim_api.h"
58#include "lim_session_utils.h"
59
60#include "cds_utils.h"
61
62#if !defined(REMOVE_PKT_LOG)
63#include "pktlog_ac.h"
64#endif /* REMOVE_PKT_LOG */
65
66#include "dbglog_host.h"
67#include "csr_api.h"
68#include "ol_fw.h"
69
70#include "dfs.h"
71#include "radar_filters.h"
72#include "wma_internal.h"
73
74#ifndef ARRAY_LENGTH
75#define ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0]))
76#endif
77
78#define WMA_WOW_STA_WAKE_UP_EVENTS ((1 << WOW_CSA_IE_EVENT) |\
79 (1 << WOW_CLIENT_KICKOUT_EVENT) |\
80 (1 << WOW_PATTERN_MATCH_EVENT) |\
81 (1 << WOW_MAGIC_PKT_RECVD_EVENT) |\
82 (1 << WOW_DEAUTH_RECVD_EVENT) |\
83 (1 << WOW_DISASSOC_RECVD_EVENT) |\
84 (1 << WOW_BMISS_EVENT) |\
85 (1 << WOW_GTK_ERR_EVENT) |\
86 (1 << WOW_BETTER_AP_EVENT) |\
87 (1 << WOW_HTT_EVENT) |\
88 (1 << WOW_RA_MATCH_EVENT) |\
89 (1 << WOW_NLO_DETECTED_EVENT) |\
90 (1 << WOW_EXTSCAN_EVENT))\
91
92#define WMA_WOW_SAP_WAKE_UP_EVENTS ((1 << WOW_PROBE_REQ_WPS_IE_EVENT) |\
93 (1 << WOW_PATTERN_MATCH_EVENT) |\
94 (1 << WOW_AUTH_REQ_EVENT) |\
95 (1 << WOW_ASSOC_REQ_EVENT) |\
96 (1 << WOW_DEAUTH_RECVD_EVENT) |\
97 (1 << WOW_DISASSOC_RECVD_EVENT) |\
98 (1 << WOW_HTT_EVENT))\
99
100static const uint8_t arp_ptrn[] = {0x08, 0x06};
101static const uint8_t arp_mask[] = {0xff, 0xff};
102static const uint8_t ns_ptrn[] = {0x86, 0xDD};
103static const uint8_t discvr_ptrn[] = {0xe0, 0x00, 0x00, 0xf8};
104static const uint8_t discvr_mask[] = {0xf0, 0x00, 0x00, 0xf8};
105
106#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
107/**
108 * wma_post_auto_shutdown_msg() - to post auto shutdown event to sme
109 *
110 * Return: 0 for success or error code
111 */
112static int wma_post_auto_shutdown_msg(void)
113{
114 tSirAutoShutdownEvtParams *auto_sh_evt;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530115 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800116 cds_msg_t sme_msg = { 0 };
117
118 auto_sh_evt = (tSirAutoShutdownEvtParams *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530119 qdf_mem_malloc(sizeof(tSirAutoShutdownEvtParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800120 if (!auto_sh_evt) {
121 WMA_LOGE(FL("No Mem"));
122 return -ENOMEM;
123 }
124
125 auto_sh_evt->shutdown_reason =
126 WMI_HOST_AUTO_SHUTDOWN_REASON_TIMER_EXPIRY;
127 sme_msg.type = eWNI_SME_AUTO_SHUTDOWN_IND;
128 sme_msg.bodyptr = auto_sh_evt;
129 sme_msg.bodyval = 0;
130
Anurag Chouhan6d760662016-02-20 16:05:43 +0530131 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530132 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800133 WMA_LOGE("Fail to post eWNI_SME_AUTO_SHUTDOWN_IND msg to SME");
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530134 qdf_mem_free(auto_sh_evt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800135 return -EINVAL;
136 }
137
138 return 0;
139}
140#endif
141/**
142 * wma_send_snr_request() - send request to fw to get RSSI stats
143 * @wma_handle: wma handle
144 * @pGetRssiReq: get RSSI request
145 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530146 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800147 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530148QDF_STATUS wma_send_snr_request(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800149 void *pGetRssiReq)
150{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800151 tAniGetRssiReq *pRssiBkUp = NULL;
152
153 /* command is in progess */
154 if (NULL != wma_handle->pGetRssiReq)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530155 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800156
157 /* create a copy of csrRssiCallback to send rssi value
158 * after wmi event
159 */
160 if (pGetRssiReq) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530161 pRssiBkUp = qdf_mem_malloc(sizeof(tAniGetRssiReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800162 if (!pRssiBkUp) {
163 WMA_LOGE("Failed to allocate memory for tAniGetRssiReq");
164 wma_handle->pGetRssiReq = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530165 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800166 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530167 qdf_mem_set(pRssiBkUp, sizeof(tAniGetRssiReq), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800168 pRssiBkUp->sessionId =
169 ((tAniGetRssiReq *) pGetRssiReq)->sessionId;
170 pRssiBkUp->rssiCallback =
171 ((tAniGetRssiReq *) pGetRssiReq)->rssiCallback;
172 pRssiBkUp->pDevContext =
173 ((tAniGetRssiReq *) pGetRssiReq)->pDevContext;
174 wma_handle->pGetRssiReq = (void *)pRssiBkUp;
175 }
176
Govind Singhaa64c242016-03-08 11:31:49 +0530177 if (wmi_unified_snr_request_cmd(wma_handle->wmi_handle)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800178 WMA_LOGE("Failed to send host stats request to fw");
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530179 qdf_mem_free(pRssiBkUp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800180 wma_handle->pGetRssiReq = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530181 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800182 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530183 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800184}
185
186/**
187 * wma_get_snr() - get RSSI from fw
188 * @psnr_req: request params
189 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530190 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800191 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530192QDF_STATUS wma_get_snr(tAniGetSnrReq *psnr_req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800193{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800194 tAniGetSnrReq *psnr_req_bkp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800195 tp_wma_handle wma_handle = NULL;
196 struct wma_txrx_node *intr;
197
Anurag Chouhan6d760662016-02-20 16:05:43 +0530198 wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800199
200 if (NULL == wma_handle) {
201 WMA_LOGE("%s : Failed to get wma_handle", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530202 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800203 }
204
205 intr = &wma_handle->interfaces[psnr_req->sessionId];
206 /* command is in progess */
207 if (NULL != intr->psnr_req) {
208 WMA_LOGE("%s : previous snr request is pending", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530209 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800210 }
211
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530212 psnr_req_bkp = qdf_mem_malloc(sizeof(tAniGetSnrReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800213 if (!psnr_req_bkp) {
214 WMA_LOGE("Failed to allocate memory for tAniGetSnrReq");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530215 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800216 }
217
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530218 qdf_mem_set(psnr_req_bkp, sizeof(tAniGetSnrReq), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800219 psnr_req_bkp->staId = psnr_req->staId;
220 psnr_req_bkp->pDevContext = psnr_req->pDevContext;
221 psnr_req_bkp->snrCallback = psnr_req->snrCallback;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800222 intr->psnr_req = (void *)psnr_req_bkp;
Govind Singhaa64c242016-03-08 11:31:49 +0530223
224 if (wmi_unified_snr_cmd(wma_handle->wmi_handle,
225 psnr_req->sessionId)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800226 WMA_LOGE("Failed to send host stats request to fw");
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530227 qdf_mem_free(psnr_req_bkp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800228 intr->psnr_req = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530229 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800230 }
231
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530232 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800233}
234
235/**
236 * wma_process_link_status_req() - process link status request from UMAC
237 * @wma: wma handle
238 * @pGetLinkStatus: get link params
239 *
240 * Return: none
241 */
242void wma_process_link_status_req(tp_wma_handle wma,
243 tAniGetLinkStatus *pGetLinkStatus)
244{
Govind Singhaa64c242016-03-08 11:31:49 +0530245 struct link_status_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800246 struct wma_txrx_node *iface =
247 &wma->interfaces[pGetLinkStatus->sessionId];
248
249 if (iface->plink_status_req) {
250 WMA_LOGE("%s:previous link status request is pending,deleting the new request",
251 __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530252 qdf_mem_free(pGetLinkStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800253 return;
254 }
255
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800256 iface->plink_status_req = pGetLinkStatus;
Govind Singhaa64c242016-03-08 11:31:49 +0530257 cmd.session_id = pGetLinkStatus->sessionId;
258 if (wmi_unified_link_status_req_cmd(wma->wmi_handle, &cmd)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800259 WMA_LOGE("Failed to send WMI link status request to fw");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800260 iface->plink_status_req = NULL;
261 goto end;
262 }
263
264 return;
265
266end:
267 wma_post_link_status(pGetLinkStatus, LINK_STATUS_LEGACY);
268}
269
270#ifdef FEATURE_WLAN_LPHB
271/**
272 * wma_lphb_conf_hbenable() - enable command of LPHB configuration requests
273 * @wma_handle: WMA handle
274 * @lphb_conf_req: configuration info
275 * @by_user: whether this call is from user or cached resent
276 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530277 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800278 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530279QDF_STATUS wma_lphb_conf_hbenable(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800280 tSirLPHBReq *lphb_conf_req, bool by_user)
281{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530282 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800283 int status = 0;
284 tSirLPHBEnableStruct *ts_lphb_enable;
Govind Singhaa64c242016-03-08 11:31:49 +0530285 wmi_hb_set_enable_cmd_fixed_param hb_enable_fp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800286 int i;
287
288 if (lphb_conf_req == NULL) {
289 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530290 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800291 }
292
293 ts_lphb_enable = &(lphb_conf_req->params.lphbEnableReq);
294 WMA_LOGI("%s: WMA --> WMI_HB_SET_ENABLE enable=%d, item=%d, session=%d",
295 __func__,
296 ts_lphb_enable->enable,
297 ts_lphb_enable->item, ts_lphb_enable->session);
298
299 if ((ts_lphb_enable->item != 1) && (ts_lphb_enable->item != 2)) {
300 WMA_LOGE("%s : LPHB configuration wrong item %d",
301 __func__, ts_lphb_enable->item);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530302 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800303 }
304
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800305
306 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530307 hb_enable_fp.vdev_id = ts_lphb_enable->session;
308 hb_enable_fp.enable = ts_lphb_enable->enable;
309 hb_enable_fp.item = ts_lphb_enable->item;
310 hb_enable_fp.session = ts_lphb_enable->session;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800311
Govind Singhaa64c242016-03-08 11:31:49 +0530312 status = wmi_unified_lphb_config_hbenable_cmd(wma_handle->wmi_handle,
313 &hb_enable_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800314 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530315 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800316 goto error;
317 }
318
319 if (by_user) {
320 /* target already configured, now cache command status */
321 if (ts_lphb_enable->enable) {
322 i = ts_lphb_enable->item - 1;
323 wma_handle->wow.lphb_cache[i].cmd
324 = LPHB_SET_EN_PARAMS_INDID;
325 wma_handle->wow.lphb_cache[i].params.lphbEnableReq.
326 enable = ts_lphb_enable->enable;
327 wma_handle->wow.lphb_cache[i].params.lphbEnableReq.
328 item = ts_lphb_enable->item;
329 wma_handle->wow.lphb_cache[i].params.lphbEnableReq.
330 session = ts_lphb_enable->session;
331
332 WMA_LOGI("%s: cached LPHB status in WMA context for item %d",
333 __func__, i);
334 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530335 qdf_mem_zero((void *)&wma_handle->wow.lphb_cache,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800336 sizeof(wma_handle->wow.lphb_cache));
337 WMA_LOGI("%s: cleared all cached LPHB status in WMA context",
338 __func__);
339 }
340 }
341
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530342 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800343error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530344 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800345}
346
347/**
348 * wma_lphb_conf_tcp_params() - set tcp params of LPHB configuration requests
349 * @wma_handle: wma handle
350 * @lphb_conf_req: lphb config request
351 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530352 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800353 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530354QDF_STATUS wma_lphb_conf_tcp_params(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800355 tSirLPHBReq *lphb_conf_req)
356{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530357 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800358 int status = 0;
359 tSirLPHBTcpParamStruct *ts_lphb_tcp_param;
Govind Singhaa64c242016-03-08 11:31:49 +0530360 wmi_hb_set_tcp_params_cmd_fixed_param hb_tcp_params_fp = {0};
361
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800362
363 if (lphb_conf_req == NULL) {
364 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530365 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800366 }
367
368 ts_lphb_tcp_param = &(lphb_conf_req->params.lphbTcpParamReq);
Srinivas Girigowda9dc32cf2015-11-19 14:47:04 -0800369 WMA_LOGI("%s: WMA --> WMI_HB_SET_TCP_PARAMS srv_ip=%08x, "
370 "dev_ip=%08x, src_port=%d, dst_port=%d, timeout=%d, "
371 "session=%d, gateway_mac="MAC_ADDRESS_STR", timePeriodSec=%d, "
372 "tcpSn=%d", __func__, ts_lphb_tcp_param->srv_ip,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800373 ts_lphb_tcp_param->dev_ip, ts_lphb_tcp_param->src_port,
374 ts_lphb_tcp_param->dst_port, ts_lphb_tcp_param->timeout,
Srinivas Girigowda9dc32cf2015-11-19 14:47:04 -0800375 ts_lphb_tcp_param->session,
376 MAC_ADDR_ARRAY(ts_lphb_tcp_param->gateway_mac.bytes),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800377 ts_lphb_tcp_param->timePeriodSec, ts_lphb_tcp_param->tcpSn);
378
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800379 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530380 hb_tcp_params_fp.vdev_id = ts_lphb_tcp_param->session;
381 hb_tcp_params_fp.srv_ip = ts_lphb_tcp_param->srv_ip;
382 hb_tcp_params_fp.dev_ip = ts_lphb_tcp_param->dev_ip;
383 hb_tcp_params_fp.seq = ts_lphb_tcp_param->tcpSn;
384 hb_tcp_params_fp.src_port = ts_lphb_tcp_param->src_port;
385 hb_tcp_params_fp.dst_port = ts_lphb_tcp_param->dst_port;
386 hb_tcp_params_fp.interval = ts_lphb_tcp_param->timePeriodSec;
387 hb_tcp_params_fp.timeout = ts_lphb_tcp_param->timeout;
388 hb_tcp_params_fp.session = ts_lphb_tcp_param->session;
Srinivas Girigowda9dc32cf2015-11-19 14:47:04 -0800389 WMI_CHAR_ARRAY_TO_MAC_ADDR(ts_lphb_tcp_param->gateway_mac.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +0530390 &hb_tcp_params_fp.gateway_mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800391
Govind Singhaa64c242016-03-08 11:31:49 +0530392 status = wmi_unified_lphb_config_tcp_params_cmd(wma_handle->wmi_handle,
393 &hb_tcp_params_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800394 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530395 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800396 goto error;
397 }
398
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530399 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800400error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530401 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800402}
403
404/**
405 * wma_lphb_conf_tcp_pkt_filter() - configure tcp packet filter command of LPHB
406 * @wma_handle: wma handle
407 * @lphb_conf_req: lphb config request
408 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530409 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800410 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530411QDF_STATUS wma_lphb_conf_tcp_pkt_filter(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800412 tSirLPHBReq *lphb_conf_req)
413{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530414 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800415 int status = 0;
416 tSirLPHBTcpFilterStruct *ts_lphb_tcp_filter;
Govind Singhaa64c242016-03-08 11:31:49 +0530417 wmi_hb_set_tcp_pkt_filter_cmd_fixed_param hb_tcp_filter_fp = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800418
419 if (lphb_conf_req == NULL) {
420 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530421 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800422 }
423
424 ts_lphb_tcp_filter = &(lphb_conf_req->params.lphbTcpFilterReq);
425 WMA_LOGI("%s: WMA --> WMI_HB_SET_TCP_PKT_FILTER length=%d, offset=%d, session=%d, "
426 "filter=%2x:%2x:%2x:%2x:%2x:%2x ...", __func__,
427 ts_lphb_tcp_filter->length, ts_lphb_tcp_filter->offset,
428 ts_lphb_tcp_filter->session, ts_lphb_tcp_filter->filter[0],
429 ts_lphb_tcp_filter->filter[1], ts_lphb_tcp_filter->filter[2],
430 ts_lphb_tcp_filter->filter[3], ts_lphb_tcp_filter->filter[4],
431 ts_lphb_tcp_filter->filter[5]);
432
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800433 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530434 hb_tcp_filter_fp.vdev_id = ts_lphb_tcp_filter->session;
435 hb_tcp_filter_fp.length = ts_lphb_tcp_filter->length;
436 hb_tcp_filter_fp.offset = ts_lphb_tcp_filter->offset;
437 hb_tcp_filter_fp.session = ts_lphb_tcp_filter->session;
438 memcpy((void *)&hb_tcp_filter_fp.filter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800439 (void *)&ts_lphb_tcp_filter->filter,
440 WMI_WLAN_HB_MAX_FILTER_SIZE);
441
Govind Singhaa64c242016-03-08 11:31:49 +0530442 status = wmi_unified_lphb_config_tcp_pkt_filter_cmd(wma_handle->wmi_handle,
443 &hb_tcp_filter_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800444 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530445 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800446 goto error;
447 }
448
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530449 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800450error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530451 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800452}
453
454/**
455 * wma_lphb_conf_udp_params() - configure udp param command of LPHB
456 * @wma_handle: wma handle
457 * @lphb_conf_req: lphb config request
458 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530459 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800460 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530461QDF_STATUS wma_lphb_conf_udp_params(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800462 tSirLPHBReq *lphb_conf_req)
463{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530464 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800465 int status = 0;
466 tSirLPHBUdpParamStruct *ts_lphb_udp_param;
Govind Singhaa64c242016-03-08 11:31:49 +0530467 wmi_hb_set_udp_params_cmd_fixed_param hb_udp_params_fp = {0};
468
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800469
470 if (lphb_conf_req == NULL) {
471 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530472 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800473 }
474
475 ts_lphb_udp_param = &(lphb_conf_req->params.lphbUdpParamReq);
476 WMA_LOGI("%s: WMA --> WMI_HB_SET_UDP_PARAMS srv_ip=%d, dev_ip=%d, src_port=%d, "
477 "dst_port=%d, interval=%d, timeout=%d, session=%d, "
Srinivas Girigowda9eddfda2015-11-19 14:38:02 -0800478 "gateway_mac="MAC_ADDRESS_STR, __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800479 ts_lphb_udp_param->srv_ip, ts_lphb_udp_param->dev_ip,
480 ts_lphb_udp_param->src_port, ts_lphb_udp_param->dst_port,
481 ts_lphb_udp_param->interval, ts_lphb_udp_param->timeout,
Srinivas Girigowda9eddfda2015-11-19 14:38:02 -0800482 ts_lphb_udp_param->session,
483 MAC_ADDR_ARRAY(ts_lphb_udp_param->gateway_mac.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800484
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800485
486 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530487 hb_udp_params_fp.vdev_id = ts_lphb_udp_param->session;
488 hb_udp_params_fp.srv_ip = ts_lphb_udp_param->srv_ip;
489 hb_udp_params_fp.dev_ip = ts_lphb_udp_param->dev_ip;
490 hb_udp_params_fp.src_port = ts_lphb_udp_param->src_port;
491 hb_udp_params_fp.dst_port = ts_lphb_udp_param->dst_port;
492 hb_udp_params_fp.interval = ts_lphb_udp_param->interval;
493 hb_udp_params_fp.timeout = ts_lphb_udp_param->timeout;
494 hb_udp_params_fp.session = ts_lphb_udp_param->session;
Srinivas Girigowda9eddfda2015-11-19 14:38:02 -0800495 WMI_CHAR_ARRAY_TO_MAC_ADDR(ts_lphb_udp_param->gateway_mac.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +0530496 &hb_udp_params_fp.gateway_mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800497
Govind Singhaa64c242016-03-08 11:31:49 +0530498 status = wmi_unified_lphb_config_udp_params_cmd(wma_handle->wmi_handle,
499 &hb_udp_params_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800500 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530501 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800502 goto error;
503 }
504
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530505 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800506error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530507 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800508}
509
510/**
511 * wma_lphb_conf_udp_pkt_filter() - configure udp pkt filter command of LPHB
512 * @wma_handle: wma handle
513 * @lphb_conf_req: lphb config request
514 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530515 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800516 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530517QDF_STATUS wma_lphb_conf_udp_pkt_filter(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800518 tSirLPHBReq *lphb_conf_req)
519{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530520 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800521 int status = 0;
522 tSirLPHBUdpFilterStruct *ts_lphb_udp_filter;
Govind Singhaa64c242016-03-08 11:31:49 +0530523 wmi_hb_set_udp_pkt_filter_cmd_fixed_param hb_udp_filter_fp = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800524
525 if (lphb_conf_req == NULL) {
526 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530527 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800528 }
529
530 ts_lphb_udp_filter = &(lphb_conf_req->params.lphbUdpFilterReq);
531 WMA_LOGI("%s: WMA --> WMI_HB_SET_UDP_PKT_FILTER length=%d, offset=%d, session=%d, "
532 "filter=%2x:%2x:%2x:%2x:%2x:%2x ...", __func__,
533 ts_lphb_udp_filter->length, ts_lphb_udp_filter->offset,
534 ts_lphb_udp_filter->session, ts_lphb_udp_filter->filter[0],
535 ts_lphb_udp_filter->filter[1], ts_lphb_udp_filter->filter[2],
536 ts_lphb_udp_filter->filter[3], ts_lphb_udp_filter->filter[4],
537 ts_lphb_udp_filter->filter[5]);
538
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800539
540 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530541 hb_udp_filter_fp.vdev_id = ts_lphb_udp_filter->session;
542 hb_udp_filter_fp.length = ts_lphb_udp_filter->length;
543 hb_udp_filter_fp.offset = ts_lphb_udp_filter->offset;
544 hb_udp_filter_fp.session = ts_lphb_udp_filter->session;
545 memcpy((void *)&hb_udp_filter_fp.filter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800546 (void *)&ts_lphb_udp_filter->filter,
547 WMI_WLAN_HB_MAX_FILTER_SIZE);
548
Govind Singhaa64c242016-03-08 11:31:49 +0530549 status = wmi_unified_lphb_config_udp_pkt_filter_cmd(wma_handle->wmi_handle,
550 &hb_udp_filter_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800551 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530552 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800553 goto error;
554 }
555
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530556 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800557error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530558 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800559}
560
561/**
562 * wma_process_lphb_conf_req() - handle LPHB configuration requests
563 * @wma_handle: wma handle
564 * @lphb_conf_req: lphb config request
565 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530566 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800567 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530568QDF_STATUS wma_process_lphb_conf_req(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800569 tSirLPHBReq *lphb_conf_req)
570{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530571 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800572
573 if (lphb_conf_req == NULL) {
574 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530575 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800576 }
577
578 WMA_LOGI("%s : LPHB configuration cmd id is %d", __func__,
579 lphb_conf_req->cmd);
580 switch (lphb_conf_req->cmd) {
581 case LPHB_SET_EN_PARAMS_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530582 qdf_status = wma_lphb_conf_hbenable(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800583 lphb_conf_req, true);
584 break;
585
586 case LPHB_SET_TCP_PARAMS_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530587 qdf_status = wma_lphb_conf_tcp_params(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800588 lphb_conf_req);
589 break;
590
591 case LPHB_SET_TCP_PKT_FILTER_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530592 qdf_status = wma_lphb_conf_tcp_pkt_filter(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800593 lphb_conf_req);
594 break;
595
596 case LPHB_SET_UDP_PARAMS_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530597 qdf_status = wma_lphb_conf_udp_params(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800598 lphb_conf_req);
599 break;
600
601 case LPHB_SET_UDP_PKT_FILTER_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530602 qdf_status = wma_lphb_conf_udp_pkt_filter(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800603 lphb_conf_req);
604 break;
605
606 case LPHB_SET_NETWORK_INFO_INDID:
607 default:
608 break;
609 }
610
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530611 qdf_mem_free(lphb_conf_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530612 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800613}
614#endif /* FEATURE_WLAN_LPHB */
615
616/**
617 * wma_process_dhcp_ind() - process dhcp indication from SME
618 * @wma_handle: wma handle
619 * @ta_dhcp_ind: DHCP indication
620 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530621 * Return: QDF Status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800622 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530623QDF_STATUS wma_process_dhcp_ind(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800624 tAniDHCPInd *ta_dhcp_ind)
625{
626 uint8_t vdev_id;
627 int status = 0;
Govind Singhaa64c242016-03-08 11:31:49 +0530628 wmi_peer_set_param_cmd_fixed_param peer_set_param_fp = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800629
630 if (!ta_dhcp_ind) {
631 WMA_LOGE("%s : DHCP indication is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530632 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800633 }
634
Srinivas Girigowda296105a2015-09-24 16:31:16 -0700635 if (!wma_find_vdev_by_addr(wma_handle,
636 ta_dhcp_ind->adapterMacAddr.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800637 &vdev_id)) {
638 WMA_LOGE("%s: Failed to find vdev id for DHCP indication",
639 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530640 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800641 }
642
643 WMA_LOGI("%s: WMA --> WMI_PEER_SET_PARAM triggered by DHCP, "
644 "msgType=%s,"
645 "device_mode=%d, macAddr=" MAC_ADDRESS_STR,
646 __func__,
647 ta_dhcp_ind->msgType == WMA_DHCP_START_IND ?
648 "WMA_DHCP_START_IND" : "WMA_DHCP_STOP_IND",
649 ta_dhcp_ind->device_mode,
Srinivas Girigowda296105a2015-09-24 16:31:16 -0700650 MAC_ADDR_ARRAY(ta_dhcp_ind->peerMacAddr.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800651
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800652 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530653 peer_set_param_fp.vdev_id = vdev_id;
654 peer_set_param_fp.param_id = WMI_PEER_CRIT_PROTO_HINT_ENABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800655 if (WMA_DHCP_START_IND == ta_dhcp_ind->msgType)
Govind Singhaa64c242016-03-08 11:31:49 +0530656 peer_set_param_fp.param_value = 1;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800657 else
Govind Singhaa64c242016-03-08 11:31:49 +0530658 peer_set_param_fp.param_value = 0;
Srinivas Girigowda296105a2015-09-24 16:31:16 -0700659 WMI_CHAR_ARRAY_TO_MAC_ADDR(ta_dhcp_ind->peerMacAddr.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +0530660 &peer_set_param_fp.peer_macaddr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800661
Govind Singhaa64c242016-03-08 11:31:49 +0530662 status = wmi_unified_process_dhcp_ind(wma_handle->wmi_handle,
663 &peer_set_param_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800664 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530665 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800666 }
667
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530668 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800669}
670
671/**
672 * wma_chan_to_mode() - convert channel to phy mode
673 * @chan: channel number
674 * @chan_width: channel width
675 * @vht_capable: vht capable
676 * @dot11_mode: 802.11 mode
677 *
678 * Return: return phy mode
679 */
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800680WLAN_PHY_MODE wma_chan_to_mode(u8 chan, enum phy_ch_width chan_width,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800681 u8 vht_capable, u8 dot11_mode)
682{
683 WLAN_PHY_MODE phymode = MODE_UNKNOWN;
684
685 /* 2.4 GHz band */
686 if ((chan >= WMA_11G_CHANNEL_BEGIN) && (chan <= WMA_11G_CHANNEL_END)) {
687 switch (chan_width) {
688 case CH_WIDTH_20MHZ:
689 /* In case of no channel bonding, use dot11_mode
690 * to set phy mode
691 */
692 switch (dot11_mode) {
693 case WNI_CFG_DOT11_MODE_11A:
694 phymode = MODE_11A;
695 break;
696 case WNI_CFG_DOT11_MODE_11B:
697 phymode = MODE_11B;
698 break;
699 case WNI_CFG_DOT11_MODE_11G:
700 phymode = MODE_11G;
701 break;
702 case WNI_CFG_DOT11_MODE_11G_ONLY:
703 phymode = MODE_11GONLY;
704 break;
705 default:
706 /* Configure MODE_11NG_HT20 for
707 * self vdev(for vht too)
708 */
709 phymode = MODE_11NG_HT20;
710 break;
711 }
712 break;
713 case CH_WIDTH_40MHZ:
714 phymode = vht_capable ? MODE_11AC_VHT40 :
715 MODE_11NG_HT40;
716 break;
717 default:
718 break;
719 }
720 }
721
722 /* 5 GHz band */
723 if ((chan >= WMA_11A_CHANNEL_BEGIN) && (chan <= WMA_11A_CHANNEL_END)) {
724 switch (chan_width) {
725 case CH_WIDTH_20MHZ:
726 phymode = vht_capable ? MODE_11AC_VHT20 :
727 MODE_11NA_HT20;
728 break;
729 case CH_WIDTH_40MHZ:
730 phymode = vht_capable ? MODE_11AC_VHT40 :
731 MODE_11NA_HT40;
732 break;
733 case CH_WIDTH_80MHZ:
734 phymode = MODE_11AC_VHT80;
735 break;
736#if CONFIG_160MHZ_SUPPORT != 0
737 case CH_WIDTH_160MHZ:
738 phymode = MODE_11AC_VHT160;
739 break;
740 case CH_WIDTH_80P80MHZ:
741 phymode = MODE_11AC_VHT80_80;
742 break;
743#endif
744
745 default:
746 break;
747 }
748 }
749
750 /* 5.9 GHz Band */
751 if ((chan >= WMA_11P_CHANNEL_BEGIN) && (chan <= WMA_11P_CHANNEL_END))
752 /* Only Legacy Modulation Schemes are supported */
753 phymode = MODE_11A;
754
755 WMA_LOGD("%s: phymode %d channel %d ch_width %d vht_capable %d "
756 "dot11_mode %d", __func__, phymode, chan,
757 chan_width, vht_capable, dot11_mode);
758
759 return phymode;
760}
761
762/**
763 * wma_get_link_speed() -send command to get linkspeed
764 * @handle: wma handle
765 * @pLinkSpeed: link speed info
766 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530767 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800768 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530769QDF_STATUS wma_get_link_speed(WMA_HANDLE handle, tSirLinkSpeedInfo *pLinkSpeed)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800770{
771 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhaa64c242016-03-08 11:31:49 +0530772 wmi_mac_addr peer_macaddr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800773
774 if (!wma_handle || !wma_handle->wmi_handle) {
775 WMA_LOGE("%s: WMA is closed, can not issue get link speed cmd",
776 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530777 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800778 }
779 if (!WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap,
780 WMI_SERVICE_ESTIMATE_LINKSPEED)) {
781 WMA_LOGE("%s: Linkspeed feature bit not enabled"
782 " Sending value 0 as link speed.", __func__);
783 wma_send_link_speed(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530784 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800785 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800786
787 /* Copy the peer macaddress to the wma buffer */
Srinivas Girigowdadccab9a2015-11-19 14:31:14 -0800788 WMI_CHAR_ARRAY_TO_MAC_ADDR(pLinkSpeed->peer_macaddr.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +0530789 &peer_macaddr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800790
791 WMA_LOGD("%s: pLinkSpeed->peerMacAddr: %pM, "
792 "peer_macaddr.mac_addr31to0: 0x%x, peer_macaddr.mac_addr47to32: 0x%x",
Srinivas Girigowdadccab9a2015-11-19 14:31:14 -0800793 __func__, pLinkSpeed->peer_macaddr.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +0530794 peer_macaddr.mac_addr31to0,
795 peer_macaddr.mac_addr47to32);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800796
Govind Singhaa64c242016-03-08 11:31:49 +0530797 if (wmi_unified_get_link_speed_cmd(wma_handle->wmi_handle,
798 peer_macaddr)) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530799 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800800 }
Govind Singhaa64c242016-03-08 11:31:49 +0530801
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530802 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800803}
804
Gupta, Kapil4cb1d7d2016-04-16 18:16:25 -0700805/**
806* wma_add_beacon_filter() - Issue WMI command to set beacon filter
807* @wma: wma handler
808* @filter_params: beacon_filter_param to set
809*
810* Return: Return QDF_STATUS
811*/
812QDF_STATUS wma_add_beacon_filter(WMA_HANDLE handle,
813 struct beacon_filter_param *filter_params)
814{
815 int i;
816 wmi_buf_t wmi_buf;
817 u_int8_t *buf;
818 A_UINT32 *ie_map;
819 int ret;
820 tp_wma_handle wma = (tp_wma_handle) handle;
821 wmi_add_bcn_filter_cmd_fixed_param *cmd;
822 int len = sizeof(wmi_add_bcn_filter_cmd_fixed_param);
823
824 len += WMI_TLV_HDR_SIZE;
825 len += BCN_FLT_MAX_ELEMS_IE_LIST*sizeof(A_UINT32);
826
827 if (!wma || !wma->wmi_handle) {
828 WMA_LOGE("%s: WMA is closed, can not issue set beacon filter",
829 __func__);
830 return QDF_STATUS_E_INVAL;
831 }
832
833 wmi_buf = wmi_buf_alloc(wma->wmi_handle, len);
834 if (!wmi_buf) {
835 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
836 return QDF_STATUS_E_NOMEM;
837 }
838
839 buf = (u_int8_t *) wmi_buf_data(wmi_buf);
840
841 cmd = (wmi_add_bcn_filter_cmd_fixed_param *)wmi_buf_data(wmi_buf);
842 cmd->vdev_id = filter_params->vdev_id;
843
844 WMITLV_SET_HDR(&cmd->tlv_header,
845 WMITLV_TAG_STRUC_wmi_add_bcn_filter_cmd_fixed_param,
846 WMITLV_GET_STRUCT_TLVLEN(
847 wmi_add_bcn_filter_cmd_fixed_param));
848
849 buf += sizeof(wmi_add_bcn_filter_cmd_fixed_param);
850
851 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_UINT32,
852 (BCN_FLT_MAX_ELEMS_IE_LIST * sizeof(u_int32_t)));
853
854 ie_map = (A_UINT32 *)(buf + WMI_TLV_HDR_SIZE);
855 for (i = 0; i < BCN_FLT_MAX_ELEMS_IE_LIST; i++) {
856 ie_map[i] = filter_params->ie_map[i];
857 WMA_LOGD("beacon filter ie map = %u", ie_map[i]);
858 }
859
860 ret = wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len,
861 WMI_ADD_BCN_FILTER_CMDID);
862 if (ret) {
863 WMA_LOGE("Failed to send wmi add beacon filter = %d",
864 ret);
865 wmi_buf_free(wmi_buf);
866 return QDF_STATUS_E_FAILURE;
867 }
868 WMA_LOGD("added beacon filter = %d", ret);
869
870 return QDF_STATUS_SUCCESS;
871}
872
873/**
874* wma_remove_beacon_filter() - Issue WMI command to remove beacon filter
875* @wma: wma handler
876* @filter_params: beacon_filter_params
877*
878* Return: Return QDF_STATUS
879*/
880QDF_STATUS wma_remove_beacon_filter(WMA_HANDLE handle,
881 struct beacon_filter_param *filter_params)
882{
883 wmi_buf_t buf;
884 tp_wma_handle wma = (tp_wma_handle) handle;
885 wmi_rmv_bcn_filter_cmd_fixed_param *cmd;
886 int len = sizeof(wmi_rmv_bcn_filter_cmd_fixed_param);
887 int ret;
888
889 if (!wma || !wma->wmi_handle) {
890 WMA_LOGE("%s: WMA is closed, cannot issue remove beacon filter",
891 __func__);
892 return QDF_STATUS_E_INVAL;
893 }
894
895 buf = wmi_buf_alloc(wma->wmi_handle, len);
896 if (!buf) {
897 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
898 return QDF_STATUS_E_NOMEM;
899 }
900 cmd = (wmi_rmv_bcn_filter_cmd_fixed_param *)wmi_buf_data(buf);
901 cmd->vdev_id = filter_params->vdev_id;
902
903 WMITLV_SET_HDR(&cmd->tlv_header,
904 WMITLV_TAG_STRUC_wmi_rmv_bcn_filter_cmd_fixed_param,
905 WMITLV_GET_STRUCT_TLVLEN(
906 wmi_rmv_bcn_filter_cmd_fixed_param));
907
908 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
909 WMI_RMV_BCN_FILTER_CMDID);
910 if (ret) {
911 WMA_LOGE("Failed to send wmi remove beacon filter = %d",
912 ret);
913 wmi_buf_free(buf);
914 return QDF_STATUS_E_FAILURE;
915 }
916 WMA_LOGD("removed beacon filter = %d", ret);
917
918 return QDF_STATUS_SUCCESS;
919}
920
921
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800922#ifdef FEATURE_GREEN_AP
923
924/**
Ryan Hsu3c8f79f2015-12-02 16:45:09 -0800925 * wma_egap_info_status_event() - egap info status event
926 * @handle: pointer to wma handler
927 * @event: pointer to event
928 * @len: len of the event
929 *
930 * Return: 0 for success, otherwise appropriate error code
931 */
932static int wma_egap_info_status_event(void *handle, u_int8_t *event,
933 uint32_t len)
934{
935 WMI_TX_PAUSE_EVENTID_param_tlvs *param_buf;
936 wmi_ap_ps_egap_info_event_fixed_param *egap_info_event;
937 wmi_ap_ps_egap_info_chainmask_list *chainmask_event;
938 u_int8_t *buf_ptr;
939
940 param_buf = (WMI_TX_PAUSE_EVENTID_param_tlvs *)event;
941 if (!param_buf) {
942 WMA_LOGE("Invalid EGAP Info status event buffer");
943 return -EINVAL;
944 }
945
946 egap_info_event = (wmi_ap_ps_egap_info_event_fixed_param *)
947 param_buf->fixed_param;
948 buf_ptr = (uint8_t *)egap_info_event;
949 buf_ptr += sizeof(wmi_ap_ps_egap_info_event_fixed_param);
950 chainmask_event = (wmi_ap_ps_egap_info_chainmask_list *)buf_ptr;
951
952 WMA_LOGI("mac_id: %d, status: %d, tx_mask: %x, rx_mask: %d",
953 chainmask_event->mac_id,
954 egap_info_event->status,
955 chainmask_event->tx_chainmask,
956 chainmask_event->rx_chainmask);
957 return 0;
958}
959
960/**
961 * wma_send_egap_conf_params() - send wmi cmd of egap configuration params
962 * @wma_handle: wma handler
963 * @egap_params: pointer to egap_params
964 *
965 * Return: 0 for success, otherwise appropriate error code
966 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530967QDF_STATUS wma_send_egap_conf_params(WMA_HANDLE handle,
Ryan Hsu3c8f79f2015-12-02 16:45:09 -0800968 struct egap_conf_params *egap_params)
969{
970 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhaa64c242016-03-08 11:31:49 +0530971 wmi_ap_ps_egap_param_cmd_fixed_param cmd = {0};
Ryan Hsu3c8f79f2015-12-02 16:45:09 -0800972 int32_t err;
973
Govind Singhaa64c242016-03-08 11:31:49 +0530974 cmd.enable = egap_params->enable;
975 cmd.inactivity_time = egap_params->inactivity_time;
976 cmd.wait_time = egap_params->wait_time;
977 cmd.flags = egap_params->flags;
978 err = wmi_unified_egap_conf_params_cmd(wma_handle->wmi_handle, &cmd);
Ryan Hsu3c8f79f2015-12-02 16:45:09 -0800979 if (err) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530980 return QDF_STATUS_E_FAILURE;
Ryan Hsu3c8f79f2015-12-02 16:45:09 -0800981 }
Govind Singhaa64c242016-03-08 11:31:49 +0530982
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530983 return QDF_STATUS_SUCCESS;
Ryan Hsu3c8f79f2015-12-02 16:45:09 -0800984}
985
986/**
987 * wma_setup_egap_support() - setup the EGAP support flag
988 * @tgt_cfg: pointer to hdd target configuration
989 * @egap_support: EGAP support flag
990 *
991 * Return: None
992 */
993void wma_setup_egap_support(struct wma_tgt_cfg *tgt_cfg, WMA_HANDLE handle)
994{
995 tp_wma_handle wma_handle = (tp_wma_handle) handle;
996
997 if (tgt_cfg && wma_handle)
998 tgt_cfg->egap_support = wma_handle->egap_support;
999}
1000
1001/**
1002 * wma_register_egap_event_handle() - register the EGAP event handle
1003 * @wma_handle: wma handler
1004 *
1005 * Return: None
1006 */
1007void wma_register_egap_event_handle(WMA_HANDLE handle)
1008{
1009 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhd76a5b02016-03-08 15:12:14 +05301010 QDF_STATUS status;
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001011
1012 if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap,
1013 WMI_SERVICE_EGAP)) {
1014 status = wmi_unified_register_event_handler(
1015 wma_handle->wmi_handle,
1016 WMI_AP_PS_EGAP_INFO_EVENTID,
Govind Singhd76a5b02016-03-08 15:12:14 +05301017 wma_egap_info_status_event,
1018 WMA_RX_SERIALIZER_CTX);
1019 if (QDF_IS_STATUS_ERROR(status)) {
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001020 WMA_LOGE("Failed to register Enhance Green AP event");
1021 wma_handle->egap_support = false;
1022 } else {
1023 WMA_LOGI("Set the Enhance Green AP event handler");
1024 wma_handle->egap_support = true;
1025 }
1026 } else
1027 wma_handle->egap_support = false;
1028}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001029#endif /* FEATURE_GREEN_AP */
1030
Govind Singha471e5e2015-10-12 17:11:14 +05301031/**
Govind Singhaa64c242016-03-08 11:31:49 +05301032 * wma_unified_fw_profiling_cmd() - send FW profiling cmd to WLAN FW
Govind Singha471e5e2015-10-12 17:11:14 +05301033 * @wma: wma handle
1034 * @cmd: Profiling command index
1035 * @value1: parameter1 value
1036 * @value2: parameter2 value
1037 *
1038 * Return: 0 for success else error code
1039 */
Govind Singhaa64c242016-03-08 11:31:49 +05301040QDF_STATUS wma_unified_fw_profiling_cmd(wmi_unified_t wmi_handle,
Govind Singha471e5e2015-10-12 17:11:14 +05301041 uint32_t cmd, uint32_t value1, uint32_t value2)
1042{
Govind Singha471e5e2015-10-12 17:11:14 +05301043 int ret;
Govind Singha471e5e2015-10-12 17:11:14 +05301044
Govind Singhaa64c242016-03-08 11:31:49 +05301045 ret = wmi_unified_fw_profiling_data_cmd(wmi_handle, cmd,
1046 value1, value2);
1047 if (ret) {
1048 WMA_LOGE("enable cmd Failed for id %d value %d",
1049 value1, value2);
1050 return ret;
Govind Singha471e5e2015-10-12 17:11:14 +05301051 }
1052
Govind Singhaa64c242016-03-08 11:31:49 +05301053 return QDF_STATUS_SUCCESS;
Govind Singha471e5e2015-10-12 17:11:14 +05301054}
1055
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001056#ifdef FEATURE_WLAN_LPHB
1057/**
1058 * wma_lphb_handler() - send LPHB indication to SME
1059 * @wma: wma handle
1060 * @event: event handler
1061 *
1062 * Return: 0 for success or error code
1063 */
1064static int wma_lphb_handler(tp_wma_handle wma, uint8_t *event)
1065{
1066 wmi_hb_ind_event_fixed_param *hb_fp;
1067 tSirLPHBInd *slphb_indication;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301068 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001069 cds_msg_t sme_msg = { 0 };
1070
1071 hb_fp = (wmi_hb_ind_event_fixed_param *) event;
1072 if (!hb_fp) {
1073 WMA_LOGE("Invalid wmi_hb_ind_event_fixed_param buffer");
1074 return -EINVAL;
1075 }
1076
1077 WMA_LOGD("lphb indication received with vdev_id=%d, session=%d, reason=%d",
1078 hb_fp->vdev_id, hb_fp->session, hb_fp->reason);
1079
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301080 slphb_indication = (tSirLPHBInd *) qdf_mem_malloc(sizeof(tSirLPHBInd));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001081
1082 if (!slphb_indication) {
1083 WMA_LOGE("Invalid LPHB indication buffer");
1084 return -ENOMEM;
1085 }
1086
1087 slphb_indication->sessionIdx = hb_fp->session;
1088 slphb_indication->protocolType = hb_fp->reason;
1089 slphb_indication->eventReason = hb_fp->reason;
1090
1091 sme_msg.type = eWNI_SME_LPHB_IND;
1092 sme_msg.bodyptr = slphb_indication;
1093 sme_msg.bodyval = 0;
1094
Anurag Chouhan6d760662016-02-20 16:05:43 +05301095 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301096 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001097 WMA_LOGE("Fail to post eWNI_SME_LPHB_IND msg to SME");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301098 qdf_mem_free(slphb_indication);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001099 return -EINVAL;
1100 }
1101
1102 return 0;
1103}
1104#endif /* FEATURE_WLAN_LPHB */
1105
1106#ifdef FEATURE_WLAN_RA_FILTERING
1107/**
1108 * wma_wow_sta_ra_filter() - set RA filter pattern in fw
1109 * @wma: wma handle
1110 * @vdev_id: vdev id
1111 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05301112 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001113 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301114static QDF_STATUS wma_wow_sta_ra_filter(tp_wma_handle wma, uint8_t vdev_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001115{
1116
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001117 struct wma_txrx_node *iface;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001118 int ret;
Govind Singhaa64c242016-03-08 11:31:49 +05301119 uint8_t default_pattern;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001120
1121 iface = &wma->interfaces[vdev_id];
1122
Govind Singhaa64c242016-03-08 11:31:49 +05301123 default_pattern = iface->num_wow_default_patterns++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001124
1125 WMA_LOGD("%s: send RA rate limit [%d] to fw vdev = %d", __func__,
1126 wma->RArateLimitInterval, vdev_id);
1127
Govind Singhaa64c242016-03-08 11:31:49 +05301128 ret = wmi_unified_wow_sta_ra_filter_cmd(wma->wmi_handle, vdev_id,
1129 default_pattern, wma->RArateLimitInterval);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001130 if (ret) {
1131 WMA_LOGE("%s: Failed to send RA rate limit to fw", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001132 iface->num_wow_default_patterns--;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301133 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001134 }
1135
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301136 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001137
1138}
1139#endif /* FEATURE_WLAN_RA_FILTERING */
1140
1141/**
1142 * wmi_unified_nat_keepalive_enable() - enable NAT keepalive filter
1143 * @wma: wma handle
1144 * @vdev_id: vdev id
1145 *
1146 * Return: 0 for success or error code
1147 */
1148int wmi_unified_nat_keepalive_enable(tp_wma_handle wma, uint8_t vdev_id)
1149{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001150
Govind Singhaa64c242016-03-08 11:31:49 +05301151 if (wmi_unified_nat_keepalive_en_cmd(wma->wmi_handle, vdev_id))
1152 return QDF_STATUS_E_FAILURE;
1153
1154 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001155}
1156
1157/**
Govind Singhd76a5b02016-03-08 15:12:14 +05301158 * wma_unified_csa_offload_enable() - sen CSA offload enable command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001159 * @wma: wma handle
1160 * @vdev_id: vdev id
1161 *
1162 * Return: 0 for success or error code
1163 */
Govind Singhd76a5b02016-03-08 15:12:14 +05301164int wma_unified_csa_offload_enable(tp_wma_handle wma, uint8_t vdev_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001165{
Govind Singhaa64c242016-03-08 11:31:49 +05301166 if (wmi_unified_csa_offload_enable(wma->wmi_handle,
1167 vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001168 WMA_LOGP("%s: Failed to send CSA offload enable command",
1169 __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001170 return -EIO;
1171 }
Govind Singhaa64c242016-03-08 11:31:49 +05301172
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001173 return 0;
1174}
1175
1176#ifdef WLAN_FEATURE_NAN
1177/**
1178 * wma_nan_rsp_event_handler() - Function is used to handle nan response
1179 * @handle: wma handle
1180 * @event_buf: event buffer
1181 * @len: length of buffer
1182 *
1183 * Return: 0 for success or error code
1184 */
1185int wma_nan_rsp_event_handler(void *handle, uint8_t *event_buf,
1186 uint32_t len)
1187{
1188 WMI_NAN_EVENTID_param_tlvs *param_buf;
1189 tSirNanEvent *nan_rsp_event;
1190 wmi_nan_event_hdr *nan_rsp_event_hdr;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301191 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001192 cds_msg_t cds_msg;
1193 uint8_t *buf_ptr;
1194 uint32_t alloc_len;
1195
1196 /*
1197 * This is how received event_buf looks like
1198 *
1199 * <-------------------- event_buf ----------------------------------->
1200 *
1201 * <--wmi_nan_event_hdr--><---WMI_TLV_HDR_SIZE---><----- data -------->
1202 *
1203 * +-----------+---------+-----------------------+--------------------+
1204 * | tlv_header| data_len| WMITLV_TAG_ARRAY_BYTE | nan_rsp_event_data |
1205 * +-----------+---------+-----------------------+--------------------+
1206 */
1207
1208 WMA_LOGD("%s: Posting NaN response event to SME", __func__);
1209 param_buf = (WMI_NAN_EVENTID_param_tlvs *) event_buf;
1210 if (!param_buf) {
1211 WMA_LOGE("%s: Invalid nan response event buf", __func__);
1212 return -EINVAL;
1213 }
1214 nan_rsp_event_hdr = param_buf->fixed_param;
1215 buf_ptr = (uint8_t *) nan_rsp_event_hdr;
1216 alloc_len = sizeof(tSirNanEvent);
1217 alloc_len += nan_rsp_event_hdr->data_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301218 nan_rsp_event = (tSirNanEvent *) qdf_mem_malloc(alloc_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001219 if (NULL == nan_rsp_event) {
1220 WMA_LOGE("%s: Memory allocation failure", __func__);
1221 return -ENOMEM;
1222 }
1223
1224 nan_rsp_event->event_data_len = nan_rsp_event_hdr->data_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301225 qdf_mem_copy(nan_rsp_event->event_data, buf_ptr +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001226 sizeof(wmi_nan_event_hdr) + WMI_TLV_HDR_SIZE,
1227 nan_rsp_event->event_data_len);
1228 cds_msg.type = eWNI_SME_NAN_EVENT;
1229 cds_msg.bodyptr = (void *)nan_rsp_event;
1230 cds_msg.bodyval = 0;
1231
1232 status = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301233 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001234 WMA_LOGE("%s: Failed to post NaN response event to SME",
1235 __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301236 qdf_mem_free(nan_rsp_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001237 return -EFAULT;
1238 }
1239 WMA_LOGD("%s: NaN response event Posted to SME", __func__);
1240 return 0;
1241}
1242#endif /* WLAN_FEATURE_NAN */
1243
1244/**
1245 * wma_csa_offload_handler() - CSA event handler
1246 * @handle: wma handle
1247 * @event: event buffer
1248 * @len: buffer length
1249 *
1250 * This event is sent by firmware when it receives CSA IE.
1251 *
1252 * Return: 0 for success or error code
1253 */
1254int wma_csa_offload_handler(void *handle, uint8_t *event, uint32_t len)
1255{
1256 tp_wma_handle wma = (tp_wma_handle) handle;
1257 WMI_CSA_HANDLING_EVENTID_param_tlvs *param_buf;
1258 wmi_csa_event_fixed_param *csa_event;
1259 uint8_t bssid[IEEE80211_ADDR_LEN];
1260 uint8_t vdev_id = 0;
1261 uint8_t cur_chan = 0;
1262 struct ieee80211_channelswitch_ie *csa_ie;
Chandrasekaran, Manishekar5c19dc52016-02-04 14:58:26 +05301263 struct csa_offload_params *csa_offload_event;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001264 struct ieee80211_extendedchannelswitch_ie *xcsa_ie;
1265 struct ieee80211_ie_wide_bw_switch *wb_ie;
1266 struct wma_txrx_node *intr = wma->interfaces;
1267
1268 param_buf = (WMI_CSA_HANDLING_EVENTID_param_tlvs *) event;
1269
1270 WMA_LOGD("%s: Enter", __func__);
1271 if (!param_buf) {
1272 WMA_LOGE("Invalid csa event buffer");
1273 return -EINVAL;
1274 }
1275 csa_event = param_buf->fixed_param;
1276 WMI_MAC_ADDR_TO_CHAR_ARRAY(&csa_event->i_addr2, &bssid[0]);
1277
1278 if (wma_find_vdev_by_bssid(wma, bssid, &vdev_id) == NULL) {
1279 WMA_LOGE("Invalid bssid received %s:%d", __func__, __LINE__);
1280 return -EINVAL;
1281 }
1282
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301283 csa_offload_event = qdf_mem_malloc(sizeof(*csa_offload_event));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001284 if (!csa_offload_event) {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05301285 WMA_LOGE("QDF MEM Alloc Failed for csa_offload_event");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001286 return -EINVAL;
1287 }
1288
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301289 qdf_mem_zero(csa_offload_event, sizeof(*csa_offload_event));
1290 qdf_mem_copy(csa_offload_event->bssId, &bssid, IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001291
1292 if (csa_event->ies_present_flag & WMI_CSA_IE_PRESENT) {
1293 csa_ie = (struct ieee80211_channelswitch_ie *)
1294 (&csa_event->csa_ie[0]);
1295 csa_offload_event->channel = csa_ie->newchannel;
Chandrasekaran, Manishekar5c19dc52016-02-04 14:58:26 +05301296 csa_offload_event->switch_mode = csa_ie->switchmode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001297 } else if (csa_event->ies_present_flag & WMI_XCSA_IE_PRESENT) {
1298 xcsa_ie = (struct ieee80211_extendedchannelswitch_ie *)
1299 (&csa_event->xcsa_ie[0]);
1300 csa_offload_event->channel = xcsa_ie->newchannel;
Chandrasekaran, Manishekar5c19dc52016-02-04 14:58:26 +05301301 csa_offload_event->switch_mode = xcsa_ie->switchmode;
Gupta, Kapil121bf212015-11-25 19:21:29 +05301302 csa_offload_event->new_op_class = xcsa_ie->newClass;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001303 } else {
1304 WMA_LOGE("CSA Event error: No CSA IE present");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301305 qdf_mem_free(csa_offload_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001306 return -EINVAL;
1307 }
1308
1309 if (csa_event->ies_present_flag & WMI_WBW_IE_PRESENT) {
1310 wb_ie = (struct ieee80211_ie_wide_bw_switch *)
1311 (&csa_event->wb_ie[0]);
1312 csa_offload_event->new_ch_width = wb_ie->new_ch_width;
1313 csa_offload_event->new_ch_freq_seg1 = wb_ie->new_ch_freq_seg1;
1314 csa_offload_event->new_ch_freq_seg2 = wb_ie->new_ch_freq_seg2;
1315 }
1316
1317 csa_offload_event->ies_present_flag = csa_event->ies_present_flag;
1318
1319 WMA_LOGD("CSA: New Channel = %d BSSID:%pM",
1320 csa_offload_event->channel, csa_offload_event->bssId);
1321
1322 cur_chan = cds_freq_to_chan(intr[vdev_id].mhz);
1323 /*
1324 * basic sanity check: requested channel should not be 0
1325 * and equal to home channel
1326 */
1327 if ((0 == csa_offload_event->channel) ||
1328 (cur_chan == csa_offload_event->channel)) {
1329 WMA_LOGE("CSA Event with channel %d. Ignore !!",
1330 csa_offload_event->channel);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301331 qdf_mem_free(csa_offload_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001332 return -EINVAL;
1333 }
1334 wma->interfaces[vdev_id].is_channel_switch = true;
1335 wma_send_msg(wma, WMA_CSA_OFFLOAD_EVENT, (void *)csa_offload_event, 0);
1336 return 0;
1337}
1338
1339#ifdef FEATURE_OEM_DATA_SUPPORT
1340
1341/**
1342 * wma_oem_capability_event_callback() - OEM capability event handler
1343 * @handle: wma handle
1344 * @datap: data ptr
1345 * @len: data length
1346 *
1347 * Return: 0 for success or error code
1348 */
1349int wma_oem_capability_event_callback(void *handle,
1350 uint8_t *datap, uint32_t len)
1351{
1352 tp_wma_handle wma = (tp_wma_handle) handle;
1353 WMI_OEM_CAPABILITY_EVENTID_param_tlvs *param_buf;
1354 uint8_t *data;
1355 uint32_t datalen;
1356 uint32_t *msg_subtype;
1357 tStartOemDataRsp *pStartOemDataRsp;
1358
1359 param_buf = (WMI_OEM_CAPABILITY_EVENTID_param_tlvs *) datap;
1360 if (!param_buf) {
1361 WMA_LOGE("%s: Received NULL buf ptr from FW", __func__);
1362 return -ENOMEM;
1363 }
1364
1365 data = param_buf->data;
1366 datalen = param_buf->num_data;
1367
1368 if (!data) {
1369 WMA_LOGE("%s: Received NULL data from FW", __func__);
1370 return -EINVAL;
1371 }
1372
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001373 /*
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001374 * wma puts 4 bytes prefix for msg subtype, so length
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001375 * of data received from target should be 4 bytes less
1376 * then max allowed
1377 */
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001378 if (datalen > (OEM_DATA_RSP_SIZE - OEM_MESSAGE_SUBTYPE_LEN)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001379 WMA_LOGE("%s: Received data len (%d) exceeds max value (%d)",
1380 __func__, datalen, (OEM_DATA_RSP_SIZE - 4));
1381 return -EINVAL;
1382 }
1383
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301384 pStartOemDataRsp = qdf_mem_malloc(sizeof(*pStartOemDataRsp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001385 if (!pStartOemDataRsp) {
1386 WMA_LOGE("%s: Failed to alloc pStartOemDataRsp", __func__);
1387 return -ENOMEM;
1388 }
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001389
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001390 pStartOemDataRsp->rsp_len = datalen + OEM_MESSAGE_SUBTYPE_LEN;
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001391 if (pStartOemDataRsp->rsp_len) {
1392 pStartOemDataRsp->oem_data_rsp =
1393 qdf_mem_malloc(pStartOemDataRsp->rsp_len);
1394 if (!pStartOemDataRsp->oem_data_rsp) {
1395 WMA_LOGE(FL("malloc failed for oem_data_rsp"));
1396 qdf_mem_free(pStartOemDataRsp);
1397 return -ENOMEM;
1398 }
1399 } else {
1400 WMA_LOGE(FL("Invalid rsp length: %d"),
1401 pStartOemDataRsp->rsp_len);
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001402 qdf_mem_free(pStartOemDataRsp);
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001403 return -EINVAL;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001404 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001405
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001406 pStartOemDataRsp->target_rsp = true;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001407 msg_subtype = (uint32_t *) pStartOemDataRsp->oem_data_rsp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001408 *msg_subtype = WMI_OEM_CAPABILITY_RSP;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001409 /* copy data after msg sub type */
1410 qdf_mem_copy(pStartOemDataRsp->oem_data_rsp + OEM_MESSAGE_SUBTYPE_LEN,
1411 data, datalen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001412
1413 WMA_LOGI("%s: Sending WMA_START_OEM_DATA_RSP, data len (%d)",
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001414 __func__, pStartOemDataRsp->rsp_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001415
1416 wma_send_msg(wma, WMA_START_OEM_DATA_RSP, (void *)pStartOemDataRsp, 0);
1417 return 0;
1418}
1419
1420/**
1421 * wma_oem_measurement_report_event_callback() - OEM measurement report handler
1422 * @handle: wma handle
1423 * @datap: data ptr
1424 * @len: data length
1425 *
1426 * Return: 0 for success or error code
1427 */
1428int wma_oem_measurement_report_event_callback(void *handle,
1429 uint8_t *datap,
1430 uint32_t len)
1431{
1432 tp_wma_handle wma = (tp_wma_handle) handle;
1433 WMI_OEM_MEASUREMENT_REPORT_EVENTID_param_tlvs *param_buf;
1434 uint8_t *data;
1435 uint32_t datalen;
1436 uint32_t *msg_subtype;
1437 tStartOemDataRsp *pStartOemDataRsp;
1438
1439 param_buf = (WMI_OEM_MEASUREMENT_REPORT_EVENTID_param_tlvs *) datap;
1440 if (!param_buf) {
1441 WMA_LOGE("%s: Received NULL buf ptr from FW", __func__);
1442 return -ENOMEM;
1443 }
1444
1445 data = param_buf->data;
1446 datalen = param_buf->num_data;
1447
1448 if (!data) {
1449 WMA_LOGE("%s: Received NULL data from FW", __func__);
1450 return -EINVAL;
1451 }
1452
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001453 /*
1454 * wma puts 4 bytes prefix for msg subtype, so length
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001455 * of data received from target should be 4 bytes less
1456 * then max allowed
1457 */
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001458 if (datalen > (OEM_DATA_RSP_SIZE - OEM_MESSAGE_SUBTYPE_LEN)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001459 WMA_LOGE("%s: Received data len (%d) exceeds max value (%d)",
1460 __func__, datalen, (OEM_DATA_RSP_SIZE - 4));
1461 return -EINVAL;
1462 }
1463
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301464 pStartOemDataRsp = qdf_mem_malloc(sizeof(*pStartOemDataRsp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001465 if (!pStartOemDataRsp) {
1466 WMA_LOGE("%s: Failed to alloc pStartOemDataRsp", __func__);
1467 return -ENOMEM;
1468 }
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001469
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001470 pStartOemDataRsp->rsp_len = datalen + OEM_MESSAGE_SUBTYPE_LEN;
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001471 if (pStartOemDataRsp->rsp_len) {
1472 pStartOemDataRsp->oem_data_rsp =
1473 qdf_mem_malloc(pStartOemDataRsp->rsp_len);
1474 if (!pStartOemDataRsp->oem_data_rsp) {
1475 WMA_LOGE(FL("malloc failed for oem_data_rsp"));
1476 qdf_mem_free(pStartOemDataRsp);
1477 return -ENOMEM;
1478 }
1479 } else {
1480 WMA_LOGE(FL("Invalid rsp length: %d"),
1481 pStartOemDataRsp->rsp_len);
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001482 qdf_mem_free(pStartOemDataRsp);
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001483 return -EINVAL;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001484 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001485
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001486 pStartOemDataRsp->target_rsp = true;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001487 msg_subtype = (uint32_t *) pStartOemDataRsp->oem_data_rsp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001488 *msg_subtype = WMI_OEM_MEASUREMENT_RSP;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001489 /* copy data after msg sub type */
1490 qdf_mem_copy(pStartOemDataRsp->oem_data_rsp + OEM_MESSAGE_SUBTYPE_LEN,
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001491 data, datalen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001492
1493 WMA_LOGI("%s: Sending WMA_START_OEM_DATA_RSP, data len (%d)",
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001494 __func__, pStartOemDataRsp->rsp_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001495
1496 wma_send_msg(wma, WMA_START_OEM_DATA_RSP, (void *)pStartOemDataRsp, 0);
1497 return 0;
1498}
1499
1500/**
1501 * wma_oem_error_report_event_callback() - OEM error report handler
1502 * @handle: wma handle
1503 * @datap: data ptr
1504 * @len: data length
1505 *
1506 * Return: 0 for success or error code
1507 */
1508int wma_oem_error_report_event_callback(void *handle,
1509 uint8_t *datap, uint32_t len)
1510{
1511 tp_wma_handle wma = (tp_wma_handle) handle;
1512 WMI_OEM_ERROR_REPORT_EVENTID_param_tlvs *param_buf;
1513 uint8_t *data;
1514 uint32_t datalen;
1515 uint32_t *msg_subtype;
1516 tStartOemDataRsp *pStartOemDataRsp;
1517
1518 param_buf = (WMI_OEM_ERROR_REPORT_EVENTID_param_tlvs *) datap;
1519 if (!param_buf) {
1520 WMA_LOGE("%s: Received NULL buf ptr from FW", __func__);
1521 return -ENOMEM;
1522 }
1523
1524 data = param_buf->data;
1525 datalen = param_buf->num_data;
1526
1527 if (!data) {
1528 WMA_LOGE("%s: Received NULL data from FW", __func__);
1529 return -EINVAL;
1530 }
1531
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001532 /*
1533 * wma puts 4 bytes prefix for msg subtype, so length
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001534 * of data received from target should be 4 bytes less
1535 * then max allowed
1536 */
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001537 if (datalen > (OEM_DATA_RSP_SIZE - OEM_MESSAGE_SUBTYPE_LEN)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001538 WMA_LOGE("%s: Received data len (%d) exceeds max value (%d)",
1539 __func__, datalen, (OEM_DATA_RSP_SIZE - 4));
1540 return -EINVAL;
1541 }
1542
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301543 pStartOemDataRsp = qdf_mem_malloc(sizeof(*pStartOemDataRsp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001544 if (!pStartOemDataRsp) {
1545 WMA_LOGE("%s: Failed to alloc pStartOemDataRsp", __func__);
1546 return -ENOMEM;
1547 }
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001548
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001549 pStartOemDataRsp->rsp_len = datalen + OEM_MESSAGE_SUBTYPE_LEN;
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001550 if (pStartOemDataRsp->rsp_len) {
1551 pStartOemDataRsp->oem_data_rsp =
1552 qdf_mem_malloc(pStartOemDataRsp->rsp_len);
1553 if (!pStartOemDataRsp->oem_data_rsp) {
1554 WMA_LOGE(FL("malloc failed for oem_data_rsp"));
1555 qdf_mem_free(pStartOemDataRsp);
1556 return -ENOMEM;
1557 }
1558 } else {
1559 WMA_LOGE(FL("Invalid rsp length: %d"),
1560 pStartOemDataRsp->rsp_len);
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001561 qdf_mem_free(pStartOemDataRsp);
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001562 return -EINVAL;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001563 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001564
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001565 pStartOemDataRsp->target_rsp = true;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001566 msg_subtype = (uint32_t *) pStartOemDataRsp->oem_data_rsp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001567 *msg_subtype = WMI_OEM_ERROR_REPORT_RSP;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001568 /* copy data after msg sub type */
1569 qdf_mem_copy(pStartOemDataRsp->oem_data_rsp + OEM_MESSAGE_SUBTYPE_LEN,
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001570 data, datalen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001571
1572 WMA_LOGI("%s: Sending WMA_START_OEM_DATA_RSP, data len (%d)",
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001573 __func__, pStartOemDataRsp->rsp_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001574
1575 wma_send_msg(wma, WMA_START_OEM_DATA_RSP, (void *)pStartOemDataRsp, 0);
1576 return 0;
1577}
1578
1579/**
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001580 * wma_oem_data_response_handler() - OEM data response event handler
1581 * @handle: wma handle
1582 * @datap: data ptr
1583 * @len: data length
1584 *
1585 * Return: 0 for success or error code
1586 */
1587int wma_oem_data_response_handler(void *handle,
1588 uint8_t *datap, uint32_t len)
1589{
1590 tp_wma_handle wma = (tp_wma_handle) handle;
1591 WMI_OEM_RESPONSE_EVENTID_param_tlvs *param_buf;
1592 uint8_t *data;
1593 uint32_t datalen;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001594 tStartOemDataRsp *oem_rsp;
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001595
1596 param_buf = (WMI_OEM_RESPONSE_EVENTID_param_tlvs *) datap;
1597 if (!param_buf) {
1598 WMA_LOGE(FL("Received NULL buf ptr from FW"));
1599 return -ENOMEM;
1600 }
1601
1602 data = param_buf->data;
1603 datalen = param_buf->num_data;
1604
1605 if (!data) {
1606 WMA_LOGE(FL("Received NULL data from FW"));
1607 return -EINVAL;
1608 }
1609
1610 if (datalen > OEM_DATA_RSP_SIZE) {
1611 WMA_LOGE(FL("Received data len %d exceeds max value %d"),
1612 datalen, OEM_DATA_RSP_SIZE);
1613 return -EINVAL;
1614 }
1615
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001616 oem_rsp = qdf_mem_malloc(sizeof(*oem_rsp));
1617 if (!oem_rsp) {
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001618 WMA_LOGE(FL("Failed to alloc oem_data_rsp"));
1619 return -ENOMEM;
1620 }
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001621 oem_rsp->rsp_len = datalen;
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001622 if (oem_rsp->rsp_len) {
1623 oem_rsp->oem_data_rsp = qdf_mem_malloc(oem_rsp->rsp_len);
1624 if (!oem_rsp->oem_data_rsp) {
1625 WMA_LOGE(FL("malloc failed for oem_data_rsp"));
1626 qdf_mem_free(oem_rsp);
1627 return -ENOMEM;
1628 }
1629 } else {
1630 WMA_LOGE(FL("Invalid rsp length: %d"),
1631 oem_rsp->rsp_len);
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001632 qdf_mem_free(oem_rsp);
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001633 return -EINVAL;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001634 }
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001635
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001636 oem_rsp->target_rsp = true;
1637 qdf_mem_copy(oem_rsp->oem_data_rsp, data, datalen);
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001638
1639 WMA_LOGI(FL("Sending WMA_START_OEM_DATA_RSP, data len %d"), datalen);
1640
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001641 wma_send_msg(wma, WMA_START_OEM_DATA_RSP, (void *)oem_rsp, 0);
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001642 return 0;
1643}
1644
1645/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001646 * wma_start_oem_data_req() - start OEM data request to target
1647 * @wma_handle: wma handle
1648 * @startOemDataReq: start request params
1649 *
1650 * Return: none
1651 */
1652void wma_start_oem_data_req(tp_wma_handle wma_handle,
1653 tStartOemDataReq *startOemDataReq)
1654{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001655 int ret = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001656 tStartOemDataRsp *pStartOemDataRsp;
1657
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001658 WMA_LOGD(FL("Send OEM Data Request to target"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001659
Sreelakshmi Konamki86d79202016-02-10 12:33:40 +05301660 if (!startOemDataReq || !startOemDataReq->data) {
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001661 WMA_LOGE(FL("startOemDataReq is null"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001662 goto out;
1663 }
1664
1665 if (!wma_handle || !wma_handle->wmi_handle) {
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001666 WMA_LOGE(FL("WMA - closed, can not send Oem data request cmd"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001667 return;
1668 }
1669
Govind Singhaa64c242016-03-08 11:31:49 +05301670 ret = wmi_unified_start_oem_data_cmd(wma_handle->wmi_handle,
1671 startOemDataReq->data_len,
1672 startOemDataReq->data);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001673
1674 if (ret != EOK) {
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001675 WMA_LOGE(FL(":wmi cmd send failed"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001676 }
1677
1678out:
1679 /* free oem data req buffer received from UMAC */
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001680 if (startOemDataReq) {
1681 if (startOemDataReq->data)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301682 qdf_mem_free(startOemDataReq->data);
1683 qdf_mem_free(startOemDataReq);
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001684 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001685
1686 /* Now send data resp back to PE/SME with message sub-type of
1687 * WMI_OEM_INTERNAL_RSP. This is required so that PE/SME clears
1688 * up pending active command. Later when desired oem response(s)
1689 * comes as wmi event from target then those shall be passed
1690 * to oem application
1691 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301692 pStartOemDataRsp = qdf_mem_malloc(sizeof(*pStartOemDataRsp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001693 if (!pStartOemDataRsp) {
1694 WMA_LOGE("%s:failed to allocate memory for OEM Data Resp to PE",
1695 __func__);
1696 return;
1697 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301698 qdf_mem_zero(pStartOemDataRsp, sizeof(tStartOemDataRsp));
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001699 pStartOemDataRsp->target_rsp = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001700
1701 WMA_LOGI("%s: Sending WMA_START_OEM_DATA_RSP to clear up PE/SME pending cmd",
1702 __func__);
1703
1704 wma_send_msg(wma_handle, WMA_START_OEM_DATA_RSP,
1705 (void *)pStartOemDataRsp, 0);
1706
1707 return;
1708}
1709#endif /* FEATURE_OEM_DATA_SUPPORT */
1710
1711
1712/**
1713 * wma_unified_dfs_radar_rx_event_handler() - dfs radar rx event handler
1714 * @handle: wma handle
1715 * @data: data buffer
1716 * @datalen: data length
1717 *
1718 * WMI handler for WMI_DFS_RADAR_EVENTID
1719 * This handler is registered for handling
1720 * filtered DFS Phyerror. This handler is
1721 * will be invoked only when DFS Phyerr
1722 * filtering offload is enabled.
1723 *
1724 * Return: 1 for Success and 0 for error
1725 */
1726static int wma_unified_dfs_radar_rx_event_handler(void *handle,
1727 uint8_t *data,
1728 uint32_t datalen)
1729{
1730 tp_wma_handle wma = (tp_wma_handle) handle;
1731 struct ieee80211com *ic;
1732 struct ath_dfs *dfs;
1733 struct dfs_event *event;
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05301734 struct dfs_ieee80211_channel *chan;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001735 int empty;
1736 int do_check_chirp = 0;
1737 int is_hw_chirp = 0;
1738 int is_sw_chirp = 0;
1739 int is_pri = 0;
Vishwajith Upendrabf673e72016-01-19 16:05:40 -08001740 bool is_ch_dfs = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001741
1742 WMI_DFS_RADAR_EVENTID_param_tlvs *param_tlvs;
1743 wmi_dfs_radar_event_fixed_param *radar_event;
1744
1745 ic = wma->dfs_ic;
1746 if (NULL == ic) {
1747 WMA_LOGE("%s: dfs_ic is NULL ", __func__);
1748 return 0;
1749 }
1750
1751 dfs = (struct ath_dfs *)ic->ic_dfs;
1752 param_tlvs = (WMI_DFS_RADAR_EVENTID_param_tlvs *) data;
1753
1754 if (NULL == dfs) {
1755 WMA_LOGE("%s: dfs is NULL ", __func__);
1756 return 0;
1757 }
1758 /*
1759 * This parameter holds the number
1760 * of phyerror interrupts to the host
1761 * after the phyerrors have passed through
1762 * false detect filters in the firmware.
1763 */
1764 dfs->dfs_phyerr_count++;
1765
1766 if (!param_tlvs) {
1767 WMA_LOGE("%s: Received NULL data from FW", __func__);
1768 return 0;
1769 }
1770
1771 radar_event = param_tlvs->fixed_param;
1772
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301773 qdf_spin_lock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001774 chan = ic->ic_curchan;
Edhar, Mahesh Kumar35d9b2e2015-10-26 17:06:23 +05301775 if (ic->disable_phy_err_processing) {
1776 WMA_LOGD("%s: radar indication done,drop phyerror event",
1777 __func__);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301778 qdf_spin_unlock_bh(&ic->chan_lock);
Edhar, Mahesh Kumar35d9b2e2015-10-26 17:06:23 +05301779 return 0;
1780 }
1781
Vishwajith Upendrabf673e72016-01-19 16:05:40 -08001782 if (IEEE80211_IS_CHAN_11AC_VHT160(chan)) {
1783 is_ch_dfs = true;
1784 } else if (IEEE80211_IS_CHAN_11AC_VHT80P80(chan)) {
1785 if (cds_get_channel_state(chan->ic_ieee) == CHANNEL_STATE_DFS ||
1786 cds_get_channel_state(chan->ic_ieee_ext -
1787 WMA_80MHZ_START_CENTER_CH_DIFF) ==
1788 CHANNEL_STATE_DFS)
1789 is_ch_dfs = true;
1790 } else {
1791 if (cds_get_channel_state(chan->ic_ieee) == CHANNEL_STATE_DFS)
1792 is_ch_dfs = true;
1793 }
1794 if (!is_ch_dfs) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001795 WMA_LOGE
1796 ("%s: Invalid DFS Phyerror event. Channel=%d is Non-DFS",
1797 __func__, chan->ic_ieee);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301798 qdf_spin_unlock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001799 return 0;
1800 }
1801
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301802 qdf_spin_unlock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001803 dfs->ath_dfs_stats.total_phy_errors++;
1804
1805 if (dfs->dfs_caps.ath_chip_is_bb_tlv) {
1806 do_check_chirp = 1;
1807 is_pri = 1;
1808 is_hw_chirp = radar_event->pulse_is_chirp;
1809
1810 if ((uint32_t) dfs->dfs_phyerr_freq_min >
1811 radar_event->pulse_center_freq) {
1812 dfs->dfs_phyerr_freq_min =
1813 (int)radar_event->pulse_center_freq;
1814 }
1815
1816 if (dfs->dfs_phyerr_freq_max <
1817 (int)radar_event->pulse_center_freq) {
1818 dfs->dfs_phyerr_freq_max =
1819 (int)radar_event->pulse_center_freq;
1820 }
1821 }
1822
1823 /*
1824 * Now, add the parsed, checked and filtered
1825 * radar phyerror event radar pulse event list.
1826 * This event will then be processed by
1827 * dfs_radar_processevent() to see if the pattern
1828 * of pulses in radar pulse list match any radar
1829 * singnature in the current regulatory domain.
1830 */
1831
1832 ATH_DFSEVENTQ_LOCK(dfs);
1833 empty = STAILQ_EMPTY(&(dfs->dfs_eventq));
1834 ATH_DFSEVENTQ_UNLOCK(dfs);
1835 if (empty) {
1836 return 0;
1837 }
1838 /*
1839 * Add the event to the list, if there's space.
1840 */
1841 ATH_DFSEVENTQ_LOCK(dfs);
1842 event = STAILQ_FIRST(&(dfs->dfs_eventq));
1843 if (event == NULL) {
1844 ATH_DFSEVENTQ_UNLOCK(dfs);
1845 WMA_LOGE("%s: No more space left for queuing DFS Phyerror events",
1846 __func__);
1847 return 0;
1848 }
1849 STAILQ_REMOVE_HEAD(&(dfs->dfs_eventq), re_list);
1850 ATH_DFSEVENTQ_UNLOCK(dfs);
1851 dfs->dfs_phyerr_queued_count++;
1852 dfs->dfs_phyerr_w53_counter++;
1853 event->re_dur = (uint8_t) radar_event->pulse_duration;
1854 event->re_rssi = radar_event->rssi;
1855 event->re_ts = radar_event->pulse_detect_ts & DFS_TSMASK;
1856 event->re_full_ts = (((uint64_t) radar_event->upload_fullts_high) << 32)
1857 | radar_event->upload_fullts_low;
1858
1859 /*
1860 * Index of peak magnitude
1861 */
1862 event->sidx = radar_event->peak_sidx;
1863
1864 /*
1865 * Handle chirp flags.
1866 */
1867 if (do_check_chirp) {
1868 event->re_flags |= DFS_EVENT_CHECKCHIRP;
1869 if (is_hw_chirp) {
1870 event->re_flags |= DFS_EVENT_HW_CHIRP;
1871 }
1872 if (is_sw_chirp) {
1873 event->re_flags |= DFS_EVENT_SW_CHIRP;
1874 }
1875 }
1876 /*
1877 * Correctly set which channel is being reported on
1878 */
1879 if (is_pri) {
1880 event->re_chanindex = (uint8_t) dfs->dfs_curchan_radindex;
1881 } else {
1882 if (dfs->dfs_extchan_radindex == -1) {
1883 WMA_LOGI("%s phyerr on ext channel", __func__);
1884 }
1885 event->re_chanindex = (uint8_t) dfs->dfs_extchan_radindex;
1886 WMA_LOGI("%s:New extension channel event is added to queue",
1887 __func__);
1888 }
1889
1890 ATH_DFSQ_LOCK(dfs);
1891
1892 STAILQ_INSERT_TAIL(&(dfs->dfs_radarq), event, re_list);
1893
1894 empty = STAILQ_EMPTY(&dfs->dfs_radarq);
1895
1896 ATH_DFSQ_UNLOCK(dfs);
1897
1898 if (!empty && !dfs->ath_radar_tasksched) {
1899 dfs->ath_radar_tasksched = 1;
1900 OS_SET_TIMER(&dfs->ath_dfs_task_timer, 0);
1901 }
1902
1903 return 1;
1904
1905}
1906
1907/**
1908 * wma_unified_phyerr_rx_event_handler() - phyerr event handler
1909 * @handle: wma handle
1910 * @data: data buffer
1911 * @datalen: buffer length
1912 *
1913 * WMI Handler for WMI_PHYERR_EVENTID event from firmware.
1914 * This handler is currently handling only DFS phy errors.
1915 * This handler will be invoked only when the DFS phyerror
1916 * filtering offload is disabled.
1917 *
1918 * Return: 1:Success, 0:Failure
1919 */
1920static int wma_unified_phyerr_rx_event_handler(void *handle,
1921 uint8_t *data, uint32_t datalen)
1922{
1923 tp_wma_handle wma = (tp_wma_handle) handle;
1924 WMI_PHYERR_EVENTID_param_tlvs *param_tlvs;
1925 wmi_comb_phyerr_rx_hdr *pe_hdr;
1926 uint8_t *bufp;
1927 wmi_single_phyerr_rx_event *ev;
1928 struct ieee80211com *ic = wma->dfs_ic;
Anurag Chouhan6d760662016-02-20 16:05:43 +05301929 qdf_size_t n;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001930 A_UINT64 tsf64 = 0;
1931 int phy_err_code = 0;
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08001932 A_UINT32 phy_err_mask = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001933 int error = 0;
1934 tpAniSirGlobal mac_ctx =
Anurag Chouhan6d760662016-02-20 16:05:43 +05301935 (tpAniSirGlobal)cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001936 bool enable_log = false;
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08001937 int max_dfs_buf_length = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001938
1939 if (NULL == mac_ctx) {
1940 WMA_LOGE("%s: mac_ctx is NULL", __func__);
1941 return 0;
1942 }
1943 enable_log = mac_ctx->sap.enable_dfs_phy_error_logs;
1944
1945 param_tlvs = (WMI_PHYERR_EVENTID_param_tlvs *) data;
1946
1947 if (!param_tlvs) {
1948 WMA_LOGE("%s: Received NULL data from FW", __func__);
1949 return 0;
1950 }
1951
1952 pe_hdr = param_tlvs->hdr;
1953 if (pe_hdr == NULL) {
1954 WMA_LOGE("%s: Received Data PE Header is NULL", __func__);
1955 return 0;
1956 }
1957
1958 /* Ensure it's at least the size of the header */
1959 if (datalen < sizeof(*pe_hdr)) {
1960 WMA_LOGE("%s: Expected minimum size %zu, received %d",
1961 __func__, sizeof(*pe_hdr), datalen);
1962 return 0;
1963 }
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08001964 /*
1965 * The max buffer lenght is larger for DFS-3 than DFS-2.
1966 * So, accordingly use the correct max buffer size.
1967 */
1968 if (wma->hw_bd_id != WMI_HWBD_QCA6174)
1969 max_dfs_buf_length = DFS3_MAX_BUF_LENGTH;
1970 else
1971 max_dfs_buf_length = DFS_MAX_BUF_LENGTH;
1972
1973 if (pe_hdr->buf_len > max_dfs_buf_length) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001974 WMA_LOGE("%s: Received Invalid Phyerror event buffer length = %d"
1975 "Maximum allowed buf length = %d", __func__,
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08001976 pe_hdr->buf_len, max_dfs_buf_length);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001977
1978 return 0;
1979 }
1980
1981 /*
1982 * Reconstruct the 64 bit event TSF. This isn't from the MAC, it's
1983 * at the time the event was sent to us, the TSF value will be
1984 * in the future.
1985 */
1986 tsf64 = pe_hdr->tsf_l32;
1987 tsf64 |= (((uint64_t) pe_hdr->tsf_u32) << 32);
1988
1989 /*
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08001990 * Check the HW board ID to figure out
1991 * if DFS-3 is supported. In DFS-3
1992 * phyerror mask indicates the type of
1993 * phyerror, whereas in DFS-2 phyerrorcode
1994 * indicates the type of phyerror. If the
1995 * board is NOT WMI_HWBD_QCA6174, for now
1996 * assume that it supports DFS-3.
1997 */
1998 if (wma->hw_bd_id != WMI_HWBD_QCA6174) {
1999 phy_err_mask = pe_hdr->rsPhyErrMask0;
2000 WMA_LOGD("%s: DFS-3 phyerror mask = 0x%x",
2001 __func__, phy_err_mask);
2002 }
2003
2004 /*
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002005 * Loop over the bufp, extracting out phyerrors
2006 * wmi_unified_comb_phyerr_rx_event.bufp is a char pointer,
2007 * which isn't correct here - what we have received here
2008 * is an array of TLV-style PHY errors.
2009 */
2010 n = 0; /* Start just after the header */
2011 bufp = param_tlvs->bufp;
2012 while (n < pe_hdr->buf_len) {
2013 /* ensure there's at least space for the header */
2014 if ((pe_hdr->buf_len - n) < sizeof(ev->hdr)) {
2015 WMA_LOGE("%s: Not enough space.(datalen=%d, n=%zu, hdr=%zu bytes",
2016 __func__, pe_hdr->buf_len, n, sizeof(ev->hdr));
2017 error = 1;
2018 break;
2019 }
2020 /*
2021 * Obtain a pointer to the beginning of the current event.
2022 * data[0] is the beginning of the WMI payload.
2023 */
2024 ev = (wmi_single_phyerr_rx_event *) &bufp[n];
2025
2026 /*
2027 * Sanity check the buffer length of the event against
2028 * what we currently have.
2029 * Since buf_len is 32 bits, we check if it overflows
2030 * a large 32 bit value. It's not 0x7fffffff because
2031 * we increase n by (buf_len + sizeof(hdr)), which would
2032 * in itself cause n to overflow.
2033 * If "int" is 64 bits then this becomes a moot point.
2034 */
2035 if (ev->hdr.buf_len > 0x7f000000) {
2036 WMA_LOGE("%s:buf_len is garbage (0x%x)", __func__,
2037 ev->hdr.buf_len);
2038 error = 1;
2039 break;
2040 }
2041 if (n + ev->hdr.buf_len > pe_hdr->buf_len) {
2042 WMA_LOGE("%s: buf_len exceeds available space n=%zu,"
2043 "buf_len=%d, datalen=%d",
2044 __func__, n, ev->hdr.buf_len, pe_hdr->buf_len);
2045 error = 1;
2046 break;
2047 }
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002048 /*
2049 * If the board id is WMI_HWBD_QCA6174
2050 * then it supports only DFS-2. So, fetch
2051 * phyerror code in order to know the type
2052 * of phyerror.
2053 */
2054 if (wma->hw_bd_id == WMI_HWBD_QCA6174) {
2055 phy_err_code = WMI_UNIFIED_PHYERRCODE_GET(&ev->hdr);
2056 WMA_LOGD("%s: DFS-2 phyerror code = 0x%x",
2057 __func__, phy_err_code);
2058 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002059
2060 /*
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002061 * phy_err_code is set for DFS-2 and phy_err_mask
2062 * is set for DFS-3. Checking both to support
2063 * compatability for older platforms.
2064 * If the phyerror or phyerrmask category matches,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002065 * pass radar events to the dfs pattern matching code.
2066 * Don't pass radar events with no buffer payload.
2067 */
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002068 if (((phy_err_mask & WMI_PHY_ERROR_MASK0_RADAR) ||
2069 (phy_err_mask & WMI_PHY_ERROR_MASK0_FALSE_RADAR_EXT)) ||
2070 (phy_err_code == WMA_DFS2_PHYERROR_CODE ||
2071 phy_err_code == WMA_DFS2_FALSE_RADAR_EXT)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002072 if (ev->hdr.buf_len > 0) {
2073 /* Calling in to the DFS module to process the phyerr */
2074 dfs_process_phyerr(ic, &ev->bufp[0],
2075 ev->hdr.buf_len,
2076 WMI_UNIFIED_RSSI_COMB_GET
2077 (&ev->hdr) & 0xff,
2078 /* Extension RSSI */
2079 WMI_UNIFIED_RSSI_COMB_GET
2080 (&ev->hdr) & 0xff,
2081 ev->hdr.tsf_timestamp,
2082 tsf64, enable_log);
2083 }
2084 }
2085
2086 /*
2087 * Advance the buffer pointer to the next PHY error.
2088 * buflen is the length of this payload, so we need to
2089 * advance past the current header _AND_ the payload.
2090 */
2091 n += sizeof(*ev) + ev->hdr.buf_len;
2092
2093 } /*end while() */
2094 if (error)
2095 return 0;
2096 else
2097 return 1;
2098}
2099
2100/**
2101 * wma_register_dfs_event_handler() - register dfs event handler
2102 * @wma_handle: wma handle
2103 *
2104 * Register appropriate dfs phyerror event handler
2105 * based on phyerror filtering offload is enabled
2106 * or disabled.
2107 *
2108 * Return: none
2109 */
2110void wma_register_dfs_event_handler(tp_wma_handle wma_handle)
2111{
2112 if (NULL == wma_handle) {
2113 WMA_LOGE("%s:wma_handle is NULL", __func__);
2114 return;
2115 }
2116
2117 if (false == wma_handle->dfs_phyerr_filter_offload) {
2118 /*
2119 * Register the wma_unified_phyerr_rx_event_handler
2120 * for filtering offload disabled case to handle
2121 * the DFS phyerrors.
2122 */
2123 WMA_LOGD("%s:Phyerror Filtering offload is Disabled in ini",
2124 __func__);
2125 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Govind Singhd76a5b02016-03-08 15:12:14 +05302126 WMI_PHYERR_EVENTID,
2127 wma_unified_phyerr_rx_event_handler,
2128 WMA_RX_WORK_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002129 WMA_LOGD("%s: WMI_PHYERR_EVENTID event handler registered",
2130 __func__);
2131 } else {
2132 WMA_LOGD("%s:Phyerror Filtering offload is Enabled in ini",
2133 __func__);
2134 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Govind Singhd76a5b02016-03-08 15:12:14 +05302135 WMI_DFS_RADAR_EVENTID,
2136 wma_unified_dfs_radar_rx_event_handler,
2137 WMA_RX_WORK_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002138 WMA_LOGD("%s:WMI_DFS_RADAR_EVENTID event handler registered",
2139 __func__);
2140 }
2141
2142 return;
2143}
2144
2145
2146/**
2147 * wma_unified_dfs_phyerr_filter_offload_enable() - enable dfs phyerr filter
2148 * @wma_handle: wma handle
2149 *
2150 * Send WMI_DFS_PHYERR_FILTER_ENA_CMDID or
2151 * WMI_DFS_PHYERR_FILTER_DIS_CMDID command
2152 * to firmware based on phyerr filtering
2153 * offload status.
2154 *
2155 * Return: 1 success, 0 failure
2156 */
2157int
2158wma_unified_dfs_phyerr_filter_offload_enable(tp_wma_handle wma_handle)
2159{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002160 int ret;
2161
2162 if (NULL == wma_handle) {
2163 WMA_LOGE("%s:wma_handle is NULL", __func__);
2164 return 0;
2165 }
2166
Govind Singhaa64c242016-03-08 11:31:49 +05302167 ret = wmi_unified_dfs_phyerr_filter_offload_en_cmd(wma_handle->wmi_handle,
2168 wma_handle->dfs_phyerr_filter_offload);
2169 if (ret)
2170 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002171
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002172
Govind Singhaa64c242016-03-08 11:31:49 +05302173 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002174}
2175
2176#if !defined(REMOVE_PKT_LOG)
2177/**
2178 * wma_pktlog_wmi_send_cmd() - send pktlog enable/disable command to target
2179 * @handle: wma handle
2180 * @params: pktlog params
2181 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302182 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002183 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302184QDF_STATUS wma_pktlog_wmi_send_cmd(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002185 struct ath_pktlog_wmi_params *params)
2186{
2187 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhaa64c242016-03-08 11:31:49 +05302188 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002189
2190 /*Check if packet log is enabled in cfg.ini */
2191 if (!cds_is_packet_log_enabled()) {
2192 WMA_LOGE("%s:pkt log is not enabled in cfg.ini", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302193 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002194 }
2195
Govind Singhaa64c242016-03-08 11:31:49 +05302196 ret = wmi_unified_pktlog_wmi_send_cmd(wma_handle->wmi_handle,
2197 params->pktlog_event,
2198 params->cmd_id);
2199 if (ret)
2200 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002201
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002202
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302203 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002204}
2205#endif /* REMOVE_PKT_LOG */
2206
2207static void wma_send_status_to_suspend_ind(tp_wma_handle wma, bool suspended)
2208{
2209 tSirReadyToSuspendInd *ready_to_suspend;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302210 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002211 cds_msg_t cds_msg;
2212 uint8_t len;
2213
2214 WMA_LOGD("Posting ready to suspend indication to umac");
2215
2216 len = sizeof(tSirReadyToSuspendInd);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302217 ready_to_suspend = (tSirReadyToSuspendInd *) qdf_mem_malloc(len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002218
2219 if (NULL == ready_to_suspend) {
2220 WMA_LOGE("%s: Memory allocation failure", __func__);
2221 return;
2222 }
2223
2224 ready_to_suspend->mesgType = eWNI_SME_READY_TO_SUSPEND_IND;
2225 ready_to_suspend->mesgLen = len;
2226 ready_to_suspend->suspended = suspended;
2227
2228 cds_msg.type = eWNI_SME_READY_TO_SUSPEND_IND;
2229 cds_msg.bodyptr = (void *)ready_to_suspend;
2230 cds_msg.bodyval = 0;
2231
2232 status = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302233 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002234 WMA_LOGE("Failed to post ready to suspend");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302235 qdf_mem_free(ready_to_suspend);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002236 }
2237}
2238
2239/**
2240 * wma_wow_wake_reason_str() - Converts wow wakeup reason code to text format
2241 * @wake_reason - WOW wake reason
2242 *
2243 * Return: reason code in string format
2244 */
2245static const u8 *wma_wow_wake_reason_str(A_INT32 wake_reason)
2246{
2247 switch (wake_reason) {
2248 case WOW_REASON_UNSPECIFIED:
2249 return "UNSPECIFIED";
2250 case WOW_REASON_NLOD:
2251 return "NLOD";
2252 case WOW_REASON_AP_ASSOC_LOST:
2253 return "AP_ASSOC_LOST";
2254 case WOW_REASON_LOW_RSSI:
2255 return "LOW_RSSI";
2256 case WOW_REASON_DEAUTH_RECVD:
2257 return "DEAUTH_RECVD";
2258 case WOW_REASON_DISASSOC_RECVD:
2259 return "DISASSOC_RECVD";
2260 case WOW_REASON_GTK_HS_ERR:
2261 return "GTK_HS_ERR";
2262 case WOW_REASON_EAP_REQ:
2263 return "EAP_REQ";
2264 case WOW_REASON_FOURWAY_HS_RECV:
2265 return "FOURWAY_HS_RECV";
2266 case WOW_REASON_TIMER_INTR_RECV:
2267 return "TIMER_INTR_RECV";
2268 case WOW_REASON_PATTERN_MATCH_FOUND:
2269 return "PATTERN_MATCH_FOUND";
2270 case WOW_REASON_RECV_MAGIC_PATTERN:
2271 return "RECV_MAGIC_PATTERN";
2272 case WOW_REASON_P2P_DISC:
2273 return "P2P_DISC";
2274#ifdef FEATURE_WLAN_LPHB
2275 case WOW_REASON_WLAN_HB:
2276 return "WLAN_HB";
2277#endif /* FEATURE_WLAN_LPHB */
2278
2279 case WOW_REASON_CSA_EVENT:
2280 return "CSA_EVENT";
2281 case WOW_REASON_PROBE_REQ_WPS_IE_RECV:
2282 return "PROBE_REQ_RECV";
2283 case WOW_REASON_AUTH_REQ_RECV:
2284 return "AUTH_REQ_RECV";
2285 case WOW_REASON_ASSOC_REQ_RECV:
2286 return "ASSOC_REQ_RECV";
2287 case WOW_REASON_HTT_EVENT:
2288 return "WOW_REASON_HTT_EVENT";
2289#ifdef FEATURE_WLAN_RA_FILTERING
2290 case WOW_REASON_RA_MATCH:
2291 return "WOW_REASON_RA_MATCH";
2292#endif /* FEATURE_WLAN_RA_FILTERING */
2293 case WOW_REASON_BEACON_RECV:
2294 return "WOW_REASON_IBSS_BEACON_RECV";
2295#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
2296 case WOW_REASON_HOST_AUTO_SHUTDOWN:
2297 return "WOW_REASON_HOST_AUTO_SHUTDOWN";
2298#endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
2299#ifdef WLAN_FEATURE_ROAM_OFFLOAD
2300 case WOW_REASON_ROAM_HO:
2301 return "WOW_REASON_ROAM_HO";
2302#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
2303#ifdef FEATURE_WLAN_EXTSCAN
2304 case WOW_REASON_EXTSCAN:
2305 return "WOW_REASON_EXTSCAN";
2306#endif
2307 case WOW_REASON_RSSI_BREACH_EVENT:
2308 return "WOW_REASON_RSSI_BREACH_EVENT";
Srinivas Girigowdae80cea92015-11-23 11:33:57 -08002309 case WOW_REASON_NLO_SCAN_COMPLETE:
2310 return "WOW_REASON_NLO_SCAN_COMPLETE";
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002311 }
2312 return "unknown";
2313}
2314
2315/**
2316 * wma_wow_wake_up_stats_display() - display wow wake up stats
2317 * @wma: Pointer to wma handle
2318 *
2319 * Return: none
2320 */
2321static void wma_wow_wake_up_stats_display(tp_wma_handle wma)
2322{
2323 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",
2324 wma->wow_ucast_wake_up_count,
2325 wma->wow_bcast_wake_up_count,
2326 wma->wow_ipv4_mcast_wake_up_count,
2327 wma->wow_ipv6_mcast_wake_up_count,
2328 wma->wow_ipv6_mcast_ra_stats,
2329 wma->wow_ipv6_mcast_ns_stats,
2330 wma->wow_ipv6_mcast_na_stats,
2331 wma->wow_pno_match_wake_up_count,
2332 wma->wow_pno_complete_wake_up_count,
2333 wma->wow_gscan_wake_up_count,
2334 wma->wow_low_rssi_wake_up_count,
2335 wma->wow_rssi_breach_wake_up_count);
2336
2337 return;
2338}
2339
2340/**
2341 * wma_wow_ipv6_mcast_stats() - ipv6 mcast wake up stats
2342 * @wma: Pointer to wma handle
2343 * @data: Pointer to pattern match data
2344 *
2345 * Return: none
2346 */
2347static void wma_wow_ipv6_mcast_stats(tp_wma_handle wma, uint8_t *data)
2348{
2349 static const uint8_t ipv6_mcast[] = {0x86, 0xDD};
2350
2351 if (!memcmp(ipv6_mcast, (data + WMA_ETHER_TYPE_OFFSET),
2352 sizeof(ipv6_mcast))) {
2353 if (WMA_ICMP_V6_HEADER_TYPE ==
2354 *(data + WMA_ICMP_V6_HEADER_OFFSET)) {
2355 if (WMA_ICMP_V6_RA_TYPE ==
2356 *(data + WMA_ICMP_V6_TYPE_OFFSET))
2357 wma->wow_ipv6_mcast_ra_stats++;
2358 else if (WMA_ICMP_V6_NS_TYPE ==
2359 *(data + WMA_ICMP_V6_TYPE_OFFSET))
2360 wma->wow_ipv6_mcast_ns_stats++;
2361 else if (WMA_ICMP_V6_NA_TYPE ==
2362 *(data + WMA_ICMP_V6_TYPE_OFFSET))
2363 wma->wow_ipv6_mcast_na_stats++;
2364 else
2365 WMA_LOGA("ICMP V6 type : 0x%x",
2366 *(data + WMA_ICMP_V6_TYPE_OFFSET));
2367 } else {
2368 WMA_LOGA("ICMP_V6 header 0x%x",
2369 *(data + WMA_ICMP_V6_HEADER_OFFSET));
2370 }
2371 } else {
2372 WMA_LOGA("Ethertype x%x:0x%x",
2373 *(data + WMA_ETHER_TYPE_OFFSET),
2374 *(data + WMA_ETHER_TYPE_OFFSET + 1));
2375 }
2376
2377 return;
2378}
2379
2380/**
2381 * wma_wow_wake_up_stats() - maintain wow pattern match wake up stats
2382 * @wma: Pointer to wma handle
2383 * @data: Pointer to pattern match data
2384 * @len: Pattern match data length
2385 * @event: Wake up event
2386 *
2387 * Return: none
2388 */
2389static void wma_wow_wake_up_stats(tp_wma_handle wma, uint8_t *data,
2390 int32_t len, WOW_WAKE_REASON_TYPE event)
2391{
2392 switch (event) {
2393
2394 case WOW_REASON_PATTERN_MATCH_FOUND:
2395 if (WMA_BCAST_MAC_ADDR == *data) {
2396 wma->wow_bcast_wake_up_count++;
2397 } else if (WMA_MCAST_IPV4_MAC_ADDR == *data) {
2398 wma->wow_ipv4_mcast_wake_up_count++;
2399 } else if (WMA_MCAST_IPV6_MAC_ADDR == *data) {
2400 wma->wow_ipv6_mcast_wake_up_count++;
2401 if (len > WMA_ICMP_V6_TYPE_OFFSET)
2402 wma_wow_ipv6_mcast_stats(wma, data);
2403 else
2404 WMA_LOGA("ICMP_V6 data len %d", len);
2405 } else {
2406 wma->wow_ucast_wake_up_count++;
2407 }
2408 break;
2409
2410 case WOW_REASON_RA_MATCH:
2411 wma->wow_ipv6_mcast_ra_stats++;
2412 break;
2413
2414 case WOW_REASON_NLOD:
2415 wma->wow_pno_match_wake_up_count++;
2416 break;
2417
2418 case WOW_REASON_NLO_SCAN_COMPLETE:
2419 wma->wow_pno_complete_wake_up_count++;
2420 break;
2421
2422 case WOW_REASON_LOW_RSSI:
2423 wma->wow_low_rssi_wake_up_count++;
2424 break;
2425
2426 case WOW_REASON_EXTSCAN:
2427 wma->wow_gscan_wake_up_count++;
2428 break;
2429
2430 case WOW_REASON_RSSI_BREACH_EVENT:
2431 wma->wow_rssi_breach_wake_up_count++;
2432 break;
2433
2434 default:
2435 WMA_LOGE("Unknown wake up reason");
2436 break;
2437 }
2438
2439 wma_wow_wake_up_stats_display(wma);
2440 return;
2441}
2442
2443/**
2444 * wma_wow_wakeup_host_event() - wakeup host event handler
2445 * @handle: wma handle
2446 * @event: event data
2447 * @len: buffer length
2448 *
2449 * Handler to catch wow wakeup host event. This event will have
2450 * reason why the firmware has woken the host.
2451 *
2452 * Return: 0 for success or error
2453 */
2454int wma_wow_wakeup_host_event(void *handle, uint8_t *event,
2455 uint32_t len)
2456{
2457 tp_wma_handle wma = (tp_wma_handle) handle;
2458 WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *param_buf;
2459 WOW_EVENT_INFO_fixed_param *wake_info;
2460#ifdef FEATURE_WLAN_SCAN_PNO
2461 struct wma_txrx_node *node;
2462#endif /* FEATURE_WLAN_SCAN_PNO */
2463 uint32_t wake_lock_duration = 0;
2464 uint32_t wow_buf_pkt_len = 0;
2465
2466 param_buf = (WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *) event;
2467 if (!param_buf) {
2468 WMA_LOGE("Invalid wow wakeup host event buf");
2469 return -EINVAL;
2470 }
2471
2472 wake_info = param_buf->fixed_param;
2473
2474 WMA_LOGA("WOW wakeup host event received (reason: %s(%d)) for vdev %d",
2475 wma_wow_wake_reason_str(wake_info->wake_reason),
2476 wake_info->wake_reason, wake_info->vdev_id);
2477
Anurag Chouhance0dc992016-02-16 18:18:03 +05302478 qdf_event_set(&wma->wma_resume_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002479
2480 switch (wake_info->wake_reason) {
2481 case WOW_REASON_AUTH_REQ_RECV:
2482 wake_lock_duration = WMA_AUTH_REQ_RECV_WAKE_LOCK_TIMEOUT;
2483 break;
2484
2485 case WOW_REASON_ASSOC_REQ_RECV:
2486 wake_lock_duration = WMA_ASSOC_REQ_RECV_WAKE_LOCK_DURATION;
2487 break;
2488
2489 case WOW_REASON_DEAUTH_RECVD:
2490 wake_lock_duration = WMA_DEAUTH_RECV_WAKE_LOCK_DURATION;
2491 break;
2492
2493 case WOW_REASON_DISASSOC_RECVD:
2494 wake_lock_duration = WMA_DISASSOC_RECV_WAKE_LOCK_DURATION;
2495 break;
2496
2497 case WOW_REASON_AP_ASSOC_LOST:
2498 wake_lock_duration = WMA_BMISS_EVENT_WAKE_LOCK_DURATION;
2499 WMA_LOGA("Beacon miss indication on vdev %x",
2500 wake_info->vdev_id);
2501 wma_beacon_miss_handler(wma, wake_info->vdev_id);
2502 break;
2503#ifdef FEATURE_WLAN_RA_FILTERING
2504 case WOW_REASON_RA_MATCH:
2505 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_RA_MATCH);
2506 break;
2507#endif /* FEATURE_WLAN_RA_FILTERING */
2508#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
2509 case WOW_REASON_HOST_AUTO_SHUTDOWN:
2510 wake_lock_duration = WMA_AUTO_SHUTDOWN_WAKE_LOCK_DURATION;
2511 WMA_LOGA("Received WOW Auto Shutdown trigger in suspend");
2512 if (wma_post_auto_shutdown_msg())
2513 return -EINVAL;
2514 break;
2515#endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
2516#ifdef FEATURE_WLAN_SCAN_PNO
2517 case WOW_REASON_NLOD:
2518 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_NLOD);
2519 node = &wma->interfaces[wake_info->vdev_id];
2520 if (node) {
2521 WMA_LOGD("NLO match happened");
2522 node->nlo_match_evt_received = true;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302523 qdf_wake_lock_timeout_acquire(&wma->pno_wake_lock,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002524 WMA_PNO_MATCH_WAKE_LOCK_TIMEOUT,
2525 WIFI_POWER_EVENT_WAKELOCK_PNO);
Srinivas Girigowdae80cea92015-11-23 11:33:57 -08002526 }
2527 break;
2528
2529 case WOW_REASON_NLO_SCAN_COMPLETE:
2530 {
2531 WMI_NLO_SCAN_COMPLETE_EVENTID_param_tlvs param;
2532
2533 WMA_LOGD("Host woken up due to pno scan complete reason");
2534
2535 /* First 4-bytes of wow_packet_buffer is the length */
2536 if (param_buf->wow_packet_buffer) {
2537 param.fixed_param = (wmi_nlo_event *)
2538 (param_buf->wow_packet_buffer + 4);
2539 wma_nlo_scan_cmp_evt_handler(handle,
2540 (u_int8_t *)&param, sizeof(param));
2541 } else
2542 WMA_LOGD("No wow_packet_buffer present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002543 }
2544 break;
2545#endif /* FEATURE_WLAN_SCAN_PNO */
2546
2547 case WOW_REASON_CSA_EVENT:
2548 {
2549 WMI_CSA_HANDLING_EVENTID_param_tlvs param;
2550 WMA_LOGD("Host woken up because of CSA IE");
2551 param.fixed_param = (wmi_csa_event_fixed_param *)
2552 (((uint8_t *) wake_info)
2553 + sizeof(WOW_EVENT_INFO_fixed_param)
2554 + WOW_CSA_EVENT_OFFSET);
2555 wma_csa_offload_handler(handle, (uint8_t *) &param,
2556 sizeof(param));
2557 }
2558 break;
2559
2560#ifdef FEATURE_WLAN_LPHB
2561 case WOW_REASON_WLAN_HB:
2562 wma_lphb_handler(wma, (uint8_t *) param_buf->hb_indevt);
2563 break;
2564#endif /* FEATURE_WLAN_LPHB */
2565
2566 case WOW_REASON_HTT_EVENT:
2567 break;
2568 case WOW_REASON_PATTERN_MATCH_FOUND:
2569 wma_wow_wake_up_stats_display(wma);
2570 WMA_LOGD("Wake up for Rx packet, dump starting from ethernet hdr");
2571 if (param_buf->wow_packet_buffer) {
2572 /* First 4-bytes of wow_packet_buffer is the length */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302573 qdf_mem_copy((uint8_t *) &wow_buf_pkt_len,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002574 param_buf->wow_packet_buffer, 4);
2575 wma_wow_wake_up_stats(wma,
2576 param_buf->wow_packet_buffer + 4,
2577 wow_buf_pkt_len,
2578 WOW_REASON_PATTERN_MATCH_FOUND);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302579 qdf_trace_hex_dump(QDF_MODULE_ID_WMA,
2580 QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002581 param_buf->wow_packet_buffer + 4,
2582 wow_buf_pkt_len);
2583 } else {
2584 WMA_LOGE("No wow packet buffer present");
2585 }
2586 break;
2587
2588 case WOW_REASON_LOW_RSSI:
2589 {
2590 /* WOW_REASON_LOW_RSSI is used for all roaming events.
2591 * WMI_ROAM_REASON_BETTER_AP, WMI_ROAM_REASON_BMISS,
2592 * WMI_ROAM_REASON_SUITABLE_AP will be handled by
2593 * wma_roam_event_callback().
2594 */
2595 WMI_ROAM_EVENTID_param_tlvs param;
2596 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_LOW_RSSI);
2597 if (param_buf->wow_packet_buffer) {
2598 /* Roam event is embedded in wow_packet_buffer */
2599 WMA_LOGD("Host woken up because of roam event");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302600 qdf_mem_copy((uint8_t *) &wow_buf_pkt_len,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002601 param_buf->wow_packet_buffer, 4);
2602 WMA_LOGD("wow_packet_buffer dump");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302603 qdf_trace_hex_dump(QDF_MODULE_ID_WMA,
2604 QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002605 param_buf->wow_packet_buffer,
2606 wow_buf_pkt_len);
2607 if (wow_buf_pkt_len >= sizeof(param)) {
2608 param.fixed_param =
2609 (wmi_roam_event_fixed_param *)
2610 (param_buf->wow_packet_buffer + 4);
2611 wma_roam_event_callback(handle,
2612 (uint8_t *) &
2613 param,
2614 sizeof(param));
2615 } else {
2616 WMA_LOGE("Wrong length for roam event = %d bytes",
2617 wow_buf_pkt_len);
2618 }
2619 } else {
2620 /* No wow_packet_buffer means a better AP beacon
2621 * will follow in a later event.
2622 */
2623 WMA_LOGD("Host woken up because of better AP beacon");
2624 }
2625 break;
2626 }
2627 case WOW_REASON_CLIENT_KICKOUT_EVENT:
2628 {
2629 WMI_PEER_STA_KICKOUT_EVENTID_param_tlvs param;
2630 if (param_buf->wow_packet_buffer) {
2631 /* station kickout event embedded in wow_packet_buffer */
2632 WMA_LOGD("Host woken up because of sta_kickout event");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302633 qdf_mem_copy((u_int8_t *) &wow_buf_pkt_len,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002634 param_buf->wow_packet_buffer, 4);
2635 WMA_LOGD("wow_packet_buffer dump");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302636 qdf_trace_hex_dump(QDF_MODULE_ID_WMA,
2637 QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002638 param_buf->wow_packet_buffer, wow_buf_pkt_len);
2639 if (wow_buf_pkt_len >= sizeof(param)) {
2640 param.fixed_param = (wmi_peer_sta_kickout_event_fixed_param *)
2641 (param_buf->wow_packet_buffer + 4);
2642 wma_peer_sta_kickout_event_handler(handle,
2643 (u_int8_t *)&param, sizeof(param));
2644 } else {
2645 WMA_LOGE("Wrong length for sta_kickout event = %d bytes",
2646 wow_buf_pkt_len);
2647 }
2648 } else {
2649 WMA_LOGD("No wow_packet_buffer present");
2650 }
2651 break;
2652 }
2653#ifdef FEATURE_WLAN_EXTSCAN
2654 case WOW_REASON_EXTSCAN:
2655 WMA_LOGD("Host woken up because of extscan reason");
2656 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_EXTSCAN);
2657 if (param_buf->wow_packet_buffer) {
2658 wow_buf_pkt_len =
2659 *(uint32_t *)param_buf->wow_packet_buffer;
2660 wma_extscan_wow_event_callback(handle,
2661 (u_int8_t *)(param_buf->wow_packet_buffer + 4),
2662 wow_buf_pkt_len);
2663 } else
2664 WMA_LOGE("wow_packet_buffer is empty");
2665 break;
2666#endif
2667 case WOW_REASON_RSSI_BREACH_EVENT:
2668 {
2669 WMI_RSSI_BREACH_EVENTID_param_tlvs param;
2670
2671 wma_wow_wake_up_stats(wma, NULL, 0,
2672 WOW_REASON_RSSI_BREACH_EVENT);
2673 WMA_LOGD("Host woken up because of rssi breach reason");
2674 /* rssi breach event is embedded in wow_packet_buffer */
2675 if (param_buf->wow_packet_buffer) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302676 qdf_mem_copy((u_int8_t *) &wow_buf_pkt_len,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002677 param_buf->wow_packet_buffer, 4);
2678 if (wow_buf_pkt_len >= sizeof(param)) {
2679 param.fixed_param =
2680 (wmi_rssi_breach_event_fixed_param *)
2681 (param_buf->wow_packet_buffer + 4);
2682 wma_rssi_breached_event_handler(handle,
2683 (u_int8_t *)&param,
2684 sizeof(param));
2685 } else {
2686 WMA_LOGE("%s: Wrong length: %d bytes",
2687 __func__, wow_buf_pkt_len);
2688 }
2689 } else
2690 WMA_LOGD("No wow_packet_buffer present");
2691 }
2692 break;
2693 default:
2694 break;
2695 }
2696
2697 if (wake_lock_duration) {
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302698 qdf_wake_lock_timeout_acquire(&wma->wow_wake_lock,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002699 wake_lock_duration,
2700 WIFI_POWER_EVENT_WAKELOCK_WOW);
2701 WMA_LOGA("Holding %d msec wake_lock", wake_lock_duration);
2702 }
2703
2704 return 0;
2705}
2706
2707/**
2708 * wma_pdev_resume_event_handler() - PDEV resume event handler
2709 * @handle: wma handle
2710 * @event: event data
2711 * @len: buffer length
2712 *
2713 * Return: 0 for success or error
2714 */
2715int wma_pdev_resume_event_handler(void *handle, uint8_t *event, uint32_t len)
2716{
2717 tp_wma_handle wma = (tp_wma_handle) handle;
2718
2719 WMA_LOGA("Received PDEV resume event");
2720
Anurag Chouhance0dc992016-02-16 18:18:03 +05302721 qdf_event_set(&wma->wma_resume_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002722
2723 return 0;
2724}
2725/**
2726 * wma_set_wow_bus_suspend() - set suspend flag
2727 * @wma: wma handle
2728 * @val: value
2729 *
2730 * Return: none
2731 */
2732static inline void wma_set_wow_bus_suspend(tp_wma_handle wma, int val)
2733{
2734
Anurag Chouhan8e0ccd32016-02-19 15:30:20 +05302735 qdf_atomic_set(&wma->is_wow_bus_suspended, val);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002736}
2737
2738
2739
2740/**
2741 * wma_add_wow_wakeup_event() - Configures wow wakeup events.
2742 * @wma: wma handle
2743 * @vdev_id: vdev id
2744 * @bitmap: Event bitmap
2745 * @enable: enable/disable
2746 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302747 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002748 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302749static QDF_STATUS wma_add_wow_wakeup_event(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002750 uint32_t vdev_id,
2751 uint32_t bitmap,
2752 bool enable)
2753{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002754 int ret;
2755
Govind Singhaa64c242016-03-08 11:31:49 +05302756 ret = wmi_unified_add_wow_wakeup_event_cmd(wma->wmi_handle, vdev_id,
2757 enable, bitmap);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002758 if (ret) {
2759 WMA_LOGE("Failed to config wow wakeup event");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302760 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002761 }
2762
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302763 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002764}
2765
2766/**
2767 * wma_send_wow_patterns_to_fw() - Sends WOW patterns to FW.
2768 * @wma: wma handle
2769 * @vdev_id: vdev id
2770 * @ptrn_id: pattern id
2771 * @ptrn: pattern
2772 * @ptrn_len: pattern length
2773 * @ptrn_offset: pattern offset
2774 * @mask: mask
2775 * @mask_len: mask length
2776 * @user: true for user configured pattern and false for default pattern
2777 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302778 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002779 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302780static QDF_STATUS wma_send_wow_patterns_to_fw(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002781 uint8_t vdev_id, uint8_t ptrn_id,
2782 const uint8_t *ptrn, uint8_t ptrn_len,
2783 uint8_t ptrn_offset, const uint8_t *mask,
2784 uint8_t mask_len, bool user)
2785{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002786 struct wma_txrx_node *iface;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002787 int ret;
Govind Singhaa64c242016-03-08 11:31:49 +05302788 uint8_t default_patterns;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002789
2790 iface = &wma->interfaces[vdev_id];
Govind Singhaa64c242016-03-08 11:31:49 +05302791 default_patterns = iface->num_wow_default_patterns++;
2792 ret = wmi_unified_wow_patterns_to_fw_cmd(wma->wmi_handle,
2793 vdev_id, ptrn_id, ptrn,
2794 ptrn_len, ptrn_offset, mask,
2795 mask_len, user, default_patterns);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002796 if (ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002797 if (!user)
2798 iface->num_wow_default_patterns--;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302799 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002800 }
2801
2802 if (user)
2803 iface->num_wow_user_patterns++;
2804
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302805 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002806}
2807
2808/**
2809 * wma_wow_ap() - set WOW patterns in ap mode
2810 * @wma: wma handle
2811 * @vdev_id: vdev id
2812 *
2813 * Configures default WOW pattern for the given vdev_id which is in AP mode.
2814 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302815 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002816 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302817static QDF_STATUS wma_wow_ap(tp_wma_handle wma, uint8_t vdev_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002818{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302819 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002820 uint8_t arp_offset = 20;
2821 uint8_t mac_mask[IEEE80211_ADDR_LEN];
2822
2823 /* Setup unicast pkt pattern */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302824 qdf_mem_set(&mac_mask, IEEE80211_ADDR_LEN, 0xFF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002825 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
2826 wma->interfaces[vdev_id].addr,
2827 IEEE80211_ADDR_LEN, 0, mac_mask,
2828 IEEE80211_ADDR_LEN, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302829 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002830 WMA_LOGE("Failed to add WOW unicast pattern ret %d", ret);
2831 return ret;
2832 }
2833
2834 /*
2835 * Setup all ARP pkt pattern. This is dummy pattern hence the length
2836 * is zero
2837 */
2838 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
2839 arp_ptrn, 0, arp_offset, arp_mask, 0, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302840 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002841 WMA_LOGE("Failed to add WOW ARP pattern ret %d", ret);
2842 return ret;
2843 }
2844
2845 return ret;
2846}
2847
2848/**
2849 * wma_wow_sta() - set WOW patterns in sta mode
2850 * @wma: wma handle
2851 * @vdev_id: vdev id
2852 *
2853 * Configures default WOW pattern for the given vdev_id which is in sta mode.
2854 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302855 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002856 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302857static QDF_STATUS wma_wow_sta(tp_wma_handle wma, uint8_t vdev_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002858{
2859 uint8_t arp_offset = 12;
2860 uint8_t discvr_offset = 30;
2861 uint8_t mac_mask[IEEE80211_ADDR_LEN];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302862 QDF_STATUS ret = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002863
2864 /* Setup unicast pkt pattern */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302865 qdf_mem_set(&mac_mask, IEEE80211_ADDR_LEN, 0xFF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002866 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
2867 wma->interfaces[vdev_id].addr,
2868 IEEE80211_ADDR_LEN, 0, mac_mask,
2869 IEEE80211_ADDR_LEN, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302870 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002871 WMA_LOGE("Failed to add WOW unicast pattern ret %d", ret);
2872 return ret;
2873 }
2874
2875 /*
2876 * Setup multicast pattern for mDNS 224.0.0.251,
2877 * SSDP 239.255.255.250 and LLMNR 224.0.0.252
2878 */
2879 if (wma->ssdp) {
2880 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
2881 discvr_ptrn, sizeof(discvr_ptrn), discvr_offset,
2882 discvr_mask, sizeof(discvr_ptrn), false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302883 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002884 WMA_LOGE("Failed to add WOW mDNS/SSDP/LLMNR pattern");
2885 return ret;
2886 }
2887 } else
2888 WMA_LOGD("mDNS, SSDP, LLMNR patterns are disabled from ini");
2889
2890 /* when arp offload or ns offloaded is disabled
2891 * from ini file, configure broad cast arp pattern
2892 * to fw, so that host can wake up
2893 */
2894 if (!(wma->ol_ini_info & 0x1)) {
2895 /* Setup all ARP pkt pattern */
2896 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
2897 arp_ptrn, sizeof(arp_ptrn), arp_offset,
2898 arp_mask, sizeof(arp_mask), false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302899 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002900 WMA_LOGE("Failed to add WOW ARP pattern");
2901 return ret;
2902 }
2903 }
2904
2905 /* for NS or NDP offload packets */
2906 if (!(wma->ol_ini_info & 0x2)) {
2907 /* Setup all NS pkt pattern */
2908 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
2909 ns_ptrn, sizeof(arp_ptrn), arp_offset,
2910 arp_mask, sizeof(arp_mask), false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302911 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002912 WMA_LOGE("Failed to add WOW NS pattern");
2913 return ret;
2914 }
2915 }
2916
2917 return ret;
2918}
2919
2920/**
2921 * wma_register_wow_default_patterns() - register default wow patterns with fw
2922 * @handle: Pointer to wma handle
2923 * @vdev_id: vdev id
2924 *
2925 * WoW default wake up pattern rule is:
2926 * - For STA & P2P CLI mode register for same STA specific wow patterns
2927 * - For SAP/P2P GO & IBSS mode register for same SAP specific wow patterns
2928 *
2929 * Return: none
2930 */
2931void wma_register_wow_default_patterns(WMA_HANDLE handle, uint8_t vdev_id)
2932{
2933 tp_wma_handle wma = handle;
2934 struct wma_txrx_node *iface;
2935
2936 if (vdev_id > wma->max_bssid) {
2937 WMA_LOGE("Invalid vdev id %d", vdev_id);
2938 return;
2939 }
2940 iface = &wma->interfaces[vdev_id];
2941
2942 if (iface->ptrn_match_enable) {
Houston Hoffman79b4af22015-10-06 12:01:08 -07002943 if (wma_is_vdev_in_beaconning_mode(wma, vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002944 /* Configure SAP/GO/IBSS mode default wow patterns */
2945 WMA_LOGI("Config SAP specific default wow patterns vdev_id %d",
2946 vdev_id);
2947 wma_wow_ap(wma, vdev_id);
2948 } else {
2949 /* Configure STA/P2P CLI mode default wow patterns */
2950 WMA_LOGI("Config STA specific default wow patterns vdev_id %d",
2951 vdev_id);
2952 wma_wow_sta(wma, vdev_id);
2953 if (wma->IsRArateLimitEnabled) {
2954 WMA_LOGI("Config STA RA limit wow patterns vdev_id %d",
2955 vdev_id);
2956 wma_wow_sta_ra_filter(wma, vdev_id);
2957 }
2958 }
2959 }
2960
2961 return;
2962}
2963
2964/**
2965 * wma_register_wow_wakeup_events() - register vdev specific wake events with fw
2966 * @handle: Pointer to wma handle
2967 * @vdev_id: vdev Id
2968 * @vdev_type: vdev type
2969 * @vdev_subtype: vdev sub type
2970 *
2971 * WoW wake up event rule is following:
2972 * 1) STA mode and P2P CLI mode wake up events are same
2973 * 2) SAP mode and P2P GO mode wake up events are same
2974 * 3) IBSS mode wake events are same as STA mode plus WOW_BEACON_EVENT
2975 *
2976 * Return: none
2977 */
2978void wma_register_wow_wakeup_events(WMA_HANDLE handle,
2979 uint8_t vdev_id,
2980 uint8_t vdev_type,
2981 uint8_t vdev_subtype)
2982{
2983 tp_wma_handle wma = handle;
2984 uint32_t event_bitmap;
2985
2986 WMA_LOGI("vdev_type %d vdev_subtype %d vdev_id %d", vdev_type,
2987 vdev_subtype, vdev_id);
2988
2989 if ((WMI_VDEV_TYPE_STA == vdev_type) ||
2990 ((WMI_VDEV_TYPE_AP == vdev_type) &&
2991 (WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE == vdev_subtype))) {
2992 /* Configure STA/P2P CLI mode specific default wake up events */
2993 event_bitmap = WMA_WOW_STA_WAKE_UP_EVENTS;
2994 WMA_LOGI("STA specific default wake up event 0x%x vdev id %d",
2995 event_bitmap, vdev_id);
2996 } else if (WMI_VDEV_TYPE_IBSS == vdev_type) {
2997 /* Configure IBSS mode specific default wake up events */
2998 event_bitmap = (WMA_WOW_STA_WAKE_UP_EVENTS |
2999 (1 << WOW_BEACON_EVENT));
3000 WMA_LOGI("IBSS specific default wake up event 0x%x vdev id %d",
3001 event_bitmap, vdev_id);
3002 } else if (WMI_VDEV_TYPE_AP == vdev_type) {
3003 /* Configure SAP/GO mode specific default wake up events */
3004 event_bitmap = WMA_WOW_SAP_WAKE_UP_EVENTS;
3005 WMA_LOGI("SAP specific default wake up event 0x%x vdev id %d",
3006 event_bitmap, vdev_id);
3007 } else {
3008 WMA_LOGE("unknown type %d subtype %d", vdev_type, vdev_subtype);
3009 return;
3010 }
3011
3012 wma_add_wow_wakeup_event(wma, vdev_id, event_bitmap, true);
3013
3014 return;
3015}
3016
3017/**
3018 * wma_enable_disable_wakeup_event() - Configures wow wakeup events
3019 * @wma: wma handle
3020 * @vdev_id: vdev id
3021 * @bitmap: Event bitmap
3022 * @enable: enable/disable
3023 *
3024 * Return: none
3025 */
3026void wma_enable_disable_wakeup_event(WMA_HANDLE handle,
3027 uint32_t vdev_id,
3028 uint32_t bitmap,
3029 bool enable)
3030{
3031 tp_wma_handle wma = handle;
3032
3033 WMA_LOGI("vdev_id %d wake up event 0x%x enable %d",
3034 vdev_id, bitmap, enable);
3035 wma_add_wow_wakeup_event(wma, vdev_id, bitmap, enable);
3036}
3037
3038/**
3039 * wma_enable_wow_in_fw() - wnable wow in fw
3040 * @wma: wma handle
3041 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303042 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003043 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303044QDF_STATUS wma_enable_wow_in_fw(WMA_HANDLE handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003045{
3046 tp_wma_handle wma = handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003047 int ret;
Komal Seelam3d202862016-02-24 18:43:24 +05303048 struct hif_opaque_softc *scn;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003049 int host_credits;
3050 int wmi_pending_cmds;
Govind Singhd76a5b02016-03-08 15:12:14 +05303051 struct wow_cmd_params param = {0};
3052
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003053#ifdef CONFIG_CNSS
Anurag Chouhan6d760662016-02-20 16:05:43 +05303054 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003055
3056 if (NULL == pMac) {
3057 WMA_LOGE("%s: Unable to get PE context", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303058 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003059 }
3060#endif /* CONFIG_CNSS */
3061
Anurag Chouhance0dc992016-02-16 18:18:03 +05303062 qdf_event_reset(&wma->target_suspend);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003063 wma->wow_nack = 0;
3064
3065 host_credits = wmi_get_host_credits(wma->wmi_handle);
3066 wmi_pending_cmds = wmi_get_pending_cmds(wma->wmi_handle);
3067
3068 WMA_LOGD("Credits:%d; Pending_Cmds: %d",
3069 host_credits, wmi_pending_cmds);
3070
3071 if (host_credits < WMI_WOW_REQUIRED_CREDITS) {
3072 WMA_LOGE("%s: Host Doesn't have enough credits to Post WMI_WOW_ENABLE_CMDID! "
3073 "Credits:%d, pending_cmds:%d\n", __func__, host_credits,
3074 wmi_pending_cmds);
3075#ifndef QCA_WIFI_3_0_EMU
3076 goto error;
3077#endif
3078 }
3079
Govind Singhd76a5b02016-03-08 15:12:14 +05303080 param.enable = true;
3081 param.can_suspend_link = hif_can_suspend_link(wma->htc_handle);
3082 ret = wmi_unified_wow_enable_send(wma->wmi_handle, &param,
3083 WMA_WILDCARD_PDEV_ID);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003084 if (ret) {
3085 WMA_LOGE("Failed to enable wow in fw");
3086 goto error;
3087 }
3088
3089 wmi_set_target_suspend(wma->wmi_handle, true);
3090
Anurag Chouhance0dc992016-02-16 18:18:03 +05303091 if (qdf_wait_single_event(&wma->target_suspend,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003092 WMA_TGT_SUSPEND_COMPLETE_TIMEOUT)
Anurag Chouhance0dc992016-02-16 18:18:03 +05303093 != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003094 WMA_LOGE("Failed to receive WoW Enable Ack from FW");
3095 WMA_LOGE("Credits:%d; Pending_Cmds: %d",
3096 wmi_get_host_credits(wma->wmi_handle),
3097 wmi_get_pending_cmds(wma->wmi_handle));
Prashanth Bhatta9e143052015-12-04 11:56:47 -08003098 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003099#ifdef CONFIG_CNSS
Yue Ma455aff62015-10-20 18:29:16 -07003100 if (pMac->sme.enableSelfRecovery) {
3101 cds_trigger_recovery();
3102 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303103 QDF_BUG(0);
Yue Ma455aff62015-10-20 18:29:16 -07003104 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003105#else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303106 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003107#endif /* CONFIG_CNSS */
Yue Ma455aff62015-10-20 18:29:16 -07003108 } else {
3109 WMA_LOGE("%s: LOGP is in progress, ignore!", __func__);
3110 }
3111
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003112 wmi_set_target_suspend(wma->wmi_handle, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303113 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003114 }
3115
3116 if (wma->wow_nack) {
3117 WMA_LOGE("FW not ready to WOW");
3118 wmi_set_target_suspend(wma->wmi_handle, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303119 return QDF_STATUS_E_AGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003120 }
3121
3122 host_credits = wmi_get_host_credits(wma->wmi_handle);
3123 wmi_pending_cmds = wmi_get_pending_cmds(wma->wmi_handle);
3124
3125 if (host_credits < WMI_WOW_REQUIRED_CREDITS) {
3126 WMA_LOGE("%s: No Credits after HTC ACK:%d, pending_cmds:%d, "
3127 "cannot resume back", __func__, host_credits,
3128 wmi_pending_cmds);
3129 htc_dump_counter_info(wma->htc_handle);
Prashanth Bhatta9e143052015-12-04 11:56:47 -08003130 if (!cds_is_driver_recovering())
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303131 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003132 else
3133 WMA_LOGE("%s: SSR in progress, ignore no credit issue",
3134 __func__);
3135 }
3136
3137 WMA_LOGD("WOW enabled successfully in fw: credits:%d"
3138 "pending_cmds: %d", host_credits, wmi_pending_cmds);
3139
Anurag Chouhan6d760662016-02-20 16:05:43 +05303140 scn = cds_get_context(QDF_MODULE_ID_HIF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003141
3142 if (scn == NULL) {
3143 WMA_LOGE("%s: Failed to get HIF context", __func__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303144 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303145 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003146 }
3147
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003148 wma->wow.wow_enable_cmd_sent = true;
3149
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303150 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003151
3152error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303153 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003154}
3155
3156/**
3157 * wma_resume_req() - clear configured wow patterns in fw
3158 * @wma: wma handle
Houston Hoffmana76591b2015-11-10 16:52:05 -08003159 * @type: type of suspend
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003160 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303161 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003162 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05303163QDF_STATUS wma_resume_req(tp_wma_handle wma, enum qdf_suspend_type type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003164{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303165 if (type == QDF_SYSTEM_SUSPEND) {
Houston Hoffmana76591b2015-11-10 16:52:05 -08003166 wma->no_of_resume_ind++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003167
Houston Hoffmana76591b2015-11-10 16:52:05 -08003168 if (wma->no_of_resume_ind < wma_get_vdev_count(wma))
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303169 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003170
Houston Hoffmana76591b2015-11-10 16:52:05 -08003171 wma->no_of_resume_ind = 0;
3172 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003173
3174 /* Reset the DTIM Parameters */
3175 wma_set_resume_dtim(wma);
3176 /* need to reset if hif_pci_suspend_fails */
3177 wma_set_wow_bus_suspend(wma, 0);
3178 /* unpause the vdev if left paused and hif_pci_suspend fails */
3179 wma_unpause_vdev(wma);
3180
Houston Hoffman1460fa32015-11-18 02:36:30 -08003181 wmi_set_runtime_pm_inprogress(wma->wmi_handle, false);
3182
Houston Hoffmanc45db892015-11-13 19:59:25 -08003183 if (type == QDF_RUNTIME_SUSPEND)
3184 qdf_runtime_pm_allow_suspend(wma->wma_runtime_resume_lock);
3185
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303186 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003187}
3188
3189/**
3190 * wma_wow_delete_pattern() - delete wow pattern in target
3191 * @wma: wma handle
3192 * @ptrn_id: pattern id
3193 * @vdev_id: vdev id
3194 * @user: true for user pattern and false for default pattern
3195 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303196 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003197 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303198static QDF_STATUS wma_wow_delete_pattern(tp_wma_handle wma, uint8_t ptrn_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003199 uint8_t vdev_id, bool user)
3200{
Govind Singhaa64c242016-03-08 11:31:49 +05303201
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003202 struct wma_txrx_node *iface;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003203 int ret;
3204
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003205 iface = &wma->interfaces[vdev_id];
Govind Singhaa64c242016-03-08 11:31:49 +05303206 ret = wmi_unified_wow_delete_pattern_cmd(wma->wmi_handle, ptrn_id,
3207 vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003208 if (ret) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303209 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003210 }
3211
3212 if (user)
3213 iface->num_wow_user_patterns--;
3214
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303215 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003216}
3217
3218/**
3219 * wma_wow_add_pattern() - add wow pattern in target
3220 * @wma: wma handle
3221 * @ptrn: wow pattern
3222 *
3223 * This function does following:
3224 * 1) Delete all default patterns of the vdev
3225 * 2) Add received wow patterns for given vdev in target.
3226 *
3227 * Target is responsible for caching wow patterns accross multiple
3228 * suspend/resumes until the pattern is deleted by user
3229 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303230 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003231 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303232QDF_STATUS wma_wow_add_pattern(tp_wma_handle wma, struct wow_add_pattern *ptrn)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003233{
3234 uint8_t id;
3235 uint8_t bit_to_check, pos;
3236 struct wma_txrx_node *iface;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303237 QDF_STATUS ret = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003238 uint8_t new_mask[SIR_WOWL_BCAST_PATTERN_MAX_SIZE];
3239
3240 if (ptrn->session_id > wma->max_bssid) {
3241 WMA_LOGE("Invalid vdev id (%d)", ptrn->session_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303242 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003243 }
3244
3245 iface = &wma->interfaces[ptrn->session_id];
3246
3247 /* clear all default patterns cofigured by wma */
3248 for (id = 0; id < iface->num_wow_default_patterns; id++)
3249 wma_wow_delete_pattern(wma, id, ptrn->session_id, false);
3250
3251 iface->num_wow_default_patterns = 0;
3252
3253 WMA_LOGI("Add user passed wow pattern id %d vdev id %d",
3254 ptrn->pattern_id, ptrn->session_id);
3255 /*
3256 * Convert received pattern mask value from bit representation
3257 * to byte representation.
3258 *
3259 * For example, received value from umac,
3260 *
3261 * Mask value : A1 (equivalent binary is "1010 0001")
3262 * Pattern value : 12:00:13:00:00:00:00:44
3263 *
3264 * The value which goes to FW after the conversion from this
3265 * function (1 in mask value will become FF and 0 will
3266 * become 00),
3267 *
3268 * Mask value : FF:00:FF:00:0:00:00:FF
3269 * Pattern value : 12:00:13:00:00:00:00:44
3270 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303271 qdf_mem_zero(new_mask, sizeof(new_mask));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003272 for (pos = 0; pos < ptrn->pattern_size; pos++) {
3273 bit_to_check = (WMA_NUM_BITS_IN_BYTE - 1) -
3274 (pos % WMA_NUM_BITS_IN_BYTE);
3275 bit_to_check = 0x1 << bit_to_check;
3276 if (ptrn->pattern_mask[pos / WMA_NUM_BITS_IN_BYTE] &
3277 bit_to_check)
3278 new_mask[pos] = WMA_WOW_PTRN_MASK_VALID;
3279 }
3280
3281 ret = wma_send_wow_patterns_to_fw(wma, ptrn->session_id,
3282 ptrn->pattern_id,
3283 ptrn->pattern, ptrn->pattern_size,
3284 ptrn->pattern_byte_offset, new_mask,
3285 ptrn->pattern_size, true);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303286 if (ret != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003287 WMA_LOGE("Failed to add wow pattern %d", ptrn->pattern_id);
3288
3289 return ret;
3290}
3291
3292/**
3293 * wma_wow_delete_user_pattern() - delete user configured wow pattern in target
3294 * @wma: wma handle
3295 * @ptrn: wow pattern
3296 *
3297 * This function does following:
3298 * 1) Deletes a particular user configured wow pattern in target
3299 * 2) After deleting all user wow patterns add default wow patterns
3300 * specific to that vdev.
3301 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303302 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003303 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303304QDF_STATUS wma_wow_delete_user_pattern(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003305 struct wow_delete_pattern *pattern)
3306{
3307 struct wma_txrx_node *iface;
3308
3309 if (pattern->session_id > wma->max_bssid) {
3310 WMA_LOGE("Invalid vdev id %d", pattern->session_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303311 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003312 }
3313
3314 iface = &wma->interfaces[pattern->session_id];
3315 if (iface->num_wow_user_patterns <= 0) {
3316 WMA_LOGE("No valid user pattern. Num user pattern %u vdev %d",
3317 iface->num_wow_user_patterns, pattern->session_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303318 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003319 }
3320
3321 WMA_LOGI("Delete user passed wow pattern id %d total user pattern %d",
3322 pattern->pattern_id, iface->num_wow_user_patterns);
3323
3324 wma_wow_delete_pattern(wma, pattern->pattern_id,
3325 pattern->session_id, true);
3326
3327 /* configure default patterns once all user patterns are deleted */
3328 if (!iface->num_wow_user_patterns)
3329 wma_register_wow_default_patterns(wma, pattern->session_id);
3330
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303331 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003332}
3333
3334/**
3335 * wma_wow_enter() - store enable/disable status for pattern
3336 * @wma: wma handle
3337 * @info: wow parameters
3338 *
3339 * Records pattern enable/disable status locally. This choice will
3340 * take effect when the driver enter into suspend state.
3341 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303342 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003343 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303344QDF_STATUS wma_wow_enter(tp_wma_handle wma, tpSirHalWowlEnterParams info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003345{
3346 struct wma_txrx_node *iface;
3347
3348 WMA_LOGD("wow enable req received for vdev id: %d", info->sessionId);
3349
3350 if (info->sessionId > wma->max_bssid) {
3351 WMA_LOGE("Invalid vdev id (%d)", info->sessionId);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303352 qdf_mem_free(info);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303353 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003354 }
3355
3356 iface = &wma->interfaces[info->sessionId];
3357 iface->ptrn_match_enable = info->ucPatternFilteringEnable ?
3358 true : false;
3359 wma->wow.magic_ptrn_enable = info->ucMagicPktEnable ? true : false;
3360 wma->wow.deauth_enable = info->ucWowDeauthRcv ? true : false;
3361 wma->wow.disassoc_enable = info->ucWowDeauthRcv ? true : false;
3362 wma->wow.bmiss_enable = info->ucWowMaxMissedBeacons ? true : false;
3363
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303364 qdf_mem_free(info);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003365
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303366 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003367}
3368
3369/**
3370 * wma_wow_exit() - clear all wma states
3371 * @wma: wma handle
3372 * @info: wow params
3373 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303374 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003375 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303376QDF_STATUS wma_wow_exit(tp_wma_handle wma, tpSirHalWowlExitParams info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003377{
3378 struct wma_txrx_node *iface;
3379
3380 WMA_LOGD("wow disable req received for vdev id: %d", info->sessionId);
3381
3382 if (info->sessionId > wma->max_bssid) {
3383 WMA_LOGE("Invalid vdev id (%d)", info->sessionId);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303384 qdf_mem_free(info);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303385 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003386 }
3387
3388 iface = &wma->interfaces[info->sessionId];
3389 iface->ptrn_match_enable = false;
3390 wma->wow.magic_ptrn_enable = false;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303391 qdf_mem_free(info);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003392
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303393 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003394}
3395
3396/**
Houston Hoffmana76591b2015-11-10 16:52:05 -08003397 * wma_calculate_and_update_conn_state(): calculate each interfaces conn state
3398 * @wma: validated wma handle
3399 *
3400 * Identifies any vdev that is up and not in ap mode as connected.
3401 * stores this in the interfaces conn_state varible.
3402 */
3403void wma_calculate_and_update_conn_state(tp_wma_handle wma)
3404{
3405 int i;
3406 for (i = 0; i < wma->max_bssid; i++) {
3407 wma->interfaces[i].conn_state =
3408 !!(wma->interfaces[i].vdev_up &&
3409 !wma_is_vdev_in_ap_mode(wma, i));
3410 }
3411}
3412
3413/**
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003414 * wma_update_conn_state(): synchronize wma & hdd
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003415 * @wma: wma handle
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003416 * @conn_state: boolean array to populate
3417 * @len: validation parameter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003418 *
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003419 * populate interfaces conn_state with true if the interface
3420 * is a connected client and wow will configure a pattern.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003421 */
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003422void wma_update_conn_state(tp_wma_handle wma, uint32_t conn_mask)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003423{
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003424 int i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003425 for (i = 0; i < wma->max_bssid; i++) {
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003426 if (conn_mask & (1 << i))
3427 wma->interfaces[i].conn_state = true;
3428 else
3429 wma->interfaces[i].conn_state = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003430 }
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003431
3432 if (wma->wow.magic_ptrn_enable)
3433 return;
3434
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003435 for (i = 0; i < wma->max_bssid; i++) {
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003436 if (!wma->interfaces[i].ptrn_match_enable)
3437 wma->interfaces[i].conn_state = false;
3438 }
3439}
3440
3441/**
3442 * wma_is_beaconning_vdev_up(): check if a beaconning vdev is up
3443 * @wma: wma handle
3444 *
3445 * Return TRUE if beaconning vdev is up
3446 */
3447static inline
3448bool wma_is_beaconning_vdev_up(tp_wma_handle wma)
3449{
3450 int i;
3451 for (i = 0; i < wma->max_bssid; i++) {
3452 if (wma_is_vdev_in_beaconning_mode(wma, i)
3453 && wma->interfaces[i].vdev_up)
3454 return true;
3455 }
3456 return false;
3457}
3458
3459/**
3460 * wma_support_wow_for_beaconing: wow query for beaconning
3461 * @wma: wma handle
3462 *
3463 * Need to configure wow to enable beaconning offload when
3464 * a beaconing vdev is up and beaonning offload is configured.
3465 *
3466 * Return: true if we need to enable wow for beaconning offload
3467 */
3468static inline
3469bool wma_support_wow_for_beaconing(tp_wma_handle wma)
3470{
3471 if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
3472 WMI_SERVICE_BEACON_OFFLOAD)) {
3473 if (wma_is_beaconning_vdev_up(wma))
3474 return true;
3475 }
3476 return false;
3477}
3478
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003479#ifdef FEATURE_WLAN_SCAN_PNO
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003480/**
3481 * wma_is_pnoscan_in_progress(): check if a pnoscan is in progress
3482 * @wma: wma handle
3483 * @vdev_id: vdev_id
3484 *
3485 * Return: TRUE/FALSE
3486 */
3487static inline
3488bool wma_is_pnoscan_in_progress(tp_wma_handle wma, int vdev_id)
3489{
3490 return wma->interfaces[vdev_id].pno_in_progress;
3491}
Houston Hoffman345fa402015-12-16 11:28:51 -08003492
3493/**
3494 * wma_is_pnoscan_match_found(): check if a scan match was found
3495 * @wma: wma handle
3496 * @vdev_id: vdev_id
3497 *
3498 * Return: TRUE/FALSE
3499 */
3500static inline
3501bool wma_is_pnoscan_match_found(tp_wma_handle wma, int vdev_id)
3502{
3503 return wma->interfaces[vdev_id].nlo_match_evt_received;
3504}
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003505#else
3506/**
3507 * wma_is_pnoscan_in_progress(): dummy
3508 *
Houston Hoffman345fa402015-12-16 11:28:51 -08003509 * Return: False since no pnoscan cannot be in progress
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003510 * when feature flag is not defined.
3511 */
3512bool wma_is_pnoscan_in_progress(tp_wma_handle wma, int vdev_id)
3513{
3514 return FALSE;
3515}
Houston Hoffman345fa402015-12-16 11:28:51 -08003516
3517/**
3518 * wma_is_pnoscan_match_found(): dummy
3519 * @wma: wma handle
3520 * @vdev_id: vdev_id
3521 *
3522 * Return: False since no pnoscan cannot occur
3523 * when feature flag is not defined.
3524 */
3525static inline
3526bool wma_is_pnoscan_match_found(tp_wma_handle wma, int vdev_id)
3527{
3528 return FALSE;
3529}
Houston Hoffman61667962015-12-15 20:15:41 -08003530#endif
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003531
3532#ifdef FEATURE_WLAN_EXTSCAN
3533static inline
3534/**
3535 * wma_is_extscan_in_progress(): check if an extscan is in progress
3536 * @wma: wma handle
3537 * @vdev_id: vdev_id
3538 *
3539 * Return: TRUE/FALSvE
3540 */
3541bool wma_is_extscan_in_progress(tp_wma_handle wma, int vdev_id)
3542{
3543 return wma->interfaces[vdev_id].extscan_in_progress;
3544}
3545#else
3546/**
3547 * wma_is_extscan_in_progress(): dummy
3548 *
3549 * Return: False since no extscan can be in progress
3550 * when feature flag is not defined.
3551 */
3552bool wma_is_extscan_in_progress(tp_wma_handle wma, int vdev_id)
3553{
3554 return false;
3555}
3556#endif
3557
3558/**
3559 * wma_is_wow_applicable(): should enable wow
3560 * @wma: wma handle
3561 *
3562 * Enable WOW if any one of the condition meets,
3563 * 1) Is any one of vdev in beaconning mode (in AP mode) ?
3564 * 2) Is any one of vdev in connected state (in STA mode) ?
3565 * 3) Is PNO in progress in any one of vdev ?
3566 * 4) Is Extscan in progress in any one of vdev ?
Rajeev Kumaraea89632016-02-02 18:02:32 -08003567 * If none of above conditions is true then return false
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003568 *
Rajeev Kumaraea89632016-02-02 18:02:32 -08003569 * Return: true if wma needs to configure wow false otherwise.
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003570 */
3571bool wma_is_wow_applicable(tp_wma_handle wma)
3572{
3573 int vdev_id;
3574 if (wma_support_wow_for_beaconing(wma)) {
3575 WMA_LOGD("vdev is in beaconning mode, enabling wow");
3576 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003577 }
3578
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003579 for (vdev_id = 0; vdev_id < wma->max_bssid; vdev_id++) {
3580 if (wma->interfaces[vdev_id].conn_state) {
3581 WMA_LOGD("STA is connected, enabling wow");
3582 return true;
3583 } else if (wma_is_pnoscan_in_progress(wma, vdev_id)) {
3584 WMA_LOGD("PNO is in progress, enabling wow");
3585 return true;
3586 } else if (wma_is_extscan_in_progress(wma, vdev_id)) {
3587 WMA_LOGD("EXT is in progress, enabling wow");
3588 return true;
3589 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003590 }
3591
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003592 WMA_LOGD("All vdev are in disconnected state and pno/extscan is not in progress, skipping wow");
Rajeev Kumaraea89632016-02-02 18:02:32 -08003593 return false;
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003594}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003595
Houston Hoffman345fa402015-12-16 11:28:51 -08003596/**
3597 * wma_configure_dynamic_wake_events(): configure dyanmic wake events
3598 * @wma: wma handle
3599 *
3600 * Some wake events need to be enabled dynamically. Controll those here.
3601 *
3602 * Return: none
3603 */
3604void wma_configure_dynamic_wake_events(tp_wma_handle wma)
3605{
3606 int vdev_id;
3607 int enable_mask;
3608 int disable_mask;
3609
3610 for (vdev_id = 0; vdev_id < wma->max_bssid; vdev_id++) {
3611 enable_mask = 0;
3612 disable_mask = 0;
3613
3614 if (wma_is_pnoscan_in_progress(wma, vdev_id)) {
3615 if (wma_is_pnoscan_match_found(wma, vdev_id))
3616 enable_mask |=
3617 (1 << WOW_NLO_SCAN_COMPLETE_EVENT);
3618 else
3619 disable_mask |=
3620 (1 << WOW_NLO_SCAN_COMPLETE_EVENT);
3621 }
3622
3623 if (enable_mask != 0)
3624 wma_enable_disable_wakeup_event(wma, vdev_id,
3625 enable_mask, true);
3626 if (disable_mask != 0)
3627 wma_enable_disable_wakeup_event(wma, vdev_id,
3628 disable_mask, false);
3629 }
3630}
3631
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003632#ifdef FEATURE_WLAN_LPHB
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003633/**
3634 * wma_apply_lphb(): apply cached LPHB settings
3635 * @wma: wma handle
3636 *
3637 * LPHB cache, if any item was enabled, should be
3638 * applied.
3639 */
3640static inline
3641void wma_apply_lphb(tp_wma_handle wma)
3642{
3643 int i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003644 WMA_LOGD("%s: checking LPHB cache", __func__);
3645 for (i = 0; i < 2; i++) {
3646 if (wma->wow.lphb_cache[i].params.lphbEnableReq.enable) {
3647 WMA_LOGD("%s: LPHB cache for item %d is marked as enable",
3648 __func__, i + 1);
3649 wma_lphb_conf_hbenable(wma, &(wma->wow.lphb_cache[i]),
3650 false);
3651 }
3652 }
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003653}
3654#else
3655void wma_apply_lphb(tp_wma_handle wma) {}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003656#endif /* FEATURE_WLAN_LPHB */
3657
Houston Hoffmana76591b2015-11-10 16:52:05 -08003658static void wma_notify_suspend_req_procesed(tp_wma_handle wma,
Anurag Chouhan6d760662016-02-20 16:05:43 +05303659 enum qdf_suspend_type type)
Houston Hoffmana76591b2015-11-10 16:52:05 -08003660{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303661 if (type == QDF_SYSTEM_SUSPEND)
Houston Hoffmana76591b2015-11-10 16:52:05 -08003662 wma_send_status_to_suspend_ind(wma, true);
Anurag Chouhan6d760662016-02-20 16:05:43 +05303663 else if (type == QDF_RUNTIME_SUSPEND)
Anurag Chouhance0dc992016-02-16 18:18:03 +05303664 qdf_event_set(&wma->runtime_suspend);
Houston Hoffmana76591b2015-11-10 16:52:05 -08003665}
3666
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003667/**
3668 * wma_suspend_req() - Handles suspend indication request received from umac.
3669 * @wma: wma handle
Houston Hoffmana76591b2015-11-10 16:52:05 -08003670 * @type: type of suspend
3671 *
3672 * The type controlls how we notify the indicator that the indication has
3673 * been processed
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003674 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303675 * Return: QDF status
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003676 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05303677QDF_STATUS wma_suspend_req(tp_wma_handle wma, enum qdf_suspend_type type)
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003678{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303679 if (type == QDF_RUNTIME_SUSPEND)
Houston Hoffman1460fa32015-11-18 02:36:30 -08003680 wmi_set_runtime_pm_inprogress(wma->wmi_handle, true);
3681
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003682 if (wma_is_wow_applicable(wma)) {
3683 WMA_LOGE("WOW Suspend");
3684 wma_apply_lphb(wma);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003685
Houston Hoffman345fa402015-12-16 11:28:51 -08003686 wma_configure_dynamic_wake_events(wma);
3687
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003688 wma->wow.wow_enable = true;
3689 wma->wow.wow_enable_cmd_sent = false;
3690 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003691
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003692 /* Set the Suspend DTIM Parameters */
3693 wma_set_suspend_dtim(wma);
Houston Hoffmana76591b2015-11-10 16:52:05 -08003694
3695 wma_notify_suspend_req_procesed(wma, type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003696
3697 /* to handle race between hif_pci_suspend and
3698 * unpause/pause tx handler
3699 */
3700 wma_set_wow_bus_suspend(wma, 1);
3701
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303702 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003703}
3704
3705/**
3706 * wma_send_host_wakeup_ind_to_fw() - send wakeup ind to fw
3707 * @wma: wma handle
3708 *
3709 * Sends host wakeup indication to FW. On receiving this indication,
3710 * FW will come out of WOW.
3711 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303712 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003713 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303714static QDF_STATUS wma_send_host_wakeup_ind_to_fw(tp_wma_handle wma)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003715{
Anurag Chouhance0dc992016-02-16 18:18:03 +05303716 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003717 int ret;
3718#ifdef CONFIG_CNSS
Anurag Chouhan6d760662016-02-20 16:05:43 +05303719 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003720 if (NULL == pMac) {
3721 WMA_LOGE("%s: Unable to get PE context", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303722 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003723 }
3724#endif /* CONFIG_CNSS */
3725
Anurag Chouhance0dc992016-02-16 18:18:03 +05303726 qdf_event_reset(&wma->wma_resume_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003727
Govind Singhaa64c242016-03-08 11:31:49 +05303728 ret = wmi_unified_host_wakeup_ind_to_fw_cmd(wma->wmi_handle);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003729 if (ret) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303730 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003731 }
3732
3733 WMA_LOGD("Host wakeup indication sent to fw");
3734
Anurag Chouhance0dc992016-02-16 18:18:03 +05303735 qdf_status = qdf_wait_single_event(&(wma->wma_resume_event),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003736 WMA_RESUME_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05303737 if (QDF_STATUS_SUCCESS != qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003738 WMA_LOGP("%s: Timeout waiting for resume event from FW",
3739 __func__);
3740 WMA_LOGP("%s: Pending commands %d credits %d", __func__,
3741 wmi_get_pending_cmds(wma->wmi_handle),
3742 wmi_get_host_credits(wma->wmi_handle));
Prashanth Bhatta9e143052015-12-04 11:56:47 -08003743 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003744#ifdef CONFIG_CNSS
3745 if (pMac->sme.enableSelfRecovery) {
3746 cds_trigger_recovery();
3747 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303748 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003749 }
3750#else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303751 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003752#endif /* CONFIG_CNSS */
3753 } else {
3754 WMA_LOGE("%s: SSR in progress, ignore resume timeout",
3755 __func__);
3756 }
3757 } else {
3758 WMA_LOGD("Host wakeup received");
3759 }
3760
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303761 if (QDF_STATUS_SUCCESS == qdf_status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003762 wmi_set_target_suspend(wma->wmi_handle, false);
3763
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303764 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003765}
3766
3767/**
3768 * wma_disable_wow_in_fw() - Disable wow in PCIe resume context.
3769 * @handle: wma handle
3770 *
3771 * Return: 0 for success or error code
3772 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303773QDF_STATUS wma_disable_wow_in_fw(WMA_HANDLE handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003774{
3775 tp_wma_handle wma = handle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303776 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003777
3778 if (!wma->wow.wow_enable || !wma->wow.wow_enable_cmd_sent)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303779 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003780
3781 ret = wma_send_host_wakeup_ind_to_fw(wma);
3782
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303783 if (ret != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003784 return ret;
3785
3786 wma->wow.wow_enable = false;
3787 wma->wow.wow_enable_cmd_sent = false;
3788
3789 /* To allow the tx pause/unpause events */
3790 wma_set_wow_bus_suspend(wma, 0);
3791 /* Unpause the vdev as we are resuming */
3792 wma_unpause_vdev(wma);
3793
3794 return ret;
3795}
3796
3797#ifdef WLAN_FEATURE_LPSS
3798/**
3799 * wma_is_lpass_enabled() - check if lpass is enabled
3800 * @handle: Pointer to wma handle
3801 *
3802 * WoW is needed if LPASS or NaN feature is enabled in INI because
3803 * target can't wake up itself if its put in PDEV suspend when LPASS
3804 * or NaN features are supported
3805 *
3806 * Return: true if lpass is enabled else false
3807 */
3808bool static wma_is_lpass_enabled(tp_wma_handle wma)
3809{
3810 if (wma->is_lpass_enabled)
3811 return true;
3812 else
3813 return false;
3814}
3815#else
3816bool static wma_is_lpass_enabled(tp_wma_handle wma)
3817{
3818 return false;
3819}
3820#endif
3821
3822#ifdef WLAN_FEATURE_NAN
3823/**
3824 * wma_is_nan_enabled() - check if NaN is enabled
3825 * @handle: Pointer to wma handle
3826 *
3827 * WoW is needed if LPASS or NaN feature is enabled in INI because
3828 * target can't wake up itself if its put in PDEV suspend when LPASS
3829 * or NaN features are supported
3830 *
3831 * Return: true if NaN is enabled else false
3832 */
3833bool static wma_is_nan_enabled(tp_wma_handle wma)
3834{
3835 if (wma->is_nan_enabled)
3836 return true;
3837 else
3838 return false;
3839}
3840#else
3841bool static wma_is_nan_enabled(tp_wma_handle wma)
3842{
3843 return false;
3844}
3845#endif
3846
3847/**
3848 * wma_is_wow_mode_selected() - check if wow needs to be enabled in fw
3849 * @handle: Pointer to wma handle
3850 *
3851 * If lpass is enabled then always do wow else check wow_enable config
3852 *
3853 * Return: true is wow mode is needed else false
3854 */
Houston Hoffmana76591b2015-11-10 16:52:05 -08003855bool wma_is_wow_mode_selected(WMA_HANDLE handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003856{
3857 tp_wma_handle wma = (tp_wma_handle) handle;
3858
3859 if (wma_is_lpass_enabled(wma)) {
3860 WMA_LOGD("LPASS is enabled select WoW");
3861 return true;
3862 } else if (wma_is_nan_enabled(wma)) {
3863 WMA_LOGD("NAN is enabled select WoW");
3864 return true;
3865 } else {
3866 WMA_LOGD("WoW enable %d", wma->wow.wow_enable);
3867 return wma->wow.wow_enable;
3868 }
3869}
3870
3871/**
3872 * wma_del_ts_req() - send DELTS request to fw
3873 * @wma: wma handle
3874 * @msg: delts params
3875 *
3876 * Return: none
3877 */
3878void wma_del_ts_req(tp_wma_handle wma, tDelTsParams *msg)
3879{
Govind Singhaa64c242016-03-08 11:31:49 +05303880 if (wmi_unified_del_ts_cmd(wma->wmi_handle,
3881 msg->sessionId,
3882 TID_TO_WME_AC(msg->userPrio))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003883 WMA_LOGP("%s: Failed to send vdev DELTS command", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003884 }
Govind Singhaa64c242016-03-08 11:31:49 +05303885
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003886#ifdef WLAN_FEATURE_ROAM_OFFLOAD
3887 if (msg->setRICparams == true)
3888 wma_set_ric_req(wma, msg, false);
3889#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
3890
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303891 qdf_mem_free(msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003892}
3893
3894/**
3895 * wma_aggr_qos_req() - send aggr qos request to fw
3896 * @wma: handle to wma
3897 * @pAggrQosRspMsg - combined struct for all ADD_TS requests.
3898 *
3899 * A function to handle WMA_AGGR_QOS_REQ. This will send out
3900 * ADD_TS requestes to firmware in loop for all the ACs with
3901 * active flow.
3902 *
3903 * Return: none
3904 */
3905void wma_aggr_qos_req(tp_wma_handle wma,
3906 tAggrAddTsParams *pAggrQosRspMsg)
3907{
Govind Singhaa64c242016-03-08 11:31:49 +05303908 wmi_unified_aggr_qos_cmd(wma->wmi_handle,
3909 (struct aggr_add_ts_param *)pAggrQosRspMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003910 /* send reponse to upper layers from here only. */
3911 wma_send_msg(wma, WMA_AGGR_QOS_RSP, pAggrQosRspMsg, 0);
3912}
3913
3914/**
3915 * wma_add_ts_req() - send ADDTS request to fw
3916 * @wma: wma handle
3917 * @msg: ADDTS params
3918 *
3919 * Return: none
3920 */
3921void wma_add_ts_req(tp_wma_handle wma, tAddTsParams *msg)
3922{
Govind Singhaa64c242016-03-08 11:31:49 +05303923 struct add_ts_param cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003924
3925#ifdef FEATURE_WLAN_ESE
3926 /*
3927 * msmt_interval is in unit called TU (1 TU = 1024 us)
3928 * max value of msmt_interval cannot make resulting
3929 * interval_miliseconds overflow 32 bit
3930 */
3931 uint32_t intervalMiliseconds;
Anurag Chouhan6d760662016-02-20 16:05:43 +05303932 ol_txrx_pdev_handle pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003933 if (NULL == pdev) {
3934 WMA_LOGE("%s: Failed to get pdev", __func__);
3935 goto err;
3936 }
3937
3938 intervalMiliseconds = (msg->tsm_interval * 1024) / 1000;
3939
3940 ol_tx_set_compute_interval(pdev, intervalMiliseconds);
3941#endif /* FEATURE_WLAN_ESE */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303942 msg->status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003943
Govind Singhaa64c242016-03-08 11:31:49 +05303944
3945 cmd.sme_session_id = msg->sme_session_id;
3946 cmd.tspec.tsinfo.traffic.userPrio =
3947 TID_TO_WME_AC(msg->tspec.tsinfo.traffic.userPrio);
3948 cmd.tspec.mediumTime = msg->tspec.mediumTime;
3949 if (wmi_unified_add_ts_cmd(wma->wmi_handle, &cmd))
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303950 msg->status = QDF_STATUS_E_FAILURE;
Govind Singhaa64c242016-03-08 11:31:49 +05303951
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003952#ifdef WLAN_FEATURE_ROAM_OFFLOAD
3953 if (msg->setRICparams == true)
3954 wma_set_ric_req(wma, msg, true);
3955#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
3956
3957err:
3958 wma_send_msg(wma, WMA_ADD_TS_RSP, msg, 0);
3959}
3960
3961/**
3962 * wma_enable_disable_packet_filter() - enable/disable packet filter in target
3963 * @wma: Pointer to wma handle
3964 * @vdev_id: vdev id
3965 * @enable: Flag to enable/disable packet filter
3966 *
3967 * Return: 0 for success or error code
3968 */
3969static int wma_enable_disable_packet_filter(tp_wma_handle wma,
3970 uint8_t vdev_id, bool enable)
3971{
Govind Singhaa64c242016-03-08 11:31:49 +05303972 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003973
Govind Singhaa64c242016-03-08 11:31:49 +05303974 ret = wmi_unified_enable_disable_packet_filter_cmd(wma->wmi_handle,
3975 vdev_id, enable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003976 if (ret)
3977 WMA_LOGE("Failed to send packet filter wmi cmd to fw");
3978
3979 return ret;
3980}
3981
3982/**
3983 * wma_config_packet_filter() - configure packet filter in target
3984 * @wma: Pointer to wma handle
3985 * @vdev_id: vdev id
3986 * @rcv_filter_param: Packet filter parameters
3987 * @filter_id: Filter id
3988 * @enable: Flag to add/delete packet filter configuration
3989 *
3990 * Return: 0 for success or error code
3991 */
3992static int wma_config_packet_filter(tp_wma_handle wma,
3993 uint8_t vdev_id, tSirRcvPktFilterCfgType *rcv_filter_param,
3994 uint8_t filter_id, bool enable)
3995{
Govind Singhaa64c242016-03-08 11:31:49 +05303996 int err;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003997
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003998 /* send the command along with data */
Govind Singhaa64c242016-03-08 11:31:49 +05303999 err = wmi_unified_config_packet_filter_cmd(wma->wmi_handle,
4000 vdev_id, (struct rcv_pkt_filter_config *)rcv_filter_param,
4001 filter_id, enable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004002 if (err) {
4003 WMA_LOGE("Failed to send pkt_filter cmd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004004 return -EIO;
4005 }
4006
4007 /* Enable packet filter */
4008 if (enable)
4009 wma_enable_disable_packet_filter(wma, vdev_id, true);
4010
4011 return 0;
4012}
4013
4014/**
4015 * wma_process_receive_filter_set_filter_req() - enable packet filter
4016 * @wma_handle: wma handle
4017 * @rcv_filter_param: filter params
4018 *
4019 * Return: 0 for success or error code
4020 */
4021int wma_process_receive_filter_set_filter_req(tp_wma_handle wma,
4022 tSirRcvPktFilterCfgType *rcv_filter_param)
4023{
4024 int ret = 0;
4025 uint8_t vdev_id;
4026
4027 /* Get the vdev id */
Srinivas Girigowda98530492015-11-20 17:39:24 -08004028 if (!wma_find_vdev_by_bssid(wma,
4029 rcv_filter_param->bssid.bytes, &vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004030 WMA_LOGE("vdev handle is invalid for %pM",
Srinivas Girigowda98530492015-11-20 17:39:24 -08004031 rcv_filter_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004032 return -EINVAL;
4033 }
4034
4035 ret = wma_config_packet_filter(wma, vdev_id, rcv_filter_param,
4036 rcv_filter_param->filterId, true);
4037
4038 return ret;
4039}
4040
4041/**
4042 * wma_process_receive_filter_clear_filter_req() - disable packet filter
4043 * @wma_handle: wma handle
4044 * @rcv_clear_param: filter params
4045 *
4046 * Return: 0 for success or error code
4047 */
4048int wma_process_receive_filter_clear_filter_req(tp_wma_handle wma,
4049 tSirRcvFltPktClearParam *rcv_clear_param)
4050{
4051 int ret = 0;
4052 uint8_t vdev_id;
4053
4054 /* Get the vdev id */
Srinivas Girigowda98530492015-11-20 17:39:24 -08004055 if (!wma_find_vdev_by_bssid(wma,
4056 rcv_clear_param->bssid.bytes, &vdev_id)) {
4057 WMA_LOGE("vdev handle is invalid for %pM",
4058 rcv_clear_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004059 return -EINVAL;
4060 }
4061
4062 ret = wma_config_packet_filter(wma, vdev_id, NULL,
4063 rcv_clear_param->filterId, false);
4064
4065 return ret;
4066}
4067
4068#ifdef FEATURE_WLAN_ESE
4069
4070#define TSM_DELAY_HISTROGRAM_BINS 4
4071/**
4072 * wma_process_tsm_stats_req() - process tsm stats request
4073 * @wma_handler - handle to wma
4074 * @pTsmStatsMsg - TSM stats struct that needs to be populated and
4075 * passed in message.
4076 *
4077 * A parallel function to WMA_ProcessTsmStatsReq for pronto. This
4078 * function fetches stats from data path APIs and post
4079 * WMA_TSM_STATS_RSP msg back to LIM.
4080 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304081 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004082 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304083QDF_STATUS wma_process_tsm_stats_req(tp_wma_handle wma_handler,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004084 void *pTsmStatsMsg)
4085{
4086 uint8_t counter;
4087 uint32_t queue_delay_microsec = 0;
4088 uint32_t tx_delay_microsec = 0;
4089 uint16_t packet_count = 0;
4090 uint16_t packet_loss_count = 0;
4091 tpAniTrafStrmMetrics pTsmMetric = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004092 tpAniGetTsmStatsReq pStats = (tpAniGetTsmStatsReq) pTsmStatsMsg;
4093 tpAniGetTsmStatsRsp pTsmRspParams = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004094 int tid = pStats->tid;
4095 /*
4096 * The number of histrogram bin report by data path api are different
4097 * than required by TSM, hence different (6) size array used
4098 */
4099 uint16_t bin_values[QCA_TX_DELAY_HIST_REPORT_BINS] = { 0, };
4100
Anurag Chouhan6d760662016-02-20 16:05:43 +05304101 ol_txrx_pdev_handle pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004102
4103 if (NULL == pdev) {
4104 WMA_LOGE("%s: Failed to get pdev", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304105 qdf_mem_free(pTsmStatsMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304106 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004107 }
4108
4109 /* get required values from data path APIs */
4110 ol_tx_delay(pdev, &queue_delay_microsec, &tx_delay_microsec, tid);
4111 ol_tx_delay_hist(pdev, bin_values, tid);
4112 ol_tx_packet_count(pdev, &packet_count, &packet_loss_count, tid);
4113
Srinivas Girigowda515a9ef2015-12-11 11:00:48 -08004114 pTsmRspParams = qdf_mem_malloc(sizeof(*pTsmRspParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004115 if (NULL == pTsmRspParams) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304116 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304117 "%s: QDF MEM Alloc Failure", __func__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304118 QDF_ASSERT(0);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304119 qdf_mem_free(pTsmStatsMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304120 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004121 }
4122 pTsmRspParams->staId = pStats->staId;
4123 pTsmRspParams->rc = eSIR_FAILURE;
4124 pTsmRspParams->tsmStatsReq = pStats;
4125 pTsmMetric = &pTsmRspParams->tsmMetrics;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004126 /* populate pTsmMetric */
4127 pTsmMetric->UplinkPktQueueDly = queue_delay_microsec;
4128 /* store only required number of bin values */
4129 for (counter = 0; counter < TSM_DELAY_HISTROGRAM_BINS; counter++) {
4130 pTsmMetric->UplinkPktQueueDlyHist[counter] =
4131 bin_values[counter];
4132 }
4133 pTsmMetric->UplinkPktTxDly = tx_delay_microsec;
4134 pTsmMetric->UplinkPktLoss = packet_loss_count;
4135 pTsmMetric->UplinkPktCount = packet_count;
4136
4137 /*
4138 * No need to populate roaming delay and roaming count as they are
4139 * being populated just before sending IAPP frame out
4140 */
4141 /* post this message to LIM/PE */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004142 wma_send_msg(wma_handler, WMA_TSM_STATS_RSP, (void *)pTsmRspParams, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304143 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004144}
4145
4146#endif /* FEATURE_WLAN_ESE */
4147
4148/**
4149 * wma_add_clear_mcbc_filter() - set mcast filter command to fw
4150 * @wma_handle: wma handle
4151 * @vdev_id: vdev id
4152 * @multicastAddr: mcast address
4153 * @clearList: clear list flag
4154 *
4155 * Return: 0 for success or error code
4156 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304157static QDF_STATUS wma_add_clear_mcbc_filter(tp_wma_handle wma_handle,
4158 uint8_t vdev_id,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304159 struct qdf_mac_addr multicast_addr,
Srinivas Girigowda98530492015-11-20 17:39:24 -08004160 bool clearList)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004161{
Himanshu Agarwal44195412016-03-09 13:03:54 +05304162 return wmi_unified_add_clear_mcbc_filter_cmd(wma_handle->wmi_handle,
4163 vdev_id, multicast_addr, clearList);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004164}
4165
4166/**
Rajeev Kumaref96e152016-04-15 18:10:33 -07004167 * wma_config_enhance_multicast_offload() - config enhance multicast offload
4168 * @wma_handle: wma handle
4169 * @vdev_id: vdev id
4170 * @action: enable or disable enhance multicast offload
4171 *
4172 * Return: none
4173 */
4174static void wma_config_enhance_multicast_offload(tp_wma_handle wma_handle,
4175 uint8_t vdev_id,
4176 uint8_t action)
4177{
4178 int status;
4179 wmi_buf_t buf;
4180 wmi_config_enhanced_mcast_filter_cmd_fixed_param *cmd;
4181
4182 buf = wmi_buf_alloc(wma_handle->wmi_handle, sizeof(*cmd));
4183 if (!buf) {
4184 WMA_LOGE("Failed to allocate buffer to send set key cmd");
4185 return;
4186 }
4187
4188 cmd = (wmi_config_enhanced_mcast_filter_cmd_fixed_param *)
4189 wmi_buf_data(buf);
4190
4191 WMITLV_SET_HDR(&cmd->tlv_header,
4192 WMITLV_TAG_STRUC_wmi_config_enhanced_mcast_filter_fixed_param,
4193 WMITLV_GET_STRUCT_TLVLEN(wmi_config_enhanced_mcast_filter_cmd_fixed_param));
4194
4195 cmd->vdev_id = vdev_id;
4196 cmd->enable = ((0 == action) ? ENHANCED_MCAST_FILTER_DISABLED :
4197 ENHANCED_MCAST_FILTER_ENABLED);
4198
4199 WMA_LOGD("%s: config enhance multicast offload action %d for vdev %d",
4200 __func__, action, vdev_id);
4201
4202 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
4203 sizeof(*cmd), WMI_CONFIG_ENHANCED_MCAST_FILTER_CMDID);
4204 if (status) {
4205 qdf_nbuf_free(buf);
4206 WMA_LOGE("%s:Failed to send WMI_CONFIG_ENHANCED_MCAST_FILTER_CMDID",
4207 __func__);
4208 }
4209
4210 return;
4211}
4212
4213/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004214 * wma_process_mcbc_set_filter_req() - process mcbc set filter request
4215 * @wma_handle: wma handle
4216 * @mcbc_param: mcbc params
4217 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304218 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004219 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304220QDF_STATUS wma_process_mcbc_set_filter_req(tp_wma_handle wma_handle,
Anurag Chouhance0dc992016-02-16 18:18:03 +05304221 tSirRcvFltMcAddrList *mcbc_param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004222{
4223 uint8_t vdev_id = 0;
4224 int i;
4225
4226 if (mcbc_param->ulMulticastAddrCnt <= 0) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004227 WMA_LOGW("Number of multicast addresses is 0");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304228 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004229 }
4230
Srinivas Girigowda98530492015-11-20 17:39:24 -08004231 if (!wma_find_vdev_by_addr(wma_handle,
4232 mcbc_param->self_macaddr.bytes, &vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004233 WMA_LOGE("%s: Failed to find vdev id for %pM", __func__,
Srinivas Girigowda98530492015-11-20 17:39:24 -08004234 mcbc_param->bssid.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304235 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004236 }
Rajeev Kumaref96e152016-04-15 18:10:33 -07004237
4238 /*
4239 * Configure enhance multicast offload feature for filtering out
4240 * multicast IP data packets transmitted using unicast MAC address
4241 */
4242 if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap,
4243 WMI_SERVICE_ENHANCED_MCAST_FILTER)) {
4244 WMA_LOGD("%s: FW supports enhance multicast offload", __func__);
4245 wma_config_enhance_multicast_offload(wma_handle, vdev_id,
4246 mcbc_param->action);
4247 } else {
4248 WMA_LOGD("%s: FW does not support enhance multicast offload",
4249 __func__);
4250 }
4251
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004252 /* set mcbc_param->action to clear MCList and reset
4253 * to configure the MCList in FW
4254 */
4255
4256 for (i = 0; i < mcbc_param->ulMulticastAddrCnt; i++) {
4257 wma_add_clear_mcbc_filter(wma_handle, vdev_id,
4258 mcbc_param->multicastAddr[i],
4259 (mcbc_param->action == 0));
4260 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304261 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004262}
4263
4264#ifdef WLAN_FEATURE_GTK_OFFLOAD
4265#define GTK_OFFLOAD_ENABLE 0
4266#define GTK_OFFLOAD_DISABLE 1
4267
4268/**
4269 * wma_gtk_offload_status_event() - GTK offload status event handler
4270 * @handle: wma handle
4271 * @event: event buffer
4272 * @len: buffer length
4273 *
4274 * Return: 0 for success or error code
4275 */
4276int wma_gtk_offload_status_event(void *handle, uint8_t *event,
4277 uint32_t len)
4278{
4279 tp_wma_handle wma = (tp_wma_handle) handle;
4280 WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param *status;
4281 WMI_GTK_OFFLOAD_STATUS_EVENTID_param_tlvs *param_buf;
4282 tpSirGtkOffloadGetInfoRspParams resp;
4283 cds_msg_t cds_msg;
4284 uint8_t *bssid;
4285
4286 WMA_LOGD("%s Enter", __func__);
4287
4288 param_buf = (WMI_GTK_OFFLOAD_STATUS_EVENTID_param_tlvs *) event;
4289 if (!param_buf) {
4290 WMA_LOGE("param_buf is NULL");
4291 return -EINVAL;
4292 }
4293
4294 status = (WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param *) param_buf->fixed_param;
4295
4296 if (len < sizeof(WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param)) {
4297 WMA_LOGE("Invalid length for GTK status");
4298 return -EINVAL;
4299 }
4300 bssid = wma_find_bssid_by_vdev_id(wma, status->vdev_id);
4301 if (!bssid) {
4302 WMA_LOGE("invalid bssid for vdev id %d", status->vdev_id);
4303 return -ENOENT;
4304 }
4305
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304306 resp = qdf_mem_malloc(sizeof(*resp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004307 if (!resp) {
4308 WMA_LOGE("%s: Failed to alloc response", __func__);
4309 return -ENOMEM;
4310 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304311 qdf_mem_zero(resp, sizeof(*resp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004312 resp->mesgType = eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP;
4313 resp->mesgLen = sizeof(*resp);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304314 resp->ulStatus = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004315 resp->ulTotalRekeyCount = status->refresh_cnt;
4316 /* TODO: Is the total rekey count and GTK rekey count same? */
4317 resp->ulGTKRekeyCount = status->refresh_cnt;
4318
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304319 qdf_mem_copy(&resp->ullKeyReplayCounter, &status->replay_counter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004320 GTK_REPLAY_COUNTER_BYTES);
4321
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304322 qdf_mem_copy(resp->bssid.bytes, bssid, IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004323
4324#ifdef IGTK_OFFLOAD
4325 /* TODO: Is the refresh count same for GTK and IGTK? */
4326 resp->ulIGTKRekeyCount = status->refresh_cnt;
4327#endif /* IGTK_OFFLOAD */
4328
4329 cds_msg.type = eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP;
4330 cds_msg.bodyptr = (void *)resp;
4331 cds_msg.bodyval = 0;
4332
4333 if (cds_mq_post_message(CDS_MQ_ID_SME, (cds_msg_t *) &cds_msg)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304334 != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004335 WMA_LOGE("Failed to post GTK response to SME");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304336 qdf_mem_free(resp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004337 return -EINVAL;
4338 }
4339
4340 WMA_LOGD("GTK: got target status with replay counter "
4341 "%02x%02x%02x%02x%02x%02x%02x%02x. vdev %d "
4342 "Refresh GTK %d times exchanges since last set operation",
4343 status->replay_counter[0],
4344 status->replay_counter[1],
4345 status->replay_counter[2],
4346 status->replay_counter[3],
4347 status->replay_counter[4],
4348 status->replay_counter[5],
4349 status->replay_counter[6],
4350 status->replay_counter[7],
4351 status->vdev_id, status->refresh_cnt);
4352
4353 WMA_LOGD("%s Exit", __func__);
4354
4355 return 0;
4356}
4357
4358/**
4359 * wma_send_gtk_offload_req() - send GTK offload command to fw
4360 * @wma: wma handle
4361 * @vdev_id: vdev id
4362 * @params: GTK offload parameters
4363 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304364 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004365 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304366static QDF_STATUS wma_send_gtk_offload_req(tp_wma_handle wma, uint8_t vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004367 tpSirGtkOffloadParams params)
4368{
Himanshu Agarwal44195412016-03-09 13:03:54 +05304369 struct gtk_offload_params offload_params = {0};
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304370 QDF_STATUS status = QDF_STATUS_SUCCESS;
Himanshu Agarwal44195412016-03-09 13:03:54 +05304371 bool enable_offload;
4372 uint32_t gtk_offload_opcode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004373
4374 WMA_LOGD("%s Enter", __func__);
4375
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004376 /* Request target to enable GTK offload */
4377 if (params->ulFlags == GTK_OFFLOAD_ENABLE) {
Himanshu Agarwal44195412016-03-09 13:03:54 +05304378 gtk_offload_opcode = GTK_OFFLOAD_ENABLE_OPCODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004379 wma->wow.gtk_err_enable[vdev_id] = true;
4380
4381 /* Copy the keys and replay counter */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304382 qdf_mem_copy(offload_params.aKCK, params->aKCK,
4383 GTK_OFFLOAD_KCK_BYTES);
4384 qdf_mem_copy(offload_params.aKEK, params->aKEK,
4385 GTK_OFFLOAD_KEK_BYTES);
4386 qdf_mem_copy(&offload_params.ullKeyReplayCounter,
4387 &params->ullKeyReplayCounter, GTK_REPLAY_COUNTER_BYTES);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004388 } else {
4389 wma->wow.gtk_err_enable[vdev_id] = false;
Himanshu Agarwal44195412016-03-09 13:03:54 +05304390 gtk_offload_opcode = GTK_OFFLOAD_DISABLE_OPCODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004391 }
4392
Himanshu Agarwal44195412016-03-09 13:03:54 +05304393 enable_offload = params->ulFlags;
4394
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004395 /* send the wmi command */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304396 status = wmi_unified_send_gtk_offload_cmd(wma->wmi_handle,
4397 vdev_id, &offload_params,
4398 enable_offload,
4399 gtk_offload_opcode);
4400 if (QDF_IS_STATUS_ERROR(status))
4401 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004402
Himanshu Agarwal44195412016-03-09 13:03:54 +05304403 WMA_LOGD("VDEVID: %d, GTK_FLAGS: x%x", vdev_id, gtk_offload_opcode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004404out:
4405 WMA_LOGD("%s Exit", __func__);
4406 return status;
4407}
4408
4409/**
4410 * wma_process_gtk_offload_req() - process GTK offload req from umac
4411 * @handle: wma handle
4412 * @params: GTK offload params
4413 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304414 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004415 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304416QDF_STATUS wma_process_gtk_offload_req(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004417 tpSirGtkOffloadParams params)
4418{
4419 uint8_t vdev_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304420 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004421
4422 WMA_LOGD("%s Enter", __func__);
4423
4424 /* Get the vdev id */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08004425 if (!wma_find_vdev_by_bssid(wma, params->bssid.bytes, &vdev_id)) {
4426 WMA_LOGE("vdev handle is invalid for %pM", params->bssid.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304427 status = QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004428 goto out;
4429 }
4430
4431 /* Validate vdev id */
4432 if (vdev_id >= wma->max_bssid) {
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08004433 WMA_LOGE("invalid vdev_id %d for %pM", vdev_id,
4434 params->bssid.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304435 status = QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004436 goto out;
4437 }
4438
4439 if ((params->ulFlags == GTK_OFFLOAD_ENABLE) &&
4440 (wma->wow.gtk_err_enable[vdev_id] == true)) {
4441 WMA_LOGE("%s GTK Offload already enabled. Disable it first "
4442 "vdev_id %d", __func__, vdev_id);
4443 params->ulFlags = GTK_OFFLOAD_DISABLE;
4444 status = wma_send_gtk_offload_req(wma, vdev_id, params);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304445 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004446 WMA_LOGE("%s Failed to disable GTK Offload", __func__);
4447 goto out;
4448 }
4449 WMA_LOGD("%s Enable GTK Offload again with updated inputs",
4450 __func__);
4451 params->ulFlags = GTK_OFFLOAD_ENABLE;
4452 }
4453 status = wma_send_gtk_offload_req(wma, vdev_id, params);
4454out:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304455 qdf_mem_free(params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004456 WMA_LOGD("%s Exit", __func__);
4457 return status;
4458}
4459
4460/**
4461 * wma_process_gtk_offload_getinfo_req() - send GTK offload cmd to fw
4462 * @wma: wma handle
4463 * @params: GTK offload params
4464 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304465 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004466 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304467QDF_STATUS wma_process_gtk_offload_getinfo_req(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004468 tpSirGtkOffloadGetInfoRspParams params)
4469{
4470 uint8_t vdev_id;
Himanshu Agarwal44195412016-03-09 13:03:54 +05304471 uint64_t offload_req_opcode;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304472 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004473
4474 WMA_LOGD("%s Enter", __func__);
4475
4476 /* Get the vdev id */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08004477 if (!wma_find_vdev_by_bssid(wma, params->bssid.bytes, &vdev_id)) {
4478 WMA_LOGE("vdev handle is invalid for %pM", params->bssid.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304479 status = QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004480 goto out;
4481 }
4482
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004483 /* Request for GTK offload status */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304484 offload_req_opcode = GTK_OFFLOAD_REQUEST_STATUS_OPCODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004485
4486 /* send the wmi command */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304487 status = wmi_unified_process_gtk_offload_getinfo_cmd(wma->wmi_handle,
4488 vdev_id, offload_req_opcode);
4489
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004490out:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304491 qdf_mem_free(params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004492 WMA_LOGD("%s Exit", __func__);
4493 return status;
4494}
4495#endif /* WLAN_FEATURE_GTK_OFFLOAD */
4496
4497/**
4498 * wma_enable_arp_ns_offload() - enable ARP NS offload
4499 * @wma: wma handle
4500 * @tpSirHostOffloadReq: offload request
Govind Singhaa64c242016-03-08 11:31:49 +05304501 * @arp_only: flag
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004502 *
4503 * To configure ARP NS off load data to firmware
4504 * when target goes to wow mode.
4505 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304506 * Return: QDF Status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004507 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304508QDF_STATUS wma_enable_arp_ns_offload(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004509 tpSirHostOffloadReq
Govind Singhaa64c242016-03-08 11:31:49 +05304510 pHostOffloadParams, bool arp_only)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004511{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004512 int32_t res;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004513 uint8_t vdev_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004514
4515 /* Get the vdev id */
Srinivas Girigowdab084b552015-11-24 12:39:12 -08004516 if (!wma_find_vdev_by_bssid(wma, pHostOffloadParams->bssid.bytes,
4517 &vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004518 WMA_LOGE("vdev handle is invalid for %pM",
Srinivas Girigowdab084b552015-11-24 12:39:12 -08004519 pHostOffloadParams->bssid.bytes);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304520 qdf_mem_free(pHostOffloadParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304521 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004522 }
4523
4524 if (!wma->interfaces[vdev_id].vdev_up) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004525 WMA_LOGE("vdev %d is not up skipping arp/ns offload", vdev_id);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304526 qdf_mem_free(pHostOffloadParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304527 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004528 }
4529
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004530
Govind Singhaa64c242016-03-08 11:31:49 +05304531 res = wmi_unified_enable_arp_ns_offload_cmd(wma->wmi_handle,
4532 (struct host_offload_req_param *)pHostOffloadParams,
4533 arp_only,
4534 vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004535 if (res) {
4536 WMA_LOGE("Failed to enable ARP NDP/NSffload");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304537 qdf_mem_free(pHostOffloadParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304538 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004539 }
4540
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304541 qdf_mem_free(pHostOffloadParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304542 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004543}
4544
4545/**
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08004546 * wma_process_cesium_enable_ind() - enables cesium functionality in target
4547 * @wma: wma handle
4548 *
4549 * Return: QDF status
4550 */
4551QDF_STATUS wma_process_cesium_enable_ind(tp_wma_handle wma)
4552{
4553 QDF_STATUS ret;
4554 int32_t vdev_id;
4555
4556 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
4557 if (vdev_id < 0) {
4558 WMA_LOGE("%s: IBSS vdev does not exist could not enable cesium",
4559 __func__);
4560 return QDF_STATUS_E_FAILURE;
4561 }
4562
4563 /* Send enable cesium command to target */
4564 WMA_LOGE("Enable cesium in target for vdevId %d ", vdev_id);
4565 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
4566 WMI_VDEV_PARAM_ENABLE_RMC, 1);
4567 if (ret) {
4568 WMA_LOGE("Enable cesium failed for vdevId %d", vdev_id);
4569 return QDF_STATUS_E_FAILURE;
4570 }
4571 return QDF_STATUS_SUCCESS;
4572}
4573
4574/**
4575 * wma_process_get_peer_info_req() - sends get peer info cmd to target
4576 * @wma: wma handle
4577 * @preq: get peer info request
4578 *
4579 * Return: QDF status
4580 */
4581QDF_STATUS wma_process_get_peer_info_req
4582 (tp_wma_handle wma, tSirIbssGetPeerInfoReqParams *pReq)
4583{
4584 int32_t ret;
4585 uint8_t *p;
4586 uint16_t len;
4587 wmi_buf_t buf;
4588 int32_t vdev_id;
4589 ol_txrx_pdev_handle pdev;
4590 struct ol_txrx_peer_t *peer;
4591 uint8_t peer_mac[IEEE80211_ADDR_LEN];
4592 wmi_peer_info_req_cmd_fixed_param *p_get_peer_info_cmd;
4593 uint8_t bcast_mac[IEEE80211_ADDR_LEN] = { 0xff, 0xff, 0xff,
4594 0xff, 0xff, 0xff };
4595
4596 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
4597 if (vdev_id < 0) {
4598 WMA_LOGE("%s: IBSS vdev does not exist could not get peer info",
4599 __func__);
4600 return QDF_STATUS_E_FAILURE;
4601 }
4602
4603 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
4604 if (NULL == pdev) {
4605 WMA_LOGE("%s: Failed to get pdev context", __func__);
4606 return QDF_STATUS_E_FAILURE;
4607 }
4608
4609 if (0xFF == pReq->staIdx) {
4610 /*get info for all peers */
4611 qdf_mem_copy(peer_mac, bcast_mac, IEEE80211_ADDR_LEN);
4612 } else {
4613 /*get info for a single peer */
4614 peer = ol_txrx_peer_find_by_local_id(pdev, pReq->staIdx);
4615 if (!peer) {
4616 WMA_LOGE("%s: Failed to get peer handle using peer id %d",
4617 __func__, pReq->staIdx);
4618 return QDF_STATUS_E_FAILURE;
4619 }
4620 WMA_LOGE("%s: staIdx %d peer mac: 0x%2x:0x%2x:0x%2x:0x%2x:0x%2x:0x%2x",
4621 __func__, pReq->staIdx, peer->mac_addr.raw[0],
4622 peer->mac_addr.raw[1], peer->mac_addr.raw[2],
4623 peer->mac_addr.raw[3], peer->mac_addr.raw[4],
4624 peer->mac_addr.raw[5]);
4625 qdf_mem_copy(peer_mac, peer->mac_addr.raw, IEEE80211_ADDR_LEN);
4626 }
4627
4628 len = sizeof(wmi_peer_info_req_cmd_fixed_param);
4629 buf = wmi_buf_alloc(wma->wmi_handle, len);
4630 if (!buf) {
4631 WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__);
4632 return QDF_STATUS_E_FAILURE;
4633 }
4634
4635 p = (uint8_t *) wmi_buf_data(buf);
4636 qdf_mem_zero(p, len);
4637 p_get_peer_info_cmd = (wmi_peer_info_req_cmd_fixed_param *) p;
4638
4639 WMITLV_SET_HDR(&p_get_peer_info_cmd->tlv_header,
4640 WMITLV_TAG_STRUC_wmi_peer_info_req_cmd_fixed_param,
4641 WMITLV_GET_STRUCT_TLVLEN
4642 (wmi_peer_info_req_cmd_fixed_param));
4643
4644 p_get_peer_info_cmd->vdev_id = vdev_id;
4645 WMI_CHAR_ARRAY_TO_MAC_ADDR(peer_mac,
4646 &p_get_peer_info_cmd->peer_mac_address);
4647
4648 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
4649 WMI_PEER_INFO_REQ_CMDID);
4650
4651 WMA_LOGE("IBSS get peer info cmd sent len: %d, vdev %d"
4652 " command id: %d, status: %d", len,
4653 p_get_peer_info_cmd->vdev_id, WMI_PEER_INFO_REQ_CMDID, ret);
4654
4655 return QDF_STATUS_SUCCESS;
4656}
4657
4658/**
4659 * wma_process_tx_fail_monitor_ind() - sends tx fail monitor cmd to target
4660 * @wma: wma handle
4661 * @pReq: tx fail monitor command params
4662 *
4663 * Return: QDF status
4664 */
4665QDF_STATUS wma_process_tx_fail_monitor_ind
4666 (tp_wma_handle wma, tAniTXFailMonitorInd *pReq)
4667{
4668 QDF_STATUS ret;
4669 int32_t vdev_id;
4670
4671 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
4672 if (vdev_id < 0) {
4673 WMA_LOGE("%s: IBSS vdev does not exist could not send fast tx fail"
4674 " monitor indication message to target", __func__);
4675 return QDF_STATUS_E_FAILURE;
4676 }
4677
4678 /* Send enable cesium command to target */
4679 WMA_LOGE("send fast tx fail monitor ind cmd target for vdevId %d val %d",
4680 vdev_id, pReq->tx_fail_count);
4681
4682 if (0 == pReq->tx_fail_count) {
4683 wma->hddTxFailCb = NULL;
4684 } else {
4685 wma->hddTxFailCb = pReq->txFailIndCallback;
4686 }
4687 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
4688 WMI_VDEV_PARAM_SET_IBSS_TX_FAIL_CNT_THR,
4689 pReq->tx_fail_count);
4690 if (ret) {
4691 WMA_LOGE("tx fail monitor failed for vdevId %d", vdev_id);
4692 return QDF_STATUS_E_FAILURE;
4693 }
4694
4695 return QDF_STATUS_SUCCESS;
4696}
4697
4698/**
4699 * wma_process_rmc_enable_ind() - enables RMC functionality in target
4700 * @wma: wma handle
4701 *
4702 * Return: QDF status
4703 */
4704QDF_STATUS wma_process_rmc_enable_ind(tp_wma_handle wma)
4705{
4706 int ret;
4707 uint8_t *p;
4708 uint16_t len;
4709 wmi_buf_t buf;
4710 int32_t vdev_id;
4711 wmi_rmc_set_mode_cmd_fixed_param *p_rmc_enable_cmd;
4712
4713 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
4714 if (vdev_id < 0) {
4715 WMA_LOGE("%s: IBSS vdev does not exist could not enable RMC",
4716 __func__);
4717 return QDF_STATUS_E_FAILURE;
4718 }
4719
4720 len = sizeof(wmi_rmc_set_mode_cmd_fixed_param);
4721 buf = wmi_buf_alloc(wma->wmi_handle, len);
4722 if (!buf) {
4723 WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__);
4724 return QDF_STATUS_E_FAILURE;
4725 }
4726
4727 p = (uint8_t *) wmi_buf_data(buf);
4728 qdf_mem_zero(p, len);
4729 p_rmc_enable_cmd = (wmi_rmc_set_mode_cmd_fixed_param *) p;
4730
4731 WMITLV_SET_HDR(&p_rmc_enable_cmd->tlv_header,
4732 WMITLV_TAG_STRUC_wmi_rmc_set_mode_cmd_fixed_param,
4733 WMITLV_GET_STRUCT_TLVLEN
4734 (wmi_rmc_set_mode_cmd_fixed_param));
4735
4736 p_rmc_enable_cmd->vdev_id = vdev_id;
4737 p_rmc_enable_cmd->enable_rmc = WMI_RMC_MODE_ENABLED;
4738
4739 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
4740 WMI_RMC_SET_MODE_CMDID);
4741
4742 WMA_LOGE("Enable RMC cmd sent len: %d, vdev %d" " command id: %d,"
4743 " status: %d", len, p_rmc_enable_cmd->vdev_id,
4744 WMI_RMC_SET_MODE_CMDID, ret);
4745
4746 return QDF_STATUS_SUCCESS;
4747}
4748
4749/**
4750 * wma_process_rmc_disable_ind() - disables rmc functionality in target
4751 * @wma: wma handle
4752 *
4753 * Return: QDF status
4754 */
4755QDF_STATUS wma_process_rmc_disable_ind(tp_wma_handle wma)
4756{
4757 int ret;
4758 uint8_t *p;
4759 uint16_t len;
4760 wmi_buf_t buf;
4761 int32_t vdev_id;
4762 wmi_rmc_set_mode_cmd_fixed_param *p_rmc_disable_cmd;
4763
4764 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
4765 if (vdev_id < 0) {
4766 WMA_LOGE("%s: IBSS vdev does not exist could not disable RMC",
4767 __func__);
4768 return QDF_STATUS_E_FAILURE;
4769 }
4770
4771 len = sizeof(wmi_rmc_set_mode_cmd_fixed_param);
4772 buf = wmi_buf_alloc(wma->wmi_handle, len);
4773 if (!buf) {
4774 WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__);
4775 return QDF_STATUS_E_FAILURE;
4776 }
4777
4778 p = (uint8_t *) wmi_buf_data(buf);
4779 qdf_mem_zero(p, len);
4780 p_rmc_disable_cmd = (wmi_rmc_set_mode_cmd_fixed_param *) p;
4781
4782 WMITLV_SET_HDR(&p_rmc_disable_cmd->tlv_header,
4783 WMITLV_TAG_STRUC_wmi_rmc_set_mode_cmd_fixed_param,
4784 WMITLV_GET_STRUCT_TLVLEN
4785 (wmi_rmc_set_mode_cmd_fixed_param));
4786
4787 p_rmc_disable_cmd->vdev_id = vdev_id;
4788 p_rmc_disable_cmd->enable_rmc = WMI_RMC_MODE_DISABLED;
4789
4790 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
4791 WMI_RMC_SET_MODE_CMDID);
4792
4793 WMA_LOGE("Disable RMC cmd sent len: %d, vdev %d" " command id: %d,"
4794 " status: %d", len, p_rmc_disable_cmd->vdev_id,
4795 WMI_RMC_SET_MODE_CMDID, ret);
4796
4797 return QDF_STATUS_SUCCESS;
4798}
4799
4800/**
4801 * wma_process_rmc_action_period_ind() - sends RMC action period to target
4802 * @wma: wma handle
4803 *
4804 * Return: QDF status
4805 */
4806QDF_STATUS wma_process_rmc_action_period_ind(tp_wma_handle wma)
4807{
4808 int ret;
4809 uint8_t *p;
4810 uint16_t len;
4811 uint32_t val;
4812 wmi_buf_t buf;
4813 int32_t vdev_id;
4814 wmi_rmc_set_action_period_cmd_fixed_param *p_rmc_cmd;
4815 struct sAniSirGlobal *mac = cds_get_context(QDF_MODULE_ID_PE);
4816
4817 if (NULL == mac) {
4818 WMA_LOGE("%s: MAC mac does not exist", __func__);
4819 return QDF_STATUS_E_FAILURE;
4820 }
4821
4822 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
4823 if (vdev_id < 0) {
4824 WMA_LOGE("%s: IBSS vdev does not exist could not send"
4825 " RMC action period to target", __func__);
4826 return QDF_STATUS_E_FAILURE;
4827 }
4828
4829 len = sizeof(wmi_rmc_set_action_period_cmd_fixed_param);
4830 buf = wmi_buf_alloc(wma->wmi_handle, len);
4831 if (!buf) {
4832 WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__);
4833 return QDF_STATUS_E_FAILURE;
4834 }
4835
4836 p = (uint8_t *) wmi_buf_data(buf);
4837 qdf_mem_zero(p, len);
4838 p_rmc_cmd = (wmi_rmc_set_action_period_cmd_fixed_param *) p;
4839
4840 WMITLV_SET_HDR(&p_rmc_cmd->tlv_header,
4841 WMITLV_TAG_STRUC_wmi_rmc_set_action_period_cmd_fixed_param,
4842 WMITLV_GET_STRUCT_TLVLEN
4843 (wmi_rmc_set_action_period_cmd_fixed_param));
4844
4845 if (wlan_cfg_get_int(mac, WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY, &val)
4846 != eSIR_SUCCESS) {
4847 WMA_LOGE("Failed to get value for RMC action period using default");
4848 val = WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_STADEF;
4849 }
4850
4851 p_rmc_cmd->vdev_id = vdev_id;
4852 p_rmc_cmd->periodicity_msec = val;
4853
4854 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
4855 WMI_RMC_SET_ACTION_PERIOD_CMDID);
4856
4857 WMA_LOGE("RMC action period %d cmd sent len: %d, vdev %d"
4858 " command id: %d, status: %d", p_rmc_cmd->periodicity_msec,
4859 len, p_rmc_cmd->vdev_id, WMI_RMC_SET_ACTION_PERIOD_CMDID, ret);
4860
4861 return QDF_STATUS_SUCCESS;
4862}
4863
4864/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004865 * wma_process_add_periodic_tx_ptrn_ind - add periodic tx ptrn
4866 * @handle: wma handle
4867 * @pAddPeriodicTxPtrnParams: tx ptrn params
4868 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304869 * Retrun: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004870 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304871QDF_STATUS wma_process_add_periodic_tx_ptrn_ind(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004872 tSirAddPeriodicTxPtrn *
4873 pAddPeriodicTxPtrnParams)
4874{
4875 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Himanshu Agarwal44195412016-03-09 13:03:54 +05304876 struct periodic_tx_pattern params;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004877 uint8_t vdev_id;
Himanshu Agarwal44195412016-03-09 13:03:54 +05304878
4879 qdf_mem_set(&params, sizeof(struct periodic_tx_pattern), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004880
4881 if (!wma_handle || !wma_handle->wmi_handle) {
4882 WMA_LOGE("%s: WMA is closed, can not issue fw add pattern cmd",
4883 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304884 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004885 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004886
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004887 if (!wma_find_vdev_by_addr(wma_handle,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004888 pAddPeriodicTxPtrnParams->mac_address.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004889 &vdev_id)) {
4890 WMA_LOGE("%s: Failed to find vdev id for %pM", __func__,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004891 pAddPeriodicTxPtrnParams->mac_address.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304892 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004893 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004894
Himanshu Agarwal44195412016-03-09 13:03:54 +05304895 params.ucPtrnId = pAddPeriodicTxPtrnParams->ucPtrnId;
4896 params.ucPtrnSize = pAddPeriodicTxPtrnParams->ucPtrnSize;
4897 params.usPtrnIntervalMs = pAddPeriodicTxPtrnParams->usPtrnIntervalMs;
4898 qdf_mem_copy(&params.mac_address,
4899 &pAddPeriodicTxPtrnParams->mac_address,
4900 sizeof(struct qdf_mac_addr));
4901 qdf_mem_copy(params.ucPattern, pAddPeriodicTxPtrnParams->ucPattern,
4902 params.ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004903
Himanshu Agarwal44195412016-03-09 13:03:54 +05304904 return wmi_unified_process_add_periodic_tx_ptrn_cmd(
4905 wma_handle->wmi_handle, &params, vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004906}
4907
4908/**
4909 * wma_process_del_periodic_tx_ptrn_ind - del periodic tx ptrn
4910 * @handle: wma handle
4911 * @pDelPeriodicTxPtrnParams: tx ptrn params
4912 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304913 * Retrun: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004914 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304915QDF_STATUS wma_process_del_periodic_tx_ptrn_ind(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004916 tSirDelPeriodicTxPtrn *
4917 pDelPeriodicTxPtrnParams)
4918{
4919 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004920 uint8_t vdev_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004921
4922 if (!wma_handle || !wma_handle->wmi_handle) {
4923 WMA_LOGE("%s: WMA is closed, can not issue Del Pattern cmd",
4924 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304925 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004926 }
Himanshu Agarwal44195412016-03-09 13:03:54 +05304927
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004928 if (!wma_find_vdev_by_addr(wma_handle,
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08004929 pDelPeriodicTxPtrnParams->mac_address.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004930 &vdev_id)) {
4931 WMA_LOGE("%s: Failed to find vdev id for %pM", __func__,
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08004932 pDelPeriodicTxPtrnParams->mac_address.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304933 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004934 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004935
Himanshu Agarwal44195412016-03-09 13:03:54 +05304936 return wmi_unified_process_del_periodic_tx_ptrn_cmd(
4937 wma_handle->wmi_handle, vdev_id,
4938 pDelPeriodicTxPtrnParams->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004939}
4940
4941#ifdef WLAN_FEATURE_STATS_EXT
4942/**
4943 * wma_stats_ext_req() - request ext stats from fw
4944 * @wma_ptr: wma handle
4945 * @preq: stats ext params
4946 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304947 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004948 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304949QDF_STATUS wma_stats_ext_req(void *wma_ptr, tpStatsExtRequest preq)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004950{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004951 tp_wma_handle wma = (tp_wma_handle) wma_ptr;
Himanshu Agarwal44195412016-03-09 13:03:54 +05304952 struct stats_ext_params params = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004953
Himanshu Agarwal44195412016-03-09 13:03:54 +05304954 if (!wma) {
4955 WMA_LOGE("%s: wma handle is NULL", __func__);
4956 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004957 }
4958
Himanshu Agarwal44195412016-03-09 13:03:54 +05304959 params.vdev_id = preq->vdev_id;
4960 params.request_data_len = preq->request_data_len;
4961 qdf_mem_copy(params.request_data, preq->request_data,
4962 params.request_data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004963
Himanshu Agarwal44195412016-03-09 13:03:54 +05304964 return wmi_unified_stats_ext_req_cmd(wma->wmi_handle,
4965 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004966}
4967
4968#endif /* WLAN_FEATURE_STATS_EXT */
4969
4970#ifdef WLAN_FEATURE_EXTWOW_SUPPORT
4971/**
4972 * wma_send_status_of_ext_wow() - send ext wow status to SME
4973 * @wma: wma handle
4974 * @status: status
4975 *
4976 * Return: none
4977 */
4978static void wma_send_status_of_ext_wow(tp_wma_handle wma, bool status)
4979{
4980 tSirReadyToExtWoWInd *ready_to_extwow;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304981 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004982 cds_msg_t cds_msg;
4983 uint8_t len;
4984
4985 WMA_LOGD("Posting ready to suspend indication to umac");
4986
4987 len = sizeof(tSirReadyToExtWoWInd);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304988 ready_to_extwow = (tSirReadyToExtWoWInd *) qdf_mem_malloc(len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004989
4990 if (NULL == ready_to_extwow) {
4991 WMA_LOGE("%s: Memory allocation failure", __func__);
4992 return;
4993 }
4994
4995 ready_to_extwow->mesgType = eWNI_SME_READY_TO_EXTWOW_IND;
4996 ready_to_extwow->mesgLen = len;
4997 ready_to_extwow->status = status;
4998
4999 cds_msg.type = eWNI_SME_READY_TO_EXTWOW_IND;
5000 cds_msg.bodyptr = (void *)ready_to_extwow;
5001 cds_msg.bodyval = 0;
5002
5003 vstatus = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305004 if (vstatus != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005005 WMA_LOGE("Failed to post ready to suspend");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305006 qdf_mem_free(ready_to_extwow);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005007 }
5008}
5009
5010/**
5011 * wma_enable_ext_wow() - enable ext wow in fw
5012 * @wma: wma handle
5013 * @params: ext wow params
5014 *
5015 * Return:0 for success or error code
5016 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05305017QDF_STATUS wma_enable_ext_wow(tp_wma_handle wma, tpSirExtWoWParams params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005018{
Himanshu Agarwal44195412016-03-09 13:03:54 +05305019 struct ext_wow_params wow_params = {0};
5020 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005021
Himanshu Agarwal44195412016-03-09 13:03:54 +05305022 if (!wma) {
5023 WMA_LOGE("%s: wma handle is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305024 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005025 }
5026
Himanshu Agarwal44195412016-03-09 13:03:54 +05305027 wow_params.vdev_id = params->vdev_id;
5028 wow_params.type = (enum wmi_ext_wow_type) params->type;
5029 wow_params.wakeup_pin_num = params->wakeup_pin_num;
5030
5031 status = wmi_unified_enable_ext_wow_cmd(wma->wmi_handle,
5032 &wow_params);
5033 if (QDF_IS_STATUS_ERROR(status))
5034 return status;
5035
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005036 wma_send_status_of_ext_wow(wma, true);
Himanshu Agarwal44195412016-03-09 13:03:54 +05305037 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005038
5039}
5040
5041/**
5042 * wma_set_app_type1_params_in_fw() - set app type1 params in fw
5043 * @wma: wma handle
5044 * @appType1Params: app type1 params
5045 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305046 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005047 */
5048int wma_set_app_type1_params_in_fw(tp_wma_handle wma,
5049 tpSirAppType1Params appType1Params)
5050{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005051 int ret;
5052
Govind Singhaa64c242016-03-08 11:31:49 +05305053 ret = wmi_unified_app_type1_params_in_fw_cmd(wma->wmi_handle,
5054 (struct app_type1_params *)appType1Params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005055 if (ret) {
5056 WMA_LOGE("%s: Failed to set APP TYPE1 PARAMS", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305057 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005058 }
5059
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305060 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005061}
5062
5063/**
5064 * wma_set_app_type2_params_in_fw() - set app type2 params in fw
5065 * @wma: wma handle
5066 * @appType2Params: app type2 params
5067 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305068 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005069 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05305070QDF_STATUS wma_set_app_type2_params_in_fw(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005071 tpSirAppType2Params appType2Params)
5072{
Himanshu Agarwal44195412016-03-09 13:03:54 +05305073 struct app_type2_params params = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005074
Himanshu Agarwal44195412016-03-09 13:03:54 +05305075 if (!wma) {
5076 WMA_LOGE("%s: wma handle is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305077 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005078 }
5079
Himanshu Agarwal44195412016-03-09 13:03:54 +05305080 params.vdev_id = appType2Params->vdev_id;
5081 params.rc4_key_len = appType2Params->rc4_key_len;
5082 qdf_mem_copy(params.rc4_key, appType2Params->rc4_key, 16);
5083 params.ip_id = appType2Params->ip_id;
5084 params.ip_device_ip = appType2Params->ip_device_ip;
5085 params.ip_server_ip = appType2Params->ip_server_ip;
5086 params.tcp_src_port = appType2Params->tcp_src_port;
5087 params.tcp_dst_port = appType2Params->tcp_dst_port;
5088 params.tcp_seq = appType2Params->tcp_seq;
5089 params.tcp_ack_seq = appType2Params->tcp_ack_seq;
5090 params.keepalive_init = appType2Params->keepalive_init;
5091 params.keepalive_min = appType2Params->keepalive_min;
5092 params.keepalive_max = appType2Params->keepalive_max;
5093 params.keepalive_inc = appType2Params->keepalive_inc;
5094 params.tcp_tx_timeout_val = appType2Params->tcp_tx_timeout_val;
5095 params.tcp_rx_timeout_val = appType2Params->tcp_rx_timeout_val;
5096 qdf_mem_copy(&params.gateway_mac, &appType2Params->gateway_mac,
5097 sizeof(struct qdf_mac_addr));
5098
5099 return wmi_unified_set_app_type2_params_in_fw_cmd(wma->wmi_handle,
5100 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005101
5102}
5103#endif /* WLAN_FEATURE_EXTWOW_SUPPORT */
5104
5105#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
5106/**
5107 * wma_auto_shutdown_event_handler() - process auto shutdown timer trigger
5108 * @handle: wma handle
5109 * @event: event buffer
5110 * @len: buffer length
5111 *
5112 * Return: 0 for success or error code
5113 */
5114int wma_auto_shutdown_event_handler(void *handle, uint8_t *event,
5115 uint32_t len)
5116{
5117 wmi_host_auto_shutdown_event_fixed_param *wmi_auto_sh_evt;
5118 WMI_HOST_AUTO_SHUTDOWN_EVENTID_param_tlvs *param_buf =
5119 (WMI_HOST_AUTO_SHUTDOWN_EVENTID_param_tlvs *)
5120 event;
5121
5122 if (!param_buf || !param_buf->fixed_param) {
5123 WMA_LOGE("%s:%d: Invalid Auto shutdown timer evt", __func__,
5124 __LINE__);
5125 return -EINVAL;
5126 }
5127
5128 wmi_auto_sh_evt = param_buf->fixed_param;
5129
5130 if (wmi_auto_sh_evt->shutdown_reason
5131 != WMI_HOST_AUTO_SHUTDOWN_REASON_TIMER_EXPIRY) {
5132 WMA_LOGE("%s:%d: Invalid Auto shutdown timer evt", __func__,
5133 __LINE__);
5134 return -EINVAL;
5135 }
5136
5137 WMA_LOGD("%s:%d: Auto Shutdown Evt: %d", __func__, __LINE__,
5138 wmi_auto_sh_evt->shutdown_reason);
5139 return wma_post_auto_shutdown_msg();
5140}
5141
5142/**
5143 * wma_set_auto_shutdown_timer_req() - sets auto shutdown timer in firmware
5144 * @wma: wma handle
5145 * @auto_sh_cmd: auto shutdown timer value
5146 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305147 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005148 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305149QDF_STATUS wma_set_auto_shutdown_timer_req(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005150 tSirAutoShutdownCmdParams *
5151 auto_sh_cmd)
5152{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005153 if (auto_sh_cmd == NULL) {
5154 WMA_LOGE("%s : Invalid Autoshutdown cfg cmd", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305155 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005156 }
5157
Himanshu Agarwal44195412016-03-09 13:03:54 +05305158 return wmi_unified_set_auto_shutdown_timer_cmd(wma_handle->wmi_handle,
5159 auto_sh_cmd->timer_val);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005160}
5161#endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
5162
5163#ifdef WLAN_FEATURE_NAN
5164/**
5165 * wma_nan_req() - to send nan request to target
5166 * @wma: wma_handle
5167 * @nan_req: request data which will be non-null
5168 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305169 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005170 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305171QDF_STATUS wma_nan_req(void *wma_ptr, tpNanRequest nan_req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005172{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005173 tp_wma_handle wma_handle = (tp_wma_handle) wma_ptr;
Himanshu Agarwal44195412016-03-09 13:03:54 +05305174 struct nan_req_params params = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005175
Himanshu Agarwal44195412016-03-09 13:03:54 +05305176 if (!wma_handle) {
5177 WMA_LOGE("%s: wma handle is NULL", __func__);
5178 return QDF_STATUS_E_FAILURE;
5179 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005180 if (!nan_req) {
5181 WMA_LOGE("%s:nan req is not valid", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305182 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005183 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005184
Himanshu Agarwal44195412016-03-09 13:03:54 +05305185 params.request_data_len = nan_req->request_data_len;
5186 qdf_mem_copy(params.request_data, nan_req->request_data,
5187 params.request_data_len);
5188
5189 return wmi_unified_nan_req_cmd(wma_handle->wmi_handle,
5190 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005191}
5192#endif /* WLAN_FEATURE_NAN */
5193
5194#ifdef DHCP_SERVER_OFFLOAD
5195/**
5196 * wma_process_dhcpserver_offload() - enable DHCP server offload
5197 * @wma_handle: wma handle
5198 * @pDhcpSrvOffloadInfo: DHCP server offload info
5199 *
5200 * Return: 0 for success or error code
5201 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05305202QDF_STATUS wma_process_dhcpserver_offload(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005203 tSirDhcpSrvOffloadInfo *
5204 pDhcpSrvOffloadInfo)
5205{
Himanshu Agarwal44195412016-03-09 13:03:54 +05305206 struct dhcp_offload_info_params params = {0};
5207 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005208
Himanshu Agarwal44195412016-03-09 13:03:54 +05305209 if (!wma_handle) {
5210 WMA_LOGE("%s: wma handle is NULL", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005211 return -EIO;
5212 }
Himanshu Agarwal44195412016-03-09 13:03:54 +05305213
5214 params.vdev_id = pDhcpSrvOffloadInfo->vdev_id;
5215 params.dhcpSrvOffloadEnabled =
5216 pDhcpSrvOffloadInfo->dhcpSrvOffloadEnabled;
5217 params.dhcpClientNum = pDhcpSrvOffloadInfo->dhcpClientNum;
5218 params.dhcpSrvIP = pDhcpSrvOffloadInfo->;
5219
5220 status = wmi_unified_process_dhcpserver_offload_cmd(
5221 wma_handle->wmi_handle, &params);
5222 if (QDF_IS_STATUS_ERROR(status))
5223 return status;
5224
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005225 WMA_LOGD("Set dhcp server offload to vdevId %d",
5226 pDhcpSrvOffloadInfo->vdev_id);
Himanshu Agarwal44195412016-03-09 13:03:54 +05305227 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005228}
5229#endif /* DHCP_SERVER_OFFLOAD */
5230
5231#ifdef WLAN_FEATURE_GPIO_LED_FLASHING
5232/**
5233 * wma_set_led_flashing() - set led flashing in fw
5234 * @wma_handle: wma handle
5235 * @flashing: flashing request
5236 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305237 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005238 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305239QDF_STATUS wma_set_led_flashing(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005240 tSirLedFlashingReq *flashing)
5241{
Govind Singhaa64c242016-03-08 11:31:49 +05305242 struct flashing_req_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005243
5244 if (!wma_handle || !wma_handle->wmi_handle) {
5245 WMA_LOGE(FL("WMA is closed, can not issue cmd"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305246 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005247 }
5248 if (!flashing) {
5249 WMA_LOGE(FL("invalid parameter: flashing"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305250 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005251 }
Govind Singhaa64c242016-03-08 11:31:49 +05305252 cmd.req_id = flashing->reqId;
5253 cmd.pattern_id = flashing->pattern_id;
5254 cmd.led_x0 = flashing->led_x0;
5255 cmd.led_x1 = flashing->led_x1;
5256 status = wmi_unified_set_led_flashing_cmd(wma_handle->wmi_handle,
5257 &cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005258 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305259 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005260 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305261 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005262}
5263#endif /* WLAN_FEATURE_GPIO_LED_FLASHING */
5264
5265#ifdef FEATURE_WLAN_CH_AVOID
5266/**
5267 * wma_channel_avoid_evt_handler() - process channel to avoid event from FW.
5268 * @handle: wma handle
5269 * @event: event buffer
5270 * @len: buffer length
5271 *
5272 * Return: 0 for success or error code
5273 */
5274int wma_channel_avoid_evt_handler(void *handle, uint8_t *event,
5275 uint32_t len)
5276{
5277 wmi_avoid_freq_ranges_event_fixed_param *afr_fixed_param;
5278 wmi_avoid_freq_range_desc *afr_desc;
5279 uint32_t num_freq_ranges, freq_range_idx;
5280 tSirChAvoidIndType *sca_indication;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305281 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005282 cds_msg_t sme_msg = { 0 };
5283 WMI_WLAN_FREQ_AVOID_EVENTID_param_tlvs *param_buf =
5284 (WMI_WLAN_FREQ_AVOID_EVENTID_param_tlvs *) event;
5285
5286 if (!param_buf) {
5287 WMA_LOGE("Invalid channel avoid event buffer");
5288 return -EINVAL;
5289 }
5290
5291 afr_fixed_param = param_buf->fixed_param;
5292 if (!afr_fixed_param) {
5293 WMA_LOGE("Invalid channel avoid event fixed param buffer");
5294 return -EINVAL;
5295 }
5296
5297 num_freq_ranges =
5298 (afr_fixed_param->num_freq_ranges >
5299 SIR_CH_AVOID_MAX_RANGE) ? SIR_CH_AVOID_MAX_RANGE :
5300 afr_fixed_param->num_freq_ranges;
5301
5302 WMA_LOGD("Channel avoid event received with %d ranges",
5303 num_freq_ranges);
5304 for (freq_range_idx = 0; freq_range_idx < num_freq_ranges;
5305 freq_range_idx++) {
5306 afr_desc = (wmi_avoid_freq_range_desc *)
5307 ((void *)param_buf->avd_freq_range +
5308 freq_range_idx * sizeof(wmi_avoid_freq_range_desc));
5309
5310 WMA_LOGD("range %d: tlv id = %u, start freq = %u, end freq = %u",
5311 freq_range_idx, afr_desc->tlv_header, afr_desc->start_freq,
5312 afr_desc->end_freq);
5313 }
5314
5315 sca_indication = (tSirChAvoidIndType *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305316 qdf_mem_malloc(sizeof(tSirChAvoidIndType));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005317 if (!sca_indication) {
5318 WMA_LOGE("Invalid channel avoid indication buffer");
5319 return -EINVAL;
5320 }
5321
5322 sca_indication->avoid_range_count = num_freq_ranges;
5323 for (freq_range_idx = 0; freq_range_idx < num_freq_ranges;
5324 freq_range_idx++) {
5325 afr_desc = (wmi_avoid_freq_range_desc *)
5326 ((void *)param_buf->avd_freq_range +
5327 freq_range_idx * sizeof(wmi_avoid_freq_range_desc));
5328 sca_indication->avoid_freq_range[freq_range_idx].start_freq =
5329 afr_desc->start_freq;
5330 sca_indication->avoid_freq_range[freq_range_idx].end_freq =
5331 afr_desc->end_freq;
5332 }
5333
5334 sme_msg.type = eWNI_SME_CH_AVOID_IND;
5335 sme_msg.bodyptr = sca_indication;
5336 sme_msg.bodyval = 0;
5337
Anurag Chouhan6d760662016-02-20 16:05:43 +05305338 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305339 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005340 WMA_LOGE("Fail to post eWNI_SME_CH_AVOID_IND msg to SME");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305341 qdf_mem_free(sca_indication);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005342 return -EINVAL;
5343 }
5344
5345 return 0;
5346}
5347
5348/**
5349 * wma_process_ch_avoid_update_req() - handles channel avoid update request
5350 * @wma_handle: wma handle
5351 * @ch_avoid_update_req: channel avoid update params
5352 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305353 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005354 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305355QDF_STATUS wma_process_ch_avoid_update_req(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005356 tSirChAvoidUpdateReq *
5357 ch_avoid_update_req)
5358{
Himanshu Agarwal44195412016-03-09 13:03:54 +05305359 QDF_STATUS status;
5360 if (!wma_handle) {
5361 WMA_LOGE("%s: wma handle is NULL", __func__);
5362 return QDF_STATUS_E_FAILURE;
5363 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005364 if (ch_avoid_update_req == NULL) {
5365 WMA_LOGE("%s : ch_avoid_update_req is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305366 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005367 }
5368
5369 WMA_LOGI("%s: WMA --> WMI_CHAN_AVOID_UPDATE", __func__);
5370
Himanshu Agarwal44195412016-03-09 13:03:54 +05305371 status = wmi_unified_process_ch_avoid_update_cmd(
5372 wma_handle->wmi_handle);
5373 if (QDF_IS_STATUS_ERROR(status))
5374 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005375
5376 WMA_LOGI("%s: WMA --> WMI_CHAN_AVOID_UPDATE sent through WMI",
5377 __func__);
Himanshu Agarwal44195412016-03-09 13:03:54 +05305378 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005379}
5380#endif /* FEATURE_WLAN_CH_AVOID */
5381
5382/**
5383 * wma_set_reg_domain() - set reg domain
5384 * @clientCtxt: client context
5385 * @regId: reg id
5386 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305387 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005388 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305389QDF_STATUS wma_set_reg_domain(void *clientCtxt, v_REGDOMAIN_t regId)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005390{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305391 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005392 cds_set_reg_domain(clientCtxt, regId))
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305393 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005394
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305395 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005396}
5397
5398/**
5399 * wma_send_regdomain_info_to_fw() - send regdomain info to fw
5400 * @reg_dmn: reg domain
5401 * @regdmn2G: 2G reg domain
5402 * @regdmn5G: 5G reg domain
5403 * @ctl2G: 2G test limit
5404 * @ctl5G: 5G test limit
5405 *
5406 * Return: none
5407 */
5408void wma_send_regdomain_info_to_fw(uint32_t reg_dmn, uint16_t regdmn2G,
5409 uint16_t regdmn5G, int8_t ctl2G,
5410 int8_t ctl5G)
5411{
Anurag Chouhan6d760662016-02-20 16:05:43 +05305412 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005413 int32_t cck_mask_val = 0;
Govind Singhd76a5b02016-03-08 15:12:14 +05305414 struct pdev_params pdev_param = {0};
Himanshu Agarwal44195412016-03-09 13:03:54 +05305415 QDF_STATUS ret = QDF_STATUS_SUCCESS;
5416 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005417
5418 if (NULL == wma) {
5419 WMA_LOGE("%s: wma context is NULL", __func__);
5420 return;
5421 }
5422
Himanshu Agarwal44195412016-03-09 13:03:54 +05305423 status = wmi_unified_send_regdomain_info_to_fw_cmd(wma->wmi_handle,
5424 reg_dmn, regdmn2G, regdmn5G, ctl2G, ctl5G);
5425 if (status == QDF_STATUS_E_NOMEM)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005426 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005427
Amar Singhal76b41322015-12-09 14:39:17 -08005428 if ((((reg_dmn & ~COUNTRY_ERD_FLAG) == CTRY_JAPAN14) ||
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005429 ((reg_dmn & ~COUNTRY_ERD_FLAG) == CTRY_KOREA_ROC)) &&
5430 (true == wma->tx_chain_mask_cck))
5431 cck_mask_val = 1;
5432
5433 cck_mask_val |= (wma->self_gen_frm_pwr << 16);
Govind Singhd76a5b02016-03-08 15:12:14 +05305434 pdev_param.param_id = WMI_PDEV_PARAM_TX_CHAIN_MASK_CCK;
5435 pdev_param.param_value = cck_mask_val;
5436 ret = wmi_unified_pdev_param_send(wma->wmi_handle,
5437 &pdev_param,
5438 WMA_WILDCARD_PDEV_ID);
5439
Himanshu Agarwal44195412016-03-09 13:03:54 +05305440 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005441 WMA_LOGE("failed to set PDEV tx_chain_mask_cck %d",
5442 ret);
5443
5444 return;
5445}
5446
5447/**
Houston Hoffmana76591b2015-11-10 16:52:05 -08005448 * wma_post_runtime_resume_msg() - post the resume request
5449 * @handle: validated wma handle
5450 *
5451 * request the MC thread unpaus the vdev and set resume dtim
5452 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305453 * Return: qdf status of the mq post
Houston Hoffmana76591b2015-11-10 16:52:05 -08005454 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305455static QDF_STATUS wma_post_runtime_resume_msg(WMA_HANDLE handle)
Houston Hoffmana76591b2015-11-10 16:52:05 -08005456{
5457 cds_msg_t resume_msg;
Houston Hoffmanc45db892015-11-13 19:59:25 -08005458 QDF_STATUS status;
5459 tp_wma_handle wma = (tp_wma_handle) handle;
5460
5461 qdf_runtime_pm_prevent_suspend(wma->wma_runtime_resume_lock);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005462
5463 resume_msg.bodyptr = NULL;
5464 resume_msg.type = WMA_RUNTIME_PM_RESUME_IND;
Houston Hoffmanc45db892015-11-13 19:59:25 -08005465
5466 status = cds_mq_post_message(QDF_MODULE_ID_WMA, &resume_msg);
5467
5468 if (!QDF_IS_STATUS_SUCCESS(status)) {
5469 WMA_LOGE("Failed to post Runtime PM Resume IND to VOS");
5470 qdf_runtime_pm_allow_suspend(wma->wma_runtime_resume_lock);
5471 }
5472
5473 return status;
Houston Hoffmana76591b2015-11-10 16:52:05 -08005474}
5475
5476/**
5477 * wma_post_runtime_suspend_msg() - post the suspend request
5478 * @handle: validated wma handle
5479 *
5480 * Requests for offloads to be configured for runtime suspend
5481 * on the MC thread
5482 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305483 * Return QDF_STATUS_E_AGAIN in case of timeout or QDF_STATUS_SUCCESS
Houston Hoffmana76591b2015-11-10 16:52:05 -08005484 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305485static QDF_STATUS wma_post_runtime_suspend_msg(WMA_HANDLE handle)
Houston Hoffmana76591b2015-11-10 16:52:05 -08005486{
5487 cds_msg_t cds_msg;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305488 QDF_STATUS qdf_status;
Houston Hoffmana76591b2015-11-10 16:52:05 -08005489 tp_wma_handle wma = (tp_wma_handle) handle;
5490
Anurag Chouhance0dc992016-02-16 18:18:03 +05305491 qdf_event_reset(&wma->runtime_suspend);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005492
5493 cds_msg.bodyptr = NULL;
5494 cds_msg.type = WMA_RUNTIME_PM_SUSPEND_IND;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305495 qdf_status = cds_mq_post_message(QDF_MODULE_ID_WMA, &cds_msg);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005496
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305497 if (qdf_status != QDF_STATUS_SUCCESS)
Houston Hoffmana76591b2015-11-10 16:52:05 -08005498 goto failure;
5499
Anurag Chouhance0dc992016-02-16 18:18:03 +05305500 if (qdf_wait_single_event(&wma->runtime_suspend,
Houston Hoffmana76591b2015-11-10 16:52:05 -08005501 WMA_TGT_SUSPEND_COMPLETE_TIMEOUT) !=
Anurag Chouhance0dc992016-02-16 18:18:03 +05305502 QDF_STATUS_SUCCESS) {
Houston Hoffmana76591b2015-11-10 16:52:05 -08005503 WMA_LOGE("Failed to get runtime suspend event");
Houston Hoffmanc45db892015-11-13 19:59:25 -08005504 goto msg_timed_out;
Houston Hoffmana76591b2015-11-10 16:52:05 -08005505 }
5506
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305507 return QDF_STATUS_SUCCESS;
Houston Hoffmana76591b2015-11-10 16:52:05 -08005508
Houston Hoffmanc45db892015-11-13 19:59:25 -08005509msg_timed_out:
5510 wma_post_runtime_resume_msg(wma);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005511failure:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305512 return QDF_STATUS_E_AGAIN;
Houston Hoffmana76591b2015-11-10 16:52:05 -08005513}
5514
5515/**
5516 * __wma_bus_suspend(): handles bus suspend for wma
5517 * @type: is this suspend part of runtime suspend or system suspend?
5518 *
5519 * Bails if a scan is in progress.
5520 * Calls the appropriate handlers based on configuration and event.
5521 *
5522 * Return: 0 for success or error code
5523 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05305524static int __wma_bus_suspend(enum qdf_suspend_type type)
Houston Hoffmana76591b2015-11-10 16:52:05 -08005525{
Anurag Chouhan6d760662016-02-20 16:05:43 +05305526 WMA_HANDLE handle = cds_get_context(QDF_MODULE_ID_WMA);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005527 if (NULL == handle) {
5528 WMA_LOGE("%s: wma context is NULL", __func__);
5529 return -EFAULT;
5530 }
5531
5532 if (wma_check_scan_in_progress(handle)) {
5533 WMA_LOGE("%s: Scan in progress. Aborting suspend", __func__);
5534 return -EBUSY;
5535 }
5536
Anurag Chouhan6d760662016-02-20 16:05:43 +05305537 if (type == QDF_RUNTIME_SUSPEND) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305538 QDF_STATUS status = wma_post_runtime_suspend_msg(handle);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005539 if (status)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305540 return qdf_status_to_os_return(status);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005541 }
5542
Anurag Chouhan6d760662016-02-20 16:05:43 +05305543 if (type == QDF_SYSTEM_SUSPEND)
Houston Hoffmana76591b2015-11-10 16:52:05 -08005544 WMA_LOGE("%s: wow mode selected %d", __func__,
5545 wma_is_wow_mode_selected(handle));
5546
5547 if (wma_is_wow_mode_selected(handle)) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305548 QDF_STATUS status = wma_enable_wow_in_fw(handle);
5549 return qdf_status_to_os_return(status);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005550 }
5551
5552 return wma_suspend_target(handle, 0);
5553}
5554
5555/**
5556 * wma_runtime_suspend() - handles runtime suspend request from hdd
5557 *
5558 * Calls the appropriate handler based on configuration and event.
5559 * Last busy marking should prevent race conditions between processing
5560 * of asyncronous fw events and the running of runtime suspend.
5561 * (eg. last busy marking should guarantee that any auth requests have
5562 * been processed)
5563 * Events comming from the host are not protected, but aren't expected
5564 * to be an issue.
5565 *
5566 * Return: 0 for success or error code
5567 */
5568int wma_runtime_suspend(void)
5569{
Anurag Chouhan6d760662016-02-20 16:05:43 +05305570 return __wma_bus_suspend(QDF_RUNTIME_SUSPEND);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005571}
5572
5573/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005574 * wma_bus_suspend() - handles bus suspend request from hdd
5575 *
5576 * Calls the appropriate handler based on configuration and event
5577 *
5578 * Return: 0 for success or error code
5579 */
5580int wma_bus_suspend(void)
5581{
Houston Hoffmana76591b2015-11-10 16:52:05 -08005582
Anurag Chouhan6d760662016-02-20 16:05:43 +05305583 return __wma_bus_suspend(QDF_SYSTEM_SUSPEND);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005584}
5585
5586/**
5587 * __wma_bus_resume() - bus resume for wma
5588 *
5589 * does the part of the bus resume common to bus and system suspend
5590 *
5591 * Return: os error code.
5592 */
5593int __wma_bus_resume(WMA_HANDLE handle)
5594{
5595 bool wow_mode = wma_is_wow_mode_selected(handle);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305596 QDF_STATUS status;
Houston Hoffmana76591b2015-11-10 16:52:05 -08005597
5598 WMA_LOGE("%s: wow mode %d", __func__, wow_mode);
5599
5600 if (!wow_mode)
Rajeev Kumar9be537e2016-04-25 17:35:33 -07005601 return qdf_status_to_os_return(wma_resume_target(handle));
Houston Hoffmana76591b2015-11-10 16:52:05 -08005602
5603 status = wma_disable_wow_in_fw(handle);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305604 return qdf_status_to_os_return(status);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005605}
5606
5607/**
5608 * wma_runtime_resume() - do the runtime resume operation for wma
5609 *
5610 * Return: os error code.
5611 */
5612int wma_runtime_resume(void)
5613{
5614 int ret;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305615 QDF_STATUS status;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305616 WMA_HANDLE handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005617 if (NULL == handle) {
5618 WMA_LOGE("%s: wma context is NULL", __func__);
5619 return -EFAULT;
5620 }
5621
Houston Hoffmana76591b2015-11-10 16:52:05 -08005622 ret = __wma_bus_resume(handle);
5623 if (ret)
5624 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005625
Houston Hoffmana76591b2015-11-10 16:52:05 -08005626 status = wma_post_runtime_resume_msg(handle);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305627 return qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005628}
5629
5630/**
5631 * wma_bus_resume() - handles bus resume request from hdd
5632 * @handle: valid wma handle
5633 *
5634 * Calls the appropriate handler based on configuration
5635 *
5636 * Return: 0 for success or error code
5637 */
5638int wma_bus_resume(void)
5639{
Anurag Chouhan6d760662016-02-20 16:05:43 +05305640 WMA_HANDLE handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005641 if (NULL == handle) {
5642 WMA_LOGE("%s: wma context is NULL", __func__);
5643 return -EFAULT;
5644 }
5645
Houston Hoffmana76591b2015-11-10 16:52:05 -08005646 return __wma_bus_resume(handle);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005647}
5648
5649/**
Manjunathappa Prakash7b67e622016-04-12 15:18:45 +05305650 * wma_suspend_target_timeout() - Handles the target suspend timeout
5651 * @is_self_recovery_enabled: Is self recovery enabled or not
5652 *
5653 * Return: NONE
5654 */
5655#ifdef QCA_WIFI_3_0_ADRASTEA
5656static inline void wma_suspend_target_timeout(bool is_self_recovery_enabled)
5657{
5658 if (cds_is_driver_recovering()) {
5659 WMA_LOGE("%s: recovery is in progress, ignore!", __func__);
5660 } else {
5661 if (is_self_recovery_enabled) {
5662 cds_trigger_recovery();
5663 } else {
5664 QDF_BUG(0);
5665 }
5666 }
5667}
5668#else /* ROME chipset */
5669static inline void wma_suspend_target_timeout(bool is_self_recovery_enabled)
5670{
5671 if (cds_is_load_or_unload_in_progress() || cds_is_driver_recovering()) {
5672 WMA_LOGE("%s: Unloading/Loading/recovery is in progress, Ignore!",
5673 __func__);
5674 } else {
5675 if (is_self_recovery_enabled) {
5676 cds_trigger_recovery();
5677 } else {
5678 QDF_BUG(0);
5679 }
5680 }
5681}
5682#endif
5683
5684/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005685 * wma_suspend_target() - suspend target
5686 * @handle: wma handle
5687 * @disable_target_intr: disable target interrupt
5688 *
Govind Singhd76a5b02016-03-08 15:12:14 +05305689 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005690 */
Govind Singhd76a5b02016-03-08 15:12:14 +05305691QDF_STATUS wma_suspend_target(WMA_HANDLE handle, int disable_target_intr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005692{
5693 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Komal Seelam3d202862016-02-24 18:43:24 +05305694 struct hif_opaque_softc *scn;
Govind Singhd76a5b02016-03-08 15:12:14 +05305695 QDF_STATUS status;
5696 struct suspend_params param = {0};
5697
Anurag Chouhan6d760662016-02-20 16:05:43 +05305698 tpAniSirGlobal pmac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005699
5700 if (!wma_handle || !wma_handle->wmi_handle) {
5701 WMA_LOGE("WMA is closed. can not issue suspend cmd");
Govind Singhd76a5b02016-03-08 15:12:14 +05305702 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005703 }
Yue Mae1a85f32015-10-20 18:12:45 -07005704
Yue Mae1a85f32015-10-20 18:12:45 -07005705 if (NULL == pmac) {
5706 WMA_LOGE("%s: Unable to get PE context", __func__);
Govind Singhd76a5b02016-03-08 15:12:14 +05305707 return QDF_STATUS_E_INVAL;
Yue Mae1a85f32015-10-20 18:12:45 -07005708 }
Houston Hoffman52ec6692016-04-21 16:36:45 -07005709
Anurag Chouhance0dc992016-02-16 18:18:03 +05305710 qdf_event_reset(&wma_handle->target_suspend);
Govind Singhd76a5b02016-03-08 15:12:14 +05305711 param.disable_target_intr = disable_target_intr;
5712 status = wmi_unified_suspend_send(wma_handle->wmi_handle,
5713 &param,
5714 WMA_WILDCARD_PDEV_ID);
5715 if (QDF_IS_STATUS_ERROR(status))
5716 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005717
5718 wmi_set_target_suspend(wma_handle->wmi_handle, true);
5719
Anurag Chouhance0dc992016-02-16 18:18:03 +05305720 if (qdf_wait_single_event(&wma_handle->target_suspend,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005721 WMA_TGT_SUSPEND_COMPLETE_TIMEOUT)
Anurag Chouhance0dc992016-02-16 18:18:03 +05305722 != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005723 WMA_LOGE("Failed to get ACK from firmware for pdev suspend");
5724 wmi_set_target_suspend(wma_handle->wmi_handle, false);
Manjunathappa Prakash7b67e622016-04-12 15:18:45 +05305725 wma_suspend_target_timeout(pmac->sme.enableSelfRecovery);
Govind Singhd76a5b02016-03-08 15:12:14 +05305726 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005727 }
5728
Anurag Chouhan6d760662016-02-20 16:05:43 +05305729 scn = cds_get_context(QDF_MODULE_ID_HIF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005730
5731 if (scn == NULL) {
5732 WMA_LOGE("%s: Failed to get HIF context", __func__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305733 QDF_ASSERT(0);
Govind Singhd76a5b02016-03-08 15:12:14 +05305734 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005735 }
5736
Govind Singhd76a5b02016-03-08 15:12:14 +05305737 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005738}
5739
5740/**
5741 * wma_target_suspend_acknowledge() - update target susspend status
5742 * @context: wma context
5743 *
5744 * Return: none
5745 */
5746void wma_target_suspend_acknowledge(void *context)
5747{
Anurag Chouhan6d760662016-02-20 16:05:43 +05305748 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005749 int wow_nack = *((int *)context);
5750
5751 if (NULL == wma) {
5752 WMA_LOGE("%s: wma is NULL", __func__);
5753 return;
5754 }
5755
5756 wma->wow_nack = wow_nack;
Anurag Chouhance0dc992016-02-16 18:18:03 +05305757 qdf_event_set(&wma->target_suspend);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005758 if (wow_nack)
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305759 qdf_wake_lock_timeout_acquire(&wma->wow_wake_lock,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005760 WMA_WAKE_LOCK_TIMEOUT,
5761 WIFI_POWER_EVENT_WAKELOCK_WOW);
5762}
5763
5764/**
5765 * wma_resume_target() - resume target
5766 * @handle: wma handle
5767 *
Govind Singhd76a5b02016-03-08 15:12:14 +05305768 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005769 */
Govind Singhd76a5b02016-03-08 15:12:14 +05305770QDF_STATUS wma_resume_target(WMA_HANDLE handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005771{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005772 tp_wma_handle wma = (tp_wma_handle) handle;
Anurag Chouhance0dc992016-02-16 18:18:03 +05305773 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005774#ifdef CONFIG_CNSS
Anurag Chouhan6d760662016-02-20 16:05:43 +05305775 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005776 if (NULL == pMac) {
5777 WMA_LOGE("%s: Unable to get PE context", __func__);
Govind Singhd76a5b02016-03-08 15:12:14 +05305778 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005779 }
5780#endif /* CONFIG_CNSS */
5781
Anurag Chouhance0dc992016-02-16 18:18:03 +05305782 qdf_event_reset(&wma->wma_resume_event);
Govind Singhd76a5b02016-03-08 15:12:14 +05305783 qdf_status = wmi_unified_resume_send(wma->wmi_handle,
5784 WMA_WILDCARD_PDEV_ID);
5785 if (QDF_IS_STATUS_ERROR(qdf_status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005786 WMA_LOGE("Failed to send WMI_PDEV_RESUME_CMDID command");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005787
Anurag Chouhance0dc992016-02-16 18:18:03 +05305788 qdf_status = qdf_wait_single_event(&(wma->wma_resume_event),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005789 WMA_RESUME_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05305790 if (QDF_STATUS_SUCCESS != qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005791 WMA_LOGP("%s: Timeout waiting for resume event from FW",
5792 __func__);
5793 WMA_LOGP("%s: Pending commands %d credits %d", __func__,
5794 wmi_get_pending_cmds(wma->wmi_handle),
5795 wmi_get_host_credits(wma->wmi_handle));
Prashanth Bhatta9e143052015-12-04 11:56:47 -08005796 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005797#ifdef CONFIG_CNSS
5798 if (pMac->sme.enableSelfRecovery) {
5799 cds_trigger_recovery();
5800 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305801 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005802 }
5803#else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305804 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005805#endif /* CONFIG_CNSS */
5806 } else {
5807 WMA_LOGE("%s: SSR in progress, ignore resume timeout",
5808 __func__);
5809 }
5810 } else {
5811 WMA_LOGD("Host wakeup received");
5812 }
5813
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305814 if (QDF_STATUS_SUCCESS == qdf_status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005815 wmi_set_target_suspend(wma->wmi_handle, false);
5816
Houston Hoffman52ec6692016-04-21 16:36:45 -07005817 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005818}
5819
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005820#ifdef FEATURE_WLAN_TDLS
5821/**
5822 * wma_tdls_event_handler() - handle TDLS event
5823 * @handle: wma handle
5824 * @event: event buffer
5825 * @len: buffer length
5826 *
5827 * Return: 0 for success or error code
5828 */
5829int wma_tdls_event_handler(void *handle, uint8_t *event, uint32_t len)
5830{
5831 tp_wma_handle wma = (tp_wma_handle) handle;
5832 WMI_TDLS_PEER_EVENTID_param_tlvs *param_buf = NULL;
5833 wmi_tdls_peer_event_fixed_param *peer_event = NULL;
5834 tSirTdlsEventnotify *tdls_event;
5835
5836 if (!event) {
5837 WMA_LOGE("%s: event param null", __func__);
5838 return -EINVAL;
5839 }
5840
5841 param_buf = (WMI_TDLS_PEER_EVENTID_param_tlvs *) event;
5842 if (!param_buf) {
5843 WMA_LOGE("%s: received null buf from target", __func__);
5844 return -EINVAL;
5845 }
5846
5847 peer_event = param_buf->fixed_param;
5848 if (!peer_event) {
5849 WMA_LOGE("%s: received null event data from target", __func__);
5850 return -EINVAL;
5851 }
5852
5853 tdls_event = (tSirTdlsEventnotify *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305854 qdf_mem_malloc(sizeof(*tdls_event));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005855 if (!tdls_event) {
5856 WMA_LOGE("%s: failed to allocate memory for tdls_event",
5857 __func__);
5858 return -ENOMEM;
5859 }
5860
5861 tdls_event->sessionId = peer_event->vdev_id;
5862 WMI_MAC_ADDR_TO_CHAR_ARRAY(&peer_event->peer_macaddr,
Srinivas Girigowda4f593792015-11-19 15:33:42 -08005863 tdls_event->peermac.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005864
5865 switch (peer_event->peer_status) {
5866 case WMI_TDLS_SHOULD_DISCOVER:
5867 tdls_event->messageType = WMA_TDLS_SHOULD_DISCOVER_CMD;
5868 break;
5869 case WMI_TDLS_SHOULD_TEARDOWN:
5870 tdls_event->messageType = WMA_TDLS_SHOULD_TEARDOWN_CMD;
5871 break;
5872 case WMI_TDLS_PEER_DISCONNECTED:
5873 tdls_event->messageType = WMA_TDLS_PEER_DISCONNECTED_CMD;
5874 break;
5875 default:
5876 WMA_LOGE("%s: Discarding unknown tdls event(%d) from target",
5877 __func__, peer_event->peer_status);
5878 return -EINVAL;
5879 }
5880
5881 switch (peer_event->peer_reason) {
5882 case WMI_TDLS_TEARDOWN_REASON_TX:
5883 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_TX;
5884 break;
5885 case WMI_TDLS_TEARDOWN_REASON_RSSI:
5886 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_RSSI;
5887 break;
5888 case WMI_TDLS_TEARDOWN_REASON_SCAN:
5889 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_SCAN;
5890 break;
5891 case WMI_TDLS_DISCONNECTED_REASON_PEER_DELETE:
5892 tdls_event->peer_reason =
5893 eWNI_TDLS_DISCONNECTED_REASON_PEER_DELETE;
5894 break;
5895 case WMI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT:
5896 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT;
5897 break;
5898 case WMI_TDLS_TEARDOWN_REASON_BAD_PTR:
5899 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_BAD_PTR;
5900 break;
5901 case WMI_TDLS_TEARDOWN_REASON_NO_RESPONSE:
5902 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_NO_RESPONSE;
5903 break;
5904 default:
5905 WMA_LOGE("%s: unknown reason(%d) in tdls event(%d) from target",
5906 __func__, peer_event->peer_reason,
5907 peer_event->peer_status);
5908 return -EINVAL;
5909 }
5910
5911 WMA_LOGD("%s: sending msg to umac, messageType: 0x%x, "
5912 "for peer: %pM, reason: %d, smesessionId: %d",
Srinivas Girigowda4f593792015-11-19 15:33:42 -08005913 __func__, tdls_event->messageType, tdls_event->peermac.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005914 tdls_event->peer_reason, tdls_event->sessionId);
5915
5916 wma_send_msg(wma, tdls_event->messageType, (void *)tdls_event, 0);
5917 return 0;
5918}
5919
5920/**
5921 * wma_set_tdls_offchan_mode() - set tdls off channel mode
5922 * @handle: wma handle
5923 * @chan_switch_params: Pointer to tdls channel switch parameter structure
5924 *
5925 * This function sets tdls off channel mode
5926 *
5927 * Return: 0 on success; Negative errno otherwise
5928 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05305929QDF_STATUS wma_set_tdls_offchan_mode(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005930 tdls_chan_switch_params *chan_switch_params)
5931{
5932 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Himanshu Agarwal44195412016-03-09 13:03:54 +05305933 struct tdls_channel_switch_params params = {0};
5934 QDF_STATUS ret = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005935
5936 if (!wma_handle || !wma_handle->wmi_handle) {
5937 WMA_LOGE(FL(
5938 "WMA is closed, can not issue tdls off channel cmd"
5939 ));
5940 ret = -EINVAL;
5941 goto end;
5942 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005943
Himanshu Agarwal44195412016-03-09 13:03:54 +05305944 params.vdev_id = chan_switch_params->vdev_id;
5945 params.tdls_off_ch_bw_offset =
5946 chan_switch_params->tdls_off_ch_bw_offset;
5947 params.tdls_off_ch = chan_switch_params->tdls_off_ch;
5948 params.tdls_sw_mode = chan_switch_params->tdls_sw_mode;
5949 params.oper_class = chan_switch_params->oper_class;
5950 params.is_responder = chan_switch_params->is_responder;
5951 qdf_mem_copy(params.peer_mac_addr, chan_switch_params->peer_mac_addr,
Krunal Soniab793342016-04-22 18:43:20 -07005952 IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005953
Himanshu Agarwal44195412016-03-09 13:03:54 +05305954 ret = wmi_unified_set_tdls_offchan_mode_cmd(wma_handle->wmi_handle,
5955 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005956
5957end:
5958 if (chan_switch_params)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305959 qdf_mem_free(chan_switch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005960 return ret;
5961}
5962
5963/**
5964 * wma_update_fw_tdls_state() - send enable/disable tdls for a vdev
5965 * @wma: wma handle
5966 * @pwmaTdlsparams: TDLS params
5967 *
5968 * Return: 0 for sucess or error code
5969 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05305970QDF_STATUS wma_update_fw_tdls_state(WMA_HANDLE handle, void *pwmaTdlsparams)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005971{
5972 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005973 t_wma_tdls_mode tdls_mode;
5974 t_wma_tdls_params *wma_tdls = (t_wma_tdls_params *) pwmaTdlsparams;
Himanshu Agarwal44195412016-03-09 13:03:54 +05305975 struct wmi_tdls_params params = {0};
5976 QDF_STATUS ret = QDF_STATUS_SUCCESS;
5977 uint8_t tdls_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005978
5979 if (!wma_handle || !wma_handle->wmi_handle) {
5980 WMA_LOGE("%s: WMA is closed, can not issue fw tdls state cmd",
5981 __func__);
5982 ret = -EINVAL;
5983 goto end_fw_tdls_state;
5984 }
5985
Himanshu Agarwal44195412016-03-09 13:03:54 +05305986 params.tdls_state = wma_tdls->tdls_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005987 tdls_mode = wma_tdls->tdls_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005988
5989 if (WMA_TDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == tdls_mode) {
Himanshu Agarwal44195412016-03-09 13:03:54 +05305990 tdls_state = WMI_TDLS_ENABLE_PASSIVE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005991 } else if (WMA_TDLS_SUPPORT_ENABLED == tdls_mode) {
Himanshu Agarwal44195412016-03-09 13:03:54 +05305992 tdls_state = WMI_TDLS_ENABLE_ACTIVE;
Kabilan Kannan421714b2015-11-23 04:44:59 -08005993 } else if (WMA_TDLS_SUPPORT_ACTIVE_EXTERNAL_CONTROL == tdls_mode) {
Himanshu Agarwal44195412016-03-09 13:03:54 +05305994 tdls_state = WMI_TDLS_ENABLE_ACTIVE_EXTERNAL_CONTROL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005995 } else {
Himanshu Agarwal44195412016-03-09 13:03:54 +05305996 tdls_state = WMI_TDLS_DISABLE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005997 }
5998
Himanshu Agarwal44195412016-03-09 13:03:54 +05305999 params.vdev_id = wma_tdls->vdev_id;
6000 params.notification_interval_ms = wma_tdls->notification_interval_ms;
6001 params.tx_discovery_threshold = wma_tdls->tx_discovery_threshold;
6002 params.tx_teardown_threshold = wma_tdls->tx_teardown_threshold;
6003 params.rssi_teardown_threshold = wma_tdls->rssi_teardown_threshold;
6004 params.rssi_delta = wma_tdls->rssi_delta;
6005 params.tdls_options = wma_tdls->tdls_options;
6006 params.peer_traffic_ind_window = wma_tdls->peer_traffic_ind_window;
6007 params.peer_traffic_response_timeout =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006008 wma_tdls->peer_traffic_response_timeout;
Himanshu Agarwal44195412016-03-09 13:03:54 +05306009 params.puapsd_mask = wma_tdls->puapsd_mask;
6010 params.puapsd_inactivity_time = wma_tdls->puapsd_inactivity_time;
6011 params.puapsd_rx_frame_threshold =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006012 wma_tdls->puapsd_rx_frame_threshold;
Himanshu Agarwal44195412016-03-09 13:03:54 +05306013 params.teardown_notification_ms =
Kabilan Kannanca670be2015-11-23 01:56:12 -08006014 wma_tdls->teardown_notification_ms;
Himanshu Agarwal44195412016-03-09 13:03:54 +05306015 params.tdls_peer_kickout_threshold =
Kabilan Kannan421714b2015-11-23 04:44:59 -08006016 wma_tdls->tdls_peer_kickout_threshold;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006017
Himanshu Agarwal44195412016-03-09 13:03:54 +05306018 ret = wmi_unified_update_fw_tdls_state_cmd(wma_handle->wmi_handle,
6019 &params, tdls_state);
6020 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006021 goto end_fw_tdls_state;
Himanshu Agarwal44195412016-03-09 13:03:54 +05306022
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006023 WMA_LOGD("%s: vdev_id %d", __func__, wma_tdls->vdev_id);
6024
6025end_fw_tdls_state:
6026 if (pwmaTdlsparams)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306027 qdf_mem_free(pwmaTdlsparams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006028 return ret;
6029}
6030
6031/**
6032 * wma_update_tdls_peer_state() - update TDLS peer state
6033 * @handle: wma handle
6034 * @peerStateParams: TDLS peer state params
6035 *
6036 * Return: 0 for success or error code
6037 */
6038int wma_update_tdls_peer_state(WMA_HANDLE handle,
6039 tTdlsPeerStateParams *peerStateParams)
6040{
6041 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006042 uint32_t i;
6043 ol_txrx_pdev_handle pdev;
6044 uint8_t peer_id;
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07006045 ol_txrx_peer_handle peer;
6046 uint8_t *peer_mac_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006047 int ret = 0;
Govind Singhaa64c242016-03-08 11:31:49 +05306048 uint32_t *ch_mhz;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006049
6050 if (!wma_handle || !wma_handle->wmi_handle) {
6051 WMA_LOGE("%s: WMA is closed, can not issue cmd", __func__);
6052 ret = -EINVAL;
6053 goto end_tdls_peer_state;
6054 }
6055
6056 /* peer capability info is valid only when peer state is connected */
6057 if (WMA_TDLS_PEER_STATE_CONNECTED != peerStateParams->peerState) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306058 qdf_mem_zero(&peerStateParams->peerCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006059 sizeof(tTdlsPeerCapParams));
6060 }
6061
Govind Singhaa64c242016-03-08 11:31:49 +05306062 ch_mhz = qdf_mem_malloc(sizeof(uint32_t) *
6063 peerStateParams->peerCap.peerChanLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006064 for (i = 0; i < peerStateParams->peerCap.peerChanLen; ++i) {
Govind Singhaa64c242016-03-08 11:31:49 +05306065 ch_mhz[i] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006066 cds_chan_to_freq(peerStateParams->peerCap.peerChan[i].
6067 chanId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006068 }
6069
Govind Singhaa64c242016-03-08 11:31:49 +05306070 if (wmi_unified_update_tdls_peer_state_cmd(wma_handle->wmi_handle,
6071 (struct tdls_peer_state_params *)peerStateParams,
6072 ch_mhz)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006073 WMA_LOGE("%s: failed to send tdls peer update state command",
6074 __func__);
Govind Singhaa64c242016-03-08 11:31:49 +05306075 qdf_mem_free(ch_mhz);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006076 ret = -EIO;
6077 goto end_tdls_peer_state;
6078 }
6079
Govind Singhaa64c242016-03-08 11:31:49 +05306080 qdf_mem_free(ch_mhz);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006081 /* in case of teardown, remove peer from fw */
6082 if (WMA_TDLS_PEER_STATE_TEARDOWN == peerStateParams->peerState) {
Anurag Chouhan6d760662016-02-20 16:05:43 +05306083 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006084 if (!pdev) {
6085 WMA_LOGE("%s: Failed to find pdev", __func__);
6086 ret = -EIO;
6087 goto end_tdls_peer_state;
6088 }
6089
6090 peer = ol_txrx_find_peer_by_addr(pdev,
6091 peerStateParams->peerMacAddr,
6092 &peer_id);
6093 if (!peer) {
6094 WMA_LOGE("%s: Failed to get peer handle using peer mac %pM",
6095 __func__, peerStateParams->peerMacAddr);
6096 ret = -EIO;
6097 goto end_tdls_peer_state;
6098 }
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07006099 peer_mac_addr = ol_txrx_peer_get_peer_mac_addr(peer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006100
6101 WMA_LOGD("%s: calling wma_remove_peer for peer " MAC_ADDRESS_STR
6102 " vdevId: %d", __func__,
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07006103 MAC_ADDR_ARRAY(peer_mac_addr),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006104 peerStateParams->vdevId);
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07006105 wma_remove_peer(wma_handle, peer_mac_addr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006106 peerStateParams->vdevId, peer, false);
6107 }
6108
6109end_tdls_peer_state:
6110 if (peerStateParams)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306111 qdf_mem_free(peerStateParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006112 return ret;
6113}
6114#endif /* FEATURE_WLAN_TDLS */
6115
6116
6117/**
6118 * wma_dfs_attach() - Attach DFS methods to the umac state.
6119 * @dfs_ic: ieee80211com ptr
6120 *
6121 * Return: Return ieee80211com ptr with updated info
6122 */
6123struct ieee80211com *wma_dfs_attach(struct ieee80211com *dfs_ic)
6124{
6125 /*Allocate memory for dfs_ic before passing it up to dfs_attach() */
6126 dfs_ic = (struct ieee80211com *)
6127 os_malloc(NULL, sizeof(struct ieee80211com), GFP_ATOMIC);
6128 if (dfs_ic == NULL) {
6129 WMA_LOGE("%s:Allocation of dfs_ic failed %zu",
6130 __func__, sizeof(struct ieee80211com));
6131 return NULL;
6132 }
6133 OS_MEMZERO(dfs_ic, sizeof(struct ieee80211com));
6134 /* DFS pattern matching hooks */
6135 dfs_ic->ic_dfs_attach = ol_if_dfs_attach;
6136 dfs_ic->ic_dfs_disable = ol_if_dfs_disable;
6137 dfs_ic->ic_find_channel = ieee80211_find_channel;
6138 dfs_ic->ic_dfs_enable = ol_if_dfs_enable;
6139 dfs_ic->ic_ieee2mhz = ieee80211_ieee2mhz;
6140
6141 /* Hardware facing hooks */
6142 dfs_ic->ic_get_ext_busy = ol_if_dfs_get_ext_busy;
6143 dfs_ic->ic_get_mib_cycle_counts_pct =
6144 ol_if_dfs_get_mib_cycle_counts_pct;
6145 dfs_ic->ic_get_TSF64 = ol_if_get_tsf64;
6146
6147 /* NOL related hooks */
6148 dfs_ic->ic_dfs_usenol = ol_if_dfs_usenol;
6149 /*
6150 * Hooks from wma/dfs/ back
6151 * into the PE/SME
6152 * and shared DFS code
6153 */
6154 dfs_ic->ic_dfs_notify_radar = ieee80211_mark_dfs;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306155 qdf_spinlock_create(&dfs_ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006156 /* Initializes DFS Data Structures and queues */
6157 dfs_attach(dfs_ic);
6158
6159 return dfs_ic;
6160}
6161
6162/**
6163 * wma_dfs_detach() - Detach DFS methods
6164 * @dfs_ic: ieee80211com ptr
6165 *
6166 * Return: none
6167 */
6168void wma_dfs_detach(struct ieee80211com *dfs_ic)
6169{
6170 dfs_detach(dfs_ic);
6171
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306172 qdf_spinlock_destroy(&dfs_ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006173 if (NULL != dfs_ic->ic_curchan) {
6174 OS_FREE(dfs_ic->ic_curchan);
6175 dfs_ic->ic_curchan = NULL;
6176 }
6177
6178 OS_FREE(dfs_ic);
6179}
6180
6181/**
6182 * wma_dfs_configure() - configure dfs
6183 * @ic: ieee80211com ptr
6184 *
6185 * Configures Radar Filters during
6186 * vdev start/channel change/regulatory domain
6187 * change.This Configuration enables to program
6188 * the DFS pattern matching module.
6189 *
6190 * Return: none
6191 */
6192void wma_dfs_configure(struct ieee80211com *ic)
6193{
6194 struct ath_dfs_radar_tab_info rinfo;
6195 int dfsdomain;
6196 int radar_enabled_status = 0;
6197 if (ic == NULL) {
6198 WMA_LOGE("%s: DFS ic is Invalid", __func__);
6199 return;
6200 }
6201
6202 dfsdomain = ic->current_dfs_regdomain;
6203
6204 /* Fetch current radar patterns from the lmac */
6205 OS_MEMZERO(&rinfo, sizeof(rinfo));
6206
6207 /*
6208 * Look up the current DFS
6209 * regulatory domain and decide
6210 * which radar pulses to use.
6211 */
6212 switch (dfsdomain) {
Amar Singhala7bb01b2016-01-27 11:31:59 -08006213 case DFS_FCC_REGION:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006214 WMA_LOGI("%s: DFS-FCC domain", __func__);
Amar Singhala7bb01b2016-01-27 11:31:59 -08006215 rinfo.dfsdomain = DFS_FCC_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006216 rinfo.dfs_radars = dfs_fcc_radars;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306217 rinfo.numradars = QDF_ARRAY_SIZE(dfs_fcc_radars);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006218 rinfo.b5pulses = dfs_fcc_bin5pulses;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306219 rinfo.numb5radars = QDF_ARRAY_SIZE(dfs_fcc_bin5pulses);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006220 break;
Amar Singhala7bb01b2016-01-27 11:31:59 -08006221 case DFS_ETSI_REGION:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006222 WMA_LOGI("%s: DFS-ETSI domain", __func__);
Amar Singhala7bb01b2016-01-27 11:31:59 -08006223 rinfo.dfsdomain = DFS_ETSI_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006224 rinfo.dfs_radars = dfs_etsi_radars;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306225 rinfo.numradars = QDF_ARRAY_SIZE(dfs_etsi_radars);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006226 rinfo.b5pulses = NULL;
6227 rinfo.numb5radars = 0;
6228 break;
Amar Singhala7bb01b2016-01-27 11:31:59 -08006229 case DFS_MKK_REGION:
6230 WMA_LOGI("%s: DFS-MKK domain", __func__);
6231 rinfo.dfsdomain = DFS_MKK_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006232 rinfo.dfs_radars = dfs_mkk4_radars;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306233 rinfo.numradars = QDF_ARRAY_SIZE(dfs_mkk4_radars);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006234 rinfo.b5pulses = dfs_jpn_bin5pulses;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306235 rinfo.numb5radars = QDF_ARRAY_SIZE(dfs_jpn_bin5pulses);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006236 break;
6237 default:
6238 WMA_LOGI("%s: DFS-UNINT domain", __func__);
Amar Singhala7bb01b2016-01-27 11:31:59 -08006239 rinfo.dfsdomain = DFS_UNINIT_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006240 rinfo.dfs_radars = NULL;
6241 rinfo.numradars = 0;
6242 rinfo.b5pulses = NULL;
6243 rinfo.numb5radars = 0;
6244 break;
6245 }
6246
6247 rinfo.dfs_pri_multiplier = ic->dfs_pri_multiplier;
6248
6249 /*
6250 * Set the regulatory domain,
6251 * radar pulse table and enable
6252 * radar events if required.
6253 * dfs_radar_enable() returns
6254 * 0 on success and non-zero
6255 * failure.
6256 */
6257 radar_enabled_status = dfs_radar_enable(ic, &rinfo);
6258 if (radar_enabled_status != DFS_STATUS_SUCCESS) {
6259 WMA_LOGE("%s[%d]: DFS- Radar Detection Enabling Failed",
6260 __func__, __LINE__);
6261 }
6262}
6263
6264/**
6265 * wma_dfs_configure_channel() - configure DFS channel
6266 * @dfs_ic: ieee80211com ptr
Siddarth Poddar17dc4712016-03-09 16:30:27 +05306267 * @band_center_freq1: center frequency 1
6268 * @band_center_freq2: center frequency 2
6269 * (valid only for 11ac vht 80plus80 mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006270 * @ req: vdev start request
6271 *
6272 * Set the Channel parameters in to DFS module
6273 * Also,configure the DFS radar filters for
6274 * matching the DFS phyerrors.
6275 *
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306276 * Return: dfs_ieee80211_channel / NULL for error
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006277 */
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306278struct dfs_ieee80211_channel *wma_dfs_configure_channel(
6279 struct ieee80211com *dfs_ic,
Siddarth Poddar17dc4712016-03-09 16:30:27 +05306280 uint32_t band_center_freq1,
6281 uint32_t band_center_freq2,
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306282 struct wma_vdev_start_req
6283 *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006284{
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006285 uint8_t ext_channel;
6286
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006287 if (dfs_ic == NULL) {
6288 WMA_LOGE("%s: DFS ic is Invalid", __func__);
6289 return NULL;
6290 }
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05306291
6292 if (!dfs_ic->ic_curchan) {
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306293 dfs_ic->ic_curchan = (struct dfs_ieee80211_channel *)os_malloc(
6294 NULL,
6295 sizeof(struct dfs_ieee80211_channel),
6296 GFP_ATOMIC);
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05306297 if (dfs_ic->ic_curchan == NULL) {
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306298 WMA_LOGE(
6299 "%s: allocation of dfs_ic->ic_curchan failed %zu",
6300 __func__, sizeof(struct dfs_ieee80211_channel));
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05306301 return NULL;
6302 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006303 }
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05306304
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306305 OS_MEMZERO(dfs_ic->ic_curchan, sizeof(struct dfs_ieee80211_channel));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006306
6307 dfs_ic->ic_curchan->ic_ieee = req->chan;
Siddarth Poddar17dc4712016-03-09 16:30:27 +05306308 dfs_ic->ic_curchan->ic_freq = cds_chan_to_freq(req->chan);
6309 dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg1 = band_center_freq1;
6310 dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg2 = band_center_freq2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006311 dfs_ic->ic_curchan->ic_pri_freq_center_freq_mhz_separation =
6312 dfs_ic->ic_curchan->ic_freq -
6313 dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg1;
6314
6315 if ((dfs_ic->ic_curchan->ic_ieee >= WMA_11A_CHANNEL_BEGIN) &&
6316 (dfs_ic->ic_curchan->ic_ieee <= WMA_11A_CHANNEL_END)) {
6317 dfs_ic->ic_curchan->ic_flags |= IEEE80211_CHAN_5GHZ;
6318 }
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006319
6320 switch (req->chan_width) {
6321 case CH_WIDTH_20MHZ:
6322 dfs_ic->ic_curchan->ic_flags |=
6323 (req->vht_capable ? IEEE80211_CHAN_VHT20 :
6324 IEEE80211_CHAN_HT20);
6325 break;
6326 case CH_WIDTH_40MHZ:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006327 if (req->chan < req->ch_center_freq_seg0)
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006328 dfs_ic->ic_curchan->ic_flags |=
6329 (req->vht_capable ?
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006330 IEEE80211_CHAN_VHT40PLUS :
6331 IEEE80211_CHAN_HT40PLUS);
6332 else
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006333 dfs_ic->ic_curchan->ic_flags |=
6334 (req->vht_capable ?
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006335 IEEE80211_CHAN_VHT40MINUS :
6336 IEEE80211_CHAN_HT40MINUS);
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006337 break;
6338 case CH_WIDTH_80MHZ:
6339 dfs_ic->ic_curchan->ic_flags |= IEEE80211_CHAN_VHT80;
6340 break;
6341 case CH_WIDTH_80P80MHZ:
Siddarth Poddar17dc4712016-03-09 16:30:27 +05306342 ext_channel = cds_freq_to_chan(band_center_freq2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006343 dfs_ic->ic_curchan->ic_flags |=
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006344 IEEE80211_CHAN_VHT80P80;
6345 dfs_ic->ic_curchan->ic_freq_ext =
Siddarth Poddar17dc4712016-03-09 16:30:27 +05306346 band_center_freq2;
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006347 dfs_ic->ic_curchan->ic_ieee_ext = ext_channel;
6348
6349 /* verify both the 80MHz are DFS bands or not */
Rajeev Kumara3f6c2d2016-04-15 12:47:41 -07006350 if ((CHANNEL_STATE_DFS ==
6351 cds_get_5g_bonded_channel_state(req->chan ,
6352 CH_WIDTH_80MHZ)) &&
6353 (CHANNEL_STATE_DFS == cds_get_5g_bonded_channel_state(
6354 ext_channel - WMA_80MHZ_START_CENTER_CH_DIFF,
6355 CH_WIDTH_80MHZ)))
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006356 dfs_ic->ic_curchan->ic_80p80_both_dfs = true;
6357 break;
6358 case CH_WIDTH_160MHZ:
6359 dfs_ic->ic_curchan->ic_flags |=
6360 IEEE80211_CHAN_VHT160;
6361 break;
6362 default:
6363 WMA_LOGE(
6364 "%s: Recieved a wrong channel width %d",
6365 __func__, req->chan_width);
6366 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006367 }
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006368
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006369 dfs_ic->ic_curchan->ic_flagext |= IEEE80211_CHAN_DFS;
6370
6371 if (req->oper_mode == BSS_OPERATIONAL_MODE_AP) {
6372 dfs_ic->ic_opmode = IEEE80211_M_HOSTAP;
6373 dfs_ic->vdev_id = req->vdev_id;
6374 }
6375
6376 dfs_ic->dfs_pri_multiplier = req->dfs_pri_multiplier;
6377
6378 /*
6379 * Configuring the DFS with current channel and the radar filters
6380 */
6381 wma_dfs_configure(dfs_ic);
6382 WMA_LOGI("%s: DFS- CHANNEL CONFIGURED", __func__);
6383 return dfs_ic->ic_curchan;
6384}
6385
6386
6387/**
6388 * wma_set_dfs_region() - set DFS region
6389 * @wma: wma handle
6390 *
6391 * Configure the DFS region for DFS radar filter initialization
6392 *
6393 * Return: none
6394 */
6395void wma_set_dfs_region(tp_wma_handle wma, uint8_t dfs_region)
6396{
6397 /* dfs information is passed */
Amar Singhala7bb01b2016-01-27 11:31:59 -08006398 if (dfs_region > DFS_MKK_REGION || dfs_region == DFS_UNINIT_REGION)
6399 /* assign DFS_FCC_REGION as default region*/
6400 wma->dfs_ic->current_dfs_regdomain = DFS_FCC_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006401 else
6402 wma->dfs_ic->current_dfs_regdomain = dfs_region;
6403
6404 WMA_LOGI("%s: DFS Region Domain: %d", __func__,
6405 wma->dfs_ic->current_dfs_regdomain);
6406}
6407
6408/**
6409 * wma_get_channels() - prepare dfs radar channel list
6410 * @ichan: channel
6411 * @chan_list: return channel list
6412 *
6413 * Return: return number of channels
6414 */
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306415int wma_get_channels(struct dfs_ieee80211_channel *ichan,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006416 struct wma_dfs_radar_channel_list *chan_list)
6417{
6418 uint8_t center_chan = cds_freq_to_chan(ichan->ic_vhtop_ch_freq_seg1);
Vishwajith Upendrabf673e72016-01-19 16:05:40 -08006419 int count = 0;
6420 int start_channel = 0;
6421 int loop;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006422
6423 chan_list->nchannels = 0;
6424
Vishwajith Upendrabf673e72016-01-19 16:05:40 -08006425 if (IEEE80211_IS_CHAN_11AC_VHT160(ichan)) {
6426 /*
6427 * In 160MHz channel width, need to
6428 * check if each of the 8 20MHz channel
6429 * is DFS before adding to the NOL list.
6430 * As it is possible that part of the
6431 * 160MHz can be Non-DFS channels.
6432 */
6433 start_channel = center_chan - WMA_160MHZ_START_CENTER_CH_DIFF;
6434 for (loop = 0; loop < WMA_DFS_MAX_20M_SUB_CH; loop++) {
6435 if (cds_get_channel_state(start_channel +
6436 (loop * WMA_NEXT_20MHZ_START_CH_DIFF)) ==
6437 CHANNEL_STATE_DFS) {
6438 chan_list->channels[count] = start_channel +
6439 (loop * WMA_NEXT_20MHZ_START_CH_DIFF);
6440 count++;
6441 }
6442 }
6443 chan_list->nchannels = count;
6444 } else if (IEEE80211_IS_CHAN_11AC_VHT80P80(ichan)) {
6445 chan_list->nchannels = 4;
6446 /*
6447 * If SAP is operating in 80p80 mode, either
6448 * one of the two 80 segments or both the 80
6449 * segments can be DFS channels, so need to
6450 * identify on which 80 segment radar has
6451 * been detected and only add those channels
6452 * to the NOL list. center frequency should be
6453 * based on the segment id passed as part of
6454 * channel information in radar indication.
6455 */
6456 if (ichan->ic_radar_found_segid == DFS_80P80_SEG1)
6457 center_chan =
6458 cds_freq_to_chan(ichan->ic_vhtop_ch_freq_seg2);
6459 chan_list->channels[0] = center_chan - 6;
6460 chan_list->channels[1] = center_chan - 2;
6461 chan_list->channels[2] = center_chan + 2;
6462 chan_list->channels[3] = center_chan + 6;
6463 } else if (IEEE80211_IS_CHAN_11AC_VHT80(ichan)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006464 chan_list->nchannels = 4;
6465 chan_list->channels[0] = center_chan - 6;
6466 chan_list->channels[1] = center_chan - 2;
6467 chan_list->channels[2] = center_chan + 2;
6468 chan_list->channels[3] = center_chan + 6;
6469 } else if (IEEE80211_IS_CHAN_11N_HT40(ichan) ||
6470 IEEE80211_IS_CHAN_11AC_VHT40(ichan)) {
6471 chan_list->nchannels = 2;
6472 chan_list->channels[0] = center_chan - 2;
6473 chan_list->channels[1] = center_chan + 2;
6474 } else {
6475 chan_list->nchannels = 1;
6476 chan_list->channels[0] = center_chan;
6477 }
6478
6479 return chan_list->nchannels;
6480}
6481
6482
6483/**
6484 * wma_dfs_indicate_radar() - Indicate Radar to SAP/HDD
6485 * @ic: ieee80211com ptr
6486 * @ichan: ieee 80211 channel
6487 *
6488 * Return: 0 for success or error code
6489 */
6490int wma_dfs_indicate_radar(struct ieee80211com *ic,
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306491 struct dfs_ieee80211_channel *ichan)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006492{
6493 tp_wma_handle wma;
6494 void *hdd_ctx;
6495 struct wma_dfs_radar_indication *radar_event;
6496 struct wma_dfs_radar_ind wma_radar_event;
6497 tpAniSirGlobal pmac = NULL;
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05306498 bool indication_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006499
Anurag Chouhan6d760662016-02-20 16:05:43 +05306500 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006501 if (wma == NULL) {
6502 WMA_LOGE("%s: DFS- Invalid wma", __func__);
6503 return -ENOENT;
6504 }
6505
Anurag Chouhan6d760662016-02-20 16:05:43 +05306506 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006507 pmac = (tpAniSirGlobal)
Anurag Chouhan6d760662016-02-20 16:05:43 +05306508 cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006509
6510 if (!pmac) {
6511 WMA_LOGE("%s: Invalid MAC handle", __func__);
6512 return -ENOENT;
6513 }
6514
6515 if (wma->dfs_ic != ic) {
6516 WMA_LOGE("%s:DFS- Invalid WMA handle", __func__);
6517 return -ENOENT;
6518 }
6519 radar_event = (struct wma_dfs_radar_indication *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306520 qdf_mem_malloc(sizeof(struct wma_dfs_radar_indication));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006521 if (radar_event == NULL) {
6522 WMA_LOGE("%s:DFS- Invalid radar_event", __func__);
6523 return -ENOMEM;
6524 }
6525
6526 /*
6527 * Do not post multiple Radar events on the same channel.
6528 * But, when DFS test mode is enabled, allow multiple dfs
6529 * radar events to be posted on the same channel.
6530 */
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306531 qdf_spin_lock_bh(&ic->chan_lock);
Edhar, Mahesh Kumar35d9b2e2015-10-26 17:06:23 +05306532 if (!pmac->sap.SapDfsInfo.disable_dfs_ch_switch)
6533 wma->dfs_ic->disable_phy_err_processing = true;
6534
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006535 if ((ichan->ic_ieee != (wma->dfs_ic->last_radar_found_chan)) ||
6536 (pmac->sap.SapDfsInfo.disable_dfs_ch_switch == true)) {
6537 wma->dfs_ic->last_radar_found_chan = ichan->ic_ieee;
6538 /* Indicate the radar event to HDD to stop the netif Tx queues */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006539 wma_radar_event.chan_freq = ichan->ic_freq;
6540 wma_radar_event.dfs_radar_status = WMA_DFS_RADAR_FOUND;
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05306541 indication_status =
6542 wma->dfs_radar_indication_cb(hdd_ctx, &wma_radar_event);
6543 if (indication_status == false) {
6544 WMA_LOGE("%s:Application triggered channel switch in progress!.. drop radar event indiaction to SAP",
6545 __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306546 qdf_mem_free(radar_event);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306547 qdf_spin_unlock_bh(&ic->chan_lock);
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05306548 return 0;
6549 }
6550
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006551 WMA_LOGE("%s:DFS- RADAR INDICATED TO HDD", __func__);
6552
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05306553 wma_radar_event.ieee_chan_number = ichan->ic_ieee;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006554 /*
6555 * Indicate to the radar event to SAP to
6556 * select a new channel and set CSA IE
6557 */
6558 radar_event->vdev_id = ic->vdev_id;
6559 wma_get_channels(ichan, &radar_event->chan_list);
6560 radar_event->dfs_radar_status = WMA_DFS_RADAR_FOUND;
6561 radar_event->use_nol = ic->ic_dfs_usenol(ic);
6562 wma_send_msg(wma, WMA_DFS_RADAR_IND, (void *)radar_event, 0);
6563 WMA_LOGE("%s:DFS- WMA_DFS_RADAR_IND Message Posted", __func__);
6564 }
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306565 qdf_spin_unlock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006566
6567 return 0;
6568}
6569
6570#ifdef WLAN_FEATURE_MEMDUMP
6571/*
6572 * wma_process_fw_mem_dump_req() - Function to request fw memory dump from
6573 * firmware
6574 * @wma: Pointer to WMA handle
6575 * @mem_dump_req: Pointer for mem_dump_req
6576 *
6577 * This function sends memory dump request to firmware
6578 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306579 * Return: QDF_STATUS_SUCCESS for success otherwise failure
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006580 *
6581 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306582QDF_STATUS wma_process_fw_mem_dump_req(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006583 struct fw_dump_req *mem_dump_req)
6584{
Govind Singhaa64c242016-03-08 11:31:49 +05306585 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006586
6587 if (!mem_dump_req || !wma) {
6588 WMA_LOGE(FL("input pointer is NULL"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306589 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006590 }
6591
Govind Singhaa64c242016-03-08 11:31:49 +05306592 ret = wmi_unified_process_fw_mem_dump_cmd(wma->wmi_handle,
6593 (struct fw_dump_req_param *) mem_dump_req);
6594 if (ret)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306595 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006596
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306597 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006598}
6599
6600/**
6601 * wma_fw_mem_dump_rsp() - send fw mem dump response to SME
6602 *
6603 * @req_id - request id.
6604 * @status - copy status from the firmware.
6605 *
6606 * This function is called by the memory dump response handler to
6607 * indicate SME that firmware dump copy is complete
6608 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306609 * Return: QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006610 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306611static QDF_STATUS wma_fw_mem_dump_rsp(uint32_t req_id, uint32_t status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006612{
6613 struct fw_dump_rsp *dump_rsp;
6614 cds_msg_t sme_msg = {0};
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306615 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006616
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306617 dump_rsp = qdf_mem_malloc(sizeof(*dump_rsp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006618
6619 if (!dump_rsp) {
6620 WMA_LOGE(FL("Memory allocation failed."));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306621 qdf_status = QDF_STATUS_E_NOMEM;
6622 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006623 }
6624
6625 WMA_LOGI(FL("FW memory dump copy complete status: %d for request: %d"),
6626 status, req_id);
6627
6628 dump_rsp->request_id = req_id;
6629 dump_rsp->dump_complete = status;
6630
6631 sme_msg.type = eWNI_SME_FW_DUMP_IND;
6632 sme_msg.bodyptr = dump_rsp;
6633 sme_msg.bodyval = 0;
6634
Anurag Chouhan6d760662016-02-20 16:05:43 +05306635 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306636 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006637 WMA_LOGE(FL("Fail to post fw mem dump ind msg"));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306638 qdf_mem_free(dump_rsp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006639 }
6640
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306641 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006642}
6643
6644/**
6645 * wma_fw_mem_dump_event_handler() - handles fw memory dump event
6646 *
6647 * @handle: pointer to wma handle.
6648 * @cmd_param_info: pointer to TLV info received in the event.
6649 * @len: length of data in @cmd_param_info
6650 *
6651 * This function is a handler for firmware memory dump event.
6652 *
6653 * Return: integer (0 for success and error code otherwise)
6654 */
6655int wma_fw_mem_dump_event_handler(void *handle, u_int8_t *cmd_param_info,
6656 u_int32_t len)
6657{
6658 WMI_UPDATE_FW_MEM_DUMP_EVENTID_param_tlvs *param_buf;
6659 wmi_update_fw_mem_dump_fixed_param *event;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306660 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006661
6662 param_buf =
6663 (WMI_UPDATE_FW_MEM_DUMP_EVENTID_param_tlvs *) cmd_param_info;
6664 if (!param_buf) {
6665 WMA_LOGA("%s: Invalid stats event", __func__);
6666 return -EINVAL;
6667 }
6668
6669 event = param_buf->fixed_param;
6670
6671 status = wma_fw_mem_dump_rsp(event->request_id,
6672 event->fw_mem_dump_complete);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306673 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006674 WMA_LOGE("Error posting FW MEM DUMP RSP.");
6675 return -EINVAL;
6676 }
6677
6678 WMA_LOGI("FW MEM DUMP RSP posted successfully");
6679 return 0;
6680}
6681#endif /* WLAN_FEATURE_MEMDUMP */
6682
6683/*
6684 * wma_process_set_ie_info() - Function to send IE info to firmware
6685 * @wma: Pointer to WMA handle
6686 * @ie_data: Pointer for ie data
6687 *
6688 * This function sends IE information to firmware
6689 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306690 * Return: QDF_STATUS_SUCCESS for success otherwise failure
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006691 *
6692 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306693QDF_STATUS wma_process_set_ie_info(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006694 struct vdev_ie_info *ie_info)
6695{
Govind Singhaa64c242016-03-08 11:31:49 +05306696 struct vdev_ie_info_param cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006697 int ret;
6698
6699 if (!ie_info || !wma) {
6700 WMA_LOGE(FL("input pointer is NULL"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306701 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006702 }
6703
6704 /* Validate the input */
6705 if (ie_info->length <= 0) {
6706 WMA_LOGE(FL("Invalid IE length"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306707 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006708 }
6709
Govind Singhaa64c242016-03-08 11:31:49 +05306710 cmd.vdev_id = ie_info->vdev_id;
6711 cmd.ie_id = ie_info->ie_id;
6712 cmd.length = ie_info->length;
6713 cmd.data = ie_info->data;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006714
Govind Singhaa64c242016-03-08 11:31:49 +05306715 ret = wmi_unified_process_set_ie_info_cmd(wma->wmi_handle,
6716 &cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006717
6718 return ret;
6719}
6720