blob: 669854cce0be29cc2a4cc3d0f7f4404db7b5ebff [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
805#ifdef FEATURE_GREEN_AP
806
807/**
Ryan Hsu3c8f79f2015-12-02 16:45:09 -0800808 * wma_egap_info_status_event() - egap info status event
809 * @handle: pointer to wma handler
810 * @event: pointer to event
811 * @len: len of the event
812 *
813 * Return: 0 for success, otherwise appropriate error code
814 */
815static int wma_egap_info_status_event(void *handle, u_int8_t *event,
816 uint32_t len)
817{
818 WMI_TX_PAUSE_EVENTID_param_tlvs *param_buf;
819 wmi_ap_ps_egap_info_event_fixed_param *egap_info_event;
820 wmi_ap_ps_egap_info_chainmask_list *chainmask_event;
821 u_int8_t *buf_ptr;
822
823 param_buf = (WMI_TX_PAUSE_EVENTID_param_tlvs *)event;
824 if (!param_buf) {
825 WMA_LOGE("Invalid EGAP Info status event buffer");
826 return -EINVAL;
827 }
828
829 egap_info_event = (wmi_ap_ps_egap_info_event_fixed_param *)
830 param_buf->fixed_param;
831 buf_ptr = (uint8_t *)egap_info_event;
832 buf_ptr += sizeof(wmi_ap_ps_egap_info_event_fixed_param);
833 chainmask_event = (wmi_ap_ps_egap_info_chainmask_list *)buf_ptr;
834
835 WMA_LOGI("mac_id: %d, status: %d, tx_mask: %x, rx_mask: %d",
836 chainmask_event->mac_id,
837 egap_info_event->status,
838 chainmask_event->tx_chainmask,
839 chainmask_event->rx_chainmask);
840 return 0;
841}
842
843/**
844 * wma_send_egap_conf_params() - send wmi cmd of egap configuration params
845 * @wma_handle: wma handler
846 * @egap_params: pointer to egap_params
847 *
848 * Return: 0 for success, otherwise appropriate error code
849 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530850QDF_STATUS wma_send_egap_conf_params(WMA_HANDLE handle,
Ryan Hsu3c8f79f2015-12-02 16:45:09 -0800851 struct egap_conf_params *egap_params)
852{
853 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhaa64c242016-03-08 11:31:49 +0530854 wmi_ap_ps_egap_param_cmd_fixed_param cmd = {0};
Ryan Hsu3c8f79f2015-12-02 16:45:09 -0800855 int32_t err;
856
Govind Singhaa64c242016-03-08 11:31:49 +0530857 cmd.enable = egap_params->enable;
858 cmd.inactivity_time = egap_params->inactivity_time;
859 cmd.wait_time = egap_params->wait_time;
860 cmd.flags = egap_params->flags;
861 err = wmi_unified_egap_conf_params_cmd(wma_handle->wmi_handle, &cmd);
Ryan Hsu3c8f79f2015-12-02 16:45:09 -0800862 if (err) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530863 return QDF_STATUS_E_FAILURE;
Ryan Hsu3c8f79f2015-12-02 16:45:09 -0800864 }
Govind Singhaa64c242016-03-08 11:31:49 +0530865
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530866 return QDF_STATUS_SUCCESS;
Ryan Hsu3c8f79f2015-12-02 16:45:09 -0800867}
868
869/**
870 * wma_setup_egap_support() - setup the EGAP support flag
871 * @tgt_cfg: pointer to hdd target configuration
872 * @egap_support: EGAP support flag
873 *
874 * Return: None
875 */
876void wma_setup_egap_support(struct wma_tgt_cfg *tgt_cfg, WMA_HANDLE handle)
877{
878 tp_wma_handle wma_handle = (tp_wma_handle) handle;
879
880 if (tgt_cfg && wma_handle)
881 tgt_cfg->egap_support = wma_handle->egap_support;
882}
883
884/**
885 * wma_register_egap_event_handle() - register the EGAP event handle
886 * @wma_handle: wma handler
887 *
888 * Return: None
889 */
890void wma_register_egap_event_handle(WMA_HANDLE handle)
891{
892 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhd76a5b02016-03-08 15:12:14 +0530893 QDF_STATUS status;
Ryan Hsu3c8f79f2015-12-02 16:45:09 -0800894
895 if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap,
896 WMI_SERVICE_EGAP)) {
897 status = wmi_unified_register_event_handler(
898 wma_handle->wmi_handle,
899 WMI_AP_PS_EGAP_INFO_EVENTID,
Govind Singhd76a5b02016-03-08 15:12:14 +0530900 wma_egap_info_status_event,
901 WMA_RX_SERIALIZER_CTX);
902 if (QDF_IS_STATUS_ERROR(status)) {
Ryan Hsu3c8f79f2015-12-02 16:45:09 -0800903 WMA_LOGE("Failed to register Enhance Green AP event");
904 wma_handle->egap_support = false;
905 } else {
906 WMA_LOGI("Set the Enhance Green AP event handler");
907 wma_handle->egap_support = true;
908 }
909 } else
910 wma_handle->egap_support = false;
911}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800912#endif /* FEATURE_GREEN_AP */
913
Govind Singha471e5e2015-10-12 17:11:14 +0530914/**
Govind Singhaa64c242016-03-08 11:31:49 +0530915 * wma_unified_fw_profiling_cmd() - send FW profiling cmd to WLAN FW
Govind Singha471e5e2015-10-12 17:11:14 +0530916 * @wma: wma handle
917 * @cmd: Profiling command index
918 * @value1: parameter1 value
919 * @value2: parameter2 value
920 *
921 * Return: 0 for success else error code
922 */
Govind Singhaa64c242016-03-08 11:31:49 +0530923QDF_STATUS wma_unified_fw_profiling_cmd(wmi_unified_t wmi_handle,
Govind Singha471e5e2015-10-12 17:11:14 +0530924 uint32_t cmd, uint32_t value1, uint32_t value2)
925{
Govind Singha471e5e2015-10-12 17:11:14 +0530926 int ret;
Govind Singha471e5e2015-10-12 17:11:14 +0530927
Govind Singhaa64c242016-03-08 11:31:49 +0530928 ret = wmi_unified_fw_profiling_data_cmd(wmi_handle, cmd,
929 value1, value2);
930 if (ret) {
931 WMA_LOGE("enable cmd Failed for id %d value %d",
932 value1, value2);
933 return ret;
Govind Singha471e5e2015-10-12 17:11:14 +0530934 }
935
Govind Singhaa64c242016-03-08 11:31:49 +0530936 return QDF_STATUS_SUCCESS;
Govind Singha471e5e2015-10-12 17:11:14 +0530937}
938
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800939#ifdef FEATURE_WLAN_LPHB
940/**
941 * wma_lphb_handler() - send LPHB indication to SME
942 * @wma: wma handle
943 * @event: event handler
944 *
945 * Return: 0 for success or error code
946 */
947static int wma_lphb_handler(tp_wma_handle wma, uint8_t *event)
948{
949 wmi_hb_ind_event_fixed_param *hb_fp;
950 tSirLPHBInd *slphb_indication;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530951 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800952 cds_msg_t sme_msg = { 0 };
953
954 hb_fp = (wmi_hb_ind_event_fixed_param *) event;
955 if (!hb_fp) {
956 WMA_LOGE("Invalid wmi_hb_ind_event_fixed_param buffer");
957 return -EINVAL;
958 }
959
960 WMA_LOGD("lphb indication received with vdev_id=%d, session=%d, reason=%d",
961 hb_fp->vdev_id, hb_fp->session, hb_fp->reason);
962
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530963 slphb_indication = (tSirLPHBInd *) qdf_mem_malloc(sizeof(tSirLPHBInd));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800964
965 if (!slphb_indication) {
966 WMA_LOGE("Invalid LPHB indication buffer");
967 return -ENOMEM;
968 }
969
970 slphb_indication->sessionIdx = hb_fp->session;
971 slphb_indication->protocolType = hb_fp->reason;
972 slphb_indication->eventReason = hb_fp->reason;
973
974 sme_msg.type = eWNI_SME_LPHB_IND;
975 sme_msg.bodyptr = slphb_indication;
976 sme_msg.bodyval = 0;
977
Anurag Chouhan6d760662016-02-20 16:05:43 +0530978 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530979 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800980 WMA_LOGE("Fail to post eWNI_SME_LPHB_IND msg to SME");
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530981 qdf_mem_free(slphb_indication);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800982 return -EINVAL;
983 }
984
985 return 0;
986}
987#endif /* FEATURE_WLAN_LPHB */
988
989#ifdef FEATURE_WLAN_RA_FILTERING
990/**
991 * wma_wow_sta_ra_filter() - set RA filter pattern in fw
992 * @wma: wma handle
993 * @vdev_id: vdev id
994 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530995 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800996 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530997static QDF_STATUS wma_wow_sta_ra_filter(tp_wma_handle wma, uint8_t vdev_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800998{
999
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001000 struct wma_txrx_node *iface;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001001 int ret;
Govind Singhaa64c242016-03-08 11:31:49 +05301002 uint8_t default_pattern;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001003
1004 iface = &wma->interfaces[vdev_id];
1005
Govind Singhaa64c242016-03-08 11:31:49 +05301006 default_pattern = iface->num_wow_default_patterns++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001007
1008 WMA_LOGD("%s: send RA rate limit [%d] to fw vdev = %d", __func__,
1009 wma->RArateLimitInterval, vdev_id);
1010
Govind Singhaa64c242016-03-08 11:31:49 +05301011 ret = wmi_unified_wow_sta_ra_filter_cmd(wma->wmi_handle, vdev_id,
1012 default_pattern, wma->RArateLimitInterval);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001013 if (ret) {
1014 WMA_LOGE("%s: Failed to send RA rate limit to fw", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001015 iface->num_wow_default_patterns--;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301016 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001017 }
1018
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301019 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001020
1021}
1022#endif /* FEATURE_WLAN_RA_FILTERING */
1023
1024/**
1025 * wmi_unified_nat_keepalive_enable() - enable NAT keepalive filter
1026 * @wma: wma handle
1027 * @vdev_id: vdev id
1028 *
1029 * Return: 0 for success or error code
1030 */
1031int wmi_unified_nat_keepalive_enable(tp_wma_handle wma, uint8_t vdev_id)
1032{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001033
Govind Singhaa64c242016-03-08 11:31:49 +05301034 if (wmi_unified_nat_keepalive_en_cmd(wma->wmi_handle, vdev_id))
1035 return QDF_STATUS_E_FAILURE;
1036
1037 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001038}
1039
1040/**
Govind Singhd76a5b02016-03-08 15:12:14 +05301041 * wma_unified_csa_offload_enable() - sen CSA offload enable command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001042 * @wma: wma handle
1043 * @vdev_id: vdev id
1044 *
1045 * Return: 0 for success or error code
1046 */
Govind Singhd76a5b02016-03-08 15:12:14 +05301047int wma_unified_csa_offload_enable(tp_wma_handle wma, uint8_t vdev_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001048{
Govind Singhaa64c242016-03-08 11:31:49 +05301049 if (wmi_unified_csa_offload_enable(wma->wmi_handle,
1050 vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001051 WMA_LOGP("%s: Failed to send CSA offload enable command",
1052 __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001053 return -EIO;
1054 }
Govind Singhaa64c242016-03-08 11:31:49 +05301055
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001056 return 0;
1057}
1058
1059#ifdef WLAN_FEATURE_NAN
1060/**
1061 * wma_nan_rsp_event_handler() - Function is used to handle nan response
1062 * @handle: wma handle
1063 * @event_buf: event buffer
1064 * @len: length of buffer
1065 *
1066 * Return: 0 for success or error code
1067 */
1068int wma_nan_rsp_event_handler(void *handle, uint8_t *event_buf,
1069 uint32_t len)
1070{
1071 WMI_NAN_EVENTID_param_tlvs *param_buf;
1072 tSirNanEvent *nan_rsp_event;
1073 wmi_nan_event_hdr *nan_rsp_event_hdr;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301074 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001075 cds_msg_t cds_msg;
1076 uint8_t *buf_ptr;
1077 uint32_t alloc_len;
1078
1079 /*
1080 * This is how received event_buf looks like
1081 *
1082 * <-------------------- event_buf ----------------------------------->
1083 *
1084 * <--wmi_nan_event_hdr--><---WMI_TLV_HDR_SIZE---><----- data -------->
1085 *
1086 * +-----------+---------+-----------------------+--------------------+
1087 * | tlv_header| data_len| WMITLV_TAG_ARRAY_BYTE | nan_rsp_event_data |
1088 * +-----------+---------+-----------------------+--------------------+
1089 */
1090
1091 WMA_LOGD("%s: Posting NaN response event to SME", __func__);
1092 param_buf = (WMI_NAN_EVENTID_param_tlvs *) event_buf;
1093 if (!param_buf) {
1094 WMA_LOGE("%s: Invalid nan response event buf", __func__);
1095 return -EINVAL;
1096 }
1097 nan_rsp_event_hdr = param_buf->fixed_param;
1098 buf_ptr = (uint8_t *) nan_rsp_event_hdr;
1099 alloc_len = sizeof(tSirNanEvent);
1100 alloc_len += nan_rsp_event_hdr->data_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301101 nan_rsp_event = (tSirNanEvent *) qdf_mem_malloc(alloc_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001102 if (NULL == nan_rsp_event) {
1103 WMA_LOGE("%s: Memory allocation failure", __func__);
1104 return -ENOMEM;
1105 }
1106
1107 nan_rsp_event->event_data_len = nan_rsp_event_hdr->data_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301108 qdf_mem_copy(nan_rsp_event->event_data, buf_ptr +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001109 sizeof(wmi_nan_event_hdr) + WMI_TLV_HDR_SIZE,
1110 nan_rsp_event->event_data_len);
1111 cds_msg.type = eWNI_SME_NAN_EVENT;
1112 cds_msg.bodyptr = (void *)nan_rsp_event;
1113 cds_msg.bodyval = 0;
1114
1115 status = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301116 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001117 WMA_LOGE("%s: Failed to post NaN response event to SME",
1118 __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301119 qdf_mem_free(nan_rsp_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001120 return -EFAULT;
1121 }
1122 WMA_LOGD("%s: NaN response event Posted to SME", __func__);
1123 return 0;
1124}
1125#endif /* WLAN_FEATURE_NAN */
1126
1127/**
1128 * wma_csa_offload_handler() - CSA event handler
1129 * @handle: wma handle
1130 * @event: event buffer
1131 * @len: buffer length
1132 *
1133 * This event is sent by firmware when it receives CSA IE.
1134 *
1135 * Return: 0 for success or error code
1136 */
1137int wma_csa_offload_handler(void *handle, uint8_t *event, uint32_t len)
1138{
1139 tp_wma_handle wma = (tp_wma_handle) handle;
1140 WMI_CSA_HANDLING_EVENTID_param_tlvs *param_buf;
1141 wmi_csa_event_fixed_param *csa_event;
1142 uint8_t bssid[IEEE80211_ADDR_LEN];
1143 uint8_t vdev_id = 0;
1144 uint8_t cur_chan = 0;
1145 struct ieee80211_channelswitch_ie *csa_ie;
Chandrasekaran, Manishekar5c19dc52016-02-04 14:58:26 +05301146 struct csa_offload_params *csa_offload_event;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001147 struct ieee80211_extendedchannelswitch_ie *xcsa_ie;
1148 struct ieee80211_ie_wide_bw_switch *wb_ie;
1149 struct wma_txrx_node *intr = wma->interfaces;
1150
1151 param_buf = (WMI_CSA_HANDLING_EVENTID_param_tlvs *) event;
1152
1153 WMA_LOGD("%s: Enter", __func__);
1154 if (!param_buf) {
1155 WMA_LOGE("Invalid csa event buffer");
1156 return -EINVAL;
1157 }
1158 csa_event = param_buf->fixed_param;
1159 WMI_MAC_ADDR_TO_CHAR_ARRAY(&csa_event->i_addr2, &bssid[0]);
1160
1161 if (wma_find_vdev_by_bssid(wma, bssid, &vdev_id) == NULL) {
1162 WMA_LOGE("Invalid bssid received %s:%d", __func__, __LINE__);
1163 return -EINVAL;
1164 }
1165
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301166 csa_offload_event = qdf_mem_malloc(sizeof(*csa_offload_event));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001167 if (!csa_offload_event) {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05301168 WMA_LOGE("QDF MEM Alloc Failed for csa_offload_event");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001169 return -EINVAL;
1170 }
1171
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301172 qdf_mem_zero(csa_offload_event, sizeof(*csa_offload_event));
1173 qdf_mem_copy(csa_offload_event->bssId, &bssid, IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001174
1175 if (csa_event->ies_present_flag & WMI_CSA_IE_PRESENT) {
1176 csa_ie = (struct ieee80211_channelswitch_ie *)
1177 (&csa_event->csa_ie[0]);
1178 csa_offload_event->channel = csa_ie->newchannel;
Chandrasekaran, Manishekar5c19dc52016-02-04 14:58:26 +05301179 csa_offload_event->switch_mode = csa_ie->switchmode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001180 } else if (csa_event->ies_present_flag & WMI_XCSA_IE_PRESENT) {
1181 xcsa_ie = (struct ieee80211_extendedchannelswitch_ie *)
1182 (&csa_event->xcsa_ie[0]);
1183 csa_offload_event->channel = xcsa_ie->newchannel;
Chandrasekaran, Manishekar5c19dc52016-02-04 14:58:26 +05301184 csa_offload_event->switch_mode = xcsa_ie->switchmode;
Gupta, Kapil121bf212015-11-25 19:21:29 +05301185 csa_offload_event->new_op_class = xcsa_ie->newClass;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001186 } else {
1187 WMA_LOGE("CSA Event error: No CSA IE present");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301188 qdf_mem_free(csa_offload_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001189 return -EINVAL;
1190 }
1191
1192 if (csa_event->ies_present_flag & WMI_WBW_IE_PRESENT) {
1193 wb_ie = (struct ieee80211_ie_wide_bw_switch *)
1194 (&csa_event->wb_ie[0]);
1195 csa_offload_event->new_ch_width = wb_ie->new_ch_width;
1196 csa_offload_event->new_ch_freq_seg1 = wb_ie->new_ch_freq_seg1;
1197 csa_offload_event->new_ch_freq_seg2 = wb_ie->new_ch_freq_seg2;
1198 }
1199
1200 csa_offload_event->ies_present_flag = csa_event->ies_present_flag;
1201
1202 WMA_LOGD("CSA: New Channel = %d BSSID:%pM",
1203 csa_offload_event->channel, csa_offload_event->bssId);
1204
1205 cur_chan = cds_freq_to_chan(intr[vdev_id].mhz);
1206 /*
1207 * basic sanity check: requested channel should not be 0
1208 * and equal to home channel
1209 */
1210 if ((0 == csa_offload_event->channel) ||
1211 (cur_chan == csa_offload_event->channel)) {
1212 WMA_LOGE("CSA Event with channel %d. Ignore !!",
1213 csa_offload_event->channel);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301214 qdf_mem_free(csa_offload_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001215 return -EINVAL;
1216 }
1217 wma->interfaces[vdev_id].is_channel_switch = true;
1218 wma_send_msg(wma, WMA_CSA_OFFLOAD_EVENT, (void *)csa_offload_event, 0);
1219 return 0;
1220}
1221
1222#ifdef FEATURE_OEM_DATA_SUPPORT
1223
1224/**
1225 * wma_oem_capability_event_callback() - OEM capability event handler
1226 * @handle: wma handle
1227 * @datap: data ptr
1228 * @len: data length
1229 *
1230 * Return: 0 for success or error code
1231 */
1232int wma_oem_capability_event_callback(void *handle,
1233 uint8_t *datap, uint32_t len)
1234{
1235 tp_wma_handle wma = (tp_wma_handle) handle;
1236 WMI_OEM_CAPABILITY_EVENTID_param_tlvs *param_buf;
1237 uint8_t *data;
1238 uint32_t datalen;
1239 uint32_t *msg_subtype;
1240 tStartOemDataRsp *pStartOemDataRsp;
1241
1242 param_buf = (WMI_OEM_CAPABILITY_EVENTID_param_tlvs *) datap;
1243 if (!param_buf) {
1244 WMA_LOGE("%s: Received NULL buf ptr from FW", __func__);
1245 return -ENOMEM;
1246 }
1247
1248 data = param_buf->data;
1249 datalen = param_buf->num_data;
1250
1251 if (!data) {
1252 WMA_LOGE("%s: Received NULL data from FW", __func__);
1253 return -EINVAL;
1254 }
1255
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001256 /*
1257 * wma puts 4 bytes prefix for msg subtype, so length
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001258 * of data received from target should be 4 bytes less
1259 * then max allowed
1260 */
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001261 if (datalen > (OEM_DATA_RSP_SIZE - OEM_MESSAGE_SUBTYPE_LEN)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001262 WMA_LOGE("%s: Received data len (%d) exceeds max value (%d)",
1263 __func__, datalen, (OEM_DATA_RSP_SIZE - 4));
1264 return -EINVAL;
1265 }
1266
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301267 pStartOemDataRsp = qdf_mem_malloc(sizeof(*pStartOemDataRsp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001268 if (!pStartOemDataRsp) {
1269 WMA_LOGE("%s: Failed to alloc pStartOemDataRsp", __func__);
1270 return -ENOMEM;
1271 }
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001272 pStartOemDataRsp->rsp_len = datalen + OEM_MESSAGE_SUBTYPE_LEN;
1273 pStartOemDataRsp->oem_data_rsp = qdf_mem_malloc(datalen);
1274 if (!pStartOemDataRsp->oem_data_rsp) {
1275 WMA_LOGE(FL("malloc failed for oem_data_rsp"));
1276 qdf_mem_free(pStartOemDataRsp);
1277 return -ENOMEM;
1278 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001279
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001280 pStartOemDataRsp->target_rsp = true;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001281 msg_subtype = (uint32_t *) pStartOemDataRsp->oem_data_rsp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001282 *msg_subtype = WMI_OEM_CAPABILITY_RSP;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001283 /* copy data after msg sub type */
1284 qdf_mem_copy(pStartOemDataRsp->oem_data_rsp + OEM_MESSAGE_SUBTYPE_LEN,
1285 data, datalen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001286
1287 WMA_LOGI("%s: Sending WMA_START_OEM_DATA_RSP, data len (%d)",
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001288 __func__, pStartOemDataRsp->rsp_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001289
1290 wma_send_msg(wma, WMA_START_OEM_DATA_RSP, (void *)pStartOemDataRsp, 0);
1291 return 0;
1292}
1293
1294/**
1295 * wma_oem_measurement_report_event_callback() - OEM measurement report handler
1296 * @handle: wma handle
1297 * @datap: data ptr
1298 * @len: data length
1299 *
1300 * Return: 0 for success or error code
1301 */
1302int wma_oem_measurement_report_event_callback(void *handle,
1303 uint8_t *datap,
1304 uint32_t len)
1305{
1306 tp_wma_handle wma = (tp_wma_handle) handle;
1307 WMI_OEM_MEASUREMENT_REPORT_EVENTID_param_tlvs *param_buf;
1308 uint8_t *data;
1309 uint32_t datalen;
1310 uint32_t *msg_subtype;
1311 tStartOemDataRsp *pStartOemDataRsp;
1312
1313 param_buf = (WMI_OEM_MEASUREMENT_REPORT_EVENTID_param_tlvs *) datap;
1314 if (!param_buf) {
1315 WMA_LOGE("%s: Received NULL buf ptr from FW", __func__);
1316 return -ENOMEM;
1317 }
1318
1319 data = param_buf->data;
1320 datalen = param_buf->num_data;
1321
1322 if (!data) {
1323 WMA_LOGE("%s: Received NULL data from FW", __func__);
1324 return -EINVAL;
1325 }
1326
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001327 /*
1328 * wma puts 4 bytes prefix for msg subtype, so length
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001329 * of data received from target should be 4 bytes less
1330 * then max allowed
1331 */
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001332 if (datalen > (OEM_DATA_RSP_SIZE - OEM_MESSAGE_SUBTYPE_LEN)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001333 WMA_LOGE("%s: Received data len (%d) exceeds max value (%d)",
1334 __func__, datalen, (OEM_DATA_RSP_SIZE - 4));
1335 return -EINVAL;
1336 }
1337
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301338 pStartOemDataRsp = qdf_mem_malloc(sizeof(*pStartOemDataRsp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001339 if (!pStartOemDataRsp) {
1340 WMA_LOGE("%s: Failed to alloc pStartOemDataRsp", __func__);
1341 return -ENOMEM;
1342 }
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001343 pStartOemDataRsp->rsp_len = datalen + OEM_MESSAGE_SUBTYPE_LEN;
1344 pStartOemDataRsp->oem_data_rsp = qdf_mem_malloc(datalen);
1345 if (!pStartOemDataRsp->oem_data_rsp) {
1346 WMA_LOGE(FL("malloc failed for oem_data_rsp"));
1347 qdf_mem_free(pStartOemDataRsp);
1348 return -ENOMEM;
1349 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001350
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001351 pStartOemDataRsp->target_rsp = true;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001352 msg_subtype = (uint32_t *) pStartOemDataRsp->oem_data_rsp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001353 *msg_subtype = WMI_OEM_MEASUREMENT_RSP;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001354 /* copy data after msg sub type */
1355 qdf_mem_copy(pStartOemDataRsp->oem_data_rsp + OEM_MESSAGE_SUBTYPE_LEN,
1356 data, pStartOemDataRsp->rsp_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001357
1358 WMA_LOGI("%s: Sending WMA_START_OEM_DATA_RSP, data len (%d)",
1359 __func__, datalen);
1360
1361 wma_send_msg(wma, WMA_START_OEM_DATA_RSP, (void *)pStartOemDataRsp, 0);
1362 return 0;
1363}
1364
1365/**
1366 * wma_oem_error_report_event_callback() - OEM error report handler
1367 * @handle: wma handle
1368 * @datap: data ptr
1369 * @len: data length
1370 *
1371 * Return: 0 for success or error code
1372 */
1373int wma_oem_error_report_event_callback(void *handle,
1374 uint8_t *datap, uint32_t len)
1375{
1376 tp_wma_handle wma = (tp_wma_handle) handle;
1377 WMI_OEM_ERROR_REPORT_EVENTID_param_tlvs *param_buf;
1378 uint8_t *data;
1379 uint32_t datalen;
1380 uint32_t *msg_subtype;
1381 tStartOemDataRsp *pStartOemDataRsp;
1382
1383 param_buf = (WMI_OEM_ERROR_REPORT_EVENTID_param_tlvs *) datap;
1384 if (!param_buf) {
1385 WMA_LOGE("%s: Received NULL buf ptr from FW", __func__);
1386 return -ENOMEM;
1387 }
1388
1389 data = param_buf->data;
1390 datalen = param_buf->num_data;
1391
1392 if (!data) {
1393 WMA_LOGE("%s: Received NULL data from FW", __func__);
1394 return -EINVAL;
1395 }
1396
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001397 /*
1398 * wma puts 4 bytes prefix for msg subtype, so length
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001399 * of data received from target should be 4 bytes less
1400 * then max allowed
1401 */
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001402 if (datalen > (OEM_DATA_RSP_SIZE - OEM_MESSAGE_SUBTYPE_LEN)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001403 WMA_LOGE("%s: Received data len (%d) exceeds max value (%d)",
1404 __func__, datalen, (OEM_DATA_RSP_SIZE - 4));
1405 return -EINVAL;
1406 }
1407
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301408 pStartOemDataRsp = qdf_mem_malloc(sizeof(*pStartOemDataRsp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001409 if (!pStartOemDataRsp) {
1410 WMA_LOGE("%s: Failed to alloc pStartOemDataRsp", __func__);
1411 return -ENOMEM;
1412 }
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001413 pStartOemDataRsp->rsp_len = datalen + OEM_MESSAGE_SUBTYPE_LEN;
1414 pStartOemDataRsp->oem_data_rsp = qdf_mem_malloc(datalen);
1415 if (!pStartOemDataRsp->oem_data_rsp) {
1416 WMA_LOGE(FL("malloc failed for oem_data_rsp"));
1417 qdf_mem_free(pStartOemDataRsp);
1418 return -ENOMEM;
1419 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001420
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001421 pStartOemDataRsp->target_rsp = true;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001422 msg_subtype = (uint32_t *) pStartOemDataRsp->oem_data_rsp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001423 *msg_subtype = WMI_OEM_ERROR_REPORT_RSP;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001424 /* copy data after msg sub type */
1425 qdf_mem_copy(pStartOemDataRsp->oem_data_rsp + OEM_MESSAGE_SUBTYPE_LEN,
1426 data, pStartOemDataRsp->rsp_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001427
1428 WMA_LOGI("%s: Sending WMA_START_OEM_DATA_RSP, data len (%d)",
1429 __func__, datalen);
1430
1431 wma_send_msg(wma, WMA_START_OEM_DATA_RSP, (void *)pStartOemDataRsp, 0);
1432 return 0;
1433}
1434
1435/**
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001436 * wma_oem_data_response_handler() - OEM data response event handler
1437 * @handle: wma handle
1438 * @datap: data ptr
1439 * @len: data length
1440 *
1441 * Return: 0 for success or error code
1442 */
1443int wma_oem_data_response_handler(void *handle,
1444 uint8_t *datap, uint32_t len)
1445{
1446 tp_wma_handle wma = (tp_wma_handle) handle;
1447 WMI_OEM_RESPONSE_EVENTID_param_tlvs *param_buf;
1448 uint8_t *data;
1449 uint32_t datalen;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001450 tStartOemDataRsp *oem_rsp;
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001451
1452 param_buf = (WMI_OEM_RESPONSE_EVENTID_param_tlvs *) datap;
1453 if (!param_buf) {
1454 WMA_LOGE(FL("Received NULL buf ptr from FW"));
1455 return -ENOMEM;
1456 }
1457
1458 data = param_buf->data;
1459 datalen = param_buf->num_data;
1460
1461 if (!data) {
1462 WMA_LOGE(FL("Received NULL data from FW"));
1463 return -EINVAL;
1464 }
1465
1466 if (datalen > OEM_DATA_RSP_SIZE) {
1467 WMA_LOGE(FL("Received data len %d exceeds max value %d"),
1468 datalen, OEM_DATA_RSP_SIZE);
1469 return -EINVAL;
1470 }
1471
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001472 oem_rsp = qdf_mem_malloc(sizeof(*oem_rsp));
1473 if (!oem_rsp) {
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001474 WMA_LOGE(FL("Failed to alloc oem_data_rsp"));
1475 return -ENOMEM;
1476 }
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001477 oem_rsp->rsp_len = datalen;
1478 oem_rsp->oem_data_rsp = qdf_mem_malloc(datalen);
1479 if (!oem_rsp->rsp_len) {
1480 WMA_LOGE(FL("malloc failed for oem_data_rsp"));
1481 qdf_mem_free(oem_rsp);
1482 return -ENOMEM;
1483 }
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001484
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001485 oem_rsp->target_rsp = true;
1486 qdf_mem_copy(oem_rsp->oem_data_rsp, data, datalen);
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001487
1488 WMA_LOGI(FL("Sending WMA_START_OEM_DATA_RSP, data len %d"), datalen);
1489
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001490 wma_send_msg(wma, WMA_START_OEM_DATA_RSP, (void *)oem_rsp, 0);
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001491 return 0;
1492}
1493
1494/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001495 * wma_start_oem_data_req() - start OEM data request to target
1496 * @wma_handle: wma handle
1497 * @startOemDataReq: start request params
1498 *
1499 * Return: none
1500 */
1501void wma_start_oem_data_req(tp_wma_handle wma_handle,
1502 tStartOemDataReq *startOemDataReq)
1503{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001504 int ret = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001505 tStartOemDataRsp *pStartOemDataRsp;
1506
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001507 WMA_LOGD(FL("Send OEM Data Request to target"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001508
Sreelakshmi Konamki86d79202016-02-10 12:33:40 +05301509 if (!startOemDataReq || !startOemDataReq->data) {
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001510 WMA_LOGE(FL("startOemDataReq is null"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001511 goto out;
1512 }
1513
1514 if (!wma_handle || !wma_handle->wmi_handle) {
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001515 WMA_LOGE(FL("WMA - closed, can not send Oem data request cmd"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001516 return;
1517 }
1518
Govind Singhaa64c242016-03-08 11:31:49 +05301519 ret = wmi_unified_start_oem_data_cmd(wma_handle->wmi_handle,
1520 startOemDataReq->data_len,
1521 startOemDataReq->data);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001522
1523 if (ret != EOK) {
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001524 WMA_LOGE(FL(":wmi cmd send failed"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001525 }
1526
1527out:
1528 /* free oem data req buffer received from UMAC */
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001529 if (startOemDataReq) {
1530 if (startOemDataReq->data)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301531 qdf_mem_free(startOemDataReq->data);
1532 qdf_mem_free(startOemDataReq);
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001533 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001534
1535 /* Now send data resp back to PE/SME with message sub-type of
1536 * WMI_OEM_INTERNAL_RSP. This is required so that PE/SME clears
1537 * up pending active command. Later when desired oem response(s)
1538 * comes as wmi event from target then those shall be passed
1539 * to oem application
1540 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301541 pStartOemDataRsp = qdf_mem_malloc(sizeof(*pStartOemDataRsp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001542 if (!pStartOemDataRsp) {
1543 WMA_LOGE("%s:failed to allocate memory for OEM Data Resp to PE",
1544 __func__);
1545 return;
1546 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301547 qdf_mem_zero(pStartOemDataRsp, sizeof(tStartOemDataRsp));
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001548 pStartOemDataRsp->target_rsp = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001549
1550 WMA_LOGI("%s: Sending WMA_START_OEM_DATA_RSP to clear up PE/SME pending cmd",
1551 __func__);
1552
1553 wma_send_msg(wma_handle, WMA_START_OEM_DATA_RSP,
1554 (void *)pStartOemDataRsp, 0);
1555
1556 return;
1557}
1558#endif /* FEATURE_OEM_DATA_SUPPORT */
1559
1560
1561/**
1562 * wma_unified_dfs_radar_rx_event_handler() - dfs radar rx event handler
1563 * @handle: wma handle
1564 * @data: data buffer
1565 * @datalen: data length
1566 *
1567 * WMI handler for WMI_DFS_RADAR_EVENTID
1568 * This handler is registered for handling
1569 * filtered DFS Phyerror. This handler is
1570 * will be invoked only when DFS Phyerr
1571 * filtering offload is enabled.
1572 *
1573 * Return: 1 for Success and 0 for error
1574 */
1575static int wma_unified_dfs_radar_rx_event_handler(void *handle,
1576 uint8_t *data,
1577 uint32_t datalen)
1578{
1579 tp_wma_handle wma = (tp_wma_handle) handle;
1580 struct ieee80211com *ic;
1581 struct ath_dfs *dfs;
1582 struct dfs_event *event;
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05301583 struct dfs_ieee80211_channel *chan;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001584 int empty;
1585 int do_check_chirp = 0;
1586 int is_hw_chirp = 0;
1587 int is_sw_chirp = 0;
1588 int is_pri = 0;
Vishwajith Upendrabf673e72016-01-19 16:05:40 -08001589 bool is_ch_dfs = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001590
1591 WMI_DFS_RADAR_EVENTID_param_tlvs *param_tlvs;
1592 wmi_dfs_radar_event_fixed_param *radar_event;
1593
1594 ic = wma->dfs_ic;
1595 if (NULL == ic) {
1596 WMA_LOGE("%s: dfs_ic is NULL ", __func__);
1597 return 0;
1598 }
1599
1600 dfs = (struct ath_dfs *)ic->ic_dfs;
1601 param_tlvs = (WMI_DFS_RADAR_EVENTID_param_tlvs *) data;
1602
1603 if (NULL == dfs) {
1604 WMA_LOGE("%s: dfs is NULL ", __func__);
1605 return 0;
1606 }
1607 /*
1608 * This parameter holds the number
1609 * of phyerror interrupts to the host
1610 * after the phyerrors have passed through
1611 * false detect filters in the firmware.
1612 */
1613 dfs->dfs_phyerr_count++;
1614
1615 if (!param_tlvs) {
1616 WMA_LOGE("%s: Received NULL data from FW", __func__);
1617 return 0;
1618 }
1619
1620 radar_event = param_tlvs->fixed_param;
1621
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301622 qdf_spin_lock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001623 chan = ic->ic_curchan;
Edhar, Mahesh Kumar35d9b2e2015-10-26 17:06:23 +05301624 if (ic->disable_phy_err_processing) {
1625 WMA_LOGD("%s: radar indication done,drop phyerror event",
1626 __func__);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301627 qdf_spin_unlock_bh(&ic->chan_lock);
Edhar, Mahesh Kumar35d9b2e2015-10-26 17:06:23 +05301628 return 0;
1629 }
1630
Vishwajith Upendrabf673e72016-01-19 16:05:40 -08001631 if (IEEE80211_IS_CHAN_11AC_VHT160(chan)) {
1632 is_ch_dfs = true;
1633 } else if (IEEE80211_IS_CHAN_11AC_VHT80P80(chan)) {
1634 if (cds_get_channel_state(chan->ic_ieee) == CHANNEL_STATE_DFS ||
1635 cds_get_channel_state(chan->ic_ieee_ext -
1636 WMA_80MHZ_START_CENTER_CH_DIFF) ==
1637 CHANNEL_STATE_DFS)
1638 is_ch_dfs = true;
1639 } else {
1640 if (cds_get_channel_state(chan->ic_ieee) == CHANNEL_STATE_DFS)
1641 is_ch_dfs = true;
1642 }
1643 if (!is_ch_dfs) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001644 WMA_LOGE
1645 ("%s: Invalid DFS Phyerror event. Channel=%d is Non-DFS",
1646 __func__, chan->ic_ieee);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301647 qdf_spin_unlock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001648 return 0;
1649 }
1650
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301651 qdf_spin_unlock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001652 dfs->ath_dfs_stats.total_phy_errors++;
1653
1654 if (dfs->dfs_caps.ath_chip_is_bb_tlv) {
1655 do_check_chirp = 1;
1656 is_pri = 1;
1657 is_hw_chirp = radar_event->pulse_is_chirp;
1658
1659 if ((uint32_t) dfs->dfs_phyerr_freq_min >
1660 radar_event->pulse_center_freq) {
1661 dfs->dfs_phyerr_freq_min =
1662 (int)radar_event->pulse_center_freq;
1663 }
1664
1665 if (dfs->dfs_phyerr_freq_max <
1666 (int)radar_event->pulse_center_freq) {
1667 dfs->dfs_phyerr_freq_max =
1668 (int)radar_event->pulse_center_freq;
1669 }
1670 }
1671
1672 /*
1673 * Now, add the parsed, checked and filtered
1674 * radar phyerror event radar pulse event list.
1675 * This event will then be processed by
1676 * dfs_radar_processevent() to see if the pattern
1677 * of pulses in radar pulse list match any radar
1678 * singnature in the current regulatory domain.
1679 */
1680
1681 ATH_DFSEVENTQ_LOCK(dfs);
1682 empty = STAILQ_EMPTY(&(dfs->dfs_eventq));
1683 ATH_DFSEVENTQ_UNLOCK(dfs);
1684 if (empty) {
1685 return 0;
1686 }
1687 /*
1688 * Add the event to the list, if there's space.
1689 */
1690 ATH_DFSEVENTQ_LOCK(dfs);
1691 event = STAILQ_FIRST(&(dfs->dfs_eventq));
1692 if (event == NULL) {
1693 ATH_DFSEVENTQ_UNLOCK(dfs);
1694 WMA_LOGE("%s: No more space left for queuing DFS Phyerror events",
1695 __func__);
1696 return 0;
1697 }
1698 STAILQ_REMOVE_HEAD(&(dfs->dfs_eventq), re_list);
1699 ATH_DFSEVENTQ_UNLOCK(dfs);
1700 dfs->dfs_phyerr_queued_count++;
1701 dfs->dfs_phyerr_w53_counter++;
1702 event->re_dur = (uint8_t) radar_event->pulse_duration;
1703 event->re_rssi = radar_event->rssi;
1704 event->re_ts = radar_event->pulse_detect_ts & DFS_TSMASK;
1705 event->re_full_ts = (((uint64_t) radar_event->upload_fullts_high) << 32)
1706 | radar_event->upload_fullts_low;
1707
1708 /*
1709 * Index of peak magnitude
1710 */
1711 event->sidx = radar_event->peak_sidx;
1712
1713 /*
1714 * Handle chirp flags.
1715 */
1716 if (do_check_chirp) {
1717 event->re_flags |= DFS_EVENT_CHECKCHIRP;
1718 if (is_hw_chirp) {
1719 event->re_flags |= DFS_EVENT_HW_CHIRP;
1720 }
1721 if (is_sw_chirp) {
1722 event->re_flags |= DFS_EVENT_SW_CHIRP;
1723 }
1724 }
1725 /*
1726 * Correctly set which channel is being reported on
1727 */
1728 if (is_pri) {
1729 event->re_chanindex = (uint8_t) dfs->dfs_curchan_radindex;
1730 } else {
1731 if (dfs->dfs_extchan_radindex == -1) {
1732 WMA_LOGI("%s phyerr on ext channel", __func__);
1733 }
1734 event->re_chanindex = (uint8_t) dfs->dfs_extchan_radindex;
1735 WMA_LOGI("%s:New extension channel event is added to queue",
1736 __func__);
1737 }
1738
1739 ATH_DFSQ_LOCK(dfs);
1740
1741 STAILQ_INSERT_TAIL(&(dfs->dfs_radarq), event, re_list);
1742
1743 empty = STAILQ_EMPTY(&dfs->dfs_radarq);
1744
1745 ATH_DFSQ_UNLOCK(dfs);
1746
1747 if (!empty && !dfs->ath_radar_tasksched) {
1748 dfs->ath_radar_tasksched = 1;
1749 OS_SET_TIMER(&dfs->ath_dfs_task_timer, 0);
1750 }
1751
1752 return 1;
1753
1754}
1755
1756/**
1757 * wma_unified_phyerr_rx_event_handler() - phyerr event handler
1758 * @handle: wma handle
1759 * @data: data buffer
1760 * @datalen: buffer length
1761 *
1762 * WMI Handler for WMI_PHYERR_EVENTID event from firmware.
1763 * This handler is currently handling only DFS phy errors.
1764 * This handler will be invoked only when the DFS phyerror
1765 * filtering offload is disabled.
1766 *
1767 * Return: 1:Success, 0:Failure
1768 */
1769static int wma_unified_phyerr_rx_event_handler(void *handle,
1770 uint8_t *data, uint32_t datalen)
1771{
1772 tp_wma_handle wma = (tp_wma_handle) handle;
1773 WMI_PHYERR_EVENTID_param_tlvs *param_tlvs;
1774 wmi_comb_phyerr_rx_hdr *pe_hdr;
1775 uint8_t *bufp;
1776 wmi_single_phyerr_rx_event *ev;
1777 struct ieee80211com *ic = wma->dfs_ic;
Anurag Chouhan6d760662016-02-20 16:05:43 +05301778 qdf_size_t n;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001779 A_UINT64 tsf64 = 0;
1780 int phy_err_code = 0;
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08001781 A_UINT32 phy_err_mask = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001782 int error = 0;
1783 tpAniSirGlobal mac_ctx =
Anurag Chouhan6d760662016-02-20 16:05:43 +05301784 (tpAniSirGlobal)cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001785 bool enable_log = false;
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08001786 int max_dfs_buf_length = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001787
1788 if (NULL == mac_ctx) {
1789 WMA_LOGE("%s: mac_ctx is NULL", __func__);
1790 return 0;
1791 }
1792 enable_log = mac_ctx->sap.enable_dfs_phy_error_logs;
1793
1794 param_tlvs = (WMI_PHYERR_EVENTID_param_tlvs *) data;
1795
1796 if (!param_tlvs) {
1797 WMA_LOGE("%s: Received NULL data from FW", __func__);
1798 return 0;
1799 }
1800
1801 pe_hdr = param_tlvs->hdr;
1802 if (pe_hdr == NULL) {
1803 WMA_LOGE("%s: Received Data PE Header is NULL", __func__);
1804 return 0;
1805 }
1806
1807 /* Ensure it's at least the size of the header */
1808 if (datalen < sizeof(*pe_hdr)) {
1809 WMA_LOGE("%s: Expected minimum size %zu, received %d",
1810 __func__, sizeof(*pe_hdr), datalen);
1811 return 0;
1812 }
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08001813 /*
1814 * The max buffer lenght is larger for DFS-3 than DFS-2.
1815 * So, accordingly use the correct max buffer size.
1816 */
1817 if (wma->hw_bd_id != WMI_HWBD_QCA6174)
1818 max_dfs_buf_length = DFS3_MAX_BUF_LENGTH;
1819 else
1820 max_dfs_buf_length = DFS_MAX_BUF_LENGTH;
1821
1822 if (pe_hdr->buf_len > max_dfs_buf_length) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001823 WMA_LOGE("%s: Received Invalid Phyerror event buffer length = %d"
1824 "Maximum allowed buf length = %d", __func__,
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08001825 pe_hdr->buf_len, max_dfs_buf_length);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001826
1827 return 0;
1828 }
1829
1830 /*
1831 * Reconstruct the 64 bit event TSF. This isn't from the MAC, it's
1832 * at the time the event was sent to us, the TSF value will be
1833 * in the future.
1834 */
1835 tsf64 = pe_hdr->tsf_l32;
1836 tsf64 |= (((uint64_t) pe_hdr->tsf_u32) << 32);
1837
1838 /*
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08001839 * Check the HW board ID to figure out
1840 * if DFS-3 is supported. In DFS-3
1841 * phyerror mask indicates the type of
1842 * phyerror, whereas in DFS-2 phyerrorcode
1843 * indicates the type of phyerror. If the
1844 * board is NOT WMI_HWBD_QCA6174, for now
1845 * assume that it supports DFS-3.
1846 */
1847 if (wma->hw_bd_id != WMI_HWBD_QCA6174) {
1848 phy_err_mask = pe_hdr->rsPhyErrMask0;
1849 WMA_LOGD("%s: DFS-3 phyerror mask = 0x%x",
1850 __func__, phy_err_mask);
1851 }
1852
1853 /*
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001854 * Loop over the bufp, extracting out phyerrors
1855 * wmi_unified_comb_phyerr_rx_event.bufp is a char pointer,
1856 * which isn't correct here - what we have received here
1857 * is an array of TLV-style PHY errors.
1858 */
1859 n = 0; /* Start just after the header */
1860 bufp = param_tlvs->bufp;
1861 while (n < pe_hdr->buf_len) {
1862 /* ensure there's at least space for the header */
1863 if ((pe_hdr->buf_len - n) < sizeof(ev->hdr)) {
1864 WMA_LOGE("%s: Not enough space.(datalen=%d, n=%zu, hdr=%zu bytes",
1865 __func__, pe_hdr->buf_len, n, sizeof(ev->hdr));
1866 error = 1;
1867 break;
1868 }
1869 /*
1870 * Obtain a pointer to the beginning of the current event.
1871 * data[0] is the beginning of the WMI payload.
1872 */
1873 ev = (wmi_single_phyerr_rx_event *) &bufp[n];
1874
1875 /*
1876 * Sanity check the buffer length of the event against
1877 * what we currently have.
1878 * Since buf_len is 32 bits, we check if it overflows
1879 * a large 32 bit value. It's not 0x7fffffff because
1880 * we increase n by (buf_len + sizeof(hdr)), which would
1881 * in itself cause n to overflow.
1882 * If "int" is 64 bits then this becomes a moot point.
1883 */
1884 if (ev->hdr.buf_len > 0x7f000000) {
1885 WMA_LOGE("%s:buf_len is garbage (0x%x)", __func__,
1886 ev->hdr.buf_len);
1887 error = 1;
1888 break;
1889 }
1890 if (n + ev->hdr.buf_len > pe_hdr->buf_len) {
1891 WMA_LOGE("%s: buf_len exceeds available space n=%zu,"
1892 "buf_len=%d, datalen=%d",
1893 __func__, n, ev->hdr.buf_len, pe_hdr->buf_len);
1894 error = 1;
1895 break;
1896 }
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08001897 /*
1898 * If the board id is WMI_HWBD_QCA6174
1899 * then it supports only DFS-2. So, fetch
1900 * phyerror code in order to know the type
1901 * of phyerror.
1902 */
1903 if (wma->hw_bd_id == WMI_HWBD_QCA6174) {
1904 phy_err_code = WMI_UNIFIED_PHYERRCODE_GET(&ev->hdr);
1905 WMA_LOGD("%s: DFS-2 phyerror code = 0x%x",
1906 __func__, phy_err_code);
1907 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001908
1909 /*
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08001910 * phy_err_code is set for DFS-2 and phy_err_mask
1911 * is set for DFS-3. Checking both to support
1912 * compatability for older platforms.
1913 * If the phyerror or phyerrmask category matches,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001914 * pass radar events to the dfs pattern matching code.
1915 * Don't pass radar events with no buffer payload.
1916 */
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08001917 if (((phy_err_mask & WMI_PHY_ERROR_MASK0_RADAR) ||
1918 (phy_err_mask & WMI_PHY_ERROR_MASK0_FALSE_RADAR_EXT)) ||
1919 (phy_err_code == WMA_DFS2_PHYERROR_CODE ||
1920 phy_err_code == WMA_DFS2_FALSE_RADAR_EXT)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001921 if (ev->hdr.buf_len > 0) {
1922 /* Calling in to the DFS module to process the phyerr */
1923 dfs_process_phyerr(ic, &ev->bufp[0],
1924 ev->hdr.buf_len,
1925 WMI_UNIFIED_RSSI_COMB_GET
1926 (&ev->hdr) & 0xff,
1927 /* Extension RSSI */
1928 WMI_UNIFIED_RSSI_COMB_GET
1929 (&ev->hdr) & 0xff,
1930 ev->hdr.tsf_timestamp,
1931 tsf64, enable_log);
1932 }
1933 }
1934
1935 /*
1936 * Advance the buffer pointer to the next PHY error.
1937 * buflen is the length of this payload, so we need to
1938 * advance past the current header _AND_ the payload.
1939 */
1940 n += sizeof(*ev) + ev->hdr.buf_len;
1941
1942 } /*end while() */
1943 if (error)
1944 return 0;
1945 else
1946 return 1;
1947}
1948
1949/**
1950 * wma_register_dfs_event_handler() - register dfs event handler
1951 * @wma_handle: wma handle
1952 *
1953 * Register appropriate dfs phyerror event handler
1954 * based on phyerror filtering offload is enabled
1955 * or disabled.
1956 *
1957 * Return: none
1958 */
1959void wma_register_dfs_event_handler(tp_wma_handle wma_handle)
1960{
1961 if (NULL == wma_handle) {
1962 WMA_LOGE("%s:wma_handle is NULL", __func__);
1963 return;
1964 }
1965
1966 if (false == wma_handle->dfs_phyerr_filter_offload) {
1967 /*
1968 * Register the wma_unified_phyerr_rx_event_handler
1969 * for filtering offload disabled case to handle
1970 * the DFS phyerrors.
1971 */
1972 WMA_LOGD("%s:Phyerror Filtering offload is Disabled in ini",
1973 __func__);
1974 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Govind Singhd76a5b02016-03-08 15:12:14 +05301975 WMI_PHYERR_EVENTID,
1976 wma_unified_phyerr_rx_event_handler,
1977 WMA_RX_WORK_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001978 WMA_LOGD("%s: WMI_PHYERR_EVENTID event handler registered",
1979 __func__);
1980 } else {
1981 WMA_LOGD("%s:Phyerror Filtering offload is Enabled in ini",
1982 __func__);
1983 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Govind Singhd76a5b02016-03-08 15:12:14 +05301984 WMI_DFS_RADAR_EVENTID,
1985 wma_unified_dfs_radar_rx_event_handler,
1986 WMA_RX_WORK_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001987 WMA_LOGD("%s:WMI_DFS_RADAR_EVENTID event handler registered",
1988 __func__);
1989 }
1990
1991 return;
1992}
1993
1994
1995/**
1996 * wma_unified_dfs_phyerr_filter_offload_enable() - enable dfs phyerr filter
1997 * @wma_handle: wma handle
1998 *
1999 * Send WMI_DFS_PHYERR_FILTER_ENA_CMDID or
2000 * WMI_DFS_PHYERR_FILTER_DIS_CMDID command
2001 * to firmware based on phyerr filtering
2002 * offload status.
2003 *
2004 * Return: 1 success, 0 failure
2005 */
2006int
2007wma_unified_dfs_phyerr_filter_offload_enable(tp_wma_handle wma_handle)
2008{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002009 int ret;
2010
2011 if (NULL == wma_handle) {
2012 WMA_LOGE("%s:wma_handle is NULL", __func__);
2013 return 0;
2014 }
2015
Govind Singhaa64c242016-03-08 11:31:49 +05302016 ret = wmi_unified_dfs_phyerr_filter_offload_en_cmd(wma_handle->wmi_handle,
2017 wma_handle->dfs_phyerr_filter_offload);
2018 if (ret)
2019 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002020
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002021
Govind Singhaa64c242016-03-08 11:31:49 +05302022 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002023}
2024
2025#if !defined(REMOVE_PKT_LOG)
2026/**
2027 * wma_pktlog_wmi_send_cmd() - send pktlog enable/disable command to target
2028 * @handle: wma handle
2029 * @params: pktlog params
2030 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302031 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002032 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302033QDF_STATUS wma_pktlog_wmi_send_cmd(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002034 struct ath_pktlog_wmi_params *params)
2035{
2036 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhaa64c242016-03-08 11:31:49 +05302037 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002038
2039 /*Check if packet log is enabled in cfg.ini */
2040 if (!cds_is_packet_log_enabled()) {
2041 WMA_LOGE("%s:pkt log is not enabled in cfg.ini", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302042 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002043 }
2044
Govind Singhaa64c242016-03-08 11:31:49 +05302045 ret = wmi_unified_pktlog_wmi_send_cmd(wma_handle->wmi_handle,
2046 params->pktlog_event,
2047 params->cmd_id);
2048 if (ret)
2049 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002050
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002051
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302052 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002053}
2054#endif /* REMOVE_PKT_LOG */
2055
2056static void wma_send_status_to_suspend_ind(tp_wma_handle wma, bool suspended)
2057{
2058 tSirReadyToSuspendInd *ready_to_suspend;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302059 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002060 cds_msg_t cds_msg;
2061 uint8_t len;
2062
2063 WMA_LOGD("Posting ready to suspend indication to umac");
2064
2065 len = sizeof(tSirReadyToSuspendInd);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302066 ready_to_suspend = (tSirReadyToSuspendInd *) qdf_mem_malloc(len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002067
2068 if (NULL == ready_to_suspend) {
2069 WMA_LOGE("%s: Memory allocation failure", __func__);
2070 return;
2071 }
2072
2073 ready_to_suspend->mesgType = eWNI_SME_READY_TO_SUSPEND_IND;
2074 ready_to_suspend->mesgLen = len;
2075 ready_to_suspend->suspended = suspended;
2076
2077 cds_msg.type = eWNI_SME_READY_TO_SUSPEND_IND;
2078 cds_msg.bodyptr = (void *)ready_to_suspend;
2079 cds_msg.bodyval = 0;
2080
2081 status = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302082 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002083 WMA_LOGE("Failed to post ready to suspend");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302084 qdf_mem_free(ready_to_suspend);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002085 }
2086}
2087
2088/**
2089 * wma_wow_wake_reason_str() - Converts wow wakeup reason code to text format
2090 * @wake_reason - WOW wake reason
2091 *
2092 * Return: reason code in string format
2093 */
2094static const u8 *wma_wow_wake_reason_str(A_INT32 wake_reason)
2095{
2096 switch (wake_reason) {
2097 case WOW_REASON_UNSPECIFIED:
2098 return "UNSPECIFIED";
2099 case WOW_REASON_NLOD:
2100 return "NLOD";
2101 case WOW_REASON_AP_ASSOC_LOST:
2102 return "AP_ASSOC_LOST";
2103 case WOW_REASON_LOW_RSSI:
2104 return "LOW_RSSI";
2105 case WOW_REASON_DEAUTH_RECVD:
2106 return "DEAUTH_RECVD";
2107 case WOW_REASON_DISASSOC_RECVD:
2108 return "DISASSOC_RECVD";
2109 case WOW_REASON_GTK_HS_ERR:
2110 return "GTK_HS_ERR";
2111 case WOW_REASON_EAP_REQ:
2112 return "EAP_REQ";
2113 case WOW_REASON_FOURWAY_HS_RECV:
2114 return "FOURWAY_HS_RECV";
2115 case WOW_REASON_TIMER_INTR_RECV:
2116 return "TIMER_INTR_RECV";
2117 case WOW_REASON_PATTERN_MATCH_FOUND:
2118 return "PATTERN_MATCH_FOUND";
2119 case WOW_REASON_RECV_MAGIC_PATTERN:
2120 return "RECV_MAGIC_PATTERN";
2121 case WOW_REASON_P2P_DISC:
2122 return "P2P_DISC";
2123#ifdef FEATURE_WLAN_LPHB
2124 case WOW_REASON_WLAN_HB:
2125 return "WLAN_HB";
2126#endif /* FEATURE_WLAN_LPHB */
2127
2128 case WOW_REASON_CSA_EVENT:
2129 return "CSA_EVENT";
2130 case WOW_REASON_PROBE_REQ_WPS_IE_RECV:
2131 return "PROBE_REQ_RECV";
2132 case WOW_REASON_AUTH_REQ_RECV:
2133 return "AUTH_REQ_RECV";
2134 case WOW_REASON_ASSOC_REQ_RECV:
2135 return "ASSOC_REQ_RECV";
2136 case WOW_REASON_HTT_EVENT:
2137 return "WOW_REASON_HTT_EVENT";
2138#ifdef FEATURE_WLAN_RA_FILTERING
2139 case WOW_REASON_RA_MATCH:
2140 return "WOW_REASON_RA_MATCH";
2141#endif /* FEATURE_WLAN_RA_FILTERING */
2142 case WOW_REASON_BEACON_RECV:
2143 return "WOW_REASON_IBSS_BEACON_RECV";
2144#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
2145 case WOW_REASON_HOST_AUTO_SHUTDOWN:
2146 return "WOW_REASON_HOST_AUTO_SHUTDOWN";
2147#endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
2148#ifdef WLAN_FEATURE_ROAM_OFFLOAD
2149 case WOW_REASON_ROAM_HO:
2150 return "WOW_REASON_ROAM_HO";
2151#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
2152#ifdef FEATURE_WLAN_EXTSCAN
2153 case WOW_REASON_EXTSCAN:
2154 return "WOW_REASON_EXTSCAN";
2155#endif
2156 case WOW_REASON_RSSI_BREACH_EVENT:
2157 return "WOW_REASON_RSSI_BREACH_EVENT";
Srinivas Girigowdae80cea92015-11-23 11:33:57 -08002158 case WOW_REASON_NLO_SCAN_COMPLETE:
2159 return "WOW_REASON_NLO_SCAN_COMPLETE";
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002160 }
2161 return "unknown";
2162}
2163
2164/**
2165 * wma_wow_wake_up_stats_display() - display wow wake up stats
2166 * @wma: Pointer to wma handle
2167 *
2168 * Return: none
2169 */
2170static void wma_wow_wake_up_stats_display(tp_wma_handle wma)
2171{
2172 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",
2173 wma->wow_ucast_wake_up_count,
2174 wma->wow_bcast_wake_up_count,
2175 wma->wow_ipv4_mcast_wake_up_count,
2176 wma->wow_ipv6_mcast_wake_up_count,
2177 wma->wow_ipv6_mcast_ra_stats,
2178 wma->wow_ipv6_mcast_ns_stats,
2179 wma->wow_ipv6_mcast_na_stats,
2180 wma->wow_pno_match_wake_up_count,
2181 wma->wow_pno_complete_wake_up_count,
2182 wma->wow_gscan_wake_up_count,
2183 wma->wow_low_rssi_wake_up_count,
2184 wma->wow_rssi_breach_wake_up_count);
2185
2186 return;
2187}
2188
2189/**
2190 * wma_wow_ipv6_mcast_stats() - ipv6 mcast wake up stats
2191 * @wma: Pointer to wma handle
2192 * @data: Pointer to pattern match data
2193 *
2194 * Return: none
2195 */
2196static void wma_wow_ipv6_mcast_stats(tp_wma_handle wma, uint8_t *data)
2197{
2198 static const uint8_t ipv6_mcast[] = {0x86, 0xDD};
2199
2200 if (!memcmp(ipv6_mcast, (data + WMA_ETHER_TYPE_OFFSET),
2201 sizeof(ipv6_mcast))) {
2202 if (WMA_ICMP_V6_HEADER_TYPE ==
2203 *(data + WMA_ICMP_V6_HEADER_OFFSET)) {
2204 if (WMA_ICMP_V6_RA_TYPE ==
2205 *(data + WMA_ICMP_V6_TYPE_OFFSET))
2206 wma->wow_ipv6_mcast_ra_stats++;
2207 else if (WMA_ICMP_V6_NS_TYPE ==
2208 *(data + WMA_ICMP_V6_TYPE_OFFSET))
2209 wma->wow_ipv6_mcast_ns_stats++;
2210 else if (WMA_ICMP_V6_NA_TYPE ==
2211 *(data + WMA_ICMP_V6_TYPE_OFFSET))
2212 wma->wow_ipv6_mcast_na_stats++;
2213 else
2214 WMA_LOGA("ICMP V6 type : 0x%x",
2215 *(data + WMA_ICMP_V6_TYPE_OFFSET));
2216 } else {
2217 WMA_LOGA("ICMP_V6 header 0x%x",
2218 *(data + WMA_ICMP_V6_HEADER_OFFSET));
2219 }
2220 } else {
2221 WMA_LOGA("Ethertype x%x:0x%x",
2222 *(data + WMA_ETHER_TYPE_OFFSET),
2223 *(data + WMA_ETHER_TYPE_OFFSET + 1));
2224 }
2225
2226 return;
2227}
2228
2229/**
2230 * wma_wow_wake_up_stats() - maintain wow pattern match wake up stats
2231 * @wma: Pointer to wma handle
2232 * @data: Pointer to pattern match data
2233 * @len: Pattern match data length
2234 * @event: Wake up event
2235 *
2236 * Return: none
2237 */
2238static void wma_wow_wake_up_stats(tp_wma_handle wma, uint8_t *data,
2239 int32_t len, WOW_WAKE_REASON_TYPE event)
2240{
2241 switch (event) {
2242
2243 case WOW_REASON_PATTERN_MATCH_FOUND:
2244 if (WMA_BCAST_MAC_ADDR == *data) {
2245 wma->wow_bcast_wake_up_count++;
2246 } else if (WMA_MCAST_IPV4_MAC_ADDR == *data) {
2247 wma->wow_ipv4_mcast_wake_up_count++;
2248 } else if (WMA_MCAST_IPV6_MAC_ADDR == *data) {
2249 wma->wow_ipv6_mcast_wake_up_count++;
2250 if (len > WMA_ICMP_V6_TYPE_OFFSET)
2251 wma_wow_ipv6_mcast_stats(wma, data);
2252 else
2253 WMA_LOGA("ICMP_V6 data len %d", len);
2254 } else {
2255 wma->wow_ucast_wake_up_count++;
2256 }
2257 break;
2258
2259 case WOW_REASON_RA_MATCH:
2260 wma->wow_ipv6_mcast_ra_stats++;
2261 break;
2262
2263 case WOW_REASON_NLOD:
2264 wma->wow_pno_match_wake_up_count++;
2265 break;
2266
2267 case WOW_REASON_NLO_SCAN_COMPLETE:
2268 wma->wow_pno_complete_wake_up_count++;
2269 break;
2270
2271 case WOW_REASON_LOW_RSSI:
2272 wma->wow_low_rssi_wake_up_count++;
2273 break;
2274
2275 case WOW_REASON_EXTSCAN:
2276 wma->wow_gscan_wake_up_count++;
2277 break;
2278
2279 case WOW_REASON_RSSI_BREACH_EVENT:
2280 wma->wow_rssi_breach_wake_up_count++;
2281 break;
2282
2283 default:
2284 WMA_LOGE("Unknown wake up reason");
2285 break;
2286 }
2287
2288 wma_wow_wake_up_stats_display(wma);
2289 return;
2290}
2291
2292/**
2293 * wma_wow_wakeup_host_event() - wakeup host event handler
2294 * @handle: wma handle
2295 * @event: event data
2296 * @len: buffer length
2297 *
2298 * Handler to catch wow wakeup host event. This event will have
2299 * reason why the firmware has woken the host.
2300 *
2301 * Return: 0 for success or error
2302 */
2303int wma_wow_wakeup_host_event(void *handle, uint8_t *event,
2304 uint32_t len)
2305{
2306 tp_wma_handle wma = (tp_wma_handle) handle;
2307 WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *param_buf;
2308 WOW_EVENT_INFO_fixed_param *wake_info;
2309#ifdef FEATURE_WLAN_SCAN_PNO
2310 struct wma_txrx_node *node;
2311#endif /* FEATURE_WLAN_SCAN_PNO */
2312 uint32_t wake_lock_duration = 0;
2313 uint32_t wow_buf_pkt_len = 0;
2314
2315 param_buf = (WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *) event;
2316 if (!param_buf) {
2317 WMA_LOGE("Invalid wow wakeup host event buf");
2318 return -EINVAL;
2319 }
2320
2321 wake_info = param_buf->fixed_param;
2322
2323 WMA_LOGA("WOW wakeup host event received (reason: %s(%d)) for vdev %d",
2324 wma_wow_wake_reason_str(wake_info->wake_reason),
2325 wake_info->wake_reason, wake_info->vdev_id);
2326
Anurag Chouhance0dc992016-02-16 18:18:03 +05302327 qdf_event_set(&wma->wma_resume_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002328
2329 switch (wake_info->wake_reason) {
2330 case WOW_REASON_AUTH_REQ_RECV:
2331 wake_lock_duration = WMA_AUTH_REQ_RECV_WAKE_LOCK_TIMEOUT;
2332 break;
2333
2334 case WOW_REASON_ASSOC_REQ_RECV:
2335 wake_lock_duration = WMA_ASSOC_REQ_RECV_WAKE_LOCK_DURATION;
2336 break;
2337
2338 case WOW_REASON_DEAUTH_RECVD:
2339 wake_lock_duration = WMA_DEAUTH_RECV_WAKE_LOCK_DURATION;
2340 break;
2341
2342 case WOW_REASON_DISASSOC_RECVD:
2343 wake_lock_duration = WMA_DISASSOC_RECV_WAKE_LOCK_DURATION;
2344 break;
2345
2346 case WOW_REASON_AP_ASSOC_LOST:
2347 wake_lock_duration = WMA_BMISS_EVENT_WAKE_LOCK_DURATION;
2348 WMA_LOGA("Beacon miss indication on vdev %x",
2349 wake_info->vdev_id);
2350 wma_beacon_miss_handler(wma, wake_info->vdev_id);
2351 break;
2352#ifdef FEATURE_WLAN_RA_FILTERING
2353 case WOW_REASON_RA_MATCH:
2354 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_RA_MATCH);
2355 break;
2356#endif /* FEATURE_WLAN_RA_FILTERING */
2357#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
2358 case WOW_REASON_HOST_AUTO_SHUTDOWN:
2359 wake_lock_duration = WMA_AUTO_SHUTDOWN_WAKE_LOCK_DURATION;
2360 WMA_LOGA("Received WOW Auto Shutdown trigger in suspend");
2361 if (wma_post_auto_shutdown_msg())
2362 return -EINVAL;
2363 break;
2364#endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
2365#ifdef FEATURE_WLAN_SCAN_PNO
2366 case WOW_REASON_NLOD:
2367 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_NLOD);
2368 node = &wma->interfaces[wake_info->vdev_id];
2369 if (node) {
2370 WMA_LOGD("NLO match happened");
2371 node->nlo_match_evt_received = true;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302372 qdf_wake_lock_timeout_acquire(&wma->pno_wake_lock,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002373 WMA_PNO_MATCH_WAKE_LOCK_TIMEOUT,
2374 WIFI_POWER_EVENT_WAKELOCK_PNO);
Srinivas Girigowdae80cea92015-11-23 11:33:57 -08002375 }
2376 break;
2377
2378 case WOW_REASON_NLO_SCAN_COMPLETE:
2379 {
2380 WMI_NLO_SCAN_COMPLETE_EVENTID_param_tlvs param;
2381
2382 WMA_LOGD("Host woken up due to pno scan complete reason");
2383
2384 /* First 4-bytes of wow_packet_buffer is the length */
2385 if (param_buf->wow_packet_buffer) {
2386 param.fixed_param = (wmi_nlo_event *)
2387 (param_buf->wow_packet_buffer + 4);
2388 wma_nlo_scan_cmp_evt_handler(handle,
2389 (u_int8_t *)&param, sizeof(param));
2390 } else
2391 WMA_LOGD("No wow_packet_buffer present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002392 }
2393 break;
2394#endif /* FEATURE_WLAN_SCAN_PNO */
2395
2396 case WOW_REASON_CSA_EVENT:
2397 {
2398 WMI_CSA_HANDLING_EVENTID_param_tlvs param;
2399 WMA_LOGD("Host woken up because of CSA IE");
2400 param.fixed_param = (wmi_csa_event_fixed_param *)
2401 (((uint8_t *) wake_info)
2402 + sizeof(WOW_EVENT_INFO_fixed_param)
2403 + WOW_CSA_EVENT_OFFSET);
2404 wma_csa_offload_handler(handle, (uint8_t *) &param,
2405 sizeof(param));
2406 }
2407 break;
2408
2409#ifdef FEATURE_WLAN_LPHB
2410 case WOW_REASON_WLAN_HB:
2411 wma_lphb_handler(wma, (uint8_t *) param_buf->hb_indevt);
2412 break;
2413#endif /* FEATURE_WLAN_LPHB */
2414
2415 case WOW_REASON_HTT_EVENT:
2416 break;
2417 case WOW_REASON_PATTERN_MATCH_FOUND:
2418 wma_wow_wake_up_stats_display(wma);
2419 WMA_LOGD("Wake up for Rx packet, dump starting from ethernet hdr");
2420 if (param_buf->wow_packet_buffer) {
2421 /* First 4-bytes of wow_packet_buffer is the length */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302422 qdf_mem_copy((uint8_t *) &wow_buf_pkt_len,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002423 param_buf->wow_packet_buffer, 4);
2424 wma_wow_wake_up_stats(wma,
2425 param_buf->wow_packet_buffer + 4,
2426 wow_buf_pkt_len,
2427 WOW_REASON_PATTERN_MATCH_FOUND);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302428 qdf_trace_hex_dump(QDF_MODULE_ID_WMA,
2429 QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002430 param_buf->wow_packet_buffer + 4,
2431 wow_buf_pkt_len);
2432 } else {
2433 WMA_LOGE("No wow packet buffer present");
2434 }
2435 break;
2436
2437 case WOW_REASON_LOW_RSSI:
2438 {
2439 /* WOW_REASON_LOW_RSSI is used for all roaming events.
2440 * WMI_ROAM_REASON_BETTER_AP, WMI_ROAM_REASON_BMISS,
2441 * WMI_ROAM_REASON_SUITABLE_AP will be handled by
2442 * wma_roam_event_callback().
2443 */
2444 WMI_ROAM_EVENTID_param_tlvs param;
2445 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_LOW_RSSI);
2446 if (param_buf->wow_packet_buffer) {
2447 /* Roam event is embedded in wow_packet_buffer */
2448 WMA_LOGD("Host woken up because of roam event");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302449 qdf_mem_copy((uint8_t *) &wow_buf_pkt_len,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002450 param_buf->wow_packet_buffer, 4);
2451 WMA_LOGD("wow_packet_buffer dump");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302452 qdf_trace_hex_dump(QDF_MODULE_ID_WMA,
2453 QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002454 param_buf->wow_packet_buffer,
2455 wow_buf_pkt_len);
2456 if (wow_buf_pkt_len >= sizeof(param)) {
2457 param.fixed_param =
2458 (wmi_roam_event_fixed_param *)
2459 (param_buf->wow_packet_buffer + 4);
2460 wma_roam_event_callback(handle,
2461 (uint8_t *) &
2462 param,
2463 sizeof(param));
2464 } else {
2465 WMA_LOGE("Wrong length for roam event = %d bytes",
2466 wow_buf_pkt_len);
2467 }
2468 } else {
2469 /* No wow_packet_buffer means a better AP beacon
2470 * will follow in a later event.
2471 */
2472 WMA_LOGD("Host woken up because of better AP beacon");
2473 }
2474 break;
2475 }
2476 case WOW_REASON_CLIENT_KICKOUT_EVENT:
2477 {
2478 WMI_PEER_STA_KICKOUT_EVENTID_param_tlvs param;
2479 if (param_buf->wow_packet_buffer) {
2480 /* station kickout event embedded in wow_packet_buffer */
2481 WMA_LOGD("Host woken up because of sta_kickout event");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302482 qdf_mem_copy((u_int8_t *) &wow_buf_pkt_len,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002483 param_buf->wow_packet_buffer, 4);
2484 WMA_LOGD("wow_packet_buffer dump");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302485 qdf_trace_hex_dump(QDF_MODULE_ID_WMA,
2486 QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002487 param_buf->wow_packet_buffer, wow_buf_pkt_len);
2488 if (wow_buf_pkt_len >= sizeof(param)) {
2489 param.fixed_param = (wmi_peer_sta_kickout_event_fixed_param *)
2490 (param_buf->wow_packet_buffer + 4);
2491 wma_peer_sta_kickout_event_handler(handle,
2492 (u_int8_t *)&param, sizeof(param));
2493 } else {
2494 WMA_LOGE("Wrong length for sta_kickout event = %d bytes",
2495 wow_buf_pkt_len);
2496 }
2497 } else {
2498 WMA_LOGD("No wow_packet_buffer present");
2499 }
2500 break;
2501 }
2502#ifdef FEATURE_WLAN_EXTSCAN
2503 case WOW_REASON_EXTSCAN:
2504 WMA_LOGD("Host woken up because of extscan reason");
2505 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_EXTSCAN);
2506 if (param_buf->wow_packet_buffer) {
2507 wow_buf_pkt_len =
2508 *(uint32_t *)param_buf->wow_packet_buffer;
2509 wma_extscan_wow_event_callback(handle,
2510 (u_int8_t *)(param_buf->wow_packet_buffer + 4),
2511 wow_buf_pkt_len);
2512 } else
2513 WMA_LOGE("wow_packet_buffer is empty");
2514 break;
2515#endif
2516 case WOW_REASON_RSSI_BREACH_EVENT:
2517 {
2518 WMI_RSSI_BREACH_EVENTID_param_tlvs param;
2519
2520 wma_wow_wake_up_stats(wma, NULL, 0,
2521 WOW_REASON_RSSI_BREACH_EVENT);
2522 WMA_LOGD("Host woken up because of rssi breach reason");
2523 /* rssi breach event is embedded in wow_packet_buffer */
2524 if (param_buf->wow_packet_buffer) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302525 qdf_mem_copy((u_int8_t *) &wow_buf_pkt_len,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002526 param_buf->wow_packet_buffer, 4);
2527 if (wow_buf_pkt_len >= sizeof(param)) {
2528 param.fixed_param =
2529 (wmi_rssi_breach_event_fixed_param *)
2530 (param_buf->wow_packet_buffer + 4);
2531 wma_rssi_breached_event_handler(handle,
2532 (u_int8_t *)&param,
2533 sizeof(param));
2534 } else {
2535 WMA_LOGE("%s: Wrong length: %d bytes",
2536 __func__, wow_buf_pkt_len);
2537 }
2538 } else
2539 WMA_LOGD("No wow_packet_buffer present");
2540 }
2541 break;
2542 default:
2543 break;
2544 }
2545
2546 if (wake_lock_duration) {
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302547 qdf_wake_lock_timeout_acquire(&wma->wow_wake_lock,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002548 wake_lock_duration,
2549 WIFI_POWER_EVENT_WAKELOCK_WOW);
2550 WMA_LOGA("Holding %d msec wake_lock", wake_lock_duration);
2551 }
2552
2553 return 0;
2554}
2555
2556/**
2557 * wma_pdev_resume_event_handler() - PDEV resume event handler
2558 * @handle: wma handle
2559 * @event: event data
2560 * @len: buffer length
2561 *
2562 * Return: 0 for success or error
2563 */
2564int wma_pdev_resume_event_handler(void *handle, uint8_t *event, uint32_t len)
2565{
2566 tp_wma_handle wma = (tp_wma_handle) handle;
2567
2568 WMA_LOGA("Received PDEV resume event");
2569
Anurag Chouhance0dc992016-02-16 18:18:03 +05302570 qdf_event_set(&wma->wma_resume_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002571
2572 return 0;
2573}
2574/**
2575 * wma_set_wow_bus_suspend() - set suspend flag
2576 * @wma: wma handle
2577 * @val: value
2578 *
2579 * Return: none
2580 */
2581static inline void wma_set_wow_bus_suspend(tp_wma_handle wma, int val)
2582{
2583
Anurag Chouhan8e0ccd32016-02-19 15:30:20 +05302584 qdf_atomic_set(&wma->is_wow_bus_suspended, val);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002585}
2586
2587
2588
2589/**
2590 * wma_add_wow_wakeup_event() - Configures wow wakeup events.
2591 * @wma: wma handle
2592 * @vdev_id: vdev id
2593 * @bitmap: Event bitmap
2594 * @enable: enable/disable
2595 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302596 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002597 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302598static QDF_STATUS wma_add_wow_wakeup_event(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002599 uint32_t vdev_id,
2600 uint32_t bitmap,
2601 bool enable)
2602{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002603 int ret;
2604
Govind Singhaa64c242016-03-08 11:31:49 +05302605 ret = wmi_unified_add_wow_wakeup_event_cmd(wma->wmi_handle, vdev_id,
2606 enable, bitmap);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002607 if (ret) {
2608 WMA_LOGE("Failed to config wow wakeup event");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302609 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002610 }
2611
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302612 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002613}
2614
2615/**
2616 * wma_send_wow_patterns_to_fw() - Sends WOW patterns to FW.
2617 * @wma: wma handle
2618 * @vdev_id: vdev id
2619 * @ptrn_id: pattern id
2620 * @ptrn: pattern
2621 * @ptrn_len: pattern length
2622 * @ptrn_offset: pattern offset
2623 * @mask: mask
2624 * @mask_len: mask length
2625 * @user: true for user configured pattern and false for default pattern
2626 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302627 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002628 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302629static QDF_STATUS wma_send_wow_patterns_to_fw(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002630 uint8_t vdev_id, uint8_t ptrn_id,
2631 const uint8_t *ptrn, uint8_t ptrn_len,
2632 uint8_t ptrn_offset, const uint8_t *mask,
2633 uint8_t mask_len, bool user)
2634{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002635 struct wma_txrx_node *iface;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002636 int ret;
Govind Singhaa64c242016-03-08 11:31:49 +05302637 uint8_t default_patterns;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002638
2639 iface = &wma->interfaces[vdev_id];
Govind Singhaa64c242016-03-08 11:31:49 +05302640 default_patterns = iface->num_wow_default_patterns++;
2641 ret = wmi_unified_wow_patterns_to_fw_cmd(wma->wmi_handle,
2642 vdev_id, ptrn_id, ptrn,
2643 ptrn_len, ptrn_offset, mask,
2644 mask_len, user, default_patterns);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002645 if (ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002646 if (!user)
2647 iface->num_wow_default_patterns--;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302648 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002649 }
2650
2651 if (user)
2652 iface->num_wow_user_patterns++;
2653
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302654 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002655}
2656
2657/**
2658 * wma_wow_ap() - set WOW patterns in ap mode
2659 * @wma: wma handle
2660 * @vdev_id: vdev id
2661 *
2662 * Configures default WOW pattern for the given vdev_id which is in AP mode.
2663 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302664 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002665 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302666static QDF_STATUS wma_wow_ap(tp_wma_handle wma, uint8_t vdev_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002667{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302668 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002669 uint8_t arp_offset = 20;
2670 uint8_t mac_mask[IEEE80211_ADDR_LEN];
2671
2672 /* Setup unicast pkt pattern */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302673 qdf_mem_set(&mac_mask, IEEE80211_ADDR_LEN, 0xFF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002674 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
2675 wma->interfaces[vdev_id].addr,
2676 IEEE80211_ADDR_LEN, 0, mac_mask,
2677 IEEE80211_ADDR_LEN, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302678 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002679 WMA_LOGE("Failed to add WOW unicast pattern ret %d", ret);
2680 return ret;
2681 }
2682
2683 /*
2684 * Setup all ARP pkt pattern. This is dummy pattern hence the length
2685 * is zero
2686 */
2687 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
2688 arp_ptrn, 0, arp_offset, arp_mask, 0, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302689 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002690 WMA_LOGE("Failed to add WOW ARP pattern ret %d", ret);
2691 return ret;
2692 }
2693
2694 return ret;
2695}
2696
2697/**
2698 * wma_wow_sta() - set WOW patterns in sta mode
2699 * @wma: wma handle
2700 * @vdev_id: vdev id
2701 *
2702 * Configures default WOW pattern for the given vdev_id which is in sta mode.
2703 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302704 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002705 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302706static QDF_STATUS wma_wow_sta(tp_wma_handle wma, uint8_t vdev_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002707{
2708 uint8_t arp_offset = 12;
2709 uint8_t discvr_offset = 30;
2710 uint8_t mac_mask[IEEE80211_ADDR_LEN];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302711 QDF_STATUS ret = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002712
2713 /* Setup unicast pkt pattern */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302714 qdf_mem_set(&mac_mask, IEEE80211_ADDR_LEN, 0xFF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002715 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
2716 wma->interfaces[vdev_id].addr,
2717 IEEE80211_ADDR_LEN, 0, mac_mask,
2718 IEEE80211_ADDR_LEN, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302719 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002720 WMA_LOGE("Failed to add WOW unicast pattern ret %d", ret);
2721 return ret;
2722 }
2723
2724 /*
2725 * Setup multicast pattern for mDNS 224.0.0.251,
2726 * SSDP 239.255.255.250 and LLMNR 224.0.0.252
2727 */
2728 if (wma->ssdp) {
2729 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
2730 discvr_ptrn, sizeof(discvr_ptrn), discvr_offset,
2731 discvr_mask, sizeof(discvr_ptrn), false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302732 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002733 WMA_LOGE("Failed to add WOW mDNS/SSDP/LLMNR pattern");
2734 return ret;
2735 }
2736 } else
2737 WMA_LOGD("mDNS, SSDP, LLMNR patterns are disabled from ini");
2738
2739 /* when arp offload or ns offloaded is disabled
2740 * from ini file, configure broad cast arp pattern
2741 * to fw, so that host can wake up
2742 */
2743 if (!(wma->ol_ini_info & 0x1)) {
2744 /* Setup all ARP pkt pattern */
2745 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
2746 arp_ptrn, sizeof(arp_ptrn), arp_offset,
2747 arp_mask, sizeof(arp_mask), false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302748 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002749 WMA_LOGE("Failed to add WOW ARP pattern");
2750 return ret;
2751 }
2752 }
2753
2754 /* for NS or NDP offload packets */
2755 if (!(wma->ol_ini_info & 0x2)) {
2756 /* Setup all NS pkt pattern */
2757 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
2758 ns_ptrn, sizeof(arp_ptrn), arp_offset,
2759 arp_mask, sizeof(arp_mask), false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302760 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002761 WMA_LOGE("Failed to add WOW NS pattern");
2762 return ret;
2763 }
2764 }
2765
2766 return ret;
2767}
2768
2769/**
2770 * wma_register_wow_default_patterns() - register default wow patterns with fw
2771 * @handle: Pointer to wma handle
2772 * @vdev_id: vdev id
2773 *
2774 * WoW default wake up pattern rule is:
2775 * - For STA & P2P CLI mode register for same STA specific wow patterns
2776 * - For SAP/P2P GO & IBSS mode register for same SAP specific wow patterns
2777 *
2778 * Return: none
2779 */
2780void wma_register_wow_default_patterns(WMA_HANDLE handle, uint8_t vdev_id)
2781{
2782 tp_wma_handle wma = handle;
2783 struct wma_txrx_node *iface;
2784
2785 if (vdev_id > wma->max_bssid) {
2786 WMA_LOGE("Invalid vdev id %d", vdev_id);
2787 return;
2788 }
2789 iface = &wma->interfaces[vdev_id];
2790
2791 if (iface->ptrn_match_enable) {
Houston Hoffman79b4af22015-10-06 12:01:08 -07002792 if (wma_is_vdev_in_beaconning_mode(wma, vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002793 /* Configure SAP/GO/IBSS mode default wow patterns */
2794 WMA_LOGI("Config SAP specific default wow patterns vdev_id %d",
2795 vdev_id);
2796 wma_wow_ap(wma, vdev_id);
2797 } else {
2798 /* Configure STA/P2P CLI mode default wow patterns */
2799 WMA_LOGI("Config STA specific default wow patterns vdev_id %d",
2800 vdev_id);
2801 wma_wow_sta(wma, vdev_id);
2802 if (wma->IsRArateLimitEnabled) {
2803 WMA_LOGI("Config STA RA limit wow patterns vdev_id %d",
2804 vdev_id);
2805 wma_wow_sta_ra_filter(wma, vdev_id);
2806 }
2807 }
2808 }
2809
2810 return;
2811}
2812
2813/**
2814 * wma_register_wow_wakeup_events() - register vdev specific wake events with fw
2815 * @handle: Pointer to wma handle
2816 * @vdev_id: vdev Id
2817 * @vdev_type: vdev type
2818 * @vdev_subtype: vdev sub type
2819 *
2820 * WoW wake up event rule is following:
2821 * 1) STA mode and P2P CLI mode wake up events are same
2822 * 2) SAP mode and P2P GO mode wake up events are same
2823 * 3) IBSS mode wake events are same as STA mode plus WOW_BEACON_EVENT
2824 *
2825 * Return: none
2826 */
2827void wma_register_wow_wakeup_events(WMA_HANDLE handle,
2828 uint8_t vdev_id,
2829 uint8_t vdev_type,
2830 uint8_t vdev_subtype)
2831{
2832 tp_wma_handle wma = handle;
2833 uint32_t event_bitmap;
2834
2835 WMA_LOGI("vdev_type %d vdev_subtype %d vdev_id %d", vdev_type,
2836 vdev_subtype, vdev_id);
2837
2838 if ((WMI_VDEV_TYPE_STA == vdev_type) ||
2839 ((WMI_VDEV_TYPE_AP == vdev_type) &&
2840 (WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE == vdev_subtype))) {
2841 /* Configure STA/P2P CLI mode specific default wake up events */
2842 event_bitmap = WMA_WOW_STA_WAKE_UP_EVENTS;
2843 WMA_LOGI("STA specific default wake up event 0x%x vdev id %d",
2844 event_bitmap, vdev_id);
2845 } else if (WMI_VDEV_TYPE_IBSS == vdev_type) {
2846 /* Configure IBSS mode specific default wake up events */
2847 event_bitmap = (WMA_WOW_STA_WAKE_UP_EVENTS |
2848 (1 << WOW_BEACON_EVENT));
2849 WMA_LOGI("IBSS specific default wake up event 0x%x vdev id %d",
2850 event_bitmap, vdev_id);
2851 } else if (WMI_VDEV_TYPE_AP == vdev_type) {
2852 /* Configure SAP/GO mode specific default wake up events */
2853 event_bitmap = WMA_WOW_SAP_WAKE_UP_EVENTS;
2854 WMA_LOGI("SAP specific default wake up event 0x%x vdev id %d",
2855 event_bitmap, vdev_id);
2856 } else {
2857 WMA_LOGE("unknown type %d subtype %d", vdev_type, vdev_subtype);
2858 return;
2859 }
2860
2861 wma_add_wow_wakeup_event(wma, vdev_id, event_bitmap, true);
2862
2863 return;
2864}
2865
2866/**
2867 * wma_enable_disable_wakeup_event() - Configures wow wakeup events
2868 * @wma: wma handle
2869 * @vdev_id: vdev id
2870 * @bitmap: Event bitmap
2871 * @enable: enable/disable
2872 *
2873 * Return: none
2874 */
2875void wma_enable_disable_wakeup_event(WMA_HANDLE handle,
2876 uint32_t vdev_id,
2877 uint32_t bitmap,
2878 bool enable)
2879{
2880 tp_wma_handle wma = handle;
2881
2882 WMA_LOGI("vdev_id %d wake up event 0x%x enable %d",
2883 vdev_id, bitmap, enable);
2884 wma_add_wow_wakeup_event(wma, vdev_id, bitmap, enable);
2885}
2886
2887/**
2888 * wma_enable_wow_in_fw() - wnable wow in fw
2889 * @wma: wma handle
2890 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302891 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002892 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302893QDF_STATUS wma_enable_wow_in_fw(WMA_HANDLE handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002894{
2895 tp_wma_handle wma = handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002896 int ret;
Komal Seelam3d202862016-02-24 18:43:24 +05302897 struct hif_opaque_softc *scn;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002898 int host_credits;
2899 int wmi_pending_cmds;
Govind Singhd76a5b02016-03-08 15:12:14 +05302900 struct wow_cmd_params param = {0};
2901
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002902#ifdef CONFIG_CNSS
Anurag Chouhan6d760662016-02-20 16:05:43 +05302903 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002904
2905 if (NULL == pMac) {
2906 WMA_LOGE("%s: Unable to get PE context", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302907 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002908 }
2909#endif /* CONFIG_CNSS */
2910
Anurag Chouhance0dc992016-02-16 18:18:03 +05302911 qdf_event_reset(&wma->target_suspend);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002912 wma->wow_nack = 0;
2913
2914 host_credits = wmi_get_host_credits(wma->wmi_handle);
2915 wmi_pending_cmds = wmi_get_pending_cmds(wma->wmi_handle);
2916
2917 WMA_LOGD("Credits:%d; Pending_Cmds: %d",
2918 host_credits, wmi_pending_cmds);
2919
2920 if (host_credits < WMI_WOW_REQUIRED_CREDITS) {
2921 WMA_LOGE("%s: Host Doesn't have enough credits to Post WMI_WOW_ENABLE_CMDID! "
2922 "Credits:%d, pending_cmds:%d\n", __func__, host_credits,
2923 wmi_pending_cmds);
2924#ifndef QCA_WIFI_3_0_EMU
2925 goto error;
2926#endif
2927 }
2928
Govind Singhd76a5b02016-03-08 15:12:14 +05302929 param.enable = true;
2930 param.can_suspend_link = hif_can_suspend_link(wma->htc_handle);
2931 ret = wmi_unified_wow_enable_send(wma->wmi_handle, &param,
2932 WMA_WILDCARD_PDEV_ID);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002933 if (ret) {
2934 WMA_LOGE("Failed to enable wow in fw");
2935 goto error;
2936 }
2937
2938 wmi_set_target_suspend(wma->wmi_handle, true);
2939
Anurag Chouhance0dc992016-02-16 18:18:03 +05302940 if (qdf_wait_single_event(&wma->target_suspend,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002941 WMA_TGT_SUSPEND_COMPLETE_TIMEOUT)
Anurag Chouhance0dc992016-02-16 18:18:03 +05302942 != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002943 WMA_LOGE("Failed to receive WoW Enable Ack from FW");
2944 WMA_LOGE("Credits:%d; Pending_Cmds: %d",
2945 wmi_get_host_credits(wma->wmi_handle),
2946 wmi_get_pending_cmds(wma->wmi_handle));
Prashanth Bhatta9e143052015-12-04 11:56:47 -08002947 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002948#ifdef CONFIG_CNSS
Yue Ma455aff62015-10-20 18:29:16 -07002949 if (pMac->sme.enableSelfRecovery) {
2950 cds_trigger_recovery();
2951 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302952 QDF_BUG(0);
Yue Ma455aff62015-10-20 18:29:16 -07002953 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002954#else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302955 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002956#endif /* CONFIG_CNSS */
Yue Ma455aff62015-10-20 18:29:16 -07002957 } else {
2958 WMA_LOGE("%s: LOGP is in progress, ignore!", __func__);
2959 }
2960
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002961 wmi_set_target_suspend(wma->wmi_handle, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302962 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002963 }
2964
2965 if (wma->wow_nack) {
2966 WMA_LOGE("FW not ready to WOW");
2967 wmi_set_target_suspend(wma->wmi_handle, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302968 return QDF_STATUS_E_AGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002969 }
2970
2971 host_credits = wmi_get_host_credits(wma->wmi_handle);
2972 wmi_pending_cmds = wmi_get_pending_cmds(wma->wmi_handle);
2973
2974 if (host_credits < WMI_WOW_REQUIRED_CREDITS) {
2975 WMA_LOGE("%s: No Credits after HTC ACK:%d, pending_cmds:%d, "
2976 "cannot resume back", __func__, host_credits,
2977 wmi_pending_cmds);
2978 htc_dump_counter_info(wma->htc_handle);
Prashanth Bhatta9e143052015-12-04 11:56:47 -08002979 if (!cds_is_driver_recovering())
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302980 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002981 else
2982 WMA_LOGE("%s: SSR in progress, ignore no credit issue",
2983 __func__);
2984 }
2985
2986 WMA_LOGD("WOW enabled successfully in fw: credits:%d"
2987 "pending_cmds: %d", host_credits, wmi_pending_cmds);
2988
Anurag Chouhan6d760662016-02-20 16:05:43 +05302989 scn = cds_get_context(QDF_MODULE_ID_HIF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002990
2991 if (scn == NULL) {
2992 WMA_LOGE("%s: Failed to get HIF context", __func__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302993 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302994 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002995 }
2996
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002997 wma->wow.wow_enable_cmd_sent = true;
2998
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302999 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003000
3001error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303002 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003003}
3004
3005/**
3006 * wma_resume_req() - clear configured wow patterns in fw
3007 * @wma: wma handle
Houston Hoffmana76591b2015-11-10 16:52:05 -08003008 * @type: type of suspend
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003009 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303010 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003011 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05303012QDF_STATUS wma_resume_req(tp_wma_handle wma, enum qdf_suspend_type type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003013{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303014 if (type == QDF_SYSTEM_SUSPEND) {
Houston Hoffmana76591b2015-11-10 16:52:05 -08003015 wma->no_of_resume_ind++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003016
Houston Hoffmana76591b2015-11-10 16:52:05 -08003017 if (wma->no_of_resume_ind < wma_get_vdev_count(wma))
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303018 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003019
Houston Hoffmana76591b2015-11-10 16:52:05 -08003020 wma->no_of_resume_ind = 0;
3021 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003022
3023 /* Reset the DTIM Parameters */
3024 wma_set_resume_dtim(wma);
3025 /* need to reset if hif_pci_suspend_fails */
3026 wma_set_wow_bus_suspend(wma, 0);
3027 /* unpause the vdev if left paused and hif_pci_suspend fails */
3028 wma_unpause_vdev(wma);
3029
Houston Hoffman1460fa32015-11-18 02:36:30 -08003030 wmi_set_runtime_pm_inprogress(wma->wmi_handle, false);
3031
Houston Hoffmanc45db892015-11-13 19:59:25 -08003032 if (type == QDF_RUNTIME_SUSPEND)
3033 qdf_runtime_pm_allow_suspend(wma->wma_runtime_resume_lock);
3034
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303035 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003036}
3037
3038/**
3039 * wma_wow_delete_pattern() - delete wow pattern in target
3040 * @wma: wma handle
3041 * @ptrn_id: pattern id
3042 * @vdev_id: vdev id
3043 * @user: true for user pattern and false for default pattern
3044 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303045 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003046 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303047static QDF_STATUS wma_wow_delete_pattern(tp_wma_handle wma, uint8_t ptrn_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003048 uint8_t vdev_id, bool user)
3049{
Govind Singhaa64c242016-03-08 11:31:49 +05303050
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003051 struct wma_txrx_node *iface;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003052 int ret;
3053
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003054 iface = &wma->interfaces[vdev_id];
Govind Singhaa64c242016-03-08 11:31:49 +05303055 ret = wmi_unified_wow_delete_pattern_cmd(wma->wmi_handle, ptrn_id,
3056 vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003057 if (ret) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303058 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003059 }
3060
3061 if (user)
3062 iface->num_wow_user_patterns--;
3063
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303064 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003065}
3066
3067/**
3068 * wma_wow_add_pattern() - add wow pattern in target
3069 * @wma: wma handle
3070 * @ptrn: wow pattern
3071 *
3072 * This function does following:
3073 * 1) Delete all default patterns of the vdev
3074 * 2) Add received wow patterns for given vdev in target.
3075 *
3076 * Target is responsible for caching wow patterns accross multiple
3077 * suspend/resumes until the pattern is deleted by user
3078 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303079 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003080 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303081QDF_STATUS wma_wow_add_pattern(tp_wma_handle wma, struct wow_add_pattern *ptrn)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003082{
3083 uint8_t id;
3084 uint8_t bit_to_check, pos;
3085 struct wma_txrx_node *iface;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303086 QDF_STATUS ret = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003087 uint8_t new_mask[SIR_WOWL_BCAST_PATTERN_MAX_SIZE];
3088
3089 if (ptrn->session_id > wma->max_bssid) {
3090 WMA_LOGE("Invalid vdev id (%d)", ptrn->session_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303091 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003092 }
3093
3094 iface = &wma->interfaces[ptrn->session_id];
3095
3096 /* clear all default patterns cofigured by wma */
3097 for (id = 0; id < iface->num_wow_default_patterns; id++)
3098 wma_wow_delete_pattern(wma, id, ptrn->session_id, false);
3099
3100 iface->num_wow_default_patterns = 0;
3101
3102 WMA_LOGI("Add user passed wow pattern id %d vdev id %d",
3103 ptrn->pattern_id, ptrn->session_id);
3104 /*
3105 * Convert received pattern mask value from bit representation
3106 * to byte representation.
3107 *
3108 * For example, received value from umac,
3109 *
3110 * Mask value : A1 (equivalent binary is "1010 0001")
3111 * Pattern value : 12:00:13:00:00:00:00:44
3112 *
3113 * The value which goes to FW after the conversion from this
3114 * function (1 in mask value will become FF and 0 will
3115 * become 00),
3116 *
3117 * Mask value : FF:00:FF:00:0:00:00:FF
3118 * Pattern value : 12:00:13:00:00:00:00:44
3119 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303120 qdf_mem_zero(new_mask, sizeof(new_mask));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003121 for (pos = 0; pos < ptrn->pattern_size; pos++) {
3122 bit_to_check = (WMA_NUM_BITS_IN_BYTE - 1) -
3123 (pos % WMA_NUM_BITS_IN_BYTE);
3124 bit_to_check = 0x1 << bit_to_check;
3125 if (ptrn->pattern_mask[pos / WMA_NUM_BITS_IN_BYTE] &
3126 bit_to_check)
3127 new_mask[pos] = WMA_WOW_PTRN_MASK_VALID;
3128 }
3129
3130 ret = wma_send_wow_patterns_to_fw(wma, ptrn->session_id,
3131 ptrn->pattern_id,
3132 ptrn->pattern, ptrn->pattern_size,
3133 ptrn->pattern_byte_offset, new_mask,
3134 ptrn->pattern_size, true);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303135 if (ret != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003136 WMA_LOGE("Failed to add wow pattern %d", ptrn->pattern_id);
3137
3138 return ret;
3139}
3140
3141/**
3142 * wma_wow_delete_user_pattern() - delete user configured wow pattern in target
3143 * @wma: wma handle
3144 * @ptrn: wow pattern
3145 *
3146 * This function does following:
3147 * 1) Deletes a particular user configured wow pattern in target
3148 * 2) After deleting all user wow patterns add default wow patterns
3149 * specific to that vdev.
3150 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303151 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003152 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303153QDF_STATUS wma_wow_delete_user_pattern(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003154 struct wow_delete_pattern *pattern)
3155{
3156 struct wma_txrx_node *iface;
3157
3158 if (pattern->session_id > wma->max_bssid) {
3159 WMA_LOGE("Invalid vdev id %d", pattern->session_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303160 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003161 }
3162
3163 iface = &wma->interfaces[pattern->session_id];
3164 if (iface->num_wow_user_patterns <= 0) {
3165 WMA_LOGE("No valid user pattern. Num user pattern %u vdev %d",
3166 iface->num_wow_user_patterns, pattern->session_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303167 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003168 }
3169
3170 WMA_LOGI("Delete user passed wow pattern id %d total user pattern %d",
3171 pattern->pattern_id, iface->num_wow_user_patterns);
3172
3173 wma_wow_delete_pattern(wma, pattern->pattern_id,
3174 pattern->session_id, true);
3175
3176 /* configure default patterns once all user patterns are deleted */
3177 if (!iface->num_wow_user_patterns)
3178 wma_register_wow_default_patterns(wma, pattern->session_id);
3179
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303180 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003181}
3182
3183/**
3184 * wma_wow_enter() - store enable/disable status for pattern
3185 * @wma: wma handle
3186 * @info: wow parameters
3187 *
3188 * Records pattern enable/disable status locally. This choice will
3189 * take effect when the driver enter into suspend state.
3190 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303191 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003192 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303193QDF_STATUS wma_wow_enter(tp_wma_handle wma, tpSirHalWowlEnterParams info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003194{
3195 struct wma_txrx_node *iface;
3196
3197 WMA_LOGD("wow enable req received for vdev id: %d", info->sessionId);
3198
3199 if (info->sessionId > wma->max_bssid) {
3200 WMA_LOGE("Invalid vdev id (%d)", info->sessionId);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303201 qdf_mem_free(info);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303202 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003203 }
3204
3205 iface = &wma->interfaces[info->sessionId];
3206 iface->ptrn_match_enable = info->ucPatternFilteringEnable ?
3207 true : false;
3208 wma->wow.magic_ptrn_enable = info->ucMagicPktEnable ? true : false;
3209 wma->wow.deauth_enable = info->ucWowDeauthRcv ? true : false;
3210 wma->wow.disassoc_enable = info->ucWowDeauthRcv ? true : false;
3211 wma->wow.bmiss_enable = info->ucWowMaxMissedBeacons ? true : false;
3212
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303213 qdf_mem_free(info);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003214
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_exit() - clear all wma states
3220 * @wma: wma handle
3221 * @info: wow params
3222 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303223 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003224 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303225QDF_STATUS wma_wow_exit(tp_wma_handle wma, tpSirHalWowlExitParams info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003226{
3227 struct wma_txrx_node *iface;
3228
3229 WMA_LOGD("wow disable req received for vdev id: %d", info->sessionId);
3230
3231 if (info->sessionId > wma->max_bssid) {
3232 WMA_LOGE("Invalid vdev id (%d)", info->sessionId);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303233 qdf_mem_free(info);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303234 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003235 }
3236
3237 iface = &wma->interfaces[info->sessionId];
3238 iface->ptrn_match_enable = false;
3239 wma->wow.magic_ptrn_enable = false;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303240 qdf_mem_free(info);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003241
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303242 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003243}
3244
3245/**
Houston Hoffmana76591b2015-11-10 16:52:05 -08003246 * wma_calculate_and_update_conn_state(): calculate each interfaces conn state
3247 * @wma: validated wma handle
3248 *
3249 * Identifies any vdev that is up and not in ap mode as connected.
3250 * stores this in the interfaces conn_state varible.
3251 */
3252void wma_calculate_and_update_conn_state(tp_wma_handle wma)
3253{
3254 int i;
3255 for (i = 0; i < wma->max_bssid; i++) {
3256 wma->interfaces[i].conn_state =
3257 !!(wma->interfaces[i].vdev_up &&
3258 !wma_is_vdev_in_ap_mode(wma, i));
3259 }
3260}
3261
3262/**
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003263 * wma_update_conn_state(): synchronize wma & hdd
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003264 * @wma: wma handle
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003265 * @conn_state: boolean array to populate
3266 * @len: validation parameter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003267 *
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003268 * populate interfaces conn_state with true if the interface
3269 * is a connected client and wow will configure a pattern.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003270 */
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003271void wma_update_conn_state(tp_wma_handle wma, uint32_t conn_mask)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003272{
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003273 int i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003274 for (i = 0; i < wma->max_bssid; i++) {
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003275 if (conn_mask & (1 << i))
3276 wma->interfaces[i].conn_state = true;
3277 else
3278 wma->interfaces[i].conn_state = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003279 }
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003280
3281 if (wma->wow.magic_ptrn_enable)
3282 return;
3283
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003284 for (i = 0; i < wma->max_bssid; i++) {
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003285 if (!wma->interfaces[i].ptrn_match_enable)
3286 wma->interfaces[i].conn_state = false;
3287 }
3288}
3289
3290/**
3291 * wma_is_beaconning_vdev_up(): check if a beaconning vdev is up
3292 * @wma: wma handle
3293 *
3294 * Return TRUE if beaconning vdev is up
3295 */
3296static inline
3297bool wma_is_beaconning_vdev_up(tp_wma_handle wma)
3298{
3299 int i;
3300 for (i = 0; i < wma->max_bssid; i++) {
3301 if (wma_is_vdev_in_beaconning_mode(wma, i)
3302 && wma->interfaces[i].vdev_up)
3303 return true;
3304 }
3305 return false;
3306}
3307
3308/**
3309 * wma_support_wow_for_beaconing: wow query for beaconning
3310 * @wma: wma handle
3311 *
3312 * Need to configure wow to enable beaconning offload when
3313 * a beaconing vdev is up and beaonning offload is configured.
3314 *
3315 * Return: true if we need to enable wow for beaconning offload
3316 */
3317static inline
3318bool wma_support_wow_for_beaconing(tp_wma_handle wma)
3319{
3320 if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
3321 WMI_SERVICE_BEACON_OFFLOAD)) {
3322 if (wma_is_beaconning_vdev_up(wma))
3323 return true;
3324 }
3325 return false;
3326}
3327
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003328#ifdef FEATURE_WLAN_SCAN_PNO
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003329/**
3330 * wma_is_pnoscan_in_progress(): check if a pnoscan is in progress
3331 * @wma: wma handle
3332 * @vdev_id: vdev_id
3333 *
3334 * Return: TRUE/FALSE
3335 */
3336static inline
3337bool wma_is_pnoscan_in_progress(tp_wma_handle wma, int vdev_id)
3338{
3339 return wma->interfaces[vdev_id].pno_in_progress;
3340}
Houston Hoffman345fa402015-12-16 11:28:51 -08003341
3342/**
3343 * wma_is_pnoscan_match_found(): check if a scan match was found
3344 * @wma: wma handle
3345 * @vdev_id: vdev_id
3346 *
3347 * Return: TRUE/FALSE
3348 */
3349static inline
3350bool wma_is_pnoscan_match_found(tp_wma_handle wma, int vdev_id)
3351{
3352 return wma->interfaces[vdev_id].nlo_match_evt_received;
3353}
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003354#else
3355/**
3356 * wma_is_pnoscan_in_progress(): dummy
3357 *
Houston Hoffman345fa402015-12-16 11:28:51 -08003358 * Return: False since no pnoscan cannot be in progress
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003359 * when feature flag is not defined.
3360 */
3361bool wma_is_pnoscan_in_progress(tp_wma_handle wma, int vdev_id)
3362{
3363 return FALSE;
3364}
Houston Hoffman345fa402015-12-16 11:28:51 -08003365
3366/**
3367 * wma_is_pnoscan_match_found(): dummy
3368 * @wma: wma handle
3369 * @vdev_id: vdev_id
3370 *
3371 * Return: False since no pnoscan cannot occur
3372 * when feature flag is not defined.
3373 */
3374static inline
3375bool wma_is_pnoscan_match_found(tp_wma_handle wma, int vdev_id)
3376{
3377 return FALSE;
3378}
Houston Hoffman61667962015-12-15 20:15:41 -08003379#endif
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003380
3381#ifdef FEATURE_WLAN_EXTSCAN
3382static inline
3383/**
3384 * wma_is_extscan_in_progress(): check if an extscan is in progress
3385 * @wma: wma handle
3386 * @vdev_id: vdev_id
3387 *
3388 * Return: TRUE/FALSvE
3389 */
3390bool wma_is_extscan_in_progress(tp_wma_handle wma, int vdev_id)
3391{
3392 return wma->interfaces[vdev_id].extscan_in_progress;
3393}
3394#else
3395/**
3396 * wma_is_extscan_in_progress(): dummy
3397 *
3398 * Return: False since no extscan can be in progress
3399 * when feature flag is not defined.
3400 */
3401bool wma_is_extscan_in_progress(tp_wma_handle wma, int vdev_id)
3402{
3403 return false;
3404}
3405#endif
3406
3407/**
3408 * wma_is_wow_applicable(): should enable wow
3409 * @wma: wma handle
3410 *
3411 * Enable WOW if any one of the condition meets,
3412 * 1) Is any one of vdev in beaconning mode (in AP mode) ?
3413 * 2) Is any one of vdev in connected state (in STA mode) ?
3414 * 3) Is PNO in progress in any one of vdev ?
3415 * 4) Is Extscan in progress in any one of vdev ?
Rajeev Kumaraea89632016-02-02 18:02:32 -08003416 * If none of above conditions is true then return false
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003417 *
Rajeev Kumaraea89632016-02-02 18:02:32 -08003418 * Return: true if wma needs to configure wow false otherwise.
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003419 */
3420bool wma_is_wow_applicable(tp_wma_handle wma)
3421{
3422 int vdev_id;
3423 if (wma_support_wow_for_beaconing(wma)) {
3424 WMA_LOGD("vdev is in beaconning mode, enabling wow");
3425 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003426 }
3427
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003428 for (vdev_id = 0; vdev_id < wma->max_bssid; vdev_id++) {
3429 if (wma->interfaces[vdev_id].conn_state) {
3430 WMA_LOGD("STA is connected, enabling wow");
3431 return true;
3432 } else if (wma_is_pnoscan_in_progress(wma, vdev_id)) {
3433 WMA_LOGD("PNO is in progress, enabling wow");
3434 return true;
3435 } else if (wma_is_extscan_in_progress(wma, vdev_id)) {
3436 WMA_LOGD("EXT is in progress, enabling wow");
3437 return true;
3438 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003439 }
3440
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003441 WMA_LOGD("All vdev are in disconnected state and pno/extscan is not in progress, skipping wow");
Rajeev Kumaraea89632016-02-02 18:02:32 -08003442 return false;
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003443}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003444
Houston Hoffman345fa402015-12-16 11:28:51 -08003445/**
3446 * wma_configure_dynamic_wake_events(): configure dyanmic wake events
3447 * @wma: wma handle
3448 *
3449 * Some wake events need to be enabled dynamically. Controll those here.
3450 *
3451 * Return: none
3452 */
3453void wma_configure_dynamic_wake_events(tp_wma_handle wma)
3454{
3455 int vdev_id;
3456 int enable_mask;
3457 int disable_mask;
3458
3459 for (vdev_id = 0; vdev_id < wma->max_bssid; vdev_id++) {
3460 enable_mask = 0;
3461 disable_mask = 0;
3462
3463 if (wma_is_pnoscan_in_progress(wma, vdev_id)) {
3464 if (wma_is_pnoscan_match_found(wma, vdev_id))
3465 enable_mask |=
3466 (1 << WOW_NLO_SCAN_COMPLETE_EVENT);
3467 else
3468 disable_mask |=
3469 (1 << WOW_NLO_SCAN_COMPLETE_EVENT);
3470 }
3471
3472 if (enable_mask != 0)
3473 wma_enable_disable_wakeup_event(wma, vdev_id,
3474 enable_mask, true);
3475 if (disable_mask != 0)
3476 wma_enable_disable_wakeup_event(wma, vdev_id,
3477 disable_mask, false);
3478 }
3479}
3480
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003481#ifdef FEATURE_WLAN_LPHB
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003482/**
3483 * wma_apply_lphb(): apply cached LPHB settings
3484 * @wma: wma handle
3485 *
3486 * LPHB cache, if any item was enabled, should be
3487 * applied.
3488 */
3489static inline
3490void wma_apply_lphb(tp_wma_handle wma)
3491{
3492 int i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003493 WMA_LOGD("%s: checking LPHB cache", __func__);
3494 for (i = 0; i < 2; i++) {
3495 if (wma->wow.lphb_cache[i].params.lphbEnableReq.enable) {
3496 WMA_LOGD("%s: LPHB cache for item %d is marked as enable",
3497 __func__, i + 1);
3498 wma_lphb_conf_hbenable(wma, &(wma->wow.lphb_cache[i]),
3499 false);
3500 }
3501 }
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003502}
3503#else
3504void wma_apply_lphb(tp_wma_handle wma) {}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003505#endif /* FEATURE_WLAN_LPHB */
3506
Houston Hoffmana76591b2015-11-10 16:52:05 -08003507static void wma_notify_suspend_req_procesed(tp_wma_handle wma,
Anurag Chouhan6d760662016-02-20 16:05:43 +05303508 enum qdf_suspend_type type)
Houston Hoffmana76591b2015-11-10 16:52:05 -08003509{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303510 if (type == QDF_SYSTEM_SUSPEND)
Houston Hoffmana76591b2015-11-10 16:52:05 -08003511 wma_send_status_to_suspend_ind(wma, true);
Anurag Chouhan6d760662016-02-20 16:05:43 +05303512 else if (type == QDF_RUNTIME_SUSPEND)
Anurag Chouhance0dc992016-02-16 18:18:03 +05303513 qdf_event_set(&wma->runtime_suspend);
Houston Hoffmana76591b2015-11-10 16:52:05 -08003514}
3515
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003516/**
3517 * wma_suspend_req() - Handles suspend indication request received from umac.
3518 * @wma: wma handle
Houston Hoffmana76591b2015-11-10 16:52:05 -08003519 * @type: type of suspend
3520 *
3521 * The type controlls how we notify the indicator that the indication has
3522 * been processed
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003523 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303524 * Return: QDF status
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003525 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05303526QDF_STATUS wma_suspend_req(tp_wma_handle wma, enum qdf_suspend_type type)
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003527{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303528 if (type == QDF_RUNTIME_SUSPEND)
Houston Hoffman1460fa32015-11-18 02:36:30 -08003529 wmi_set_runtime_pm_inprogress(wma->wmi_handle, true);
3530
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003531 if (wma_is_wow_applicable(wma)) {
3532 WMA_LOGE("WOW Suspend");
3533 wma_apply_lphb(wma);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003534
Houston Hoffman345fa402015-12-16 11:28:51 -08003535 wma_configure_dynamic_wake_events(wma);
3536
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003537 wma->wow.wow_enable = true;
3538 wma->wow.wow_enable_cmd_sent = false;
3539 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003540
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003541 /* Set the Suspend DTIM Parameters */
3542 wma_set_suspend_dtim(wma);
Houston Hoffmana76591b2015-11-10 16:52:05 -08003543
3544 wma_notify_suspend_req_procesed(wma, type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003545
3546 /* to handle race between hif_pci_suspend and
3547 * unpause/pause tx handler
3548 */
3549 wma_set_wow_bus_suspend(wma, 1);
3550
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303551 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003552}
3553
3554/**
3555 * wma_send_host_wakeup_ind_to_fw() - send wakeup ind to fw
3556 * @wma: wma handle
3557 *
3558 * Sends host wakeup indication to FW. On receiving this indication,
3559 * FW will come out of WOW.
3560 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303561 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003562 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303563static QDF_STATUS wma_send_host_wakeup_ind_to_fw(tp_wma_handle wma)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003564{
Anurag Chouhance0dc992016-02-16 18:18:03 +05303565 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003566 int ret;
3567#ifdef CONFIG_CNSS
Anurag Chouhan6d760662016-02-20 16:05:43 +05303568 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003569 if (NULL == pMac) {
3570 WMA_LOGE("%s: Unable to get PE context", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303571 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003572 }
3573#endif /* CONFIG_CNSS */
3574
Anurag Chouhance0dc992016-02-16 18:18:03 +05303575 qdf_event_reset(&wma->wma_resume_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003576
Govind Singhaa64c242016-03-08 11:31:49 +05303577 ret = wmi_unified_host_wakeup_ind_to_fw_cmd(wma->wmi_handle);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003578 if (ret) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303579 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003580 }
3581
3582 WMA_LOGD("Host wakeup indication sent to fw");
3583
Anurag Chouhance0dc992016-02-16 18:18:03 +05303584 qdf_status = qdf_wait_single_event(&(wma->wma_resume_event),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003585 WMA_RESUME_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05303586 if (QDF_STATUS_SUCCESS != qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003587 WMA_LOGP("%s: Timeout waiting for resume event from FW",
3588 __func__);
3589 WMA_LOGP("%s: Pending commands %d credits %d", __func__,
3590 wmi_get_pending_cmds(wma->wmi_handle),
3591 wmi_get_host_credits(wma->wmi_handle));
Prashanth Bhatta9e143052015-12-04 11:56:47 -08003592 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003593#ifdef CONFIG_CNSS
3594 if (pMac->sme.enableSelfRecovery) {
3595 cds_trigger_recovery();
3596 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303597 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003598 }
3599#else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303600 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003601#endif /* CONFIG_CNSS */
3602 } else {
3603 WMA_LOGE("%s: SSR in progress, ignore resume timeout",
3604 __func__);
3605 }
3606 } else {
3607 WMA_LOGD("Host wakeup received");
3608 }
3609
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303610 if (QDF_STATUS_SUCCESS == qdf_status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003611 wmi_set_target_suspend(wma->wmi_handle, false);
3612
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303613 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003614}
3615
3616/**
3617 * wma_disable_wow_in_fw() - Disable wow in PCIe resume context.
3618 * @handle: wma handle
3619 *
3620 * Return: 0 for success or error code
3621 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303622QDF_STATUS wma_disable_wow_in_fw(WMA_HANDLE handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003623{
3624 tp_wma_handle wma = handle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303625 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003626
3627 if (!wma->wow.wow_enable || !wma->wow.wow_enable_cmd_sent)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303628 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003629
3630 ret = wma_send_host_wakeup_ind_to_fw(wma);
3631
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303632 if (ret != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003633 return ret;
3634
3635 wma->wow.wow_enable = false;
3636 wma->wow.wow_enable_cmd_sent = false;
3637
3638 /* To allow the tx pause/unpause events */
3639 wma_set_wow_bus_suspend(wma, 0);
3640 /* Unpause the vdev as we are resuming */
3641 wma_unpause_vdev(wma);
3642
3643 return ret;
3644}
3645
3646#ifdef WLAN_FEATURE_LPSS
3647/**
3648 * wma_is_lpass_enabled() - check if lpass is enabled
3649 * @handle: Pointer to wma handle
3650 *
3651 * WoW is needed if LPASS or NaN feature is enabled in INI because
3652 * target can't wake up itself if its put in PDEV suspend when LPASS
3653 * or NaN features are supported
3654 *
3655 * Return: true if lpass is enabled else false
3656 */
3657bool static wma_is_lpass_enabled(tp_wma_handle wma)
3658{
3659 if (wma->is_lpass_enabled)
3660 return true;
3661 else
3662 return false;
3663}
3664#else
3665bool static wma_is_lpass_enabled(tp_wma_handle wma)
3666{
3667 return false;
3668}
3669#endif
3670
3671#ifdef WLAN_FEATURE_NAN
3672/**
3673 * wma_is_nan_enabled() - check if NaN is enabled
3674 * @handle: Pointer to wma handle
3675 *
3676 * WoW is needed if LPASS or NaN feature is enabled in INI because
3677 * target can't wake up itself if its put in PDEV suspend when LPASS
3678 * or NaN features are supported
3679 *
3680 * Return: true if NaN is enabled else false
3681 */
3682bool static wma_is_nan_enabled(tp_wma_handle wma)
3683{
3684 if (wma->is_nan_enabled)
3685 return true;
3686 else
3687 return false;
3688}
3689#else
3690bool static wma_is_nan_enabled(tp_wma_handle wma)
3691{
3692 return false;
3693}
3694#endif
3695
3696/**
3697 * wma_is_wow_mode_selected() - check if wow needs to be enabled in fw
3698 * @handle: Pointer to wma handle
3699 *
3700 * If lpass is enabled then always do wow else check wow_enable config
3701 *
3702 * Return: true is wow mode is needed else false
3703 */
Houston Hoffmana76591b2015-11-10 16:52:05 -08003704bool wma_is_wow_mode_selected(WMA_HANDLE handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003705{
3706 tp_wma_handle wma = (tp_wma_handle) handle;
3707
3708 if (wma_is_lpass_enabled(wma)) {
3709 WMA_LOGD("LPASS is enabled select WoW");
3710 return true;
3711 } else if (wma_is_nan_enabled(wma)) {
3712 WMA_LOGD("NAN is enabled select WoW");
3713 return true;
3714 } else {
3715 WMA_LOGD("WoW enable %d", wma->wow.wow_enable);
3716 return wma->wow.wow_enable;
3717 }
3718}
3719
3720/**
3721 * wma_del_ts_req() - send DELTS request to fw
3722 * @wma: wma handle
3723 * @msg: delts params
3724 *
3725 * Return: none
3726 */
3727void wma_del_ts_req(tp_wma_handle wma, tDelTsParams *msg)
3728{
Govind Singhaa64c242016-03-08 11:31:49 +05303729 if (wmi_unified_del_ts_cmd(wma->wmi_handle,
3730 msg->sessionId,
3731 TID_TO_WME_AC(msg->userPrio))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003732 WMA_LOGP("%s: Failed to send vdev DELTS command", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003733 }
Govind Singhaa64c242016-03-08 11:31:49 +05303734
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003735#ifdef WLAN_FEATURE_ROAM_OFFLOAD
3736 if (msg->setRICparams == true)
3737 wma_set_ric_req(wma, msg, false);
3738#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
3739
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303740 qdf_mem_free(msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003741}
3742
3743/**
3744 * wma_aggr_qos_req() - send aggr qos request to fw
3745 * @wma: handle to wma
3746 * @pAggrQosRspMsg - combined struct for all ADD_TS requests.
3747 *
3748 * A function to handle WMA_AGGR_QOS_REQ. This will send out
3749 * ADD_TS requestes to firmware in loop for all the ACs with
3750 * active flow.
3751 *
3752 * Return: none
3753 */
3754void wma_aggr_qos_req(tp_wma_handle wma,
3755 tAggrAddTsParams *pAggrQosRspMsg)
3756{
Govind Singhaa64c242016-03-08 11:31:49 +05303757 wmi_unified_aggr_qos_cmd(wma->wmi_handle,
3758 (struct aggr_add_ts_param *)pAggrQosRspMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003759 /* send reponse to upper layers from here only. */
3760 wma_send_msg(wma, WMA_AGGR_QOS_RSP, pAggrQosRspMsg, 0);
3761}
3762
3763/**
3764 * wma_add_ts_req() - send ADDTS request to fw
3765 * @wma: wma handle
3766 * @msg: ADDTS params
3767 *
3768 * Return: none
3769 */
3770void wma_add_ts_req(tp_wma_handle wma, tAddTsParams *msg)
3771{
Govind Singhaa64c242016-03-08 11:31:49 +05303772 struct add_ts_param cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003773
3774#ifdef FEATURE_WLAN_ESE
3775 /*
3776 * msmt_interval is in unit called TU (1 TU = 1024 us)
3777 * max value of msmt_interval cannot make resulting
3778 * interval_miliseconds overflow 32 bit
3779 */
3780 uint32_t intervalMiliseconds;
Anurag Chouhan6d760662016-02-20 16:05:43 +05303781 ol_txrx_pdev_handle pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003782 if (NULL == pdev) {
3783 WMA_LOGE("%s: Failed to get pdev", __func__);
3784 goto err;
3785 }
3786
3787 intervalMiliseconds = (msg->tsm_interval * 1024) / 1000;
3788
3789 ol_tx_set_compute_interval(pdev, intervalMiliseconds);
3790#endif /* FEATURE_WLAN_ESE */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303791 msg->status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003792
Govind Singhaa64c242016-03-08 11:31:49 +05303793
3794 cmd.sme_session_id = msg->sme_session_id;
3795 cmd.tspec.tsinfo.traffic.userPrio =
3796 TID_TO_WME_AC(msg->tspec.tsinfo.traffic.userPrio);
3797 cmd.tspec.mediumTime = msg->tspec.mediumTime;
3798 if (wmi_unified_add_ts_cmd(wma->wmi_handle, &cmd))
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303799 msg->status = QDF_STATUS_E_FAILURE;
Govind Singhaa64c242016-03-08 11:31:49 +05303800
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003801#ifdef WLAN_FEATURE_ROAM_OFFLOAD
3802 if (msg->setRICparams == true)
3803 wma_set_ric_req(wma, msg, true);
3804#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
3805
3806err:
3807 wma_send_msg(wma, WMA_ADD_TS_RSP, msg, 0);
3808}
3809
3810/**
3811 * wma_enable_disable_packet_filter() - enable/disable packet filter in target
3812 * @wma: Pointer to wma handle
3813 * @vdev_id: vdev id
3814 * @enable: Flag to enable/disable packet filter
3815 *
3816 * Return: 0 for success or error code
3817 */
3818static int wma_enable_disable_packet_filter(tp_wma_handle wma,
3819 uint8_t vdev_id, bool enable)
3820{
Govind Singhaa64c242016-03-08 11:31:49 +05303821 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003822
Govind Singhaa64c242016-03-08 11:31:49 +05303823 ret = wmi_unified_enable_disable_packet_filter_cmd(wma->wmi_handle,
3824 vdev_id, enable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003825 if (ret)
3826 WMA_LOGE("Failed to send packet filter wmi cmd to fw");
3827
3828 return ret;
3829}
3830
3831/**
3832 * wma_config_packet_filter() - configure packet filter in target
3833 * @wma: Pointer to wma handle
3834 * @vdev_id: vdev id
3835 * @rcv_filter_param: Packet filter parameters
3836 * @filter_id: Filter id
3837 * @enable: Flag to add/delete packet filter configuration
3838 *
3839 * Return: 0 for success or error code
3840 */
3841static int wma_config_packet_filter(tp_wma_handle wma,
3842 uint8_t vdev_id, tSirRcvPktFilterCfgType *rcv_filter_param,
3843 uint8_t filter_id, bool enable)
3844{
Govind Singhaa64c242016-03-08 11:31:49 +05303845 int err;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003846
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003847 /* send the command along with data */
Govind Singhaa64c242016-03-08 11:31:49 +05303848 err = wmi_unified_config_packet_filter_cmd(wma->wmi_handle,
3849 vdev_id, (struct rcv_pkt_filter_config *)rcv_filter_param,
3850 filter_id, enable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003851 if (err) {
3852 WMA_LOGE("Failed to send pkt_filter cmd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003853 return -EIO;
3854 }
3855
3856 /* Enable packet filter */
3857 if (enable)
3858 wma_enable_disable_packet_filter(wma, vdev_id, true);
3859
3860 return 0;
3861}
3862
3863/**
3864 * wma_process_receive_filter_set_filter_req() - enable packet filter
3865 * @wma_handle: wma handle
3866 * @rcv_filter_param: filter params
3867 *
3868 * Return: 0 for success or error code
3869 */
3870int wma_process_receive_filter_set_filter_req(tp_wma_handle wma,
3871 tSirRcvPktFilterCfgType *rcv_filter_param)
3872{
3873 int ret = 0;
3874 uint8_t vdev_id;
3875
3876 /* Get the vdev id */
Srinivas Girigowda98530492015-11-20 17:39:24 -08003877 if (!wma_find_vdev_by_bssid(wma,
3878 rcv_filter_param->bssid.bytes, &vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003879 WMA_LOGE("vdev handle is invalid for %pM",
Srinivas Girigowda98530492015-11-20 17:39:24 -08003880 rcv_filter_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003881 return -EINVAL;
3882 }
3883
3884 ret = wma_config_packet_filter(wma, vdev_id, rcv_filter_param,
3885 rcv_filter_param->filterId, true);
3886
3887 return ret;
3888}
3889
3890/**
3891 * wma_process_receive_filter_clear_filter_req() - disable packet filter
3892 * @wma_handle: wma handle
3893 * @rcv_clear_param: filter params
3894 *
3895 * Return: 0 for success or error code
3896 */
3897int wma_process_receive_filter_clear_filter_req(tp_wma_handle wma,
3898 tSirRcvFltPktClearParam *rcv_clear_param)
3899{
3900 int ret = 0;
3901 uint8_t vdev_id;
3902
3903 /* Get the vdev id */
Srinivas Girigowda98530492015-11-20 17:39:24 -08003904 if (!wma_find_vdev_by_bssid(wma,
3905 rcv_clear_param->bssid.bytes, &vdev_id)) {
3906 WMA_LOGE("vdev handle is invalid for %pM",
3907 rcv_clear_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003908 return -EINVAL;
3909 }
3910
3911 ret = wma_config_packet_filter(wma, vdev_id, NULL,
3912 rcv_clear_param->filterId, false);
3913
3914 return ret;
3915}
3916
3917#ifdef FEATURE_WLAN_ESE
3918
3919#define TSM_DELAY_HISTROGRAM_BINS 4
3920/**
3921 * wma_process_tsm_stats_req() - process tsm stats request
3922 * @wma_handler - handle to wma
3923 * @pTsmStatsMsg - TSM stats struct that needs to be populated and
3924 * passed in message.
3925 *
3926 * A parallel function to WMA_ProcessTsmStatsReq for pronto. This
3927 * function fetches stats from data path APIs and post
3928 * WMA_TSM_STATS_RSP msg back to LIM.
3929 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303930 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003931 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303932QDF_STATUS wma_process_tsm_stats_req(tp_wma_handle wma_handler,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003933 void *pTsmStatsMsg)
3934{
3935 uint8_t counter;
3936 uint32_t queue_delay_microsec = 0;
3937 uint32_t tx_delay_microsec = 0;
3938 uint16_t packet_count = 0;
3939 uint16_t packet_loss_count = 0;
3940 tpAniTrafStrmMetrics pTsmMetric = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003941 tpAniGetTsmStatsReq pStats = (tpAniGetTsmStatsReq) pTsmStatsMsg;
3942 tpAniGetTsmStatsRsp pTsmRspParams = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003943 int tid = pStats->tid;
3944 /*
3945 * The number of histrogram bin report by data path api are different
3946 * than required by TSM, hence different (6) size array used
3947 */
3948 uint16_t bin_values[QCA_TX_DELAY_HIST_REPORT_BINS] = { 0, };
3949
Anurag Chouhan6d760662016-02-20 16:05:43 +05303950 ol_txrx_pdev_handle pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003951
3952 if (NULL == pdev) {
3953 WMA_LOGE("%s: Failed to get pdev", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303954 qdf_mem_free(pTsmStatsMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303955 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003956 }
3957
3958 /* get required values from data path APIs */
3959 ol_tx_delay(pdev, &queue_delay_microsec, &tx_delay_microsec, tid);
3960 ol_tx_delay_hist(pdev, bin_values, tid);
3961 ol_tx_packet_count(pdev, &packet_count, &packet_loss_count, tid);
3962
Srinivas Girigowda515a9ef2015-12-11 11:00:48 -08003963 pTsmRspParams = qdf_mem_malloc(sizeof(*pTsmRspParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003964 if (NULL == pTsmRspParams) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303965 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303966 "%s: QDF MEM Alloc Failure", __func__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303967 QDF_ASSERT(0);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303968 qdf_mem_free(pTsmStatsMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303969 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003970 }
3971 pTsmRspParams->staId = pStats->staId;
3972 pTsmRspParams->rc = eSIR_FAILURE;
3973 pTsmRspParams->tsmStatsReq = pStats;
3974 pTsmMetric = &pTsmRspParams->tsmMetrics;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003975 /* populate pTsmMetric */
3976 pTsmMetric->UplinkPktQueueDly = queue_delay_microsec;
3977 /* store only required number of bin values */
3978 for (counter = 0; counter < TSM_DELAY_HISTROGRAM_BINS; counter++) {
3979 pTsmMetric->UplinkPktQueueDlyHist[counter] =
3980 bin_values[counter];
3981 }
3982 pTsmMetric->UplinkPktTxDly = tx_delay_microsec;
3983 pTsmMetric->UplinkPktLoss = packet_loss_count;
3984 pTsmMetric->UplinkPktCount = packet_count;
3985
3986 /*
3987 * No need to populate roaming delay and roaming count as they are
3988 * being populated just before sending IAPP frame out
3989 */
3990 /* post this message to LIM/PE */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003991 wma_send_msg(wma_handler, WMA_TSM_STATS_RSP, (void *)pTsmRspParams, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303992 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003993}
3994
3995#endif /* FEATURE_WLAN_ESE */
3996
3997/**
3998 * wma_add_clear_mcbc_filter() - set mcast filter command to fw
3999 * @wma_handle: wma handle
4000 * @vdev_id: vdev id
4001 * @multicastAddr: mcast address
4002 * @clearList: clear list flag
4003 *
4004 * Return: 0 for success or error code
4005 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304006static QDF_STATUS wma_add_clear_mcbc_filter(tp_wma_handle wma_handle,
4007 uint8_t vdev_id,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304008 struct qdf_mac_addr multicast_addr,
Srinivas Girigowda98530492015-11-20 17:39:24 -08004009 bool clearList)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004010{
Himanshu Agarwal44195412016-03-09 13:03:54 +05304011 return wmi_unified_add_clear_mcbc_filter_cmd(wma_handle->wmi_handle,
4012 vdev_id, multicast_addr, clearList);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004013}
4014
4015/**
4016 * wma_process_mcbc_set_filter_req() - process mcbc set filter request
4017 * @wma_handle: wma handle
4018 * @mcbc_param: mcbc params
4019 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304020 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004021 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304022QDF_STATUS wma_process_mcbc_set_filter_req(tp_wma_handle wma_handle,
Anurag Chouhance0dc992016-02-16 18:18:03 +05304023 tSirRcvFltMcAddrList *mcbc_param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004024{
4025 uint8_t vdev_id = 0;
4026 int i;
4027
4028 if (mcbc_param->ulMulticastAddrCnt <= 0) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004029 WMA_LOGW("Number of multicast addresses is 0");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304030 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004031 }
4032
Srinivas Girigowda98530492015-11-20 17:39:24 -08004033 if (!wma_find_vdev_by_addr(wma_handle,
4034 mcbc_param->self_macaddr.bytes, &vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004035 WMA_LOGE("%s: Failed to find vdev id for %pM", __func__,
Srinivas Girigowda98530492015-11-20 17:39:24 -08004036 mcbc_param->bssid.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304037 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004038 }
4039 /* set mcbc_param->action to clear MCList and reset
4040 * to configure the MCList in FW
4041 */
4042
4043 for (i = 0; i < mcbc_param->ulMulticastAddrCnt; i++) {
4044 wma_add_clear_mcbc_filter(wma_handle, vdev_id,
4045 mcbc_param->multicastAddr[i],
4046 (mcbc_param->action == 0));
4047 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304048 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004049}
4050
4051#ifdef WLAN_FEATURE_GTK_OFFLOAD
4052#define GTK_OFFLOAD_ENABLE 0
4053#define GTK_OFFLOAD_DISABLE 1
4054
4055/**
4056 * wma_gtk_offload_status_event() - GTK offload status event handler
4057 * @handle: wma handle
4058 * @event: event buffer
4059 * @len: buffer length
4060 *
4061 * Return: 0 for success or error code
4062 */
4063int wma_gtk_offload_status_event(void *handle, uint8_t *event,
4064 uint32_t len)
4065{
4066 tp_wma_handle wma = (tp_wma_handle) handle;
4067 WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param *status;
4068 WMI_GTK_OFFLOAD_STATUS_EVENTID_param_tlvs *param_buf;
4069 tpSirGtkOffloadGetInfoRspParams resp;
4070 cds_msg_t cds_msg;
4071 uint8_t *bssid;
4072
4073 WMA_LOGD("%s Enter", __func__);
4074
4075 param_buf = (WMI_GTK_OFFLOAD_STATUS_EVENTID_param_tlvs *) event;
4076 if (!param_buf) {
4077 WMA_LOGE("param_buf is NULL");
4078 return -EINVAL;
4079 }
4080
4081 status = (WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param *) param_buf->fixed_param;
4082
4083 if (len < sizeof(WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param)) {
4084 WMA_LOGE("Invalid length for GTK status");
4085 return -EINVAL;
4086 }
4087 bssid = wma_find_bssid_by_vdev_id(wma, status->vdev_id);
4088 if (!bssid) {
4089 WMA_LOGE("invalid bssid for vdev id %d", status->vdev_id);
4090 return -ENOENT;
4091 }
4092
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304093 resp = qdf_mem_malloc(sizeof(*resp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004094 if (!resp) {
4095 WMA_LOGE("%s: Failed to alloc response", __func__);
4096 return -ENOMEM;
4097 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304098 qdf_mem_zero(resp, sizeof(*resp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004099 resp->mesgType = eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP;
4100 resp->mesgLen = sizeof(*resp);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304101 resp->ulStatus = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004102 resp->ulTotalRekeyCount = status->refresh_cnt;
4103 /* TODO: Is the total rekey count and GTK rekey count same? */
4104 resp->ulGTKRekeyCount = status->refresh_cnt;
4105
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304106 qdf_mem_copy(&resp->ullKeyReplayCounter, &status->replay_counter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004107 GTK_REPLAY_COUNTER_BYTES);
4108
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304109 qdf_mem_copy(resp->bssid.bytes, bssid, IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004110
4111#ifdef IGTK_OFFLOAD
4112 /* TODO: Is the refresh count same for GTK and IGTK? */
4113 resp->ulIGTKRekeyCount = status->refresh_cnt;
4114#endif /* IGTK_OFFLOAD */
4115
4116 cds_msg.type = eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP;
4117 cds_msg.bodyptr = (void *)resp;
4118 cds_msg.bodyval = 0;
4119
4120 if (cds_mq_post_message(CDS_MQ_ID_SME, (cds_msg_t *) &cds_msg)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304121 != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004122 WMA_LOGE("Failed to post GTK response to SME");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304123 qdf_mem_free(resp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004124 return -EINVAL;
4125 }
4126
4127 WMA_LOGD("GTK: got target status with replay counter "
4128 "%02x%02x%02x%02x%02x%02x%02x%02x. vdev %d "
4129 "Refresh GTK %d times exchanges since last set operation",
4130 status->replay_counter[0],
4131 status->replay_counter[1],
4132 status->replay_counter[2],
4133 status->replay_counter[3],
4134 status->replay_counter[4],
4135 status->replay_counter[5],
4136 status->replay_counter[6],
4137 status->replay_counter[7],
4138 status->vdev_id, status->refresh_cnt);
4139
4140 WMA_LOGD("%s Exit", __func__);
4141
4142 return 0;
4143}
4144
4145/**
4146 * wma_send_gtk_offload_req() - send GTK offload command to fw
4147 * @wma: wma handle
4148 * @vdev_id: vdev id
4149 * @params: GTK offload parameters
4150 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304151 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004152 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304153static QDF_STATUS wma_send_gtk_offload_req(tp_wma_handle wma, uint8_t vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004154 tpSirGtkOffloadParams params)
4155{
Himanshu Agarwal44195412016-03-09 13:03:54 +05304156 struct gtk_offload_params offload_params = {0};
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304157 QDF_STATUS status = QDF_STATUS_SUCCESS;
Himanshu Agarwal44195412016-03-09 13:03:54 +05304158 bool enable_offload;
4159 uint32_t gtk_offload_opcode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004160
4161 WMA_LOGD("%s Enter", __func__);
4162
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004163 /* Request target to enable GTK offload */
4164 if (params->ulFlags == GTK_OFFLOAD_ENABLE) {
Himanshu Agarwal44195412016-03-09 13:03:54 +05304165 gtk_offload_opcode = GTK_OFFLOAD_ENABLE_OPCODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004166 wma->wow.gtk_err_enable[vdev_id] = true;
4167
4168 /* Copy the keys and replay counter */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304169 qdf_mem_copy(offload_params.aKCK, params->aKCK,
4170 GTK_OFFLOAD_KCK_BYTES);
4171 qdf_mem_copy(offload_params.aKEK, params->aKEK,
4172 GTK_OFFLOAD_KEK_BYTES);
4173 qdf_mem_copy(&offload_params.ullKeyReplayCounter,
4174 &params->ullKeyReplayCounter, GTK_REPLAY_COUNTER_BYTES);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004175 } else {
4176 wma->wow.gtk_err_enable[vdev_id] = false;
Himanshu Agarwal44195412016-03-09 13:03:54 +05304177 gtk_offload_opcode = GTK_OFFLOAD_DISABLE_OPCODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004178 }
4179
Himanshu Agarwal44195412016-03-09 13:03:54 +05304180 enable_offload = params->ulFlags;
4181
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004182 /* send the wmi command */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304183 status = wmi_unified_send_gtk_offload_cmd(wma->wmi_handle,
4184 vdev_id, &offload_params,
4185 enable_offload,
4186 gtk_offload_opcode);
4187 if (QDF_IS_STATUS_ERROR(status))
4188 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004189
Himanshu Agarwal44195412016-03-09 13:03:54 +05304190 WMA_LOGD("VDEVID: %d, GTK_FLAGS: x%x", vdev_id, gtk_offload_opcode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004191out:
4192 WMA_LOGD("%s Exit", __func__);
4193 return status;
4194}
4195
4196/**
4197 * wma_process_gtk_offload_req() - process GTK offload req from umac
4198 * @handle: wma handle
4199 * @params: GTK offload params
4200 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304201 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004202 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304203QDF_STATUS wma_process_gtk_offload_req(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004204 tpSirGtkOffloadParams params)
4205{
4206 uint8_t vdev_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304207 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004208
4209 WMA_LOGD("%s Enter", __func__);
4210
4211 /* Get the vdev id */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08004212 if (!wma_find_vdev_by_bssid(wma, params->bssid.bytes, &vdev_id)) {
4213 WMA_LOGE("vdev handle is invalid for %pM", params->bssid.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304214 status = QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004215 goto out;
4216 }
4217
4218 /* Validate vdev id */
4219 if (vdev_id >= wma->max_bssid) {
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08004220 WMA_LOGE("invalid vdev_id %d for %pM", vdev_id,
4221 params->bssid.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304222 status = QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004223 goto out;
4224 }
4225
4226 if ((params->ulFlags == GTK_OFFLOAD_ENABLE) &&
4227 (wma->wow.gtk_err_enable[vdev_id] == true)) {
4228 WMA_LOGE("%s GTK Offload already enabled. Disable it first "
4229 "vdev_id %d", __func__, vdev_id);
4230 params->ulFlags = GTK_OFFLOAD_DISABLE;
4231 status = wma_send_gtk_offload_req(wma, vdev_id, params);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304232 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004233 WMA_LOGE("%s Failed to disable GTK Offload", __func__);
4234 goto out;
4235 }
4236 WMA_LOGD("%s Enable GTK Offload again with updated inputs",
4237 __func__);
4238 params->ulFlags = GTK_OFFLOAD_ENABLE;
4239 }
4240 status = wma_send_gtk_offload_req(wma, vdev_id, params);
4241out:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304242 qdf_mem_free(params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004243 WMA_LOGD("%s Exit", __func__);
4244 return status;
4245}
4246
4247/**
4248 * wma_process_gtk_offload_getinfo_req() - send GTK offload cmd to fw
4249 * @wma: wma handle
4250 * @params: GTK offload params
4251 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304252 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004253 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304254QDF_STATUS wma_process_gtk_offload_getinfo_req(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004255 tpSirGtkOffloadGetInfoRspParams params)
4256{
4257 uint8_t vdev_id;
Himanshu Agarwal44195412016-03-09 13:03:54 +05304258 uint64_t offload_req_opcode;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304259 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004260
4261 WMA_LOGD("%s Enter", __func__);
4262
4263 /* Get the vdev id */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08004264 if (!wma_find_vdev_by_bssid(wma, params->bssid.bytes, &vdev_id)) {
4265 WMA_LOGE("vdev handle is invalid for %pM", params->bssid.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304266 status = QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004267 goto out;
4268 }
4269
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004270 /* Request for GTK offload status */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304271 offload_req_opcode = GTK_OFFLOAD_REQUEST_STATUS_OPCODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004272
4273 /* send the wmi command */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304274 status = wmi_unified_process_gtk_offload_getinfo_cmd(wma->wmi_handle,
4275 vdev_id, offload_req_opcode);
4276
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004277out:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304278 qdf_mem_free(params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004279 WMA_LOGD("%s Exit", __func__);
4280 return status;
4281}
4282#endif /* WLAN_FEATURE_GTK_OFFLOAD */
4283
4284/**
4285 * wma_enable_arp_ns_offload() - enable ARP NS offload
4286 * @wma: wma handle
4287 * @tpSirHostOffloadReq: offload request
Govind Singhaa64c242016-03-08 11:31:49 +05304288 * @arp_only: flag
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004289 *
4290 * To configure ARP NS off load data to firmware
4291 * when target goes to wow mode.
4292 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304293 * Return: QDF Status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004294 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304295QDF_STATUS wma_enable_arp_ns_offload(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004296 tpSirHostOffloadReq
Govind Singhaa64c242016-03-08 11:31:49 +05304297 pHostOffloadParams, bool arp_only)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004298{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004299 int32_t res;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004300 uint8_t vdev_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004301
4302 /* Get the vdev id */
Srinivas Girigowdab084b552015-11-24 12:39:12 -08004303 if (!wma_find_vdev_by_bssid(wma, pHostOffloadParams->bssid.bytes,
4304 &vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004305 WMA_LOGE("vdev handle is invalid for %pM",
Srinivas Girigowdab084b552015-11-24 12:39:12 -08004306 pHostOffloadParams->bssid.bytes);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304307 qdf_mem_free(pHostOffloadParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304308 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004309 }
4310
4311 if (!wma->interfaces[vdev_id].vdev_up) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004312 WMA_LOGE("vdev %d is not up skipping arp/ns offload", vdev_id);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304313 qdf_mem_free(pHostOffloadParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304314 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004315 }
4316
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004317
Govind Singhaa64c242016-03-08 11:31:49 +05304318 res = wmi_unified_enable_arp_ns_offload_cmd(wma->wmi_handle,
4319 (struct host_offload_req_param *)pHostOffloadParams,
4320 arp_only,
4321 vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004322 if (res) {
4323 WMA_LOGE("Failed to enable ARP NDP/NSffload");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304324 qdf_mem_free(pHostOffloadParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304325 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004326 }
4327
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304328 qdf_mem_free(pHostOffloadParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304329 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004330}
4331
4332/**
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08004333 * wma_process_cesium_enable_ind() - enables cesium functionality in target
4334 * @wma: wma handle
4335 *
4336 * Return: QDF status
4337 */
4338QDF_STATUS wma_process_cesium_enable_ind(tp_wma_handle wma)
4339{
4340 QDF_STATUS ret;
4341 int32_t vdev_id;
4342
4343 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
4344 if (vdev_id < 0) {
4345 WMA_LOGE("%s: IBSS vdev does not exist could not enable cesium",
4346 __func__);
4347 return QDF_STATUS_E_FAILURE;
4348 }
4349
4350 /* Send enable cesium command to target */
4351 WMA_LOGE("Enable cesium in target for vdevId %d ", vdev_id);
4352 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
4353 WMI_VDEV_PARAM_ENABLE_RMC, 1);
4354 if (ret) {
4355 WMA_LOGE("Enable cesium failed for vdevId %d", vdev_id);
4356 return QDF_STATUS_E_FAILURE;
4357 }
4358 return QDF_STATUS_SUCCESS;
4359}
4360
4361/**
4362 * wma_process_get_peer_info_req() - sends get peer info cmd to target
4363 * @wma: wma handle
4364 * @preq: get peer info request
4365 *
4366 * Return: QDF status
4367 */
4368QDF_STATUS wma_process_get_peer_info_req
4369 (tp_wma_handle wma, tSirIbssGetPeerInfoReqParams *pReq)
4370{
4371 int32_t ret;
4372 uint8_t *p;
4373 uint16_t len;
4374 wmi_buf_t buf;
4375 int32_t vdev_id;
4376 ol_txrx_pdev_handle pdev;
4377 struct ol_txrx_peer_t *peer;
4378 uint8_t peer_mac[IEEE80211_ADDR_LEN];
4379 wmi_peer_info_req_cmd_fixed_param *p_get_peer_info_cmd;
4380 uint8_t bcast_mac[IEEE80211_ADDR_LEN] = { 0xff, 0xff, 0xff,
4381 0xff, 0xff, 0xff };
4382
4383 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
4384 if (vdev_id < 0) {
4385 WMA_LOGE("%s: IBSS vdev does not exist could not get peer info",
4386 __func__);
4387 return QDF_STATUS_E_FAILURE;
4388 }
4389
4390 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
4391 if (NULL == pdev) {
4392 WMA_LOGE("%s: Failed to get pdev context", __func__);
4393 return QDF_STATUS_E_FAILURE;
4394 }
4395
4396 if (0xFF == pReq->staIdx) {
4397 /*get info for all peers */
4398 qdf_mem_copy(peer_mac, bcast_mac, IEEE80211_ADDR_LEN);
4399 } else {
4400 /*get info for a single peer */
4401 peer = ol_txrx_peer_find_by_local_id(pdev, pReq->staIdx);
4402 if (!peer) {
4403 WMA_LOGE("%s: Failed to get peer handle using peer id %d",
4404 __func__, pReq->staIdx);
4405 return QDF_STATUS_E_FAILURE;
4406 }
4407 WMA_LOGE("%s: staIdx %d peer mac: 0x%2x:0x%2x:0x%2x:0x%2x:0x%2x:0x%2x",
4408 __func__, pReq->staIdx, peer->mac_addr.raw[0],
4409 peer->mac_addr.raw[1], peer->mac_addr.raw[2],
4410 peer->mac_addr.raw[3], peer->mac_addr.raw[4],
4411 peer->mac_addr.raw[5]);
4412 qdf_mem_copy(peer_mac, peer->mac_addr.raw, IEEE80211_ADDR_LEN);
4413 }
4414
4415 len = sizeof(wmi_peer_info_req_cmd_fixed_param);
4416 buf = wmi_buf_alloc(wma->wmi_handle, len);
4417 if (!buf) {
4418 WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__);
4419 return QDF_STATUS_E_FAILURE;
4420 }
4421
4422 p = (uint8_t *) wmi_buf_data(buf);
4423 qdf_mem_zero(p, len);
4424 p_get_peer_info_cmd = (wmi_peer_info_req_cmd_fixed_param *) p;
4425
4426 WMITLV_SET_HDR(&p_get_peer_info_cmd->tlv_header,
4427 WMITLV_TAG_STRUC_wmi_peer_info_req_cmd_fixed_param,
4428 WMITLV_GET_STRUCT_TLVLEN
4429 (wmi_peer_info_req_cmd_fixed_param));
4430
4431 p_get_peer_info_cmd->vdev_id = vdev_id;
4432 WMI_CHAR_ARRAY_TO_MAC_ADDR(peer_mac,
4433 &p_get_peer_info_cmd->peer_mac_address);
4434
4435 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
4436 WMI_PEER_INFO_REQ_CMDID);
4437
4438 WMA_LOGE("IBSS get peer info cmd sent len: %d, vdev %d"
4439 " command id: %d, status: %d", len,
4440 p_get_peer_info_cmd->vdev_id, WMI_PEER_INFO_REQ_CMDID, ret);
4441
4442 return QDF_STATUS_SUCCESS;
4443}
4444
4445/**
4446 * wma_process_tx_fail_monitor_ind() - sends tx fail monitor cmd to target
4447 * @wma: wma handle
4448 * @pReq: tx fail monitor command params
4449 *
4450 * Return: QDF status
4451 */
4452QDF_STATUS wma_process_tx_fail_monitor_ind
4453 (tp_wma_handle wma, tAniTXFailMonitorInd *pReq)
4454{
4455 QDF_STATUS ret;
4456 int32_t vdev_id;
4457
4458 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
4459 if (vdev_id < 0) {
4460 WMA_LOGE("%s: IBSS vdev does not exist could not send fast tx fail"
4461 " monitor indication message to target", __func__);
4462 return QDF_STATUS_E_FAILURE;
4463 }
4464
4465 /* Send enable cesium command to target */
4466 WMA_LOGE("send fast tx fail monitor ind cmd target for vdevId %d val %d",
4467 vdev_id, pReq->tx_fail_count);
4468
4469 if (0 == pReq->tx_fail_count) {
4470 wma->hddTxFailCb = NULL;
4471 } else {
4472 wma->hddTxFailCb = pReq->txFailIndCallback;
4473 }
4474 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
4475 WMI_VDEV_PARAM_SET_IBSS_TX_FAIL_CNT_THR,
4476 pReq->tx_fail_count);
4477 if (ret) {
4478 WMA_LOGE("tx fail monitor failed for vdevId %d", vdev_id);
4479 return QDF_STATUS_E_FAILURE;
4480 }
4481
4482 return QDF_STATUS_SUCCESS;
4483}
4484
4485/**
4486 * wma_process_rmc_enable_ind() - enables RMC functionality in target
4487 * @wma: wma handle
4488 *
4489 * Return: QDF status
4490 */
4491QDF_STATUS wma_process_rmc_enable_ind(tp_wma_handle wma)
4492{
4493 int ret;
4494 uint8_t *p;
4495 uint16_t len;
4496 wmi_buf_t buf;
4497 int32_t vdev_id;
4498 wmi_rmc_set_mode_cmd_fixed_param *p_rmc_enable_cmd;
4499
4500 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
4501 if (vdev_id < 0) {
4502 WMA_LOGE("%s: IBSS vdev does not exist could not enable RMC",
4503 __func__);
4504 return QDF_STATUS_E_FAILURE;
4505 }
4506
4507 len = sizeof(wmi_rmc_set_mode_cmd_fixed_param);
4508 buf = wmi_buf_alloc(wma->wmi_handle, len);
4509 if (!buf) {
4510 WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__);
4511 return QDF_STATUS_E_FAILURE;
4512 }
4513
4514 p = (uint8_t *) wmi_buf_data(buf);
4515 qdf_mem_zero(p, len);
4516 p_rmc_enable_cmd = (wmi_rmc_set_mode_cmd_fixed_param *) p;
4517
4518 WMITLV_SET_HDR(&p_rmc_enable_cmd->tlv_header,
4519 WMITLV_TAG_STRUC_wmi_rmc_set_mode_cmd_fixed_param,
4520 WMITLV_GET_STRUCT_TLVLEN
4521 (wmi_rmc_set_mode_cmd_fixed_param));
4522
4523 p_rmc_enable_cmd->vdev_id = vdev_id;
4524 p_rmc_enable_cmd->enable_rmc = WMI_RMC_MODE_ENABLED;
4525
4526 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
4527 WMI_RMC_SET_MODE_CMDID);
4528
4529 WMA_LOGE("Enable RMC cmd sent len: %d, vdev %d" " command id: %d,"
4530 " status: %d", len, p_rmc_enable_cmd->vdev_id,
4531 WMI_RMC_SET_MODE_CMDID, ret);
4532
4533 return QDF_STATUS_SUCCESS;
4534}
4535
4536/**
4537 * wma_process_rmc_disable_ind() - disables rmc functionality in target
4538 * @wma: wma handle
4539 *
4540 * Return: QDF status
4541 */
4542QDF_STATUS wma_process_rmc_disable_ind(tp_wma_handle wma)
4543{
4544 int ret;
4545 uint8_t *p;
4546 uint16_t len;
4547 wmi_buf_t buf;
4548 int32_t vdev_id;
4549 wmi_rmc_set_mode_cmd_fixed_param *p_rmc_disable_cmd;
4550
4551 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
4552 if (vdev_id < 0) {
4553 WMA_LOGE("%s: IBSS vdev does not exist could not disable RMC",
4554 __func__);
4555 return QDF_STATUS_E_FAILURE;
4556 }
4557
4558 len = sizeof(wmi_rmc_set_mode_cmd_fixed_param);
4559 buf = wmi_buf_alloc(wma->wmi_handle, len);
4560 if (!buf) {
4561 WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__);
4562 return QDF_STATUS_E_FAILURE;
4563 }
4564
4565 p = (uint8_t *) wmi_buf_data(buf);
4566 qdf_mem_zero(p, len);
4567 p_rmc_disable_cmd = (wmi_rmc_set_mode_cmd_fixed_param *) p;
4568
4569 WMITLV_SET_HDR(&p_rmc_disable_cmd->tlv_header,
4570 WMITLV_TAG_STRUC_wmi_rmc_set_mode_cmd_fixed_param,
4571 WMITLV_GET_STRUCT_TLVLEN
4572 (wmi_rmc_set_mode_cmd_fixed_param));
4573
4574 p_rmc_disable_cmd->vdev_id = vdev_id;
4575 p_rmc_disable_cmd->enable_rmc = WMI_RMC_MODE_DISABLED;
4576
4577 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
4578 WMI_RMC_SET_MODE_CMDID);
4579
4580 WMA_LOGE("Disable RMC cmd sent len: %d, vdev %d" " command id: %d,"
4581 " status: %d", len, p_rmc_disable_cmd->vdev_id,
4582 WMI_RMC_SET_MODE_CMDID, ret);
4583
4584 return QDF_STATUS_SUCCESS;
4585}
4586
4587/**
4588 * wma_process_rmc_action_period_ind() - sends RMC action period to target
4589 * @wma: wma handle
4590 *
4591 * Return: QDF status
4592 */
4593QDF_STATUS wma_process_rmc_action_period_ind(tp_wma_handle wma)
4594{
4595 int ret;
4596 uint8_t *p;
4597 uint16_t len;
4598 uint32_t val;
4599 wmi_buf_t buf;
4600 int32_t vdev_id;
4601 wmi_rmc_set_action_period_cmd_fixed_param *p_rmc_cmd;
4602 struct sAniSirGlobal *mac = cds_get_context(QDF_MODULE_ID_PE);
4603
4604 if (NULL == mac) {
4605 WMA_LOGE("%s: MAC mac does not exist", __func__);
4606 return QDF_STATUS_E_FAILURE;
4607 }
4608
4609 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
4610 if (vdev_id < 0) {
4611 WMA_LOGE("%s: IBSS vdev does not exist could not send"
4612 " RMC action period to target", __func__);
4613 return QDF_STATUS_E_FAILURE;
4614 }
4615
4616 len = sizeof(wmi_rmc_set_action_period_cmd_fixed_param);
4617 buf = wmi_buf_alloc(wma->wmi_handle, len);
4618 if (!buf) {
4619 WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__);
4620 return QDF_STATUS_E_FAILURE;
4621 }
4622
4623 p = (uint8_t *) wmi_buf_data(buf);
4624 qdf_mem_zero(p, len);
4625 p_rmc_cmd = (wmi_rmc_set_action_period_cmd_fixed_param *) p;
4626
4627 WMITLV_SET_HDR(&p_rmc_cmd->tlv_header,
4628 WMITLV_TAG_STRUC_wmi_rmc_set_action_period_cmd_fixed_param,
4629 WMITLV_GET_STRUCT_TLVLEN
4630 (wmi_rmc_set_action_period_cmd_fixed_param));
4631
4632 if (wlan_cfg_get_int(mac, WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY, &val)
4633 != eSIR_SUCCESS) {
4634 WMA_LOGE("Failed to get value for RMC action period using default");
4635 val = WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_STADEF;
4636 }
4637
4638 p_rmc_cmd->vdev_id = vdev_id;
4639 p_rmc_cmd->periodicity_msec = val;
4640
4641 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
4642 WMI_RMC_SET_ACTION_PERIOD_CMDID);
4643
4644 WMA_LOGE("RMC action period %d cmd sent len: %d, vdev %d"
4645 " command id: %d, status: %d", p_rmc_cmd->periodicity_msec,
4646 len, p_rmc_cmd->vdev_id, WMI_RMC_SET_ACTION_PERIOD_CMDID, ret);
4647
4648 return QDF_STATUS_SUCCESS;
4649}
4650
4651/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004652 * wma_process_add_periodic_tx_ptrn_ind - add periodic tx ptrn
4653 * @handle: wma handle
4654 * @pAddPeriodicTxPtrnParams: tx ptrn params
4655 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304656 * Retrun: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004657 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304658QDF_STATUS wma_process_add_periodic_tx_ptrn_ind(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004659 tSirAddPeriodicTxPtrn *
4660 pAddPeriodicTxPtrnParams)
4661{
4662 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Himanshu Agarwal44195412016-03-09 13:03:54 +05304663 struct periodic_tx_pattern params;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004664 uint8_t vdev_id;
Himanshu Agarwal44195412016-03-09 13:03:54 +05304665
4666 qdf_mem_set(&params, sizeof(struct periodic_tx_pattern), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004667
4668 if (!wma_handle || !wma_handle->wmi_handle) {
4669 WMA_LOGE("%s: WMA is closed, can not issue fw add pattern cmd",
4670 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304671 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004672 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004673
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004674 if (!wma_find_vdev_by_addr(wma_handle,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004675 pAddPeriodicTxPtrnParams->mac_address.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004676 &vdev_id)) {
4677 WMA_LOGE("%s: Failed to find vdev id for %pM", __func__,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004678 pAddPeriodicTxPtrnParams->mac_address.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304679 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004680 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004681
Himanshu Agarwal44195412016-03-09 13:03:54 +05304682 params.ucPtrnId = pAddPeriodicTxPtrnParams->ucPtrnId;
4683 params.ucPtrnSize = pAddPeriodicTxPtrnParams->ucPtrnSize;
4684 params.usPtrnIntervalMs = pAddPeriodicTxPtrnParams->usPtrnIntervalMs;
4685 qdf_mem_copy(&params.mac_address,
4686 &pAddPeriodicTxPtrnParams->mac_address,
4687 sizeof(struct qdf_mac_addr));
4688 qdf_mem_copy(params.ucPattern, pAddPeriodicTxPtrnParams->ucPattern,
4689 params.ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004690
Himanshu Agarwal44195412016-03-09 13:03:54 +05304691 return wmi_unified_process_add_periodic_tx_ptrn_cmd(
4692 wma_handle->wmi_handle, &params, vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004693}
4694
4695/**
4696 * wma_process_del_periodic_tx_ptrn_ind - del periodic tx ptrn
4697 * @handle: wma handle
4698 * @pDelPeriodicTxPtrnParams: tx ptrn params
4699 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304700 * Retrun: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004701 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304702QDF_STATUS wma_process_del_periodic_tx_ptrn_ind(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004703 tSirDelPeriodicTxPtrn *
4704 pDelPeriodicTxPtrnParams)
4705{
4706 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004707 uint8_t vdev_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004708
4709 if (!wma_handle || !wma_handle->wmi_handle) {
4710 WMA_LOGE("%s: WMA is closed, can not issue Del Pattern cmd",
4711 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304712 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004713 }
Himanshu Agarwal44195412016-03-09 13:03:54 +05304714
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004715 if (!wma_find_vdev_by_addr(wma_handle,
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08004716 pDelPeriodicTxPtrnParams->mac_address.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004717 &vdev_id)) {
4718 WMA_LOGE("%s: Failed to find vdev id for %pM", __func__,
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08004719 pDelPeriodicTxPtrnParams->mac_address.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304720 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004721 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004722
Himanshu Agarwal44195412016-03-09 13:03:54 +05304723 return wmi_unified_process_del_periodic_tx_ptrn_cmd(
4724 wma_handle->wmi_handle, vdev_id,
4725 pDelPeriodicTxPtrnParams->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004726}
4727
4728#ifdef WLAN_FEATURE_STATS_EXT
4729/**
4730 * wma_stats_ext_req() - request ext stats from fw
4731 * @wma_ptr: wma handle
4732 * @preq: stats ext params
4733 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304734 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004735 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304736QDF_STATUS wma_stats_ext_req(void *wma_ptr, tpStatsExtRequest preq)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004737{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004738 tp_wma_handle wma = (tp_wma_handle) wma_ptr;
Himanshu Agarwal44195412016-03-09 13:03:54 +05304739 struct stats_ext_params params = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004740
Himanshu Agarwal44195412016-03-09 13:03:54 +05304741 if (!wma) {
4742 WMA_LOGE("%s: wma handle is NULL", __func__);
4743 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004744 }
4745
Himanshu Agarwal44195412016-03-09 13:03:54 +05304746 params.vdev_id = preq->vdev_id;
4747 params.request_data_len = preq->request_data_len;
4748 qdf_mem_copy(params.request_data, preq->request_data,
4749 params.request_data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004750
Himanshu Agarwal44195412016-03-09 13:03:54 +05304751 return wmi_unified_stats_ext_req_cmd(wma->wmi_handle,
4752 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004753}
4754
4755#endif /* WLAN_FEATURE_STATS_EXT */
4756
4757#ifdef WLAN_FEATURE_EXTWOW_SUPPORT
4758/**
4759 * wma_send_status_of_ext_wow() - send ext wow status to SME
4760 * @wma: wma handle
4761 * @status: status
4762 *
4763 * Return: none
4764 */
4765static void wma_send_status_of_ext_wow(tp_wma_handle wma, bool status)
4766{
4767 tSirReadyToExtWoWInd *ready_to_extwow;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304768 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004769 cds_msg_t cds_msg;
4770 uint8_t len;
4771
4772 WMA_LOGD("Posting ready to suspend indication to umac");
4773
4774 len = sizeof(tSirReadyToExtWoWInd);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304775 ready_to_extwow = (tSirReadyToExtWoWInd *) qdf_mem_malloc(len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004776
4777 if (NULL == ready_to_extwow) {
4778 WMA_LOGE("%s: Memory allocation failure", __func__);
4779 return;
4780 }
4781
4782 ready_to_extwow->mesgType = eWNI_SME_READY_TO_EXTWOW_IND;
4783 ready_to_extwow->mesgLen = len;
4784 ready_to_extwow->status = status;
4785
4786 cds_msg.type = eWNI_SME_READY_TO_EXTWOW_IND;
4787 cds_msg.bodyptr = (void *)ready_to_extwow;
4788 cds_msg.bodyval = 0;
4789
4790 vstatus = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304791 if (vstatus != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004792 WMA_LOGE("Failed to post ready to suspend");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304793 qdf_mem_free(ready_to_extwow);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004794 }
4795}
4796
4797/**
4798 * wma_enable_ext_wow() - enable ext wow in fw
4799 * @wma: wma handle
4800 * @params: ext wow params
4801 *
4802 * Return:0 for success or error code
4803 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304804QDF_STATUS wma_enable_ext_wow(tp_wma_handle wma, tpSirExtWoWParams params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004805{
Himanshu Agarwal44195412016-03-09 13:03:54 +05304806 struct ext_wow_params wow_params = {0};
4807 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004808
Himanshu Agarwal44195412016-03-09 13:03:54 +05304809 if (!wma) {
4810 WMA_LOGE("%s: wma handle is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304811 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004812 }
4813
Himanshu Agarwal44195412016-03-09 13:03:54 +05304814 wow_params.vdev_id = params->vdev_id;
4815 wow_params.type = (enum wmi_ext_wow_type) params->type;
4816 wow_params.wakeup_pin_num = params->wakeup_pin_num;
4817
4818 status = wmi_unified_enable_ext_wow_cmd(wma->wmi_handle,
4819 &wow_params);
4820 if (QDF_IS_STATUS_ERROR(status))
4821 return status;
4822
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004823 wma_send_status_of_ext_wow(wma, true);
Himanshu Agarwal44195412016-03-09 13:03:54 +05304824 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004825
4826}
4827
4828/**
4829 * wma_set_app_type1_params_in_fw() - set app type1 params in fw
4830 * @wma: wma handle
4831 * @appType1Params: app type1 params
4832 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304833 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004834 */
4835int wma_set_app_type1_params_in_fw(tp_wma_handle wma,
4836 tpSirAppType1Params appType1Params)
4837{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004838 int ret;
4839
Govind Singhaa64c242016-03-08 11:31:49 +05304840 ret = wmi_unified_app_type1_params_in_fw_cmd(wma->wmi_handle,
4841 (struct app_type1_params *)appType1Params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004842 if (ret) {
4843 WMA_LOGE("%s: Failed to set APP TYPE1 PARAMS", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304844 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004845 }
4846
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304847 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004848}
4849
4850/**
4851 * wma_set_app_type2_params_in_fw() - set app type2 params in fw
4852 * @wma: wma handle
4853 * @appType2Params: app type2 params
4854 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304855 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004856 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304857QDF_STATUS wma_set_app_type2_params_in_fw(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004858 tpSirAppType2Params appType2Params)
4859{
Himanshu Agarwal44195412016-03-09 13:03:54 +05304860 struct app_type2_params params = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004861
Himanshu Agarwal44195412016-03-09 13:03:54 +05304862 if (!wma) {
4863 WMA_LOGE("%s: wma handle is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304864 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004865 }
4866
Himanshu Agarwal44195412016-03-09 13:03:54 +05304867 params.vdev_id = appType2Params->vdev_id;
4868 params.rc4_key_len = appType2Params->rc4_key_len;
4869 qdf_mem_copy(params.rc4_key, appType2Params->rc4_key, 16);
4870 params.ip_id = appType2Params->ip_id;
4871 params.ip_device_ip = appType2Params->ip_device_ip;
4872 params.ip_server_ip = appType2Params->ip_server_ip;
4873 params.tcp_src_port = appType2Params->tcp_src_port;
4874 params.tcp_dst_port = appType2Params->tcp_dst_port;
4875 params.tcp_seq = appType2Params->tcp_seq;
4876 params.tcp_ack_seq = appType2Params->tcp_ack_seq;
4877 params.keepalive_init = appType2Params->keepalive_init;
4878 params.keepalive_min = appType2Params->keepalive_min;
4879 params.keepalive_max = appType2Params->keepalive_max;
4880 params.keepalive_inc = appType2Params->keepalive_inc;
4881 params.tcp_tx_timeout_val = appType2Params->tcp_tx_timeout_val;
4882 params.tcp_rx_timeout_val = appType2Params->tcp_rx_timeout_val;
4883 qdf_mem_copy(&params.gateway_mac, &appType2Params->gateway_mac,
4884 sizeof(struct qdf_mac_addr));
4885
4886 return wmi_unified_set_app_type2_params_in_fw_cmd(wma->wmi_handle,
4887 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004888
4889}
4890#endif /* WLAN_FEATURE_EXTWOW_SUPPORT */
4891
4892#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
4893/**
4894 * wma_auto_shutdown_event_handler() - process auto shutdown timer trigger
4895 * @handle: wma handle
4896 * @event: event buffer
4897 * @len: buffer length
4898 *
4899 * Return: 0 for success or error code
4900 */
4901int wma_auto_shutdown_event_handler(void *handle, uint8_t *event,
4902 uint32_t len)
4903{
4904 wmi_host_auto_shutdown_event_fixed_param *wmi_auto_sh_evt;
4905 WMI_HOST_AUTO_SHUTDOWN_EVENTID_param_tlvs *param_buf =
4906 (WMI_HOST_AUTO_SHUTDOWN_EVENTID_param_tlvs *)
4907 event;
4908
4909 if (!param_buf || !param_buf->fixed_param) {
4910 WMA_LOGE("%s:%d: Invalid Auto shutdown timer evt", __func__,
4911 __LINE__);
4912 return -EINVAL;
4913 }
4914
4915 wmi_auto_sh_evt = param_buf->fixed_param;
4916
4917 if (wmi_auto_sh_evt->shutdown_reason
4918 != WMI_HOST_AUTO_SHUTDOWN_REASON_TIMER_EXPIRY) {
4919 WMA_LOGE("%s:%d: Invalid Auto shutdown timer evt", __func__,
4920 __LINE__);
4921 return -EINVAL;
4922 }
4923
4924 WMA_LOGD("%s:%d: Auto Shutdown Evt: %d", __func__, __LINE__,
4925 wmi_auto_sh_evt->shutdown_reason);
4926 return wma_post_auto_shutdown_msg();
4927}
4928
4929/**
4930 * wma_set_auto_shutdown_timer_req() - sets auto shutdown timer in firmware
4931 * @wma: wma handle
4932 * @auto_sh_cmd: auto shutdown timer value
4933 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304934 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004935 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304936QDF_STATUS wma_set_auto_shutdown_timer_req(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004937 tSirAutoShutdownCmdParams *
4938 auto_sh_cmd)
4939{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004940 if (auto_sh_cmd == NULL) {
4941 WMA_LOGE("%s : Invalid Autoshutdown cfg cmd", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304942 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004943 }
4944
Himanshu Agarwal44195412016-03-09 13:03:54 +05304945 return wmi_unified_set_auto_shutdown_timer_cmd(wma_handle->wmi_handle,
4946 auto_sh_cmd->timer_val);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004947}
4948#endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
4949
4950#ifdef WLAN_FEATURE_NAN
4951/**
4952 * wma_nan_req() - to send nan request to target
4953 * @wma: wma_handle
4954 * @nan_req: request data which will be non-null
4955 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304956 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004957 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304958QDF_STATUS wma_nan_req(void *wma_ptr, tpNanRequest nan_req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004959{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004960 tp_wma_handle wma_handle = (tp_wma_handle) wma_ptr;
Himanshu Agarwal44195412016-03-09 13:03:54 +05304961 struct nan_req_params params = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004962
Himanshu Agarwal44195412016-03-09 13:03:54 +05304963 if (!wma_handle) {
4964 WMA_LOGE("%s: wma handle is NULL", __func__);
4965 return QDF_STATUS_E_FAILURE;
4966 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004967 if (!nan_req) {
4968 WMA_LOGE("%s:nan req is not valid", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304969 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004970 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004971
Himanshu Agarwal44195412016-03-09 13:03:54 +05304972 params.request_data_len = nan_req->request_data_len;
4973 qdf_mem_copy(params.request_data, nan_req->request_data,
4974 params.request_data_len);
4975
4976 return wmi_unified_nan_req_cmd(wma_handle->wmi_handle,
4977 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004978}
4979#endif /* WLAN_FEATURE_NAN */
4980
4981#ifdef DHCP_SERVER_OFFLOAD
4982/**
4983 * wma_process_dhcpserver_offload() - enable DHCP server offload
4984 * @wma_handle: wma handle
4985 * @pDhcpSrvOffloadInfo: DHCP server offload info
4986 *
4987 * Return: 0 for success or error code
4988 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304989QDF_STATUS wma_process_dhcpserver_offload(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004990 tSirDhcpSrvOffloadInfo *
4991 pDhcpSrvOffloadInfo)
4992{
Himanshu Agarwal44195412016-03-09 13:03:54 +05304993 struct dhcp_offload_info_params params = {0};
4994 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004995
Himanshu Agarwal44195412016-03-09 13:03:54 +05304996 if (!wma_handle) {
4997 WMA_LOGE("%s: wma handle is NULL", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004998 return -EIO;
4999 }
Himanshu Agarwal44195412016-03-09 13:03:54 +05305000
5001 params.vdev_id = pDhcpSrvOffloadInfo->vdev_id;
5002 params.dhcpSrvOffloadEnabled =
5003 pDhcpSrvOffloadInfo->dhcpSrvOffloadEnabled;
5004 params.dhcpClientNum = pDhcpSrvOffloadInfo->dhcpClientNum;
5005 params.dhcpSrvIP = pDhcpSrvOffloadInfo->;
5006
5007 status = wmi_unified_process_dhcpserver_offload_cmd(
5008 wma_handle->wmi_handle, &params);
5009 if (QDF_IS_STATUS_ERROR(status))
5010 return status;
5011
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005012 WMA_LOGD("Set dhcp server offload to vdevId %d",
5013 pDhcpSrvOffloadInfo->vdev_id);
Himanshu Agarwal44195412016-03-09 13:03:54 +05305014 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005015}
5016#endif /* DHCP_SERVER_OFFLOAD */
5017
5018#ifdef WLAN_FEATURE_GPIO_LED_FLASHING
5019/**
5020 * wma_set_led_flashing() - set led flashing in fw
5021 * @wma_handle: wma handle
5022 * @flashing: flashing request
5023 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305024 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005025 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305026QDF_STATUS wma_set_led_flashing(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005027 tSirLedFlashingReq *flashing)
5028{
Govind Singhaa64c242016-03-08 11:31:49 +05305029 struct flashing_req_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005030
5031 if (!wma_handle || !wma_handle->wmi_handle) {
5032 WMA_LOGE(FL("WMA is closed, can not issue cmd"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305033 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005034 }
5035 if (!flashing) {
5036 WMA_LOGE(FL("invalid parameter: flashing"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305037 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005038 }
Govind Singhaa64c242016-03-08 11:31:49 +05305039 cmd.req_id = flashing->reqId;
5040 cmd.pattern_id = flashing->pattern_id;
5041 cmd.led_x0 = flashing->led_x0;
5042 cmd.led_x1 = flashing->led_x1;
5043 status = wmi_unified_set_led_flashing_cmd(wma_handle->wmi_handle,
5044 &cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005045 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305046 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005047 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305048 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005049}
5050#endif /* WLAN_FEATURE_GPIO_LED_FLASHING */
5051
5052#ifdef FEATURE_WLAN_CH_AVOID
5053/**
5054 * wma_channel_avoid_evt_handler() - process channel to avoid event from FW.
5055 * @handle: wma handle
5056 * @event: event buffer
5057 * @len: buffer length
5058 *
5059 * Return: 0 for success or error code
5060 */
5061int wma_channel_avoid_evt_handler(void *handle, uint8_t *event,
5062 uint32_t len)
5063{
5064 wmi_avoid_freq_ranges_event_fixed_param *afr_fixed_param;
5065 wmi_avoid_freq_range_desc *afr_desc;
5066 uint32_t num_freq_ranges, freq_range_idx;
5067 tSirChAvoidIndType *sca_indication;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305068 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005069 cds_msg_t sme_msg = { 0 };
5070 WMI_WLAN_FREQ_AVOID_EVENTID_param_tlvs *param_buf =
5071 (WMI_WLAN_FREQ_AVOID_EVENTID_param_tlvs *) event;
5072
5073 if (!param_buf) {
5074 WMA_LOGE("Invalid channel avoid event buffer");
5075 return -EINVAL;
5076 }
5077
5078 afr_fixed_param = param_buf->fixed_param;
5079 if (!afr_fixed_param) {
5080 WMA_LOGE("Invalid channel avoid event fixed param buffer");
5081 return -EINVAL;
5082 }
5083
5084 num_freq_ranges =
5085 (afr_fixed_param->num_freq_ranges >
5086 SIR_CH_AVOID_MAX_RANGE) ? SIR_CH_AVOID_MAX_RANGE :
5087 afr_fixed_param->num_freq_ranges;
5088
5089 WMA_LOGD("Channel avoid event received with %d ranges",
5090 num_freq_ranges);
5091 for (freq_range_idx = 0; freq_range_idx < num_freq_ranges;
5092 freq_range_idx++) {
5093 afr_desc = (wmi_avoid_freq_range_desc *)
5094 ((void *)param_buf->avd_freq_range +
5095 freq_range_idx * sizeof(wmi_avoid_freq_range_desc));
5096
5097 WMA_LOGD("range %d: tlv id = %u, start freq = %u, end freq = %u",
5098 freq_range_idx, afr_desc->tlv_header, afr_desc->start_freq,
5099 afr_desc->end_freq);
5100 }
5101
5102 sca_indication = (tSirChAvoidIndType *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305103 qdf_mem_malloc(sizeof(tSirChAvoidIndType));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005104 if (!sca_indication) {
5105 WMA_LOGE("Invalid channel avoid indication buffer");
5106 return -EINVAL;
5107 }
5108
5109 sca_indication->avoid_range_count = num_freq_ranges;
5110 for (freq_range_idx = 0; freq_range_idx < num_freq_ranges;
5111 freq_range_idx++) {
5112 afr_desc = (wmi_avoid_freq_range_desc *)
5113 ((void *)param_buf->avd_freq_range +
5114 freq_range_idx * sizeof(wmi_avoid_freq_range_desc));
5115 sca_indication->avoid_freq_range[freq_range_idx].start_freq =
5116 afr_desc->start_freq;
5117 sca_indication->avoid_freq_range[freq_range_idx].end_freq =
5118 afr_desc->end_freq;
5119 }
5120
5121 sme_msg.type = eWNI_SME_CH_AVOID_IND;
5122 sme_msg.bodyptr = sca_indication;
5123 sme_msg.bodyval = 0;
5124
Anurag Chouhan6d760662016-02-20 16:05:43 +05305125 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305126 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005127 WMA_LOGE("Fail to post eWNI_SME_CH_AVOID_IND msg to SME");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305128 qdf_mem_free(sca_indication);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005129 return -EINVAL;
5130 }
5131
5132 return 0;
5133}
5134
5135/**
5136 * wma_process_ch_avoid_update_req() - handles channel avoid update request
5137 * @wma_handle: wma handle
5138 * @ch_avoid_update_req: channel avoid update params
5139 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305140 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005141 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305142QDF_STATUS wma_process_ch_avoid_update_req(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005143 tSirChAvoidUpdateReq *
5144 ch_avoid_update_req)
5145{
Himanshu Agarwal44195412016-03-09 13:03:54 +05305146 QDF_STATUS status;
5147 if (!wma_handle) {
5148 WMA_LOGE("%s: wma handle is NULL", __func__);
5149 return QDF_STATUS_E_FAILURE;
5150 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005151 if (ch_avoid_update_req == NULL) {
5152 WMA_LOGE("%s : ch_avoid_update_req is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305153 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005154 }
5155
5156 WMA_LOGI("%s: WMA --> WMI_CHAN_AVOID_UPDATE", __func__);
5157
Himanshu Agarwal44195412016-03-09 13:03:54 +05305158 status = wmi_unified_process_ch_avoid_update_cmd(
5159 wma_handle->wmi_handle);
5160 if (QDF_IS_STATUS_ERROR(status))
5161 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005162
5163 WMA_LOGI("%s: WMA --> WMI_CHAN_AVOID_UPDATE sent through WMI",
5164 __func__);
Himanshu Agarwal44195412016-03-09 13:03:54 +05305165 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005166}
5167#endif /* FEATURE_WLAN_CH_AVOID */
5168
5169/**
5170 * wma_set_reg_domain() - set reg domain
5171 * @clientCtxt: client context
5172 * @regId: reg id
5173 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305174 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005175 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305176QDF_STATUS wma_set_reg_domain(void *clientCtxt, v_REGDOMAIN_t regId)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005177{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305178 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005179 cds_set_reg_domain(clientCtxt, regId))
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305180 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005181
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305182 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005183}
5184
5185/**
5186 * wma_send_regdomain_info_to_fw() - send regdomain info to fw
5187 * @reg_dmn: reg domain
5188 * @regdmn2G: 2G reg domain
5189 * @regdmn5G: 5G reg domain
5190 * @ctl2G: 2G test limit
5191 * @ctl5G: 5G test limit
5192 *
5193 * Return: none
5194 */
5195void wma_send_regdomain_info_to_fw(uint32_t reg_dmn, uint16_t regdmn2G,
5196 uint16_t regdmn5G, int8_t ctl2G,
5197 int8_t ctl5G)
5198{
Anurag Chouhan6d760662016-02-20 16:05:43 +05305199 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005200 int32_t cck_mask_val = 0;
Govind Singhd76a5b02016-03-08 15:12:14 +05305201 struct pdev_params pdev_param = {0};
Himanshu Agarwal44195412016-03-09 13:03:54 +05305202 QDF_STATUS ret = QDF_STATUS_SUCCESS;
5203 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005204
5205 if (NULL == wma) {
5206 WMA_LOGE("%s: wma context is NULL", __func__);
5207 return;
5208 }
5209
Himanshu Agarwal44195412016-03-09 13:03:54 +05305210 status = wmi_unified_send_regdomain_info_to_fw_cmd(wma->wmi_handle,
5211 reg_dmn, regdmn2G, regdmn5G, ctl2G, ctl5G);
5212 if (status == QDF_STATUS_E_NOMEM)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005213 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005214
Amar Singhal76b41322015-12-09 14:39:17 -08005215 if ((((reg_dmn & ~COUNTRY_ERD_FLAG) == CTRY_JAPAN14) ||
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005216 ((reg_dmn & ~COUNTRY_ERD_FLAG) == CTRY_KOREA_ROC)) &&
5217 (true == wma->tx_chain_mask_cck))
5218 cck_mask_val = 1;
5219
5220 cck_mask_val |= (wma->self_gen_frm_pwr << 16);
Govind Singhd76a5b02016-03-08 15:12:14 +05305221 pdev_param.param_id = WMI_PDEV_PARAM_TX_CHAIN_MASK_CCK;
5222 pdev_param.param_value = cck_mask_val;
5223 ret = wmi_unified_pdev_param_send(wma->wmi_handle,
5224 &pdev_param,
5225 WMA_WILDCARD_PDEV_ID);
5226
Himanshu Agarwal44195412016-03-09 13:03:54 +05305227 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005228 WMA_LOGE("failed to set PDEV tx_chain_mask_cck %d",
5229 ret);
5230
5231 return;
5232}
5233
5234/**
Houston Hoffmana76591b2015-11-10 16:52:05 -08005235 * wma_post_runtime_resume_msg() - post the resume request
5236 * @handle: validated wma handle
5237 *
5238 * request the MC thread unpaus the vdev and set resume dtim
5239 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305240 * Return: qdf status of the mq post
Houston Hoffmana76591b2015-11-10 16:52:05 -08005241 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305242static QDF_STATUS wma_post_runtime_resume_msg(WMA_HANDLE handle)
Houston Hoffmana76591b2015-11-10 16:52:05 -08005243{
5244 cds_msg_t resume_msg;
Houston Hoffmanc45db892015-11-13 19:59:25 -08005245 QDF_STATUS status;
5246 tp_wma_handle wma = (tp_wma_handle) handle;
5247
5248 qdf_runtime_pm_prevent_suspend(wma->wma_runtime_resume_lock);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005249
5250 resume_msg.bodyptr = NULL;
5251 resume_msg.type = WMA_RUNTIME_PM_RESUME_IND;
Houston Hoffmanc45db892015-11-13 19:59:25 -08005252
5253 status = cds_mq_post_message(QDF_MODULE_ID_WMA, &resume_msg);
5254
5255 if (!QDF_IS_STATUS_SUCCESS(status)) {
5256 WMA_LOGE("Failed to post Runtime PM Resume IND to VOS");
5257 qdf_runtime_pm_allow_suspend(wma->wma_runtime_resume_lock);
5258 }
5259
5260 return status;
Houston Hoffmana76591b2015-11-10 16:52:05 -08005261}
5262
5263/**
5264 * wma_post_runtime_suspend_msg() - post the suspend request
5265 * @handle: validated wma handle
5266 *
5267 * Requests for offloads to be configured for runtime suspend
5268 * on the MC thread
5269 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305270 * Return QDF_STATUS_E_AGAIN in case of timeout or QDF_STATUS_SUCCESS
Houston Hoffmana76591b2015-11-10 16:52:05 -08005271 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305272static QDF_STATUS wma_post_runtime_suspend_msg(WMA_HANDLE handle)
Houston Hoffmana76591b2015-11-10 16:52:05 -08005273{
5274 cds_msg_t cds_msg;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305275 QDF_STATUS qdf_status;
Houston Hoffmana76591b2015-11-10 16:52:05 -08005276 tp_wma_handle wma = (tp_wma_handle) handle;
5277
Anurag Chouhance0dc992016-02-16 18:18:03 +05305278 qdf_event_reset(&wma->runtime_suspend);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005279
5280 cds_msg.bodyptr = NULL;
5281 cds_msg.type = WMA_RUNTIME_PM_SUSPEND_IND;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305282 qdf_status = cds_mq_post_message(QDF_MODULE_ID_WMA, &cds_msg);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005283
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305284 if (qdf_status != QDF_STATUS_SUCCESS)
Houston Hoffmana76591b2015-11-10 16:52:05 -08005285 goto failure;
5286
Anurag Chouhance0dc992016-02-16 18:18:03 +05305287 if (qdf_wait_single_event(&wma->runtime_suspend,
Houston Hoffmana76591b2015-11-10 16:52:05 -08005288 WMA_TGT_SUSPEND_COMPLETE_TIMEOUT) !=
Anurag Chouhance0dc992016-02-16 18:18:03 +05305289 QDF_STATUS_SUCCESS) {
Houston Hoffmana76591b2015-11-10 16:52:05 -08005290 WMA_LOGE("Failed to get runtime suspend event");
Houston Hoffmanc45db892015-11-13 19:59:25 -08005291 goto msg_timed_out;
Houston Hoffmana76591b2015-11-10 16:52:05 -08005292 }
5293
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305294 return QDF_STATUS_SUCCESS;
Houston Hoffmana76591b2015-11-10 16:52:05 -08005295
Houston Hoffmanc45db892015-11-13 19:59:25 -08005296msg_timed_out:
5297 wma_post_runtime_resume_msg(wma);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005298failure:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305299 return QDF_STATUS_E_AGAIN;
Houston Hoffmana76591b2015-11-10 16:52:05 -08005300}
5301
5302/**
5303 * __wma_bus_suspend(): handles bus suspend for wma
5304 * @type: is this suspend part of runtime suspend or system suspend?
5305 *
5306 * Bails if a scan is in progress.
5307 * Calls the appropriate handlers based on configuration and event.
5308 *
5309 * Return: 0 for success or error code
5310 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05305311static int __wma_bus_suspend(enum qdf_suspend_type type)
Houston Hoffmana76591b2015-11-10 16:52:05 -08005312{
Anurag Chouhan6d760662016-02-20 16:05:43 +05305313 WMA_HANDLE handle = cds_get_context(QDF_MODULE_ID_WMA);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005314 if (NULL == handle) {
5315 WMA_LOGE("%s: wma context is NULL", __func__);
5316 return -EFAULT;
5317 }
5318
5319 if (wma_check_scan_in_progress(handle)) {
5320 WMA_LOGE("%s: Scan in progress. Aborting suspend", __func__);
5321 return -EBUSY;
5322 }
5323
Anurag Chouhan6d760662016-02-20 16:05:43 +05305324 if (type == QDF_RUNTIME_SUSPEND) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305325 QDF_STATUS status = wma_post_runtime_suspend_msg(handle);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005326 if (status)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305327 return qdf_status_to_os_return(status);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005328 }
5329
Anurag Chouhan6d760662016-02-20 16:05:43 +05305330 if (type == QDF_SYSTEM_SUSPEND)
Houston Hoffmana76591b2015-11-10 16:52:05 -08005331 WMA_LOGE("%s: wow mode selected %d", __func__,
5332 wma_is_wow_mode_selected(handle));
5333
5334 if (wma_is_wow_mode_selected(handle)) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305335 QDF_STATUS status = wma_enable_wow_in_fw(handle);
5336 return qdf_status_to_os_return(status);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005337 }
5338
5339 return wma_suspend_target(handle, 0);
5340}
5341
5342/**
5343 * wma_runtime_suspend() - handles runtime suspend request from hdd
5344 *
5345 * Calls the appropriate handler based on configuration and event.
5346 * Last busy marking should prevent race conditions between processing
5347 * of asyncronous fw events and the running of runtime suspend.
5348 * (eg. last busy marking should guarantee that any auth requests have
5349 * been processed)
5350 * Events comming from the host are not protected, but aren't expected
5351 * to be an issue.
5352 *
5353 * Return: 0 for success or error code
5354 */
5355int wma_runtime_suspend(void)
5356{
Anurag Chouhan6d760662016-02-20 16:05:43 +05305357 return __wma_bus_suspend(QDF_RUNTIME_SUSPEND);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005358}
5359
5360/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005361 * wma_bus_suspend() - handles bus suspend request from hdd
5362 *
5363 * Calls the appropriate handler based on configuration and event
5364 *
5365 * Return: 0 for success or error code
5366 */
5367int wma_bus_suspend(void)
5368{
Houston Hoffmana76591b2015-11-10 16:52:05 -08005369
Anurag Chouhan6d760662016-02-20 16:05:43 +05305370 return __wma_bus_suspend(QDF_SYSTEM_SUSPEND);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005371}
5372
5373/**
5374 * __wma_bus_resume() - bus resume for wma
5375 *
5376 * does the part of the bus resume common to bus and system suspend
5377 *
5378 * Return: os error code.
5379 */
5380int __wma_bus_resume(WMA_HANDLE handle)
5381{
5382 bool wow_mode = wma_is_wow_mode_selected(handle);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305383 QDF_STATUS status;
Houston Hoffmana76591b2015-11-10 16:52:05 -08005384
5385 WMA_LOGE("%s: wow mode %d", __func__, wow_mode);
5386
5387 if (!wow_mode)
5388 return wma_resume_target(handle);
5389
5390 status = wma_disable_wow_in_fw(handle);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305391 return qdf_status_to_os_return(status);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005392}
5393
5394/**
5395 * wma_runtime_resume() - do the runtime resume operation for wma
5396 *
5397 * Return: os error code.
5398 */
5399int wma_runtime_resume(void)
5400{
5401 int ret;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305402 QDF_STATUS status;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305403 WMA_HANDLE handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005404 if (NULL == handle) {
5405 WMA_LOGE("%s: wma context is NULL", __func__);
5406 return -EFAULT;
5407 }
5408
Houston Hoffmana76591b2015-11-10 16:52:05 -08005409 ret = __wma_bus_resume(handle);
5410 if (ret)
5411 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005412
Houston Hoffmana76591b2015-11-10 16:52:05 -08005413 status = wma_post_runtime_resume_msg(handle);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305414 return qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005415}
5416
5417/**
5418 * wma_bus_resume() - handles bus resume request from hdd
5419 * @handle: valid wma handle
5420 *
5421 * Calls the appropriate handler based on configuration
5422 *
5423 * Return: 0 for success or error code
5424 */
5425int wma_bus_resume(void)
5426{
Anurag Chouhan6d760662016-02-20 16:05:43 +05305427 WMA_HANDLE handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005428 if (NULL == handle) {
5429 WMA_LOGE("%s: wma context is NULL", __func__);
5430 return -EFAULT;
5431 }
5432
Houston Hoffmana76591b2015-11-10 16:52:05 -08005433 return __wma_bus_resume(handle);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005434}
5435
5436/**
Manjunathappa Prakash7b67e622016-04-12 15:18:45 +05305437 * wma_suspend_target_timeout() - Handles the target suspend timeout
5438 * @is_self_recovery_enabled: Is self recovery enabled or not
5439 *
5440 * Return: NONE
5441 */
5442#ifdef QCA_WIFI_3_0_ADRASTEA
5443static inline void wma_suspend_target_timeout(bool is_self_recovery_enabled)
5444{
5445 if (cds_is_driver_recovering()) {
5446 WMA_LOGE("%s: recovery is in progress, ignore!", __func__);
5447 } else {
5448 if (is_self_recovery_enabled) {
5449 cds_trigger_recovery();
5450 } else {
5451 QDF_BUG(0);
5452 }
5453 }
5454}
5455#else /* ROME chipset */
5456static inline void wma_suspend_target_timeout(bool is_self_recovery_enabled)
5457{
5458 if (cds_is_load_or_unload_in_progress() || cds_is_driver_recovering()) {
5459 WMA_LOGE("%s: Unloading/Loading/recovery is in progress, Ignore!",
5460 __func__);
5461 } else {
5462 if (is_self_recovery_enabled) {
5463 cds_trigger_recovery();
5464 } else {
5465 QDF_BUG(0);
5466 }
5467 }
5468}
5469#endif
5470
5471/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005472 * wma_suspend_target() - suspend target
5473 * @handle: wma handle
5474 * @disable_target_intr: disable target interrupt
5475 *
Govind Singhd76a5b02016-03-08 15:12:14 +05305476 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005477 */
Govind Singhd76a5b02016-03-08 15:12:14 +05305478QDF_STATUS wma_suspend_target(WMA_HANDLE handle, int disable_target_intr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005479{
5480 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Komal Seelam3d202862016-02-24 18:43:24 +05305481 struct hif_opaque_softc *scn;
Govind Singhd76a5b02016-03-08 15:12:14 +05305482 QDF_STATUS status;
5483 struct suspend_params param = {0};
5484
Yue Mae1a85f32015-10-20 18:12:45 -07005485#ifdef CONFIG_CNSS
Anurag Chouhan6d760662016-02-20 16:05:43 +05305486 tpAniSirGlobal pmac = cds_get_context(QDF_MODULE_ID_PE);
Yue Mae1a85f32015-10-20 18:12:45 -07005487#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005488
5489 if (!wma_handle || !wma_handle->wmi_handle) {
5490 WMA_LOGE("WMA is closed. can not issue suspend cmd");
Govind Singhd76a5b02016-03-08 15:12:14 +05305491 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005492 }
Yue Mae1a85f32015-10-20 18:12:45 -07005493
5494#ifdef CONFIG_CNSS
5495 if (NULL == pmac) {
5496 WMA_LOGE("%s: Unable to get PE context", __func__);
Govind Singhd76a5b02016-03-08 15:12:14 +05305497 return QDF_STATUS_E_INVAL;
Yue Mae1a85f32015-10-20 18:12:45 -07005498 }
5499#endif
Anurag Chouhance0dc992016-02-16 18:18:03 +05305500 qdf_event_reset(&wma_handle->target_suspend);
Govind Singhd76a5b02016-03-08 15:12:14 +05305501 param.disable_target_intr = disable_target_intr;
5502 status = wmi_unified_suspend_send(wma_handle->wmi_handle,
5503 &param,
5504 WMA_WILDCARD_PDEV_ID);
5505 if (QDF_IS_STATUS_ERROR(status))
5506 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005507
5508 wmi_set_target_suspend(wma_handle->wmi_handle, true);
5509
Anurag Chouhance0dc992016-02-16 18:18:03 +05305510 if (qdf_wait_single_event(&wma_handle->target_suspend,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005511 WMA_TGT_SUSPEND_COMPLETE_TIMEOUT)
Anurag Chouhance0dc992016-02-16 18:18:03 +05305512 != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005513 WMA_LOGE("Failed to get ACK from firmware for pdev suspend");
5514 wmi_set_target_suspend(wma_handle->wmi_handle, false);
Manjunathappa Prakash7b67e622016-04-12 15:18:45 +05305515 wma_suspend_target_timeout(pmac->sme.enableSelfRecovery);
Govind Singhd76a5b02016-03-08 15:12:14 +05305516 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005517 }
5518
Anurag Chouhan6d760662016-02-20 16:05:43 +05305519 scn = cds_get_context(QDF_MODULE_ID_HIF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005520
5521 if (scn == NULL) {
5522 WMA_LOGE("%s: Failed to get HIF context", __func__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305523 QDF_ASSERT(0);
Govind Singhd76a5b02016-03-08 15:12:14 +05305524 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005525 }
5526
Govind Singhd76a5b02016-03-08 15:12:14 +05305527 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005528}
5529
5530/**
5531 * wma_target_suspend_acknowledge() - update target susspend status
5532 * @context: wma context
5533 *
5534 * Return: none
5535 */
5536void wma_target_suspend_acknowledge(void *context)
5537{
Anurag Chouhan6d760662016-02-20 16:05:43 +05305538 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005539 int wow_nack = *((int *)context);
5540
5541 if (NULL == wma) {
5542 WMA_LOGE("%s: wma is NULL", __func__);
5543 return;
5544 }
5545
5546 wma->wow_nack = wow_nack;
Anurag Chouhance0dc992016-02-16 18:18:03 +05305547 qdf_event_set(&wma->target_suspend);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005548 if (wow_nack)
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305549 qdf_wake_lock_timeout_acquire(&wma->wow_wake_lock,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005550 WMA_WAKE_LOCK_TIMEOUT,
5551 WIFI_POWER_EVENT_WAKELOCK_WOW);
5552}
5553
5554/**
5555 * wma_resume_target() - resume target
5556 * @handle: wma handle
5557 *
Govind Singhd76a5b02016-03-08 15:12:14 +05305558 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005559 */
Govind Singhd76a5b02016-03-08 15:12:14 +05305560QDF_STATUS wma_resume_target(WMA_HANDLE handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005561{
5562 int ret;
5563 tp_wma_handle wma = (tp_wma_handle) handle;
Anurag Chouhance0dc992016-02-16 18:18:03 +05305564 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005565#ifdef CONFIG_CNSS
Anurag Chouhan6d760662016-02-20 16:05:43 +05305566 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005567 if (NULL == pMac) {
5568 WMA_LOGE("%s: Unable to get PE context", __func__);
Govind Singhd76a5b02016-03-08 15:12:14 +05305569 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005570 }
5571#endif /* CONFIG_CNSS */
5572
Anurag Chouhance0dc992016-02-16 18:18:03 +05305573 qdf_event_reset(&wma->wma_resume_event);
Govind Singhd76a5b02016-03-08 15:12:14 +05305574 qdf_status = wmi_unified_resume_send(wma->wmi_handle,
5575 WMA_WILDCARD_PDEV_ID);
5576 if (QDF_IS_STATUS_ERROR(qdf_status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005577 WMA_LOGE("Failed to send WMI_PDEV_RESUME_CMDID command");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005578
Anurag Chouhance0dc992016-02-16 18:18:03 +05305579 qdf_status = qdf_wait_single_event(&(wma->wma_resume_event),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005580 WMA_RESUME_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05305581 if (QDF_STATUS_SUCCESS != qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005582 WMA_LOGP("%s: Timeout waiting for resume event from FW",
5583 __func__);
5584 WMA_LOGP("%s: Pending commands %d credits %d", __func__,
5585 wmi_get_pending_cmds(wma->wmi_handle),
5586 wmi_get_host_credits(wma->wmi_handle));
Prashanth Bhatta9e143052015-12-04 11:56:47 -08005587 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005588#ifdef CONFIG_CNSS
5589 if (pMac->sme.enableSelfRecovery) {
5590 cds_trigger_recovery();
5591 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305592 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005593 }
5594#else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305595 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005596#endif /* CONFIG_CNSS */
5597 } else {
5598 WMA_LOGE("%s: SSR in progress, ignore resume timeout",
5599 __func__);
5600 }
5601 } else {
5602 WMA_LOGD("Host wakeup received");
5603 }
5604
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305605 if (QDF_STATUS_SUCCESS == qdf_status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005606 wmi_set_target_suspend(wma->wmi_handle, false);
5607
5608 return ret;
5609}
5610
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005611#ifdef FEATURE_WLAN_TDLS
5612/**
5613 * wma_tdls_event_handler() - handle TDLS event
5614 * @handle: wma handle
5615 * @event: event buffer
5616 * @len: buffer length
5617 *
5618 * Return: 0 for success or error code
5619 */
5620int wma_tdls_event_handler(void *handle, uint8_t *event, uint32_t len)
5621{
5622 tp_wma_handle wma = (tp_wma_handle) handle;
5623 WMI_TDLS_PEER_EVENTID_param_tlvs *param_buf = NULL;
5624 wmi_tdls_peer_event_fixed_param *peer_event = NULL;
5625 tSirTdlsEventnotify *tdls_event;
5626
5627 if (!event) {
5628 WMA_LOGE("%s: event param null", __func__);
5629 return -EINVAL;
5630 }
5631
5632 param_buf = (WMI_TDLS_PEER_EVENTID_param_tlvs *) event;
5633 if (!param_buf) {
5634 WMA_LOGE("%s: received null buf from target", __func__);
5635 return -EINVAL;
5636 }
5637
5638 peer_event = param_buf->fixed_param;
5639 if (!peer_event) {
5640 WMA_LOGE("%s: received null event data from target", __func__);
5641 return -EINVAL;
5642 }
5643
5644 tdls_event = (tSirTdlsEventnotify *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305645 qdf_mem_malloc(sizeof(*tdls_event));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005646 if (!tdls_event) {
5647 WMA_LOGE("%s: failed to allocate memory for tdls_event",
5648 __func__);
5649 return -ENOMEM;
5650 }
5651
5652 tdls_event->sessionId = peer_event->vdev_id;
5653 WMI_MAC_ADDR_TO_CHAR_ARRAY(&peer_event->peer_macaddr,
Srinivas Girigowda4f593792015-11-19 15:33:42 -08005654 tdls_event->peermac.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005655
5656 switch (peer_event->peer_status) {
5657 case WMI_TDLS_SHOULD_DISCOVER:
5658 tdls_event->messageType = WMA_TDLS_SHOULD_DISCOVER_CMD;
5659 break;
5660 case WMI_TDLS_SHOULD_TEARDOWN:
5661 tdls_event->messageType = WMA_TDLS_SHOULD_TEARDOWN_CMD;
5662 break;
5663 case WMI_TDLS_PEER_DISCONNECTED:
5664 tdls_event->messageType = WMA_TDLS_PEER_DISCONNECTED_CMD;
5665 break;
5666 default:
5667 WMA_LOGE("%s: Discarding unknown tdls event(%d) from target",
5668 __func__, peer_event->peer_status);
5669 return -EINVAL;
5670 }
5671
5672 switch (peer_event->peer_reason) {
5673 case WMI_TDLS_TEARDOWN_REASON_TX:
5674 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_TX;
5675 break;
5676 case WMI_TDLS_TEARDOWN_REASON_RSSI:
5677 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_RSSI;
5678 break;
5679 case WMI_TDLS_TEARDOWN_REASON_SCAN:
5680 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_SCAN;
5681 break;
5682 case WMI_TDLS_DISCONNECTED_REASON_PEER_DELETE:
5683 tdls_event->peer_reason =
5684 eWNI_TDLS_DISCONNECTED_REASON_PEER_DELETE;
5685 break;
5686 case WMI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT:
5687 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT;
5688 break;
5689 case WMI_TDLS_TEARDOWN_REASON_BAD_PTR:
5690 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_BAD_PTR;
5691 break;
5692 case WMI_TDLS_TEARDOWN_REASON_NO_RESPONSE:
5693 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_NO_RESPONSE;
5694 break;
5695 default:
5696 WMA_LOGE("%s: unknown reason(%d) in tdls event(%d) from target",
5697 __func__, peer_event->peer_reason,
5698 peer_event->peer_status);
5699 return -EINVAL;
5700 }
5701
5702 WMA_LOGD("%s: sending msg to umac, messageType: 0x%x, "
5703 "for peer: %pM, reason: %d, smesessionId: %d",
Srinivas Girigowda4f593792015-11-19 15:33:42 -08005704 __func__, tdls_event->messageType, tdls_event->peermac.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005705 tdls_event->peer_reason, tdls_event->sessionId);
5706
5707 wma_send_msg(wma, tdls_event->messageType, (void *)tdls_event, 0);
5708 return 0;
5709}
5710
5711/**
5712 * wma_set_tdls_offchan_mode() - set tdls off channel mode
5713 * @handle: wma handle
5714 * @chan_switch_params: Pointer to tdls channel switch parameter structure
5715 *
5716 * This function sets tdls off channel mode
5717 *
5718 * Return: 0 on success; Negative errno otherwise
5719 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05305720QDF_STATUS wma_set_tdls_offchan_mode(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005721 tdls_chan_switch_params *chan_switch_params)
5722{
5723 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Himanshu Agarwal44195412016-03-09 13:03:54 +05305724 struct tdls_channel_switch_params params = {0};
5725 QDF_STATUS ret = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005726
5727 if (!wma_handle || !wma_handle->wmi_handle) {
5728 WMA_LOGE(FL(
5729 "WMA is closed, can not issue tdls off channel cmd"
5730 ));
5731 ret = -EINVAL;
5732 goto end;
5733 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005734
Himanshu Agarwal44195412016-03-09 13:03:54 +05305735 params.vdev_id = chan_switch_params->vdev_id;
5736 params.tdls_off_ch_bw_offset =
5737 chan_switch_params->tdls_off_ch_bw_offset;
5738 params.tdls_off_ch = chan_switch_params->tdls_off_ch;
5739 params.tdls_sw_mode = chan_switch_params->tdls_sw_mode;
5740 params.oper_class = chan_switch_params->oper_class;
5741 params.is_responder = chan_switch_params->is_responder;
5742 qdf_mem_copy(params.peer_mac_addr, chan_switch_params->peer_mac_addr,
5743 WMI_ETH_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005744
Himanshu Agarwal44195412016-03-09 13:03:54 +05305745 ret = wmi_unified_set_tdls_offchan_mode_cmd(wma_handle->wmi_handle,
5746 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005747
5748end:
5749 if (chan_switch_params)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305750 qdf_mem_free(chan_switch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005751 return ret;
5752}
5753
5754/**
5755 * wma_update_fw_tdls_state() - send enable/disable tdls for a vdev
5756 * @wma: wma handle
5757 * @pwmaTdlsparams: TDLS params
5758 *
5759 * Return: 0 for sucess or error code
5760 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05305761QDF_STATUS wma_update_fw_tdls_state(WMA_HANDLE handle, void *pwmaTdlsparams)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005762{
5763 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005764 t_wma_tdls_mode tdls_mode;
5765 t_wma_tdls_params *wma_tdls = (t_wma_tdls_params *) pwmaTdlsparams;
Himanshu Agarwal44195412016-03-09 13:03:54 +05305766 struct wmi_tdls_params params = {0};
5767 QDF_STATUS ret = QDF_STATUS_SUCCESS;
5768 uint8_t tdls_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005769
5770 if (!wma_handle || !wma_handle->wmi_handle) {
5771 WMA_LOGE("%s: WMA is closed, can not issue fw tdls state cmd",
5772 __func__);
5773 ret = -EINVAL;
5774 goto end_fw_tdls_state;
5775 }
5776
Himanshu Agarwal44195412016-03-09 13:03:54 +05305777 params.tdls_state = wma_tdls->tdls_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005778 tdls_mode = wma_tdls->tdls_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005779
5780 if (WMA_TDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == tdls_mode) {
Himanshu Agarwal44195412016-03-09 13:03:54 +05305781 tdls_state = WMI_TDLS_ENABLE_PASSIVE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005782 } else if (WMA_TDLS_SUPPORT_ENABLED == tdls_mode) {
Himanshu Agarwal44195412016-03-09 13:03:54 +05305783 tdls_state = WMI_TDLS_ENABLE_ACTIVE;
Kabilan Kannan421714b2015-11-23 04:44:59 -08005784 } else if (WMA_TDLS_SUPPORT_ACTIVE_EXTERNAL_CONTROL == tdls_mode) {
Himanshu Agarwal44195412016-03-09 13:03:54 +05305785 tdls_state = WMI_TDLS_ENABLE_ACTIVE_EXTERNAL_CONTROL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005786 } else {
Himanshu Agarwal44195412016-03-09 13:03:54 +05305787 tdls_state = WMI_TDLS_DISABLE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005788 }
5789
Himanshu Agarwal44195412016-03-09 13:03:54 +05305790 params.vdev_id = wma_tdls->vdev_id;
5791 params.notification_interval_ms = wma_tdls->notification_interval_ms;
5792 params.tx_discovery_threshold = wma_tdls->tx_discovery_threshold;
5793 params.tx_teardown_threshold = wma_tdls->tx_teardown_threshold;
5794 params.rssi_teardown_threshold = wma_tdls->rssi_teardown_threshold;
5795 params.rssi_delta = wma_tdls->rssi_delta;
5796 params.tdls_options = wma_tdls->tdls_options;
5797 params.peer_traffic_ind_window = wma_tdls->peer_traffic_ind_window;
5798 params.peer_traffic_response_timeout =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005799 wma_tdls->peer_traffic_response_timeout;
Himanshu Agarwal44195412016-03-09 13:03:54 +05305800 params.puapsd_mask = wma_tdls->puapsd_mask;
5801 params.puapsd_inactivity_time = wma_tdls->puapsd_inactivity_time;
5802 params.puapsd_rx_frame_threshold =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005803 wma_tdls->puapsd_rx_frame_threshold;
Himanshu Agarwal44195412016-03-09 13:03:54 +05305804 params.teardown_notification_ms =
Kabilan Kannanca670be2015-11-23 01:56:12 -08005805 wma_tdls->teardown_notification_ms;
Himanshu Agarwal44195412016-03-09 13:03:54 +05305806 params.tdls_peer_kickout_threshold =
Kabilan Kannan421714b2015-11-23 04:44:59 -08005807 wma_tdls->tdls_peer_kickout_threshold;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005808
Himanshu Agarwal44195412016-03-09 13:03:54 +05305809 ret = wmi_unified_update_fw_tdls_state_cmd(wma_handle->wmi_handle,
5810 &params, tdls_state);
5811 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005812 goto end_fw_tdls_state;
Himanshu Agarwal44195412016-03-09 13:03:54 +05305813
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005814 WMA_LOGD("%s: vdev_id %d", __func__, wma_tdls->vdev_id);
5815
5816end_fw_tdls_state:
5817 if (pwmaTdlsparams)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305818 qdf_mem_free(pwmaTdlsparams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005819 return ret;
5820}
5821
5822/**
5823 * wma_update_tdls_peer_state() - update TDLS peer state
5824 * @handle: wma handle
5825 * @peerStateParams: TDLS peer state params
5826 *
5827 * Return: 0 for success or error code
5828 */
5829int wma_update_tdls_peer_state(WMA_HANDLE handle,
5830 tTdlsPeerStateParams *peerStateParams)
5831{
5832 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005833 uint32_t i;
5834 ol_txrx_pdev_handle pdev;
5835 uint8_t peer_id;
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07005836 ol_txrx_peer_handle peer;
5837 uint8_t *peer_mac_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005838 int ret = 0;
Govind Singhaa64c242016-03-08 11:31:49 +05305839 uint32_t *ch_mhz;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005840
5841 if (!wma_handle || !wma_handle->wmi_handle) {
5842 WMA_LOGE("%s: WMA is closed, can not issue cmd", __func__);
5843 ret = -EINVAL;
5844 goto end_tdls_peer_state;
5845 }
5846
5847 /* peer capability info is valid only when peer state is connected */
5848 if (WMA_TDLS_PEER_STATE_CONNECTED != peerStateParams->peerState) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305849 qdf_mem_zero(&peerStateParams->peerCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005850 sizeof(tTdlsPeerCapParams));
5851 }
5852
Govind Singhaa64c242016-03-08 11:31:49 +05305853 ch_mhz = qdf_mem_malloc(sizeof(uint32_t) *
5854 peerStateParams->peerCap.peerChanLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005855 for (i = 0; i < peerStateParams->peerCap.peerChanLen; ++i) {
Govind Singhaa64c242016-03-08 11:31:49 +05305856 ch_mhz[i] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005857 cds_chan_to_freq(peerStateParams->peerCap.peerChan[i].
5858 chanId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005859 }
5860
Govind Singhaa64c242016-03-08 11:31:49 +05305861 if (wmi_unified_update_tdls_peer_state_cmd(wma_handle->wmi_handle,
5862 (struct tdls_peer_state_params *)peerStateParams,
5863 ch_mhz)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005864 WMA_LOGE("%s: failed to send tdls peer update state command",
5865 __func__);
Govind Singhaa64c242016-03-08 11:31:49 +05305866 qdf_mem_free(ch_mhz);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005867 ret = -EIO;
5868 goto end_tdls_peer_state;
5869 }
5870
Govind Singhaa64c242016-03-08 11:31:49 +05305871 qdf_mem_free(ch_mhz);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005872 /* in case of teardown, remove peer from fw */
5873 if (WMA_TDLS_PEER_STATE_TEARDOWN == peerStateParams->peerState) {
Anurag Chouhan6d760662016-02-20 16:05:43 +05305874 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005875 if (!pdev) {
5876 WMA_LOGE("%s: Failed to find pdev", __func__);
5877 ret = -EIO;
5878 goto end_tdls_peer_state;
5879 }
5880
5881 peer = ol_txrx_find_peer_by_addr(pdev,
5882 peerStateParams->peerMacAddr,
5883 &peer_id);
5884 if (!peer) {
5885 WMA_LOGE("%s: Failed to get peer handle using peer mac %pM",
5886 __func__, peerStateParams->peerMacAddr);
5887 ret = -EIO;
5888 goto end_tdls_peer_state;
5889 }
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07005890 peer_mac_addr = ol_txrx_peer_get_peer_mac_addr(peer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005891
5892 WMA_LOGD("%s: calling wma_remove_peer for peer " MAC_ADDRESS_STR
5893 " vdevId: %d", __func__,
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07005894 MAC_ADDR_ARRAY(peer_mac_addr),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005895 peerStateParams->vdevId);
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07005896 wma_remove_peer(wma_handle, peer_mac_addr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005897 peerStateParams->vdevId, peer, false);
5898 }
5899
5900end_tdls_peer_state:
5901 if (peerStateParams)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305902 qdf_mem_free(peerStateParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005903 return ret;
5904}
5905#endif /* FEATURE_WLAN_TDLS */
5906
5907
5908/**
5909 * wma_dfs_attach() - Attach DFS methods to the umac state.
5910 * @dfs_ic: ieee80211com ptr
5911 *
5912 * Return: Return ieee80211com ptr with updated info
5913 */
5914struct ieee80211com *wma_dfs_attach(struct ieee80211com *dfs_ic)
5915{
5916 /*Allocate memory for dfs_ic before passing it up to dfs_attach() */
5917 dfs_ic = (struct ieee80211com *)
5918 os_malloc(NULL, sizeof(struct ieee80211com), GFP_ATOMIC);
5919 if (dfs_ic == NULL) {
5920 WMA_LOGE("%s:Allocation of dfs_ic failed %zu",
5921 __func__, sizeof(struct ieee80211com));
5922 return NULL;
5923 }
5924 OS_MEMZERO(dfs_ic, sizeof(struct ieee80211com));
5925 /* DFS pattern matching hooks */
5926 dfs_ic->ic_dfs_attach = ol_if_dfs_attach;
5927 dfs_ic->ic_dfs_disable = ol_if_dfs_disable;
5928 dfs_ic->ic_find_channel = ieee80211_find_channel;
5929 dfs_ic->ic_dfs_enable = ol_if_dfs_enable;
5930 dfs_ic->ic_ieee2mhz = ieee80211_ieee2mhz;
5931
5932 /* Hardware facing hooks */
5933 dfs_ic->ic_get_ext_busy = ol_if_dfs_get_ext_busy;
5934 dfs_ic->ic_get_mib_cycle_counts_pct =
5935 ol_if_dfs_get_mib_cycle_counts_pct;
5936 dfs_ic->ic_get_TSF64 = ol_if_get_tsf64;
5937
5938 /* NOL related hooks */
5939 dfs_ic->ic_dfs_usenol = ol_if_dfs_usenol;
5940 /*
5941 * Hooks from wma/dfs/ back
5942 * into the PE/SME
5943 * and shared DFS code
5944 */
5945 dfs_ic->ic_dfs_notify_radar = ieee80211_mark_dfs;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305946 qdf_spinlock_create(&dfs_ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005947 /* Initializes DFS Data Structures and queues */
5948 dfs_attach(dfs_ic);
5949
5950 return dfs_ic;
5951}
5952
5953/**
5954 * wma_dfs_detach() - Detach DFS methods
5955 * @dfs_ic: ieee80211com ptr
5956 *
5957 * Return: none
5958 */
5959void wma_dfs_detach(struct ieee80211com *dfs_ic)
5960{
5961 dfs_detach(dfs_ic);
5962
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305963 qdf_spinlock_destroy(&dfs_ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005964 if (NULL != dfs_ic->ic_curchan) {
5965 OS_FREE(dfs_ic->ic_curchan);
5966 dfs_ic->ic_curchan = NULL;
5967 }
5968
5969 OS_FREE(dfs_ic);
5970}
5971
5972/**
5973 * wma_dfs_configure() - configure dfs
5974 * @ic: ieee80211com ptr
5975 *
5976 * Configures Radar Filters during
5977 * vdev start/channel change/regulatory domain
5978 * change.This Configuration enables to program
5979 * the DFS pattern matching module.
5980 *
5981 * Return: none
5982 */
5983void wma_dfs_configure(struct ieee80211com *ic)
5984{
5985 struct ath_dfs_radar_tab_info rinfo;
5986 int dfsdomain;
5987 int radar_enabled_status = 0;
5988 if (ic == NULL) {
5989 WMA_LOGE("%s: DFS ic is Invalid", __func__);
5990 return;
5991 }
5992
5993 dfsdomain = ic->current_dfs_regdomain;
5994
5995 /* Fetch current radar patterns from the lmac */
5996 OS_MEMZERO(&rinfo, sizeof(rinfo));
5997
5998 /*
5999 * Look up the current DFS
6000 * regulatory domain and decide
6001 * which radar pulses to use.
6002 */
6003 switch (dfsdomain) {
Amar Singhala7bb01b2016-01-27 11:31:59 -08006004 case DFS_FCC_REGION:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006005 WMA_LOGI("%s: DFS-FCC domain", __func__);
Amar Singhala7bb01b2016-01-27 11:31:59 -08006006 rinfo.dfsdomain = DFS_FCC_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006007 rinfo.dfs_radars = dfs_fcc_radars;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306008 rinfo.numradars = QDF_ARRAY_SIZE(dfs_fcc_radars);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006009 rinfo.b5pulses = dfs_fcc_bin5pulses;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306010 rinfo.numb5radars = QDF_ARRAY_SIZE(dfs_fcc_bin5pulses);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006011 break;
Amar Singhala7bb01b2016-01-27 11:31:59 -08006012 case DFS_ETSI_REGION:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006013 WMA_LOGI("%s: DFS-ETSI domain", __func__);
Amar Singhala7bb01b2016-01-27 11:31:59 -08006014 rinfo.dfsdomain = DFS_ETSI_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006015 rinfo.dfs_radars = dfs_etsi_radars;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306016 rinfo.numradars = QDF_ARRAY_SIZE(dfs_etsi_radars);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006017 rinfo.b5pulses = NULL;
6018 rinfo.numb5radars = 0;
6019 break;
Amar Singhala7bb01b2016-01-27 11:31:59 -08006020 case DFS_MKK_REGION:
6021 WMA_LOGI("%s: DFS-MKK domain", __func__);
6022 rinfo.dfsdomain = DFS_MKK_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006023 rinfo.dfs_radars = dfs_mkk4_radars;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306024 rinfo.numradars = QDF_ARRAY_SIZE(dfs_mkk4_radars);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006025 rinfo.b5pulses = dfs_jpn_bin5pulses;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306026 rinfo.numb5radars = QDF_ARRAY_SIZE(dfs_jpn_bin5pulses);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006027 break;
6028 default:
6029 WMA_LOGI("%s: DFS-UNINT domain", __func__);
Amar Singhala7bb01b2016-01-27 11:31:59 -08006030 rinfo.dfsdomain = DFS_UNINIT_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006031 rinfo.dfs_radars = NULL;
6032 rinfo.numradars = 0;
6033 rinfo.b5pulses = NULL;
6034 rinfo.numb5radars = 0;
6035 break;
6036 }
6037
6038 rinfo.dfs_pri_multiplier = ic->dfs_pri_multiplier;
6039
6040 /*
6041 * Set the regulatory domain,
6042 * radar pulse table and enable
6043 * radar events if required.
6044 * dfs_radar_enable() returns
6045 * 0 on success and non-zero
6046 * failure.
6047 */
6048 radar_enabled_status = dfs_radar_enable(ic, &rinfo);
6049 if (radar_enabled_status != DFS_STATUS_SUCCESS) {
6050 WMA_LOGE("%s[%d]: DFS- Radar Detection Enabling Failed",
6051 __func__, __LINE__);
6052 }
6053}
6054
6055/**
6056 * wma_dfs_configure_channel() - configure DFS channel
6057 * @dfs_ic: ieee80211com ptr
Siddarth Poddar17dc4712016-03-09 16:30:27 +05306058 * @band_center_freq1: center frequency 1
6059 * @band_center_freq2: center frequency 2
6060 * (valid only for 11ac vht 80plus80 mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006061 * @ req: vdev start request
6062 *
6063 * Set the Channel parameters in to DFS module
6064 * Also,configure the DFS radar filters for
6065 * matching the DFS phyerrors.
6066 *
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306067 * Return: dfs_ieee80211_channel / NULL for error
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006068 */
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306069struct dfs_ieee80211_channel *wma_dfs_configure_channel(
6070 struct ieee80211com *dfs_ic,
Siddarth Poddar17dc4712016-03-09 16:30:27 +05306071 uint32_t band_center_freq1,
6072 uint32_t band_center_freq2,
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306073 struct wma_vdev_start_req
6074 *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006075{
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006076 uint8_t ext_channel;
6077
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006078 if (dfs_ic == NULL) {
6079 WMA_LOGE("%s: DFS ic is Invalid", __func__);
6080 return NULL;
6081 }
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05306082
6083 if (!dfs_ic->ic_curchan) {
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306084 dfs_ic->ic_curchan = (struct dfs_ieee80211_channel *)os_malloc(
6085 NULL,
6086 sizeof(struct dfs_ieee80211_channel),
6087 GFP_ATOMIC);
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05306088 if (dfs_ic->ic_curchan == NULL) {
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306089 WMA_LOGE(
6090 "%s: allocation of dfs_ic->ic_curchan failed %zu",
6091 __func__, sizeof(struct dfs_ieee80211_channel));
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05306092 return NULL;
6093 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006094 }
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05306095
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306096 OS_MEMZERO(dfs_ic->ic_curchan, sizeof(struct dfs_ieee80211_channel));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006097
6098 dfs_ic->ic_curchan->ic_ieee = req->chan;
Siddarth Poddar17dc4712016-03-09 16:30:27 +05306099 dfs_ic->ic_curchan->ic_freq = cds_chan_to_freq(req->chan);
6100 dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg1 = band_center_freq1;
6101 dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg2 = band_center_freq2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006102 dfs_ic->ic_curchan->ic_pri_freq_center_freq_mhz_separation =
6103 dfs_ic->ic_curchan->ic_freq -
6104 dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg1;
6105
6106 if ((dfs_ic->ic_curchan->ic_ieee >= WMA_11A_CHANNEL_BEGIN) &&
6107 (dfs_ic->ic_curchan->ic_ieee <= WMA_11A_CHANNEL_END)) {
6108 dfs_ic->ic_curchan->ic_flags |= IEEE80211_CHAN_5GHZ;
6109 }
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006110
6111 switch (req->chan_width) {
6112 case CH_WIDTH_20MHZ:
6113 dfs_ic->ic_curchan->ic_flags |=
6114 (req->vht_capable ? IEEE80211_CHAN_VHT20 :
6115 IEEE80211_CHAN_HT20);
6116 break;
6117 case CH_WIDTH_40MHZ:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006118 if (req->chan < req->ch_center_freq_seg0)
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006119 dfs_ic->ic_curchan->ic_flags |=
6120 (req->vht_capable ?
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006121 IEEE80211_CHAN_VHT40PLUS :
6122 IEEE80211_CHAN_HT40PLUS);
6123 else
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006124 dfs_ic->ic_curchan->ic_flags |=
6125 (req->vht_capable ?
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006126 IEEE80211_CHAN_VHT40MINUS :
6127 IEEE80211_CHAN_HT40MINUS);
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006128 break;
6129 case CH_WIDTH_80MHZ:
6130 dfs_ic->ic_curchan->ic_flags |= IEEE80211_CHAN_VHT80;
6131 break;
6132 case CH_WIDTH_80P80MHZ:
Siddarth Poddar17dc4712016-03-09 16:30:27 +05306133 ext_channel = cds_freq_to_chan(band_center_freq2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006134 dfs_ic->ic_curchan->ic_flags |=
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006135 IEEE80211_CHAN_VHT80P80;
6136 dfs_ic->ic_curchan->ic_freq_ext =
Siddarth Poddar17dc4712016-03-09 16:30:27 +05306137 band_center_freq2;
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006138 dfs_ic->ic_curchan->ic_ieee_ext = ext_channel;
6139
6140 /* verify both the 80MHz are DFS bands or not */
Vishwajith Upendrabf673e72016-01-19 16:05:40 -08006141 if (CHANNEL_STATE_DFS == cds_get_channel_state(req->chan) &&
6142 CHANNEL_STATE_DFS == cds_get_channel_state(ext_channel -
6143 WMA_80MHZ_START_CENTER_CH_DIFF))
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006144 dfs_ic->ic_curchan->ic_80p80_both_dfs = true;
6145 break;
6146 case CH_WIDTH_160MHZ:
6147 dfs_ic->ic_curchan->ic_flags |=
6148 IEEE80211_CHAN_VHT160;
6149 break;
6150 default:
6151 WMA_LOGE(
6152 "%s: Recieved a wrong channel width %d",
6153 __func__, req->chan_width);
6154 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006155 }
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006156
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006157 dfs_ic->ic_curchan->ic_flagext |= IEEE80211_CHAN_DFS;
6158
6159 if (req->oper_mode == BSS_OPERATIONAL_MODE_AP) {
6160 dfs_ic->ic_opmode = IEEE80211_M_HOSTAP;
6161 dfs_ic->vdev_id = req->vdev_id;
6162 }
6163
6164 dfs_ic->dfs_pri_multiplier = req->dfs_pri_multiplier;
6165
6166 /*
6167 * Configuring the DFS with current channel and the radar filters
6168 */
6169 wma_dfs_configure(dfs_ic);
6170 WMA_LOGI("%s: DFS- CHANNEL CONFIGURED", __func__);
6171 return dfs_ic->ic_curchan;
6172}
6173
6174
6175/**
6176 * wma_set_dfs_region() - set DFS region
6177 * @wma: wma handle
6178 *
6179 * Configure the DFS region for DFS radar filter initialization
6180 *
6181 * Return: none
6182 */
6183void wma_set_dfs_region(tp_wma_handle wma, uint8_t dfs_region)
6184{
6185 /* dfs information is passed */
Amar Singhala7bb01b2016-01-27 11:31:59 -08006186 if (dfs_region > DFS_MKK_REGION || dfs_region == DFS_UNINIT_REGION)
6187 /* assign DFS_FCC_REGION as default region*/
6188 wma->dfs_ic->current_dfs_regdomain = DFS_FCC_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006189 else
6190 wma->dfs_ic->current_dfs_regdomain = dfs_region;
6191
6192 WMA_LOGI("%s: DFS Region Domain: %d", __func__,
6193 wma->dfs_ic->current_dfs_regdomain);
6194}
6195
6196/**
6197 * wma_get_channels() - prepare dfs radar channel list
6198 * @ichan: channel
6199 * @chan_list: return channel list
6200 *
6201 * Return: return number of channels
6202 */
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306203int wma_get_channels(struct dfs_ieee80211_channel *ichan,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006204 struct wma_dfs_radar_channel_list *chan_list)
6205{
6206 uint8_t center_chan = cds_freq_to_chan(ichan->ic_vhtop_ch_freq_seg1);
Vishwajith Upendrabf673e72016-01-19 16:05:40 -08006207 int count = 0;
6208 int start_channel = 0;
6209 int loop;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006210
6211 chan_list->nchannels = 0;
6212
Vishwajith Upendrabf673e72016-01-19 16:05:40 -08006213 if (IEEE80211_IS_CHAN_11AC_VHT160(ichan)) {
6214 /*
6215 * In 160MHz channel width, need to
6216 * check if each of the 8 20MHz channel
6217 * is DFS before adding to the NOL list.
6218 * As it is possible that part of the
6219 * 160MHz can be Non-DFS channels.
6220 */
6221 start_channel = center_chan - WMA_160MHZ_START_CENTER_CH_DIFF;
6222 for (loop = 0; loop < WMA_DFS_MAX_20M_SUB_CH; loop++) {
6223 if (cds_get_channel_state(start_channel +
6224 (loop * WMA_NEXT_20MHZ_START_CH_DIFF)) ==
6225 CHANNEL_STATE_DFS) {
6226 chan_list->channels[count] = start_channel +
6227 (loop * WMA_NEXT_20MHZ_START_CH_DIFF);
6228 count++;
6229 }
6230 }
6231 chan_list->nchannels = count;
6232 } else if (IEEE80211_IS_CHAN_11AC_VHT80P80(ichan)) {
6233 chan_list->nchannels = 4;
6234 /*
6235 * If SAP is operating in 80p80 mode, either
6236 * one of the two 80 segments or both the 80
6237 * segments can be DFS channels, so need to
6238 * identify on which 80 segment radar has
6239 * been detected and only add those channels
6240 * to the NOL list. center frequency should be
6241 * based on the segment id passed as part of
6242 * channel information in radar indication.
6243 */
6244 if (ichan->ic_radar_found_segid == DFS_80P80_SEG1)
6245 center_chan =
6246 cds_freq_to_chan(ichan->ic_vhtop_ch_freq_seg2);
6247 chan_list->channels[0] = center_chan - 6;
6248 chan_list->channels[1] = center_chan - 2;
6249 chan_list->channels[2] = center_chan + 2;
6250 chan_list->channels[3] = center_chan + 6;
6251 } else if (IEEE80211_IS_CHAN_11AC_VHT80(ichan)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006252 chan_list->nchannels = 4;
6253 chan_list->channels[0] = center_chan - 6;
6254 chan_list->channels[1] = center_chan - 2;
6255 chan_list->channels[2] = center_chan + 2;
6256 chan_list->channels[3] = center_chan + 6;
6257 } else if (IEEE80211_IS_CHAN_11N_HT40(ichan) ||
6258 IEEE80211_IS_CHAN_11AC_VHT40(ichan)) {
6259 chan_list->nchannels = 2;
6260 chan_list->channels[0] = center_chan - 2;
6261 chan_list->channels[1] = center_chan + 2;
6262 } else {
6263 chan_list->nchannels = 1;
6264 chan_list->channels[0] = center_chan;
6265 }
6266
6267 return chan_list->nchannels;
6268}
6269
6270
6271/**
6272 * wma_dfs_indicate_radar() - Indicate Radar to SAP/HDD
6273 * @ic: ieee80211com ptr
6274 * @ichan: ieee 80211 channel
6275 *
6276 * Return: 0 for success or error code
6277 */
6278int wma_dfs_indicate_radar(struct ieee80211com *ic,
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306279 struct dfs_ieee80211_channel *ichan)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006280{
6281 tp_wma_handle wma;
6282 void *hdd_ctx;
6283 struct wma_dfs_radar_indication *radar_event;
6284 struct wma_dfs_radar_ind wma_radar_event;
6285 tpAniSirGlobal pmac = NULL;
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05306286 bool indication_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006287
Anurag Chouhan6d760662016-02-20 16:05:43 +05306288 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006289 if (wma == NULL) {
6290 WMA_LOGE("%s: DFS- Invalid wma", __func__);
6291 return -ENOENT;
6292 }
6293
Anurag Chouhan6d760662016-02-20 16:05:43 +05306294 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006295 pmac = (tpAniSirGlobal)
Anurag Chouhan6d760662016-02-20 16:05:43 +05306296 cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006297
6298 if (!pmac) {
6299 WMA_LOGE("%s: Invalid MAC handle", __func__);
6300 return -ENOENT;
6301 }
6302
6303 if (wma->dfs_ic != ic) {
6304 WMA_LOGE("%s:DFS- Invalid WMA handle", __func__);
6305 return -ENOENT;
6306 }
6307 radar_event = (struct wma_dfs_radar_indication *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306308 qdf_mem_malloc(sizeof(struct wma_dfs_radar_indication));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006309 if (radar_event == NULL) {
6310 WMA_LOGE("%s:DFS- Invalid radar_event", __func__);
6311 return -ENOMEM;
6312 }
6313
6314 /*
6315 * Do not post multiple Radar events on the same channel.
6316 * But, when DFS test mode is enabled, allow multiple dfs
6317 * radar events to be posted on the same channel.
6318 */
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306319 qdf_spin_lock_bh(&ic->chan_lock);
Edhar, Mahesh Kumar35d9b2e2015-10-26 17:06:23 +05306320 if (!pmac->sap.SapDfsInfo.disable_dfs_ch_switch)
6321 wma->dfs_ic->disable_phy_err_processing = true;
6322
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006323 if ((ichan->ic_ieee != (wma->dfs_ic->last_radar_found_chan)) ||
6324 (pmac->sap.SapDfsInfo.disable_dfs_ch_switch == true)) {
6325 wma->dfs_ic->last_radar_found_chan = ichan->ic_ieee;
6326 /* Indicate the radar event to HDD to stop the netif Tx queues */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006327 wma_radar_event.chan_freq = ichan->ic_freq;
6328 wma_radar_event.dfs_radar_status = WMA_DFS_RADAR_FOUND;
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05306329 indication_status =
6330 wma->dfs_radar_indication_cb(hdd_ctx, &wma_radar_event);
6331 if (indication_status == false) {
6332 WMA_LOGE("%s:Application triggered channel switch in progress!.. drop radar event indiaction to SAP",
6333 __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306334 qdf_mem_free(radar_event);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306335 qdf_spin_unlock_bh(&ic->chan_lock);
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05306336 return 0;
6337 }
6338
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006339 WMA_LOGE("%s:DFS- RADAR INDICATED TO HDD", __func__);
6340
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05306341 wma_radar_event.ieee_chan_number = ichan->ic_ieee;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006342 /*
6343 * Indicate to the radar event to SAP to
6344 * select a new channel and set CSA IE
6345 */
6346 radar_event->vdev_id = ic->vdev_id;
6347 wma_get_channels(ichan, &radar_event->chan_list);
6348 radar_event->dfs_radar_status = WMA_DFS_RADAR_FOUND;
6349 radar_event->use_nol = ic->ic_dfs_usenol(ic);
6350 wma_send_msg(wma, WMA_DFS_RADAR_IND, (void *)radar_event, 0);
6351 WMA_LOGE("%s:DFS- WMA_DFS_RADAR_IND Message Posted", __func__);
6352 }
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306353 qdf_spin_unlock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006354
6355 return 0;
6356}
6357
6358#ifdef WLAN_FEATURE_MEMDUMP
6359/*
6360 * wma_process_fw_mem_dump_req() - Function to request fw memory dump from
6361 * firmware
6362 * @wma: Pointer to WMA handle
6363 * @mem_dump_req: Pointer for mem_dump_req
6364 *
6365 * This function sends memory dump request to firmware
6366 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306367 * Return: QDF_STATUS_SUCCESS for success otherwise failure
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006368 *
6369 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306370QDF_STATUS wma_process_fw_mem_dump_req(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006371 struct fw_dump_req *mem_dump_req)
6372{
Govind Singhaa64c242016-03-08 11:31:49 +05306373 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006374
6375 if (!mem_dump_req || !wma) {
6376 WMA_LOGE(FL("input pointer is NULL"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306377 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006378 }
6379
Govind Singhaa64c242016-03-08 11:31:49 +05306380 ret = wmi_unified_process_fw_mem_dump_cmd(wma->wmi_handle,
6381 (struct fw_dump_req_param *) mem_dump_req);
6382 if (ret)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306383 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006384
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306385 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006386}
6387
6388/**
6389 * wma_fw_mem_dump_rsp() - send fw mem dump response to SME
6390 *
6391 * @req_id - request id.
6392 * @status - copy status from the firmware.
6393 *
6394 * This function is called by the memory dump response handler to
6395 * indicate SME that firmware dump copy is complete
6396 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306397 * Return: QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006398 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306399static QDF_STATUS wma_fw_mem_dump_rsp(uint32_t req_id, uint32_t status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006400{
6401 struct fw_dump_rsp *dump_rsp;
6402 cds_msg_t sme_msg = {0};
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306403 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006404
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306405 dump_rsp = qdf_mem_malloc(sizeof(*dump_rsp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006406
6407 if (!dump_rsp) {
6408 WMA_LOGE(FL("Memory allocation failed."));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306409 qdf_status = QDF_STATUS_E_NOMEM;
6410 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006411 }
6412
6413 WMA_LOGI(FL("FW memory dump copy complete status: %d for request: %d"),
6414 status, req_id);
6415
6416 dump_rsp->request_id = req_id;
6417 dump_rsp->dump_complete = status;
6418
6419 sme_msg.type = eWNI_SME_FW_DUMP_IND;
6420 sme_msg.bodyptr = dump_rsp;
6421 sme_msg.bodyval = 0;
6422
Anurag Chouhan6d760662016-02-20 16:05:43 +05306423 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306424 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006425 WMA_LOGE(FL("Fail to post fw mem dump ind msg"));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306426 qdf_mem_free(dump_rsp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006427 }
6428
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306429 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006430}
6431
6432/**
6433 * wma_fw_mem_dump_event_handler() - handles fw memory dump event
6434 *
6435 * @handle: pointer to wma handle.
6436 * @cmd_param_info: pointer to TLV info received in the event.
6437 * @len: length of data in @cmd_param_info
6438 *
6439 * This function is a handler for firmware memory dump event.
6440 *
6441 * Return: integer (0 for success and error code otherwise)
6442 */
6443int wma_fw_mem_dump_event_handler(void *handle, u_int8_t *cmd_param_info,
6444 u_int32_t len)
6445{
6446 WMI_UPDATE_FW_MEM_DUMP_EVENTID_param_tlvs *param_buf;
6447 wmi_update_fw_mem_dump_fixed_param *event;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306448 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006449
6450 param_buf =
6451 (WMI_UPDATE_FW_MEM_DUMP_EVENTID_param_tlvs *) cmd_param_info;
6452 if (!param_buf) {
6453 WMA_LOGA("%s: Invalid stats event", __func__);
6454 return -EINVAL;
6455 }
6456
6457 event = param_buf->fixed_param;
6458
6459 status = wma_fw_mem_dump_rsp(event->request_id,
6460 event->fw_mem_dump_complete);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306461 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006462 WMA_LOGE("Error posting FW MEM DUMP RSP.");
6463 return -EINVAL;
6464 }
6465
6466 WMA_LOGI("FW MEM DUMP RSP posted successfully");
6467 return 0;
6468}
6469#endif /* WLAN_FEATURE_MEMDUMP */
6470
6471/*
6472 * wma_process_set_ie_info() - Function to send IE info to firmware
6473 * @wma: Pointer to WMA handle
6474 * @ie_data: Pointer for ie data
6475 *
6476 * This function sends IE information to firmware
6477 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306478 * Return: QDF_STATUS_SUCCESS for success otherwise failure
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006479 *
6480 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306481QDF_STATUS wma_process_set_ie_info(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006482 struct vdev_ie_info *ie_info)
6483{
Govind Singhaa64c242016-03-08 11:31:49 +05306484 struct vdev_ie_info_param cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006485 int ret;
6486
6487 if (!ie_info || !wma) {
6488 WMA_LOGE(FL("input pointer is NULL"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306489 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006490 }
6491
6492 /* Validate the input */
6493 if (ie_info->length <= 0) {
6494 WMA_LOGE(FL("Invalid IE length"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306495 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006496 }
6497
Govind Singhaa64c242016-03-08 11:31:49 +05306498 cmd.vdev_id = ie_info->vdev_id;
6499 cmd.ie_id = ie_info->ie_id;
6500 cmd.length = ie_info->length;
6501 cmd.data = ie_info->data;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006502
Govind Singhaa64c242016-03-08 11:31:49 +05306503 ret = wmi_unified_process_set_ie_info_cmd(wma->wmi_handle,
6504 &cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006505
6506 return ret;
6507}
6508